Skip to content

Commit 8c7c8b7

Browse files
committed
Release 1.2.0 (#8)
* chore: update deps * chore: update version number * feat: assign to range (#10) * feat: assign to range * feat: improve assignment form * feat: add helper text, closes #6 * feat: allow days to be copied, closes #7 (#11) * feat: support tss 2.0.0 (#12), closes #9
1 parent 7d73d8f commit 8c7c8b7

File tree

8 files changed

+811
-549
lines changed

8 files changed

+811
-549
lines changed

app/lib/constants.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
export const VERSION = '1.1.0'
1+
export const VERSION = '1.2.0'
22

33
export const RequiredVersions = {
44
controller: VERSION,
5-
tts: '1.0.1',
6-
piper: '1.2.0',
5+
tts: '2.0.0',
6+
piper: '1.3.0',
77
sounder: '1.1.1'
88
}
99

app/lib/ui.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,18 @@ export const FormElement: React.FC<{
5959
<label className="grid grid-cols-2 gap-4 mb-2">
6060
<span className="font-semibold">{label}</span>
6161
<div className="row-span-2">{children}</div>
62-
<span className="text-neutral-400">{helperText}</span>
62+
<HelperText>{helperText}</HelperText>
6363
</label>
6464
</div>
6565
)
6666
}
6767

68+
export const HelperText: React.FC<{
69+
children: React.ReactNode
70+
}> = ({children}) => {
71+
return <span className="text-neutral-400">{children}</span>
72+
}
73+
6874
export const Actions: React.FC<{
6975
actions: {
7076
label: string

app/routes/about.tsx

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,28 @@ export const loader = async ({request}: LoaderFunctionArgs) => {
2828
const piperData = await new Promise<{
2929
version: string
3030
piperVersion: string
31+
pythonVersion: string
3132
}>(resolve => {
32-
fetch(`${process.env.TTS_API}/status`)
33+
fetch(`${process.env.TTS_API}/status.json`)
3334
.then(response => {
3435
response
3536
.json()
3637
.then(data => resolve(data))
37-
.catch(() => resolve({version: '0.0.0', piperVersion: '0.0.0'}))
38+
.catch(() =>
39+
resolve({
40+
version: '0.0.0',
41+
piperVersion: '0.0.0',
42+
pythonVersion: '0.0.0'
43+
})
44+
)
45+
})
46+
.catch(() => {
47+
resolve({
48+
version: '0.0.0',
49+
piperVersion: '0.0.0',
50+
pythonVersion: '0.0.0'
51+
})
3852
})
39-
.catch(() => resolve({version: '0.0.0', piperVersion: '0.0.0'}))
4053
})
4154

4255
const sounderLatest = await new Promise<string>(resolve => {

app/routes/days.add.tsx

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import {
33
type ActionFunctionArgs,
44
type LoaderFunctionArgs
55
} from '@remix-run/node'
6-
import {useNavigate} from '@remix-run/react'
6+
import {useNavigate, useLoaderData} from '@remix-run/react'
77
import {invariant} from '@arcath/utils'
88

99
import {getPrisma} from '~/lib/prisma.server'
@@ -18,7 +18,11 @@ export const loader = async ({request}: LoaderFunctionArgs) => {
1818
return redirect('/login')
1919
}
2020

21-
return {}
21+
const prisma = getPrisma()
22+
23+
const days = await prisma.dayType.findMany({orderBy: {name: 'asc'}})
24+
25+
return {days}
2226
}
2327

2428
export const action = async ({request}: ActionFunctionArgs) => {
@@ -33,23 +37,56 @@ export const action = async ({request}: ActionFunctionArgs) => {
3337
const formData = await request.formData()
3438

3539
const name = formData.get('name') as string | undefined
40+
const copyFrom = formData.get('copyFrom') as string | undefined
3641

3742
invariant(name)
43+
invariant(copyFrom)
44+
45+
const dayType = await prisma.dayType.create({data: {name}})
3846

39-
await prisma.dayType.create({data: {name}})
47+
if (copyFrom !== '-') {
48+
const schedules = await prisma.schedule.findMany({
49+
where: {dayTypeId: copyFrom === '_' ? undefined : copyFrom}
50+
})
51+
52+
await prisma.schedule.createMany({
53+
data: schedules.map(({time, weekDays, zoneId, audioId}) => {
54+
return {dayTypeId: dayType.id, time, weekDays, zoneId, audioId}
55+
})
56+
})
57+
}
4058

4159
return redirect(`/calendar`)
4260
}
4361

4462
const AddDay = () => {
4563
const navigate = useNavigate()
64+
const {days} = useLoaderData<typeof loader>()
4665

4766
return (
4867
<Page title="Add Day">
4968
<form method="post">
5069
<FormElement label="Name" helperText="Descriptive name for the day.">
5170
<input name="name" className={INPUT_CLASSES} />
5271
</FormElement>
72+
<FormElement
73+
label="Copy From"
74+
helperText="The day type to copy the schedule from"
75+
>
76+
<select name="copyFrom" className={INPUT_CLASSES}>
77+
<option value="-" selected>
78+
None
79+
</option>
80+
<option value="_">Default</option>
81+
{days.map(({id, name}) => {
82+
return (
83+
<option key={id} value={id}>
84+
{name}
85+
</option>
86+
)
87+
})}
88+
</select>
89+
</FormElement>
5390
<Actions
5491
actions={[
5592
{

app/routes/days.assignments.tsx

Lines changed: 95 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@ import {
44
type MetaFunction,
55
redirect
66
} from '@remix-run/node'
7-
import {useLoaderData} from '@remix-run/react'
8-
import {invariant} from '@arcath/utils'
9-
import {subDays, format} from 'date-fns'
7+
import {useLoaderData, useNavigate} from '@remix-run/react'
8+
import {invariant, asyncForEach} from '@arcath/utils'
9+
import {subDays, format, eachDayOfInterval} from 'date-fns'
1010

1111
import {getPrisma} from '~/lib/prisma.server'
1212
import {INPUT_CLASSES, pageTitle} from '~/lib/utils'
1313
import {checkSession} from '~/lib/session'
14-
import {Page} from '~/lib/ui'
14+
import {Page, FormElement, Actions, HelperText} from '~/lib/ui'
1515
import {useLocalStorage} from '~/lib/hooks/use-local-storage'
1616

1717
export const meta: MetaFunction = () => {
@@ -49,14 +49,23 @@ export const action = async ({request}: ActionFunctionArgs) => {
4949

5050
const formData = await request.formData()
5151

52-
const date = formData.get('date') as string | undefined
52+
const startDate = formData.get('startDate') as string | undefined
53+
const endDate = formData.get('endDate') as string | undefined
5354
const day = formData.get('day') as string | undefined
5455

55-
invariant(date)
56+
invariant(startDate)
57+
invariant(endDate)
5658
invariant(day)
5759

58-
await prisma.dayTypeAssignment.create({
59-
data: {date: new Date(date), dayTypeId: day}
60+
const days = eachDayOfInterval({
61+
start: new Date(startDate),
62+
end: new Date(endDate)
63+
})
64+
65+
await asyncForEach(days, async date => {
66+
await prisma.dayTypeAssignment.create({
67+
data: {date, dayTypeId: day}
68+
})
6069
})
6170

6271
return redirect(`/days/assignments`)
@@ -69,10 +78,15 @@ const DayAssignments = () => {
6978
'assignmentDate',
7079
format(new Date(), 'yyyy-LL-dd')
7180
)
81+
const navigate = useNavigate()
7282

7383
return (
74-
<Page title="Day Assignments">
75-
<form method="post">
84+
<div className="grid grid-cols-1 gap-4">
85+
<Page title="Day Assignments">
86+
<HelperText>
87+
These assignments change the day type for the given days to that day
88+
types schedule.
89+
</HelperText>
7690
<table className="box-table">
7791
<thead>
7892
<tr>
@@ -99,49 +113,78 @@ const DayAssignments = () => {
99113
)
100114
})}
101115
</tbody>
102-
<tfoot>
103-
<tr>
104-
<td>
105-
<input
106-
type="date"
107-
className={INPUT_CLASSES}
108-
name="date"
109-
defaultValue={assignmentDate}
110-
onChange={e => {
111-
setAssignmentDate(e.target.value)
112-
}}
113-
/>
114-
</td>
115-
<td>
116-
<select
117-
className={INPUT_CLASSES}
118-
name="day"
119-
defaultValue={day}
120-
onChange={e => {
121-
setDay(e.target.value)
122-
}}
123-
>
124-
{days.map(({id, name}) => {
125-
return (
126-
<option key={id} value={id}>
127-
{name}
128-
</option>
129-
)
130-
})}
131-
</select>
132-
</td>
133-
<td>
134-
<input
135-
type="submit"
136-
value="Add"
137-
className={`${INPUT_CLASSES} bg-green-400`}
138-
/>
139-
</td>
140-
</tr>
141-
</tfoot>
142116
</table>
143-
</form>
144-
</Page>
117+
</Page>
118+
<Page title="Add Assignments">
119+
<form method="post">
120+
<FormElement
121+
label="From"
122+
helperText="The date to start assigning from. To only assign one day set both From and To to the same date."
123+
>
124+
<input
125+
type="date"
126+
name="startDate"
127+
className={INPUT_CLASSES}
128+
defaultValue={assignmentDate}
129+
onChange={e => {
130+
setAssignmentDate(e.target.value)
131+
}}
132+
/>
133+
</FormElement>
134+
<FormElement
135+
label="To"
136+
helperText="The date to end assignments. To only assign one day set both From and To to the same date."
137+
>
138+
<input
139+
type="date"
140+
className={INPUT_CLASSES}
141+
name="endDate"
142+
defaultValue={assignmentDate}
143+
onChange={e => {
144+
setAssignmentDate(e.target.value)
145+
}}
146+
/>
147+
</FormElement>
148+
<FormElement
149+
label="Day"
150+
helperText="The day type to assign to these dates"
151+
>
152+
<select
153+
className={INPUT_CLASSES}
154+
name="day"
155+
defaultValue={day}
156+
onChange={e => {
157+
setDay(e.target.value)
158+
}}
159+
>
160+
{days.map(({id, name}) => {
161+
return (
162+
<option key={id} value={id}>
163+
{name}
164+
</option>
165+
)
166+
})}
167+
</select>
168+
</FormElement>
169+
<Actions
170+
actions={[
171+
{
172+
label: 'Cancel',
173+
color: 'bg-stone-200',
174+
onClick: e => {
175+
e.preventDefault()
176+
navigate('/calendar')
177+
}
178+
},
179+
{
180+
label: 'Add Assignments',
181+
color: 'bg-green-300'
182+
}
183+
]}
184+
/>
185+
</form>
186+
</Page>
187+
</div>
145188
)
146189
}
147190

app/routes/sounds.add-tts.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,8 @@ export const action = async ({request}: ActionFunctionArgs) => {
6262

6363
const downloadResponse = await fetch(`${process.env.TTS_API}/piper`, {
6464
body: JSON.stringify({
65-
target: `${sound.id}.wav`,
6665
text: tts,
67-
speed
66+
length_scale: speed
6867
}),
6968
headers: {'Content-Type': 'application/json'},
7069
method: 'post'

0 commit comments

Comments
 (0)