Release 0.5.1
This commit is contained in:
1 parent
5a9d7735d4
commit
fb24d171ae
36 files changed
+5099
-263
No files matched your search
+392
-9
@@ -1,6 +1,7 @@
|
||||
import { randomUUID } from 'node:crypto';
|
||||
import type Database from 'better-sqlite3';
|
||||
import { getDatabase } from './database.js';
|
||||
import { detectVideoProvider, type PresentationMode } from './presentation.js';
|
||||
|
||||
export const SHOW_STATUSES = ['draft', 'ready', 'live', 'completed'] as const;
|
||||
export const USAGE_STATUSES = ['open', 'current', 'done', 'skipped'] as const;
|
||||
@@ -46,9 +47,32 @@ export type PieceUsage = {
|
||||
moderation: string;
|
||||
transition: string;
|
||||
presentation: string;
|
||||
presentationMode: PresentationMode;
|
||||
presentationSourceLabel: string;
|
||||
presentationSourceUrl: string;
|
||||
presentationSourceTimecodeSeconds: number | null;
|
||||
presentationTitle: string;
|
||||
presentationDescription: string;
|
||||
presentationImageUrl: string;
|
||||
presentationSiteName: string;
|
||||
presentationProvider: string;
|
||||
presentationProviderId: string;
|
||||
ownNotes: string;
|
||||
};
|
||||
|
||||
export type SentPieceUsage = {
|
||||
usageId: string;
|
||||
showId: string;
|
||||
showTitle: string;
|
||||
usedAtUtc: string;
|
||||
};
|
||||
|
||||
export type PieceUsageContext = {
|
||||
sentHistory: SentPieceUsage[];
|
||||
isPlannedInActiveShow: boolean;
|
||||
isPlannedInCurrentShow: boolean;
|
||||
};
|
||||
|
||||
export type ShowSection = {
|
||||
id: string;
|
||||
name: string;
|
||||
@@ -110,9 +134,16 @@ export type PieceUsageUpdate = {
|
||||
moderation: string;
|
||||
transition: string;
|
||||
presentation: string;
|
||||
presentationMode: PresentationMode;
|
||||
presentationSourceLabel: string;
|
||||
presentationSourceUrl: string;
|
||||
presentationSourceTimecodeSeconds: number | null;
|
||||
presentationTitle: string;
|
||||
presentationDescription: string;
|
||||
presentationImageUrl: string;
|
||||
presentationSiteName: string;
|
||||
ownNotes: string;
|
||||
durationSeconds: number;
|
||||
status: UsageStatus;
|
||||
};
|
||||
|
||||
export type MovePieceUsageInput = {
|
||||
@@ -159,6 +190,16 @@ type UsageRow = {
|
||||
moderation_snapshot: string;
|
||||
transition_snapshot: string;
|
||||
presentation_snapshot: string;
|
||||
presentation_mode_snapshot: PresentationMode;
|
||||
presentation_source_label_snapshot: string;
|
||||
presentation_source_url_snapshot: string;
|
||||
presentation_source_timecode_snapshot: number | null;
|
||||
presentation_title_meta_snapshot: string;
|
||||
presentation_description_snapshot: string;
|
||||
presentation_image_url_snapshot: string;
|
||||
presentation_site_name_snapshot: string;
|
||||
presentation_provider_snapshot: string;
|
||||
presentation_provider_id_snapshot: string;
|
||||
own_notes: string;
|
||||
};
|
||||
|
||||
@@ -191,6 +232,50 @@ function validTimestamp(value: string | null): string | null {
|
||||
return date.toISOString();
|
||||
}
|
||||
|
||||
function validPresentation(
|
||||
mode: PresentationMode,
|
||||
sourceLabel: string,
|
||||
sourceUrl: string,
|
||||
timecodeSeconds: number | null,
|
||||
title: string,
|
||||
description: string,
|
||||
imageUrl: string,
|
||||
siteName: string
|
||||
) {
|
||||
if (!['text', 'link', 'video'].includes(mode)) throw new Error('INVALID_PRESENTATION');
|
||||
const cleanUrl = cleanText(sourceUrl, 2_000, 'presentation_source');
|
||||
const cleanImageUrl = cleanText(imageUrl, 2_000, 'presentation_image');
|
||||
for (const value of [cleanUrl, cleanImageUrl]) {
|
||||
if (!value) continue;
|
||||
try {
|
||||
const url = new URL(value);
|
||||
if (!['http:', 'https:'].includes(url.protocol)) throw new Error();
|
||||
} catch {
|
||||
throw new Error('INVALID_PRESENTATION');
|
||||
}
|
||||
}
|
||||
if (mode !== 'text' && !cleanUrl) throw new Error('INVALID_PRESENTATION');
|
||||
if (
|
||||
timecodeSeconds !== null &&
|
||||
(!Number.isInteger(timecodeSeconds) || timecodeSeconds < 0 || timecodeSeconds > 86_400)
|
||||
) {
|
||||
throw new Error('INVALID_PRESENTATION');
|
||||
}
|
||||
const detected = detectVideoProvider(cleanUrl);
|
||||
return {
|
||||
mode,
|
||||
sourceLabel: cleanText(sourceLabel, 200, 'presentation_source'),
|
||||
sourceUrl: cleanUrl,
|
||||
timecodeSeconds,
|
||||
title: cleanText(title, 300, 'presentation_title'),
|
||||
description: cleanText(description, 1_000, 'presentation_description'),
|
||||
imageUrl: cleanImageUrl,
|
||||
siteName: cleanText(siteName, 200, 'presentation_site'),
|
||||
provider: detected?.provider ?? '',
|
||||
providerId: detected?.id ?? ''
|
||||
};
|
||||
}
|
||||
|
||||
function requireRevision(expectedRevision: number): void {
|
||||
if (!Number.isInteger(expectedRevision) || expectedRevision < 1) {
|
||||
throw new Error('INVALID_REVISION');
|
||||
@@ -296,6 +381,16 @@ function usageFromRow(row: UsageRow): PieceUsage {
|
||||
moderation: row.moderation_snapshot,
|
||||
transition: row.transition_snapshot,
|
||||
presentation: row.presentation_snapshot,
|
||||
presentationMode: row.presentation_mode_snapshot,
|
||||
presentationSourceLabel: row.presentation_source_label_snapshot,
|
||||
presentationSourceUrl: row.presentation_source_url_snapshot,
|
||||
presentationSourceTimecodeSeconds: row.presentation_source_timecode_snapshot,
|
||||
presentationTitle: row.presentation_title_meta_snapshot,
|
||||
presentationDescription: row.presentation_description_snapshot,
|
||||
presentationImageUrl: row.presentation_image_url_snapshot,
|
||||
presentationSiteName: row.presentation_site_name_snapshot,
|
||||
presentationProvider: row.presentation_provider_snapshot,
|
||||
presentationProviderId: row.presentation_provider_id_snapshot,
|
||||
ownNotes: row.own_notes
|
||||
};
|
||||
}
|
||||
@@ -384,7 +479,12 @@ export function getShow(id: string): Show | null {
|
||||
.prepare(
|
||||
`SELECT u.id, u.show_section_id, u.original_piece_id, u.position, u.status,
|
||||
u.duration_seconds, u.title_snapshot, u.intro_snapshot, u.research_snapshot,
|
||||
u.moderation_snapshot, u.transition_snapshot, u.presentation_snapshot, u.own_notes
|
||||
u.moderation_snapshot, u.transition_snapshot, u.presentation_snapshot,
|
||||
u.presentation_mode_snapshot, u.presentation_source_label_snapshot,
|
||||
u.presentation_source_url_snapshot, u.presentation_source_timecode_snapshot,
|
||||
u.presentation_title_meta_snapshot, u.presentation_description_snapshot,
|
||||
u.presentation_image_url_snapshot, u.presentation_site_name_snapshot,
|
||||
u.presentation_provider_snapshot, u.presentation_provider_id_snapshot, u.own_notes
|
||||
FROM piece_usages u JOIN show_sections s ON s.id = u.show_section_id
|
||||
WHERE s.show_id = ? ORDER BY s.position, u.position`
|
||||
)
|
||||
@@ -430,6 +530,80 @@ export function getShow(id: string): Show | null {
|
||||
};
|
||||
}
|
||||
|
||||
export function getPieceUsageContexts(
|
||||
pieceIds: string[],
|
||||
currentShowId?: string
|
||||
): Record<string, PieceUsageContext> {
|
||||
const uniquePieceIds = [...new Set(pieceIds.filter(Boolean))];
|
||||
const contexts = Object.fromEntries(
|
||||
uniquePieceIds.map((pieceId) => [
|
||||
pieceId,
|
||||
{
|
||||
sentHistory: [],
|
||||
isPlannedInActiveShow: false,
|
||||
isPlannedInCurrentShow: false
|
||||
} satisfies PieceUsageContext
|
||||
])
|
||||
) as Record<string, PieceUsageContext>;
|
||||
if (!uniquePieceIds.length) return contexts;
|
||||
|
||||
const database = getDatabase();
|
||||
const history = database
|
||||
.prepare(
|
||||
`SELECT u.id AS usage_id, u.original_piece_id, sh.id AS show_id,
|
||||
sh.title AS show_title, COALESCE(sh.starts_at_utc, sh.updated_at_utc) AS used_at_utc
|
||||
FROM piece_usages u
|
||||
JOIN show_sections s ON s.id = u.show_section_id
|
||||
JOIN shows sh ON sh.id = s.show_id
|
||||
WHERE u.original_piece_id IS NOT NULL AND u.status = 'done'
|
||||
AND sh.status = 'completed' AND s.is_reserve_bank = 0
|
||||
ORDER BY used_at_utc DESC, u.id DESC`
|
||||
)
|
||||
.all() as {
|
||||
usage_id: string;
|
||||
original_piece_id: string;
|
||||
show_id: string;
|
||||
show_title: string;
|
||||
used_at_utc: string;
|
||||
}[];
|
||||
for (const usage of history) {
|
||||
contexts[usage.original_piece_id]?.sentHistory.push({
|
||||
usageId: usage.usage_id,
|
||||
showId: usage.show_id,
|
||||
showTitle: usage.show_title,
|
||||
usedAtUtc: usage.used_at_utc
|
||||
});
|
||||
}
|
||||
const plannedInActiveShows = database
|
||||
.prepare(
|
||||
`SELECT DISTINCT u.original_piece_id FROM piece_usages u
|
||||
JOIN show_sections s ON s.id = u.show_section_id
|
||||
JOIN shows sh ON sh.id = s.show_id
|
||||
WHERE sh.status != 'completed' AND u.original_piece_id IS NOT NULL`
|
||||
)
|
||||
.all() as { original_piece_id: string }[];
|
||||
for (const usage of plannedInActiveShows) {
|
||||
const context = contexts[usage.original_piece_id];
|
||||
if (context) context.isPlannedInActiveShow = true;
|
||||
}
|
||||
|
||||
if (currentShowId) {
|
||||
const planned = database
|
||||
.prepare(
|
||||
`SELECT DISTINCT u.original_piece_id FROM piece_usages u
|
||||
JOIN show_sections s ON s.id = u.show_section_id
|
||||
WHERE s.show_id = ? AND u.original_piece_id IS NOT NULL`
|
||||
)
|
||||
.all(currentShowId) as { original_piece_id: string }[];
|
||||
for (const usage of planned) {
|
||||
const context = contexts[usage.original_piece_id];
|
||||
if (context) context.isPlannedInCurrentShow = true;
|
||||
}
|
||||
}
|
||||
|
||||
return contexts;
|
||||
}
|
||||
|
||||
export function createShow(input: CreateShowInput): CreatedMutationResult {
|
||||
const database = getDatabase();
|
||||
const id = randomUUID();
|
||||
@@ -631,8 +805,15 @@ export function addPieceUsage(
|
||||
sectionBelongsToShow(database, showId, sectionId, input.sectionId === null);
|
||||
const piece = database
|
||||
.prepare(
|
||||
`SELECT title, duration_seconds, intro, research_text, moderation_notes,
|
||||
transition_text, presentation_text, status FROM pieces WHERE id = ?`
|
||||
`SELECT p.title, p.duration_seconds, p.intro, p.research_text, p.moderation_notes,
|
||||
p.transition_text, p.presentation_text, p.status, p.presentation_mode,
|
||||
COALESCE(ps.label, '') AS presentation_source_label,
|
||||
COALESCE(ps.url, '') AS presentation_source_url,
|
||||
ps.timecode_seconds AS presentation_source_timecode,
|
||||
p.presentation_title, p.presentation_description, p.presentation_image_url,
|
||||
p.presentation_site_name, p.presentation_provider, p.presentation_provider_id
|
||||
FROM pieces p LEFT JOIN piece_sources ps ON ps.piece_id = p.id
|
||||
AND ps.position = p.presentation_source_position WHERE p.id = ?`
|
||||
)
|
||||
.get(input.pieceId) as
|
||||
| {
|
||||
@@ -643,6 +824,16 @@ export function addPieceUsage(
|
||||
moderation_notes: string;
|
||||
transition_text: string;
|
||||
presentation_text: string;
|
||||
presentation_mode: PresentationMode;
|
||||
presentation_source_label: string;
|
||||
presentation_source_url: string;
|
||||
presentation_source_timecode: number | null;
|
||||
presentation_title: string;
|
||||
presentation_description: string;
|
||||
presentation_image_url: string;
|
||||
presentation_site_name: string;
|
||||
presentation_provider: string;
|
||||
presentation_provider_id: string;
|
||||
status: string;
|
||||
}
|
||||
| undefined;
|
||||
@@ -659,8 +850,13 @@ export function addPieceUsage(
|
||||
.prepare(
|
||||
`INSERT INTO piece_usages (id, show_section_id, original_piece_id, position, status,
|
||||
duration_seconds, title_snapshot, intro_snapshot, research_snapshot,
|
||||
moderation_snapshot, transition_snapshot, presentation_snapshot, own_notes, is_reserve)
|
||||
VALUES (?, ?, ?, ?, 'open', ?, ?, ?, ?, ?, ?, ?, '', ?)`
|
||||
moderation_snapshot, transition_snapshot, presentation_snapshot,
|
||||
presentation_mode_snapshot, presentation_source_label_snapshot,
|
||||
presentation_source_url_snapshot, presentation_source_timecode_snapshot,
|
||||
presentation_title_meta_snapshot, presentation_description_snapshot,
|
||||
presentation_image_url_snapshot, presentation_site_name_snapshot,
|
||||
presentation_provider_snapshot, presentation_provider_id_snapshot, own_notes, is_reserve)
|
||||
VALUES (?, ?, ?, ?, 'open', ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, '', ?)`
|
||||
)
|
||||
.run(
|
||||
id,
|
||||
@@ -674,6 +870,16 @@ export function addPieceUsage(
|
||||
piece.moderation_notes,
|
||||
piece.transition_text,
|
||||
piece.presentation_text,
|
||||
piece.presentation_mode,
|
||||
piece.presentation_source_label,
|
||||
piece.presentation_source_url,
|
||||
piece.presentation_source_timecode,
|
||||
piece.presentation_title,
|
||||
piece.presentation_description,
|
||||
piece.presentation_image_url,
|
||||
piece.presentation_site_name,
|
||||
piece.presentation_provider,
|
||||
piece.presentation_provider_id,
|
||||
input.sectionId === null ? 1 : 0
|
||||
);
|
||||
ids.splice(position, 0, id);
|
||||
@@ -682,6 +888,160 @@ export function addPieceUsage(
|
||||
})();
|
||||
}
|
||||
|
||||
export function duplicatePieceUsage(
|
||||
showId: string,
|
||||
usageId: string,
|
||||
expectedRevision: number
|
||||
): CreatedMutationResult {
|
||||
const database = getDatabase();
|
||||
return database.transaction(() => {
|
||||
const result = bumpShow(database, showId, expectedRevision);
|
||||
const sourceSection = usageSection(database, showId, usageId);
|
||||
const source = database
|
||||
.prepare(
|
||||
`SELECT original_piece_id, status, duration_seconds, title_snapshot, intro_snapshot,
|
||||
research_snapshot, moderation_snapshot, transition_snapshot, presentation_snapshot,
|
||||
presentation_mode_snapshot, presentation_source_label_snapshot,
|
||||
presentation_source_url_snapshot, presentation_source_timecode_snapshot,
|
||||
presentation_title_meta_snapshot, presentation_description_snapshot,
|
||||
presentation_image_url_snapshot, presentation_site_name_snapshot,
|
||||
presentation_provider_snapshot, presentation_provider_id_snapshot,
|
||||
own_notes, is_reserve FROM piece_usages WHERE id = ?`
|
||||
)
|
||||
.get(usageId) as Omit<UsageRow, 'id' | 'show_section_id' | 'position'> & {
|
||||
is_reserve: number;
|
||||
};
|
||||
const ids = (
|
||||
database
|
||||
.prepare('SELECT id FROM piece_usages WHERE show_section_id = ? ORDER BY position')
|
||||
.all(sourceSection.sectionId) as { id: string }[]
|
||||
).map((row) => row.id);
|
||||
const sourcePosition = ids.indexOf(usageId);
|
||||
if (sourcePosition < 0) throw new Error('NOT_FOUND');
|
||||
const id = randomUUID();
|
||||
database
|
||||
.prepare(
|
||||
`INSERT INTO piece_usages (id, show_section_id, original_piece_id, position, status,
|
||||
duration_seconds, title_snapshot, intro_snapshot, research_snapshot,
|
||||
moderation_snapshot, transition_snapshot, presentation_snapshot,
|
||||
presentation_mode_snapshot, presentation_source_label_snapshot,
|
||||
presentation_source_url_snapshot, presentation_source_timecode_snapshot,
|
||||
presentation_title_meta_snapshot, presentation_description_snapshot,
|
||||
presentation_image_url_snapshot, presentation_site_name_snapshot,
|
||||
presentation_provider_snapshot, presentation_provider_id_snapshot, own_notes, is_reserve)
|
||||
VALUES (?, ?, ?, ?, 'open', ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
||||
)
|
||||
.run(
|
||||
id,
|
||||
sourceSection.sectionId,
|
||||
source.original_piece_id,
|
||||
ids.length,
|
||||
source.duration_seconds,
|
||||
source.title_snapshot,
|
||||
source.intro_snapshot,
|
||||
source.research_snapshot,
|
||||
source.moderation_snapshot,
|
||||
source.transition_snapshot,
|
||||
source.presentation_snapshot,
|
||||
source.presentation_mode_snapshot,
|
||||
source.presentation_source_label_snapshot,
|
||||
source.presentation_source_url_snapshot,
|
||||
source.presentation_source_timecode_snapshot,
|
||||
source.presentation_title_meta_snapshot,
|
||||
source.presentation_description_snapshot,
|
||||
source.presentation_image_url_snapshot,
|
||||
source.presentation_site_name_snapshot,
|
||||
source.presentation_provider_snapshot,
|
||||
source.presentation_provider_id_snapshot,
|
||||
source.own_notes,
|
||||
source.is_reserve
|
||||
);
|
||||
ids.splice(sourcePosition + 1, 0, id);
|
||||
normalizePositions(database, 'piece_usages', ids);
|
||||
return { ...result, id };
|
||||
})();
|
||||
}
|
||||
|
||||
export function refreshPieceUsageFromOriginal(
|
||||
showId: string,
|
||||
usageId: string,
|
||||
expectedRevision: number
|
||||
): MutationResult {
|
||||
const database = getDatabase();
|
||||
return database.transaction(() => {
|
||||
const result = bumpShow(database, showId, expectedRevision);
|
||||
usageSection(database, showId, usageId);
|
||||
const source = database
|
||||
.prepare(
|
||||
`SELECT p.title, p.duration_seconds, p.intro, p.research_text,
|
||||
p.moderation_notes, p.transition_text, p.presentation_text, p.presentation_mode,
|
||||
COALESCE(ps.label, '') AS presentation_source_label,
|
||||
COALESCE(ps.url, '') AS presentation_source_url,
|
||||
ps.timecode_seconds AS presentation_source_timecode,
|
||||
p.presentation_title, p.presentation_description, p.presentation_image_url,
|
||||
p.presentation_site_name, p.presentation_provider, p.presentation_provider_id
|
||||
FROM piece_usages u JOIN pieces p ON p.id = u.original_piece_id
|
||||
LEFT JOIN piece_sources ps ON ps.piece_id = p.id
|
||||
AND ps.position = p.presentation_source_position
|
||||
WHERE u.id = ?`
|
||||
)
|
||||
.get(usageId) as
|
||||
| {
|
||||
title: string;
|
||||
duration_seconds: number;
|
||||
intro: string;
|
||||
research_text: string;
|
||||
moderation_notes: string;
|
||||
transition_text: string;
|
||||
presentation_text: string;
|
||||
presentation_mode: PresentationMode;
|
||||
presentation_source_label: string;
|
||||
presentation_source_url: string;
|
||||
presentation_source_timecode: number | null;
|
||||
presentation_title: string;
|
||||
presentation_description: string;
|
||||
presentation_image_url: string;
|
||||
presentation_site_name: string;
|
||||
presentation_provider: string;
|
||||
presentation_provider_id: string;
|
||||
}
|
||||
| undefined;
|
||||
if (!source) throw new Error('ORIGINAL_NOT_FOUND');
|
||||
database
|
||||
.prepare(
|
||||
`UPDATE piece_usages SET title_snapshot = ?, duration_seconds = ?, intro_snapshot = ?,
|
||||
research_snapshot = ?, moderation_snapshot = ?, transition_snapshot = ?,
|
||||
presentation_snapshot = ?, presentation_mode_snapshot = ?,
|
||||
presentation_source_label_snapshot = ?, presentation_source_url_snapshot = ?,
|
||||
presentation_source_timecode_snapshot = ?, presentation_title_meta_snapshot = ?,
|
||||
presentation_description_snapshot = ?, presentation_image_url_snapshot = ?,
|
||||
presentation_site_name_snapshot = ?, presentation_provider_snapshot = ?,
|
||||
presentation_provider_id_snapshot = ? WHERE id = ?`
|
||||
)
|
||||
.run(
|
||||
source.title,
|
||||
source.duration_seconds,
|
||||
source.intro,
|
||||
source.research_text,
|
||||
source.moderation_notes,
|
||||
source.transition_text,
|
||||
source.presentation_text,
|
||||
source.presentation_mode,
|
||||
source.presentation_source_label,
|
||||
source.presentation_source_url,
|
||||
source.presentation_source_timecode,
|
||||
source.presentation_title,
|
||||
source.presentation_description,
|
||||
source.presentation_image_url,
|
||||
source.presentation_site_name,
|
||||
source.presentation_provider,
|
||||
source.presentation_provider_id,
|
||||
usageId
|
||||
);
|
||||
return result;
|
||||
})();
|
||||
}
|
||||
|
||||
export function updatePieceUsage(
|
||||
showId: string,
|
||||
usageId: string,
|
||||
@@ -690,7 +1050,6 @@ export function updatePieceUsage(
|
||||
): MutationResult {
|
||||
const title = cleanText(input.title, 200, 'title', true);
|
||||
const duration = validDuration(input.durationSeconds)!;
|
||||
if (!USAGE_STATUSES.includes(input.status)) throw new Error('INVALID_STATUS');
|
||||
const values = {
|
||||
intro: cleanText(input.intro, 50_000, 'intro'),
|
||||
research: cleanText(input.research, 50_000, 'research'),
|
||||
@@ -699,6 +1058,16 @@ export function updatePieceUsage(
|
||||
presentation: cleanText(input.presentation, 50_000, 'presentation'),
|
||||
ownNotes: cleanText(input.ownNotes, 50_000, 'notes')
|
||||
};
|
||||
const presentation = validPresentation(
|
||||
input.presentationMode,
|
||||
input.presentationSourceLabel,
|
||||
input.presentationSourceUrl,
|
||||
input.presentationSourceTimecodeSeconds,
|
||||
input.presentationTitle,
|
||||
input.presentationDescription,
|
||||
input.presentationImageUrl,
|
||||
input.presentationSiteName
|
||||
);
|
||||
const database = getDatabase();
|
||||
return database.transaction(() => {
|
||||
const result = bumpShow(database, showId, expectedRevision);
|
||||
@@ -707,7 +1076,12 @@ export function updatePieceUsage(
|
||||
.prepare(
|
||||
`UPDATE piece_usages SET title_snapshot = ?, intro_snapshot = ?, research_snapshot = ?,
|
||||
moderation_snapshot = ?, transition_snapshot = ?, presentation_snapshot = ?,
|
||||
own_notes = ?, duration_seconds = ?, status = ? WHERE id = ?`
|
||||
presentation_mode_snapshot = ?, presentation_source_label_snapshot = ?,
|
||||
presentation_source_url_snapshot = ?, presentation_source_timecode_snapshot = ?,
|
||||
presentation_title_meta_snapshot = ?, presentation_description_snapshot = ?,
|
||||
presentation_image_url_snapshot = ?, presentation_site_name_snapshot = ?,
|
||||
presentation_provider_snapshot = ?, presentation_provider_id_snapshot = ?,
|
||||
own_notes = ?, duration_seconds = ? WHERE id = ?`
|
||||
)
|
||||
.run(
|
||||
title,
|
||||
@@ -716,9 +1090,18 @@ export function updatePieceUsage(
|
||||
values.moderation,
|
||||
values.transition,
|
||||
values.presentation,
|
||||
presentation.mode,
|
||||
presentation.sourceLabel,
|
||||
presentation.sourceUrl,
|
||||
presentation.timecodeSeconds,
|
||||
presentation.title,
|
||||
presentation.description,
|
||||
presentation.imageUrl,
|
||||
presentation.siteName,
|
||||
presentation.provider,
|
||||
presentation.providerId,
|
||||
values.ownNotes,
|
||||
duration,
|
||||
input.status,
|
||||
usageId
|
||||
);
|
||||
return result;
|
||||
|
||||
Reference in new issue
Block a user