@myrmidon/cadmus-refs-asserted-ids 10.0.17 β†’ 11.0.1

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/README.md CHANGED
@@ -8,13 +8,16 @@ This project was generated using [Angular CLI](https://github.com/angular/angula
8
8
  - [External IDs](#external-ids)
9
9
  - [Internal IDs](#internal-ids)
10
10
  - [ID Components](#id-components)
11
- - [AssertedIdComponent](#assertedidcomponent)
12
- - [Configuring Asserted ID](#configuring-asserted-id)
13
- - [AssertedIdsComponent](#assertedidscomponent)
14
- - [PinTargetLookupComponent](#pintargetlookupcomponent)
15
- - [Configuring the Target ID Editor](#configuring-the-target-id-editor)
16
- - [Asserted Composite ID](#asserted-composite-id)
17
- - [Asserted Composite IDs](#asserted-composite-ids)
11
+ - [AssertedCompositeIdComponent](#assertedcompositeidcomponent)
12
+ - [AssertedCompositeIdsComponent](#assertedcompositeidscomponent)
13
+ - [PinTargetLookupComponent](#pintargetlookupcomponent)
14
+ - [Configuring Asserted ID](#configuring-asserted-id)
15
+ - [Configuring Lookup Providers](#configuring-lookup-providers)
16
+ - [Configuring Taxonomy Store](#configuring-taxonomy-store)
17
+ - [Defining Index Lookups](#defining-index-lookups)
18
+ - [Legacy Components](#legacy-components)
19
+ - [AssertedIdComponent](#assertedidcomponent)
20
+ - [AssertedIdsComponent](#assertedidscomponent)
18
21
  - [History](#history)
19
22
  - [10.0.14](#10014)
20
23
  - [10.0.13](#10013)
@@ -31,6 +34,8 @@ This project was generated using [Angular CLI](https://github.com/angular/angula
31
34
 
32
35
  The asserted ID and asserted composite IDs bricks provide a way to include _external_ or _internal_ references to resource identifiers, whatever their type and origin. These components are the foundation for pin-based links in links part and links fragment types, as they provide both external and internal links, optionally accompanied by an assertion.
33
36
 
37
+ Additionally, since version 10.1.0 they can target also editable taxonomies from the [Cadmus Taxonomies Store](https://vedph.github.io/cadmus-doc/models/taxonomies.html).
38
+
34
39
  ## External IDs
35
40
 
36
41
  External IDs are provided by users, either manually or with the aid of lookup services. Cadmus already provides a set of builtin lookup providers for popular web APIs like VIAF, DBPedia, Geonames, and WHG, and you can add as many as you want.
@@ -46,27 +51,28 @@ So, in its most complete model an external ID has:
46
51
  - an optional scope.
47
52
  - an optional tag, which can be used to group or classify IDs in some way.
48
53
 
49
- ## Internal IDs
50
-
51
- Internal IDs are human-friendly identifiers connected to any data in the Cadmus database. They can refer to an item as a whole, or to a specific part or fragment of it, or to a specific feature inside a part or fragment.
54
+ An external ID can also come from a taxonomy. In this case:
52
55
 
53
- In most cases, human users prefer friendly identifiers, unique only in the context of their editing environment (which is what is present to the user's mind when entering data). These identifiers in Cadmus are named **EID**s (=_entity IDs_), and may be found scattered among parts or fragments via pins, or linked to whole items via a metadata part.
56
+ - the GID is built as `@TX:TREEID/NODEKEY` where `@TX:` is a fixed prefix (meaning the GID refers to a taxonomy), `TREEID` is the tree's ID (an arbitrary ID), and `NODEKEY` the node's key. The node's key is a string unique only within its tree; that's why we build a global ID by prefixing its tree ID. Internally, in the taxonomies store each ID has a unique numeric ID, but this is just an implementation detail and nodes are always referred by their key.
57
+ - the label comes from the node's label.
54
58
 
55
- >Of course, all Cadmus data objects (items, parts and fragments) have their own globally unique identifier, which is an opaque GUID like `401267e7-282c-40e6-8f47-67be54382b07`. EIDs instead provide human-friendly identifiers, e.g. just like the IDs you type in a TEI document. Additionally, they can be used to target a specific feature inside a part or fragment, via search pins provided by it.
59
+ ## Internal IDs
56
60
 
57
- **Item EID**s are just human-friendly aliases used to refer to a Cadmus item as a whole. Whenever we want to assign a human-friendly ID to the _item_ itself, rather than referring to it by its GUID, the conventional method relies on the generic _metadata part_, which allows users entering any number of arbitrarily defined name=value pairs. So, a user might enter a pair like e.g. `eid=vat_lat_123`, and use it as the human friendly identifier for a manuscript item corresponding to Vat.Lat.123.
61
+ Every Cadmus object (item, part or fragment) has its own own _globally unique identifier_, which is an opaque GUID like `401267e7-282c-40e6-8f47-67be54382b07`. These identify the objects; but the framework is completely agnostic with reference to their model: the item is just an empty box, while objects put in it (parts or fragments) can have any model. This is a requirement for those objects to be composable and reusable in the context of an open-ended, dynamic modeling.
58
62
 
59
- Ultimately, even an item EID, just like any other EID is just based on a **search pin**. In Cadmus, any part or fragment in an item provides any number of _search pins_, which essentially are name=value pairs, used for a simple search during editing.
63
+ The only way Cadmus has to link a part or an entry inside it is via "**pins**", i.e. name=value pairs which the part or fragment exposes in the index whenever it is saved. The part or fragment is the only component which knows what is inside its model; for the rest of the system, it is (and must be) a blackbox. Therefore, these pins are assigned by the object itself by reflecting on its own data, and act as target points for internal links.
60
64
 
61
- Each pin name is unique only in the context of the part or fragment defining it, so that pin design is not constrained; yet, a pin can easily be turned into a globally unique identifier by adding to it other data.
65
+ Typically, according to the nature of each model, some pins can be designed to be used as anchor points and refer to the object as a whole, or to an entry in its model, when the model contains multiple entries. For instance, in a part with a list of manuscript [decorations](https://github.com/vedph/cadmus-codicology/blob/master/docs/cod-decorations.md), there are multiple entries, one per decoration; and one might want to target a specific decoration. To this end, each decoration has an `eid` property which represents a human-friendly, arbitrary string used to identify it, like `angel`. These identifiers are like the IDs you may type in a TEI document using the `@xml:id` attribute: they are short and human-friendly, and also allow to deeply link a subset of the object's data.
62
66
 
63
- For instance, given that every part or fragment has its own globally unique ID, you can just prepend it to the pin name to get a globally unique internal ID pointing to a specific feature of a specific part or fragment. Thus, users just enter pins as arbitrary, easy to use strings, when entering data; but the general architecture also provides a way for making them globally unique.
67
+ So, internal IDs are human-friendly identifiers connected to any data in the Cadmus database. They can refer to:
64
68
 
65
- >This is how the in-editor search is implemented, and a similar mechanism is also used when mapping entities from parts into a semantic graph (via mapping rules).
69
+ - a specific _internal entry_ inside a part or fragment containing multiple entries (typically via a property conventionally named `eid`);
70
+ - a specific _part or fragment_ (via any of its pins designed or chosen to represent the object as a whole);
71
+ - an _item_ as a whole (via its [metadata part](https://github.com/vedph/cadmus-general/blob/master/docs/metadata.md)'s `eid` metadatum): this is more tricky, because items are just containers of parts and fragments. So, they have no pins at all on their own, except for those connected to their fixed set of metadata (like title), which usually are not convenient as identifiers, unless you have a well-defined convention for assigning titles. So, conventionally the metadata part is used to provide a human-friendly ID for the item as a whole: whenever the item contains that part, and that part has a metadatum with name=`eid`, this is assumed to be the item's human-friendly ID. So, a user might enter a metadatum like e.g. `eid`=`vat_lat_123`, and use it as the human friendly identifier for a manuscript item corresponding to Vat.Lat.123.
66
72
 
67
- For instance, say a decorations part in a manuscript item collects a number of decorations; for each one, it might define an arbitrary EID (like e.g. `angel1`) used to identify it among the others, in the context of that part.
73
+ Thus, ultimately all EIDs are based on a search pins. Each _pin name is unique only in the context of the part or fragment defining it_, so that pin design is not constrained; yet, a pin can easily be turned into a globally unique identifier by adding to it other data. For instance, given that every part or fragment has its own globally unique ID, you can just prepend it to the pin name to get a globally unique internal ID pointing to a specific feature of a specific part or fragment. Thus, we get the best of both worlds: when entering data, users are free to define pins as arbitrary, easy to use strings (e.g. "angel1", "angel2", "devil", etc.); but the general architecture also provides a way for making them globally unique, so they do not have to worry about that. All what they need to care about is that they are unique within the part or fragment they are editing.
68
74
 
69
- When filling the decorations part with data, users just ensure that this EID is unique in the context of the list they are editing; in other terms, no other decoration in that part will have `angel1` as its ID, while it might happen that `angel1` is used somewhere else in another part. Yet, should we be in need of a non-scoped, unique ID, we could easily build it by assembling together the EID with its part/item IDs, which by definition are globally unique (being GUIDs).
75
+ ---
70
76
 
71
77
  ## ID Components
72
78
 
@@ -79,154 +85,78 @@ According to the scenario illustrated above, the basic requirements for ID compo
79
85
 
80
86
  >πŸ‘‰ The demo found in this workspace uses a [mock data service](../../../src/app/services/mock-item.service.ts) instead of the real one, which provides a minimal set of data and functions, just required for the components to function.
81
87
 
82
- Various components from this library provide a different level of complexity, so you can pick the one which best fits your purposes; in general, the most powerful and versatile ID picker is represented by the [asserted composite ID](#asserted-composite-id), which can be used for both external and internal IDs, with full lookup support from lookup providers in either case.
83
-
84
- ## AssertedIdComponent
85
-
86
- - πŸ”‘ `AssertedIdComponent`
87
- - 🚩 `cadmus-refs-asserted-id`
88
- - ▢️ input:
89
- - `id` (`AssertedId? | null`)
90
- - `noEidLookup` (`boolean?`)
91
- - `hasSubmit` (`boolean?`)
92
- - πŸ“š thesauri:
93
- - `asserted-id-scopes` (for `idScopeEntries`)
94
- - `asserted-id-tags` (for `idTagEntries`).
95
- - `assertion-tags` (for `assTagEntries`).
96
- - `doc-reference-types` (for `refTypeEntries`).
97
- - `doc-reference-tags` (for `refTagEntries`).
98
- - `asserted-id-features` (for `featureEntries`).
99
- - πŸ”₯ output:
100
- - `idChange` (`AssertedId`)
101
- - `editorClose`
102
- - `extMoreRequest` (`RefLookupSetEvent`): the user requested more about the current external lookup source.
103
-
104
- The asserted ID component allows editing a simple model representing a generic ID with an optional assertion. The ID has:
105
-
106
- - **value**: the ID itself.
107
- - **scope**: the context the ID originates from (e.g. an ontology, a repository, a website, etc.).
108
- - an optional **tag**, used to group or classify the ID.
109
- - an optional set of **features**, from a hierarchical thesaurus. For instance, these could be the role(s) of a person linked to an object, like customer, seller, creator, etc.
110
- - an optional **note**.
111
- - an optional **assertion**, used to define the uncertainty level of the assignment of this ID to the context it applies to.
112
-
113
- The asserted ID component provides an internal lookup mechanism based on data pins and metadata conventions. When users want to add an ID referring to some internal entity, either found in a part or corresponding to an item, he just has to pick the type of desired lookup (when more than a single lookup search definition is present), and type some characters to get the first N pins starting with these characters; he can then pick one from the list. Once a pin value is picked, the lookup control shows all the relevant data which can be used as components for the ID to build:
114
-
115
- - the item GUID.
116
- - the item title.
117
- - the part GUID.
118
- - the part type ID.
119
- - the item's metadata part entries.
120
-
121
- The user can then use buttons to append each of these components to the ID being built, and/or variously edit it. When he's ok with the ID, he can then use it as the reference ID being edited.
122
-
123
- ### Configuring Asserted ID
124
-
125
- The asserted ID component internally uses a scoped pin lookup component (`ScopedPinLookupComponent`) to provide a list of pin-based searches with a lookup control. Whenever the user picks a pin value, he gets the details about its item and part, and item's metadata part, if any. He can then use these data to build a globally unique internal identifier by variously assembling these components.
126
-
127
- You can use the scoped ID lookup control to add a pin-based lookup for any entity in your own UI:
128
-
129
- (1) ensure to import the component (`ScopedPinLookupComponent`).
130
-
131
- (2) add a lookup control to your UI, like this:
132
-
133
- ```html
134
- <!-- lookup -->
135
- <cadmus-scoped-pin-lookup *ngIf="!noLookup" (idPick)="onIdPick($event)"/>
136
- ```
137
-
138
- In this sample, my UI has a `noLookup` property which can be used to hide the lookup if not required:
139
-
140
- ```ts
141
- @Input()
142
- public noLookup?: boolean;
143
-
144
- public onIdPick(id: string): void {
145
- // TODO: set your control's value, e.g.:
146
- // this.myId.setValue(id);
147
- // this.myId.updateValueAndValidity();
148
- // this.myId.markAsDirty();
149
- }
150
- ```
151
-
152
- (3) in your app's `index-lookup-definitions.ts` file, add the required lookup definitions. Each definition has a conventional key, and is an object with part type ID for the lookup scope, and pin name, e.g.:
88
+ Various components from this library provide a different level of complexity, so you can pick the one which best fits your purposes; in general, the most powerful and versatile ID picker is represented by the [asserted composite ID](#assertedcompositeidcomponent) and its multiple-targets counterpart [asserted composite IDs](#assertedcompositeidscomponent), which can be used for both external and internal IDs and editable taxonomies, with full lookup support. Other components in this library should be considered obsolete.
153
89
 
154
- ```ts
155
- import { IndexLookupDefinitions } from '@myrmidon/cadmus-core';
156
- import {
157
- METADATA_PART_TYPEID,
158
- HISTORICAL_EVENTS_PART_TYPEID,
159
- } from '@myrmidon/cadmus-part-general-ui';
160
-
161
- export const INDEX_LOOKUP_DEFINITIONS: IndexLookupDefinitions = {
162
- // item's metadata
163
- meta_eid: {
164
- typeId: METADATA_PART_TYPEID,
165
- name: 'eid',
166
- },
167
- // general parts
168
- event_eid: {
169
- typeId: HISTORICAL_EVENTS_PART_TYPEID,
170
- name: 'eid',
171
- },
172
- // ... etc.
173
- };
174
- ```
175
-
176
- >Note that while pin name and type will not be displayed to the end user, the key of each definition will. Unless you have a single definition, the lookup component will display a dropdown list with all the available keys, so that the user can select the lookup's scope. So, use short, yet meaningful keys here, like in the above sample (`meta_eid`, `event_eid`).
177
-
178
- ## AssertedIdsComponent
179
-
180
- An editable list of asserted IDs.
90
+ ### AssertedCompositeIdComponent
181
91
 
182
- - πŸ”‘ `AssertedIdsComponent`
183
- - 🚩 `cadmus-refs-asserted-ids`
92
+ - πŸ”‘ `AssertedCompositeIdComponent`
93
+ - 🚩 `cadmus-refs-asserted-composite-id`
184
94
  - ▢️ input:
185
- - `ids` (`AssertedId[]`)
95
+ - `id` (`AssertedId`)
96
+ - `pinByTypeMode` (`boolean?`)
97
+ - `canSwitchMode` (`boolean?`)
98
+ - `canEditTarget` (`boolean?`)
99
+ - `defaultPartTypeKey` (`string?|null`)
100
+ - `lookupDefinitions` (`IndexLookupDefinitions?`)
186
101
  - πŸ“š thesauri:
187
102
  - `asserted-id-scopes` (for `idScopeEntries`)
188
103
  - `asserted-id-tags` (for `idTagEntries`)
189
104
  - `assertion-tags` (for `assTagEntries`)
190
105
  - `doc-reference-types` (for `refTypeEntries`)
191
106
  - `doc-reference-tags` (for `refTagEntries`)
192
- - `asserted-id-features` (for `featureEntries`).
193
- - πŸ”₯ output:
194
- - `idsChange` (`AssertedId[]`)
195
-
196
- ## PinTargetLookupComponent
197
-
198
- - ▢️ input:
199
- - `target` (`PinTarget? | null`)
200
- - `pinByTypeMode` (`boolean?`)
201
- - `canSwitchMode` (`boolean?`)
202
- - `canEditTarget` (`boolean?`)
203
- - `defaultPartTypeKey` (`string?|null`)
204
- - `lookupDefinitions` (`IndexLookupDefinitions?`)
205
- - `extLookupConfigs` (`RefLookupConfig[]`): the configurations of external lookup providers, if any.
206
- - πŸ”₯ output:
207
- - `targetChange` (`PinTarget`)
107
+ - ⚑ output:
108
+ - `idChange` (`AssertedId[]`)
208
109
  - `editorClose`
110
+ - `extMoreRequest` (`RefLookupSetEvent`): the user requested more about the current external lookup source.
209
111
 
210
- This component is used to edit an internal or external ID via lookup, and is the core of the [asserted composite ID](#asserted-composite-id) component:
112
+ This is the most complete ID reference, which can be used for both external and internal IDs, providing full lookup in either cases. Each asserted composite ID has:
211
113
 
212
- - for **external** IDs, you can enter the ID and its human-friendly label manually, or get them from any number of lookup providers (e.g. VIAF, geonames, etc.).
114
+ - a `target`, representing the pin-based target of the ID. The target model has these properties:
115
+ - a global ID, `gid`, built from the pin or manually defined;
116
+ - a human-friendly `label` for the target, built from the pin or manually defined;
117
+ - for _internal_ links only:
118
+ - `itemId` for the item the pin derives from;
119
+ - when the pin derives from a part, an optional `partId`, `partTypeId`, `roleId`;
120
+ - the `name` and `value` of the pin.
121
+ - an optional `scope`, representing the context the ID originates from (e.g. an ontology, a repository, a website, etc.).
122
+ - an optional `tag`, possibly used to group or classify the ID.
123
+ - an optional `assertion`, possibly used to define the uncertainty level of the assignment of this ID to the context it applies to.
213
124
 
214
- - for **internal** IDs, your lookup is based on search pins.
125
+ To distinguish among link targets:
215
126
 
216
- - for **both** external and internal IDs, you can optionally specify a scope (usually defining the context of the ID, like VIAF or DBPedia, or your own Cadmus database) and a tag (an arbitrary string for grouping or tagging the ID in some way).
127
+ - when the ID is **external**, the only properties set for the target model are `gid` (=the ID) and `label`. So, they never have the `name` property, which instead is required for internal links.
128
+ - when the ID is a **taxonomy** node, it is just like an external link, but the `gid` always starts with prefix `@TX:`.
129
+ - when the ID is **internal**, it has the `name` property (which is the pin's name, a pin being required by definition for an internal link).
130
+ - You can easily distinguish between an external and internal ID by looking at a property like `name`, which is always present for internal IDs, and never present for external IDs.
217
131
 
218
- With thousands of parts/fragments providing dozens of pins, you quickly end up with a lot of them. So, to ease their lookup in this control, you can filter them. This component provides _two modes_ to get to a pin-based link target:
132
+ For internal lookup, with thousands of parts/fragments providing dozens of pins, you quickly end up with a lot of them. So, to ease their lookup in this control, you can filter them. This component provides _two modes_ to get to a pin-based link target:
219
133
 
220
- - **by item** (default mode): the user selects an item from a lookup list; then a part, from the list of the parts found in the selected item; and finally a pin, from a lookup list of pins filtered by that item's part. This essentially provides a way of selecting a pin from a restricted lookup set, by walking the data hierarchy from item to part/fragment and finally pin.
221
- - **by type**: the user selects the part's type (this is automatically pre-selected when only a single type is set), and then selects a pin from a lookup list of pins filtered by that part's type. The list of part types may come from several sources:
134
+ - _by item instance_ (option `pinByTypeMode`=`false`): lookup pins filtered by a specific item (via its assigned EID in its metadata part), and optionally by any of its parts. This is the default mode, as in most cases users have a top-bottom approach and think first of the item they want to target, and then, possibly, to a specific portion of its data (unless they are just happy to target the item as a whole).
135
+ - _by part type_ (option `pinByTypeMode`=`true`): directly lookup by pin value, in the context of a specific part type and pin namem, as specified by index lookup definitions (`indexLookupDefinitions` property). The list of part types may come from several sources:
222
136
  - explicitly set via the component `lookupDefinitions` property;
223
137
  - if this is not set, the lookup definitions will be got via injection when available;
224
138
  - if the injected definitions are empty, the lookup definitions will be built from the `model-types` thesaurus;
225
139
  - if this is not available either, the _by-type_ lookup will be disabled.
226
140
 
227
141
  >Filtering by item essentially means filtering by an object instance: for instance a specific manuscript object. Filtering by type instead means filtering by pin class, as each part or fragment provides its own set of search pins, whose names are meaningful and unique only in their context.
142
+ >You can use options `canSwitchMode` to allow users switching between by-type and by-item modes, and `canEditTarget` to allow users edit the link target GID and label also for internal pins, where they are automatically provided by pin lookup.
228
143
 
229
- In both cases, in the end the target ID model is the same; it's just the way the user selects the pin which changes. You can specify the mode for the component with `pinByTypeMode`, and control the possibility of switching between modes with `canSwitchMode`.
144
+ According to the target type and component settings, the following modes are available:
145
+
146
+ - external:
147
+ - pick an ID from 1 or more lookup providers
148
+ - manually type or paste an ID
149
+ - manually build an ID from the target object's properties
150
+ - internal:
151
+ - from pin lookup:
152
+ - by type: pick a preset (as specified by lookup index definitions) and then lookup a pin within its scope.
153
+ - by item:
154
+ - filter by item: lookup pins limited to a specific item.
155
+ - filter by item's part: lookup pins limited to a specific item's part.
156
+ - lookup pin directly from its name
157
+ - manual
158
+ - both
159
+ - taxonomy: from 1 tree's node.
230
160
 
231
161
  Once the user picks an internal pin, the target is automatically filled with data from the pin itself. Two values are calculated:
232
162
 
@@ -243,54 +173,14 @@ Optionally, users can customize both `gid` and `label` (when `canBuildGid` and `
243
173
 
244
174
  The user can then use buttons to append each of these components to the ID being built, and/or variously edit it. When he's ok with the ID, he can then use it as the reference ID being edited.
245
175
 
246
- >πŸ‘‰ The demo found in this workspace uses a [mock data service](../../../src/app/services/mock-item.service.ts) instead of the real one, which provides a minimal set of data and functions, just required for the components to function.
247
-
248
- ### Configuring the Target ID Editor
249
-
250
- You can configure the target ID editor to use any number of lookup providers:
251
-
252
- (1) ensure to import the `PinTargetLookupComponent` control in your component.
176
+ ### AssertedCompositeIdsComponent
253
177
 
254
- (2) add a lookup control to your UI, like this:
255
-
256
- ```html
257
- <!-- lookup -->
258
- <cadmus-pin-target-lookup [canSwitchMode]="true"
259
- (targetChange)="onTargetChange($event)"/>
260
- ```
261
-
262
- (3) specify the lookup definitions, either from binding, or via injection. In the latter case, in your app's `index-lookup-definitions.ts` file, add the required lookup definitions. Each definition has a conventional key, and is an object with part type ID for the lookup scope, and pin name, e.g.:
263
-
264
- ```ts
265
- import { IndexLookupDefinitions } from '@myrmidon/cadmus-core';
266
- import {
267
- METADATA_PART_TYPEID,
268
- HISTORICAL_EVENTS_PART_TYPEID,
269
- } from '@myrmidon/cadmus-part-general-ui';
270
-
271
- export const INDEX_LOOKUP_DEFINITIONS: IndexLookupDefinitions = {
272
- // item's metadata
273
- meta_eid: {
274
- typeId: METADATA_PART_TYPEID,
275
- name: 'eid',
276
- },
277
- // general parts
278
- event_eid: {
279
- typeId: HISTORICAL_EVENTS_PART_TYPEID,
280
- name: 'eid',
281
- },
282
- // ... etc.
283
- };
284
- ```
285
-
286
- >Note that while pin name and type will not be displayed to the end user, the key of each definition will. Unless you have a single definition, the lookup component will display a dropdown list with all the available keys, so that the user can select the lookup's scope. So, use short, yet meaningful keys here, like in the above sample (`meta_eid`, `event_eid`).
287
-
288
- ## Asserted Composite ID
178
+ A collection of asserted composite IDs.
289
179
 
290
- - πŸ”‘ `AssertedCompositeIdComponent`
291
- - 🚩 `cadmus-refs-asserted-composite-id`
180
+ - πŸ”‘ `AssertedCompositeIdsComponent`
181
+ - 🚩 `cadmus-refs-asserted-composite-ids`
292
182
  - ▢️ input:
293
- - `id` (`AssertedId`)
183
+ - `ids` (`AssertedId[]`)
294
184
  - `pinByTypeMode` (`boolean?`)
295
185
  - `canSwitchMode` (`boolean?`)
296
186
  - `canEditTarget` (`boolean?`)
@@ -303,87 +193,250 @@ export const INDEX_LOOKUP_DEFINITIONS: IndexLookupDefinitions = {
303
193
  - `doc-reference-types` (for `refTypeEntries`)
304
194
  - `doc-reference-tags` (for `refTagEntries`)
305
195
  - ⚑ output:
306
- - `idChange` (`AssertedId[]`)
307
- - `editorClose`
308
- - `extMoreRequest` (`RefLookupSetEvent`): the user requested more about the current external lookup source.
309
-
310
- This is the most complete ID reference, which can be used for both external and internal IDs, providing full lookup in either cases. Each asserted composite ID has:
311
-
312
- - a `target`, representing the pin-based target of the ID. The target model has these properties:
313
- - a global ID, `gid`, built from the pin or manually defined;
314
- - a human-friendly `label` for the target, built from the pin or manually defined;
315
- - for internal links only:
316
- - `itemId` for the item the pin derives from;
317
- - when the pin derives from a part, an optional `partId`, `partTypeId`, `roleId`;
318
- - the `name` and `value` of the pin.
319
- - an optional `scope`, representing the context the ID originates from (e.g. an ontology, a repository, a website, etc.).
320
- - an optional `tag`, eventually used to group or classify the ID.
321
- - an optional `assertion`, eventually used to define the uncertainty level of the assignment of this ID to the context it applies to.
196
+ - `idsChange` (`AssertedCompositeId[]`)
322
197
 
323
- When the ID is **external**, the only properties set for the target model are `gid` (=the ID) and `label`. You can easily distinguish between an external and internal ID by looking at a property like `name`, which is always present for internal IDs, and never present for external IDs.
198
+ ### PinTargetLookupComponent
324
199
 
325
- There are different **options** to customize the lookup behavior:
200
+ This component is not designed for direct use by higher-level consumer components. It is embedded by other components to edit their target.
326
201
 
327
- - lookup pins by part type or by item instance:
328
- - _by part type_: you directly lookup by pin name, in the context of a specific part type. The part type is selected from a dropdown list, which draws its data from the configured `IndexLookupDefinitions`.
329
- - _by item instance_: you lookup pins filtered by a specific item (via its assigned EID in its metadata part), and optionally by any of its parts. This is the default mode, as in most cases users have a top-bottom approach and think first of the item they want to target, and then, possibly, to a specific portion of its data (unless they are just happy to target the item as a whole).
202
+ - ▢️ input:
203
+ - `target` (`PinTarget? | null`)
204
+ - `pinByTypeMode` (`boolean?`)
205
+ - `canSwitchMode` (`boolean?`)
206
+ - `canEditTarget` (`boolean?`)
207
+ - `defaultPartTypeKey` (`string?|null`)
208
+ - `lookupDefinitions` (`IndexLookupDefinitions?`)
209
+ - `extLookupConfigs` (`RefLookupConfig[]`): the configurations of external lookup providers, if any.
210
+ - πŸ”₯ output:
211
+ - `targetChange` (`PinTarget`)
212
+ - `editorClose`
330
213
 
331
- >The part type ID and pin name filter (i.e. the _index lookup definitions_) can be set from many sources:
214
+ ## Configuring Asserted ID
215
+
216
+ ### Configuring Lookup Providers
217
+
218
+ Lookup providers must be configured once in the app's root component. Typically (see [app.ts](../../../src/app/app.ts) in this repository):
219
+
220
+ 1. add a `configureLookup` function to your app's component code:
221
+
222
+ ```ts
223
+ private configureLookup(): void {
224
+ const storage = inject(RamStorageService);
225
+ storage.store(LOOKUP_CONFIGS_KEY, [
226
+ // the colors provider is a mock provider using local data
227
+ {
228
+ name: 'colors',
229
+ iconUrl: '/img/colors128.png',
230
+ description: 'Colors',
231
+ label: 'color',
232
+ service: new WebColorLookup(),
233
+ // compute the lookup item's ID
234
+ itemIdGetter: (item: any) => item?.value,
235
+ // compute the lookup item's human-friendly label
236
+ itemLabelGetter: (item: any) => item?.name,
237
+ },
238
+ // the VIAF provider consumes the public VIAF API
239
+ {
240
+ name: 'VIAF',
241
+ iconUrl: '/img/viaf128.png',
242
+ description: 'Virtual International Authority File',
243
+ label: 'ID',
244
+ service: inject(ViafRefLookupService),
245
+ itemIdGetter: (item: any) => item?.viafid,
246
+ itemLabelGetter: (item: any) => item?.term,
247
+ },
248
+ // ... etc.
249
+ }
250
+ ```
251
+
252
+ 2. call this function from your app's constructor.
253
+
254
+ >It is suggested to add an icon for each provider so you can easily identify it. You can grab icons for existing providers from this repository (see the `public` folder).
255
+
256
+ ### Configuring Taxonomy Store
257
+
258
+ The taxonomy store can be configured as follows:
259
+
260
+ 1. ensure to add TaxoStore packages: `pnpm i @myrmidon/taxo-store-api @myrmidon/taxo-store-picker`.
261
+ 2. add a `configureTaxoLookup` function to your app's component code, adding an entry for each taxonomy tree you want to expose:
262
+
263
+ ```ts
264
+ private configureTaxoLookup(storage: RamStorageService): void {
265
+ storage.store(LOOKUP_TAXOSTORE_CONFIGS_KEY, [
266
+ {
267
+ treeId: 'animals',
268
+ treeName: 'animals',
269
+ // user can edit nodes
270
+ canEdit: false,
271
+ // user can add new nodes
272
+ canAdd: false,
273
+ // user can delete nodes
274
+ canDelete: false,
275
+ },
276
+ {
277
+ treeId: 'food',
278
+ treeName: 'food',
279
+ canEdit: false,
280
+ canAdd: false,
281
+ canDelete: false,
282
+ },
283
+ // ... etc.
284
+ ] as TaxoStoreLookupConfig[]);
285
+ }
286
+ ```
287
+
288
+ >Note that here you can be very granular in your settings: for each taxonomy tree, you can define its UI label and whether its nodes can be edited, deleted and added by users, and set other options to change the picker's behavior (see `TaxoStoreLookupConfig`).
289
+
290
+ 3. call this function from your app's constructor.
291
+
292
+ ### Defining Index Lookups
293
+
294
+ The part type ID and pin name filter (i.e. the _index lookup definitions_) can be set from many sources:
332
295
 
333
296
  1. directly from the consumer code by setting `lookupDefinitions`;
334
297
  2. from injection, when (1) is not used;
335
298
  3. from thesaurus `model-types`, when (2) is empty.
336
299
 
337
- - set `pinByTypeMode` to true to let the editor use by-type mode instead of by-item;
338
- - set `canSwitchMode` to true to allow users switch between by-type and by-item modes;
339
- - set `canEditTarget` to true to allow users edit the link target GID and label also for internal pins, where they are automatically provided by pin lookup.
300
+ The typical approach is via `lookupDefinitions`. To this end:
301
+
302
+ 1. add an `index-lookup-definitions.ts` file to your app with code like this (change the array to fit your scenario):
303
+
304
+ ```ts
305
+ import { IndexLookupDefinitions } from '@myrmidon/cadmus-core';
306
+ import {
307
+ HISTORICAL_EVENTS_PART_TYPEID,
308
+ METADATA_PART_TYPEID,
309
+ } from '@myrmidon/cadmus-part-general-ui';
310
+ import { COD_CONTENTS_PART_TYPEID } from '@myrmidon/cadmus-part-codicology-contents';
311
+ import { COD_DECORATIONS_PART_TYPEID } from '@myrmidon/cadmus-part-codicology-decorations';
312
+ import { COD_EDITS_PART_TYPEID } from '@myrmidon/cadmus-part-codicology-edits';
313
+ import { COD_HANDS_PART_TYPEID } from '@myrmidon/cadmus-part-codicology-hands';
314
+ import { COD_MATERIAL_DSC_PART_TYPEID } from '@myrmidon/cadmus-part-codicology-material-dsc';
315
+
316
+ export const INDEX_LOOKUP_DEFINITIONS: IndexLookupDefinitions = {
317
+ // item's metadata
318
+ meta_eid: {
319
+ typeId: METADATA_PART_TYPEID,
320
+ name: 'eid',
321
+ },
322
+ // general parts
323
+ event_eid: {
324
+ typeId: HISTORICAL_EVENTS_PART_TYPEID,
325
+ name: 'eid',
326
+ },
327
+ // codicology parts
328
+ cod_unit_eid: {
329
+ typeId: COD_MATERIAL_DSC_PART_TYPEID,
330
+ name: 'unit-eid',
331
+ },
332
+ cod_hand_eid: {
333
+ typeId: COD_HANDS_PART_TYPEID,
334
+ name: 'eid',
335
+ },
336
+ cod_decoration_eid: {
337
+ typeId: COD_DECORATIONS_PART_TYPEID,
338
+ name: 'eid',
339
+ },
340
+ cod_artist_eid: {
341
+ typeId: COD_DECORATIONS_PART_TYPEID,
342
+ name: 'artist-id',
343
+ },
344
+ cod_content_eid: {
345
+ typeId: COD_CONTENTS_PART_TYPEID,
346
+ name: 'eid',
347
+ },
348
+ cod_edit_eid: {
349
+ typeId: COD_EDITS_PART_TYPEID,
350
+ name: 'eid',
351
+ },
352
+ };
353
+ ```
354
+
355
+ These definitions are used to define preset filters for internal lookup:
356
+
357
+ - each object is a filter, with its name (e.g. `meta_eid`).
358
+ - `typeId` defines the type ID of the part/fragment where the ID to be looked up is stored.
359
+ - `roleId` (optional) can be used to specify the part or fragment's role ID.
360
+ - `name` defines the corresponding data pin's name to search in.
340
361
 
341
- These options can be variously combined to force users to use a specific behavior only; for instance, if you just want by-type lookup and automatic GID/label, set `pinByTypeMode` to true and `canSwitchMode` and `canEditTarget` to false.
362
+ >Note that while pin name and type will not be displayed to the end user, the key of each definition will. Unless you have a single definition, the lookup component will display a dropdown list with all the available keys, so that the user can select the lookup's scope. So, use short, yet meaningful keys here, like in the above sample (`meta_eid`, `event_eid`).
342
363
 
343
- Also, you can use any number of lookup components for external IDs. To globally configure all the asserted composite IDs components for this purpose, you can define (e.g. in your app's component constructor) an array of configuration objects keyed under `ASSERTED_COMPOSITE_ID_CONFIGS_KEY`. Thus, this component provides many different ways for creating a link:
364
+ This way, a pin-based lookup will be limited within the scope defined by the combination of object's type ID and pin's name, thus focusing on a specific subset of pins.
344
365
 
345
- - external:
346
- - from 1 or more lookups
347
- - manual
348
- - both
349
- - internal:
350
- - from pin lookup:
351
- - filter by item
352
- - filter by item's part
353
- - lookup pin
354
- - manual
355
- - both
366
+ Once this definition is in place, it can be injected where needed by adding this among the consumer class constructor’s arguments:
356
367
 
357
- Three components are used for this brick:
368
+ ```ts
369
+ @Inject(INDEX_LOOKUP_DEFINITIONS)
370
+ private _lookupDefs: IndexLookupDefinitions
371
+ ```
358
372
 
359
- - `AssertedCompositeIdsComponent`, the top level editor for the list of IDs. This has buttons to add new internal/external IDs, and a list of existing IDs. Each existing ID has buttons for editing, moving, and deleting it. When editing, the `AssertedIdComponent` is used in an expansion panel.
360
- - `AssertedCompositeIdComponent`, the editor for each single ID. This allows you to edit shared metadata (tag and scope), and specific properties for both external and internal ID.
361
- - `PinTargetLookupComponent`, the editor for an internal ID, i.e. a link target based on pins lookup. This is the core of the editor's logic.
373
+ ## Legacy Components
362
374
 
363
- ## Asserted Composite IDs
375
+ ### AssertedIdComponent
364
376
 
365
- A collection of asserted composite IDs.
377
+ >⚠️ Obsolete, use [AssertedCompositeIdComponent](#assertedcompositeidcomponent).
366
378
 
367
- - πŸ”‘ `AssertedCompositeIdsComponent`
368
- - 🚩 `cadmus-refs-asserted-composite-ids`
379
+ - πŸ”‘ `AssertedIdComponent`
380
+ - 🚩 `cadmus-refs-asserted-id`
381
+ - ▢️ input:
382
+ - `id` (`AssertedId? | null`)
383
+ - `noEidLookup` (`boolean?`)
384
+ - `hasSubmit` (`boolean?`)
385
+ - πŸ“š thesauri:
386
+ - `asserted-id-scopes` (for `idScopeEntries`)
387
+ - `asserted-id-tags` (for `idTagEntries`).
388
+ - `assertion-tags` (for `assTagEntries`).
389
+ - `doc-reference-types` (for `refTypeEntries`).
390
+ - `doc-reference-tags` (for `refTagEntries`).
391
+ - `asserted-id-features` (for `featureEntries`).
392
+ - πŸ”₯ output:
393
+ - `idChange` (`AssertedId`)
394
+ - `editorClose`
395
+ - `extMoreRequest` (`RefLookupSetEvent`): the user requested more about the current external lookup source.
396
+
397
+ The asserted ID component allows editing a simple model representing a generic ID with an optional assertion. The ID has:
398
+
399
+ - **value**: the ID itself.
400
+ - **scope**: the context the ID originates from (e.g. an ontology, a repository, a website, etc.).
401
+ - an optional **tag**, used to group or classify the ID.
402
+ - an optional set of **features**, from a hierarchical thesaurus. For instance, these could be the role(s) of a person linked to an object, like customer, seller, creator, etc.
403
+ - an optional **note**.
404
+ - an optional **assertion**, used to define the uncertainty level of the assignment of this ID to the context it applies to.
405
+
406
+ The asserted ID component provides an internal lookup mechanism based on data pins and metadata conventions. When users want to add an ID referring to some internal entity, either found in a part or corresponding to an item, he just has to pick the type of desired lookup (when more than a single lookup search definition is present), and type some characters to get the first N pins starting with these characters; he can then pick one from the list. Once a pin value is picked, the lookup control shows all the relevant data which can be used as components for the ID to build:
407
+
408
+ - the item GUID.
409
+ - the item title.
410
+ - the part GUID.
411
+ - the part type ID.
412
+ - the item's metadata part entries.
413
+
414
+ The user can then use buttons to append each of these components to the ID being built, and/or variously edit it. When he's ok with the ID, he can then use it as the reference ID being edited.
415
+
416
+ ### AssertedIdsComponent
417
+
418
+ >⚠️ Obsolete, use [AssertedCompositeIdsComponent](#assertedcompositeidscomponent).
419
+
420
+ An editable list of asserted IDs.
421
+
422
+ - πŸ”‘ `AssertedIdsComponent`
423
+ - 🚩 `cadmus-refs-asserted-ids`
369
424
  - ▢️ input:
370
425
  - `ids` (`AssertedId[]`)
371
- - `pinByTypeMode` (`boolean?`)
372
- - `canSwitchMode` (`boolean?`)
373
- - `canEditTarget` (`boolean?`)
374
- - `defaultPartTypeKey` (`string?|null`)
375
- - `lookupDefinitions` (`IndexLookupDefinitions?`)
376
426
  - πŸ“š thesauri:
377
427
  - `asserted-id-scopes` (for `idScopeEntries`)
378
428
  - `asserted-id-tags` (for `idTagEntries`)
379
429
  - `assertion-tags` (for `assTagEntries`)
380
430
  - `doc-reference-types` (for `refTypeEntries`)
381
431
  - `doc-reference-tags` (for `refTagEntries`)
382
- - ⚑ output:
383
- - `idsChange` (`AssertedCompositeId[]`)
432
+ - `asserted-id-features` (for `featureEntries`).
433
+ - πŸ”₯ output:
434
+ - `idsChange` (`AssertedId[]`)
384
435
 
385
436
  ## History
386
437
 
438
+ - 2026-06-11: πŸ†• added taxonomies mode to `AssertedCompositeId` and `AssertedCompositeIds`.
439
+
387
440
  ### 10.0.14
388
441
 
389
442
  - 2026-02-01: minor fix to pin target lookup component template.