@myrmidon/cadmus-refs-asserted-ids 11.0.0 β 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
|
-
|
|
12
|
-
- [
|
|
13
|
-
|
|
14
|
-
- [
|
|
15
|
-
- [Configuring
|
|
16
|
-
|
|
17
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
59
|
+
## Internal IDs
|
|
56
60
|
|
|
57
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
67
|
+
So, internal IDs are human-friendly identifiers connected to any data in the Cadmus database. They can refer to:
|
|
64
68
|
|
|
65
|
-
|
|
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,
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
- π `
|
|
183
|
-
- π© `cadmus-refs-asserted-
|
|
92
|
+
- π `AssertedCompositeIdComponent`
|
|
93
|
+
- π© `cadmus-refs-asserted-composite-id`
|
|
184
94
|
- βΆοΈ input:
|
|
185
|
-
- `
|
|
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
|
-
|
|
193
|
-
-
|
|
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
|
|
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
|
-
-
|
|
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
|
-
|
|
125
|
+
To distinguish among link targets:
|
|
215
126
|
|
|
216
|
-
-
|
|
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
|
-
|
|
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
|
-
-
|
|
221
|
-
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
- π `
|
|
291
|
-
- π© `cadmus-refs-asserted-composite-
|
|
180
|
+
- π `AssertedCompositeIdsComponent`
|
|
181
|
+
- π© `cadmus-refs-asserted-composite-ids`
|
|
292
182
|
- βΆοΈ input:
|
|
293
|
-
- `
|
|
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
|
-
- `
|
|
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
|
-
|
|
198
|
+
### PinTargetLookupComponent
|
|
324
199
|
|
|
325
|
-
|
|
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
|
-
-
|
|
328
|
-
-
|
|
329
|
-
-
|
|
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
|
-
|
|
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
|
-
|
|
338
|
-
|
|
339
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
368
|
+
```ts
|
|
369
|
+
@Inject(INDEX_LOOKUP_DEFINITIONS)
|
|
370
|
+
private _lookupDefs: IndexLookupDefinitions
|
|
371
|
+
```
|
|
358
372
|
|
|
359
|
-
|
|
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
|
-
|
|
375
|
+
### AssertedIdComponent
|
|
364
376
|
|
|
365
|
-
|
|
377
|
+
>β οΈ Obsolete, use [AssertedCompositeIdComponent](#assertedcompositeidcomponent).
|
|
366
378
|
|
|
367
|
-
- π `
|
|
368
|
-
- π© `cadmus-refs-asserted-
|
|
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
|
-
-
|
|
383
|
-
|
|
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.
|