@glossarist/concept-browser 0.7.91 → 0.7.93
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/package.json +2 -2
- package/src/__tests__/components/GenericRelationList.test.ts +147 -0
- package/src/__tests__/components/GenericRelationList.test.ts.bak +147 -0
- package/src/__tests__/composables/use-concept-edges-v2.test.ts +22 -23
- package/src/__tests__/composables/use-concept-edges-v2.test.ts.bak +166 -0
- package/src/__tests__/model-bridge-partitive-migration.test.ts +2 -2
- package/src/__tests__/wire-keys.test.ts +1 -1
- package/src/__tests__/wire-keys.test.ts.bak +65 -0
- package/src/adapters/model-bridge/concept.ts +12 -2
- package/src/adapters/model-bridge/hyperedge.ts +103 -0
- package/src/adapters/model-bridge/jsonld-types.ts +3 -0
- package/src/adapters/non-verbal/glossarist-augment.d.ts +77 -46
- package/src/adapters/types.ts +27 -0
- package/src/adapters/wire-keys.ts +4 -0
- package/src/components/ConceptDetail.vue +10 -0
- package/src/components/GenericRelationList.vue +176 -0
- package/src/components/PartitiveRelationList.vue +2 -19
- package/src/composables/use-concept-edges.ts +56 -52
- package/src/utils/resolve-designation.ts +50 -0
- package/src/views/ConceptView.vue +1 -1
|
@@ -4,6 +4,8 @@ import type { Router } from 'vue-router';
|
|
|
4
4
|
// Import the MECE-augmented types from glossarist/models (extended by
|
|
5
5
|
// src/adapters/non-verbal/glossarist-augment.d.ts).
|
|
6
6
|
import type { Concept, RelatedConcept, ConceptRef } from 'glossarist';
|
|
7
|
+
import { PartitiveHyperedge } from 'glossarist';
|
|
8
|
+
import { GenericHyperedge } from 'glossarist/models';
|
|
7
9
|
import type {
|
|
8
10
|
PartitiveRelation as GlsPartitiveRelation,
|
|
9
11
|
PartitiveMember as GlsPartitiveMember,
|
|
@@ -13,9 +15,11 @@ import type {
|
|
|
13
15
|
GraphEdge,
|
|
14
16
|
PartitiveRelationWire,
|
|
15
17
|
PartitiveMemberWire,
|
|
18
|
+
GenericRelationWire,
|
|
16
19
|
} from '../adapters/types';
|
|
17
20
|
import { getFactory } from '../adapters/factory';
|
|
18
21
|
import { conceptUri } from '../adapters/model-bridge';
|
|
22
|
+
import { resolveDesignation } from '../utils/resolve-designation';
|
|
19
23
|
import { UriRouter } from '../adapters/UriRouter';
|
|
20
24
|
import { useVocabularyStore } from '../stores/vocabulary';
|
|
21
25
|
import { useDsStyle } from '../utils/dataset-style';
|
|
@@ -111,25 +115,7 @@ export function useConceptEdges(
|
|
|
111
115
|
* IDs like '1.3'.
|
|
112
116
|
*/
|
|
113
117
|
function designationFor(uri: string): string {
|
|
114
|
-
|
|
115
|
-
if (node) {
|
|
116
|
-
const des = node.designations[locale.value]
|
|
117
|
-
|| node.designations.eng
|
|
118
|
-
|| Object.values(node.designations)[0];
|
|
119
|
-
if (des) return des;
|
|
120
|
-
}
|
|
121
|
-
const resolution = factory.resolve(uri);
|
|
122
|
-
if (resolution.type === 'internal') {
|
|
123
|
-
const adapter = store.datasets.get(resolution.registerId);
|
|
124
|
-
const entry = adapter?.getIndexEntry(resolution.conceptId);
|
|
125
|
-
if (entry) {
|
|
126
|
-
const des = entry.designations[locale.value]
|
|
127
|
-
|| entry.designations.eng
|
|
128
|
-
|| Object.values(entry.designations)[0];
|
|
129
|
-
if (des) return des;
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
return resolution.type === 'internal' ? resolution.conceptId : uri;
|
|
118
|
+
return resolveDesignation(uri, store, factory, locale.value);
|
|
133
119
|
}
|
|
134
120
|
|
|
135
121
|
function edgeBadgeColor(type: string, direction: 'out' | 'in'): string {
|
|
@@ -174,42 +160,59 @@ export function useConceptEdges(
|
|
|
174
160
|
});
|
|
175
161
|
});
|
|
176
162
|
|
|
177
|
-
// Concept-level
|
|
178
|
-
// Reads the glossarist-js
|
|
179
|
-
// and projects
|
|
180
|
-
//
|
|
181
|
-
//
|
|
182
|
-
|
|
163
|
+
// Concept-level n-ary hyperedge relations (ISO 704 one-to-many
|
|
164
|
+
// decompositions). Reads the glossarist-js unified `concept.relations`
|
|
165
|
+
// array and projects PartitiveHyperedge → PartitiveRelationWire,
|
|
166
|
+
// GenericHyperedge → GenericRelationWire for display.
|
|
167
|
+
//
|
|
168
|
+
// glossarist 0.4.33+ exposes a unified `.relations` array; type
|
|
169
|
+
// discrimination is via instanceof.
|
|
170
|
+
function projectHyperedge(rel: any): PartitiveRelationWire | GenericRelationWire | null {
|
|
183
171
|
const source = conceptUriValue.value;
|
|
184
|
-
const
|
|
185
|
-
return
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
const
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
presence: readPresence(m),
|
|
196
|
-
count: readCount(m),
|
|
197
|
-
isDelimiting: readIsDelimiting(m),
|
|
198
|
-
};
|
|
199
|
-
})
|
|
200
|
-
.filter((m: PartitiveMemberWire | null): m is PartitiveMemberWire => m !== null);
|
|
201
|
-
if (partitives.length === 0) return null;
|
|
202
|
-
|
|
203
|
-
return {
|
|
204
|
-
source,
|
|
205
|
-
comprehensive,
|
|
206
|
-
partitives,
|
|
207
|
-
completeness: rel.completeness,
|
|
208
|
-
criterion: rel.criterion ?? undefined,
|
|
209
|
-
register: registerId.value,
|
|
172
|
+
const comprehensive = resolveConceptRefUri(rel.comprehensive);
|
|
173
|
+
if (!comprehensive) return null;
|
|
174
|
+
const isGeneric = rel instanceof GenericHyperedge;
|
|
175
|
+
const members: any[] = (rel.members ?? rel.partitives ?? [])
|
|
176
|
+
.map((m: any): any | null => {
|
|
177
|
+
const uri = resolveConceptRefUri(m.ref);
|
|
178
|
+
if (!uri || uri === source) return null;
|
|
179
|
+
const base: any = {
|
|
180
|
+
uri,
|
|
181
|
+
presence: readPresence(m),
|
|
182
|
+
count: readCount(m),
|
|
210
183
|
};
|
|
184
|
+
if (isGeneric) {
|
|
185
|
+
base.delimitingCharacteristic = m.delimitingCharacteristic;
|
|
186
|
+
} else {
|
|
187
|
+
base.isDelimiting = readIsDelimiting(m);
|
|
188
|
+
}
|
|
189
|
+
return base;
|
|
211
190
|
})
|
|
212
|
-
.filter((
|
|
191
|
+
.filter((m: any | null): m is any => m !== null);
|
|
192
|
+
if (members.length === 0) return null;
|
|
193
|
+
return {
|
|
194
|
+
source,
|
|
195
|
+
comprehensive,
|
|
196
|
+
members,
|
|
197
|
+
partitives: members,
|
|
198
|
+
completeness: rel.completeness,
|
|
199
|
+
criterion: rel.criterion ?? undefined,
|
|
200
|
+
register: registerId.value,
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
const conceptPartitiveRelations = computed<PartitiveRelationWire[]>(() => {
|
|
205
|
+
return (concept.value.relations as any[] ?? [])
|
|
206
|
+
.filter(r => r instanceof PartitiveHyperedge)
|
|
207
|
+
.map(projectHyperedge)
|
|
208
|
+
.filter((r): r is PartitiveRelationWire => r !== null);
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
const conceptGenericRelations = computed<GenericRelationWire[]>(() => {
|
|
212
|
+
return (concept.value.relations as any[] ?? [])
|
|
213
|
+
.filter(r => r instanceof GenericHyperedge)
|
|
214
|
+
.map(projectHyperedge)
|
|
215
|
+
.filter((r): r is GenericRelationWire => r !== null);
|
|
213
216
|
});
|
|
214
217
|
|
|
215
218
|
function resolveConceptRefUri(ref: ConceptRef | null): string | null {
|
|
@@ -307,6 +310,7 @@ export function useConceptEdges(
|
|
|
307
310
|
inverseEdgeType,
|
|
308
311
|
conceptRelated,
|
|
309
312
|
conceptPartitiveRelations,
|
|
313
|
+
conceptGenericRelations,
|
|
310
314
|
resolveRelatedRef,
|
|
311
315
|
getResolvedRef,
|
|
312
316
|
relatedLabel,
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve a concept URI to its display designation (term string).
|
|
3
|
+
*
|
|
4
|
+
* Single SSOT for the designation fallback chain used by:
|
|
5
|
+
* - PartitiveRelationList.vue
|
|
6
|
+
* - GenericRelationList.vue
|
|
7
|
+
* - use-concept-edges.ts (designationFor method)
|
|
8
|
+
*
|
|
9
|
+
* Previously each site had its own copy with subtle divergences (one
|
|
10
|
+
* used `entry.titles`, another used `entry.designations` — the former
|
|
11
|
+
* is a bug since ConceptSummary has no `titles` property).
|
|
12
|
+
*
|
|
13
|
+
* Fallback chain:
|
|
14
|
+
* 1. BFS graph node (already loaded as a neighbor) → locale → eng → any
|
|
15
|
+
* 2. Dataset adapter index entry → designations[locale] → eng → any
|
|
16
|
+
* 3. Concept ID (for internal URIs) or raw URI (for external)
|
|
17
|
+
*/
|
|
18
|
+
import type { useVocabularyStore } from '../stores/vocabulary';
|
|
19
|
+
import type { AdapterFactory } from '../adapters/factory';
|
|
20
|
+
|
|
21
|
+
type VocabularyStore = ReturnType<typeof useVocabularyStore>;
|
|
22
|
+
type Factory = AdapterFactory;
|
|
23
|
+
|
|
24
|
+
export function resolveDesignation(
|
|
25
|
+
uri: string,
|
|
26
|
+
store: VocabularyStore,
|
|
27
|
+
factory: Factory,
|
|
28
|
+
currentLocale: string,
|
|
29
|
+
): string {
|
|
30
|
+
const node = store.graph.getNode(uri);
|
|
31
|
+
if (node) {
|
|
32
|
+
const des = node.designations[currentLocale]
|
|
33
|
+
|| node.designations.eng
|
|
34
|
+
|| Object.values(node.designations)[0];
|
|
35
|
+
if (des) return des;
|
|
36
|
+
}
|
|
37
|
+
const resolution = factory.resolve(uri);
|
|
38
|
+
if (resolution.type === 'internal') {
|
|
39
|
+
const adapter = store.datasets.get(resolution.registerId);
|
|
40
|
+
const entry = adapter?.getIndexEntry(resolution.conceptId);
|
|
41
|
+
if (entry) {
|
|
42
|
+
const des = entry.designations[currentLocale]
|
|
43
|
+
|| entry.designations.eng
|
|
44
|
+
|| Object.values(entry.designations)[0];
|
|
45
|
+
if (des) return des;
|
|
46
|
+
}
|
|
47
|
+
return resolution.conceptId;
|
|
48
|
+
}
|
|
49
|
+
return uri;
|
|
50
|
+
}
|
|
@@ -89,7 +89,7 @@ const partitiveRelationsForSphere = computed<PartitiveRelationWire[]>(() => {
|
|
|
89
89
|
if (uri === sourceUri) return null;
|
|
90
90
|
const presence: PartitivePresence = member.presence;
|
|
91
91
|
const count: PartitiveCount = member.count;
|
|
92
|
-
const isDelimiting = member.
|
|
92
|
+
const isDelimiting = (member as any).is_delimiting === true;
|
|
93
93
|
return { uri, presence, count, isDelimiting };
|
|
94
94
|
})
|
|
95
95
|
.filter((x): x is PartitiveMemberWire => x !== null);
|