Move recordings UI to Livewire pages with Flux components.
Replace controller-driven Blade views with full-page Livewire index/show/create flows so Flux tables, toasts, and uploads work natively.
This commit is contained in:
@@ -2,16 +2,21 @@
|
||||
* Shared helpers and Alpine components for live transcription updates via Reverb.
|
||||
*/
|
||||
|
||||
const BADGE_CLASSES = {
|
||||
done: 'bg-teal-50 text-teal-800 ring-teal-600/20 dark:bg-teal-950 dark:text-teal-200 dark:ring-teal-400/30',
|
||||
processing: 'bg-amber-50 text-amber-800 ring-amber-600/20 dark:bg-amber-950 dark:text-amber-200 dark:ring-amber-400/30',
|
||||
pending: 'bg-amber-50 text-amber-800 ring-amber-600/20 dark:bg-amber-950 dark:text-amber-200 dark:ring-amber-400/30',
|
||||
failed: 'bg-red-50 text-red-800 ring-red-600/20 dark:bg-red-950 dark:text-red-200 dark:ring-red-400/30',
|
||||
cancelled: 'bg-stone-100 text-stone-700 ring-stone-500/20 dark:bg-zinc-800 dark:text-zinc-300 dark:ring-zinc-500/30',
|
||||
const BADGE_COLORS = {
|
||||
done: 'teal',
|
||||
processing: 'amber',
|
||||
pending: 'amber',
|
||||
failed: 'red',
|
||||
cancelled: 'zinc',
|
||||
};
|
||||
|
||||
export function badgeColorFor(status) {
|
||||
return BADGE_COLORS[status] || 'zinc';
|
||||
}
|
||||
|
||||
/** @deprecated Use badgeColorFor — kept for any leftover callers */
|
||||
export function badgeClassFor(status) {
|
||||
return BADGE_CLASSES[status] || 'bg-stone-100 text-stone-700 ring-stone-500/20 dark:bg-zinc-800 dark:text-zinc-300 dark:ring-zinc-500/30';
|
||||
return badgeColorFor(status);
|
||||
}
|
||||
|
||||
export function formatElapsed(seconds) {
|
||||
@@ -85,13 +90,16 @@ function subscribeToRecordings(recordingIds, handler) {
|
||||
export function transcriptionMonitor({ statusUrl, initial }) {
|
||||
return {
|
||||
statusUrl,
|
||||
status: initial,
|
||||
status: {
|
||||
...initial,
|
||||
badge_color: badgeColorFor(initial.status),
|
||||
},
|
||||
pollError: null,
|
||||
tickTimer: null,
|
||||
leaveChannel: null,
|
||||
|
||||
get badgeClass() {
|
||||
return badgeClassFor(this.status.status);
|
||||
get badgeColor() {
|
||||
return badgeColorFor(this.status.status);
|
||||
},
|
||||
|
||||
get startButtonLabel() {
|
||||
@@ -128,7 +136,11 @@ export function transcriptionMonitor({ statusUrl, initial }) {
|
||||
|
||||
applyPayload(payload) {
|
||||
const wasActive = this.status.is_active;
|
||||
this.status = { ...this.status, ...payload };
|
||||
this.status = {
|
||||
...this.status,
|
||||
...payload,
|
||||
badge_color: badgeColorFor(payload.status ?? this.status.status),
|
||||
};
|
||||
this.pollError = null;
|
||||
|
||||
if (this.status.is_active) {
|
||||
@@ -209,6 +221,8 @@ export function recordingsIndex({ recordings, pendingCount }) {
|
||||
rows: byId,
|
||||
pendingCount: Number(pendingCount) || 0,
|
||||
leaveChannel: null,
|
||||
playingId: null,
|
||||
isPlaying: false,
|
||||
|
||||
start() {
|
||||
this.leaveChannel = subscribeToRecordings(Object.keys(this.rows), (event) => {
|
||||
@@ -221,6 +235,52 @@ export function recordingsIndex({ recordings, pendingCount }) {
|
||||
this.leaveChannel();
|
||||
this.leaveChannel = null;
|
||||
}
|
||||
|
||||
const player = this.$refs.player;
|
||||
|
||||
if (player) {
|
||||
player.pause();
|
||||
player.removeAttribute('src');
|
||||
player.load();
|
||||
}
|
||||
},
|
||||
|
||||
syncPlayer() {
|
||||
const player = this.$refs.player;
|
||||
|
||||
this.isPlaying = Boolean(player && !player.paused && !player.ended);
|
||||
|
||||
if (player?.ended) {
|
||||
this.playingId = null;
|
||||
}
|
||||
},
|
||||
|
||||
isPlayingRow(id) {
|
||||
return this.playingId === id && this.isPlaying;
|
||||
},
|
||||
|
||||
togglePlay(id, url) {
|
||||
const player = this.$refs.player;
|
||||
|
||||
if (!player) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.playingId === id && this.isPlaying) {
|
||||
player.pause();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.playingId !== id) {
|
||||
player.src = url;
|
||||
this.playingId = id;
|
||||
}
|
||||
|
||||
player.play().catch(() => {
|
||||
this.playingId = null;
|
||||
this.isPlaying = false;
|
||||
});
|
||||
},
|
||||
|
||||
applyPayload(payload) {
|
||||
@@ -240,7 +300,7 @@ export function recordingsIndex({ recordings, pendingCount }) {
|
||||
is_active: payload.is_active,
|
||||
word_count: payload.word_count ?? this.rows[id].word_count,
|
||||
word_count_display: formatWordCount(payload.word_count ?? this.rows[id].word_count),
|
||||
badge_class: badgeClassFor(payload.status),
|
||||
badge_color: badgeColorFor(payload.status),
|
||||
};
|
||||
|
||||
this.rows[id] = next;
|
||||
|
||||
Reference in New Issue
Block a user