music on hold: play order set in the UI, and shuffle

Owner: the first upload always played first. A class is now an Asterisk playlist in the order
set on Sounds & music (move up/down), new uploads last, with a Shuffle option (sort = random).
moh-test.ts plays both in a real Asterisk and reads the file order from its debug log.
This commit is contained in:
iamdoubz committed 2026-10-21 13:27:02 -05:00
1 parent aa6681da03
commit 175d5a2c73
17 files changed
+4432 -27

No files matched your search

@@ -0,0 +1,7 @@
ALTER TABLE "moh_classes" ADD COLUMN "shuffle" boolean DEFAULT false NOT NULL;--> statement-breakpoint
ALTER TABLE "sound_files" ADD COLUMN "position" integer DEFAULT 0 NOT NULL;--> statement-breakpoint
-- Existing music on hold keeps the order it was uploaded in (owner, 2026-10-21).
UPDATE "sound_files" s SET "position" = o.n FROM (
SELECT "id", row_number() OVER (PARTITION BY "moh_class_id" ORDER BY "created_at", "id") - 1 AS n
FROM "sound_files" WHERE "moh_class_id" IS NOT NULL
) o WHERE s."id" = o."id";
File diff suppressed because it is too large. Load diff
@@ -36,6 +36,13 @@
"when": 1792512298128,
"tag": "0004_system_events",
"breakpoints": true
},
{
"idx": 5,
"version": "7",
"when": 1792606712441,
"tag": "0005_moh_order",
"breakpoints": true
}
]
}
+4
View File
@@ -334,6 +334,8 @@ export const queueCalls = pgTable(
export const mohClasses = pgTable('moh_classes', {
id: id(),
name: text().notNull().unique(),
/** Play the files in random order; otherwise in `sound_files.position` order (03 §8). */
shuffle: boolean().notNull().default(false),
...timestamps,
});
@@ -349,6 +351,8 @@ export const soundFiles = pgTable(
originalFilename: text(),
asteriskName: text().notNull().unique(),
durationMs: integer().notNull(),
/** Music on hold: where it plays in its class's list (0 first). Prompts don't use it. */
position: integer().notNull().default(0),
...timestamps,
},
(t) => [