@semiont/react-ui 0.4.2 → 0.4.4
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/{PdfAnnotationCanvas.client-PVTVPDBQ.mjs → PdfAnnotationCanvas.client-LF6DDTCV.mjs} +3 -3
- package/dist/{ar-5REA6P4J.mjs → ar-RJLR7NDD.mjs} +13 -11
- package/dist/ar-RJLR7NDD.mjs.map +1 -0
- package/dist/{bn-YHRYHHPD.mjs → bn-4NU2UAZ7.mjs} +13 -11
- package/dist/bn-4NU2UAZ7.mjs.map +1 -0
- package/dist/{chunk-VVCCMJS7.mjs → chunk-2VWLGQIO.mjs} +13 -11
- package/dist/chunk-2VWLGQIO.mjs.map +1 -0
- package/dist/chunk-5JZFKRLW.mjs +62 -0
- package/dist/chunk-5JZFKRLW.mjs.map +1 -0
- package/dist/{chunk-PFQYNPQJ.mjs → chunk-EKQMINCV.mjs} +61 -92
- package/dist/chunk-EKQMINCV.mjs.map +1 -0
- package/dist/{chunk-ZPV43WN2.mjs → chunk-XMCUHQ2Y.mjs} +72 -3
- package/dist/chunk-XMCUHQ2Y.mjs.map +1 -0
- package/dist/{cs-JTJXTX2T.mjs → cs-6UJZFF55.mjs} +13 -11
- package/dist/cs-6UJZFF55.mjs.map +1 -0
- package/dist/{da-MK37SJB6.mjs → da-CFFBBOH3.mjs} +13 -11
- package/dist/da-CFFBBOH3.mjs.map +1 -0
- package/dist/{de-LGBCWERA.mjs → de-2KAG6KMX.mjs} +13 -11
- package/dist/de-2KAG6KMX.mjs.map +1 -0
- package/dist/{el-FKJMFCWY.mjs → el-KVPQ7VNF.mjs} +13 -11
- package/dist/el-KVPQ7VNF.mjs.map +1 -0
- package/dist/{en-AOSMPC2M.mjs → en-ZW4UKTVX.mjs} +2 -2
- package/dist/{es-LVDPIXWU.mjs → es-ZU2ECPVG.mjs} +13 -11
- package/dist/es-ZU2ECPVG.mjs.map +1 -0
- package/dist/{fa-3VA2PIUD.mjs → fa-CBIVKDIQ.mjs} +13 -11
- package/dist/fa-CBIVKDIQ.mjs.map +1 -0
- package/dist/{fi-3WM75ZLR.mjs → fi-5HUVT7IK.mjs} +13 -11
- package/dist/fi-5HUVT7IK.mjs.map +1 -0
- package/dist/{fr-NK4A72WA.mjs → fr-O5WU2US2.mjs} +13 -11
- package/dist/fr-O5WU2US2.mjs.map +1 -0
- package/dist/{he-IACZDZMB.mjs → he-WP4C2SNJ.mjs} +13 -11
- package/dist/he-WP4C2SNJ.mjs.map +1 -0
- package/dist/{hi-JZ7MGMMS.mjs → hi-HLQXNRWI.mjs} +13 -11
- package/dist/hi-HLQXNRWI.mjs.map +1 -0
- package/dist/{id-P3KDQGNK.mjs → id-DTJT2ZA6.mjs} +13 -11
- package/dist/id-DTJT2ZA6.mjs.map +1 -0
- package/dist/index.css +213 -0
- package/dist/index.css.map +1 -1
- package/dist/index.d.mts +48 -50
- package/dist/index.mjs +1492 -1474
- package/dist/index.mjs.map +1 -1
- package/dist/{it-LQS33SUY.mjs → it-2DK57IMT.mjs} +13 -11
- package/dist/it-2DK57IMT.mjs.map +1 -0
- package/dist/{ja-G4FKZPWD.mjs → ja-52ZNY72Y.mjs} +13 -11
- package/dist/ja-52ZNY72Y.mjs.map +1 -0
- package/dist/{ko-2XWKQ7BA.mjs → ko-4Z2IMYZO.mjs} +13 -11
- package/dist/ko-4Z2IMYZO.mjs.map +1 -0
- package/dist/{ms-2SNONIUD.mjs → ms-HKU73KEX.mjs} +13 -11
- package/dist/ms-HKU73KEX.mjs.map +1 -0
- package/dist/{nl-BMZUAJ7J.mjs → nl-HPHQMXPT.mjs} +13 -11
- package/dist/nl-HPHQMXPT.mjs.map +1 -0
- package/dist/{no-6J3WIZ6L.mjs → no-Q7G4PVFT.mjs} +13 -11
- package/dist/no-Q7G4PVFT.mjs.map +1 -0
- package/dist/{pl-QQ7DAUVK.mjs → pl-D43C2CE3.mjs} +13 -11
- package/dist/pl-D43C2CE3.mjs.map +1 -0
- package/dist/{pt-MU3GN7MW.mjs → pt-V3GFSY7B.mjs} +13 -11
- package/dist/pt-V3GFSY7B.mjs.map +1 -0
- package/dist/{ro-6GBE72QK.mjs → ro-3UIRV3OA.mjs} +13 -11
- package/dist/ro-3UIRV3OA.mjs.map +1 -0
- package/dist/{sv-NQIL7PEM.mjs → sv-BMW26A7M.mjs} +13 -11
- package/dist/sv-BMW26A7M.mjs.map +1 -0
- package/dist/test-utils.mjs +4 -4
- package/dist/{th-6OCNZQBE.mjs → th-CMND2QET.mjs} +13 -11
- package/dist/th-CMND2QET.mjs.map +1 -0
- package/dist/{tr-XWJ5P3SC.mjs → tr-P3AD7MYA.mjs} +13 -11
- package/dist/tr-P3AD7MYA.mjs.map +1 -0
- package/dist/{uk-AKSN6DGW.mjs → uk-QPONRQ5O.mjs} +13 -11
- package/dist/uk-QPONRQ5O.mjs.map +1 -0
- package/dist/{vi-23GHQ45M.mjs → vi-G2OMVMCI.mjs} +13 -11
- package/dist/vi-G2OMVMCI.mjs.map +1 -0
- package/dist/{zh-ITT4QBSN.mjs → zh-HTDN4LKE.mjs} +13 -11
- package/dist/zh-HTDN4LKE.mjs.map +1 -0
- package/package.json +3 -5
- package/src/components/CodeMirrorRenderer.tsx +9 -9
- package/src/components/ResourceTagsInline.tsx +1 -1
- package/src/components/__tests__/ResourceTagsInline.test.tsx +3 -3
- package/src/components/modals/ContextSummary.tsx +56 -165
- package/src/components/modals/GatherContextStep.tsx +124 -42
- package/src/components/modals/ReferenceWizardModal.tsx +8 -25
- package/src/components/modals/SearchModal.css +241 -0
- package/src/components/resource/AnnotateView.tsx +3 -3
- package/src/components/resource/BrowseView.tsx +2 -2
- package/src/components/resource/ResourceViewer.tsx +4 -4
- package/src/components/resource/__tests__/annotation-interactions.test.tsx +1 -1
- package/src/components/resource/panels/AssessmentPanel.tsx +3 -0
- package/src/components/resource/panels/AssistSection.tsx +4 -1
- package/src/components/resource/panels/CommentsPanel.tsx +3 -0
- package/src/components/resource/panels/ResourceInfoPanel.tsx +82 -0
- package/src/components/resource/panels/UnifiedAnnotationsPanel.tsx +4 -0
- package/src/components/resource/panels/__tests__/ResourceInfoPanel.test.tsx +94 -0
- package/src/features/resource-viewer/__tests__/AnnotationCreationPending.test.tsx +6 -6
- package/src/features/resource-viewer/__tests__/AnnotationProgressDismissal.test.tsx +4 -4
- package/src/features/resource-viewer/__tests__/BindFlowIntegration.test.tsx +23 -17
- package/src/features/resource-viewer/__tests__/DetectionFlowBug.test.tsx +4 -4
- package/src/features/resource-viewer/__tests__/DetectionFlowIntegration.test.tsx +14 -14
- package/src/features/resource-viewer/__tests__/ResourceViewerPage.test.tsx +2 -2
- package/src/features/resource-viewer/__tests__/YieldFlowIntegration.test.tsx +2 -2
- package/src/features/resource-viewer/__tests__/annotation-progress-flow.test.tsx +4 -4
- package/src/features/resource-viewer/components/ResourceViewerPage.tsx +12 -10
- package/translations/ar.json +12 -10
- package/translations/bn.json +12 -10
- package/translations/cs.json +12 -10
- package/translations/da.json +12 -10
- package/translations/de.json +12 -10
- package/translations/el.json +12 -10
- package/translations/en.json +13 -11
- package/translations/es.json +12 -10
- package/translations/fa.json +12 -10
- package/translations/fi.json +12 -10
- package/translations/fr.json +12 -10
- package/translations/he.json +12 -10
- package/translations/hi.json +12 -10
- package/translations/id.json +12 -10
- package/translations/it.json +12 -10
- package/translations/ja.json +12 -10
- package/translations/ko.json +12 -10
- package/translations/ms.json +12 -10
- package/translations/nl.json +12 -10
- package/translations/no.json +12 -10
- package/translations/pl.json +12 -10
- package/translations/pt.json +12 -10
- package/translations/ro.json +12 -10
- package/translations/sv.json +12 -10
- package/translations/th.json +12 -10
- package/translations/tr.json +12 -10
- package/translations/uk.json +12 -10
- package/translations/vi.json +12 -10
- package/translations/zh.json +12 -10
- package/dist/ar-5REA6P4J.mjs.map +0 -1
- package/dist/bn-YHRYHHPD.mjs.map +0 -1
- package/dist/chunk-2HGWOLVN.mjs +0 -31
- package/dist/chunk-2HGWOLVN.mjs.map +0 -1
- package/dist/chunk-PFQYNPQJ.mjs.map +0 -1
- package/dist/chunk-VVCCMJS7.mjs.map +0 -1
- package/dist/chunk-ZPV43WN2.mjs.map +0 -1
- package/dist/cs-JTJXTX2T.mjs.map +0 -1
- package/dist/da-MK37SJB6.mjs.map +0 -1
- package/dist/de-LGBCWERA.mjs.map +0 -1
- package/dist/el-FKJMFCWY.mjs.map +0 -1
- package/dist/es-LVDPIXWU.mjs.map +0 -1
- package/dist/fa-3VA2PIUD.mjs.map +0 -1
- package/dist/fi-3WM75ZLR.mjs.map +0 -1
- package/dist/fr-NK4A72WA.mjs.map +0 -1
- package/dist/he-IACZDZMB.mjs.map +0 -1
- package/dist/hi-JZ7MGMMS.mjs.map +0 -1
- package/dist/id-P3KDQGNK.mjs.map +0 -1
- package/dist/it-LQS33SUY.mjs.map +0 -1
- package/dist/ja-G4FKZPWD.mjs.map +0 -1
- package/dist/ko-2XWKQ7BA.mjs.map +0 -1
- package/dist/ms-2SNONIUD.mjs.map +0 -1
- package/dist/nl-BMZUAJ7J.mjs.map +0 -1
- package/dist/no-6J3WIZ6L.mjs.map +0 -1
- package/dist/pl-QQ7DAUVK.mjs.map +0 -1
- package/dist/pt-MU3GN7MW.mjs.map +0 -1
- package/dist/ro-6GBE72QK.mjs.map +0 -1
- package/dist/sv-NQIL7PEM.mjs.map +0 -1
- package/dist/th-6OCNZQBE.mjs.map +0 -1
- package/dist/tr-XWJ5P3SC.mjs.map +0 -1
- package/dist/uk-AKSN6DGW.mjs.map +0 -1
- package/dist/vi-23GHQ45M.mjs.map +0 -1
- package/dist/zh-ITT4QBSN.mjs.map +0 -1
- /package/dist/{PdfAnnotationCanvas.client-PVTVPDBQ.mjs.map → PdfAnnotationCanvas.client-LF6DDTCV.mjs.map} +0 -0
- /package/dist/{en-AOSMPC2M.mjs.map → en-ZW4UKTVX.mjs.map} +0 -0
|
@@ -47,6 +47,7 @@ interface CommentsPanelProps {
|
|
|
47
47
|
percentage?: number;
|
|
48
48
|
message?: string;
|
|
49
49
|
} | null;
|
|
50
|
+
locale?: string;
|
|
50
51
|
scrollToAnnotationId?: string | null;
|
|
51
52
|
onScrollCompleted?: () => void;
|
|
52
53
|
hoveredAnnotationId?: string | null;
|
|
@@ -65,6 +66,7 @@ export function CommentsPanel({
|
|
|
65
66
|
annotateMode = true,
|
|
66
67
|
isAssisting = false,
|
|
67
68
|
progress,
|
|
69
|
+
locale,
|
|
68
70
|
scrollToAnnotationId,
|
|
69
71
|
onScrollCompleted,
|
|
70
72
|
hoveredAnnotationId,
|
|
@@ -252,6 +254,7 @@ export function CommentsPanel({
|
|
|
252
254
|
<AssistSection
|
|
253
255
|
annotationType="comment"
|
|
254
256
|
isAssisting={isAssisting}
|
|
257
|
+
locale={locale}
|
|
255
258
|
progress={progress}
|
|
256
259
|
/>
|
|
257
260
|
)}
|
|
@@ -3,14 +3,23 @@
|
|
|
3
3
|
import { useTranslations } from '../../../contexts/TranslationContext';
|
|
4
4
|
import { useEventBus } from '../../../contexts/EventBusContext';
|
|
5
5
|
import { formatLocaleDisplay } from '@semiont/api-client';
|
|
6
|
+
import type { components } from '@semiont/core';
|
|
6
7
|
import './ResourceInfoPanel.css';
|
|
7
8
|
|
|
9
|
+
type Agent = components['schemas']['Agent'];
|
|
10
|
+
|
|
8
11
|
interface Props {
|
|
9
12
|
documentEntityTypes: string[];
|
|
10
13
|
documentLocale?: string | undefined;
|
|
11
14
|
primaryMediaType?: string | undefined;
|
|
12
15
|
primaryByteSize?: number | undefined;
|
|
13
16
|
isArchived?: boolean;
|
|
17
|
+
dateCreated?: string | undefined;
|
|
18
|
+
dateModified?: string | undefined;
|
|
19
|
+
creationMethod?: string | undefined;
|
|
20
|
+
wasAttributedTo?: Agent | Agent[] | undefined;
|
|
21
|
+
wasDerivedFrom?: string | string[] | undefined;
|
|
22
|
+
generator?: Agent | Agent[] | undefined;
|
|
14
23
|
}
|
|
15
24
|
|
|
16
25
|
/**
|
|
@@ -26,6 +35,12 @@ export function ResourceInfoPanel({
|
|
|
26
35
|
primaryMediaType,
|
|
27
36
|
primaryByteSize,
|
|
28
37
|
isArchived = false,
|
|
38
|
+
dateCreated,
|
|
39
|
+
dateModified,
|
|
40
|
+
creationMethod,
|
|
41
|
+
wasAttributedTo,
|
|
42
|
+
wasDerivedFrom,
|
|
43
|
+
generator,
|
|
29
44
|
}: Props) {
|
|
30
45
|
const t = useTranslations('ResourceInfoPanel');
|
|
31
46
|
const eventBus = useEventBus();
|
|
@@ -76,6 +91,73 @@ export function ResourceInfoPanel({
|
|
|
76
91
|
</div>
|
|
77
92
|
)}
|
|
78
93
|
|
|
94
|
+
{/* Provenance Section */}
|
|
95
|
+
{(dateCreated || dateModified || creationMethod || wasAttributedTo || wasDerivedFrom || generator) && (
|
|
96
|
+
<div className="semiont-resource-info-panel__section">
|
|
97
|
+
<h3 className="semiont-resource-info-panel__heading">{t('provenance')}</h3>
|
|
98
|
+
<div className="semiont-resource-info-panel__field-group">
|
|
99
|
+
{dateCreated && (
|
|
100
|
+
<div>
|
|
101
|
+
<span className="semiont-resource-info-panel__label">{t('createdAt')}</span>
|
|
102
|
+
<span className="semiont-resource-info-panel__value">
|
|
103
|
+
{new Date(dateCreated).toLocaleString()}
|
|
104
|
+
</span>
|
|
105
|
+
</div>
|
|
106
|
+
)}
|
|
107
|
+
{dateModified && (
|
|
108
|
+
<div>
|
|
109
|
+
<span className="semiont-resource-info-panel__label">{t('modifiedAt')}</span>
|
|
110
|
+
<span className="semiont-resource-info-panel__value">
|
|
111
|
+
{new Date(dateModified).toLocaleString()}
|
|
112
|
+
</span>
|
|
113
|
+
</div>
|
|
114
|
+
)}
|
|
115
|
+
{creationMethod && (
|
|
116
|
+
<div>
|
|
117
|
+
<span className="semiont-resource-info-panel__label">{t('creationMethod')}</span>
|
|
118
|
+
<span className="semiont-resource-info-panel__value">{creationMethod}</span>
|
|
119
|
+
</div>
|
|
120
|
+
)}
|
|
121
|
+
{wasAttributedTo && (
|
|
122
|
+
<div>
|
|
123
|
+
<span className="semiont-resource-info-panel__label">{t('attributedTo')}</span>
|
|
124
|
+
<span className="semiont-resource-info-panel__value">
|
|
125
|
+
{(Array.isArray(wasAttributedTo) ? wasAttributedTo : [wasAttributedTo])
|
|
126
|
+
.map(a => a.name)
|
|
127
|
+
.join(', ')}
|
|
128
|
+
</span>
|
|
129
|
+
</div>
|
|
130
|
+
)}
|
|
131
|
+
{wasDerivedFrom && (
|
|
132
|
+
<div>
|
|
133
|
+
<span className="semiont-resource-info-panel__label">{t('derivedFrom')}</span>
|
|
134
|
+
<span className="semiont-resource-info-panel__value">
|
|
135
|
+
{(Array.isArray(wasDerivedFrom) ? wasDerivedFrom : [wasDerivedFrom]).map((id, i) => (
|
|
136
|
+
<button
|
|
137
|
+
key={id}
|
|
138
|
+
className="semiont-resource-info-panel__link"
|
|
139
|
+
onClick={() => eventBus.get('browse:reference-navigate').next({ resourceId: id })}
|
|
140
|
+
>
|
|
141
|
+
{i > 0 && ', '}{id}
|
|
142
|
+
</button>
|
|
143
|
+
))}
|
|
144
|
+
</span>
|
|
145
|
+
</div>
|
|
146
|
+
)}
|
|
147
|
+
{generator && (
|
|
148
|
+
<div>
|
|
149
|
+
<span className="semiont-resource-info-panel__label">{t('generatedBy')}</span>
|
|
150
|
+
<span className="semiont-resource-info-panel__value">
|
|
151
|
+
{(Array.isArray(generator) ? generator : [generator])
|
|
152
|
+
.map(a => a.name)
|
|
153
|
+
.join(', ')}
|
|
154
|
+
</span>
|
|
155
|
+
</div>
|
|
156
|
+
)}
|
|
157
|
+
</div>
|
|
158
|
+
</div>
|
|
159
|
+
)}
|
|
160
|
+
|
|
79
161
|
{/* Entity Type Tags Section */}
|
|
80
162
|
{documentEntityTypes.length > 0 && (
|
|
81
163
|
<div className="semiont-resource-info-panel__section">
|
|
@@ -70,6 +70,9 @@ interface UnifiedAnnotationsPanelProps {
|
|
|
70
70
|
// Hover coordination (for bidirectional hover highlighting)
|
|
71
71
|
hoveredAnnotationId?: string | null;
|
|
72
72
|
|
|
73
|
+
// Locale for AI-generated text language
|
|
74
|
+
locale?: string;
|
|
75
|
+
|
|
73
76
|
// Routing
|
|
74
77
|
Link: React.ComponentType<LinkComponentProps>;
|
|
75
78
|
routes: RouteBuilder;
|
|
@@ -238,6 +241,7 @@ export function UnifiedAnnotationsPanel(props: UnifiedAnnotationsPanelProps) {
|
|
|
238
241
|
isAssisting,
|
|
239
242
|
progress,
|
|
240
243
|
annotateMode: props.annotateMode,
|
|
244
|
+
locale: props.locale,
|
|
241
245
|
scrollToAnnotationId: props.scrollToAnnotationId,
|
|
242
246
|
onScrollCompleted: props.onScrollCompleted,
|
|
243
247
|
hoveredAnnotationId: props.hoveredAnnotationId
|
|
@@ -21,6 +21,13 @@ vi.mock('../../../../contexts/TranslationContext', () => ({
|
|
|
21
21
|
archiveDescription: 'Move this resource to archived status',
|
|
22
22
|
unarchive: 'Unarchive',
|
|
23
23
|
unarchiveDescription: 'Restore this resource to active status',
|
|
24
|
+
provenance: 'Provenance',
|
|
25
|
+
createdAt: 'Created',
|
|
26
|
+
modifiedAt: 'Modified',
|
|
27
|
+
creationMethod: 'How created',
|
|
28
|
+
attributedTo: 'Attributed to',
|
|
29
|
+
derivedFrom: 'Derived from',
|
|
30
|
+
generatedBy: 'Generated by',
|
|
24
31
|
};
|
|
25
32
|
return translations[key] || key;
|
|
26
33
|
}),
|
|
@@ -266,6 +273,93 @@ describe('ResourceInfoPanel Component', () => {
|
|
|
266
273
|
});
|
|
267
274
|
});
|
|
268
275
|
|
|
276
|
+
describe('Provenance Section', () => {
|
|
277
|
+
it('should not render provenance section when no provenance data', () => {
|
|
278
|
+
renderWithEventBus(<ResourceInfoPanel {...defaultProps} />);
|
|
279
|
+
expect(screen.queryByText('Provenance')).not.toBeInTheDocument();
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
it('should render dateCreated when provided', () => {
|
|
283
|
+
renderWithEventBus(
|
|
284
|
+
<ResourceInfoPanel {...defaultProps} dateCreated="2024-01-15T10:30:00Z" />
|
|
285
|
+
);
|
|
286
|
+
expect(screen.getByText('Provenance')).toBeInTheDocument();
|
|
287
|
+
expect(screen.getByText('Created')).toBeInTheDocument();
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
it('should render dateModified when provided', () => {
|
|
291
|
+
renderWithEventBus(
|
|
292
|
+
<ResourceInfoPanel {...defaultProps} dateModified="2024-06-01T12:00:00Z" />
|
|
293
|
+
);
|
|
294
|
+
expect(screen.getByText('Provenance')).toBeInTheDocument();
|
|
295
|
+
expect(screen.getByText('Modified')).toBeInTheDocument();
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
it('should render creationMethod when provided', () => {
|
|
299
|
+
renderWithEventBus(
|
|
300
|
+
<ResourceInfoPanel {...defaultProps} creationMethod="generated" />
|
|
301
|
+
);
|
|
302
|
+
expect(screen.getByText('How created')).toBeInTheDocument();
|
|
303
|
+
expect(screen.getByText('generated')).toBeInTheDocument();
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
it('should render a single agent attribution', () => {
|
|
307
|
+
renderWithEventBus(
|
|
308
|
+
<ResourceInfoPanel
|
|
309
|
+
{...defaultProps}
|
|
310
|
+
wasAttributedTo={{ name: 'Alice', '@id': 'https://example.org/alice' }}
|
|
311
|
+
/>
|
|
312
|
+
);
|
|
313
|
+
expect(screen.getByText('Attributed to')).toBeInTheDocument();
|
|
314
|
+
expect(screen.getByText('Alice')).toBeInTheDocument();
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
it('should render multiple agent attributions', () => {
|
|
318
|
+
renderWithEventBus(
|
|
319
|
+
<ResourceInfoPanel
|
|
320
|
+
{...defaultProps}
|
|
321
|
+
wasAttributedTo={[
|
|
322
|
+
{ name: 'Alice' },
|
|
323
|
+
{ name: 'Bob' },
|
|
324
|
+
]}
|
|
325
|
+
/>
|
|
326
|
+
);
|
|
327
|
+
expect(screen.getByText('Alice, Bob')).toBeInTheDocument();
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
it('should render wasDerivedFrom when provided', () => {
|
|
331
|
+
renderWithEventBus(
|
|
332
|
+
<ResourceInfoPanel
|
|
333
|
+
{...defaultProps}
|
|
334
|
+
wasDerivedFrom="urn:semiont:resource:abc123"
|
|
335
|
+
/>
|
|
336
|
+
);
|
|
337
|
+
expect(screen.getByText('Derived from')).toBeInTheDocument();
|
|
338
|
+
expect(screen.getByText('urn:semiont:resource:abc123')).toBeInTheDocument();
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
it('should render generator when provided', () => {
|
|
342
|
+
renderWithEventBus(
|
|
343
|
+
<ResourceInfoPanel
|
|
344
|
+
{...defaultProps}
|
|
345
|
+
generator={{ name: 'Semiont AI' }}
|
|
346
|
+
/>
|
|
347
|
+
);
|
|
348
|
+
expect(screen.getByText('Generated by')).toBeInTheDocument();
|
|
349
|
+
expect(screen.getByText('Semiont AI')).toBeInTheDocument();
|
|
350
|
+
});
|
|
351
|
+
|
|
352
|
+
it('should render multiple generators', () => {
|
|
353
|
+
renderWithEventBus(
|
|
354
|
+
<ResourceInfoPanel
|
|
355
|
+
{...defaultProps}
|
|
356
|
+
generator={[{ name: 'Model A' }, { name: 'Model B' }]}
|
|
357
|
+
/>
|
|
358
|
+
);
|
|
359
|
+
expect(screen.getByText('Model A, Model B')).toBeInTheDocument();
|
|
360
|
+
});
|
|
361
|
+
});
|
|
362
|
+
|
|
269
363
|
describe('Archive Actions', () => {
|
|
270
364
|
it('should render archive button when not archived', () => {
|
|
271
365
|
renderWithEventBus(
|
|
@@ -103,13 +103,13 @@ function renderDetectionFlow(testUri: string) {
|
|
|
103
103
|
// ─── Tests ────────────────────────────────────────────────────────────────────
|
|
104
104
|
|
|
105
105
|
describe('Annotation creation clears pendingAnnotation', () => {
|
|
106
|
-
let
|
|
106
|
+
let markAnnotationSpy: ReturnType<typeof vi.spyOn>;
|
|
107
107
|
|
|
108
108
|
beforeEach(() => {
|
|
109
109
|
vi.clearAllMocks();
|
|
110
110
|
resetEventBusForTesting();
|
|
111
|
-
|
|
112
|
-
.spyOn(SemiontApiClient.prototype, '
|
|
111
|
+
markAnnotationSpy = vi
|
|
112
|
+
.spyOn(SemiontApiClient.prototype, 'markAnnotation')
|
|
113
113
|
.mockResolvedValue({ annotationId: MOCK_ANNOTATION.id } as any);
|
|
114
114
|
});
|
|
115
115
|
|
|
@@ -143,7 +143,7 @@ describe('Annotation creation clears pendingAnnotation', () => {
|
|
|
143
143
|
expect(screen.getByTestId('pending-motivation')).toHaveTextContent('none');
|
|
144
144
|
});
|
|
145
145
|
|
|
146
|
-
expect(
|
|
146
|
+
expect(markAnnotationSpy).toHaveBeenCalledTimes(1);
|
|
147
147
|
});
|
|
148
148
|
|
|
149
149
|
it('clears pendingAnnotation after creating an assessment (assessing)', async () => {
|
|
@@ -272,7 +272,7 @@ describe('Annotation creation clears pendingAnnotation', () => {
|
|
|
272
272
|
});
|
|
273
273
|
|
|
274
274
|
it('does NOT clear pendingAnnotation if API call fails', async () => {
|
|
275
|
-
|
|
275
|
+
markAnnotationSpy.mockRejectedValueOnce(new Error('Network error'));
|
|
276
276
|
|
|
277
277
|
const { emit } = renderDetectionFlow(TEST_URI);
|
|
278
278
|
|
|
@@ -319,6 +319,6 @@ describe('Annotation creation clears pendingAnnotation', () => {
|
|
|
319
319
|
});
|
|
320
320
|
|
|
321
321
|
// API should NOT have been called on cancel
|
|
322
|
-
expect(
|
|
322
|
+
expect(markAnnotationSpy).not.toHaveBeenCalled();
|
|
323
323
|
});
|
|
324
324
|
});
|
|
@@ -50,10 +50,10 @@ describe('Detection Progress Dismissal Bug', () => {
|
|
|
50
50
|
close: vi.fn(),
|
|
51
51
|
};
|
|
52
52
|
|
|
53
|
-
vi.spyOn(SSEClient.prototype, '
|
|
54
|
-
vi.spyOn(SSEClient.prototype, '
|
|
55
|
-
vi.spyOn(SSEClient.prototype, '
|
|
56
|
-
vi.spyOn(SSEClient.prototype, '
|
|
53
|
+
vi.spyOn(SSEClient.prototype, 'markReferences').mockReturnValue(mockStream);
|
|
54
|
+
vi.spyOn(SSEClient.prototype, 'markHighlights').mockReturnValue(mockStream);
|
|
55
|
+
vi.spyOn(SSEClient.prototype, 'markComments').mockReturnValue(mockStream);
|
|
56
|
+
vi.spyOn(SSEClient.prototype, 'markAssessments').mockReturnValue(mockStream);
|
|
57
57
|
});
|
|
58
58
|
|
|
59
59
|
afterEach(() => {
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
* Layer 3: Feature Integration Test - Bind Flow (body update)
|
|
3
3
|
*
|
|
4
4
|
* Tests the write side of useBindFlow:
|
|
5
|
-
* - bind:update-body → calls
|
|
5
|
+
* - bind:update-body → calls bindAnnotation API
|
|
6
6
|
* - bind:update-body → emits bind:body-updated on success
|
|
7
7
|
* - bind:update-body → emits bind:body-update-failed on error
|
|
8
|
-
* - auth token passed to
|
|
8
|
+
* - auth token passed to bindAnnotation
|
|
9
9
|
*
|
|
10
10
|
* The wizard modal (ReferenceWizardModal) handles modal state, context
|
|
11
11
|
* gathering, search configuration, and result display. This test covers
|
|
@@ -21,7 +21,7 @@ import { useBindFlow } from '../../../hooks/useBindFlow';
|
|
|
21
21
|
import { EventBusProvider, useEventBus, resetEventBusForTesting } from '../../../contexts/EventBusContext';
|
|
22
22
|
import { ApiClientProvider } from '../../../contexts/ApiClientContext';
|
|
23
23
|
import { AuthTokenProvider } from '../../../contexts/AuthTokenContext';
|
|
24
|
-
import {
|
|
24
|
+
import { SSEClient } from '@semiont/api-client';
|
|
25
25
|
import { resourceId, accessToken, annotationId } from '@semiont/core';
|
|
26
26
|
|
|
27
27
|
// Mock Toast module to prevent "useToast must be used within a ToastProvider" errors
|
|
@@ -35,7 +35,7 @@ vi.mock('../../../components/Toast', () => ({
|
|
|
35
35
|
}));
|
|
36
36
|
|
|
37
37
|
describe('Bind Flow - Body Update Integration', () => {
|
|
38
|
-
let
|
|
38
|
+
let bindAnnotationSpy: ReturnType<typeof vi.fn>;
|
|
39
39
|
const testId = resourceId('test-resource');
|
|
40
40
|
const testToken = 'test-resolution-token';
|
|
41
41
|
const testBaseUrl = 'http://localhost:4000';
|
|
@@ -44,8 +44,11 @@ describe('Bind Flow - Body Update Integration', () => {
|
|
|
44
44
|
vi.clearAllMocks();
|
|
45
45
|
resetEventBusForTesting();
|
|
46
46
|
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
bindAnnotationSpy = vi.fn().mockImplementation((_rId: any, annId: any, _req: any, opts: any) => {
|
|
48
|
+
queueMicrotask(() => opts.eventBus.get('bind:finished').next({ annotationId: annId }));
|
|
49
|
+
return { close: vi.fn() };
|
|
50
|
+
});
|
|
51
|
+
vi.spyOn(SSEClient.prototype, 'bindAnnotation').mockImplementation(bindAnnotationSpy as any);
|
|
49
52
|
});
|
|
50
53
|
|
|
51
54
|
afterEach(() => {
|
|
@@ -80,17 +83,17 @@ describe('Bind Flow - Body Update Integration', () => {
|
|
|
80
83
|
|
|
81
84
|
// ─── bind:update-body ──────────────────────────────────────────────────
|
|
82
85
|
|
|
83
|
-
it('bind:update-body calls
|
|
86
|
+
it('bind:update-body calls bindAnnotation API', async () => {
|
|
84
87
|
const { getEventBus } = renderBindFlow();
|
|
85
88
|
|
|
86
89
|
act(() => { getEventBus().get('bind:update-body').next({
|
|
87
90
|
annotationId: annotationId('ann-body-1'),
|
|
88
91
|
resourceId: resourceId('linked-resource-id'),
|
|
89
|
-
operations: [{ op: 'add', item: {
|
|
92
|
+
operations: [{ op: 'add', item: { type: 'SpecificResource' as const, source: 'linked-resource-id' } }],
|
|
90
93
|
}); });
|
|
91
94
|
|
|
92
95
|
await waitFor(() => {
|
|
93
|
-
expect(
|
|
96
|
+
expect(bindAnnotationSpy).toHaveBeenCalledTimes(1);
|
|
94
97
|
});
|
|
95
98
|
});
|
|
96
99
|
|
|
@@ -100,14 +103,14 @@ describe('Bind Flow - Body Update Integration', () => {
|
|
|
100
103
|
act(() => { getEventBus().get('bind:update-body').next({
|
|
101
104
|
annotationId: annotationId('ann-auth'),
|
|
102
105
|
resourceId: resourceId('resource-id'),
|
|
103
|
-
operations: [{ op: 'replace', newItem: {
|
|
106
|
+
operations: [{ op: 'replace', newItem: { type: 'SpecificResource' as const, source: 'resource-id' } }],
|
|
104
107
|
}); });
|
|
105
108
|
|
|
106
109
|
await waitFor(() => {
|
|
107
|
-
expect(
|
|
110
|
+
expect(bindAnnotationSpy).toHaveBeenCalled();
|
|
108
111
|
});
|
|
109
112
|
|
|
110
|
-
const callArgs =
|
|
113
|
+
const callArgs = bindAnnotationSpy.mock.calls[0];
|
|
111
114
|
expect(callArgs[3]).toHaveProperty('auth');
|
|
112
115
|
expect(callArgs[3].auth).toBe(accessToken(testToken));
|
|
113
116
|
});
|
|
@@ -121,7 +124,7 @@ describe('Bind Flow - Body Update Integration', () => {
|
|
|
121
124
|
act(() => { getEventBus().get('bind:update-body').next({
|
|
122
125
|
annotationId: annotationId('ann-success'),
|
|
123
126
|
resourceId: resourceId('resource-id'),
|
|
124
|
-
operations: [{ op: 'add', item: {
|
|
127
|
+
operations: [{ op: 'add', item: { type: 'SpecificResource' as const, source: 'resource-id' } }],
|
|
125
128
|
}); });
|
|
126
129
|
|
|
127
130
|
await waitFor(() => {
|
|
@@ -136,7 +139,10 @@ describe('Bind Flow - Body Update Integration', () => {
|
|
|
136
139
|
});
|
|
137
140
|
|
|
138
141
|
it('bind:update-body emits bind:body-update-failed on API error', async () => {
|
|
139
|
-
|
|
142
|
+
bindAnnotationSpy.mockImplementation((_rId: any, _annId: any, _req: any, opts: any) => {
|
|
143
|
+
queueMicrotask(() => opts.eventBus.get('bind:failed').next({ error: new Error('Update failed') }));
|
|
144
|
+
return { close: vi.fn() };
|
|
145
|
+
});
|
|
140
146
|
|
|
141
147
|
const { getEventBus } = renderBindFlow();
|
|
142
148
|
const bodyUpdateFailedSpy = vi.fn();
|
|
@@ -146,7 +152,7 @@ describe('Bind Flow - Body Update Integration', () => {
|
|
|
146
152
|
act(() => { getEventBus().get('bind:update-body').next({
|
|
147
153
|
annotationId: annotationId('ann-fail'),
|
|
148
154
|
resourceId: resourceId('resource-id'),
|
|
149
|
-
operations: [{ op: 'remove', item: {
|
|
155
|
+
operations: [{ op: 'remove', item: { type: 'SpecificResource' as const, source: 'old-id' } }],
|
|
150
156
|
}); });
|
|
151
157
|
|
|
152
158
|
await waitFor(() => {
|
|
@@ -166,11 +172,11 @@ describe('Bind Flow - Body Update Integration', () => {
|
|
|
166
172
|
act(() => { getEventBus().get('bind:update-body').next({
|
|
167
173
|
annotationId: annotationId('ann-dedup'),
|
|
168
174
|
resourceId: resourceId('resource-id'),
|
|
169
|
-
operations: [{ op: 'add', item: {
|
|
175
|
+
operations: [{ op: 'add', item: { type: 'SpecificResource' as const, source: 'resource-id' } }],
|
|
170
176
|
}); });
|
|
171
177
|
|
|
172
178
|
await waitFor(() => {
|
|
173
|
-
expect(
|
|
179
|
+
expect(bindAnnotationSpy).toHaveBeenCalledTimes(1);
|
|
174
180
|
});
|
|
175
181
|
});
|
|
176
182
|
});
|
|
@@ -35,10 +35,10 @@ describe('REPRODUCING BUG: Detection state not updating', () => {
|
|
|
35
35
|
vi.clearAllMocks();
|
|
36
36
|
|
|
37
37
|
// Minimal mock - SSE streams not needed for this test
|
|
38
|
-
vi.spyOn(SSEClient.prototype, '
|
|
39
|
-
vi.spyOn(SSEClient.prototype, '
|
|
40
|
-
vi.spyOn(SSEClient.prototype, '
|
|
41
|
-
vi.spyOn(SSEClient.prototype, '
|
|
38
|
+
vi.spyOn(SSEClient.prototype, 'markReferences').mockReturnValue({ onProgress: vi.fn().mockReturnThis(), onComplete: vi.fn().mockReturnThis(), onError: vi.fn().mockReturnThis(), close: vi.fn() } as any);
|
|
39
|
+
vi.spyOn(SSEClient.prototype, 'markHighlights').mockReturnValue({ onProgress: vi.fn().mockReturnThis(), onComplete: vi.fn().mockReturnThis(), onError: vi.fn().mockReturnThis(), close: vi.fn() } as any);
|
|
40
|
+
vi.spyOn(SSEClient.prototype, 'markComments').mockReturnValue({ onProgress: vi.fn().mockReturnThis(), onComplete: vi.fn().mockReturnThis(), onError: vi.fn().mockReturnThis(), close: vi.fn() } as any);
|
|
41
|
+
vi.spyOn(SSEClient.prototype, 'markAssessments').mockReturnValue({ onProgress: vi.fn().mockReturnThis(), onComplete: vi.fn().mockReturnThis(), onError: vi.fn().mockReturnThis(), close: vi.fn() } as any);
|
|
42
42
|
});
|
|
43
43
|
|
|
44
44
|
afterEach(() => {
|
|
@@ -54,8 +54,8 @@ const createMockSSEStream = () => {
|
|
|
54
54
|
|
|
55
55
|
describe('Detection Flow - Feature Integration', () => {
|
|
56
56
|
let mockStream: ReturnType<typeof createMockSSEStream>;
|
|
57
|
-
let
|
|
58
|
-
let
|
|
57
|
+
let markReferencesSpy: any;
|
|
58
|
+
let markHighlightsSpy: any;
|
|
59
59
|
let detectCommentsSpy: any;
|
|
60
60
|
|
|
61
61
|
beforeEach(() => {
|
|
@@ -66,10 +66,10 @@ describe('Detection Flow - Feature Integration', () => {
|
|
|
66
66
|
mockStream = createMockSSEStream();
|
|
67
67
|
|
|
68
68
|
// Spy on SSEClient prototype methods
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
detectCommentsSpy = vi.spyOn(SSEClient.prototype, '
|
|
72
|
-
vi.spyOn(SSEClient.prototype, '
|
|
69
|
+
markReferencesSpy = vi.spyOn(SSEClient.prototype, 'markReferences').mockReturnValue(mockStream as any);
|
|
70
|
+
markHighlightsSpy = vi.spyOn(SSEClient.prototype, 'markHighlights').mockReturnValue(mockStream as any);
|
|
71
|
+
detectCommentsSpy = vi.spyOn(SSEClient.prototype, 'markComments').mockReturnValue(mockStream as any);
|
|
72
|
+
vi.spyOn(SSEClient.prototype, 'markAssessments').mockReturnValue(mockStream as any);
|
|
73
73
|
});
|
|
74
74
|
|
|
75
75
|
afterEach(() => {
|
|
@@ -93,11 +93,11 @@ describe('Detection Flow - Feature Integration', () => {
|
|
|
93
93
|
// CRITICAL ASSERTION: API called exactly once (not twice!)
|
|
94
94
|
// This would FAIL if useBindFlow was called in multiple places
|
|
95
95
|
await waitFor(() => {
|
|
96
|
-
expect(
|
|
96
|
+
expect(markReferencesSpy).toHaveBeenCalledTimes(1);
|
|
97
97
|
});
|
|
98
98
|
|
|
99
99
|
// Verify correct parameters (eventBus is passed but we don't need to verify its exact value)
|
|
100
|
-
expect(
|
|
100
|
+
expect(markReferencesSpy).toHaveBeenCalledWith(
|
|
101
101
|
testId,
|
|
102
102
|
{
|
|
103
103
|
entityTypes: ['Person', 'Organization'],
|
|
@@ -122,7 +122,7 @@ describe('Detection Flow - Feature Integration', () => {
|
|
|
122
122
|
|
|
123
123
|
// Wait for stream to be created
|
|
124
124
|
await waitFor(() => {
|
|
125
|
-
expect(
|
|
125
|
+
expect(markReferencesSpy).toHaveBeenCalled();
|
|
126
126
|
});
|
|
127
127
|
|
|
128
128
|
// Simulate SSE progress event being emitted to EventBus (how SSE actually works now)
|
|
@@ -156,7 +156,7 @@ describe('Detection Flow - Feature Integration', () => {
|
|
|
156
156
|
});
|
|
157
157
|
|
|
158
158
|
await waitFor(() => {
|
|
159
|
-
expect(
|
|
159
|
+
expect(markHighlightsSpy).toHaveBeenCalledTimes(1);
|
|
160
160
|
});
|
|
161
161
|
|
|
162
162
|
// First progress update via EventBus
|
|
@@ -291,8 +291,8 @@ describe('Detection Flow - Feature Integration', () => {
|
|
|
291
291
|
});
|
|
292
292
|
|
|
293
293
|
await waitFor(() => {
|
|
294
|
-
expect(
|
|
295
|
-
expect(
|
|
294
|
+
expect(markHighlightsSpy).toHaveBeenCalledTimes(1);
|
|
295
|
+
expect(markHighlightsSpy).toHaveBeenCalledWith(testId, {
|
|
296
296
|
instructions: 'Find important text',
|
|
297
297
|
}, expect.objectContaining({ auth: undefined }));
|
|
298
298
|
});
|
|
@@ -337,11 +337,11 @@ describe('Detection Flow - Feature Integration', () => {
|
|
|
337
337
|
|
|
338
338
|
// Wait for operation to complete
|
|
339
339
|
await waitFor(() => {
|
|
340
|
-
expect(
|
|
340
|
+
expect(markReferencesSpy).toHaveBeenCalled();
|
|
341
341
|
});
|
|
342
342
|
|
|
343
343
|
// VERIFY: API called exactly once, even though multiple listeners exist
|
|
344
|
-
expect(
|
|
344
|
+
expect(markReferencesSpy).toHaveBeenCalledTimes(1);
|
|
345
345
|
|
|
346
346
|
// VERIFY: Our additional listener was called (events work)
|
|
347
347
|
expect(additionalListener).toHaveBeenCalledTimes(1);
|
|
@@ -91,7 +91,7 @@ useDebouncedCallback: (fn: any) => fn,
|
|
|
91
91
|
useResourceAnnotations: () => ({
|
|
92
92
|
clearNewAnnotationId: vi.fn(),
|
|
93
93
|
newAnnotationIds: new Set(),
|
|
94
|
-
|
|
94
|
+
markAnnotation: vi.fn(),
|
|
95
95
|
deleteAnnotation: vi.fn(),
|
|
96
96
|
triggerSparkleAnimation: vi.fn(),
|
|
97
97
|
}),
|
|
@@ -111,7 +111,7 @@ vi.mock('../../../contexts/ResourceAnnotationsContext', () => ({
|
|
|
111
111
|
useResourceAnnotations: () => ({
|
|
112
112
|
clearNewAnnotationId: vi.fn(),
|
|
113
113
|
newAnnotationIds: new Set(),
|
|
114
|
-
|
|
114
|
+
markAnnotation: vi.fn(),
|
|
115
115
|
deleteAnnotation: vi.fn(),
|
|
116
116
|
triggerSparkleAnimation: vi.fn(),
|
|
117
117
|
}),
|
|
@@ -64,7 +64,7 @@ describe('Generation Flow - Feature Integration', () => {
|
|
|
64
64
|
mockStream = createMockGenerationStream();
|
|
65
65
|
|
|
66
66
|
// Spy on SSEClient prototype method
|
|
67
|
-
generateResourceSpy = vi.spyOn(SSEClient.prototype, '
|
|
67
|
+
generateResourceSpy = vi.spyOn(SSEClient.prototype, 'yieldResource').mockReturnValue(mockStream as any);
|
|
68
68
|
|
|
69
69
|
// Mock callbacks
|
|
70
70
|
mockShowSuccess = vi.fn();
|
|
@@ -76,7 +76,7 @@ describe('Generation Flow - Feature Integration', () => {
|
|
|
76
76
|
vi.restoreAllMocks();
|
|
77
77
|
});
|
|
78
78
|
|
|
79
|
-
it('should call
|
|
79
|
+
it('should call yieldResource exactly ONCE when generation starts', async () => {
|
|
80
80
|
const testResourceId = resourceId('test-resource');
|
|
81
81
|
const testAnnotationId = annotationId('test-annotation');
|
|
82
82
|
|
|
@@ -158,10 +158,10 @@ describe('Detection Progress Flow Integration (Layer 3)', () => {
|
|
|
158
158
|
mockStream = new MockSSEStream(eventBus);
|
|
159
159
|
|
|
160
160
|
// Spy on SSEClient prototype methods to inject mock stream
|
|
161
|
-
vi.spyOn(SSEClient.prototype, '
|
|
162
|
-
vi.spyOn(SSEClient.prototype, '
|
|
163
|
-
vi.spyOn(SSEClient.prototype, '
|
|
164
|
-
vi.spyOn(SSEClient.prototype, '
|
|
161
|
+
vi.spyOn(SSEClient.prototype, 'markHighlights').mockReturnValue(mockStream as any);
|
|
162
|
+
vi.spyOn(SSEClient.prototype, 'markAssessments').mockReturnValue(mockStream as any);
|
|
163
|
+
vi.spyOn(SSEClient.prototype, 'markComments').mockReturnValue(mockStream as any);
|
|
164
|
+
vi.spyOn(SSEClient.prototype, 'markReferences').mockReturnValue(mockStream as any);
|
|
165
165
|
|
|
166
166
|
mockAnnotations = [];
|
|
167
167
|
});
|
|
@@ -415,12 +415,12 @@ export function ResourceViewerPage({
|
|
|
415
415
|
// Error notification is handled by useYieldFlow
|
|
416
416
|
}, []);
|
|
417
417
|
|
|
418
|
-
const handleReferenceNavigate = useCallback(({
|
|
419
|
-
if (routes.
|
|
420
|
-
const path = routes.
|
|
418
|
+
const handleReferenceNavigate = useCallback(({ resourceId }: { resourceId: string }) => {
|
|
419
|
+
if (routes.resourceDetail) {
|
|
420
|
+
const path = routes.resourceDetail(resourceId);
|
|
421
421
|
eventBus.get('browse:router-push').next({ path, reason: 'reference-link' });
|
|
422
422
|
}
|
|
423
|
-
}, [routes.
|
|
423
|
+
}, [routes.resourceDetail]); // eventBus is stable singleton - never in deps
|
|
424
424
|
|
|
425
425
|
const handleEntityTypeClicked = useCallback(({ entityType }: { entityType: string }) => {
|
|
426
426
|
if (routes.know) {
|
|
@@ -613,6 +613,7 @@ export function ResourceViewerPage({
|
|
|
613
613
|
referencedBy={referencedBy}
|
|
614
614
|
referencedByLoading={referencedByLoading}
|
|
615
615
|
resourceId={rUri}
|
|
616
|
+
locale={locale}
|
|
616
617
|
scrollToAnnotationId={scrollToAnnotationId}
|
|
617
618
|
hoveredAnnotationId={hoveredAnnotationId}
|
|
618
619
|
onScrollCompleted={onScrollCompleted}
|
|
@@ -643,6 +644,12 @@ export function ResourceViewerPage({
|
|
|
643
644
|
primaryMediaType={primaryMediaType}
|
|
644
645
|
primaryByteSize={primaryByteSize}
|
|
645
646
|
isArchived={resource.archived ?? false}
|
|
647
|
+
dateCreated={resource.dateCreated}
|
|
648
|
+
dateModified={resource.dateModified}
|
|
649
|
+
creationMethod={resource.creationMethod}
|
|
650
|
+
wasAttributedTo={resource.wasAttributedTo}
|
|
651
|
+
wasDerivedFrom={resource.wasDerivedFrom}
|
|
652
|
+
generator={resource.generator as components['schemas']['Agent'] | components['schemas']['Agent'][] | undefined}
|
|
646
653
|
/>
|
|
647
654
|
)}
|
|
648
655
|
|
|
@@ -690,15 +697,9 @@ export function ResourceViewerPage({
|
|
|
690
697
|
configureGenerationTitle: tw('configureGenerationTitle'),
|
|
691
698
|
configureSearchTitle: tw('configureSearchTitle'),
|
|
692
699
|
searchResultsTitle: tw('searchResultsTitle'),
|
|
693
|
-
annotationLabel: tw('annotationLabel'),
|
|
694
|
-
sourceResourceLabel: tw('sourceResourceLabel'),
|
|
695
|
-
motivationLabel: tw('motivationLabel'),
|
|
696
700
|
sourceContextLabel: tw('sourceContextLabel'),
|
|
697
|
-
entityTypesLabel: tw('entityTypesLabel'),
|
|
698
|
-
graphContextLabel: tw('graphContextLabel'),
|
|
699
701
|
connectionsLabel: tw('connectionsLabel'),
|
|
700
702
|
citedByLabel: tw('citedByLabel'),
|
|
701
|
-
siblingTypesLabel: tw('siblingTypesLabel'),
|
|
702
703
|
userHintLabel: tw('userHintLabel'),
|
|
703
704
|
userHintPlaceholder: tw('userHintPlaceholder'),
|
|
704
705
|
loadingContext: tw('loadingContext'),
|
|
@@ -708,6 +709,7 @@ export function ResourceViewerPage({
|
|
|
708
709
|
searching: tw('searching'),
|
|
709
710
|
generate: tw('generate'),
|
|
710
711
|
compose: tw('compose'),
|
|
712
|
+
resolutionStrategyLabel: tw('resolutionStrategyLabel'),
|
|
711
713
|
back: tw('back'),
|
|
712
714
|
link: tw('link'),
|
|
713
715
|
score: tw('score'),
|