diff --git a/app/lib/constants.ts b/app/lib/constants.ts
index c3ba4dd..0d5682d 100644
--- a/app/lib/constants.ts
+++ b/app/lib/constants.ts
@@ -1,10 +1,10 @@
-export const VERSION = '1.6.2'
+export const VERSION = '1.7.0'
export const RequiredVersions = {
controller: VERSION,
tts: '2.0.0',
piper: '1.3.0',
- sounder: '2.1.0',
+ sounder: '2.4.0',
button: '1.0.0'
}
diff --git a/app/lib/settings.server.ts b/app/lib/settings.server.ts
index e8af140..d8ecdb4 100644
--- a/app/lib/settings.server.ts
+++ b/app/lib/settings.server.ts
@@ -2,34 +2,30 @@ import {asyncForEach} from '@arcath/utils'
import {getPrisma} from './prisma.server'
type SettingKey =
- | 'lockdownEntrySound'
- | 'lockdownExitSound'
| 'lockdownRepeat'
- | 'lockdownExitRepeat'
| 'lockdownMode'
| 'lockdownRepeatRingerWire'
- | 'lockdownRepetitions'
| 'password'
| 'ttsSpeed'
| 'enrollUrl'
| 'controlPointKey'
| 'ttsLastSeen'
| 'workerLastSeen'
+ | 'lockdownEntrySequence'
+ | 'lockdownExitSequence'
export const DEFAULT_SETTINGS: {[setting in SettingKey]: string} = {
- lockdownEntrySound: '',
- lockdownExitSound: '',
lockdownRepeat: '5',
- lockdownExitRepeat: '2',
lockdownRepeatRingerWire: '0',
lockdownMode: '0',
- lockdownRepetitions: '4',
password: 'bell',
ttsSpeed: '1',
enrollUrl: 'http://controller:3000',
controlPointKey: '',
ttsLastSeen: '"1970-01-01T23:00:00.000Z"',
- workerLastSeen: '"1970-01-01T23:00:00.000Z"'
+ workerLastSeen: '"1970-01-01T23:00:00.000Z"',
+ lockdownEntrySequence: '[]',
+ lockdownExitSequence: '[]'
}
export const getSetting = async (setting: SettingKey) => {
diff --git a/app/locales/en.ts b/app/locales/en.ts
index b94aace..7e1b01f 100644
--- a/app/locales/en.ts
+++ b/app/locales/en.ts
@@ -193,6 +193,12 @@ export const en = {
'lockdown.field.entrySound.label': 'Lockdown start sound',
'lockdown.field.entrySound.helper':
'Sound used to start lockdown and for repetitions.',
+ 'lockdown.field.entrySequence.label': 'Lockdown Entry Sequence',
+ 'lockdown.field.entrySequence.helper':
+ 'The sequence that is run when lockdown starts and on any repetitions.',
+ 'lockdown.field.exitSequence.label': 'Lockdown Exit Sequence',
+ 'lockdown.field.exitSequence.helper':
+ 'The sequence that is run when lockdown ends.',
'lockdown.field.exitSound.label': 'Lockdown end sound',
'lockdown.field.exitSound.helper': 'Sound used to end lockdown.',
'lockdown.field.startCount.label': 'Lockdown start count',
diff --git a/app/root.tsx b/app/root.tsx
index 85d23d9..95b40cc 100644
--- a/app/root.tsx
+++ b/app/root.tsx
@@ -146,7 +146,7 @@ const AppContent = () => {
- © Open School Bell 2025
+ © Open School Bell 2026
OSB {VERSION}
diff --git a/app/routes/lockdown.tsx b/app/routes/lockdown.tsx
index 769a989..2aa4492 100644
--- a/app/routes/lockdown.tsx
+++ b/app/routes/lockdown.tsx
@@ -15,6 +15,7 @@ import {Page, FormElement, Actions} from '~/lib/ui'
import {useTranslation} from '~/lib/i18n'
import {translate} from '~/lib/i18n.shared'
import {getRootI18n} from '~/lib/i18n.meta'
+import {SequenceBuilder} from '~/lib/sequence-builder'
export const meta: MetaFunction = ({matches}) => {
const {messages} = getRootI18n(matches)
@@ -31,19 +32,15 @@ export const loader = async ({request}: LoaderFunctionArgs) => {
const {
lockdownMode,
lockdownRepeat,
- lockdownExitRepeat,
- lockdownEntrySound,
- lockdownExitSound,
lockdownRepeatRingerWire,
- lockdownRepetitions
+ lockdownEntrySequence,
+ lockdownExitSequence
} = await getSettings([
- 'lockdownEntrySound',
'lockdownMode',
'lockdownRepeat',
- 'lockdownExitRepeat',
- 'lockdownExitSound',
'lockdownRepeatRingerWire',
- 'lockdownRepetitions'
+ 'lockdownEntrySequence',
+ 'lockdownExitSequence'
])
const prisma = getPrisma()
@@ -53,11 +50,9 @@ export const loader = async ({request}: LoaderFunctionArgs) => {
return {
lockdownMode,
lockdownRepeat,
- lockdownExitRepeat,
- lockdownEntrySound,
- lockdownExitSound,
lockdownRepeatRingerWire,
- lockdownRepetitions,
+ lockdownEntrySequence,
+ lockdownExitSequence,
sounds
}
}
@@ -65,37 +60,27 @@ export const loader = async ({request}: LoaderFunctionArgs) => {
export const action = async ({request}: ActionFunctionArgs) => {
const formData = await request.formData()
- const lockdownEntrySound = formData.get('lockdownEntrySound') as
- | string
- | undefined
- const lockdownExitSound = formData.get('lockdownExitSound') as
- | string
- | undefined
- const lockdownRepetitions = formData.get('lockdownRepetitions') as
+ const lockdownRepeat = formData.get('lockdownRepeat') as string | undefined
+ const lockdownEntrySequence = formData.get('lockdownEntrySequence') as
| string
| undefined
- const lockdownExitRepeat = formData.get('lockdownExitRepeat') as
+ const lockdownExitSequence = formData.get('lockdownExitSequence') as
| string
| undefined
- const lockdownRepeat = formData.get('lockdownRepeat') as string | undefined
const lockdownRepeatRingerWire = !!(formData.get(
'lockdownRepeatRingerWire'
) as string | undefined)
? '1'
: '0'
- invariant(lockdownEntrySound)
- invariant(lockdownExitSound)
- invariant(lockdownRepetitions)
invariant(lockdownRepeat)
- invariant(lockdownExitRepeat)
+ invariant(lockdownEntrySequence)
+ invariant(lockdownExitSequence)
- await setSetting('lockdownEntrySound', lockdownEntrySound)
- await setSetting('lockdownExitSound', lockdownExitSound)
- await setSetting('lockdownRepetitions', lockdownRepetitions)
- await setSetting('lockdownExitRepeat', lockdownExitRepeat)
await setSetting('lockdownRepeat', lockdownRepeat)
await setSetting('lockdownRepeatRingerWire', lockdownRepeatRingerWire)
+ await setSetting('lockdownEntrySequence', lockdownEntrySequence)
+ await setSetting('lockdownExitSequence', lockdownExitSequence)
return redirect('/lockdown')
}
@@ -104,11 +89,9 @@ const Lockdown = () => {
const {
lockdownMode,
lockdownRepeat,
- lockdownExitRepeat,
- lockdownEntrySound,
- lockdownExitSound,
lockdownRepeatRingerWire,
- lockdownRepetitions,
+ lockdownEntrySequence,
+ lockdownExitSequence,
sounds
} = useLoaderData()
const {t} = useTranslation()
@@ -123,64 +106,20 @@ const Lockdown = () => {
: t('lockdown.status.inactive')}{' '}