@semiont/react-ui 0.5.3 → 0.5.5
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-5QESNO5H.mjs → PdfAnnotationCanvas.client-CN3C3S55.js} +2 -2
- package/dist/{ar-UUMMNQKF.mjs → ar-U2EXWUMQ.js} +2 -5
- package/dist/ar-U2EXWUMQ.js.map +1 -0
- package/dist/{bn-AL5BJSR3.mjs → bn-DRJGV772.js} +2 -5
- package/dist/bn-DRJGV772.js.map +1 -0
- package/dist/{chunk-EBBL3VJI.mjs → chunk-3Q3TUKWP.js} +32 -32
- package/dist/{chunk-OJSRLEER.mjs → chunk-GERSK2DY.js} +2 -5
- package/dist/chunk-GERSK2DY.js.map +1 -0
- package/dist/{chunk-D4GAAQMM.mjs → chunk-K6BJDL2I.js} +1 -1
- package/dist/{cs-UMINALSU.mjs → cs-PTWDM23V.js} +2 -5
- package/dist/{cs-UMINALSU.mjs.map → cs-PTWDM23V.js.map} +1 -1
- package/dist/{da-FKUX6CDL.mjs → da-KSNIKYSS.js} +2 -5
- package/dist/da-KSNIKYSS.js.map +1 -0
- package/dist/{de-XSJ3E25S.mjs → de-F2XBEWFY.js} +2 -5
- package/dist/de-F2XBEWFY.js.map +1 -0
- package/dist/{el-UJXNRCBP.mjs → el-DLD2GWAP.js} +2 -5
- package/dist/el-DLD2GWAP.js.map +1 -0
- package/dist/{en-J5DHKLQ5.mjs → en-L45VK7BS.js} +3 -3
- package/dist/{es-VURP62BU.mjs → es-WLPYWGB5.js} +2 -5
- package/dist/es-WLPYWGB5.js.map +1 -0
- package/dist/{fa-TIT5ZPZY.mjs → fa-BAXHSDZG.js} +2 -5
- package/dist/fa-BAXHSDZG.js.map +1 -0
- package/dist/{fi-F7VTGT4H.mjs → fi-FCHSYVOT.js} +2 -5
- package/dist/fi-FCHSYVOT.js.map +1 -0
- package/dist/{fr-2ZR26VF7.mjs → fr-3UERBSL6.js} +2 -5
- package/dist/fr-3UERBSL6.js.map +1 -0
- package/dist/{he-BXP2KYVZ.mjs → he-F6F3FV2K.js} +2 -5
- package/dist/he-F6F3FV2K.js.map +1 -0
- package/dist/{hi-PSWTP3NC.mjs → hi-4BK6IK7Q.js} +2 -5
- package/dist/hi-4BK6IK7Q.js.map +1 -0
- package/dist/{id-HO6TXGTO.mjs → id-7ECCWP3J.js} +2 -5
- package/dist/id-7ECCWP3J.js.map +1 -0
- package/dist/{index.d.mts → index.d.ts} +25 -10
- package/dist/{index.mjs → index.js} +43 -46
- package/dist/index.js.map +1 -0
- package/dist/{it-AGTDMBL3.mjs → it-234Z6XK6.js} +2 -5
- package/dist/it-234Z6XK6.js.map +1 -0
- package/dist/{ja-TTGOVF5K.mjs → ja-PJWQI4OQ.js} +2 -5
- package/dist/ja-PJWQI4OQ.js.map +1 -0
- package/dist/{ko-FF77IQ7N.mjs → ko-APUEW2RS.js} +2 -5
- package/dist/ko-APUEW2RS.js.map +1 -0
- package/dist/{ms-UPQWWIL4.mjs → ms-PJBZWZWD.js} +2 -5
- package/dist/ms-PJBZWZWD.js.map +1 -0
- package/dist/{nl-W75HEPFL.mjs → nl-L4C3ZBCU.js} +2 -5
- package/dist/nl-L4C3ZBCU.js.map +1 -0
- package/dist/{no-R4W7W7ZU.mjs → no-QE5N5KNG.js} +2 -5
- package/dist/no-QE5N5KNG.js.map +1 -0
- package/dist/{pl-GQC2ELWO.mjs → pl-5Q2D23PD.js} +2 -5
- package/dist/pl-5Q2D23PD.js.map +1 -0
- package/dist/{pt-YGVT62RU.mjs → pt-AIGUOIOC.js} +2 -5
- package/dist/pt-AIGUOIOC.js.map +1 -0
- package/dist/{ro-TST6XS6X.mjs → ro-T56CSHTY.js} +2 -5
- package/dist/ro-T56CSHTY.js.map +1 -0
- package/dist/{sv-TQLF6HV7.mjs → sv-L4TJQ2UH.js} +2 -5
- package/dist/sv-L4TJQ2UH.js.map +1 -0
- package/dist/{test-utils.d.mts → test-utils.d.ts} +20 -5
- package/dist/{test-utils.mjs → test-utils.js} +5 -5
- package/dist/{th-HJUIETVR.mjs → th-6O7Y6O2Q.js} +2 -5
- package/dist/th-6O7Y6O2Q.js.map +1 -0
- package/dist/{tr-CW3C46TW.mjs → tr-D4CQCSNO.js} +2 -5
- package/dist/tr-D4CQCSNO.js.map +1 -0
- package/dist/{uk-WTHZQB2U.mjs → uk-2HMQG6ND.js} +2 -5
- package/dist/uk-2HMQG6ND.js.map +1 -0
- package/dist/{vi-PHWHJLKP.mjs → vi-XVJ4RUEJ.js} +2 -5
- package/dist/{vi-PHWHJLKP.mjs.map → vi-XVJ4RUEJ.js.map} +1 -1
- package/dist/{zh-MO3FCUD6.mjs → zh-K2KDPGHK.js} +2 -5
- package/dist/zh-K2KDPGHK.js.map +1 -0
- package/package.json +22 -19
- package/src/components/resource/HistoryEvent.tsx +0 -3
- package/src/components/resource/__tests__/HistoryEvent.test.tsx +1 -4
- package/src/components/resource/__tests__/event-formatting.test.ts +2 -14
- package/src/components/resource/event-formatting.ts +3 -4
- package/src/components/resource/panels/AssessmentEntry.tsx +4 -1
- package/src/components/resource/panels/CommentEntry.tsx +4 -1
- package/src/components/resource/panels/HighlightEntry.tsx +4 -1
- package/src/components/resource/panels/ReferenceEntry.tsx +4 -1
- package/src/components/resource/panels/ResourceInfoPanel.tsx +11 -23
- package/src/components/resource/panels/TagEntry.tsx +4 -1
- package/src/components/resource/panels/__tests__/CommentEntry.test.tsx +2 -2
- package/src/components/resource/panels/__tests__/ResourceInfoPanel.test.tsx +12 -16
- package/src/components/resource/panels/__tests__/agent-label.test.ts +93 -0
- package/src/components/resource/panels/agent-label.ts +20 -0
- package/src/features/resource-compose/state/compose-page-state-unit.ts +0 -1
- package/src/features/resource-viewer/components/ResourceViewerPage.tsx +0 -1
- package/translations/ar.json +0 -3
- package/translations/bn.json +0 -3
- package/translations/cs.json +0 -3
- package/translations/da.json +0 -3
- package/translations/de.json +0 -3
- package/translations/el.json +0 -3
- package/translations/en.json +2 -5
- package/translations/es.json +0 -3
- package/translations/fa.json +0 -3
- package/translations/fi.json +0 -3
- package/translations/fr.json +0 -3
- package/translations/he.json +0 -3
- package/translations/hi.json +0 -3
- package/translations/id.json +0 -3
- package/translations/it.json +0 -3
- package/translations/ja.json +0 -3
- package/translations/ko.json +0 -3
- package/translations/ms.json +0 -3
- package/translations/nl.json +0 -3
- package/translations/no.json +0 -3
- package/translations/pl.json +0 -3
- package/translations/pt.json +0 -3
- package/translations/ro.json +0 -3
- package/translations/sv.json +0 -3
- package/translations/th.json +0 -3
- package/translations/tr.json +0 -3
- package/translations/uk.json +0 -3
- package/translations/vi.json +0 -3
- package/translations/zh.json +0 -3
- package/dist/TranslationManager-9Xj3MIWQ.d.mts +0 -16
- package/dist/ar-UUMMNQKF.mjs.map +0 -1
- package/dist/bn-AL5BJSR3.mjs.map +0 -1
- package/dist/chunk-OJSRLEER.mjs.map +0 -1
- package/dist/da-FKUX6CDL.mjs.map +0 -1
- package/dist/de-XSJ3E25S.mjs.map +0 -1
- package/dist/el-UJXNRCBP.mjs.map +0 -1
- package/dist/es-VURP62BU.mjs.map +0 -1
- package/dist/fa-TIT5ZPZY.mjs.map +0 -1
- package/dist/fi-F7VTGT4H.mjs.map +0 -1
- package/dist/fr-2ZR26VF7.mjs.map +0 -1
- package/dist/he-BXP2KYVZ.mjs.map +0 -1
- package/dist/hi-PSWTP3NC.mjs.map +0 -1
- package/dist/id-HO6TXGTO.mjs.map +0 -1
- package/dist/index.mjs.map +0 -1
- package/dist/it-AGTDMBL3.mjs.map +0 -1
- package/dist/ja-TTGOVF5K.mjs.map +0 -1
- package/dist/ko-FF77IQ7N.mjs.map +0 -1
- package/dist/ms-UPQWWIL4.mjs.map +0 -1
- package/dist/nl-W75HEPFL.mjs.map +0 -1
- package/dist/no-R4W7W7ZU.mjs.map +0 -1
- package/dist/pl-GQC2ELWO.mjs.map +0 -1
- package/dist/pt-YGVT62RU.mjs.map +0 -1
- package/dist/ro-TST6XS6X.mjs.map +0 -1
- package/dist/sv-TQLF6HV7.mjs.map +0 -1
- package/dist/th-HJUIETVR.mjs.map +0 -1
- package/dist/tr-CW3C46TW.mjs.map +0 -1
- package/dist/uk-WTHZQB2U.mjs.map +0 -1
- package/dist/zh-MO3FCUD6.mjs.map +0 -1
- /package/dist/{PdfAnnotationCanvas.client-5QESNO5H.mjs.map → PdfAnnotationCanvas.client-CN3C3S55.js.map} +0 -0
- /package/dist/{chunk-EBBL3VJI.mjs.map → chunk-3Q3TUKWP.js.map} +0 -0
- /package/dist/{chunk-D4GAAQMM.mjs.map → chunk-K6BJDL2I.js.map} +0 -0
- /package/dist/{en-J5DHKLQ5.mjs.map → en-L45VK7BS.js.map} +0 -0
- /package/dist/{test-utils.mjs.map → test-utils.js.map} +0 -0
- /package/src/integrations/{tailwind-plugin.js → tailwind-plugin.cjs} +0 -0
|
@@ -204,14 +204,13 @@ describe('event-formatting', () => {
|
|
|
204
204
|
it('returns created details for yield:created', () => {
|
|
205
205
|
const event = {
|
|
206
206
|
type: 'yield:created' as const,
|
|
207
|
-
payload: { name: 'Doc'
|
|
207
|
+
payload: { name: 'Doc' },
|
|
208
208
|
userId: 'user-1',
|
|
209
209
|
timestamp: '',
|
|
210
210
|
} as any;
|
|
211
211
|
const result = getResourceCreationDetails(event);
|
|
212
212
|
expect(result).toEqual({
|
|
213
213
|
type: 'created',
|
|
214
|
-
method: 'upload',
|
|
215
214
|
userId: 'user-1',
|
|
216
215
|
metadata: undefined,
|
|
217
216
|
});
|
|
@@ -220,14 +219,13 @@ describe('event-formatting', () => {
|
|
|
220
219
|
it('returns cloned details for yield:cloned', () => {
|
|
221
220
|
const event = {
|
|
222
221
|
type: 'yield:cloned' as const,
|
|
223
|
-
payload: { name: 'Clone',
|
|
222
|
+
payload: { name: 'Clone', parentResourceId: 'parent-1' },
|
|
224
223
|
userId: 'user-2',
|
|
225
224
|
timestamp: '',
|
|
226
225
|
} as any;
|
|
227
226
|
const result = getResourceCreationDetails(event);
|
|
228
227
|
expect(result).toEqual({
|
|
229
228
|
type: 'cloned',
|
|
230
|
-
method: 'clone',
|
|
231
229
|
userId: 'user-2',
|
|
232
230
|
sourceDocId: 'parent-1',
|
|
233
231
|
parentResourceId: 'parent-1',
|
|
@@ -235,16 +233,6 @@ describe('event-formatting', () => {
|
|
|
235
233
|
});
|
|
236
234
|
});
|
|
237
235
|
|
|
238
|
-
it('uses fallback method when creationMethod missing', () => {
|
|
239
|
-
const event = {
|
|
240
|
-
type: 'yield:created' as const,
|
|
241
|
-
payload: { name: 'Doc' },
|
|
242
|
-
userId: 'u1',
|
|
243
|
-
timestamp: '',
|
|
244
|
-
} as any;
|
|
245
|
-
expect(getResourceCreationDetails(event)?.method).toBe('unknown');
|
|
246
|
-
});
|
|
247
|
-
|
|
248
236
|
it('returns null for non-creation events', () => {
|
|
249
237
|
const event = { type: 'mark:added' as const, payload: {} } as any;
|
|
250
238
|
expect(getResourceCreationDetails(event)).toBeNull();
|
|
@@ -306,11 +306,12 @@ export function getEventEntityTypes(event: StoredEventLike): string[] {
|
|
|
306
306
|
}
|
|
307
307
|
|
|
308
308
|
/**
|
|
309
|
-
* Resource creation details
|
|
309
|
+
* Resource creation details derived from a yield:created or yield:cloned
|
|
310
|
+
* event. The creation kind (`type`) is read from the event channel —
|
|
311
|
+
* the redundant `creationMethod` payload field is gone.
|
|
310
312
|
*/
|
|
311
313
|
export interface ResourceCreationDetails {
|
|
312
314
|
type: 'created' | 'cloned';
|
|
313
|
-
method: string;
|
|
314
315
|
userId?: string;
|
|
315
316
|
sourceDocId?: string; // For cloned resources
|
|
316
317
|
parentResourceId?: string;
|
|
@@ -327,7 +328,6 @@ export function getResourceCreationDetails(event: StoredEventLike): ResourceCrea
|
|
|
327
328
|
if (eventData.type === 'yield:created') {
|
|
328
329
|
return {
|
|
329
330
|
type: 'created',
|
|
330
|
-
method: payload.creationMethod || 'unknown',
|
|
331
331
|
userId: eventData.userId,
|
|
332
332
|
metadata: undefined,
|
|
333
333
|
};
|
|
@@ -336,7 +336,6 @@ export function getResourceCreationDetails(event: StoredEventLike): ResourceCrea
|
|
|
336
336
|
if (eventData.type === 'yield:cloned') {
|
|
337
337
|
return {
|
|
338
338
|
type: 'cloned',
|
|
339
|
-
method: payload.creationMethod || 'clone',
|
|
340
339
|
userId: eventData.userId,
|
|
341
340
|
sourceDocId: payload.parentResourceId,
|
|
342
341
|
parentResourceId: payload.parentResourceId,
|
|
@@ -6,6 +6,7 @@ import { getAnnotationExactText } from '@semiont/core';
|
|
|
6
6
|
import { useSemiont } from '../../../session/SemiontProvider';
|
|
7
7
|
import { useObservable } from '../../../hooks/useObservable';
|
|
8
8
|
import { useHoverEmitter } from '../../../hooks/useHoverEmitter';
|
|
9
|
+
import { renderAgentLabel } from './agent-label';
|
|
9
10
|
|
|
10
11
|
// W3C Annotation TextualBody type
|
|
11
12
|
interface TextualBody {
|
|
@@ -110,7 +111,9 @@ export function AssessmentEntry({
|
|
|
110
111
|
</div>
|
|
111
112
|
{assessment.generator && (
|
|
112
113
|
<div className="semiont-annotation-entry__metadata">
|
|
113
|
-
Via {
|
|
114
|
+
Via {Array.isArray(assessment.generator)
|
|
115
|
+
? assessment.generator.map(renderAgentLabel).join(', ')
|
|
116
|
+
: renderAgentLabel(assessment.generator)}
|
|
114
117
|
</div>
|
|
115
118
|
)}
|
|
116
119
|
</div>
|
|
@@ -7,6 +7,7 @@ import { getAnnotationExactText, getCommentText } from '@semiont/core';
|
|
|
7
7
|
import { useSemiont } from '../../../session/SemiontProvider';
|
|
8
8
|
import { useObservable } from '../../../hooks/useObservable';
|
|
9
9
|
import { useHoverEmitter } from '../../../hooks/useHoverEmitter';
|
|
10
|
+
import { renderAgentLabel } from './agent-label';
|
|
10
11
|
|
|
11
12
|
interface CommentEntryProps {
|
|
12
13
|
comment: Annotation;
|
|
@@ -140,7 +141,9 @@ export function CommentEntry({
|
|
|
140
141
|
</div>
|
|
141
142
|
{comment.generator && (
|
|
142
143
|
<div className="semiont-annotation-entry__metadata">
|
|
143
|
-
Via {
|
|
144
|
+
Via {Array.isArray(comment.generator)
|
|
145
|
+
? comment.generator.map(renderAgentLabel).join(', ')
|
|
146
|
+
: renderAgentLabel(comment.generator)}
|
|
144
147
|
</div>
|
|
145
148
|
)}
|
|
146
149
|
{annotateMode && (
|
|
@@ -6,6 +6,7 @@ import { getAnnotationExactText } from '@semiont/core';
|
|
|
6
6
|
import { useSemiont } from '../../../session/SemiontProvider';
|
|
7
7
|
import { useObservable } from '../../../hooks/useObservable';
|
|
8
8
|
import { useHoverEmitter } from '../../../hooks/useHoverEmitter';
|
|
9
|
+
import { renderAgentLabel } from './agent-label';
|
|
9
10
|
|
|
10
11
|
interface HighlightEntryProps {
|
|
11
12
|
highlight: Annotation;
|
|
@@ -66,7 +67,9 @@ export function HighlightEntry({
|
|
|
66
67
|
</div>
|
|
67
68
|
{highlight.generator && (
|
|
68
69
|
<div className="semiont-annotation-entry__metadata">
|
|
69
|
-
Via {
|
|
70
|
+
Via {Array.isArray(highlight.generator)
|
|
71
|
+
? highlight.generator.map(renderAgentLabel).join(', ')
|
|
72
|
+
: renderAgentLabel(highlight.generator)}
|
|
70
73
|
</div>
|
|
71
74
|
)}
|
|
72
75
|
</div>
|
|
@@ -10,6 +10,7 @@ import { getEntityTypes } from '@semiont/ontology';
|
|
|
10
10
|
import { getResourceIcon } from '../../../lib/resource-utils';
|
|
11
11
|
import { useSemiont } from '../../../session/SemiontProvider';
|
|
12
12
|
import { useObservable } from '../../../hooks/useObservable';
|
|
13
|
+
import { renderAgentLabel } from './agent-label';
|
|
13
14
|
import { useObservableExternalNavigation } from '../../../hooks/useObservableBrowse';
|
|
14
15
|
import { useHoverEmitter } from '../../../hooks/useHoverEmitter';
|
|
15
16
|
|
|
@@ -171,7 +172,9 @@ export function ReferenceEntry({
|
|
|
171
172
|
)}
|
|
172
173
|
{reference.generator && (
|
|
173
174
|
<div className="semiont-annotation-entry__metadata">
|
|
174
|
-
Via {
|
|
175
|
+
Via {Array.isArray(reference.generator)
|
|
176
|
+
? reference.generator.map(renderAgentLabel).join(', ')
|
|
177
|
+
: renderAgentLabel(reference.generator)}
|
|
175
178
|
</div>
|
|
176
179
|
)}
|
|
177
180
|
</div>
|
|
@@ -5,6 +5,7 @@ import { useSemiont } from '../../../session/SemiontProvider';
|
|
|
5
5
|
import { useObservable } from '../../../hooks/useObservable';
|
|
6
6
|
import { formatLocaleDisplay } from '@semiont/core';
|
|
7
7
|
import { resourceId as makeResourceId, type components } from '@semiont/core';
|
|
8
|
+
import { renderAgentLabel } from './agent-label';
|
|
8
9
|
import './ResourceInfoPanel.css';
|
|
9
10
|
|
|
10
11
|
type Agent = components['schemas']['Agent'];
|
|
@@ -19,7 +20,6 @@ interface Props {
|
|
|
19
20
|
isArchived?: boolean;
|
|
20
21
|
dateCreated?: string | undefined;
|
|
21
22
|
dateModified?: string | undefined;
|
|
22
|
-
creationMethod?: string | undefined;
|
|
23
23
|
wasAttributedTo?: Agent | Agent[] | undefined;
|
|
24
24
|
wasDerivedFrom?: string | string[] | undefined;
|
|
25
25
|
generator?: Agent | Agent[] | undefined;
|
|
@@ -42,7 +42,6 @@ export function ResourceInfoPanel({
|
|
|
42
42
|
isArchived = false,
|
|
43
43
|
dateCreated,
|
|
44
44
|
dateModified,
|
|
45
|
-
creationMethod,
|
|
46
45
|
wasAttributedTo,
|
|
47
46
|
wasDerivedFrom,
|
|
48
47
|
generator,
|
|
@@ -50,6 +49,13 @@ export function ResourceInfoPanel({
|
|
|
50
49
|
const t = useTranslations('ResourceInfoPanel');
|
|
51
50
|
const session = useObservable(useSemiont().activeSession$);
|
|
52
51
|
|
|
52
|
+
// Single attribution surface. `wasAttributedTo` is the canonical list
|
|
53
|
+
// of responsible parties; if a producer set only `generator` we
|
|
54
|
+
// render that as the attribution chain.
|
|
55
|
+
const attribution: Agent[] = wasAttributedTo
|
|
56
|
+
? (Array.isArray(wasAttributedTo) ? wasAttributedTo : [wasAttributedTo])
|
|
57
|
+
: (generator ? (Array.isArray(generator) ? generator : [generator]) : []);
|
|
58
|
+
|
|
53
59
|
return (
|
|
54
60
|
<div className="semiont-resource-info-panel">
|
|
55
61
|
{/* Panel Title */}
|
|
@@ -105,7 +111,7 @@ export function ResourceInfoPanel({
|
|
|
105
111
|
)}
|
|
106
112
|
|
|
107
113
|
{/* Provenance Section */}
|
|
108
|
-
{(dateCreated || dateModified ||
|
|
114
|
+
{(dateCreated || dateModified || attribution.length > 0 || wasDerivedFrom) && (
|
|
109
115
|
<div className="semiont-resource-info-panel__section">
|
|
110
116
|
<h3 className="semiont-resource-info-panel__heading">{t('provenance')}</h3>
|
|
111
117
|
<div className="semiont-resource-info-panel__field-group">
|
|
@@ -125,19 +131,11 @@ export function ResourceInfoPanel({
|
|
|
125
131
|
</span>
|
|
126
132
|
</div>
|
|
127
133
|
)}
|
|
128
|
-
{
|
|
129
|
-
<div>
|
|
130
|
-
<span className="semiont-resource-info-panel__label">{t('creationMethod')}</span>
|
|
131
|
-
<span className="semiont-resource-info-panel__value">{creationMethod}</span>
|
|
132
|
-
</div>
|
|
133
|
-
)}
|
|
134
|
-
{wasAttributedTo && (
|
|
134
|
+
{attribution.length > 0 && (
|
|
135
135
|
<div>
|
|
136
136
|
<span className="semiont-resource-info-panel__label">{t('attributedTo')}</span>
|
|
137
137
|
<span className="semiont-resource-info-panel__value">
|
|
138
|
-
{(
|
|
139
|
-
.map(a => a.name)
|
|
140
|
-
.join(', ')}
|
|
138
|
+
{attribution.map(renderAgentLabel).join(', ')}
|
|
141
139
|
</span>
|
|
142
140
|
</div>
|
|
143
141
|
)}
|
|
@@ -157,16 +155,6 @@ export function ResourceInfoPanel({
|
|
|
157
155
|
</span>
|
|
158
156
|
</div>
|
|
159
157
|
)}
|
|
160
|
-
{generator && (
|
|
161
|
-
<div>
|
|
162
|
-
<span className="semiont-resource-info-panel__label">{t('generatedBy')}</span>
|
|
163
|
-
<span className="semiont-resource-info-panel__value">
|
|
164
|
-
{(Array.isArray(generator) ? generator : [generator])
|
|
165
|
-
.map(a => a.name)
|
|
166
|
-
.join(', ')}
|
|
167
|
-
</span>
|
|
168
|
-
</div>
|
|
169
|
-
)}
|
|
170
158
|
</div>
|
|
171
159
|
</div>
|
|
172
160
|
)}
|
|
@@ -8,6 +8,7 @@ import { getTagCategory, getTagSchemaId } from '@semiont/ontology';
|
|
|
8
8
|
import { useSemiont } from '../../../session/SemiontProvider';
|
|
9
9
|
import { useObservable } from '../../../hooks/useObservable';
|
|
10
10
|
import { useHoverEmitter } from '../../../hooks/useHoverEmitter';
|
|
11
|
+
import { renderAgentLabel } from './agent-label';
|
|
11
12
|
|
|
12
13
|
interface TagEntryProps {
|
|
13
14
|
tag: Annotation;
|
|
@@ -70,7 +71,9 @@ export function TagEntry({
|
|
|
70
71
|
</div>
|
|
71
72
|
{tag.generator && (
|
|
72
73
|
<div className="semiont-annotation-entry__metadata">
|
|
73
|
-
Via {
|
|
74
|
+
Via {Array.isArray(tag.generator)
|
|
75
|
+
? tag.generator.map(renderAgentLabel).join(', ')
|
|
76
|
+
: renderAgentLabel(tag.generator)}
|
|
74
77
|
</div>
|
|
75
78
|
)}
|
|
76
79
|
</div>
|
|
@@ -27,10 +27,8 @@ vi.mock('../../../../contexts/TranslationContext', () => ({
|
|
|
27
27
|
provenance: 'Provenance',
|
|
28
28
|
createdAt: 'Created',
|
|
29
29
|
modifiedAt: 'Modified',
|
|
30
|
-
creationMethod: 'How created',
|
|
31
30
|
attributedTo: 'Attributed to',
|
|
32
31
|
derivedFrom: 'Derived from',
|
|
33
|
-
generatedBy: 'Generated by',
|
|
34
32
|
};
|
|
35
33
|
return translations[key] || key;
|
|
36
34
|
}),
|
|
@@ -293,14 +291,6 @@ describe('ResourceInfoPanel Component', () => {
|
|
|
293
291
|
expect(screen.getByText('Modified')).toBeInTheDocument();
|
|
294
292
|
});
|
|
295
293
|
|
|
296
|
-
it('should render creationMethod when provided', () => {
|
|
297
|
-
renderWithEventBus(
|
|
298
|
-
<ResourceInfoPanel {...defaultProps} creationMethod="generated" />
|
|
299
|
-
);
|
|
300
|
-
expect(screen.getByText('How created')).toBeInTheDocument();
|
|
301
|
-
expect(screen.getByText('generated')).toBeInTheDocument();
|
|
302
|
-
});
|
|
303
|
-
|
|
304
294
|
it('should render a single agent attribution', () => {
|
|
305
295
|
renderWithEventBus(
|
|
306
296
|
<ResourceInfoPanel
|
|
@@ -336,25 +326,31 @@ describe('ResourceInfoPanel Component', () => {
|
|
|
336
326
|
expect(screen.getByText('urn:semiont:resource:abc123')).toBeInTheDocument();
|
|
337
327
|
});
|
|
338
328
|
|
|
339
|
-
it('
|
|
329
|
+
it('falls back to generator for attribution when wasAttributedTo is absent', () => {
|
|
340
330
|
renderWithEventBus(
|
|
341
331
|
<ResourceInfoPanel
|
|
342
332
|
{...defaultProps}
|
|
343
|
-
generator={{ name: 'Semiont AI' }}
|
|
333
|
+
generator={{ '@type': 'Software', name: 'Semiont AI' } as never}
|
|
344
334
|
/>
|
|
345
335
|
);
|
|
346
|
-
expect(screen.getByText('
|
|
336
|
+
expect(screen.getByText('Attributed to')).toBeInTheDocument();
|
|
347
337
|
expect(screen.getByText('Semiont AI')).toBeInTheDocument();
|
|
348
338
|
});
|
|
349
339
|
|
|
350
|
-
it('
|
|
340
|
+
it('renders Software peers as `${provider} ${model}` from structured fields', () => {
|
|
351
341
|
renderWithEventBus(
|
|
352
342
|
<ResourceInfoPanel
|
|
353
343
|
{...defaultProps}
|
|
354
|
-
generator={
|
|
344
|
+
generator={{
|
|
345
|
+
'@type': 'Software',
|
|
346
|
+
'@id': 'did:web:example.com:agents:ollama:gemma2%3A27b',
|
|
347
|
+
name: 'ignored',
|
|
348
|
+
provider: 'ollama',
|
|
349
|
+
model: 'gemma2:27b',
|
|
350
|
+
} as never}
|
|
355
351
|
/>
|
|
356
352
|
);
|
|
357
|
-
expect(screen.getByText('
|
|
353
|
+
expect(screen.getByText('ollama gemma2:27b')).toBeInTheDocument();
|
|
358
354
|
});
|
|
359
355
|
});
|
|
360
356
|
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { renderAgentLabel } from '../agent-label';
|
|
3
|
+
import type { components } from '@semiont/core';
|
|
4
|
+
|
|
5
|
+
type Agent = components['schemas']['Agent'];
|
|
6
|
+
|
|
7
|
+
describe('renderAgentLabel', () => {
|
|
8
|
+
describe('Software peers', () => {
|
|
9
|
+
it('composes `${provider} ${model}` from structured fields', () => {
|
|
10
|
+
const agent: Agent = {
|
|
11
|
+
'@type': 'Software',
|
|
12
|
+
'@id': 'did:web:example.com:agents:ollama:gemma2%3A27b',
|
|
13
|
+
name: 'unused-display-name',
|
|
14
|
+
provider: 'ollama',
|
|
15
|
+
model: 'gemma2:27b',
|
|
16
|
+
};
|
|
17
|
+
expect(renderAgentLabel(agent)).toBe('ollama gemma2:27b');
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('falls back to model alone when provider is absent', () => {
|
|
21
|
+
const agent: Agent = {
|
|
22
|
+
'@type': 'Software',
|
|
23
|
+
name: 'unused',
|
|
24
|
+
model: 'gpt-4',
|
|
25
|
+
};
|
|
26
|
+
expect(renderAgentLabel(agent)).toBe('gpt-4');
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('falls back to provider alone when model is absent', () => {
|
|
30
|
+
const agent: Agent = {
|
|
31
|
+
'@type': 'Software',
|
|
32
|
+
name: 'unused',
|
|
33
|
+
provider: 'anthropic',
|
|
34
|
+
};
|
|
35
|
+
expect(renderAgentLabel(agent)).toBe('anthropic');
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('falls back to name when both provider and model are absent', () => {
|
|
39
|
+
const agent: Agent = {
|
|
40
|
+
'@type': 'Software',
|
|
41
|
+
name: 'Some Software',
|
|
42
|
+
};
|
|
43
|
+
expect(renderAgentLabel(agent)).toBe('Some Software');
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
describe('Person and Organization peers', () => {
|
|
48
|
+
it('renders Person name', () => {
|
|
49
|
+
const agent: Agent = {
|
|
50
|
+
'@type': 'Person',
|
|
51
|
+
'@id': 'did:web:example.com:users:alice%40example.com',
|
|
52
|
+
name: 'Alice',
|
|
53
|
+
};
|
|
54
|
+
expect(renderAgentLabel(agent)).toBe('Alice');
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('renders Organization name', () => {
|
|
58
|
+
const agent: Agent = {
|
|
59
|
+
'@type': 'Organization',
|
|
60
|
+
name: 'Acme Corp',
|
|
61
|
+
};
|
|
62
|
+
expect(renderAgentLabel(agent)).toBe('Acme Corp');
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
describe('Legacy and degraded shapes', () => {
|
|
67
|
+
it('renders the stored `name` for legacy SoftwareAgent shape (graceful fallback)', () => {
|
|
68
|
+
// Pre-migration generator with @type='SoftwareAgent' and concatenated name
|
|
69
|
+
const legacy = {
|
|
70
|
+
'@type': 'SoftwareAgent',
|
|
71
|
+
name: 'worker-pool / ollama gemma4:26b',
|
|
72
|
+
worker: 'worker-pool',
|
|
73
|
+
inferenceProvider: 'ollama',
|
|
74
|
+
model: 'gemma4:26b',
|
|
75
|
+
} as unknown as Agent;
|
|
76
|
+
expect(renderAgentLabel(legacy)).toBe('worker-pool / ollama gemma4:26b');
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it('falls back to @id when name is empty', () => {
|
|
80
|
+
const agent = {
|
|
81
|
+
'@type': 'Person',
|
|
82
|
+
'@id': 'did:web:example.com:users:bob%40example.com',
|
|
83
|
+
name: '',
|
|
84
|
+
} as unknown as Agent;
|
|
85
|
+
expect(renderAgentLabel(agent)).toBe('did:web:example.com:users:bob%40example.com');
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it('falls back to "unknown" when nothing identifies the agent', () => {
|
|
89
|
+
const agent = { '@type': 'Person', name: '' } as unknown as Agent;
|
|
90
|
+
expect(renderAgentLabel(agent)).toBe('unknown');
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
});
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { components } from '@semiont/core';
|
|
2
|
+
|
|
3
|
+
type Agent = components['schemas']['Agent'];
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Compose a display label for an Agent at render time. Software peers
|
|
7
|
+
* read `${provider} ${model}` from their structured fields rather than
|
|
8
|
+
* a producer-side concatenated `name`. Person/Organization fall back
|
|
9
|
+
* to `name`. Unknown shapes fall back to `name` then to `@id`.
|
|
10
|
+
*/
|
|
11
|
+
export function renderAgentLabel(agent: Agent): string {
|
|
12
|
+
if (agent['@type'] === 'Software') {
|
|
13
|
+
const provider = (agent as { provider?: string }).provider;
|
|
14
|
+
const model = (agent as { model?: string }).model;
|
|
15
|
+
if (provider && model) return `${provider} ${model}`;
|
|
16
|
+
if (model) return model;
|
|
17
|
+
if (provider) return provider;
|
|
18
|
+
}
|
|
19
|
+
return agent.name || agent['@id'] || 'unknown';
|
|
20
|
+
}
|
|
@@ -559,7 +559,6 @@ export function ResourceViewerPage({
|
|
|
559
559
|
isArchived={resource.archived ?? false}
|
|
560
560
|
dateCreated={resource.dateCreated}
|
|
561
561
|
dateModified={resource.dateModified}
|
|
562
|
-
creationMethod={resource.creationMethod}
|
|
563
562
|
wasAttributedTo={resource.wasAttributedTo}
|
|
564
563
|
wasDerivedFrom={resource.wasDerivedFrom}
|
|
565
564
|
generator={resource.generator as components['schemas']['Agent'] | components['schemas']['Agent'][] | undefined}
|
package/translations/ar.json
CHANGED
|
@@ -25,10 +25,8 @@
|
|
|
25
25
|
"provenance": "المصدر والسلسلة",
|
|
26
26
|
"createdAt": "تاريخ الإنشاء",
|
|
27
27
|
"modifiedAt": "تاريخ التعديل",
|
|
28
|
-
"creationMethod": "طريقة الإنشاء",
|
|
29
28
|
"attributedTo": "منسوب إلى",
|
|
30
29
|
"derivedFrom": "مشتق من",
|
|
31
|
-
"generatedBy": "أُنشئ بواسطة",
|
|
32
30
|
"storageUri": "التخزين"
|
|
33
31
|
},
|
|
34
32
|
"CollaborationPanel": {
|
|
@@ -54,7 +52,6 @@
|
|
|
54
52
|
"history": "السجل",
|
|
55
53
|
"loading": "جارٍ التحميل...",
|
|
56
54
|
"user": "المستخدم",
|
|
57
|
-
"method": "الطريقة",
|
|
58
55
|
"viewOriginal": "عرض الأصل",
|
|
59
56
|
"viewAnnotation": "عرض التعليق التوضيحي: {{content}}",
|
|
60
57
|
"resourceCreated": "تم إنشاء المورد",
|
package/translations/bn.json
CHANGED
|
@@ -25,10 +25,8 @@
|
|
|
25
25
|
"provenance": "উৎস ও উদ্ভব",
|
|
26
26
|
"createdAt": "তৈরির তারিখ",
|
|
27
27
|
"modifiedAt": "পরিবর্তনের তারিখ",
|
|
28
|
-
"creationMethod": "তৈরির পদ্ধতি",
|
|
29
28
|
"attributedTo": "সম্পাদককৃত",
|
|
30
29
|
"derivedFrom": "থেকে উৎপন্ন",
|
|
31
|
-
"generatedBy": "তৈরিকারক",
|
|
32
30
|
"storageUri": "সঞ্চয়স্থান"
|
|
33
31
|
},
|
|
34
32
|
"CollaborationPanel": {
|
|
@@ -54,7 +52,6 @@
|
|
|
54
52
|
"history": "ইতিহাস",
|
|
55
53
|
"loading": "লোড হচ্ছে...",
|
|
56
54
|
"user": "ব্যবহারকারী",
|
|
57
|
-
"method": "পদ্ধতি",
|
|
58
55
|
"viewOriginal": "মূল দেখুন",
|
|
59
56
|
"viewAnnotation": "টীকা দেখুন: {{content}}",
|
|
60
57
|
"resourceCreated": "সম্পদ তৈরি হয়েছে",
|
package/translations/cs.json
CHANGED
|
@@ -25,10 +25,8 @@
|
|
|
25
25
|
"provenance": "Původ",
|
|
26
26
|
"createdAt": "Vytvořeno",
|
|
27
27
|
"modifiedAt": "Upraveno",
|
|
28
|
-
"creationMethod": "Způsob vytvoření",
|
|
29
28
|
"attributedTo": "Připsáno",
|
|
30
29
|
"derivedFrom": "Odvozeno z",
|
|
31
|
-
"generatedBy": "Vygenerováno pomocí",
|
|
32
30
|
"storageUri": "Úložiště"
|
|
33
31
|
},
|
|
34
32
|
"CollaborationPanel": {
|
|
@@ -54,7 +52,6 @@
|
|
|
54
52
|
"history": "Historie",
|
|
55
53
|
"loading": "Načítání...",
|
|
56
54
|
"user": "Uživatel",
|
|
57
|
-
"method": "Metoda",
|
|
58
55
|
"viewOriginal": "Zobrazit originál",
|
|
59
56
|
"viewAnnotation": "Zobrazit anotaci: {{content}}",
|
|
60
57
|
"resourceCreated": "Zdroj vytvořen",
|
package/translations/da.json
CHANGED
|
@@ -25,10 +25,8 @@
|
|
|
25
25
|
"provenance": "Oprindelse",
|
|
26
26
|
"createdAt": "Oprettet",
|
|
27
27
|
"modifiedAt": "Ændret",
|
|
28
|
-
"creationMethod": "Oprettelsesmetode",
|
|
29
28
|
"attributedTo": "Tilskrevet",
|
|
30
29
|
"derivedFrom": "Afledt af",
|
|
31
|
-
"generatedBy": "Genereret af",
|
|
32
30
|
"storageUri": "Lagring"
|
|
33
31
|
},
|
|
34
32
|
"CollaborationPanel": {
|
|
@@ -54,7 +52,6 @@
|
|
|
54
52
|
"history": "Historik",
|
|
55
53
|
"loading": "Indlæser...",
|
|
56
54
|
"user": "Bruger",
|
|
57
|
-
"method": "Metode",
|
|
58
55
|
"viewOriginal": "Se original",
|
|
59
56
|
"viewAnnotation": "Se annotering: {{content}}",
|
|
60
57
|
"resourceCreated": "Ressource oprettet",
|
package/translations/de.json
CHANGED
|
@@ -25,10 +25,8 @@
|
|
|
25
25
|
"provenance": "Herkunft",
|
|
26
26
|
"createdAt": "Erstellt",
|
|
27
27
|
"modifiedAt": "Geändert",
|
|
28
|
-
"creationMethod": "Erstellungsmethode",
|
|
29
28
|
"attributedTo": "Zugeschrieben",
|
|
30
29
|
"derivedFrom": "Abgeleitet von",
|
|
31
|
-
"generatedBy": "Erstellt von",
|
|
32
30
|
"storageUri": "Speicher"
|
|
33
31
|
},
|
|
34
32
|
"CollaborationPanel": {
|
|
@@ -54,7 +52,6 @@
|
|
|
54
52
|
"history": "Verlauf",
|
|
55
53
|
"loading": "Wird geladen...",
|
|
56
54
|
"user": "Benutzer",
|
|
57
|
-
"method": "Methode",
|
|
58
55
|
"viewOriginal": "Original ansehen",
|
|
59
56
|
"viewAnnotation": "Annotation ansehen: {{content}}",
|
|
60
57
|
"resourceCreated": "Ressource erstellt",
|
package/translations/el.json
CHANGED
|
@@ -25,10 +25,8 @@
|
|
|
25
25
|
"provenance": "Προέλευση",
|
|
26
26
|
"createdAt": "Δημιουργήθηκε",
|
|
27
27
|
"modifiedAt": "Τροποποιήθηκε",
|
|
28
|
-
"creationMethod": "Μέθοδος δημιουργίας",
|
|
29
28
|
"attributedTo": "Αποδίδεται σε",
|
|
30
29
|
"derivedFrom": "Παράγεται από",
|
|
31
|
-
"generatedBy": "Δημιουργήθηκε από",
|
|
32
30
|
"storageUri": "Αποθήκευση"
|
|
33
31
|
},
|
|
34
32
|
"CollaborationPanel": {
|
|
@@ -54,7 +52,6 @@
|
|
|
54
52
|
"history": "Ιστορικό",
|
|
55
53
|
"loading": "Φόρτωση...",
|
|
56
54
|
"user": "Χρήστης",
|
|
57
|
-
"method": "Μέθοδος",
|
|
58
55
|
"viewOriginal": "Προβολή πρωτοτύπου",
|
|
59
56
|
"viewAnnotation": "Προβολή σχολιασμού: {{content}}",
|
|
60
57
|
"resourceCreated": "Δημιουργία Πόρου",
|
package/translations/en.json
CHANGED
|
@@ -26,10 +26,8 @@
|
|
|
26
26
|
"provenance": "Provenance",
|
|
27
27
|
"createdAt": "Created",
|
|
28
28
|
"modifiedAt": "Modified",
|
|
29
|
-
"creationMethod": "How created",
|
|
30
29
|
"attributedTo": "Attributed to",
|
|
31
|
-
"derivedFrom": "Derived from"
|
|
32
|
-
"generatedBy": "Generated by"
|
|
30
|
+
"derivedFrom": "Derived from"
|
|
33
31
|
},
|
|
34
32
|
"CollaborationPanel": {
|
|
35
33
|
"title": "Collaboration",
|
|
@@ -54,7 +52,6 @@
|
|
|
54
52
|
"history": "History",
|
|
55
53
|
"loading": "Loading...",
|
|
56
54
|
"user": "User",
|
|
57
|
-
"method": "Method",
|
|
58
55
|
"viewOriginal": "View original",
|
|
59
56
|
"viewAnnotation": "View annotation: {{content}}",
|
|
60
57
|
"resourceCreated": "Created Resource",
|
|
@@ -361,4 +358,4 @@
|
|
|
361
358
|
"searching": "Searching...",
|
|
362
359
|
"search": "Search"
|
|
363
360
|
}
|
|
364
|
-
}
|
|
361
|
+
}
|
package/translations/es.json
CHANGED
|
@@ -25,10 +25,8 @@
|
|
|
25
25
|
"provenance": "Procedencia",
|
|
26
26
|
"createdAt": "Creado",
|
|
27
27
|
"modifiedAt": "Modificado",
|
|
28
|
-
"creationMethod": "Cómo se creó",
|
|
29
28
|
"attributedTo": "Atribuido a",
|
|
30
29
|
"derivedFrom": "Derivado de",
|
|
31
|
-
"generatedBy": "Generado por",
|
|
32
30
|
"storageUri": "Almacenamiento"
|
|
33
31
|
},
|
|
34
32
|
"CollaborationPanel": {
|
|
@@ -54,7 +52,6 @@
|
|
|
54
52
|
"history": "Historial",
|
|
55
53
|
"loading": "Cargando...",
|
|
56
54
|
"user": "Usuario",
|
|
57
|
-
"method": "Método",
|
|
58
55
|
"viewOriginal": "Ver original",
|
|
59
56
|
"viewAnnotation": "Ver anotación: {{content}}",
|
|
60
57
|
"resourceCreated": "Recurso Creado",
|
package/translations/fa.json
CHANGED
|
@@ -25,10 +25,8 @@
|
|
|
25
25
|
"provenance": "منشأ",
|
|
26
26
|
"createdAt": "ایجاد شده",
|
|
27
27
|
"modifiedAt": "ویرایش شده",
|
|
28
|
-
"creationMethod": "روش ایجاد",
|
|
29
28
|
"attributedTo": "منتسب به",
|
|
30
29
|
"derivedFrom": "مشتق از",
|
|
31
|
-
"generatedBy": "تولیدشده توسط",
|
|
32
30
|
"storageUri": "ذخیرهسازی"
|
|
33
31
|
},
|
|
34
32
|
"CollaborationPanel": {
|
|
@@ -54,7 +52,6 @@
|
|
|
54
52
|
"history": "تاریخچه",
|
|
55
53
|
"loading": "در حال بارگذاری...",
|
|
56
54
|
"user": "کاربر",
|
|
57
|
-
"method": "روش",
|
|
58
55
|
"viewOriginal": "مشاهده اصلی",
|
|
59
56
|
"viewAnnotation": "مشاهده حاشیهنویسی: {{content}}",
|
|
60
57
|
"resourceCreated": "منبع ایجاد شد",
|