@happyvertical/smrt-content 0.36.1 → 0.36.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/asset-associable.d.ts +2 -2
- package/dist/asset-associable.d.ts.map +1 -1
- package/dist/body-format.d.ts +18 -3
- package/dist/body-format.d.ts.map +1 -1
- package/dist/body-format.js.map +1 -1
- package/dist/content-contribution-attachment.d.ts +4 -4
- package/dist/content-contribution-attachment.d.ts.map +1 -1
- package/dist/content-contribution-config.d.ts +1 -1
- package/dist/content-contribution-config.d.ts.map +1 -1
- package/dist/content-contribution-revision.d.ts +4 -4
- package/dist/content-contribution-revision.d.ts.map +1 -1
- package/dist/content-contribution-type.d.ts +5 -5
- package/dist/content-contribution-type.d.ts.map +1 -1
- package/dist/content-contribution.d.ts +7 -7
- package/dist/content-contribution.d.ts.map +1 -1
- package/dist/content-contributions.d.ts +24 -2
- package/dist/content-contributions.d.ts.map +1 -1
- package/dist/content-contributor.d.ts +5 -5
- package/dist/content-contributor.d.ts.map +1 -1
- package/dist/content-correction.d.ts +2 -2
- package/dist/content-correction.d.ts.map +1 -1
- package/dist/content-feed-parser.d.ts.map +1 -1
- package/dist/content-feed-source.d.ts +5 -5
- package/dist/content-feed-source.d.ts.map +1 -1
- package/dist/content-governance-assignment.d.ts +2 -2
- package/dist/content-governance-assignment.d.ts.map +1 -1
- package/dist/content-governance-policy.d.ts +2 -2
- package/dist/content-governance-policy.d.ts.map +1 -1
- package/dist/content-governance-profile.d.ts +2 -2
- package/dist/content-governance-profile.d.ts.map +1 -1
- package/dist/content-governance.d.ts +7 -7
- package/dist/content-governance.d.ts.map +1 -1
- package/dist/content-review.d.ts +2 -2
- package/dist/content-review.d.ts.map +1 -1
- package/dist/content-reviews.d.ts +1 -1
- package/dist/content-reviews.d.ts.map +1 -1
- package/dist/content-transparency.d.ts +38 -7
- package/dist/content-transparency.d.ts.map +1 -1
- package/dist/content-types.d.ts +1 -1
- package/dist/content-types.d.ts.map +1 -1
- package/dist/content-version.d.ts +17 -4
- package/dist/content-version.d.ts.map +1 -1
- package/dist/content-versions.d.ts.map +1 -1
- package/dist/content.d.ts +40 -36
- package/dist/content.d.ts.map +1 -1
- package/dist/contents.d.ts +46 -31
- package/dist/contents.d.ts.map +1 -1
- package/dist/index.js +224 -118
- package/dist/index.js.map +1 -1
- package/dist/manifest.json +40 -40
- package/dist/serialization.d.ts +66 -49
- package/dist/serialization.d.ts.map +1 -1
- package/dist/smrt-knowledge.json +4 -4
- package/dist/svelte/components/ContentAgentChat.svelte +42 -24
- package/dist/svelte/components/ContentAgentChat.svelte.d.ts.map +1 -1
- package/dist/svelte/components/ContentBodyEditor.svelte +8 -3
- package/dist/svelte/components/ContentBodyEditor.svelte.d.ts +3 -3
- package/dist/svelte/components/ContentBodyEditor.svelte.d.ts.map +1 -1
- package/dist/svelte/components/ContentClaimAuditTool.svelte +6 -6
- package/dist/svelte/components/ContentCorrectionsTool.svelte +4 -4
- package/dist/svelte/components/ContentEditor.svelte +69 -30
- package/dist/svelte/components/ContentEditor.svelte.d.ts +6 -3
- package/dist/svelte/components/ContentEditor.svelte.d.ts.map +1 -1
- package/dist/svelte/components/ContentGovernanceManager.svelte +4 -2
- package/dist/svelte/components/ContentGovernanceManager.svelte.d.ts.map +1 -1
- package/dist/svelte/components/ContentGovernancePanel.svelte +21 -21
- package/dist/svelte/components/ContentList.svelte +20 -17
- package/dist/svelte/components/ContentList.svelte.d.ts +8 -7
- package/dist/svelte/components/ContentList.svelte.d.ts.map +1 -1
- package/dist/svelte/components/ContentMetadataFields.svelte +10 -1
- package/dist/svelte/components/ContentMetadataFields.svelte.d.ts +9 -1
- package/dist/svelte/components/ContentMetadataFields.svelte.d.ts.map +1 -1
- package/dist/svelte/components/ContentStatusFields.svelte +9 -1
- package/dist/svelte/components/ContentStatusFields.svelte.d.ts +8 -1
- package/dist/svelte/components/ContentStatusFields.svelte.d.ts.map +1 -1
- package/dist/svelte/components/ContentTransparencyTool.svelte +4 -2
- package/dist/svelte/components/ContentTransparencyTool.svelte.d.ts.map +1 -1
- package/dist/svelte/components/ContentVersionsTool.svelte +6 -6
- package/dist/svelte/components/GovernedContentEditor.svelte +8 -2
- package/dist/svelte/components/GovernedContentEditor.svelte.d.ts.map +1 -1
- package/dist/svelte/routes/ContentContributionsRoute.svelte +11 -10
- package/dist/svelte/routes/ContentContributionsRoute.svelte.d.ts.map +1 -1
- package/dist/svelte/routes/ContentFactsRoute.svelte +2 -2
- package/dist/svelte/routes/ContentWorkspaceRoute.svelte +6 -6
- package/dist/thumbnail-generator.d.ts.map +1 -1
- package/package.json +14 -14
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
type ContentBodyImagePlacement,
|
|
11
11
|
editorHtmlToBody,
|
|
12
12
|
extractBodyImages,
|
|
13
|
+
type ImageAssetLike,
|
|
13
14
|
imageAssetToHtml,
|
|
14
15
|
normalizeEditorHtml,
|
|
15
16
|
resolveBodyFormat,
|
|
@@ -35,7 +36,7 @@ export interface Props {
|
|
|
35
36
|
onUseImageAsThumbnail?: (assetId: string) => void;
|
|
36
37
|
onResolveImage?: (
|
|
37
38
|
selected: ImageLike | File | string,
|
|
38
|
-
) => Promise<
|
|
39
|
+
) => Promise<unknown> | unknown;
|
|
39
40
|
}
|
|
40
41
|
|
|
41
42
|
let {
|
|
@@ -667,7 +668,7 @@ function insertImageHtml(html: string) {
|
|
|
667
668
|
emitChange();
|
|
668
669
|
}
|
|
669
670
|
|
|
670
|
-
export function insertImageAsset(asset:
|
|
671
|
+
export function insertImageAsset(asset: ImageAssetLike | null | undefined) {
|
|
671
672
|
insertImageHtml(imageAssetToHtml(asset));
|
|
672
673
|
}
|
|
673
674
|
|
|
@@ -863,9 +864,13 @@ function startImageMove(event: PointerEvent) {
|
|
|
863
864
|
}
|
|
864
865
|
|
|
865
866
|
async function resolveAndInsertImage(selected: ImageLike | File | string) {
|
|
867
|
+
// Dynamic boundary: the consumer-supplied `onResolveImage` callback returns an
|
|
868
|
+
// opaque resolved value (or, without it, the raw ImageLike/File/string). The
|
|
869
|
+
// image helpers read optional fields defensively, so coerce to the structural
|
|
870
|
+
// ImageAssetLike shape rather than widening the public insertImageAsset param.
|
|
866
871
|
const asset = onResolveImage ? await onResolveImage(selected) : selected;
|
|
867
872
|
if (asset) {
|
|
868
|
-
insertImageAsset(asset);
|
|
873
|
+
insertImageAsset(asset as ImageAssetLike);
|
|
869
874
|
}
|
|
870
875
|
}
|
|
871
876
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ImageLike } from '@happyvertical/smrt-images/svelte';
|
|
2
|
-
import { type ContentBodyFormat, type ContentBodyImage } from '../../body-format';
|
|
2
|
+
import { type ContentBodyFormat, type ContentBodyImage, type ImageAssetLike } from '../../body-format';
|
|
3
3
|
export interface ContentBodyEditorChange {
|
|
4
4
|
body: string;
|
|
5
5
|
bodyFormat: ContentBodyFormat;
|
|
@@ -14,10 +14,10 @@ export interface Props {
|
|
|
14
14
|
onOpenImageChooser?: () => void;
|
|
15
15
|
onSelectImage?: (index: number) => void;
|
|
16
16
|
onUseImageAsThumbnail?: (assetId: string) => void;
|
|
17
|
-
onResolveImage?: (selected: ImageLike | File | string) => Promise<
|
|
17
|
+
onResolveImage?: (selected: ImageLike | File | string) => Promise<unknown> | unknown;
|
|
18
18
|
}
|
|
19
19
|
declare const ContentBodyEditor: import("svelte").Component<Props, {
|
|
20
|
-
insertImageAsset: (asset:
|
|
20
|
+
insertImageAsset: (asset: ImageAssetLike | null | undefined) => void;
|
|
21
21
|
focusImage: (index: number) => void;
|
|
22
22
|
}, "">;
|
|
23
23
|
type ContentBodyEditor = ReturnType<typeof ContentBodyEditor>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ContentBodyEditor.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/ContentBodyEditor.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mCAAmC,CAAC;AAInE,OAAO,EAEL,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,
|
|
1
|
+
{"version":3,"file":"ContentBodyEditor.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/ContentBodyEditor.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mCAAmC,CAAC;AAInE,OAAO,EAEL,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EAIrB,KAAK,cAAc,EAIpB,MAAM,mBAAmB,CAAC;AAI3B,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,iBAAiB,CAAC;IAC9B,MAAM,EAAE,gBAAgB,EAAE,CAAC;CAC5B;AAED,MAAM,WAAW,KAAK;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAClC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,uBAAuB,KAAK,IAAI,CAAC;IACrD,kBAAkB,CAAC,EAAE,MAAM,IAAI,CAAC;IAChC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,qBAAqB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAClD,cAAc,CAAC,EAAE,CACf,QAAQ,EAAE,SAAS,GAAG,IAAI,GAAG,MAAM,KAChC,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;CACjC;AA4lCD,QAAA,MAAM,iBAAiB;8BAzdW,cAAc,GAAG,IAAI,GAAG,SAAS;wBAIvC,MAAM;MAqd6B,CAAC;AAChE,KAAK,iBAAiB,GAAG,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAC9D,eAAe,iBAAiB,CAAC"}
|
|
@@ -113,9 +113,9 @@ async function loadFactAudit(contentIdToLoad = savedContentId) {
|
|
|
113
113
|
if (savedContentId !== contentIdToLoad) return;
|
|
114
114
|
factAudit = response.data;
|
|
115
115
|
onFactAuditChange?.(response.data);
|
|
116
|
-
} catch (err
|
|
116
|
+
} catch (err) {
|
|
117
117
|
if (savedContentId !== contentIdToLoad) return;
|
|
118
|
-
error = err.message || 'Failed to load claim audit';
|
|
118
|
+
error = (err instanceof Error ? err.message : '') || 'Failed to load claim audit';
|
|
119
119
|
} finally {
|
|
120
120
|
if (savedContentId === contentIdToLoad) {
|
|
121
121
|
busy = false;
|
|
@@ -137,9 +137,9 @@ async function repairFactAudit() {
|
|
|
137
137
|
factAudit = response.data;
|
|
138
138
|
notice = `Fact audit repaired: ${response.data.counts.total} claim(s) checked.`;
|
|
139
139
|
onFactAuditChange?.(response.data);
|
|
140
|
-
} catch (err
|
|
140
|
+
} catch (err) {
|
|
141
141
|
if (savedContentId !== contentIdToRepair) return;
|
|
142
|
-
error = err.message || 'Failed to repair fact audit';
|
|
142
|
+
error = (err instanceof Error ? err.message : '') || 'Failed to repair fact audit';
|
|
143
143
|
} finally {
|
|
144
144
|
if (savedContentId === contentIdToRepair) {
|
|
145
145
|
busy = false;
|
|
@@ -167,9 +167,9 @@ async function recheckFactClaims(claimIds: string[]) {
|
|
|
167
167
|
notice = `Rechecked ${claimIds.length} claim${claimIds.length === 1 ? '' : 's'} against current evidence.`;
|
|
168
168
|
selectedClaimIds = selectedClaimIds.filter((id) => !claimIds.includes(id));
|
|
169
169
|
onFactAuditChange?.(response.data);
|
|
170
|
-
} catch (err
|
|
170
|
+
} catch (err) {
|
|
171
171
|
if (savedContentId !== contentIdToRecheck) return;
|
|
172
|
-
error = err.message || 'Failed to recheck claim support';
|
|
172
|
+
error = (err instanceof Error ? err.message : '') || 'Failed to recheck claim support';
|
|
173
173
|
} finally {
|
|
174
174
|
if (savedContentId === contentIdToRecheck) {
|
|
175
175
|
busy = false;
|
|
@@ -117,9 +117,9 @@ async function loadCorrections(contentIdToLoad = savedContentId) {
|
|
|
117
117
|
corrections = correctionsResponse.data;
|
|
118
118
|
facts = factsResponse.data.facts || [];
|
|
119
119
|
onCorrectionsChange?.(correctionsResponse.data);
|
|
120
|
-
} catch (err
|
|
120
|
+
} catch (err) {
|
|
121
121
|
if (savedContentId !== contentIdToLoad) return;
|
|
122
|
-
error = err.message || 'Failed to load corrections';
|
|
122
|
+
error = (err instanceof Error ? err.message : '') || 'Failed to load corrections';
|
|
123
123
|
} finally {
|
|
124
124
|
if (savedContentId === contentIdToLoad) {
|
|
125
125
|
busy = false;
|
|
@@ -149,9 +149,9 @@ async function issueCorrection() {
|
|
|
149
149
|
|
|
150
150
|
notice = 'Correction issued.';
|
|
151
151
|
await loadCorrections(contentIdToCorrect);
|
|
152
|
-
} catch (err
|
|
152
|
+
} catch (err) {
|
|
153
153
|
if (savedContentId !== contentIdToCorrect) return;
|
|
154
|
-
error = err.message || 'Failed to issue correction';
|
|
154
|
+
error = (err instanceof Error ? err.message : '') || 'Failed to issue correction';
|
|
155
155
|
} finally {
|
|
156
156
|
if (savedContentId === contentIdToCorrect) {
|
|
157
157
|
busy = false;
|
|
@@ -22,13 +22,20 @@ import type {
|
|
|
22
22
|
FactEvidenceStatus,
|
|
23
23
|
} from '../../mock-smrt-client';
|
|
24
24
|
import { joinApiUrl, normalizeApiBaseUrl } from '../api';
|
|
25
|
+
import type { ContentData } from '../../mock-smrt-client';
|
|
25
26
|
import {
|
|
27
|
+
type ContentEditorAsset,
|
|
26
28
|
type ContentEditorFormData,
|
|
29
|
+
type ContentEditorInitialContent,
|
|
30
|
+
type ContentEditorReference,
|
|
31
|
+
type ContentEditorSavePayload,
|
|
27
32
|
getContentEditorInitialFormData,
|
|
28
33
|
getContentEditorSavePayload,
|
|
29
34
|
getContentEditorSnapshot,
|
|
30
35
|
normalizePublishDate,
|
|
31
36
|
} from '../content-editor-form';
|
|
37
|
+
|
|
38
|
+
type ContentEditorSnapshot = ReturnType<typeof getContentEditorSnapshot>;
|
|
32
39
|
import { M } from '../i18n.editor.js';
|
|
33
40
|
import ContentAgentChat from './ContentAgentChat.svelte';
|
|
34
41
|
import ContentBodyEditor, {
|
|
@@ -40,7 +47,7 @@ const { t } = useI18n();
|
|
|
40
47
|
|
|
41
48
|
export interface Props {
|
|
42
49
|
apiBaseUrl?: string;
|
|
43
|
-
content?:
|
|
50
|
+
content?: ContentData | null;
|
|
44
51
|
contentId?: string;
|
|
45
52
|
factAudit?: FactAuditStateData | null;
|
|
46
53
|
saveDisabled?: boolean;
|
|
@@ -51,9 +58,9 @@ export interface Props {
|
|
|
51
58
|
hideChat?: boolean;
|
|
52
59
|
assistantFieldAllowList?: ContentEditorAssistantFieldUpdateAllowList;
|
|
53
60
|
onAssistantContextChange?: ContentEditorAssistantContextChange;
|
|
54
|
-
onChange?: (data:
|
|
61
|
+
onChange?: (data: ContentEditorSnapshot) => void;
|
|
55
62
|
onFactAuditChange?: (state: FactAuditStateData | null) => void;
|
|
56
|
-
onSave: (data:
|
|
63
|
+
onSave: (data: ContentEditorSavePayload) => void;
|
|
57
64
|
onCancel: () => void;
|
|
58
65
|
}
|
|
59
66
|
|
|
@@ -177,7 +184,11 @@ $effect(() => {
|
|
|
177
184
|
const newKey = content?.id ?? contentId;
|
|
178
185
|
if (newKey !== lastContentKey) {
|
|
179
186
|
lastContentKey = newKey;
|
|
180
|
-
|
|
187
|
+
// ContentData carries a nullable bodyFormat; the form initializer accepts
|
|
188
|
+
// the editor's stricter ContentEditorInitialContent shape and normalizes it.
|
|
189
|
+
formData = getContentEditorInitialFormData(
|
|
190
|
+
content as ContentEditorInitialContent | null,
|
|
191
|
+
);
|
|
181
192
|
fieldUndoStack = [];
|
|
182
193
|
showUndoBanner = false;
|
|
183
194
|
}
|
|
@@ -249,7 +260,7 @@ function undoLastApply() {
|
|
|
249
260
|
}
|
|
250
261
|
}
|
|
251
262
|
|
|
252
|
-
function getReferenceLabel(reference:
|
|
263
|
+
function getReferenceLabel(reference: ContentEditorReference): string {
|
|
253
264
|
return (
|
|
254
265
|
reference?.title ||
|
|
255
266
|
reference?.name ||
|
|
@@ -260,12 +271,12 @@ function getReferenceLabel(reference: any): string {
|
|
|
260
271
|
);
|
|
261
272
|
}
|
|
262
273
|
|
|
263
|
-
function getReferenceUrl(reference:
|
|
274
|
+
function getReferenceUrl(reference: ContentEditorReference): string | null {
|
|
264
275
|
return reference?.url || reference?.originalUrl || reference?.source || null;
|
|
265
276
|
}
|
|
266
277
|
|
|
267
278
|
function getResourceClaimsForReference(
|
|
268
|
-
reference:
|
|
279
|
+
reference: ContentEditorReference,
|
|
269
280
|
): FactAuditResourceClaimData[] {
|
|
270
281
|
const selector = getReferenceSourceSelector(reference);
|
|
271
282
|
const referenceId = String(reference?.id || '');
|
|
@@ -290,7 +301,7 @@ function getResourceClaimsForReference(
|
|
|
290
301
|
});
|
|
291
302
|
}
|
|
292
303
|
|
|
293
|
-
function getAuditReferences():
|
|
304
|
+
function getAuditReferences(): ContentEditorReference[] {
|
|
294
305
|
const references = [...(formData.references ?? [])];
|
|
295
306
|
const seen = new Set<string>();
|
|
296
307
|
|
|
@@ -329,7 +340,10 @@ function getAuditReferences(): any[] {
|
|
|
329
340
|
return references;
|
|
330
341
|
}
|
|
331
342
|
|
|
332
|
-
function getReferenceExpansionKey(
|
|
343
|
+
function getReferenceExpansionKey(
|
|
344
|
+
reference: ContentEditorReference,
|
|
345
|
+
index: number,
|
|
346
|
+
): string {
|
|
333
347
|
return String(
|
|
334
348
|
reference?.id ||
|
|
335
349
|
reference?.url ||
|
|
@@ -339,13 +353,19 @@ function getReferenceExpansionKey(reference: any, index: number): string {
|
|
|
339
353
|
);
|
|
340
354
|
}
|
|
341
355
|
|
|
342
|
-
function isReferenceClaimsExpanded(
|
|
356
|
+
function isReferenceClaimsExpanded(
|
|
357
|
+
reference: ContentEditorReference,
|
|
358
|
+
index: number,
|
|
359
|
+
): boolean {
|
|
343
360
|
return expandedReferenceClaimKeys.includes(
|
|
344
361
|
getReferenceExpansionKey(reference, index),
|
|
345
362
|
);
|
|
346
363
|
}
|
|
347
364
|
|
|
348
|
-
function toggleReferenceClaims(
|
|
365
|
+
function toggleReferenceClaims(
|
|
366
|
+
reference: ContentEditorReference,
|
|
367
|
+
index: number,
|
|
368
|
+
) {
|
|
349
369
|
const key = getReferenceExpansionKey(reference, index);
|
|
350
370
|
expandedReferenceClaimKeys = expandedReferenceClaimKeys.includes(key)
|
|
351
371
|
? expandedReferenceClaimKeys.filter((expandedKey) => expandedKey !== key)
|
|
@@ -432,7 +452,7 @@ function toggleResourceClaimSelection(claim: FactAuditResourceClaimData) {
|
|
|
432
452
|
: [...new Set([...selectedEvidenceIds, ...evidenceIds])];
|
|
433
453
|
}
|
|
434
454
|
|
|
435
|
-
function getReferenceSourceSelector(reference:
|
|
455
|
+
function getReferenceSourceSelector(reference: ContentEditorReference): {
|
|
436
456
|
sourceKind: string;
|
|
437
457
|
sourceId: string;
|
|
438
458
|
} | null {
|
|
@@ -496,7 +516,7 @@ function getEvidenceStatusIcon(status: FactEvidenceStatus | null | undefined) {
|
|
|
496
516
|
async function runFactAuditAction(
|
|
497
517
|
path: string,
|
|
498
518
|
method: 'POST' | 'PUT',
|
|
499
|
-
body: Record<string,
|
|
519
|
+
body: Record<string, unknown>,
|
|
500
520
|
): Promise<FactAuditStateData> {
|
|
501
521
|
if (!contentId || contentId === 'new') {
|
|
502
522
|
throw new Error('Save this content before updating evidence.');
|
|
@@ -540,8 +560,10 @@ async function updateEvidenceStatus(
|
|
|
540
560
|
);
|
|
541
561
|
evidenceNotice = `Updated ${evidenceIds.length} evidence item${evidenceIds.length === 1 ? '' : 's'}.`;
|
|
542
562
|
onFactAuditChange?.(nextAudit);
|
|
543
|
-
} catch (error
|
|
544
|
-
evidenceError =
|
|
563
|
+
} catch (error) {
|
|
564
|
+
evidenceError =
|
|
565
|
+
(error instanceof Error ? error.message : '') ||
|
|
566
|
+
'Failed to update evidence status.';
|
|
545
567
|
} finally {
|
|
546
568
|
evidenceBusy = null;
|
|
547
569
|
}
|
|
@@ -551,7 +573,7 @@ async function updateSelectedEvidenceStatus() {
|
|
|
551
573
|
await updateEvidenceStatus(selectedEvidenceIds, bulkEvidenceStatus);
|
|
552
574
|
}
|
|
553
575
|
|
|
554
|
-
async function repairReferenceEvidence(reference:
|
|
576
|
+
async function repairReferenceEvidence(reference: ContentEditorReference) {
|
|
555
577
|
const selector = getReferenceSourceSelector(reference);
|
|
556
578
|
if (!selector || evidenceBusy) {
|
|
557
579
|
return;
|
|
@@ -568,8 +590,10 @@ async function repairReferenceEvidence(reference: any) {
|
|
|
568
590
|
selectedEvidenceIds = [];
|
|
569
591
|
evidenceNotice = 'Reference evidence repaired.';
|
|
570
592
|
onFactAuditChange?.(nextAudit);
|
|
571
|
-
} catch (error
|
|
572
|
-
evidenceError =
|
|
593
|
+
} catch (error) {
|
|
594
|
+
evidenceError =
|
|
595
|
+
(error instanceof Error ? error.message : '') ||
|
|
596
|
+
'Failed to repair reference evidence.';
|
|
573
597
|
} finally {
|
|
574
598
|
evidenceBusy = null;
|
|
575
599
|
}
|
|
@@ -592,8 +616,10 @@ async function repairSelectedReferenceEvidence() {
|
|
|
592
616
|
selectedEvidenceIds = [];
|
|
593
617
|
evidenceNotice = `Repaired ${sources.length} reference${sources.length === 1 ? '' : 's'}.`;
|
|
594
618
|
onFactAuditChange?.(nextAudit);
|
|
595
|
-
} catch (error
|
|
596
|
-
evidenceError =
|
|
619
|
+
} catch (error) {
|
|
620
|
+
evidenceError =
|
|
621
|
+
(error instanceof Error ? error.message : '') ||
|
|
622
|
+
'Failed to repair selected references.';
|
|
597
623
|
} finally {
|
|
598
624
|
evidenceBusy = null;
|
|
599
625
|
}
|
|
@@ -610,7 +636,11 @@ function removeReference(id: string) {
|
|
|
610
636
|
let showImageUploader = $state(false);
|
|
611
637
|
let showInlineImageUploader = $state(false);
|
|
612
638
|
let expandedReferenceClaimKeys = $state<string[]>([]);
|
|
613
|
-
|
|
639
|
+
interface BodyEditorInstance {
|
|
640
|
+
focusImage?: (index: number) => void;
|
|
641
|
+
insertImageAsset?: (asset: ContentEditorAsset) => void;
|
|
642
|
+
}
|
|
643
|
+
let bodyEditor = $state<BodyEditorInstance | null>(null);
|
|
614
644
|
let selectedBodyImageIndex = $state(-1);
|
|
615
645
|
const bodyImages = $derived(
|
|
616
646
|
extractBodyImages(
|
|
@@ -623,8 +653,14 @@ const bodyImages = $derived(
|
|
|
623
653
|
let imageDragOver = $state(false);
|
|
624
654
|
let refDragOver = $state(false);
|
|
625
655
|
|
|
626
|
-
function getImageRecord(payload:
|
|
627
|
-
|
|
656
|
+
function getImageRecord(payload: unknown): ContentEditorAsset {
|
|
657
|
+
if (payload && typeof payload === 'object' && 'data' in payload) {
|
|
658
|
+
const data = (payload as { data?: ContentEditorAsset }).data;
|
|
659
|
+
if (data) {
|
|
660
|
+
return data;
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
return (payload ?? {}) as ContentEditorAsset;
|
|
628
664
|
}
|
|
629
665
|
|
|
630
666
|
// ---------- Image drag-and-drop ----------
|
|
@@ -791,7 +827,7 @@ async function createImageRecord(input: {
|
|
|
791
827
|
name: string;
|
|
792
828
|
sourceUri: string;
|
|
793
829
|
mimeType: string;
|
|
794
|
-
}): Promise<
|
|
830
|
+
}): Promise<ContentEditorAsset | null> {
|
|
795
831
|
const resp = await fetch(joinApiUrl(apiBaseUrl, '/images'), {
|
|
796
832
|
method: 'POST',
|
|
797
833
|
headers: { 'Content-Type': 'application/json' },
|
|
@@ -807,7 +843,7 @@ async function createImageRecord(input: {
|
|
|
807
843
|
|
|
808
844
|
async function resolveSelectedImage(
|
|
809
845
|
selected: ImageLike | File | string,
|
|
810
|
-
): Promise<
|
|
846
|
+
): Promise<ContentEditorAsset | null> {
|
|
811
847
|
if (selected && typeof selected === 'object' && 'id' in selected) {
|
|
812
848
|
addSelectedAsset(selected);
|
|
813
849
|
return selected;
|
|
@@ -853,11 +889,14 @@ function handleImageSelect(selected: ImageLike | File | string) {
|
|
|
853
889
|
})();
|
|
854
890
|
}
|
|
855
891
|
|
|
856
|
-
function getAssetImageSource(asset:
|
|
892
|
+
function getAssetImageSource(asset: ContentEditorAsset): string {
|
|
857
893
|
return String(asset?.sourceUri || asset?.url || asset?.src || '');
|
|
858
894
|
}
|
|
859
895
|
|
|
860
|
-
function handleAttachedImageDragStart(
|
|
896
|
+
function handleAttachedImageDragStart(
|
|
897
|
+
event: DragEvent,
|
|
898
|
+
asset: ContentEditorAsset,
|
|
899
|
+
) {
|
|
861
900
|
if (!event.dataTransfer) {
|
|
862
901
|
return;
|
|
863
902
|
}
|
|
@@ -902,8 +941,8 @@ async function resolveBodyDropImage(selected: ImageLike | File | string) {
|
|
|
902
941
|
}
|
|
903
942
|
}
|
|
904
943
|
|
|
905
|
-
function addSelectedAsset(asset:
|
|
906
|
-
const assetId = asset.id;
|
|
944
|
+
function addSelectedAsset(asset: ContentEditorAsset) {
|
|
945
|
+
const assetId = asset.id ?? '';
|
|
907
946
|
if (!formData.assetIds.includes(assetId)) {
|
|
908
947
|
formData.assetIds = [...formData.assetIds, assetId];
|
|
909
948
|
formData.assets = [...formData.assets, asset];
|
|
@@ -919,7 +958,7 @@ function setThumbnail(id: string) {
|
|
|
919
958
|
|
|
920
959
|
function removeAsset(id: string) {
|
|
921
960
|
formData.assetIds = formData.assetIds.filter((aId: string) => aId !== id);
|
|
922
|
-
formData.assets = formData.assets.filter((a
|
|
961
|
+
formData.assets = formData.assets.filter((a) => a.id !== id);
|
|
923
962
|
if (formData.thumbnailAssetId === id) {
|
|
924
963
|
formData.thumbnailAssetId = null;
|
|
925
964
|
}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import type { ContentEditorAssistantContextChange, ContentEditorAssistantFieldUpdateAllowList } from '../../content-editor-assistant';
|
|
2
2
|
import type { FactAuditStateData } from '../../mock-smrt-client';
|
|
3
|
+
import type { ContentData } from '../../mock-smrt-client';
|
|
4
|
+
import { type ContentEditorSavePayload, getContentEditorSnapshot } from '../content-editor-form';
|
|
5
|
+
type ContentEditorSnapshot = ReturnType<typeof getContentEditorSnapshot>;
|
|
3
6
|
export interface Props {
|
|
4
7
|
apiBaseUrl?: string;
|
|
5
|
-
content?:
|
|
8
|
+
content?: ContentData | null;
|
|
6
9
|
contentId?: string;
|
|
7
10
|
factAudit?: FactAuditStateData | null;
|
|
8
11
|
saveDisabled?: boolean;
|
|
@@ -13,9 +16,9 @@ export interface Props {
|
|
|
13
16
|
hideChat?: boolean;
|
|
14
17
|
assistantFieldAllowList?: ContentEditorAssistantFieldUpdateAllowList;
|
|
15
18
|
onAssistantContextChange?: ContentEditorAssistantContextChange;
|
|
16
|
-
onChange?: (data:
|
|
19
|
+
onChange?: (data: ContentEditorSnapshot) => void;
|
|
17
20
|
onFactAuditChange?: (state: FactAuditStateData | null) => void;
|
|
18
|
-
onSave: (data:
|
|
21
|
+
onSave: (data: ContentEditorSavePayload) => void;
|
|
19
22
|
onCancel: () => void;
|
|
20
23
|
}
|
|
21
24
|
declare const ContentEditor: import("svelte").Component<Props, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ContentEditor.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/ContentEditor.svelte.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAEV,mCAAmC,EACnC,0CAA0C,EAE3C,MAAM,gCAAgC,CAAC;AAKxC,OAAO,KAAK,EAEV,kBAAkB,EAEnB,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"ContentEditor.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/ContentEditor.svelte.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAEV,mCAAmC,EACnC,0CAA0C,EAE3C,MAAM,gCAAgC,CAAC;AAKxC,OAAO,KAAK,EAEV,kBAAkB,EAEnB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAKL,KAAK,wBAAwB,EAG7B,wBAAwB,EAEzB,MAAM,wBAAwB,CAAC;AAShC,KAAK,qBAAqB,GAAG,UAAU,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAEzE,MAAM,WAAW,KAAK;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,kBAAkB,GAAG,IAAI,CAAC;IACtC,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,uBAAuB,CAAC,EAAE,0CAA0C,CAAC;IACrE,wBAAwB,CAAC,EAAE,mCAAmC,CAAC;IAC/D,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,qBAAqB,KAAK,IAAI,CAAC;IACjD,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,kBAAkB,GAAG,IAAI,KAAK,IAAI,CAAC;IAC/D,MAAM,EAAE,CAAC,IAAI,EAAE,wBAAwB,KAAK,IAAI,CAAC;IACjD,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB;AAoxCD,QAAA,MAAM,aAAa;;MAAwC,CAAC;AAC5D,KAAK,aAAa,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC;AACtD,eAAe,aAAa,CAAC"}
|
|
@@ -56,8 +56,10 @@ async function loadDefinitions() {
|
|
|
56
56
|
const response = await governanceClient.contents.getGovernanceDefinitions();
|
|
57
57
|
definitions = response.data;
|
|
58
58
|
onChange?.(response.data);
|
|
59
|
-
} catch (err
|
|
60
|
-
error =
|
|
59
|
+
} catch (err) {
|
|
60
|
+
error =
|
|
61
|
+
(err instanceof Error ? err.message : '') ||
|
|
62
|
+
'Failed to load governance definitions';
|
|
61
63
|
} finally {
|
|
62
64
|
loading = false;
|
|
63
65
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ContentGovernanceManager.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/ContentGovernanceManager.svelte.ts"],"names":[],"mappings":"AAMA,OAAO,EAEL,KAAK,gCAAgC,EAItC,MAAM,wBAAwB,CAAC;AAEhC,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,8BAA8B,CAAC;AASnF,MAAM,WAAW,KAAK;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,8BAA8B,CAAC;IACxC,QAAQ,CAAC,EAAE,CAAC,WAAW,EAAE,gCAAgC,GAAG,IAAI,KAAK,IAAI,CAAC;CAC3E;
|
|
1
|
+
{"version":3,"file":"ContentGovernanceManager.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/ContentGovernanceManager.svelte.ts"],"names":[],"mappings":"AAMA,OAAO,EAEL,KAAK,gCAAgC,EAItC,MAAM,wBAAwB,CAAC;AAEhC,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,8BAA8B,CAAC;AASnF,MAAM,WAAW,KAAK;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,8BAA8B,CAAC;IACxC,QAAQ,CAAC,EAAE,CAAC,WAAW,EAAE,gCAAgC,GAAG,IAAI,KAAK,IAAI,CAAC;CAC3E;AAoRD,QAAA,MAAM,wBAAwB,2CAAwC,CAAC;AACvE,KAAK,wBAAwB,GAAG,UAAU,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAC5E,eAAe,wBAAwB,CAAC"}
|
|
@@ -568,10 +568,10 @@ async function searchFacts(query = factQuery, page = 1) {
|
|
|
568
568
|
catalogPage = nextPage;
|
|
569
569
|
catalogHasNextPage = rows.length > FACT_CATALOG_PAGE_SIZE;
|
|
570
570
|
catalogBrowseQuery = query;
|
|
571
|
-
} catch (err
|
|
571
|
+
} catch (err) {
|
|
572
572
|
catalogFacts = [];
|
|
573
573
|
catalogHasNextPage = false;
|
|
574
|
-
catalogError = err.message || 'Failed to browse facts';
|
|
574
|
+
catalogError = (err instanceof Error ? err.message : '') || 'Failed to browse facts';
|
|
575
575
|
} finally {
|
|
576
576
|
catalogLoading = false;
|
|
577
577
|
}
|
|
@@ -621,8 +621,8 @@ async function syncFactsIfSaved(nextFacts: FactData[]) {
|
|
|
621
621
|
updateSelectedFacts(response.data.facts || nextFacts);
|
|
622
622
|
await Promise.all([refreshGovernanceState(), refreshTransparency()]);
|
|
623
623
|
workflowNotice = 'Saved fact associations.';
|
|
624
|
-
} catch (err
|
|
625
|
-
workflowError = err.message || 'Failed to sync facts';
|
|
624
|
+
} catch (err) {
|
|
625
|
+
workflowError = (err instanceof Error ? err.message : '') || 'Failed to sync facts';
|
|
626
626
|
} finally {
|
|
627
627
|
syncingFacts = false;
|
|
628
628
|
}
|
|
@@ -644,8 +644,8 @@ async function repairFactAudit() {
|
|
|
644
644
|
onFactAuditChange?.(response.data);
|
|
645
645
|
const factsResponse = await client.contents.getFacts(savedContentId);
|
|
646
646
|
updateSelectedFacts(factsResponse.data.facts || []);
|
|
647
|
-
} catch (err
|
|
648
|
-
workflowError = err.message || 'Failed to repair fact audit';
|
|
647
|
+
} catch (err) {
|
|
648
|
+
workflowError = (err instanceof Error ? err.message : '') || 'Failed to repair fact audit';
|
|
649
649
|
} finally {
|
|
650
650
|
factAuditBusy = false;
|
|
651
651
|
}
|
|
@@ -668,8 +668,8 @@ async function recheckFactClaims(claimIds: string[]) {
|
|
|
668
668
|
workflowNotice = `Rechecked ${claimIds.length} claim${claimIds.length === 1 ? '' : 's'} against current evidence.`;
|
|
669
669
|
selectedClaimIds = selectedClaimIds.filter((id) => !claimIds.includes(id));
|
|
670
670
|
onFactAuditChange?.(response.data);
|
|
671
|
-
} catch (err
|
|
672
|
-
workflowError = err.message || 'Failed to recheck claim support';
|
|
671
|
+
} catch (err) {
|
|
672
|
+
workflowError = (err instanceof Error ? err.message : '') || 'Failed to recheck claim support';
|
|
673
673
|
} finally {
|
|
674
674
|
factAuditBusy = false;
|
|
675
675
|
}
|
|
@@ -731,12 +731,12 @@ async function loadDraftGovernance() {
|
|
|
731
731
|
activeCustomPolicyKey,
|
|
732
732
|
customReviewPolicyKey,
|
|
733
733
|
);
|
|
734
|
-
} catch (err
|
|
734
|
+
} catch (err) {
|
|
735
735
|
governanceState = null;
|
|
736
736
|
governanceDefinitions = null;
|
|
737
737
|
reviewProfiles = [];
|
|
738
738
|
onGovernanceStateChange?.(null);
|
|
739
|
-
workflowError = err.message || 'Failed to resolve content governance';
|
|
739
|
+
workflowError = (err instanceof Error ? err.message : '') || 'Failed to resolve content governance';
|
|
740
740
|
} finally {
|
|
741
741
|
workflowLoading = false;
|
|
742
742
|
}
|
|
@@ -795,8 +795,8 @@ async function loadSavedWorkflow() {
|
|
|
795
795
|
activeCustomPolicyKey,
|
|
796
796
|
customReviewPolicyKey,
|
|
797
797
|
);
|
|
798
|
-
} catch (err
|
|
799
|
-
workflowError = err.message || 'Failed to load governance workflow state';
|
|
798
|
+
} catch (err) {
|
|
799
|
+
workflowError = (err instanceof Error ? err.message : '') || 'Failed to load governance workflow state';
|
|
800
800
|
} finally {
|
|
801
801
|
workflowLoading = false;
|
|
802
802
|
}
|
|
@@ -832,7 +832,7 @@ async function runReview(action: ReviewAction) {
|
|
|
832
832
|
workflowNotice = null;
|
|
833
833
|
|
|
834
834
|
try {
|
|
835
|
-
const payload: Record<string,
|
|
835
|
+
const payload: Record<string, unknown> = {
|
|
836
836
|
kind: action.kind,
|
|
837
837
|
factIds: selectedFactIds,
|
|
838
838
|
};
|
|
@@ -851,8 +851,8 @@ async function runReview(action: ReviewAction) {
|
|
|
851
851
|
await Promise.all([refreshGovernanceState(), refreshTransparency()]);
|
|
852
852
|
workflowNotice = `${action.label} completed.`;
|
|
853
853
|
await refreshVersions();
|
|
854
|
-
} catch (err
|
|
855
|
-
workflowError = err.message || 'Failed to run content review';
|
|
854
|
+
} catch (err) {
|
|
855
|
+
workflowError = (err instanceof Error ? err.message : '') || 'Failed to run content review';
|
|
856
856
|
} finally {
|
|
857
857
|
reviewBusy = null;
|
|
858
858
|
}
|
|
@@ -883,8 +883,8 @@ async function issueCorrection() {
|
|
|
883
883
|
|
|
884
884
|
workflowNotice = 'Correction issued.';
|
|
885
885
|
await loadSavedWorkflow();
|
|
886
|
-
} catch (err
|
|
887
|
-
workflowError = err.message || 'Failed to issue correction';
|
|
886
|
+
} catch (err) {
|
|
887
|
+
workflowError = (err instanceof Error ? err.message : '') || 'Failed to issue correction';
|
|
888
888
|
} finally {
|
|
889
889
|
correctionBusy = false;
|
|
890
890
|
}
|
|
@@ -906,8 +906,8 @@ async function createSnapshot() {
|
|
|
906
906
|
});
|
|
907
907
|
workflowNotice = 'Snapshot created.';
|
|
908
908
|
await Promise.all([refreshVersions(), refreshTransparency()]);
|
|
909
|
-
} catch (err
|
|
910
|
-
workflowError = err.message || 'Failed to create version snapshot';
|
|
909
|
+
} catch (err) {
|
|
910
|
+
workflowError = (err instanceof Error ? err.message : '') || 'Failed to create version snapshot';
|
|
911
911
|
} finally {
|
|
912
912
|
versionBusy = false;
|
|
913
913
|
}
|
|
@@ -948,8 +948,8 @@ async function restoreVersion(versionNumber: number) {
|
|
|
948
948
|
);
|
|
949
949
|
workflowNotice = `Restored version ${versionNumber}.`;
|
|
950
950
|
await loadSavedWorkflow();
|
|
951
|
-
} catch (err
|
|
952
|
-
workflowError = err.message || 'Failed to restore version';
|
|
951
|
+
} catch (err) {
|
|
952
|
+
workflowError = (err instanceof Error ? err.message : '') || 'Failed to restore version';
|
|
953
953
|
} finally {
|
|
954
954
|
versionBusy = false;
|
|
955
955
|
}
|
|
@@ -5,11 +5,24 @@ import { useI18n } from '@happyvertical/smrt-ui/i18n';
|
|
|
5
5
|
import { Button } from '@happyvertical/smrt-ui/ui';
|
|
6
6
|
import type { Snippet } from 'svelte';
|
|
7
7
|
import { untrack } from 'svelte';
|
|
8
|
+
import type { ContentData } from '../../mock-smrt-client.js';
|
|
8
9
|
import { M } from '../i18n.contribution.js';
|
|
9
10
|
import ImageThumbnail from './ImageThumbnail.svelte';
|
|
10
11
|
|
|
11
12
|
const { t } = useI18n();
|
|
12
13
|
|
|
14
|
+
interface Props {
|
|
15
|
+
apiBaseUrl?: string;
|
|
16
|
+
contents: ContentData[];
|
|
17
|
+
type?: string;
|
|
18
|
+
defaultViewMode?: 'grid' | 'detailed' | 'compact';
|
|
19
|
+
onEdit: (content: ContentData) => void;
|
|
20
|
+
onDelete: (content: ContentData) => void;
|
|
21
|
+
onAdd: () => void;
|
|
22
|
+
controls?: Snippet;
|
|
23
|
+
getViewHref?: (content: ContentData) => string | null;
|
|
24
|
+
}
|
|
25
|
+
|
|
13
26
|
let {
|
|
14
27
|
apiBaseUrl = '/api/v1',
|
|
15
28
|
contents,
|
|
@@ -20,17 +33,7 @@ let {
|
|
|
20
33
|
onAdd,
|
|
21
34
|
controls,
|
|
22
35
|
getViewHref = undefined,
|
|
23
|
-
} = $props
|
|
24
|
-
apiBaseUrl?: string;
|
|
25
|
-
contents: any[];
|
|
26
|
-
type?: string;
|
|
27
|
-
defaultViewMode?: 'grid' | 'detailed' | 'compact';
|
|
28
|
-
onEdit: (content: any) => void;
|
|
29
|
-
onDelete: (content: any) => void;
|
|
30
|
-
onAdd: () => void;
|
|
31
|
-
controls?: Snippet;
|
|
32
|
-
getViewHref?: (content: any) => string | null;
|
|
33
|
-
}>();
|
|
36
|
+
}: Props = $props();
|
|
34
37
|
|
|
35
38
|
let searchTerm = $state('');
|
|
36
39
|
let selectedType = $state('All Types');
|
|
@@ -47,15 +50,15 @@ function getTextValue(value: unknown): string {
|
|
|
47
50
|
return typeof value === 'string' ? value : '';
|
|
48
51
|
}
|
|
49
52
|
|
|
50
|
-
function getDisplayTitle(content:
|
|
53
|
+
function getDisplayTitle(content: ContentData): string {
|
|
51
54
|
return getTextValue(content.title) || 'Untitled content';
|
|
52
55
|
}
|
|
53
56
|
|
|
54
|
-
function getDisplayDescription(content:
|
|
57
|
+
function getDisplayDescription(content: ContentData): string {
|
|
55
58
|
return getTextValue(content.description);
|
|
56
59
|
}
|
|
57
60
|
|
|
58
|
-
function getDisplayAuthor(content:
|
|
61
|
+
function getDisplayAuthor(content: ContentData): string {
|
|
59
62
|
return getTextValue(content.author);
|
|
60
63
|
}
|
|
61
64
|
|
|
@@ -64,7 +67,7 @@ function getNormalizedType(value: unknown): string {
|
|
|
64
67
|
}
|
|
65
68
|
|
|
66
69
|
const filteredContents = $derived(
|
|
67
|
-
contents.filter((content:
|
|
70
|
+
contents.filter((content: ContentData) => {
|
|
68
71
|
const title = getDisplayTitle(content);
|
|
69
72
|
const description = getDisplayDescription(content);
|
|
70
73
|
const author = getDisplayAuthor(content);
|
|
@@ -130,9 +133,9 @@ function getStateBadge(value: unknown) {
|
|
|
130
133
|
}
|
|
131
134
|
}
|
|
132
135
|
|
|
133
|
-
let pendingDelete = $state<
|
|
136
|
+
let pendingDelete = $state<ContentData | null>(null);
|
|
134
137
|
|
|
135
|
-
function handleDeleteContent(content:
|
|
138
|
+
function handleDeleteContent(content: ContentData) {
|
|
136
139
|
pendingDelete = content;
|
|
137
140
|
}
|
|
138
141
|
|