@myrmidon/cadmus-refs-asserted-ids 10.0.0 → 10.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.
@@ -1,34 +1,59 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Injectable, output, Inject, Component, input, model, effect, Input } from '@angular/core';
2
+ import { Injectable, model, input, output, effect, Inject, Component, Input } from '@angular/core';
3
3
  import * as i1$1 from '@angular/forms';
4
4
  import { Validators, FormsModule, ReactiveFormsModule } from '@angular/forms';
5
- import { debounceTime } from 'rxjs/operators';
5
+ import { debounceTime as debounceTime$1 } from 'rxjs/operators';
6
6
  import * as i3 from '@angular/material/button';
7
7
  import { MatButtonModule } from '@angular/material/button';
8
- import * as i4 from '@angular/material/expansion';
8
+ import * as i4$1 from '@angular/material/expansion';
9
9
  import { MatExpansionModule } from '@angular/material/expansion';
10
- import * as i6 from '@angular/material/form-field';
10
+ import * as i6$1 from '@angular/material/form-field';
11
11
  import { MatFormFieldModule } from '@angular/material/form-field';
12
- import * as i8 from '@angular/material/input';
13
- import { MatInputModule } from '@angular/material/input';
14
12
  import * as i7 from '@angular/material/icon';
15
13
  import { MatIconModule } from '@angular/material/icon';
14
+ import * as i8$1 from '@angular/material/input';
15
+ import { MatInputModule } from '@angular/material/input';
16
16
  import * as i9 from '@angular/material/select';
17
17
  import { MatSelectModule } from '@angular/material/select';
18
- import { AssertionComponent } from '@myrmidon/cadmus-refs-assertion';
19
- import { of, map, forkJoin, take, distinctUntilChanged, debounceTime as debounceTime$1 } from 'rxjs';
20
- import { RefLookupComponent, RefLookupSetComponent } from '@myrmidon/cadmus-refs-lookup';
21
- import * as i1 from '@myrmidon/cadmus-api';
22
- import * as i6$1 from '@angular/material/tooltip';
18
+ import * as i14 from '@angular/material/tooltip';
23
19
  import { MatTooltipModule } from '@angular/material/tooltip';
24
- import * as i2 from '@myrmidon/ngx-mat-tools';
25
- import * as i6$2 from '@angular/cdk/clipboard';
20
+ import { AssertionComponent } from '@myrmidon/cadmus-refs-assertion';
21
+ import { map, of, distinctUntilChanged, debounceTime, forkJoin, take } from 'rxjs';
22
+ import * as i6 from '@angular/cdk/clipboard';
26
23
  import { ClipboardModule } from '@angular/cdk/clipboard';
27
- import * as i8$1 from '@angular/material/checkbox';
24
+ import * as i8 from '@angular/material/checkbox';
28
25
  import { MatCheckboxModule } from '@angular/material/checkbox';
29
26
  import * as i3$1 from '@myrmidon/ngx-tools';
30
27
  import { FlatLookupPipe } from '@myrmidon/ngx-tools';
31
- import * as i4$1 from '@angular/material/snack-bar';
28
+ import { RefLookupComponent, RefLookupSetComponent } from '@myrmidon/cadmus-refs-lookup';
29
+ import * as i1 from '@myrmidon/cadmus-api';
30
+ import * as i4 from '@angular/material/snack-bar';
31
+ import * as i2 from '@myrmidon/ngx-mat-tools';
32
+
33
+ class ItemRefLookupService {
34
+ _itemService;
35
+ constructor(_itemService) {
36
+ this._itemService = _itemService;
37
+ }
38
+ lookup(filter, options) {
39
+ return this._itemService
40
+ .getItems({
41
+ title: filter.text,
42
+ }, 1, filter.limit || 10)
43
+ .pipe(map((page) => page.items));
44
+ }
45
+ getName(item) {
46
+ return item?.title;
47
+ }
48
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: ItemRefLookupService, deps: [{ token: i1.ItemService }], target: i0.ɵɵFactoryTarget.Injectable });
49
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: ItemRefLookupService, providedIn: 'root' });
50
+ }
51
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: ItemRefLookupService, decorators: [{
52
+ type: Injectable,
53
+ args: [{
54
+ providedIn: 'root',
55
+ }]
56
+ }], ctorParameters: () => [{ type: i1.ItemService }] });
32
57
 
33
58
  /**
34
59
  * Cadmus pin-based lookup data service. The text being searched here is just
@@ -120,293 +145,543 @@ const METADATA_PART_ID$1 = 'it.vedph.metadata';
120
145
  * item's metadata part, if any. He can then use these data to build
121
146
  * some EID by variously assembling these components.
122
147
  */
123
- class ScopedPinLookupComponent {
148
+ class PinTargetLookupComponent {
149
+ _presetLookupDefs;
150
+ itemLookupService;
151
+ pinLookupService;
124
152
  _itemService;
125
- lookupService;
126
- lookupDefs;
127
- // lookup
128
- key;
129
- keyForm;
130
- keys;
131
- info;
132
- // builder
133
- id;
134
- idForm;
153
+ _thesService;
154
+ _snackbar;
155
+ _subs = [];
156
+ _noTargetUpdate;
157
+ _noFormUpdate;
158
+ _startWithByTypeMode;
135
159
  /**
136
- * Emitted whenever the user picks an ID.
160
+ * True when the by-type pin lookup mode is active.
161
+ * User can change mode unless modeSwitching is false.
137
162
  */
138
- idPick = output();
139
- constructor(formBuilder, _itemService, lookupService, lookupDefs) {
140
- this._itemService = _itemService;
141
- this.lookupService = lookupService;
142
- this.lookupDefs = lookupDefs;
143
- // lookup
144
- // keys are all the defined lookup searches
145
- this.keys = Object.keys(lookupDefs);
146
- // the selected key defines the lookup scope
147
- this.key = formBuilder.control(null);
148
- this.keyForm = formBuilder.group({
149
- key: this.key,
150
- });
151
- // id
152
- this.id = formBuilder.control(null, [
153
- Validators.required,
154
- Validators.maxLength(300),
155
- ]);
156
- this.idForm = formBuilder.group({
157
- id: this.id,
158
- });
159
- }
160
- ngOnInit() {
161
- // pre-select a unique key
162
- if (this.keys.length === 1) {
163
- this.key.setValue(this.keys[0]);
164
- this.key.markAsDirty();
165
- this.key.updateValueAndValidity();
166
- }
167
- }
168
- onItemChange(item) {
169
- const info = {
170
- pin: item,
171
- };
172
- // lookup item and its metadata part if any
173
- forkJoin({
174
- item: item
175
- ? this._itemService.getItem(item.itemId, false, true)
176
- : of(null),
177
- part: item
178
- ? this._itemService.getPartFromTypeAndRole(item.itemId, METADATA_PART_ID$1, undefined, true)
179
- : of(null),
180
- })
181
- .pipe(take(1))
182
- .subscribe({
183
- next: (result) => {
184
- if (result.item) {
185
- info.item = result.item;
186
- info.part = result.part;
187
- this.info = info;
188
- }
189
- },
190
- error: (error) => {
191
- console.error(error ? JSON.stringify(error) : 'Error loading item/metadata');
192
- },
193
- });
194
- }
195
- appendIdComponent(type, metaIndex = -1) {
196
- let id = this.id.value || '';
197
- switch (type) {
198
- case 'pin':
199
- id += this.info?.pin.value;
200
- break;
201
- case 'itemId':
202
- id += this.info.item?.id || '';
203
- break;
204
- case 'partId':
205
- id += this.info.part?.id || '';
206
- break;
207
- case 'partTypeId':
208
- id += this.info.part?.typeId || '';
209
- break;
210
- case 'partRoleId':
211
- id += this.info.part?.roleId || '';
212
- break;
213
- case 'metadata':
214
- id += this.info.part.metadata[metaIndex].value;
215
- break;
216
- }
217
- this.id.setValue(id);
218
- this.id.markAsDirty();
219
- this.id.updateValueAndValidity();
220
- }
221
- pickId() {
222
- if (this.idForm.invalid) {
223
- return;
224
- }
225
- this.idPick.emit(this.id.value);
226
- this.info = undefined;
227
- }
228
- resetId() {
229
- this.id.reset();
230
- this.id.markAsDirty();
231
- this.id.updateValueAndValidity();
232
- }
233
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: ScopedPinLookupComponent, deps: [{ token: i1$1.FormBuilder }, { token: i1.ItemService }, { token: PinRefLookupService }, { token: 'indexLookupDefinitions' }], target: i0.ɵɵFactoryTarget.Component });
234
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.0", type: ScopedPinLookupComponent, isStandalone: true, selector: "cadmus-scoped-pin-lookup", outputs: { idPick: "idPick" }, ngImport: i0, template: "<div>\n <!-- lookup -->\n <div>\n <form [formGroup]=\"keyForm\" class=\"form-row\">\n <!-- key -->\n @if (keys.length > 1) {\n <mat-form-field>\n <mat-label>type</mat-label>\n <mat-select [formControl]=\"key\">\n @for (k of keys; track k) {\n <mat-option [value]=\"k\">{{ k }}</mat-option>\n }\n </mat-select>\n @if ($any(key).errors?.required && (key.dirty || key.touched)) {\n <mat-error>type required</mat-error>\n }\n </mat-form-field>\n }\n <cadmus-ref-lookup\n [service]=\"lookupService\"\n label=\"pin\"\n [options]=\"key.value ? lookupDefs[key.value] : undefined\"\n (itemChange)=\"onItemChange($event)\"\n />\n </form>\n </div>\n\n <!-- builder -->\n @if (info) {\n <mat-expansion-panel [expanded]=\"info\" [disabled]=\"!info\">\n <mat-expansion-panel-header>ID builder</mat-expansion-panel-header>\n <!-- ID -->\n <div>\n <form [formGroup]=\"idForm\" (submit)=\"pickId()\">\n <mat-form-field style=\"width: 100%\">\n <input matInput [formControl]=\"id\" />\n @if ($any(id).errors?.required && (id.dirty || id.touched)) {\n <mat-error>ID required</mat-error>\n } @if ($any(id).errors?.maxLength && (id.dirty || id.touched)) {\n <mat-error>ID too long</mat-error>\n }\n <button\n mat-icon-button\n type=\"button\"\n matSuffix\n (click)=\"resetId()\"\n [disabled]=\"!id.value\"\n >\n <mat-icon class=\"mat-warn\">close</mat-icon>\n </button>\n <button\n mat-icon-button\n type=\"button\"\n matSuffix\n (click)=\"pickId()\"\n [disabled]=\"idForm.invalid\"\n >\n <mat-icon class=\"mat-primary\">check_circle</mat-icon>\n </button>\n </mat-form-field>\n </form>\n </div>\n <!-- table -->\n <table>\n <thead>\n <th></th>\n <th>source</th>\n <th>value</th>\n </thead>\n <tbody>\n <!-- pin -->\n <tr>\n <td>\n <button\n type=\"button\"\n mat-icon-button\n (click)=\"appendIdComponent('pin')\"\n >\n <mat-icon class=\"mat-primary\">add_circle</mat-icon>\n </button>\n </td>\n <td>pin</td>\n <td>{{ info!.pin.value }}</td>\n </tr>\n <!-- item ID -->\n <tr>\n <td>\n <button\n type=\"button\"\n mat-icon-button\n (click)=\"appendIdComponent('itemId')\"\n >\n <mat-icon class=\"mat-primary\">add_circle</mat-icon>\n </button>\n </td>\n <td>item ID</td>\n <td>{{ info!.item?.id }}</td>\n </tr>\n <!-- item title -->\n <tr>\n <td></td>\n <td>item title</td>\n <td>{{ info!.item?.title }}</td>\n </tr>\n <!-- part ID -->\n <tr>\n <td>\n <button\n type=\"button\"\n mat-icon-button\n (click)=\"appendIdComponent('partId')\"\n >\n <mat-icon class=\"mat-primary\">add_circle</mat-icon>\n </button>\n </td>\n <td>part ID</td>\n <td>{{ info!.part?.id }}</td>\n </tr>\n <!-- part type ID -->\n <tr>\n <td>\n <button\n type=\"button\"\n mat-icon-button\n (click)=\"appendIdComponent('partTypeId')\"\n >\n <mat-icon class=\"mat-primary\">add_circle</mat-icon>\n </button>\n </td>\n <td>part type ID</td>\n <td>{{ info!.part?.typeId }}</td>\n </tr>\n <!-- part role ID -->\n <tr>\n <td>\n <button\n type=\"button\"\n mat-icon-button\n (click)=\"appendIdComponent('partRoleId')\"\n >\n <mat-icon class=\"mat-primary\">add_circle</mat-icon>\n </button>\n </td>\n <td>part role ID</td>\n <td>{{ info!.part?.roleId }}</td>\n </tr>\n <!-- part's metadata -->\n @for (m of info!.part?.metadata; track m; let i = $index) {\n <tr>\n <td>\n <button\n type=\"button\"\n mat-icon-button\n (click)=\"appendIdComponent('metadata', i)\"\n >\n <mat-icon class=\"mat-primary\">add_circle</mat-icon>\n </button>\n </td>\n <td class=\"metadata\">{{ m.name }}</td>\n <td class=\"metadata\">{{ m.value }}</td>\n </tr>\n }\n </tbody>\n </table>\n </mat-expansion-panel>\n }\n</div>\n", styles: [".metadata{color:#4a3001}table{border:1px solid silver;border-radius:6px;padding:4px;margin-top:8px}tr:nth-child(odd){background-color:#f0f0f0}th{font-weight:400;text-align:left;color:silver}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "component", type: i4.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i4.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i6.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i7.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i8.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i9.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i9.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: RefLookupComponent, selector: "cadmus-ref-lookup", inputs: ["label", "limit", "baseFilter", "service", "item", "required", "hasMore", "linkTemplate", "optDialog", "options"], outputs: ["itemChange", "optionsChange", "moreRequest"] }] });
235
- }
236
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: ScopedPinLookupComponent, decorators: [{
237
- type: Component,
238
- args: [{ selector: 'cadmus-scoped-pin-lookup', imports: [
239
- FormsModule,
240
- ReactiveFormsModule,
241
- MatButtonModule,
242
- MatExpansionModule,
243
- MatFormFieldModule,
244
- MatIconModule,
245
- MatInputModule,
246
- MatSelectModule,
247
- RefLookupComponent,
248
- ], template: "<div>\n <!-- lookup -->\n <div>\n <form [formGroup]=\"keyForm\" class=\"form-row\">\n <!-- key -->\n @if (keys.length > 1) {\n <mat-form-field>\n <mat-label>type</mat-label>\n <mat-select [formControl]=\"key\">\n @for (k of keys; track k) {\n <mat-option [value]=\"k\">{{ k }}</mat-option>\n }\n </mat-select>\n @if ($any(key).errors?.required && (key.dirty || key.touched)) {\n <mat-error>type required</mat-error>\n }\n </mat-form-field>\n }\n <cadmus-ref-lookup\n [service]=\"lookupService\"\n label=\"pin\"\n [options]=\"key.value ? lookupDefs[key.value] : undefined\"\n (itemChange)=\"onItemChange($event)\"\n />\n </form>\n </div>\n\n <!-- builder -->\n @if (info) {\n <mat-expansion-panel [expanded]=\"info\" [disabled]=\"!info\">\n <mat-expansion-panel-header>ID builder</mat-expansion-panel-header>\n <!-- ID -->\n <div>\n <form [formGroup]=\"idForm\" (submit)=\"pickId()\">\n <mat-form-field style=\"width: 100%\">\n <input matInput [formControl]=\"id\" />\n @if ($any(id).errors?.required && (id.dirty || id.touched)) {\n <mat-error>ID required</mat-error>\n } @if ($any(id).errors?.maxLength && (id.dirty || id.touched)) {\n <mat-error>ID too long</mat-error>\n }\n <button\n mat-icon-button\n type=\"button\"\n matSuffix\n (click)=\"resetId()\"\n [disabled]=\"!id.value\"\n >\n <mat-icon class=\"mat-warn\">close</mat-icon>\n </button>\n <button\n mat-icon-button\n type=\"button\"\n matSuffix\n (click)=\"pickId()\"\n [disabled]=\"idForm.invalid\"\n >\n <mat-icon class=\"mat-primary\">check_circle</mat-icon>\n </button>\n </mat-form-field>\n </form>\n </div>\n <!-- table -->\n <table>\n <thead>\n <th></th>\n <th>source</th>\n <th>value</th>\n </thead>\n <tbody>\n <!-- pin -->\n <tr>\n <td>\n <button\n type=\"button\"\n mat-icon-button\n (click)=\"appendIdComponent('pin')\"\n >\n <mat-icon class=\"mat-primary\">add_circle</mat-icon>\n </button>\n </td>\n <td>pin</td>\n <td>{{ info!.pin.value }}</td>\n </tr>\n <!-- item ID -->\n <tr>\n <td>\n <button\n type=\"button\"\n mat-icon-button\n (click)=\"appendIdComponent('itemId')\"\n >\n <mat-icon class=\"mat-primary\">add_circle</mat-icon>\n </button>\n </td>\n <td>item ID</td>\n <td>{{ info!.item?.id }}</td>\n </tr>\n <!-- item title -->\n <tr>\n <td></td>\n <td>item title</td>\n <td>{{ info!.item?.title }}</td>\n </tr>\n <!-- part ID -->\n <tr>\n <td>\n <button\n type=\"button\"\n mat-icon-button\n (click)=\"appendIdComponent('partId')\"\n >\n <mat-icon class=\"mat-primary\">add_circle</mat-icon>\n </button>\n </td>\n <td>part ID</td>\n <td>{{ info!.part?.id }}</td>\n </tr>\n <!-- part type ID -->\n <tr>\n <td>\n <button\n type=\"button\"\n mat-icon-button\n (click)=\"appendIdComponent('partTypeId')\"\n >\n <mat-icon class=\"mat-primary\">add_circle</mat-icon>\n </button>\n </td>\n <td>part type ID</td>\n <td>{{ info!.part?.typeId }}</td>\n </tr>\n <!-- part role ID -->\n <tr>\n <td>\n <button\n type=\"button\"\n mat-icon-button\n (click)=\"appendIdComponent('partRoleId')\"\n >\n <mat-icon class=\"mat-primary\">add_circle</mat-icon>\n </button>\n </td>\n <td>part role ID</td>\n <td>{{ info!.part?.roleId }}</td>\n </tr>\n <!-- part's metadata -->\n @for (m of info!.part?.metadata; track m; let i = $index) {\n <tr>\n <td>\n <button\n type=\"button\"\n mat-icon-button\n (click)=\"appendIdComponent('metadata', i)\"\n >\n <mat-icon class=\"mat-primary\">add_circle</mat-icon>\n </button>\n </td>\n <td class=\"metadata\">{{ m.name }}</td>\n <td class=\"metadata\">{{ m.value }}</td>\n </tr>\n }\n </tbody>\n </table>\n </mat-expansion-panel>\n }\n</div>\n", styles: [".metadata{color:#4a3001}table{border:1px solid silver;border-radius:6px;padding:4px;margin-top:8px}tr:nth-child(odd){background-color:#f0f0f0}th{font-weight:400;text-align:left;color:silver}\n"] }]
249
- }], ctorParameters: () => [{ type: i1$1.FormBuilder }, { type: i1.ItemService }, { type: PinRefLookupService }, { type: undefined, decorators: [{
250
- type: Inject,
251
- args: ['indexLookupDefinitions']
252
- }] }] });
253
-
254
- /**
255
- * Asserted ID editor component.
256
- */
257
- class AssertedIdComponent {
258
- lookupService;
259
- lookupDefs;
260
- _sub;
261
- _updatingForm;
262
- tag;
263
- value;
264
- label;
265
- scope;
266
- assertion;
267
- form;
268
- lookupExpanded;
269
- // asserted-id-scopes
270
- idScopeEntries = input();
271
- // asserted-id-tags
272
- idTagEntries = input();
273
- // assertion-tags
274
- assTagEntries = input();
275
- // doc-reference-types
276
- refTypeEntries = input();
277
- // doc-reference-tags
278
- refTagEntries = input();
163
+ pinByTypeMode = model();
279
164
  /**
280
- * The asserted ID being edited.
165
+ * True when the user can switch between by-type and by-item mode.
281
166
  */
282
- id = model();
167
+ canSwitchMode = model();
283
168
  /**
284
- * True to hide the pin-based EID lookup UI.
169
+ * True when the user can edit the target's gid/label for internal
170
+ * targets.
285
171
  */
286
- noEidLookup = input();
172
+ canEditTarget = input();
287
173
  /**
288
- * True to show the submit button.
174
+ * The lookup definitions to be used for the by-type lookup. If
175
+ * not specified, the lookup definitions will be got via injection
176
+ * when available; if the injected definitions are empty, the
177
+ * lookup definitions will be built from the model-types thesaurus;
178
+ * if this is not available either, the by-type lookup will be
179
+ * disabled.
289
180
  */
290
- hasSubmit = input();
181
+ lookupDefinitions = model();
291
182
  /**
292
- * Emitted when the editor is closed.
183
+ * The optional configurations for using external lookup services.
184
+ */
185
+ extLookupConfigs = input([]);
186
+ /**
187
+ * True if when a new target is set it should be internal rather than
188
+ * external by default.
189
+ */
190
+ internalDefault = input();
191
+ /**
192
+ * The target to be edited.
193
+ */
194
+ target = model();
195
+ /**
196
+ * The default value for part type key when the by-type mode is active.
197
+ */
198
+ defaultPartTypeKey = input();
199
+ /**
200
+ * Emitted when user closes the editor.
293
201
  */
294
202
  editorClose = output();
295
- constructor(formBuilder, lookupService, lookupDefs) {
296
- this.lookupService = lookupService;
297
- this.lookupDefs = lookupDefs;
298
- this.tag = formBuilder.control(null, Validators.maxLength(50));
299
- this.value = formBuilder.control(null, [
300
- Validators.required,
301
- Validators.maxLength(500),
302
- ]);
303
- this.label = formBuilder.control(null, Validators.maxLength(500));
304
- this.scope = formBuilder.control(null, Validators.maxLength(500));
305
- this.assertion = formBuilder.control(null);
306
- this.form = formBuilder.group({
307
- tag: this.tag,
308
- value: this.value,
309
- label: this.label,
310
- scope: this.scope,
311
- assertion: this.assertion,
312
- });
313
- this.lookupExpanded = false;
314
- // when id changes, update form
315
- effect(() => {
316
- this.updateForm(this.id());
203
+ /**
204
+ * Emitted when the user requests more items from an external lookup.
205
+ */
206
+ extMoreRequest = output();
207
+ /**
208
+ * Emitted when the user changes the external lookup configuration.
209
+ */
210
+ extLookupConfigChange = output();
211
+ // by type
212
+ modelEntries;
213
+ partTypeKeys;
214
+ // by item
215
+ itemParts;
216
+ // form - by item
217
+ item;
218
+ itemPart;
219
+ // form - by type
220
+ partTypeKey;
221
+ // form - both
222
+ gid;
223
+ label;
224
+ byTypeMode;
225
+ external;
226
+ form;
227
+ filter;
228
+ pinFilterOptions;
229
+ lookupData;
230
+ constructor(_presetLookupDefs, itemLookupService, pinLookupService, _itemService, _thesService, _snackbar, formBuilder) {
231
+ this._presetLookupDefs = _presetLookupDefs;
232
+ this.itemLookupService = itemLookupService;
233
+ this.pinLookupService = pinLookupService;
234
+ this._itemService = _itemService;
235
+ this._thesService = _thesService;
236
+ this._snackbar = _snackbar;
237
+ this.partTypeKeys = [];
238
+ this.itemParts = [];
239
+ this.modelEntries = [];
240
+ // this is the default filter for the pin lookup, which will
241
+ // be merged with values provided by user here
242
+ this.filter = {
243
+ text: '',
244
+ limit: 10,
245
+ };
246
+ // form
247
+ this.item = formBuilder.control(null);
248
+ this.itemPart = formBuilder.control(null);
249
+ this.partTypeKey = formBuilder.control(null);
250
+ this.gid = formBuilder.control(null, [
251
+ Validators.required,
252
+ Validators.maxLength(300),
253
+ ]);
254
+ this.label = formBuilder.control(null, [
255
+ Validators.required,
256
+ Validators.maxLength(300),
257
+ ]);
258
+ this.byTypeMode = formBuilder.control(false, { nonNullable: true });
259
+ this.external = formBuilder.control(false, { nonNullable: true });
260
+ this.form = formBuilder.group({
261
+ item: this.item,
262
+ itemPart: this.itemPart,
263
+ partTypeKey: this.partTypeKey,
264
+ gid: this.gid,
265
+ label: this.label,
266
+ byTypeMode: this.byTypeMode,
267
+ external: this.external,
317
268
  });
269
+ // when pinByTypeMode changes, adjust form
270
+ effect(() => {
271
+ if (!this.byTypeMode) {
272
+ this._startWithByTypeMode = this.pinByTypeMode();
273
+ }
274
+ else {
275
+ this.byTypeMode.setValue(this.pinByTypeMode() || false, {
276
+ emitEvent: false,
277
+ });
278
+ this.byTypeMode.updateValueAndValidity();
279
+ }
280
+ });
281
+ // when target changes, update form
282
+ effect(() => {
283
+ if (this._noFormUpdate) {
284
+ this._noFormUpdate = false;
285
+ return;
286
+ }
287
+ console.log('target changed', this.target());
288
+ this.updateForm(this.target());
289
+ });
290
+ }
291
+ forceByItem() {
292
+ this.pinByTypeMode.set(false);
293
+ this.canSwitchMode.set(false);
294
+ }
295
+ setupKeys() {
296
+ // use DI presets if no lookup definitions
297
+ if (!this.lookupDefinitions()) {
298
+ this.lookupDefinitions.set(this._presetLookupDefs);
299
+ }
300
+ // keys are all the defined lookup searches
301
+ this.partTypeKeys = Object.keys(this.lookupDefinitions());
302
+ // if no keys, get them from thesaurus model-types;
303
+ // if this is not available, just force by item mode.
304
+ if (!this.partTypeKeys.length) {
305
+ if (this.modelEntries?.length) {
306
+ // set lookupDefinitions from thesaurus entries
307
+ const defs = {};
308
+ this.modelEntries.forEach((e) => {
309
+ defs[e.value] = {
310
+ name: e.value,
311
+ typeId: e.id,
312
+ };
313
+ });
314
+ this.lookupDefinitions.set(defs);
315
+ // set type keys from thesaurus entries
316
+ this.partTypeKeys = this.modelEntries.map((e) => e.value);
317
+ }
318
+ }
319
+ // if still no keys, force by item mode
320
+ if (!this.partTypeKeys.length) {
321
+ this.forceByItem();
322
+ }
323
+ else {
324
+ // set default key
325
+ this.partTypeKey.setValue(this.defaultPartTypeKey() || this.partTypeKeys[0]);
326
+ }
318
327
  }
319
328
  ngOnInit() {
320
- this._sub = this.form.valueChanges
321
- .pipe(debounceTime(300))
322
- .subscribe((_) => {
323
- if (!this._updatingForm) {
324
- this.emitIdChange();
329
+ // set start mode if required
330
+ if (this._startWithByTypeMode) {
331
+ this.byTypeMode.setValue(true);
332
+ }
333
+ // whenever item changes (by lookup), update item's parts and filter
334
+ this._subs.push(this.item.valueChanges
335
+ .pipe(distinctUntilChanged(), debounceTime(300))
336
+ .subscribe((item) => {
337
+ this.itemPart.setValue(null, { emitEvent: false });
338
+ this.itemParts = item?.parts || [];
339
+ this.filter = {
340
+ ...this.filter,
341
+ itemId: item?.id,
342
+ };
343
+ }));
344
+ // whenever itemPart changes (by user selection), update target and
345
+ // eventually gid
346
+ this._subs.push(this.itemPart.valueChanges
347
+ .pipe(distinctUntilChanged(), debounceTime(300))
348
+ .subscribe((part) => {
349
+ if (!this.gid.value || this.gid.pristine) {
350
+ this.gid.setValue(this.buildGid());
351
+ }
352
+ this.filter = {
353
+ ...this.filter,
354
+ partId: part?.id,
355
+ };
356
+ this.updateTarget(true);
357
+ }));
358
+ // whenever partTypeKey changes, update filter's options
359
+ this._subs.push(this.partTypeKey.valueChanges
360
+ .pipe(distinctUntilChanged(), debounceTime(300))
361
+ .subscribe((key) => {
362
+ this.pinFilterOptions = key
363
+ ? this.lookupDefinitions()[key]
364
+ : undefined;
365
+ }));
366
+ // whenever external changes, set required validator in label
367
+ // (true for external, false for internal)
368
+ this._subs.push(this.external.valueChanges
369
+ .pipe(distinctUntilChanged(), debounceTime(300))
370
+ .subscribe((external) => {
371
+ if (external) {
372
+ this.label.setValidators([
373
+ Validators.required,
374
+ Validators.maxLength(300),
375
+ ]);
325
376
  }
377
+ else {
378
+ this.label.setValidators([Validators.maxLength(300)]);
379
+ }
380
+ this.label.updateValueAndValidity();
381
+ }));
382
+ // load model-types thesaurus entries
383
+ this._thesService.getThesaurus('model-types', true).subscribe({
384
+ next: (t) => {
385
+ this.modelEntries = t.entries || [];
386
+ if (this.modelEntries?.length) {
387
+ this.setupKeys();
388
+ }
389
+ else {
390
+ this.forceByItem();
391
+ }
392
+ },
393
+ error: () => {
394
+ this.forceByItem();
395
+ },
326
396
  });
327
397
  }
328
398
  ngOnDestroy() {
329
- this._sub?.unsubscribe();
399
+ for (let i = 0; i < this._subs.length; i++) {
400
+ this._subs[i].unsubscribe();
401
+ }
330
402
  }
331
- onAssertionChange(assertion) {
332
- this.assertion.setValue(assertion || null);
403
+ buildGid() {
404
+ // the GID is the part ID if any, or the item ID, followed by
405
+ // the pin's value (=EID)
406
+ const pin = this.lookupData?.pin;
407
+ if (!pin?.value) {
408
+ return null;
409
+ }
410
+ return pin.partId
411
+ ? `P${pin.partId}/${pin.value}`
412
+ : `I${pin.itemId}/${pin.value}`;
333
413
  }
334
- onIdPick(id) {
335
- this.value.setValue(id);
336
- this.value.markAsDirty();
337
- this.value.updateValueAndValidity();
338
- this.lookupExpanded = false;
414
+ buildLabel() {
415
+ if (!this.lookupData?.pin) {
416
+ return null;
417
+ }
418
+ const sb = [];
419
+ // pin value
420
+ if (this.lookupData.pin.value) {
421
+ sb.push(this.lookupData.pin.value);
422
+ sb.push(' | ');
423
+ }
424
+ // item title
425
+ sb.push(this.lookupData.item?.title || this.lookupData.pin?.itemId);
426
+ // part type and role
427
+ if (this.lookupData.pin.partTypeId) {
428
+ const e = this.modelEntries?.find((e) => e.id === this.lookupData.pin.partTypeId);
429
+ sb.push(' (');
430
+ sb.push(e?.value || this.lookupData.pin.partTypeId);
431
+ if (this.lookupData.pin.roleId) {
432
+ sb.push(`, ${this.lookupData.pin.roleId}`);
433
+ }
434
+ sb.push(')');
435
+ }
436
+ return sb.join('');
339
437
  }
340
- updateForm(value) {
341
- this._updatingForm = true;
342
- if (!value) {
343
- this.form.reset();
438
+ getTarget() {
439
+ if (this.external.value) {
440
+ return {
441
+ gid: this.gid.value || '',
442
+ label: this.label.value || '',
443
+ };
344
444
  }
345
445
  else {
346
- this.tag.setValue(value.tag || null);
347
- this.value.setValue(value.value);
348
- this.label.setValue(value.label || null);
349
- this.scope.setValue(value.scope);
350
- this.assertion.setValue(value.assertion || null);
351
- this.form.markAsPristine();
446
+ const pin = this.lookupData?.pin;
447
+ return {
448
+ gid: this.gid.value || '',
449
+ label: this.label.value || '',
450
+ itemId: pin?.itemId || '',
451
+ partId: pin?.partId || '',
452
+ partTypeId: pin?.partTypeId || '',
453
+ roleId: pin?.roleId || '',
454
+ name: pin?.name || '',
455
+ value: pin?.value || '',
456
+ };
457
+ }
458
+ }
459
+ emitChange() {
460
+ this._noFormUpdate = true;
461
+ this.target.set(this.getTarget());
462
+ }
463
+ updateTarget(noEmit = false) {
464
+ if (this._noTargetUpdate) {
465
+ return;
466
+ }
467
+ if (!this.external.value) {
468
+ this.gid.setValue(this.buildGid());
469
+ this.gid.updateValueAndValidity();
470
+ this.gid.markAsDirty();
471
+ this.label.setValue(this.buildLabel());
472
+ this.label.updateValueAndValidity();
473
+ this.label.markAsDirty();
474
+ }
475
+ if (!noEmit) {
476
+ this.emitChange();
477
+ }
478
+ }
479
+ updateForm(target) {
480
+ // build pin info from target
481
+ if (!target) {
482
+ this.lookupData = undefined;
483
+ this.item.reset();
484
+ this.itemPart.reset();
485
+ this.gid.reset();
486
+ this.label.reset();
487
+ return;
488
+ }
489
+ this._noTargetUpdate = true;
490
+ this.gid.setValue(target.gid || '', { emitEvent: false });
491
+ this.label.setValue(target.label || '', { emitEvent: false });
492
+ this.lookupData = {
493
+ pin: {
494
+ itemId: target.itemId || '',
495
+ partId: target.partId || '',
496
+ partTypeId: target.partTypeId || '',
497
+ roleId: target.roleId || '',
498
+ name: target.name || '',
499
+ value: target.value || '',
500
+ },
501
+ };
502
+ // get item
503
+ if (target.itemId) {
504
+ this._itemService.getItem(target.itemId, true, true).subscribe({
505
+ next: (item) => {
506
+ this.item.setValue(item, { emitEvent: false });
507
+ this.form.markAsPristine();
508
+ this._noTargetUpdate = false;
509
+ this.external.setValue(!target.name, { emitEvent: false });
510
+ this.updateTarget();
511
+ },
512
+ error: (error) => {
513
+ if (error) {
514
+ console.error('Item service error', error);
515
+ }
516
+ this.external.setValue(!target.name, { emitEvent: false });
517
+ this._noTargetUpdate = false;
518
+ },
519
+ });
520
+ }
521
+ else {
522
+ this.external.setValue(!target.name && !this.internalDefault(), {
523
+ emitEvent: false,
524
+ });
525
+ this._noTargetUpdate = false;
526
+ this.updateTarget();
527
+ }
528
+ }
529
+ /**
530
+ * Called when the item lookup changes (item is looked up
531
+ * by its title).
532
+ *
533
+ * @param item The item got from lookup.
534
+ */
535
+ onItemLookupChange(item) {
536
+ if (!item) {
537
+ this.itemPart.setValue(null);
538
+ this.itemParts = [];
539
+ return;
540
+ }
541
+ // load item's parts
542
+ this._itemService.getItem(item.id, true, true).subscribe({
543
+ next: (i) => {
544
+ // setting the item will trigger its parts update
545
+ this.item.setValue(i);
546
+ this.updateTarget(true);
547
+ },
548
+ error: (error) => {
549
+ if (error) {
550
+ console.error('Error getting item', error);
551
+ }
552
+ this.itemPart.setValue(null);
553
+ this.itemParts = [];
554
+ this.updateTarget(true);
555
+ },
556
+ });
557
+ }
558
+ loadItemInfo(pin) {
559
+ if (!pin) {
560
+ return;
561
+ }
562
+ forkJoin({
563
+ item: this._itemService.getItem(pin.itemId, false, true),
564
+ part: this._itemService.getPartFromTypeAndRole(pin.itemId, METADATA_PART_ID$1, undefined, true),
565
+ })
566
+ .pipe(take(1))
567
+ .subscribe({
568
+ next: (result) => {
569
+ this.lookupData = {
570
+ pin: pin,
571
+ item: result.item,
572
+ metaPart: result.part,
573
+ };
574
+ this.updateTarget(true);
575
+ },
576
+ error: (error) => {
577
+ this.lookupData = undefined;
578
+ console.error('Error loading item/metadata', error);
579
+ },
580
+ });
581
+ }
582
+ /**
583
+ * Called when the pin lookup change. A pin is looked up by its
584
+ * name and value (=the filter's text), and optionally by:
585
+ * - its index lookup definition (selected by partTypeKey).
586
+ * - its item (defined by item, in filter).
587
+ * - its part (defined by itemPart, in filter).
588
+ *
589
+ * @param info The pin info from pin lookup.
590
+ */
591
+ onPinLookupChange(info) {
592
+ this.loadItemInfo(info);
593
+ }
594
+ onExtItemChange(event) {
595
+ if (event.item) {
596
+ setTimeout(() => {
597
+ this.gid.setValue(event.itemId);
598
+ this.gid.updateValueAndValidity();
599
+ this.gid.markAsDirty();
600
+ this.label.setValue(event.itemLabel);
601
+ this.label.updateValueAndValidity();
602
+ this.label.markAsDirty();
603
+ });
352
604
  }
353
- this._updatingForm = false;
354
605
  }
355
- getId() {
356
- return {
357
- tag: this.tag.value?.trim(),
358
- value: this.value.value?.trim() || '',
359
- label: this.label.value?.trim() || undefined,
360
- scope: this.scope.value?.trim() || '',
361
- assertion: this.assertion.value || undefined,
362
- };
606
+ onExtMoreRequest(event) {
607
+ this.extMoreRequest.emit(event);
363
608
  }
364
- emitIdChange() {
365
- if (!this.hasSubmit()) {
366
- this.id.set(this.getId());
367
- }
609
+ onCopied() {
610
+ this._snackbar.open('Copied to clipboard', 'OK', {
611
+ duration: 1500,
612
+ });
368
613
  }
369
- cancel() {
614
+ onExtConfigChange(config) {
615
+ this.extLookupConfigChange.emit(config);
616
+ }
617
+ close() {
370
618
  this.editorClose.emit();
371
619
  }
372
620
  save() {
373
- if (this.form.valid) {
374
- this.id.set(this.getId());
621
+ if (this.form.invalid) {
622
+ return;
375
623
  }
624
+ this.target.set(this.getTarget());
625
+ this.emitChange();
376
626
  }
377
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: AssertedIdComponent, deps: [{ token: i1$1.FormBuilder }, { token: PinRefLookupService }, { token: 'indexLookupDefinitions' }], target: i0.ɵɵFactoryTarget.Component });
378
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.0", type: AssertedIdComponent, isStandalone: true, selector: "cadmus-refs-asserted-id", inputs: { idScopeEntries: { classPropertyName: "idScopeEntries", publicName: "idScopeEntries", isSignal: true, isRequired: false, transformFunction: null }, idTagEntries: { classPropertyName: "idTagEntries", publicName: "idTagEntries", isSignal: true, isRequired: false, transformFunction: null }, assTagEntries: { classPropertyName: "assTagEntries", publicName: "assTagEntries", isSignal: true, isRequired: false, transformFunction: null }, refTypeEntries: { classPropertyName: "refTypeEntries", publicName: "refTypeEntries", isSignal: true, isRequired: false, transformFunction: null }, refTagEntries: { classPropertyName: "refTagEntries", publicName: "refTagEntries", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, noEidLookup: { classPropertyName: "noEidLookup", publicName: "noEidLookup", isSignal: true, isRequired: false, transformFunction: null }, hasSubmit: { classPropertyName: "hasSubmit", publicName: "hasSubmit", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { id: "idChange", editorClose: "editorClose" }, ngImport: i0, template: "<form [formGroup]=\"form\" (submit)=\"save()\">\n <div>\n <div class=\"form-row\">\n <!-- tag (bound) -->\n @if (idTagEntries()?.length) {\n <mat-form-field>\n <mat-label>tag</mat-label>\n <mat-select [formControl]=\"tag\">\n @for (e of idTagEntries(); track e) {\n <mat-option [value]=\"e.id\">{{ e.value }}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n }\n <!-- tag (free) -->\n @else {\n <mat-form-field>\n <mat-label>tag</mat-label>\n <input matInput [formControl]=\"tag\" />\n @if ($any(tag.errors)?.maxLength && (tag.dirty || tag.touched)) {\n <mat-error>tag too long</mat-error>\n }\n </mat-form-field>\n }\n\n <!-- scope (bound) -->\n @if (idScopeEntries()?.length) {\n <mat-form-field>\n <mat-label>scope</mat-label>\n <mat-select [formControl]=\"scope\">\n @for (e of idScopeEntries(); track e) {\n <mat-option [value]=\"e.id\">{{ e.value }}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n }\n <!-- scope (free) -->\n @else {\n <mat-form-field>\n <mat-label>scope</mat-label>\n <input matInput [formControl]=\"scope\" />\n @if ($any(scope.errors)?.maxLength && (scope.dirty || scope.touched)) {\n <mat-error>scope too long</mat-error>\n }\n </mat-form-field>\n }\n\n <!-- value -->\n <mat-form-field>\n <mat-label>value</mat-label>\n <input matInput [formControl]=\"value\" />\n @if ($any(value.errors)?.required && (value.dirty || value.touched)) {\n <mat-error>value required</mat-error>\n } @if ($any(value.errors)?.maxLength && (value.dirty || value.touched))\n {\n <mat-error>value too long</mat-error>\n }\n </mat-form-field>\n\n <!-- label -->\n <mat-form-field>\n <mat-label>label</mat-label>\n <input matInput [formControl]=\"label\" />\n @if ($any(label.errors)?.maxLength && (label.dirty || label.touched)) {\n <mat-error>label too long</mat-error>\n }\n </mat-form-field>\n\n <!-- lookup -->\n @if (!noEidLookup()) {\n <div>\n <mat-expansion-panel [(expanded)]=\"lookupExpanded\">\n <mat-expansion-panel-header>lookup</mat-expansion-panel-header>\n <cadmus-scoped-pin-lookup\n (idPick)=\"onIdPick($event)\"\n ></cadmus-scoped-pin-lookup>\n </mat-expansion-panel>\n </div>\n }\n </div>\n\n <!-- assertion -->\n <mat-expansion-panel>\n <mat-expansion-panel-header>assertion</mat-expansion-panel-header>\n <cadmus-refs-assertion\n [assTagEntries]=\"assTagEntries()\"\n [refTypeEntries]=\"refTypeEntries()\"\n [refTagEntries]=\"refTagEntries()\"\n [assertion]=\"assertion.value || undefined\"\n (assertionChange)=\"onAssertionChange($event)\"\n >\n </cadmus-refs-assertion>\n </mat-expansion-panel>\n </div>\n\n <!-- buttons -->\n @if (hasSubmit()) {\n <div>\n <button mat-icon-button type=\"button\" (click)=\"cancel()\">\n <mat-icon class=\"mat-warn\">close</mat-icon>\n </button>\n <button mat-icon-button type=\"submit\" [disabled]=\"form.invalid\">\n <mat-icon class=\"mat-primary\">check_circle</mat-icon>\n </button>\n </div>\n }\n</form>\n", styles: [".form-row{display:flex;gap:8px;align-items:flex-start;flex-wrap:wrap}.form-row *{flex:0 0 auto}.pin-info{font-size:90%;color:silver}fieldset{border:1px solid silver;border-radius:6px;padding:6px}@media only screen and (max-width: 959px){div#container{grid-template-rows:1fr auto;grid-template-columns:1fr;grid-template-areas:\"editor\" \"lookup\"}}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "component", type: i4.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i4.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i7.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i8.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i9.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i9.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: AssertionComponent, selector: "cadmus-refs-assertion", inputs: ["assTagEntries", "refTypeEntries", "refTagEntries", "assertion"], outputs: ["assertionChange"] }, { kind: "component", type: ScopedPinLookupComponent, selector: "cadmus-scoped-pin-lookup", outputs: ["idPick"] }] });
627
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: PinTargetLookupComponent, deps: [{ token: 'indexLookupDefinitions' }, { token: ItemRefLookupService }, { token: PinRefLookupService }, { token: i1.ItemService }, { token: i1.ThesaurusService }, { token: i4.MatSnackBar }, { token: i1$1.FormBuilder }], target: i0.ɵɵFactoryTarget.Component });
628
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.0", type: PinTargetLookupComponent, isStandalone: true, selector: "cadmus-pin-target-lookup", inputs: { pinByTypeMode: { classPropertyName: "pinByTypeMode", publicName: "pinByTypeMode", isSignal: true, isRequired: false, transformFunction: null }, canSwitchMode: { classPropertyName: "canSwitchMode", publicName: "canSwitchMode", isSignal: true, isRequired: false, transformFunction: null }, canEditTarget: { classPropertyName: "canEditTarget", publicName: "canEditTarget", isSignal: true, isRequired: false, transformFunction: null }, lookupDefinitions: { classPropertyName: "lookupDefinitions", publicName: "lookupDefinitions", isSignal: true, isRequired: false, transformFunction: null }, extLookupConfigs: { classPropertyName: "extLookupConfigs", publicName: "extLookupConfigs", isSignal: true, isRequired: false, transformFunction: null }, internalDefault: { classPropertyName: "internalDefault", publicName: "internalDefault", isSignal: true, isRequired: false, transformFunction: null }, target: { classPropertyName: "target", publicName: "target", isSignal: true, isRequired: false, transformFunction: null }, defaultPartTypeKey: { classPropertyName: "defaultPartTypeKey", publicName: "defaultPartTypeKey", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { pinByTypeMode: "pinByTypeModeChange", canSwitchMode: "canSwitchModeChange", lookupDefinitions: "lookupDefinitionsChange", target: "targetChange", editorClose: "editorClose", extMoreRequest: "extMoreRequest", extLookupConfigChange: "extLookupConfigChange" }, ngImport: i0, template: "<form [formGroup]=\"form\" (submit)=\"save()\">\r\n <div class=\"form-row\">\r\n <!-- external -->\r\n <mat-checkbox [formControl]=\"external\">external</mat-checkbox>\r\n <!-- mode switcher -->\r\n @if (!external.value) {\r\n <div>\r\n @if (canSwitchMode()) {\r\n <mat-checkbox [formControl]=\"byTypeMode\"> by type</mat-checkbox>\r\n }\r\n </div>\r\n }\r\n </div>\r\n\r\n <div class=\"form-row\">\r\n <!-- label -->\r\n <div>\r\n @if (external.value || canEditTarget()) {\r\n <mat-form-field>\r\n <mat-label>label</mat-label>\r\n <input matInput [formControl]=\"label\" />\r\n @if ($any(label).errors?.required && (label.dirty || label.touched)) {\r\n <mat-error>label required</mat-error>\r\n } @if ( $any(label).errors?.maxLength && (label.dirty || label.touched)\r\n ) {\r\n <mat-error>label too long</mat-error>\r\n }\r\n </mat-form-field>\r\n } @if (!external.value && !canEditTarget() && label.value) {\r\n <div class=\"info\"><span class=\"label\">label</span>{{ label.value }}</div>\r\n }\r\n </div>\r\n\r\n <!-- gid -->\r\n <div>\r\n @if (external.value || canEditTarget()) {\r\n <mat-form-field>\r\n <mat-label>GID</mat-label>\r\n <input matInput [formControl]=\"gid\" />\r\n @if ($any(gid).errors?.required && (gid.dirty || gid.touched)) {\r\n <mat-error>GID required</mat-error>\r\n } @if ($any(gid).errors?.maxLength && (gid.dirty || gid.touched)) {\r\n <mat-error>GID too long</mat-error>\r\n }\r\n </mat-form-field>\r\n } @if (!external.value && !canEditTarget() && gid.value) {\r\n <div class=\"info\">\r\n <span class=\"label\">GID</span> <span class=\"gid\">{{ gid.value }}</span>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n\r\n <!-- external lookup set -->\r\n @if (external.value && extLookupConfigs().length) {\r\n <fieldset>\r\n <legend>external lookup</legend>\r\n <cadmus-ref-lookup-set\r\n [configs]=\"extLookupConfigs()\"\r\n (itemChange)=\"onExtItemChange($event)\"\r\n (moreRequest)=\"onExtMoreRequest($event)\"\r\n (configChange)=\"onExtConfigChange($any($event))\"\r\n />\r\n </fieldset>\r\n }\r\n\r\n <!-- BY ITEM -->\r\n @if (!external.value) {\r\n <fieldset>\r\n <legend>internal lookup</legend>\r\n <div class=\"form-row\">\r\n @if (!byTypeMode.value) {\r\n <fieldset class=\"form-row\">\r\n <legend>pin filters</legend>\r\n <!-- item filter -->\r\n <cadmus-ref-lookup\r\n [service]=\"itemLookupService\"\r\n label=\"item\"\r\n (itemChange)=\"onItemLookupChange($event)\"\r\n />\r\n <!-- part filter -->\r\n @if (itemParts.length) {\r\n <mat-form-field>\r\n <mat-label>part</mat-label>\r\n <mat-select [formControl]=\"itemPart\">\r\n <mat-option [value]=\"null\">(any)</mat-option>\r\n @for (p of itemParts; track p) {\r\n <mat-option [value]=\"p\">{{\r\n p.typeId | flatLookup : modelEntries : \"id\" : \"value\"\r\n }}</mat-option>\r\n }\r\n </mat-select>\r\n <mat-hint>parts: {{ itemParts.length }}</mat-hint>\r\n </mat-form-field>\r\n }\r\n </fieldset>\r\n }\r\n <!-- BY TYPE -->\r\n @if (byTypeMode.value) {\r\n <div>\r\n <!-- part type filter -->\r\n @if (partTypeKeys.length) {\r\n <mat-form-field>\r\n <mat-label>part type</mat-label>\r\n <mat-select [formControl]=\"partTypeKey\">\r\n @for (k of partTypeKeys; track k) {\r\n <mat-option [value]=\"k\">{{ k }}</mat-option>\r\n }\r\n </mat-select>\r\n </mat-form-field>\r\n }\r\n </div>\r\n }\r\n <!-- PIN -->\r\n @if (partTypeKey.value) {\r\n <div>\r\n <!-- pin lookup -->\r\n <cadmus-ref-lookup\r\n [service]=\"pinLookupService\"\r\n [baseFilter]=\"filter\"\r\n [options]=\"pinFilterOptions\"\r\n label=\"pin\"\r\n (itemChange)=\"onPinLookupChange($event)\"\r\n />\r\n </div>\r\n }\r\n </div>\r\n <!-- data -->\r\n @if (lookupData?.pin?.name) {\r\n <mat-expansion-panel id=\"data\">\r\n <mat-expansion-panel-header>pin data</mat-expansion-panel-header>\r\n <!-- table -->\r\n <table>\r\n <thead>\r\n <th></th>\r\n <th>source</th>\r\n <th>value</th>\r\n </thead>\r\n <tbody>\r\n <!-- pin -->\r\n @if (lookupData?.pin?.value) {\r\n <tr>\r\n <td class=\"fit-width\">\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Copy value\"\r\n [cdkCopyToClipboard]=\"lookupData!.pin!.value\"\r\n (cdkCopyToClipboardCopied)=\"onCopied()\"\r\n >\r\n <mat-icon class=\"mat-primary\">content_copy</mat-icon>\r\n </button>\r\n </td>\r\n <td>pin</td>\r\n <td>{{ lookupData!.pin.value }}</td>\r\n </tr>\r\n }\r\n <!-- item ID -->\r\n @if (lookupData?.pin?.itemId) {\r\n <tr>\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n [cdkCopyToClipboard]=\"lookupData!.pin!.itemId\"\r\n (cdkCopyToClipboardCopied)=\"onCopied()\"\r\n >\r\n <mat-icon class=\"mat-primary\">content_copy</mat-icon>\r\n </button>\r\n </td>\r\n <td>item ID</td>\r\n <td>{{ lookupData!.pin.itemId }}</td>\r\n </tr>\r\n }\r\n <!-- item title -->\r\n @if (lookupData?.item?.title) {\r\n <tr>\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n [cdkCopyToClipboard]=\"lookupData!.item!.title\"\r\n (cdkCopyToClipboardCopied)=\"onCopied()\"\r\n >\r\n <mat-icon class=\"mat-primary\">content_copy</mat-icon>\r\n </button>\r\n </td>\r\n <td>item title</td>\r\n <td>{{ lookupData!.item!.title }}</td>\r\n </tr>\r\n }\r\n <!-- part ID -->\r\n @if (lookupData?.pin?.partId) {\r\n <tr>\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n [cdkCopyToClipboard]=\"lookupData!.pin!.partId\"\r\n (cdkCopyToClipboardCopied)=\"onCopied()\"\r\n >\r\n <mat-icon class=\"mat-primary\">content_copy</mat-icon>\r\n </button>\r\n </td>\r\n <td>part ID</td>\r\n <td>{{ lookupData!.pin.partId }}</td>\r\n </tr>\r\n }\r\n <!-- part type ID -->\r\n @if (lookupData?.pin?.partTypeId) {\r\n <tr>\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n [cdkCopyToClipboard]=\"lookupData!.pin!.partTypeId\"\r\n (cdkCopyToClipboardCopied)=\"onCopied()\"\r\n >\r\n <mat-icon class=\"mat-primary\">content_copy</mat-icon>\r\n </button>\r\n </td>\r\n <td>part type ID</td>\r\n <td>{{ lookupData!.pin!.partTypeId }}</td>\r\n </tr>\r\n }\r\n <!-- part role ID -->\r\n @if (lookupData?.pin?.roleId) {\r\n <tr>\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n [cdkCopyToClipboard]=\"lookupData!.pin!.roleId!\"\r\n (cdkCopyToClipboardCopied)=\"onCopied()\"\r\n >\r\n <mat-icon class=\"mat-primary\">content_copy</mat-icon>\r\n </button>\r\n </td>\r\n <td>part role ID</td>\r\n <td>{{ lookupData!.pin!.roleId }}</td>\r\n </tr>\r\n }\r\n <!-- part's metadata -->\r\n @for ( m of lookupData?.metaPart?.metadata || []; track m; let i =\r\n $index) {\r\n <tr>\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n [cdkCopyToClipboard]=\"m.value\"\r\n (cdkCopyToClipboardCopied)=\"onCopied()\"\r\n >\r\n <mat-icon class=\"mat-primary\">content_copy</mat-icon>\r\n </button>\r\n </td>\r\n <td class=\"metadata\">{{ m.name }}</td>\r\n <td class=\"metadata\">{{ m.value }}</td>\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n </mat-expansion-panel>\r\n }\r\n </fieldset>\r\n }\r\n\r\n <!-- buttons -->\r\n <div class=\"button-row\" id=\"toolbar\">\r\n <button mat-icon-button type=\"button\" (click)=\"close()\">\r\n <mat-icon class=\"mat-warn\">close</mat-icon>\r\n </button>\r\n <button mat-flat-button type=\"submit\" [disabled]=\"form.invalid\">\r\n <mat-icon>check_circle</mat-icon>\r\n target\r\n </button>\r\n </div>\r\n</form>\r\n", styles: [".metadata{color:#4a3001}.info{border:1px solid silver;border-radius:6px;background-color:silver;color:#fff;padding:4px;margin:8px 0}.info .label{background-color:#fff;color:silver;margin:0 6px}#data{margin:8px 0}table{border:1px solid silver;border-radius:6px;padding:4px;margin-top:8px}tr:nth-child(odd){background-color:#f0f0f0}td.fit-width{width:1px;white-space:nowrap}th{font-weight:400;text-align:left;color:silver}.form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}.button-row{display:flex;align-items:center;flex-wrap:wrap}.label{border:1px solid silver;border-radius:6px;padding:4px}fieldset{border:1px solid silver;border-radius:6px;padding:8px;margin-bottom:8px}legend{color:silver}div#toolbar{margin-top:8px}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type:
629
+ // material
630
+ ClipboardModule }, { kind: "directive", type: i6.CdkCopyToClipboard, selector: "[cdkCopyToClipboard]", inputs: ["cdkCopyToClipboard", "cdkCopyToClipboardAttempts"], outputs: ["cdkCopyToClipboardCopied"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i3.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i8.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "component", type: i4$1.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i4$1.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i6$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6$1.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6$1.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i6$1.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i7.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i8$1.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i9.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i9.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i14.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "pipe", type:
631
+ // myrmidon
632
+ FlatLookupPipe, name: "flatLookup" }, { kind: "component", type:
633
+ // bricks
634
+ RefLookupComponent, selector: "cadmus-ref-lookup", inputs: ["label", "limit", "baseFilter", "service", "item", "required", "hasMore", "linkTemplate", "optDialog", "options"], outputs: ["itemChange", "optionsChange", "moreRequest"] }, { kind: "component", type: RefLookupSetComponent, selector: "cadmus-ref-lookup-set", inputs: ["configs", "iconSize"], outputs: ["configChange", "itemChange", "moreRequest"] }] });
379
635
  }
380
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: AssertedIdComponent, decorators: [{
636
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: PinTargetLookupComponent, decorators: [{
381
637
  type: Component,
382
- args: [{ selector: 'cadmus-refs-asserted-id', imports: [
638
+ args: [{ selector: 'cadmus-pin-target-lookup', imports: [
383
639
  FormsModule,
384
640
  ReactiveFormsModule,
641
+ // material
642
+ ClipboardModule,
385
643
  MatButtonModule,
644
+ MatCheckboxModule,
386
645
  MatExpansionModule,
387
646
  MatFormFieldModule,
388
647
  MatIconModule,
389
648
  MatInputModule,
390
649
  MatSelectModule,
391
- AssertionComponent,
392
- ScopedPinLookupComponent,
393
- ], template: "<form [formGroup]=\"form\" (submit)=\"save()\">\n <div>\n <div class=\"form-row\">\n <!-- tag (bound) -->\n @if (idTagEntries()?.length) {\n <mat-form-field>\n <mat-label>tag</mat-label>\n <mat-select [formControl]=\"tag\">\n @for (e of idTagEntries(); track e) {\n <mat-option [value]=\"e.id\">{{ e.value }}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n }\n <!-- tag (free) -->\n @else {\n <mat-form-field>\n <mat-label>tag</mat-label>\n <input matInput [formControl]=\"tag\" />\n @if ($any(tag.errors)?.maxLength && (tag.dirty || tag.touched)) {\n <mat-error>tag too long</mat-error>\n }\n </mat-form-field>\n }\n\n <!-- scope (bound) -->\n @if (idScopeEntries()?.length) {\n <mat-form-field>\n <mat-label>scope</mat-label>\n <mat-select [formControl]=\"scope\">\n @for (e of idScopeEntries(); track e) {\n <mat-option [value]=\"e.id\">{{ e.value }}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n }\n <!-- scope (free) -->\n @else {\n <mat-form-field>\n <mat-label>scope</mat-label>\n <input matInput [formControl]=\"scope\" />\n @if ($any(scope.errors)?.maxLength && (scope.dirty || scope.touched)) {\n <mat-error>scope too long</mat-error>\n }\n </mat-form-field>\n }\n\n <!-- value -->\n <mat-form-field>\n <mat-label>value</mat-label>\n <input matInput [formControl]=\"value\" />\n @if ($any(value.errors)?.required && (value.dirty || value.touched)) {\n <mat-error>value required</mat-error>\n } @if ($any(value.errors)?.maxLength && (value.dirty || value.touched))\n {\n <mat-error>value too long</mat-error>\n }\n </mat-form-field>\n\n <!-- label -->\n <mat-form-field>\n <mat-label>label</mat-label>\n <input matInput [formControl]=\"label\" />\n @if ($any(label.errors)?.maxLength && (label.dirty || label.touched)) {\n <mat-error>label too long</mat-error>\n }\n </mat-form-field>\n\n <!-- lookup -->\n @if (!noEidLookup()) {\n <div>\n <mat-expansion-panel [(expanded)]=\"lookupExpanded\">\n <mat-expansion-panel-header>lookup</mat-expansion-panel-header>\n <cadmus-scoped-pin-lookup\n (idPick)=\"onIdPick($event)\"\n ></cadmus-scoped-pin-lookup>\n </mat-expansion-panel>\n </div>\n }\n </div>\n\n <!-- assertion -->\n <mat-expansion-panel>\n <mat-expansion-panel-header>assertion</mat-expansion-panel-header>\n <cadmus-refs-assertion\n [assTagEntries]=\"assTagEntries()\"\n [refTypeEntries]=\"refTypeEntries()\"\n [refTagEntries]=\"refTagEntries()\"\n [assertion]=\"assertion.value || undefined\"\n (assertionChange)=\"onAssertionChange($event)\"\n >\n </cadmus-refs-assertion>\n </mat-expansion-panel>\n </div>\n\n <!-- buttons -->\n @if (hasSubmit()) {\n <div>\n <button mat-icon-button type=\"button\" (click)=\"cancel()\">\n <mat-icon class=\"mat-warn\">close</mat-icon>\n </button>\n <button mat-icon-button type=\"submit\" [disabled]=\"form.invalid\">\n <mat-icon class=\"mat-primary\">check_circle</mat-icon>\n </button>\n </div>\n }\n</form>\n", styles: [".form-row{display:flex;gap:8px;align-items:flex-start;flex-wrap:wrap}.form-row *{flex:0 0 auto}.pin-info{font-size:90%;color:silver}fieldset{border:1px solid silver;border-radius:6px;padding:6px}@media only screen and (max-width: 959px){div#container{grid-template-rows:1fr auto;grid-template-columns:1fr;grid-template-areas:\"editor\" \"lookup\"}}\n"] }]
394
- }], ctorParameters: () => [{ type: i1$1.FormBuilder }, { type: PinRefLookupService }, { type: undefined, decorators: [{
650
+ MatTooltipModule,
651
+ // myrmidon
652
+ FlatLookupPipe,
653
+ // bricks
654
+ RefLookupComponent,
655
+ RefLookupSetComponent,
656
+ ], template: "<form [formGroup]=\"form\" (submit)=\"save()\">\r\n <div class=\"form-row\">\r\n <!-- external -->\r\n <mat-checkbox [formControl]=\"external\">external</mat-checkbox>\r\n <!-- mode switcher -->\r\n @if (!external.value) {\r\n <div>\r\n @if (canSwitchMode()) {\r\n <mat-checkbox [formControl]=\"byTypeMode\"> by type</mat-checkbox>\r\n }\r\n </div>\r\n }\r\n </div>\r\n\r\n <div class=\"form-row\">\r\n <!-- label -->\r\n <div>\r\n @if (external.value || canEditTarget()) {\r\n <mat-form-field>\r\n <mat-label>label</mat-label>\r\n <input matInput [formControl]=\"label\" />\r\n @if ($any(label).errors?.required && (label.dirty || label.touched)) {\r\n <mat-error>label required</mat-error>\r\n } @if ( $any(label).errors?.maxLength && (label.dirty || label.touched)\r\n ) {\r\n <mat-error>label too long</mat-error>\r\n }\r\n </mat-form-field>\r\n } @if (!external.value && !canEditTarget() && label.value) {\r\n <div class=\"info\"><span class=\"label\">label</span>{{ label.value }}</div>\r\n }\r\n </div>\r\n\r\n <!-- gid -->\r\n <div>\r\n @if (external.value || canEditTarget()) {\r\n <mat-form-field>\r\n <mat-label>GID</mat-label>\r\n <input matInput [formControl]=\"gid\" />\r\n @if ($any(gid).errors?.required && (gid.dirty || gid.touched)) {\r\n <mat-error>GID required</mat-error>\r\n } @if ($any(gid).errors?.maxLength && (gid.dirty || gid.touched)) {\r\n <mat-error>GID too long</mat-error>\r\n }\r\n </mat-form-field>\r\n } @if (!external.value && !canEditTarget() && gid.value) {\r\n <div class=\"info\">\r\n <span class=\"label\">GID</span> <span class=\"gid\">{{ gid.value }}</span>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n\r\n <!-- external lookup set -->\r\n @if (external.value && extLookupConfigs().length) {\r\n <fieldset>\r\n <legend>external lookup</legend>\r\n <cadmus-ref-lookup-set\r\n [configs]=\"extLookupConfigs()\"\r\n (itemChange)=\"onExtItemChange($event)\"\r\n (moreRequest)=\"onExtMoreRequest($event)\"\r\n (configChange)=\"onExtConfigChange($any($event))\"\r\n />\r\n </fieldset>\r\n }\r\n\r\n <!-- BY ITEM -->\r\n @if (!external.value) {\r\n <fieldset>\r\n <legend>internal lookup</legend>\r\n <div class=\"form-row\">\r\n @if (!byTypeMode.value) {\r\n <fieldset class=\"form-row\">\r\n <legend>pin filters</legend>\r\n <!-- item filter -->\r\n <cadmus-ref-lookup\r\n [service]=\"itemLookupService\"\r\n label=\"item\"\r\n (itemChange)=\"onItemLookupChange($event)\"\r\n />\r\n <!-- part filter -->\r\n @if (itemParts.length) {\r\n <mat-form-field>\r\n <mat-label>part</mat-label>\r\n <mat-select [formControl]=\"itemPart\">\r\n <mat-option [value]=\"null\">(any)</mat-option>\r\n @for (p of itemParts; track p) {\r\n <mat-option [value]=\"p\">{{\r\n p.typeId | flatLookup : modelEntries : \"id\" : \"value\"\r\n }}</mat-option>\r\n }\r\n </mat-select>\r\n <mat-hint>parts: {{ itemParts.length }}</mat-hint>\r\n </mat-form-field>\r\n }\r\n </fieldset>\r\n }\r\n <!-- BY TYPE -->\r\n @if (byTypeMode.value) {\r\n <div>\r\n <!-- part type filter -->\r\n @if (partTypeKeys.length) {\r\n <mat-form-field>\r\n <mat-label>part type</mat-label>\r\n <mat-select [formControl]=\"partTypeKey\">\r\n @for (k of partTypeKeys; track k) {\r\n <mat-option [value]=\"k\">{{ k }}</mat-option>\r\n }\r\n </mat-select>\r\n </mat-form-field>\r\n }\r\n </div>\r\n }\r\n <!-- PIN -->\r\n @if (partTypeKey.value) {\r\n <div>\r\n <!-- pin lookup -->\r\n <cadmus-ref-lookup\r\n [service]=\"pinLookupService\"\r\n [baseFilter]=\"filter\"\r\n [options]=\"pinFilterOptions\"\r\n label=\"pin\"\r\n (itemChange)=\"onPinLookupChange($event)\"\r\n />\r\n </div>\r\n }\r\n </div>\r\n <!-- data -->\r\n @if (lookupData?.pin?.name) {\r\n <mat-expansion-panel id=\"data\">\r\n <mat-expansion-panel-header>pin data</mat-expansion-panel-header>\r\n <!-- table -->\r\n <table>\r\n <thead>\r\n <th></th>\r\n <th>source</th>\r\n <th>value</th>\r\n </thead>\r\n <tbody>\r\n <!-- pin -->\r\n @if (lookupData?.pin?.value) {\r\n <tr>\r\n <td class=\"fit-width\">\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Copy value\"\r\n [cdkCopyToClipboard]=\"lookupData!.pin!.value\"\r\n (cdkCopyToClipboardCopied)=\"onCopied()\"\r\n >\r\n <mat-icon class=\"mat-primary\">content_copy</mat-icon>\r\n </button>\r\n </td>\r\n <td>pin</td>\r\n <td>{{ lookupData!.pin.value }}</td>\r\n </tr>\r\n }\r\n <!-- item ID -->\r\n @if (lookupData?.pin?.itemId) {\r\n <tr>\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n [cdkCopyToClipboard]=\"lookupData!.pin!.itemId\"\r\n (cdkCopyToClipboardCopied)=\"onCopied()\"\r\n >\r\n <mat-icon class=\"mat-primary\">content_copy</mat-icon>\r\n </button>\r\n </td>\r\n <td>item ID</td>\r\n <td>{{ lookupData!.pin.itemId }}</td>\r\n </tr>\r\n }\r\n <!-- item title -->\r\n @if (lookupData?.item?.title) {\r\n <tr>\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n [cdkCopyToClipboard]=\"lookupData!.item!.title\"\r\n (cdkCopyToClipboardCopied)=\"onCopied()\"\r\n >\r\n <mat-icon class=\"mat-primary\">content_copy</mat-icon>\r\n </button>\r\n </td>\r\n <td>item title</td>\r\n <td>{{ lookupData!.item!.title }}</td>\r\n </tr>\r\n }\r\n <!-- part ID -->\r\n @if (lookupData?.pin?.partId) {\r\n <tr>\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n [cdkCopyToClipboard]=\"lookupData!.pin!.partId\"\r\n (cdkCopyToClipboardCopied)=\"onCopied()\"\r\n >\r\n <mat-icon class=\"mat-primary\">content_copy</mat-icon>\r\n </button>\r\n </td>\r\n <td>part ID</td>\r\n <td>{{ lookupData!.pin.partId }}</td>\r\n </tr>\r\n }\r\n <!-- part type ID -->\r\n @if (lookupData?.pin?.partTypeId) {\r\n <tr>\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n [cdkCopyToClipboard]=\"lookupData!.pin!.partTypeId\"\r\n (cdkCopyToClipboardCopied)=\"onCopied()\"\r\n >\r\n <mat-icon class=\"mat-primary\">content_copy</mat-icon>\r\n </button>\r\n </td>\r\n <td>part type ID</td>\r\n <td>{{ lookupData!.pin!.partTypeId }}</td>\r\n </tr>\r\n }\r\n <!-- part role ID -->\r\n @if (lookupData?.pin?.roleId) {\r\n <tr>\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n [cdkCopyToClipboard]=\"lookupData!.pin!.roleId!\"\r\n (cdkCopyToClipboardCopied)=\"onCopied()\"\r\n >\r\n <mat-icon class=\"mat-primary\">content_copy</mat-icon>\r\n </button>\r\n </td>\r\n <td>part role ID</td>\r\n <td>{{ lookupData!.pin!.roleId }}</td>\r\n </tr>\r\n }\r\n <!-- part's metadata -->\r\n @for ( m of lookupData?.metaPart?.metadata || []; track m; let i =\r\n $index) {\r\n <tr>\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n [cdkCopyToClipboard]=\"m.value\"\r\n (cdkCopyToClipboardCopied)=\"onCopied()\"\r\n >\r\n <mat-icon class=\"mat-primary\">content_copy</mat-icon>\r\n </button>\r\n </td>\r\n <td class=\"metadata\">{{ m.name }}</td>\r\n <td class=\"metadata\">{{ m.value }}</td>\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n </mat-expansion-panel>\r\n }\r\n </fieldset>\r\n }\r\n\r\n <!-- buttons -->\r\n <div class=\"button-row\" id=\"toolbar\">\r\n <button mat-icon-button type=\"button\" (click)=\"close()\">\r\n <mat-icon class=\"mat-warn\">close</mat-icon>\r\n </button>\r\n <button mat-flat-button type=\"submit\" [disabled]=\"form.invalid\">\r\n <mat-icon>check_circle</mat-icon>\r\n target\r\n </button>\r\n </div>\r\n</form>\r\n", styles: [".metadata{color:#4a3001}.info{border:1px solid silver;border-radius:6px;background-color:silver;color:#fff;padding:4px;margin:8px 0}.info .label{background-color:#fff;color:silver;margin:0 6px}#data{margin:8px 0}table{border:1px solid silver;border-radius:6px;padding:4px;margin-top:8px}tr:nth-child(odd){background-color:#f0f0f0}td.fit-width{width:1px;white-space:nowrap}th{font-weight:400;text-align:left;color:silver}.form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}.button-row{display:flex;align-items:center;flex-wrap:wrap}.label{border:1px solid silver;border-radius:6px;padding:4px}fieldset{border:1px solid silver;border-radius:6px;padding:8px;margin-bottom:8px}legend{color:silver}div#toolbar{margin-top:8px}\n"] }]
657
+ }], ctorParameters: () => [{ type: undefined, decorators: [{
395
658
  type: Inject,
396
659
  args: ['indexLookupDefinitions']
397
- }] }] });
660
+ }] }, { type: ItemRefLookupService }, { type: PinRefLookupService }, { type: i1.ItemService }, { type: i1.ThesaurusService }, { type: i4.MatSnackBar }, { type: i1$1.FormBuilder }] });
398
661
 
399
662
  /**
400
- * Asserted IDs editor.
663
+ * The key to be used to retrieve the external lookup configs from the
664
+ * settings storage. This is equal to the selector of
665
+ * AssertedCompositeIdComponent plus ".configs".
401
666
  */
402
- class AssertedIdsComponent {
403
- _dialogService;
404
- _editedIndex;
405
- edited;
406
- /**
407
- * The asserted IDs.
408
- */
409
- ids = model([]);
667
+ const ASSERTED_COMPOSITE_ID_CONFIGS_KEY = 'cadmus-refs-asserted-composite-id.configs';
668
+ /**
669
+ * An asserted composite ID editor. This allows the user to edit an asserted
670
+ * composite ID, which can be an external ID or a lookup ID.
671
+ */
672
+ class AssertedCompositeIdComponent {
673
+ lookupService;
674
+ lookupDefs;
675
+ _sub;
676
+ _updatingForm;
677
+ extLookupConfigs;
678
+ targetExpanded = false;
679
+ // form
680
+ target;
681
+ scope;
682
+ tag;
683
+ assertion;
684
+ form;
410
685
  // asserted-id-scopes
411
686
  idScopeEntries = input();
412
687
  // asserted-id-tags
@@ -417,680 +692,532 @@ class AssertedIdsComponent {
417
692
  refTypeEntries = input();
418
693
  // doc-reference-tags
419
694
  refTagEntries = input();
420
- entries;
421
- form;
422
- constructor(formBuilder, _dialogService) {
423
- this._dialogService = _dialogService;
424
- this._editedIndex = -1;
425
- this.entries = formBuilder.control([], { nonNullable: true });
426
- // form
427
- this.form = formBuilder.group({
428
- ids: this.entries,
429
- });
430
- // when ids change, update form
431
- effect(() => {
432
- this.updateForm(this.ids());
433
- });
434
- }
435
- updateForm(ids) {
436
- if (!ids?.length) {
437
- this.form.reset();
438
- return;
439
- }
440
- this.entries.setValue(ids, { emitEvent: false });
441
- this.entries.updateValueAndValidity();
442
- this.form.markAsPristine();
443
- }
444
- addId() {
445
- this.editId({
446
- scope: '',
447
- value: '',
448
- }, -1);
449
- }
450
- editId(id, index) {
451
- this._editedIndex = index;
452
- this.edited = id;
453
- }
454
- closeId() {
455
- this._editedIndex = -1;
456
- this.edited = undefined;
457
- }
458
- saveId(entry) {
459
- const entries = [...this.entries.value];
460
- if (this._editedIndex === -1) {
461
- entries.push(entry);
462
- }
463
- else {
464
- entries.splice(this._editedIndex, 1, entry);
465
- }
466
- this.entries.setValue(entries);
467
- this.entries.markAsDirty();
468
- this.entries.updateValueAndValidity();
469
- this.closeId();
470
- }
471
- deleteId(index) {
472
- this._dialogService
473
- .confirm('Confirmation', 'Delete ID?')
474
- .pipe(take(1))
475
- .subscribe((yes) => {
476
- if (yes) {
477
- if (this._editedIndex === index) {
478
- this.closeId();
479
- }
480
- const entries = [...this.entries.value];
481
- entries.splice(index, 1);
482
- this.entries.setValue(entries);
483
- this.entries.markAsDirty();
484
- this.entries.updateValueAndValidity();
485
- this.ids.set(this.entries.value);
486
- }
487
- });
488
- }
489
- moveIdUp(index) {
490
- if (index < 1) {
491
- return;
492
- }
493
- const entry = this.entries.value[index];
494
- const entries = [...this.entries.value];
495
- entries.splice(index, 1);
496
- entries.splice(index - 1, 0, entry);
497
- this.entries.setValue(entries);
498
- this.entries.markAsDirty();
499
- this.entries.updateValueAndValidity();
500
- this.ids.set(this.entries.value);
501
- }
502
- moveIdDown(index) {
503
- if (index + 1 >= this.entries.value.length) {
504
- return;
505
- }
506
- const entry = this.entries.value[index];
507
- const entries = [...this.entries.value];
508
- entries.splice(index, 1);
509
- entries.splice(index + 1, 0, entry);
510
- this.entries.setValue(entries);
511
- this.entries.markAsDirty();
512
- this.entries.updateValueAndValidity();
513
- this.ids.set(this.entries.value);
514
- }
515
- onIdChange(id) {
516
- this.saveId(id);
517
- this.ids.set(this.entries.value);
518
- }
519
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: AssertedIdsComponent, deps: [{ token: i1$1.FormBuilder }, { token: i2.DialogService }], target: i0.ɵɵFactoryTarget.Component });
520
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.0", type: AssertedIdsComponent, isStandalone: true, selector: "cadmus-refs-asserted-ids", inputs: { ids: { classPropertyName: "ids", publicName: "ids", isSignal: true, isRequired: false, transformFunction: null }, idScopeEntries: { classPropertyName: "idScopeEntries", publicName: "idScopeEntries", isSignal: true, isRequired: false, transformFunction: null }, idTagEntries: { classPropertyName: "idTagEntries", publicName: "idTagEntries", isSignal: true, isRequired: false, transformFunction: null }, assTagEntries: { classPropertyName: "assTagEntries", publicName: "assTagEntries", isSignal: true, isRequired: false, transformFunction: null }, refTypeEntries: { classPropertyName: "refTypeEntries", publicName: "refTypeEntries", isSignal: true, isRequired: false, transformFunction: null }, refTagEntries: { classPropertyName: "refTagEntries", publicName: "refTagEntries", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { ids: "idsChange" }, ngImport: i0, template: "<form [formGroup]=\"form\">\r\n <div>\r\n <button type=\"button\" mat-flat-button class=\"mat-primary\" (click)=\"addId()\">\r\n <mat-icon>add_circle</mat-icon> ID\r\n </button>\r\n </div>\r\n @if (entries.value.length) {\r\n <table>\r\n <thead>\r\n <tr>\r\n <th></th>\r\n <th>scope</th>\r\n <th>value</th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for ( entry of entries.value; track entry; let i = $index; let first =\r\n $first; let last = $last) {\r\n <tr [class.selected]=\"entry === edited\">\r\n <td class=\"fit-width\">\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Edit this ID\"\r\n (click)=\"editId(entry, i)\"\r\n >\r\n <mat-icon class=\"mat-primary\">edit</mat-icon>\r\n </button>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Move this ID up\"\r\n [disabled]=\"first\"\r\n (click)=\"moveIdUp(i)\"\r\n >\r\n <mat-icon>arrow_upward</mat-icon>\r\n </button>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Move this ID down\"\r\n [disabled]=\"last\"\r\n (click)=\"moveIdDown(i)\"\r\n >\r\n <mat-icon>arrow_downward</mat-icon>\r\n </button>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Delete this ID\"\r\n (click)=\"deleteId(i)\"\r\n >\r\n <mat-icon class=\"mat-warn\">remove_circle</mat-icon>\r\n </button>\r\n </td>\r\n <td>{{ entry.scope }}</td>\r\n <td>{{ entry.value }}</td>\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n }\r\n\r\n <mat-expansion-panel [expanded]=\"edited\" [disabled]=\"!edited\">\r\n <mat-expansion-panel-header\r\n >ID {{ edited?.value }}</mat-expansion-panel-header\r\n >\r\n <cadmus-refs-asserted-id\r\n [idScopeEntries]=\"idScopeEntries()\"\r\n [idTagEntries]=\"idTagEntries()\"\r\n [assTagEntries]=\"assTagEntries()\"\r\n [refTypeEntries]=\"refTypeEntries()\"\r\n [refTagEntries]=\"refTagEntries()\"\r\n [hasSubmit]=\"true\"\r\n [id]=\"edited\"\r\n (idChange)=\"onIdChange($event)\"\r\n (editorClose)=\"closeId()\"\r\n ></cadmus-refs-asserted-id>\r\n </mat-expansion-panel>\r\n</form>\r\n", styles: ["table{width:100%;border-collapse:collapse}tbody tr:nth-child(odd){background-color:#e2e2e2}th{text-align:left;font-weight:400;color:silver}td.fit-width{width:1px;white-space:nowrap}tr.selected{background-color:#d0d0d0!important}fieldset{border:1px solid silver;border-radius:6px;padding:6px}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i3.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "component", type: i4.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i4.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i7.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i6$1.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: AssertedIdComponent, selector: "cadmus-refs-asserted-id", inputs: ["idScopeEntries", "idTagEntries", "assTagEntries", "refTypeEntries", "refTagEntries", "id", "noEidLookup", "hasSubmit"], outputs: ["idChange", "editorClose"] }] });
521
- }
522
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: AssertedIdsComponent, decorators: [{
523
- type: Component,
524
- args: [{ selector: 'cadmus-refs-asserted-ids', imports: [
525
- FormsModule,
526
- ReactiveFormsModule,
527
- MatButtonModule,
528
- MatExpansionModule,
529
- MatIconModule,
530
- MatTooltipModule,
531
- AssertedIdComponent
532
- ], template: "<form [formGroup]=\"form\">\r\n <div>\r\n <button type=\"button\" mat-flat-button class=\"mat-primary\" (click)=\"addId()\">\r\n <mat-icon>add_circle</mat-icon> ID\r\n </button>\r\n </div>\r\n @if (entries.value.length) {\r\n <table>\r\n <thead>\r\n <tr>\r\n <th></th>\r\n <th>scope</th>\r\n <th>value</th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for ( entry of entries.value; track entry; let i = $index; let first =\r\n $first; let last = $last) {\r\n <tr [class.selected]=\"entry === edited\">\r\n <td class=\"fit-width\">\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Edit this ID\"\r\n (click)=\"editId(entry, i)\"\r\n >\r\n <mat-icon class=\"mat-primary\">edit</mat-icon>\r\n </button>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Move this ID up\"\r\n [disabled]=\"first\"\r\n (click)=\"moveIdUp(i)\"\r\n >\r\n <mat-icon>arrow_upward</mat-icon>\r\n </button>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Move this ID down\"\r\n [disabled]=\"last\"\r\n (click)=\"moveIdDown(i)\"\r\n >\r\n <mat-icon>arrow_downward</mat-icon>\r\n </button>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Delete this ID\"\r\n (click)=\"deleteId(i)\"\r\n >\r\n <mat-icon class=\"mat-warn\">remove_circle</mat-icon>\r\n </button>\r\n </td>\r\n <td>{{ entry.scope }}</td>\r\n <td>{{ entry.value }}</td>\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n }\r\n\r\n <mat-expansion-panel [expanded]=\"edited\" [disabled]=\"!edited\">\r\n <mat-expansion-panel-header\r\n >ID {{ edited?.value }}</mat-expansion-panel-header\r\n >\r\n <cadmus-refs-asserted-id\r\n [idScopeEntries]=\"idScopeEntries()\"\r\n [idTagEntries]=\"idTagEntries()\"\r\n [assTagEntries]=\"assTagEntries()\"\r\n [refTypeEntries]=\"refTypeEntries()\"\r\n [refTagEntries]=\"refTagEntries()\"\r\n [hasSubmit]=\"true\"\r\n [id]=\"edited\"\r\n (idChange)=\"onIdChange($event)\"\r\n (editorClose)=\"closeId()\"\r\n ></cadmus-refs-asserted-id>\r\n </mat-expansion-panel>\r\n</form>\r\n", styles: ["table{width:100%;border-collapse:collapse}tbody tr:nth-child(odd){background-color:#e2e2e2}th{text-align:left;font-weight:400;color:silver}td.fit-width{width:1px;white-space:nowrap}tr.selected{background-color:#d0d0d0!important}fieldset{border:1px solid silver;border-radius:6px;padding:6px}\n"] }]
533
- }], ctorParameters: () => [{ type: i1$1.FormBuilder }, { type: i2.DialogService }] });
534
-
535
- class ItemRefLookupService {
536
- _itemService;
537
- constructor(_itemService) {
538
- this._itemService = _itemService;
539
- }
540
- lookup(filter, options) {
541
- return this._itemService
542
- .getItems({
543
- title: filter.text,
544
- }, 1, filter.limit || 10)
545
- .pipe(map((page) => page.items));
546
- }
547
- getName(item) {
548
- return item?.title;
549
- }
550
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: ItemRefLookupService, deps: [{ token: i1.ItemService }], target: i0.ɵɵFactoryTarget.Injectable });
551
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: ItemRefLookupService, providedIn: 'root' });
552
- }
553
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: ItemRefLookupService, decorators: [{
554
- type: Injectable,
555
- args: [{
556
- providedIn: 'root',
557
- }]
558
- }], ctorParameters: () => [{ type: i1.ItemService }] });
559
-
560
- // from Cadmus general parts
561
- const METADATA_PART_ID = 'it.vedph.metadata';
562
- /*
563
- * Scoped pin-based lookup component. This component provides a list
564
- * of pin-based searches, with a lookup control. Whenever the user
565
- * picks a pin value, he gets the details about its item and part, and
566
- * item's metadata part, if any. He can then use these data to build
567
- * some EID by variously assembling these components.
568
- */
569
- class PinTargetLookupComponent {
570
- _presetLookupDefs;
571
- itemLookupService;
572
- pinLookupService;
573
- _itemService;
574
- _thesService;
575
- _snackbar;
576
- _subs = [];
577
- _noTargetUpdate;
578
- _noFormUpdate;
579
- _startWithByTypeMode;
580
695
  /**
581
- * True when the by-type pin lookup mode is active.
582
- * User can change mode unless modeSwitching is false.
696
+ * The ID being edited.
697
+ */
698
+ id = model();
699
+ /**
700
+ * True if when a new ID is set it should be internal rather than
701
+ * external by default.
702
+ */
703
+ internalDefault = input();
704
+ /**
705
+ * True if the UI has a submit button.
583
706
  */
584
- pinByTypeMode = model();
707
+ hasSubmit = input();
585
708
  /**
586
- * True when the user can switch between by-type and by-item mode.
709
+ * True when the internal UI preselected mode should be by type rather than
710
+ * by item. User can change mode unless modeSwitching is false.
587
711
  */
588
- canSwitchMode = model();
712
+ pinByTypeMode = input();
589
713
  /**
590
- * True when the user can edit the target's gid/label for internal
591
- * targets.
714
+ * True when the user can switch between by-type and by-item mode in
715
+ * the internal UI.
716
+ */
717
+ canSwitchMode = input();
718
+ /**
719
+ * True when the user can edit the target's gid/label for internal targets.
592
720
  */
593
721
  canEditTarget = input();
594
722
  /**
595
- * The lookup definitions to be used for the by-type lookup. If
596
- * not specified, the lookup definitions will be got via injection
723
+ * The lookup definitions to be used for the by-type lookup in the internal UI.
724
+ * If not specified, the lookup definitions will be got via injection
597
725
  * when available; if the injected definitions are empty, the
598
726
  * lookup definitions will be built from the model-types thesaurus;
599
727
  * if this is not available either, the by-type lookup will be
600
728
  * disabled.
601
729
  */
602
- lookupDefinitions = model();
603
- /**
604
- * The optional configurations for using external lookup services.
605
- */
606
- extLookupConfigs = input([]);
607
- /**
608
- * True if when a new target is set it should be internal rather than
609
- * external by default.
610
- */
611
- internalDefault = input();
612
- /**
613
- * The target to be edited.
614
- */
615
- target = model();
730
+ lookupDefinitions = input();
616
731
  /**
617
- * The default value for part type key when the by-type mode is active.
732
+ * The default part type key to be used.
618
733
  */
619
734
  defaultPartTypeKey = input();
620
735
  /**
621
- * Emitted when user closes the editor.
736
+ * Emitted whenever the user requests to close the editor.
622
737
  */
623
738
  editorClose = output();
624
739
  /**
625
- * Emitted when the user requests more items from an external lookup.
740
+ * Emitted when the user requests more.
626
741
  */
627
742
  extMoreRequest = output();
628
- /**
629
- * Emitted when the user changes the external lookup configuration.
630
- */
631
- extLookupConfigChange = output();
632
- // by type
633
- modelEntries;
634
- partTypeKeys;
635
- // by item
636
- itemParts;
637
- // form - by item
638
- item;
639
- itemPart;
640
- // form - by type
641
- partTypeKey;
642
- // form - both
643
- gid;
644
- label;
645
- byTypeMode;
646
- external;
647
- form;
648
- filter;
649
- pinFilterOptions;
650
- lookupData;
651
- constructor(_presetLookupDefs, itemLookupService, pinLookupService, _itemService, _thesService, _snackbar, formBuilder) {
652
- this._presetLookupDefs = _presetLookupDefs;
653
- this.itemLookupService = itemLookupService;
654
- this.pinLookupService = pinLookupService;
655
- this._itemService = _itemService;
656
- this._thesService = _thesService;
657
- this._snackbar = _snackbar;
658
- this.partTypeKeys = [];
659
- this.itemParts = [];
660
- this.modelEntries = [];
661
- // this is the default filter for the pin lookup, which will
662
- // be merged with values provided by user here
663
- this.filter = {
664
- text: '',
665
- limit: 10,
666
- };
743
+ constructor(formBuilder, lookupService, lookupDefs, settings) {
744
+ this.lookupService = lookupService;
745
+ this.lookupDefs = lookupDefs;
667
746
  // form
668
- this.item = formBuilder.control(null);
669
- this.itemPart = formBuilder.control(null);
670
- this.partTypeKey = formBuilder.control(null);
671
- this.gid = formBuilder.control(null, [
672
- Validators.required,
673
- Validators.maxLength(300),
674
- ]);
675
- this.label = formBuilder.control(null, [
676
- Validators.required,
677
- Validators.maxLength(300),
678
- ]);
679
- this.byTypeMode = formBuilder.control(false, { nonNullable: true });
680
- this.external = formBuilder.control(false, { nonNullable: true });
747
+ this.target = formBuilder.control(null, Validators.required);
748
+ this.scope = formBuilder.control(null, Validators.maxLength(500));
749
+ this.tag = formBuilder.control(null, Validators.maxLength(50));
750
+ this.assertion = formBuilder.control(null);
681
751
  this.form = formBuilder.group({
682
- item: this.item,
683
- itemPart: this.itemPart,
684
- partTypeKey: this.partTypeKey,
685
- gid: this.gid,
686
- label: this.label,
687
- byTypeMode: this.byTypeMode,
688
- external: this.external,
689
- });
690
- // when pinByTypeMode changes, adjust form
691
- effect(() => {
692
- if (!this.byTypeMode) {
693
- this._startWithByTypeMode = this.pinByTypeMode();
694
- }
695
- else {
696
- this.byTypeMode.setValue(this.pinByTypeMode() || false, {
697
- emitEvent: false,
698
- });
699
- this.byTypeMode.updateValueAndValidity();
700
- }
752
+ target: this.target,
753
+ scope: this.scope,
754
+ tag: this.tag,
755
+ assertion: this.assertion,
701
756
  });
702
- // when target changes, update form
757
+ // external lookup configs
758
+ this.extLookupConfigs =
759
+ settings.retrieve(ASSERTED_COMPOSITE_ID_CONFIGS_KEY) ||
760
+ [];
761
+ // when id changes, update form
703
762
  effect(() => {
704
- if (this._noFormUpdate) {
705
- this._noFormUpdate = false;
706
- return;
707
- }
708
- console.log('target changed', this.target());
709
- this.updateForm(this.target());
763
+ this.updateForm(this.id());
710
764
  });
711
765
  }
712
- forceByItem() {
713
- this.pinByTypeMode.set(false);
714
- this.canSwitchMode.set(false);
715
- }
716
- setupKeys() {
717
- // use DI presets if no lookup definitions
718
- if (!this.lookupDefinitions()) {
719
- this.lookupDefinitions.set(this._presetLookupDefs);
720
- }
721
- // keys are all the defined lookup searches
722
- this.partTypeKeys = Object.keys(this.lookupDefinitions());
723
- // if no keys, get them from thesaurus model-types;
724
- // if this is not available, just force by item mode.
725
- if (!this.partTypeKeys.length) {
726
- if (this.modelEntries?.length) {
727
- // set lookupDefinitions from thesaurus entries
728
- const defs = {};
729
- this.modelEntries.forEach((e) => {
730
- defs[e.value] = {
731
- name: e.value,
732
- typeId: e.id,
733
- };
734
- });
735
- this.lookupDefinitions.set(defs);
736
- // set type keys from thesaurus entries
737
- this.partTypeKeys = this.modelEntries.map((e) => e.value);
738
- }
739
- }
740
- // if still no keys, force by item mode
741
- if (!this.partTypeKeys.length) {
742
- this.forceByItem();
743
- }
744
- else {
745
- // set default key
746
- this.partTypeKey.setValue(this.defaultPartTypeKey() || this.partTypeKeys[0]);
747
- }
748
- }
749
766
  ngOnInit() {
750
- // set start mode if required
751
- if (this._startWithByTypeMode) {
752
- this.byTypeMode.setValue(true);
753
- }
754
- // whenever item changes (by lookup), update item's parts and filter
755
- this._subs.push(this.item.valueChanges
756
- .pipe(distinctUntilChanged(), debounceTime$1(300))
757
- .subscribe((item) => {
758
- this.itemPart.setValue(null, { emitEvent: false });
759
- this.itemParts = item?.parts || [];
760
- this.filter = {
761
- ...this.filter,
762
- itemId: item?.id,
763
- };
764
- }));
765
- // whenever itemPart changes (by user selection), update target and
766
- // eventually gid
767
- this._subs.push(this.itemPart.valueChanges
768
- .pipe(distinctUntilChanged(), debounceTime$1(300))
769
- .subscribe((part) => {
770
- if (!this.gid.value || this.gid.pristine) {
771
- this.gid.setValue(this.buildGid());
772
- }
773
- this.filter = {
774
- ...this.filter,
775
- partId: part?.id,
776
- };
777
- this.updateTarget(true);
778
- }));
779
- // whenever partTypeKey changes, update filter's options
780
- this._subs.push(this.partTypeKey.valueChanges
781
- .pipe(distinctUntilChanged(), debounceTime$1(300))
782
- .subscribe((key) => {
783
- this.pinFilterOptions = key
784
- ? this.lookupDefinitions()[key]
785
- : undefined;
786
- }));
787
- // whenever external changes, set required validator in label
788
- // (true for external, false for internal)
789
- this._subs.push(this.external.valueChanges
790
- .pipe(distinctUntilChanged(), debounceTime$1(300))
791
- .subscribe((external) => {
792
- if (external) {
793
- this.label.setValidators([
794
- Validators.required,
795
- Validators.maxLength(300),
796
- ]);
797
- }
798
- else {
799
- this.label.setValidators([Validators.maxLength(300)]);
767
+ this._sub = this.form.valueChanges
768
+ .pipe(debounceTime$1(300))
769
+ .subscribe((_) => {
770
+ if (!this._updatingForm) {
771
+ this.emitIdChange();
800
772
  }
801
- this.label.updateValueAndValidity();
802
- }));
803
- // load model-types thesaurus entries
804
- this._thesService.getThesaurus('model-types', true).subscribe({
805
- next: (t) => {
806
- this.modelEntries = t.entries || [];
807
- if (this.modelEntries?.length) {
808
- this.setupKeys();
809
- }
810
- else {
811
- this.forceByItem();
812
- }
813
- },
814
- error: () => {
815
- this.forceByItem();
816
- },
817
773
  });
818
774
  }
819
775
  ngOnDestroy() {
820
- for (let i = 0; i < this._subs.length; i++) {
821
- this._subs[i].unsubscribe();
776
+ this._sub?.unsubscribe();
777
+ }
778
+ onAssertionChange(assertion) {
779
+ this.assertion.setValue(assertion || null);
780
+ }
781
+ onTargetChange(target) {
782
+ this.target.setValue(target);
783
+ this.target.markAsDirty();
784
+ this.target.updateValueAndValidity();
785
+ if (this.form.valid) {
786
+ this.targetExpanded = false;
822
787
  }
823
788
  }
824
- buildGid() {
825
- // the GID is the part ID if any, or the item ID, followed by
826
- // the pin's value (=EID)
827
- const pin = this.lookupData?.pin;
828
- if (!pin?.value) {
829
- return null;
789
+ updateForm(id) {
790
+ this._updatingForm = true;
791
+ if (!id) {
792
+ this.form.reset();
830
793
  }
831
- return pin.partId
832
- ? `P${pin.partId}/${pin.value}`
833
- : `I${pin.itemId}/${pin.value}`;
834
- }
835
- buildLabel() {
836
- if (!this.lookupData?.pin) {
837
- return null;
794
+ else {
795
+ this.target.setValue(id.target);
796
+ this.scope.setValue(id.scope || null);
797
+ this.tag.setValue(id.tag || null);
798
+ this.assertion.setValue(id.assertion || null);
799
+ this.form.markAsPristine();
838
800
  }
839
- const sb = [];
840
- // pin value
841
- if (this.lookupData.pin.value) {
842
- sb.push(this.lookupData.pin.value);
843
- sb.push(' | ');
801
+ this._updatingForm = false;
802
+ }
803
+ getId() {
804
+ const external = !this.target.value?.name;
805
+ const target = this.target.value;
806
+ return {
807
+ target: external
808
+ ? {
809
+ gid: target?.gid || '',
810
+ label: target?.label || target?.gid || '',
811
+ }
812
+ : target,
813
+ scope: this.scope.value?.trim() || '',
814
+ tag: this.tag.value?.trim(),
815
+ assertion: this.assertion.value || undefined,
816
+ };
817
+ }
818
+ emitIdChange() {
819
+ if (!this.hasSubmit()) {
820
+ this.id.set(this.getId());
844
821
  }
845
- // item title
846
- sb.push(this.lookupData.item?.title || this.lookupData.pin?.itemId);
847
- // part type and role
848
- if (this.lookupData.pin.partTypeId) {
849
- const e = this.modelEntries?.find((e) => e.id === this.lookupData.pin.partTypeId);
850
- sb.push(' (');
851
- sb.push(e?.value || this.lookupData.pin.partTypeId);
852
- if (this.lookupData.pin.roleId) {
853
- sb.push(`, ${this.lookupData.pin.roleId}`);
854
- }
855
- sb.push(')');
822
+ }
823
+ onEditorClose() {
824
+ this.targetExpanded = false;
825
+ }
826
+ onExtMoreRequest(event) {
827
+ this.extMoreRequest.emit(event);
828
+ }
829
+ onExtLookupConfigChange(config) {
830
+ if (!this.scope.value ||
831
+ this.extLookupConfigs.some((c) => c.name === this.scope.value)) {
832
+ this.scope.setValue(config.name || null);
833
+ this.scope.markAsDirty();
834
+ this.scope.updateValueAndValidity();
856
835
  }
857
- return sb.join('');
858
836
  }
859
- getTarget() {
860
- if (this.external.value) {
861
- return {
862
- gid: this.gid.value || '',
863
- label: this.label.value || '',
864
- };
837
+ cancel() {
838
+ this.editorClose.emit();
839
+ }
840
+ save() {
841
+ if (this.form.valid) {
842
+ this.id.set(this.getId());
865
843
  }
866
- else {
867
- const pin = this.lookupData?.pin;
868
- return {
869
- gid: this.gid.value || '',
870
- label: this.label.value || '',
871
- itemId: pin?.itemId || '',
872
- partId: pin?.partId || '',
873
- partTypeId: pin?.partTypeId || '',
874
- roleId: pin?.roleId || '',
875
- name: pin?.name || '',
876
- value: pin?.value || '',
877
- };
844
+ }
845
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: AssertedCompositeIdComponent, deps: [{ token: i1$1.FormBuilder }, { token: PinRefLookupService }, { token: 'indexLookupDefinitions' }, { token: i3$1.RamStorageService }], target: i0.ɵɵFactoryTarget.Component });
846
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.0", type: AssertedCompositeIdComponent, isStandalone: true, selector: "cadmus-refs-asserted-composite-id", inputs: { idScopeEntries: { classPropertyName: "idScopeEntries", publicName: "idScopeEntries", isSignal: true, isRequired: false, transformFunction: null }, idTagEntries: { classPropertyName: "idTagEntries", publicName: "idTagEntries", isSignal: true, isRequired: false, transformFunction: null }, assTagEntries: { classPropertyName: "assTagEntries", publicName: "assTagEntries", isSignal: true, isRequired: false, transformFunction: null }, refTypeEntries: { classPropertyName: "refTypeEntries", publicName: "refTypeEntries", isSignal: true, isRequired: false, transformFunction: null }, refTagEntries: { classPropertyName: "refTagEntries", publicName: "refTagEntries", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, internalDefault: { classPropertyName: "internalDefault", publicName: "internalDefault", isSignal: true, isRequired: false, transformFunction: null }, hasSubmit: { classPropertyName: "hasSubmit", publicName: "hasSubmit", isSignal: true, isRequired: false, transformFunction: null }, pinByTypeMode: { classPropertyName: "pinByTypeMode", publicName: "pinByTypeMode", isSignal: true, isRequired: false, transformFunction: null }, canSwitchMode: { classPropertyName: "canSwitchMode", publicName: "canSwitchMode", isSignal: true, isRequired: false, transformFunction: null }, canEditTarget: { classPropertyName: "canEditTarget", publicName: "canEditTarget", isSignal: true, isRequired: false, transformFunction: null }, lookupDefinitions: { classPropertyName: "lookupDefinitions", publicName: "lookupDefinitions", isSignal: true, isRequired: false, transformFunction: null }, defaultPartTypeKey: { classPropertyName: "defaultPartTypeKey", publicName: "defaultPartTypeKey", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { id: "idChange", editorClose: "editorClose", extMoreRequest: "extMoreRequest" }, ngImport: i0, template: "<form [formGroup]=\"form\" (submit)=\"save()\">\r\n <div>\r\n <div class=\"form-row\">\r\n <!-- tag (bound) -->\r\n @if (idTagEntries()?.length) {\r\n <mat-form-field class=\"short-text\">\r\n <mat-label>tag</mat-label>\r\n <mat-select [formControl]=\"tag\">\r\n @for (e of idTagEntries(); track e) {\r\n <mat-option [value]=\"e.id\">{{ e.value }}</mat-option>\r\n }\r\n </mat-select>\r\n </mat-form-field>\r\n }\r\n <!-- tag (free) -->\r\n @else {\r\n <mat-form-field class=\"short-text\">\r\n <mat-label>tag</mat-label>\r\n <input matInput [formControl]=\"tag\" />\r\n @if ($any(tag.errors)?.maxLength && (tag.dirty || tag.touched)) {\r\n <mat-error>tag too long</mat-error>\r\n }\r\n </mat-form-field>\r\n }\r\n\r\n <!-- scope (bound) -->\r\n @if (idScopeEntries()?.length) {\r\n <mat-form-field class=\"short-text\">\r\n <mat-label>scope</mat-label>\r\n <mat-select [formControl]=\"scope\">\r\n @for (e of idScopeEntries(); track e) {\r\n <mat-option [value]=\"e.id\">{{ e.value }}</mat-option>\r\n }\r\n </mat-select>\r\n </mat-form-field>\r\n }\r\n <!-- scope (free) -->\r\n @else {\r\n <mat-form-field class=\"short-text\">\r\n <mat-label>scope</mat-label>\r\n <input matInput [formControl]=\"scope\" />\r\n @if ( $any(scope.errors)?.maxLength && (scope.dirty || scope.touched) )\r\n {\r\n <mat-error>scope too long</mat-error>\r\n }\r\n </mat-form-field>\r\n }\r\n\r\n <!-- label and GID -->\r\n @if (target.value?.label) {\r\n <div class=\"info\">\r\n <span class=\"label\">label</span>{{ target.value?.label }}\r\n </div>\r\n } @if (target.value?.gid) {\r\n <div class=\"info\">\r\n <span class=\"label\">GID</span>{{ target.value?.gid }}\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- target -->\r\n <div class=\"boxed\">\r\n <mat-expansion-panel [(expanded)]=\"targetExpanded\">\r\n <mat-expansion-panel-header>target</mat-expansion-panel-header>\r\n <cadmus-pin-target-lookup\r\n [pinByTypeMode]=\"pinByTypeMode()\"\r\n [canSwitchMode]=\"canSwitchMode()\"\r\n [canEditTarget]=\"canEditTarget()\"\r\n [lookupDefinitions]=\"lookupDefinitions()\"\r\n [defaultPartTypeKey]=\"defaultPartTypeKey()\"\r\n [target]=\"target.value || undefined\"\r\n [internalDefault]=\"internalDefault()\"\r\n [extLookupConfigs]=\"extLookupConfigs\"\r\n (targetChange)=\"onTargetChange($event)\"\r\n (editorClose)=\"onEditorClose()\"\r\n (extMoreRequest)=\"onExtMoreRequest($event)\"\r\n (extLookupConfigChange)=\"onExtLookupConfigChange($event)\"\r\n />\r\n </mat-expansion-panel>\r\n </div>\r\n\r\n <!-- assertion -->\r\n <br />\r\n <div class=\"boxed\">\r\n <mat-expansion-panel>\r\n <mat-expansion-panel-header>assertion</mat-expansion-panel-header>\r\n <cadmus-refs-assertion\r\n [assTagEntries]=\"assTagEntries()\"\r\n [refTypeEntries]=\"refTypeEntries()\"\r\n [refTagEntries]=\"refTagEntries()\"\r\n [assertion]=\"assertion.value || undefined\"\r\n (assertionChange)=\"onAssertionChange($event)\"\r\n />\r\n </mat-expansion-panel>\r\n </div>\r\n </div>\r\n\r\n <!-- buttons -->\r\n @if (hasSubmit()) {\r\n <div>\r\n <button\r\n mat-icon-button\r\n type=\"button\"\r\n (click)=\"cancel()\"\r\n [disabled]=\"!this.target.value?.gid || !this.target.value?.label\"\r\n >\r\n <mat-icon class=\"mat-warn\">close</mat-icon>\r\n </button>\r\n <button mat-icon-button type=\"submit\" [disabled]=\"form.invalid\">\r\n <mat-icon class=\"mat-primary\">check_circle</mat-icon>\r\n </button>\r\n </div>\r\n }\r\n</form>\r\n", styles: [".form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}.boxed{border:1px solid silver;border-radius:6px;padding:6px}.short-text{width:8em}.pin-info{font-size:90%;color:silver}fieldset{border:1px solid silver;border-radius:6px;padding:6px}.info{border:1px solid silver;border-radius:6px;background-color:silver;color:#fff;padding:4px}.info .label{background-color:#fff;color:silver;margin:0 6px}@media only screen and (max-width: 959px){div#container{grid-template-rows:1fr auto;grid-template-columns:1fr;grid-template-areas:\"editor\" \"lookup\"}}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type:
847
+ // material
848
+ MatButtonModule }, { kind: "component", type: i3.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "component", type: i4$1.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i4$1.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i6$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6$1.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6$1.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i7.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i8$1.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i9.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i9.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "component", type:
849
+ // bricks
850
+ AssertionComponent, selector: "cadmus-refs-assertion", inputs: ["assTagEntries", "refTypeEntries", "refTagEntries", "assertion"], outputs: ["assertionChange"] }, { kind: "component", type:
851
+ // local
852
+ PinTargetLookupComponent, selector: "cadmus-pin-target-lookup", inputs: ["pinByTypeMode", "canSwitchMode", "canEditTarget", "lookupDefinitions", "extLookupConfigs", "internalDefault", "target", "defaultPartTypeKey"], outputs: ["pinByTypeModeChange", "canSwitchModeChange", "lookupDefinitionsChange", "targetChange", "editorClose", "extMoreRequest", "extLookupConfigChange"] }] });
853
+ }
854
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: AssertedCompositeIdComponent, decorators: [{
855
+ type: Component,
856
+ args: [{ selector: 'cadmus-refs-asserted-composite-id', imports: [
857
+ ReactiveFormsModule,
858
+ // material
859
+ MatButtonModule,
860
+ MatExpansionModule,
861
+ MatFormFieldModule,
862
+ MatIconModule,
863
+ MatInputModule,
864
+ MatSelectModule,
865
+ MatTooltipModule,
866
+ // bricks
867
+ AssertionComponent,
868
+ // local
869
+ PinTargetLookupComponent,
870
+ ], template: "<form [formGroup]=\"form\" (submit)=\"save()\">\r\n <div>\r\n <div class=\"form-row\">\r\n <!-- tag (bound) -->\r\n @if (idTagEntries()?.length) {\r\n <mat-form-field class=\"short-text\">\r\n <mat-label>tag</mat-label>\r\n <mat-select [formControl]=\"tag\">\r\n @for (e of idTagEntries(); track e) {\r\n <mat-option [value]=\"e.id\">{{ e.value }}</mat-option>\r\n }\r\n </mat-select>\r\n </mat-form-field>\r\n }\r\n <!-- tag (free) -->\r\n @else {\r\n <mat-form-field class=\"short-text\">\r\n <mat-label>tag</mat-label>\r\n <input matInput [formControl]=\"tag\" />\r\n @if ($any(tag.errors)?.maxLength && (tag.dirty || tag.touched)) {\r\n <mat-error>tag too long</mat-error>\r\n }\r\n </mat-form-field>\r\n }\r\n\r\n <!-- scope (bound) -->\r\n @if (idScopeEntries()?.length) {\r\n <mat-form-field class=\"short-text\">\r\n <mat-label>scope</mat-label>\r\n <mat-select [formControl]=\"scope\">\r\n @for (e of idScopeEntries(); track e) {\r\n <mat-option [value]=\"e.id\">{{ e.value }}</mat-option>\r\n }\r\n </mat-select>\r\n </mat-form-field>\r\n }\r\n <!-- scope (free) -->\r\n @else {\r\n <mat-form-field class=\"short-text\">\r\n <mat-label>scope</mat-label>\r\n <input matInput [formControl]=\"scope\" />\r\n @if ( $any(scope.errors)?.maxLength && (scope.dirty || scope.touched) )\r\n {\r\n <mat-error>scope too long</mat-error>\r\n }\r\n </mat-form-field>\r\n }\r\n\r\n <!-- label and GID -->\r\n @if (target.value?.label) {\r\n <div class=\"info\">\r\n <span class=\"label\">label</span>{{ target.value?.label }}\r\n </div>\r\n } @if (target.value?.gid) {\r\n <div class=\"info\">\r\n <span class=\"label\">GID</span>{{ target.value?.gid }}\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- target -->\r\n <div class=\"boxed\">\r\n <mat-expansion-panel [(expanded)]=\"targetExpanded\">\r\n <mat-expansion-panel-header>target</mat-expansion-panel-header>\r\n <cadmus-pin-target-lookup\r\n [pinByTypeMode]=\"pinByTypeMode()\"\r\n [canSwitchMode]=\"canSwitchMode()\"\r\n [canEditTarget]=\"canEditTarget()\"\r\n [lookupDefinitions]=\"lookupDefinitions()\"\r\n [defaultPartTypeKey]=\"defaultPartTypeKey()\"\r\n [target]=\"target.value || undefined\"\r\n [internalDefault]=\"internalDefault()\"\r\n [extLookupConfigs]=\"extLookupConfigs\"\r\n (targetChange)=\"onTargetChange($event)\"\r\n (editorClose)=\"onEditorClose()\"\r\n (extMoreRequest)=\"onExtMoreRequest($event)\"\r\n (extLookupConfigChange)=\"onExtLookupConfigChange($event)\"\r\n />\r\n </mat-expansion-panel>\r\n </div>\r\n\r\n <!-- assertion -->\r\n <br />\r\n <div class=\"boxed\">\r\n <mat-expansion-panel>\r\n <mat-expansion-panel-header>assertion</mat-expansion-panel-header>\r\n <cadmus-refs-assertion\r\n [assTagEntries]=\"assTagEntries()\"\r\n [refTypeEntries]=\"refTypeEntries()\"\r\n [refTagEntries]=\"refTagEntries()\"\r\n [assertion]=\"assertion.value || undefined\"\r\n (assertionChange)=\"onAssertionChange($event)\"\r\n />\r\n </mat-expansion-panel>\r\n </div>\r\n </div>\r\n\r\n <!-- buttons -->\r\n @if (hasSubmit()) {\r\n <div>\r\n <button\r\n mat-icon-button\r\n type=\"button\"\r\n (click)=\"cancel()\"\r\n [disabled]=\"!this.target.value?.gid || !this.target.value?.label\"\r\n >\r\n <mat-icon class=\"mat-warn\">close</mat-icon>\r\n </button>\r\n <button mat-icon-button type=\"submit\" [disabled]=\"form.invalid\">\r\n <mat-icon class=\"mat-primary\">check_circle</mat-icon>\r\n </button>\r\n </div>\r\n }\r\n</form>\r\n", styles: [".form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}.boxed{border:1px solid silver;border-radius:6px;padding:6px}.short-text{width:8em}.pin-info{font-size:90%;color:silver}fieldset{border:1px solid silver;border-radius:6px;padding:6px}.info{border:1px solid silver;border-radius:6px;background-color:silver;color:#fff;padding:4px}.info .label{background-color:#fff;color:silver;margin:0 6px}@media only screen and (max-width: 959px){div#container{grid-template-rows:1fr auto;grid-template-columns:1fr;grid-template-areas:\"editor\" \"lookup\"}}\n"] }]
871
+ }], ctorParameters: () => [{ type: i1$1.FormBuilder }, { type: PinRefLookupService }, { type: undefined, decorators: [{
872
+ type: Inject,
873
+ args: ['indexLookupDefinitions']
874
+ }] }, { type: i3$1.RamStorageService }] });
875
+
876
+ /**
877
+ * Asserted composite IDs editor.
878
+ */
879
+ class AssertedCompositeIdsComponent {
880
+ _dialogService;
881
+ _ids;
882
+ _editedIndex;
883
+ edited;
884
+ /**
885
+ * The asserted IDs.
886
+ */
887
+ get ids() {
888
+ return this._ids;
889
+ }
890
+ set ids(value) {
891
+ if (this._ids !== value) {
892
+ this._ids = value || [];
893
+ this.updateForm(value);
878
894
  }
879
895
  }
880
- emitChange() {
881
- this._noFormUpdate = true;
882
- this.target.set(this.getTarget());
896
+ // asserted-id-scopes
897
+ idScopeEntries = input();
898
+ // asserted-id-tags
899
+ idTagEntries = input();
900
+ // assertion-tags
901
+ assTagEntries = input();
902
+ // doc-reference-types
903
+ refTypeEntries = input();
904
+ // doc-reference-tags
905
+ refTagEntries = input();
906
+ /**
907
+ * True when the internal UI preselected mode should be by type rather than
908
+ * by item. User can change mode unless modeSwitching is false.
909
+ */
910
+ pinByTypeMode = input();
911
+ /**
912
+ * True when the user can switch between by-type and by-item mode in
913
+ * the internal UI.
914
+ */
915
+ canSwitchMode = input();
916
+ /**
917
+ * True when the user can edit the target's gid/label for internal targets.
918
+ */
919
+ canEditTarget = input();
920
+ /**
921
+ * The lookup definitions to be used for the by-type lookup in the internal UI.
922
+ * If not specified, the lookup definitions will be got via injection
923
+ * when available; if the injected definitions are empty, the
924
+ * lookup definitions will be built from the model-types thesaurus;
925
+ * if this is not available either, the by-type lookup will be
926
+ * disabled.
927
+ */
928
+ lookupDefinitions = input();
929
+ /**
930
+ * The default part type key.
931
+ */
932
+ defaultPartTypeKey = input();
933
+ /**
934
+ * True if when a new ID is set it should be internal rather than
935
+ * external by default.
936
+ */
937
+ internalDefault = input();
938
+ /**
939
+ * Emitted whenever any ID changes.
940
+ */
941
+ idsChange = output();
942
+ entries;
943
+ form;
944
+ constructor(formBuilder, _dialogService) {
945
+ this._dialogService = _dialogService;
946
+ this._ids = [];
947
+ this._editedIndex = -1;
948
+ this.entries = formBuilder.control([], { nonNullable: true });
949
+ // form
950
+ this.form = formBuilder.group({
951
+ ids: this.entries,
952
+ });
883
953
  }
884
- updateTarget(noEmit = false) {
885
- if (this._noTargetUpdate) {
954
+ updateForm(ids) {
955
+ if (!ids?.length) {
956
+ this.form.reset();
886
957
  return;
887
958
  }
888
- if (!this.external.value) {
889
- this.gid.setValue(this.buildGid());
890
- this.gid.updateValueAndValidity();
891
- this.gid.markAsDirty();
892
- this.label.setValue(this.buildLabel());
893
- this.label.updateValueAndValidity();
894
- this.label.markAsDirty();
959
+ this.entries.setValue(ids, { emitEvent: false });
960
+ this.entries.updateValueAndValidity();
961
+ this.form.markAsPristine();
962
+ }
963
+ emitIdsChange() {
964
+ this.idsChange.emit(this.entries.value);
965
+ }
966
+ addId() {
967
+ this.editId({
968
+ target: { gid: '', label: '' },
969
+ }, -1);
970
+ }
971
+ editId(id, index) {
972
+ this._editedIndex = index;
973
+ this.edited = id;
974
+ }
975
+ closeId() {
976
+ this._editedIndex = -1;
977
+ this.edited = undefined;
978
+ }
979
+ saveId(entry) {
980
+ const entries = [...this.entries.value];
981
+ if (this._editedIndex === -1) {
982
+ entries.push(entry);
895
983
  }
896
- if (!noEmit) {
897
- this.emitChange();
984
+ else {
985
+ entries.splice(this._editedIndex, 1, entry);
898
986
  }
987
+ this.entries.setValue(entries);
988
+ this.entries.markAsDirty();
989
+ this.entries.updateValueAndValidity();
990
+ this.closeId();
991
+ }
992
+ deleteId(index) {
993
+ this._dialogService
994
+ .confirm('Confirmation', 'Delete ID?')
995
+ .pipe(take(1))
996
+ .subscribe((yes) => {
997
+ if (yes) {
998
+ if (this._editedIndex === index) {
999
+ this.closeId();
1000
+ }
1001
+ const entries = [...this.entries.value];
1002
+ entries.splice(index, 1);
1003
+ this.entries.setValue(entries);
1004
+ this.entries.markAsDirty();
1005
+ this.entries.updateValueAndValidity();
1006
+ this.emitIdsChange();
1007
+ }
1008
+ });
899
1009
  }
900
- updateForm(target) {
901
- // build pin info from target
902
- if (!target) {
903
- this.lookupData = undefined;
904
- this.item.reset();
905
- this.itemPart.reset();
906
- this.gid.reset();
907
- this.label.reset();
1010
+ moveIdUp(index) {
1011
+ if (index < 1) {
908
1012
  return;
909
1013
  }
910
- this._noTargetUpdate = true;
911
- this.gid.setValue(target.gid || '', { emitEvent: false });
912
- this.label.setValue(target.label || '', { emitEvent: false });
913
- this.lookupData = {
914
- pin: {
915
- itemId: target.itemId || '',
916
- partId: target.partId || '',
917
- partTypeId: target.partTypeId || '',
918
- roleId: target.roleId || '',
919
- name: target.name || '',
920
- value: target.value || '',
921
- },
922
- };
923
- // get item
924
- if (target.itemId) {
925
- this._itemService.getItem(target.itemId, true, true).subscribe({
926
- next: (item) => {
927
- this.item.setValue(item, { emitEvent: false });
928
- this.form.markAsPristine();
929
- this._noTargetUpdate = false;
930
- this.external.setValue(!target.name, { emitEvent: false });
931
- this.updateTarget();
932
- },
933
- error: (error) => {
934
- if (error) {
935
- console.error('Item service error', error);
936
- }
937
- this.external.setValue(!target.name, { emitEvent: false });
938
- this._noTargetUpdate = false;
939
- },
940
- });
941
- }
942
- else {
943
- this.external.setValue(!target.name && !this.internalDefault(), {
944
- emitEvent: false,
945
- });
946
- this._noTargetUpdate = false;
947
- this.updateTarget();
1014
+ const entry = this.entries.value[index];
1015
+ const entries = [...this.entries.value];
1016
+ entries.splice(index, 1);
1017
+ entries.splice(index - 1, 0, entry);
1018
+ this.entries.setValue(entries);
1019
+ this.entries.markAsDirty();
1020
+ this.entries.updateValueAndValidity();
1021
+ this.emitIdsChange();
1022
+ }
1023
+ moveIdDown(index) {
1024
+ if (index + 1 >= this.entries.value.length) {
1025
+ return;
948
1026
  }
1027
+ const entry = this.entries.value[index];
1028
+ const entries = [...this.entries.value];
1029
+ entries.splice(index, 1);
1030
+ entries.splice(index + 1, 0, entry);
1031
+ this.entries.setValue(entries);
1032
+ this.entries.markAsDirty();
1033
+ this.entries.updateValueAndValidity();
1034
+ this.emitIdsChange();
1035
+ }
1036
+ onIdChange(id) {
1037
+ this.saveId(id);
1038
+ this.emitIdsChange();
949
1039
  }
1040
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: AssertedCompositeIdsComponent, deps: [{ token: i1$1.FormBuilder }, { token: i2.DialogService }], target: i0.ɵɵFactoryTarget.Component });
1041
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.0", type: AssertedCompositeIdsComponent, isStandalone: true, selector: "cadmus-refs-asserted-composite-ids", inputs: { ids: { classPropertyName: "ids", publicName: "ids", isSignal: false, isRequired: false, transformFunction: null }, idScopeEntries: { classPropertyName: "idScopeEntries", publicName: "idScopeEntries", isSignal: true, isRequired: false, transformFunction: null }, idTagEntries: { classPropertyName: "idTagEntries", publicName: "idTagEntries", isSignal: true, isRequired: false, transformFunction: null }, assTagEntries: { classPropertyName: "assTagEntries", publicName: "assTagEntries", isSignal: true, isRequired: false, transformFunction: null }, refTypeEntries: { classPropertyName: "refTypeEntries", publicName: "refTypeEntries", isSignal: true, isRequired: false, transformFunction: null }, refTagEntries: { classPropertyName: "refTagEntries", publicName: "refTagEntries", isSignal: true, isRequired: false, transformFunction: null }, pinByTypeMode: { classPropertyName: "pinByTypeMode", publicName: "pinByTypeMode", isSignal: true, isRequired: false, transformFunction: null }, canSwitchMode: { classPropertyName: "canSwitchMode", publicName: "canSwitchMode", isSignal: true, isRequired: false, transformFunction: null }, canEditTarget: { classPropertyName: "canEditTarget", publicName: "canEditTarget", isSignal: true, isRequired: false, transformFunction: null }, lookupDefinitions: { classPropertyName: "lookupDefinitions", publicName: "lookupDefinitions", isSignal: true, isRequired: false, transformFunction: null }, defaultPartTypeKey: { classPropertyName: "defaultPartTypeKey", publicName: "defaultPartTypeKey", isSignal: true, isRequired: false, transformFunction: null }, internalDefault: { classPropertyName: "internalDefault", publicName: "internalDefault", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { idsChange: "idsChange" }, ngImport: i0, template: "<form [formGroup]=\"form\">\r\n <!-- buttons -->\r\n <button type=\"button\" class=\"mat-primary\" mat-flat-button (click)=\"addId()\">\r\n <mat-icon>add_circle</mat-icon> ID\r\n </button>\r\n <!-- list -->\r\n @if (entries.value.length) {\r\n <table>\r\n <thead>\r\n <tr>\r\n <th></th>\r\n <th>scope</th>\r\n <th>label</th>\r\n <th>gid</th>\r\n <th>ass.</th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for ( entry of entries.value; track entry; let i = $index; let first =\r\n $first; let last = $last) {\r\n <tr [class.selected]=\"entry === edited\">\r\n <td class=\"fit-width\">\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Edit this ID\"\r\n (click)=\"editId(entry, i)\"\r\n >\r\n <mat-icon class=\"mat-primary\">edit</mat-icon>\r\n </button>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Move this ID up\"\r\n [disabled]=\"first\"\r\n (click)=\"moveIdUp(i)\"\r\n >\r\n <mat-icon>arrow_upward</mat-icon>\r\n </button>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Move this ID down\"\r\n [disabled]=\"last\"\r\n (click)=\"moveIdDown(i)\"\r\n >\r\n <mat-icon>arrow_downward</mat-icon>\r\n </button>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Delete this ID\"\r\n (click)=\"deleteId(i)\"\r\n >\r\n <mat-icon class=\"mat-warn\">remove_circle</mat-icon>\r\n </button>\r\n </td>\r\n <td>{{ entry.scope }}</td>\r\n <td>{{ entry?.target?.label }}</td>\r\n <td>{{ entry?.target?.gid }}</td>\r\n <td>{{ entry?.assertion ? \"Y\" : \"N\" }}</td>\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n }\r\n\r\n <!-- editor -->\r\n <mat-expansion-panel [expanded]=\"edited\" [disabled]=\"!edited\">\r\n <mat-expansion-panel-header\r\n >ID {{ edited?.target?.label }}</mat-expansion-panel-header\r\n >\r\n <cadmus-refs-asserted-composite-id\r\n [idScopeEntries]=\"idScopeEntries()\"\r\n [idTagEntries]=\"idTagEntries()\"\r\n [assTagEntries]=\"assTagEntries()\"\r\n [refTypeEntries]=\"refTypeEntries()\"\r\n [refTagEntries]=\"refTagEntries()\"\r\n [hasSubmit]=\"true\"\r\n [pinByTypeMode]=\"pinByTypeMode()\"\r\n [canSwitchMode]=\"canSwitchMode()\"\r\n [canEditTarget]=\"canEditTarget()\"\r\n [lookupDefinitions]=\"lookupDefinitions()\"\r\n [defaultPartTypeKey]=\"defaultPartTypeKey()\"\r\n [internalDefault]=\"internalDefault()\"\r\n [id]=\"edited\"\r\n (idChange)=\"onIdChange($event)\"\r\n (editorClose)=\"closeId()\"\r\n />\r\n </mat-expansion-panel>\r\n</form>\r\n", styles: ["table{width:100%;border-collapse:collapse}tbody tr:nth-child(odd){background-color:#e2e2e2}th{text-align:left;font-weight:400;color:silver}td.fit-width{width:1px;white-space:nowrap}tr.selected{background-color:#d0d0d0!important}fieldset{border:1px solid silver;border-radius:6px;padding:6px}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i3.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "component", type: i4$1.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i4$1.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i7.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "component", type: AssertedCompositeIdComponent, selector: "cadmus-refs-asserted-composite-id", inputs: ["idScopeEntries", "idTagEntries", "assTagEntries", "refTypeEntries", "refTagEntries", "id", "internalDefault", "hasSubmit", "pinByTypeMode", "canSwitchMode", "canEditTarget", "lookupDefinitions", "defaultPartTypeKey"], outputs: ["idChange", "editorClose", "extMoreRequest"] }] });
1042
+ }
1043
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: AssertedCompositeIdsComponent, decorators: [{
1044
+ type: Component,
1045
+ args: [{ selector: 'cadmus-refs-asserted-composite-ids', imports: [
1046
+ FormsModule,
1047
+ ReactiveFormsModule,
1048
+ MatButtonModule,
1049
+ MatCheckboxModule,
1050
+ MatExpansionModule,
1051
+ MatFormFieldModule,
1052
+ MatIconModule,
1053
+ MatInputModule,
1054
+ AssertedCompositeIdComponent,
1055
+ ], template: "<form [formGroup]=\"form\">\r\n <!-- buttons -->\r\n <button type=\"button\" class=\"mat-primary\" mat-flat-button (click)=\"addId()\">\r\n <mat-icon>add_circle</mat-icon> ID\r\n </button>\r\n <!-- list -->\r\n @if (entries.value.length) {\r\n <table>\r\n <thead>\r\n <tr>\r\n <th></th>\r\n <th>scope</th>\r\n <th>label</th>\r\n <th>gid</th>\r\n <th>ass.</th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for ( entry of entries.value; track entry; let i = $index; let first =\r\n $first; let last = $last) {\r\n <tr [class.selected]=\"entry === edited\">\r\n <td class=\"fit-width\">\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Edit this ID\"\r\n (click)=\"editId(entry, i)\"\r\n >\r\n <mat-icon class=\"mat-primary\">edit</mat-icon>\r\n </button>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Move this ID up\"\r\n [disabled]=\"first\"\r\n (click)=\"moveIdUp(i)\"\r\n >\r\n <mat-icon>arrow_upward</mat-icon>\r\n </button>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Move this ID down\"\r\n [disabled]=\"last\"\r\n (click)=\"moveIdDown(i)\"\r\n >\r\n <mat-icon>arrow_downward</mat-icon>\r\n </button>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Delete this ID\"\r\n (click)=\"deleteId(i)\"\r\n >\r\n <mat-icon class=\"mat-warn\">remove_circle</mat-icon>\r\n </button>\r\n </td>\r\n <td>{{ entry.scope }}</td>\r\n <td>{{ entry?.target?.label }}</td>\r\n <td>{{ entry?.target?.gid }}</td>\r\n <td>{{ entry?.assertion ? \"Y\" : \"N\" }}</td>\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n }\r\n\r\n <!-- editor -->\r\n <mat-expansion-panel [expanded]=\"edited\" [disabled]=\"!edited\">\r\n <mat-expansion-panel-header\r\n >ID {{ edited?.target?.label }}</mat-expansion-panel-header\r\n >\r\n <cadmus-refs-asserted-composite-id\r\n [idScopeEntries]=\"idScopeEntries()\"\r\n [idTagEntries]=\"idTagEntries()\"\r\n [assTagEntries]=\"assTagEntries()\"\r\n [refTypeEntries]=\"refTypeEntries()\"\r\n [refTagEntries]=\"refTagEntries()\"\r\n [hasSubmit]=\"true\"\r\n [pinByTypeMode]=\"pinByTypeMode()\"\r\n [canSwitchMode]=\"canSwitchMode()\"\r\n [canEditTarget]=\"canEditTarget()\"\r\n [lookupDefinitions]=\"lookupDefinitions()\"\r\n [defaultPartTypeKey]=\"defaultPartTypeKey()\"\r\n [internalDefault]=\"internalDefault()\"\r\n [id]=\"edited\"\r\n (idChange)=\"onIdChange($event)\"\r\n (editorClose)=\"closeId()\"\r\n />\r\n </mat-expansion-panel>\r\n</form>\r\n", styles: ["table{width:100%;border-collapse:collapse}tbody tr:nth-child(odd){background-color:#e2e2e2}th{text-align:left;font-weight:400;color:silver}td.fit-width{width:1px;white-space:nowrap}tr.selected{background-color:#d0d0d0!important}fieldset{border:1px solid silver;border-radius:6px;padding:6px}\n"] }]
1056
+ }], ctorParameters: () => [{ type: i1$1.FormBuilder }, { type: i2.DialogService }], propDecorators: { ids: [{
1057
+ type: Input
1058
+ }] } });
1059
+
1060
+ // from Cadmus general parts
1061
+ const METADATA_PART_ID = 'it.vedph.metadata';
1062
+ /*
1063
+ * Scoped pin-based lookup component. This component provides a list
1064
+ * of pin-based searches, with a lookup control. Whenever the user
1065
+ * picks a pin value, he gets the details about its item and part, and
1066
+ * item's metadata part, if any. He can then use these data to build
1067
+ * some EID by variously assembling these components.
1068
+ */
1069
+ class ScopedPinLookupComponent {
1070
+ _itemService;
1071
+ lookupService;
1072
+ lookupDefs;
1073
+ // lookup
1074
+ key;
1075
+ keyForm;
1076
+ keys;
1077
+ info;
1078
+ // builder
1079
+ id;
1080
+ idForm;
950
1081
  /**
951
- * Called when the item lookup changes (item is looked up
952
- * by its title).
953
- *
954
- * @param item The item got from lookup.
1082
+ * Emitted whenever the user picks an ID.
955
1083
  */
956
- onItemLookupChange(item) {
957
- if (!item) {
958
- return;
959
- }
960
- // load item's parts
961
- this._itemService.getItem(item.id, true, true).subscribe({
962
- next: (i) => {
963
- // setting the item will trigger its parts update
964
- this.item.setValue(i);
965
- this.updateTarget(true);
966
- },
967
- error: (error) => {
968
- if (error) {
969
- console.error('Error getting item', error);
970
- }
971
- this.itemPart.setValue(null);
972
- this.itemParts = [];
973
- this.updateTarget(true);
974
- },
1084
+ idPick = output();
1085
+ constructor(formBuilder, _itemService, lookupService, lookupDefs) {
1086
+ this._itemService = _itemService;
1087
+ this.lookupService = lookupService;
1088
+ this.lookupDefs = lookupDefs;
1089
+ // lookup
1090
+ // keys are all the defined lookup searches
1091
+ this.keys = Object.keys(lookupDefs);
1092
+ // the selected key defines the lookup scope
1093
+ this.key = formBuilder.control(null);
1094
+ this.keyForm = formBuilder.group({
1095
+ key: this.key,
1096
+ });
1097
+ // id
1098
+ this.id = formBuilder.control(null, [
1099
+ Validators.required,
1100
+ Validators.maxLength(300),
1101
+ ]);
1102
+ this.idForm = formBuilder.group({
1103
+ id: this.id,
975
1104
  });
976
1105
  }
977
- loadItemInfo(pin) {
978
- if (!pin) {
979
- return;
1106
+ ngOnInit() {
1107
+ // pre-select a unique key
1108
+ if (this.keys.length === 1) {
1109
+ this.key.setValue(this.keys[0]);
1110
+ this.key.markAsDirty();
1111
+ this.key.updateValueAndValidity();
980
1112
  }
1113
+ }
1114
+ onItemChange(item) {
1115
+ const info = {
1116
+ pin: item,
1117
+ };
1118
+ // lookup item and its metadata part if any
981
1119
  forkJoin({
982
- item: this._itemService.getItem(pin.itemId, false, true),
983
- part: this._itemService.getPartFromTypeAndRole(pin.itemId, METADATA_PART_ID, undefined, true),
1120
+ item: item
1121
+ ? this._itemService.getItem(item.itemId, false, true)
1122
+ : of(null),
1123
+ part: item
1124
+ ? this._itemService.getPartFromTypeAndRole(item.itemId, METADATA_PART_ID, undefined, true)
1125
+ : of(null),
984
1126
  })
985
1127
  .pipe(take(1))
986
1128
  .subscribe({
987
1129
  next: (result) => {
988
- this.lookupData = {
989
- pin: pin,
990
- item: result.item,
991
- metaPart: result.part,
992
- };
993
- this.updateTarget(true);
1130
+ if (result.item) {
1131
+ info.item = result.item;
1132
+ info.part = result.part;
1133
+ this.info = info;
1134
+ }
994
1135
  },
995
1136
  error: (error) => {
996
- this.lookupData = undefined;
997
- console.error('Error loading item/metadata', error);
1137
+ console.error(error ? JSON.stringify(error) : 'Error loading item/metadata');
998
1138
  },
999
1139
  });
1000
1140
  }
1001
- /**
1002
- * Called when the pin lookup change. A pin is looked up by its
1003
- * name and value (=the filter's text), and optionally by:
1004
- * - its index lookup definition (selected by partTypeKey).
1005
- * - its item (defined by item, in filter).
1006
- * - its part (defined by itemPart, in filter).
1007
- *
1008
- * @param info The pin info from pin lookup.
1009
- */
1010
- onPinLookupChange(info) {
1011
- this.loadItemInfo(info);
1012
- }
1013
- onExtItemChange(event) {
1014
- if (event.item) {
1015
- setTimeout(() => {
1016
- this.gid.setValue(event.itemId);
1017
- this.gid.updateValueAndValidity();
1018
- this.gid.markAsDirty();
1019
- this.label.setValue(event.itemLabel);
1020
- this.label.updateValueAndValidity();
1021
- this.label.markAsDirty();
1022
- });
1141
+ appendIdComponent(type, metaIndex = -1) {
1142
+ let id = this.id.value || '';
1143
+ switch (type) {
1144
+ case 'pin':
1145
+ id += this.info?.pin.value;
1146
+ break;
1147
+ case 'itemId':
1148
+ id += this.info.item?.id || '';
1149
+ break;
1150
+ case 'partId':
1151
+ id += this.info.part?.id || '';
1152
+ break;
1153
+ case 'partTypeId':
1154
+ id += this.info.part?.typeId || '';
1155
+ break;
1156
+ case 'partRoleId':
1157
+ id += this.info.part?.roleId || '';
1158
+ break;
1159
+ case 'metadata':
1160
+ id += this.info.part.metadata[metaIndex].value;
1161
+ break;
1023
1162
  }
1163
+ this.id.setValue(id);
1164
+ this.id.markAsDirty();
1165
+ this.id.updateValueAndValidity();
1024
1166
  }
1025
- onExtMoreRequest(event) {
1026
- this.extMoreRequest.emit(event);
1027
- }
1028
- onCopied() {
1029
- this._snackbar.open('Copied to clipboard', 'OK', {
1030
- duration: 1500,
1031
- });
1032
- }
1033
- onExtConfigChange(config) {
1034
- this.extLookupConfigChange.emit(config);
1035
- }
1036
- close() {
1037
- this.editorClose.emit();
1038
- }
1039
- save() {
1040
- if (this.form.invalid) {
1167
+ pickId() {
1168
+ if (this.idForm.invalid) {
1041
1169
  return;
1042
1170
  }
1043
- this.target.set(this.getTarget());
1044
- this.emitChange();
1171
+ this.idPick.emit(this.id.value);
1172
+ this.info = undefined;
1173
+ }
1174
+ resetId() {
1175
+ this.id.reset();
1176
+ this.id.markAsDirty();
1177
+ this.id.updateValueAndValidity();
1045
1178
  }
1046
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: PinTargetLookupComponent, deps: [{ token: 'indexLookupDefinitions' }, { token: ItemRefLookupService }, { token: PinRefLookupService }, { token: i1.ItemService }, { token: i1.ThesaurusService }, { token: i4$1.MatSnackBar }, { token: i1$1.FormBuilder }], target: i0.ɵɵFactoryTarget.Component });
1047
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.0", type: PinTargetLookupComponent, isStandalone: true, selector: "cadmus-pin-target-lookup", inputs: { pinByTypeMode: { classPropertyName: "pinByTypeMode", publicName: "pinByTypeMode", isSignal: true, isRequired: false, transformFunction: null }, canSwitchMode: { classPropertyName: "canSwitchMode", publicName: "canSwitchMode", isSignal: true, isRequired: false, transformFunction: null }, canEditTarget: { classPropertyName: "canEditTarget", publicName: "canEditTarget", isSignal: true, isRequired: false, transformFunction: null }, lookupDefinitions: { classPropertyName: "lookupDefinitions", publicName: "lookupDefinitions", isSignal: true, isRequired: false, transformFunction: null }, extLookupConfigs: { classPropertyName: "extLookupConfigs", publicName: "extLookupConfigs", isSignal: true, isRequired: false, transformFunction: null }, internalDefault: { classPropertyName: "internalDefault", publicName: "internalDefault", isSignal: true, isRequired: false, transformFunction: null }, target: { classPropertyName: "target", publicName: "target", isSignal: true, isRequired: false, transformFunction: null }, defaultPartTypeKey: { classPropertyName: "defaultPartTypeKey", publicName: "defaultPartTypeKey", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { pinByTypeMode: "pinByTypeModeChange", canSwitchMode: "canSwitchModeChange", lookupDefinitions: "lookupDefinitionsChange", target: "targetChange", editorClose: "editorClose", extMoreRequest: "extMoreRequest", extLookupConfigChange: "extLookupConfigChange" }, ngImport: i0, template: "<form [formGroup]=\"form\" (submit)=\"save()\">\r\n <div class=\"form-row\">\r\n <!-- external -->\r\n <mat-checkbox [formControl]=\"external\">external</mat-checkbox>\r\n <!-- mode switcher -->\r\n @if (!external.value) {\r\n <div>\r\n @if (canSwitchMode()) {\r\n <mat-checkbox [formControl]=\"byTypeMode\"> by type</mat-checkbox>\r\n }\r\n </div>\r\n }\r\n </div>\r\n\r\n <div class=\"form-row\">\r\n <!-- label -->\r\n <div>\r\n @if (external.value || canEditTarget()) {\r\n <mat-form-field>\r\n <mat-label>label</mat-label>\r\n <input matInput [formControl]=\"label\" />\r\n @if ($any(label).errors?.required && (label.dirty || label.touched)) {\r\n <mat-error>label required</mat-error>\r\n } @if ( $any(label).errors?.maxLength && (label.dirty || label.touched)\r\n ) {\r\n <mat-error>label too long</mat-error>\r\n }\r\n </mat-form-field>\r\n } @if (!external.value && !canEditTarget() && label.value) {\r\n <div class=\"info\"><span class=\"label\">label</span>{{ label.value }}</div>\r\n }\r\n </div>\r\n\r\n <!-- gid -->\r\n <div>\r\n @if (external.value || canEditTarget()) {\r\n <mat-form-field>\r\n <mat-label>GID</mat-label>\r\n <input matInput [formControl]=\"gid\" />\r\n @if ($any(gid).errors?.required && (gid.dirty || gid.touched)) {\r\n <mat-error>GID required</mat-error>\r\n } @if ($any(gid).errors?.maxLength && (gid.dirty || gid.touched)) {\r\n <mat-error>GID too long</mat-error>\r\n }\r\n </mat-form-field>\r\n } @if (!external.value && !canEditTarget() && gid.value) {\r\n <div class=\"info\">\r\n <span class=\"label\">GID</span> <span class=\"gid\">{{ gid.value }}</span>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n\r\n <!-- external lookup set -->\r\n @if (external.value && extLookupConfigs().length) {\r\n <div>\r\n <cadmus-ref-lookup-set\r\n [configs]=\"extLookupConfigs()\"\r\n (itemChange)=\"onExtItemChange($event)\"\r\n (moreRequest)=\"onExtMoreRequest($event)\"\r\n (configChange)=\"onExtConfigChange($any($event))\"\r\n ></cadmus-ref-lookup-set>\r\n </div>\r\n }\r\n\r\n <!-- BY ITEM -->\r\n @if (!external.value) {\r\n <div>\r\n <div class=\"form-row\">\r\n @if (!byTypeMode.value) {\r\n <fieldset class=\"form-row\">\r\n <legend>pin filters</legend>\r\n <!-- item filter -->\r\n <cadmus-ref-lookup\r\n [service]=\"itemLookupService\"\r\n label=\"item\"\r\n (itemChange)=\"onItemLookupChange($event)\"\r\n ></cadmus-ref-lookup>\r\n <!-- part filter -->\r\n @if (itemParts.length) {\r\n <mat-form-field>\r\n <mat-label>part</mat-label>\r\n <mat-select [formControl]=\"itemPart\">\r\n <mat-option [value]=\"null\">(any)</mat-option>\r\n @for (p of itemParts; track p) {\r\n <mat-option [value]=\"p\">{{\r\n p.typeId | flatLookup : modelEntries : \"id\" : \"value\"\r\n }}</mat-option>\r\n }\r\n </mat-select>\r\n </mat-form-field>\r\n }\r\n </fieldset>\r\n }\r\n <!-- BY TYPE -->\r\n @if (byTypeMode.value) {\r\n <div>\r\n <!-- par type filter -->\r\n @if (partTypeKeys.length) {\r\n <mat-form-field>\r\n <mat-label>part type</mat-label>\r\n <mat-select [formControl]=\"partTypeKey\">\r\n @for (k of partTypeKeys; track k) {\r\n <mat-option [value]=\"k\">{{ k }}</mat-option>\r\n }\r\n </mat-select>\r\n </mat-form-field>\r\n }\r\n </div>\r\n }\r\n <!-- PIN -->\r\n @if (partTypeKey.value) {\r\n <div>\r\n <!-- pin lookup -->\r\n <cadmus-ref-lookup\r\n [service]=\"pinLookupService\"\r\n [baseFilter]=\"filter\"\r\n [options]=\"pinFilterOptions\"\r\n label=\"pin\"\r\n (itemChange)=\"onPinLookupChange($event)\"\r\n />\r\n </div>\r\n }\r\n </div>\r\n <!-- data -->\r\n @if (lookupData?.pin?.name) {\r\n <mat-expansion-panel id=\"data\">\r\n <mat-expansion-panel-header>pin data</mat-expansion-panel-header>\r\n <!-- table -->\r\n <table>\r\n <thead>\r\n <th></th>\r\n <th>source</th>\r\n <th>value</th>\r\n </thead>\r\n <tbody>\r\n <!-- pin -->\r\n @if (lookupData?.pin?.value) {\r\n <tr>\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n [cdkCopyToClipboard]=\"lookupData!.pin!.value\"\r\n (cdkCopyToClipboardCopied)=\"onCopied()\"\r\n >\r\n <mat-icon class=\"mat-primary\">content_copy</mat-icon>\r\n </button>\r\n </td>\r\n <td>pin</td>\r\n <td>{{ lookupData!.pin.value }}</td>\r\n </tr>\r\n }\r\n <!-- item ID -->\r\n @if (lookupData?.pin?.itemId) {\r\n <tr>\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n [cdkCopyToClipboard]=\"lookupData!.pin!.itemId\"\r\n (cdkCopyToClipboardCopied)=\"onCopied()\"\r\n >\r\n <mat-icon class=\"mat-primary\">content_copy</mat-icon>\r\n </button>\r\n </td>\r\n <td>item ID</td>\r\n <td>{{ lookupData!.pin.itemId }}</td>\r\n </tr>\r\n }\r\n <!-- item title -->\r\n @if (lookupData?.item?.title) {\r\n <tr>\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n [cdkCopyToClipboard]=\"lookupData!.item!.title\"\r\n (cdkCopyToClipboardCopied)=\"onCopied()\"\r\n >\r\n <mat-icon class=\"mat-primary\">content_copy</mat-icon>\r\n </button>\r\n </td>\r\n <td>item title</td>\r\n <td>{{ lookupData!.item!.title }}</td>\r\n </tr>\r\n }\r\n <!-- part ID -->\r\n @if (lookupData?.pin?.partId) {\r\n <tr>\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n [cdkCopyToClipboard]=\"lookupData!.pin!.partId\"\r\n (cdkCopyToClipboardCopied)=\"onCopied()\"\r\n >\r\n <mat-icon class=\"mat-primary\">content_copy</mat-icon>\r\n </button>\r\n </td>\r\n <td>part ID</td>\r\n <td>{{ lookupData!.pin.partId }}</td>\r\n </tr>\r\n }\r\n <!-- part type ID -->\r\n @if (lookupData?.pin?.partTypeId) {\r\n <tr>\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n [cdkCopyToClipboard]=\"lookupData!.pin!.partTypeId\"\r\n (cdkCopyToClipboardCopied)=\"onCopied()\"\r\n >\r\n <mat-icon class=\"mat-primary\">content_copy</mat-icon>\r\n </button>\r\n </td>\r\n <td>part type ID</td>\r\n <td>{{ lookupData!.pin!.partTypeId }}</td>\r\n </tr>\r\n }\r\n <!-- part role ID -->\r\n @if (lookupData?.pin?.roleId) {\r\n <tr>\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n [cdkCopyToClipboard]=\"lookupData!.pin!.roleId!\"\r\n (cdkCopyToClipboardCopied)=\"onCopied()\"\r\n >\r\n <mat-icon class=\"mat-primary\">content_copy</mat-icon>\r\n </button>\r\n </td>\r\n <td>part role ID</td>\r\n <td>{{ lookupData!.pin!.roleId }}</td>\r\n </tr>\r\n }\r\n <!-- part's metadata -->\r\n @for ( m of lookupData?.metaPart?.metadata || []; track m; let i =\r\n $index) {\r\n <tr>\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n [cdkCopyToClipboard]=\"m.value\"\r\n (cdkCopyToClipboardCopied)=\"onCopied()\"\r\n >\r\n <mat-icon class=\"mat-primary\">content_copy</mat-icon>\r\n </button>\r\n </td>\r\n <td class=\"metadata\">{{ m.name }}</td>\r\n <td class=\"metadata\">{{ m.value }}</td>\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n </mat-expansion-panel>\r\n }\r\n </div>\r\n }\r\n\r\n <!-- buttons -->\r\n <div class=\"button-row\" id=\"toolbar\">\r\n <button mat-icon-button type=\"button\" (click)=\"close()\">\r\n <mat-icon class=\"mat-warn\">close</mat-icon>\r\n </button>\r\n <button mat-flat-button type=\"submit\" [disabled]=\"form.invalid\">\r\n <mat-icon>check_circle</mat-icon>\r\n target\r\n </button>\r\n </div>\r\n</form>\r\n", styles: [".metadata{color:#4a3001}.info{border:1px solid silver;border-radius:6px;background-color:silver;color:#fff;padding:4px;margin:8px 0}.info .label{background-color:#fff;color:silver;margin:0 6px}#data{margin:8px 0}table{border:1px solid silver;border-radius:6px;padding:4px;margin-top:8px}tr:nth-child(odd){background-color:#f0f0f0}th{font-weight:400;text-align:left;color:silver}.form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}.button-row{display:flex;align-items:center;flex-wrap:wrap}.label{border:1px solid silver;border-radius:6px;padding:4px}fieldset{border:1px solid silver;border-radius:6px;padding:8px;margin-bottom:8px}legend{color:silver}div#toolbar{margin-top:8px}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: ClipboardModule }, { kind: "directive", type: i6$2.CdkCopyToClipboard, selector: "[cdkCopyToClipboard]", inputs: ["cdkCopyToClipboard", "cdkCopyToClipboardAttempts"], outputs: ["cdkCopyToClipboardCopied"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i3.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i8$1.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "component", type: i4.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i4.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i7.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i8.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i9.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i9.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: RefLookupComponent, selector: "cadmus-ref-lookup", inputs: ["label", "limit", "baseFilter", "service", "item", "required", "hasMore", "linkTemplate", "optDialog", "options"], outputs: ["itemChange", "optionsChange", "moreRequest"] }, { kind: "component", type: RefLookupSetComponent, selector: "cadmus-ref-lookup-set", inputs: ["configs", "iconSize"], outputs: ["configChange", "itemChange", "moreRequest"] }, { kind: "pipe", type: FlatLookupPipe, name: "flatLookup" }] });
1179
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: ScopedPinLookupComponent, deps: [{ token: i1$1.FormBuilder }, { token: i1.ItemService }, { token: PinRefLookupService }, { token: 'indexLookupDefinitions' }], target: i0.ɵɵFactoryTarget.Component });
1180
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.0", type: ScopedPinLookupComponent, isStandalone: true, selector: "cadmus-scoped-pin-lookup", outputs: { idPick: "idPick" }, ngImport: i0, template: "<div>\r\n <!-- lookup -->\r\n <div>\r\n <form [formGroup]=\"keyForm\" class=\"form-row\">\r\n <!-- key -->\r\n @if (keys.length > 1) {\r\n <mat-form-field>\r\n <mat-label>type</mat-label>\r\n <mat-select [formControl]=\"key\">\r\n @for (k of keys; track k) {\r\n <mat-option [value]=\"k\">{{ k }}</mat-option>\r\n }\r\n </mat-select>\r\n @if ($any(key).errors?.required && (key.dirty || key.touched)) {\r\n <mat-error>type required</mat-error>\r\n }\r\n </mat-form-field>\r\n }\r\n <cadmus-ref-lookup\r\n [service]=\"lookupService\"\r\n label=\"pin\"\r\n [options]=\"key.value ? lookupDefs[key.value] : undefined\"\r\n (itemChange)=\"onItemChange($event)\"\r\n />\r\n </form>\r\n </div>\r\n\r\n <!-- builder -->\r\n @if (info) {\r\n <mat-expansion-panel [expanded]=\"info\" [disabled]=\"!info\">\r\n <mat-expansion-panel-header>ID builder</mat-expansion-panel-header>\r\n <!-- ID -->\r\n <div>\r\n <form [formGroup]=\"idForm\" (submit)=\"pickId()\">\r\n <mat-form-field style=\"width: 100%\">\r\n <input matInput [formControl]=\"id\" />\r\n @if ($any(id).errors?.required && (id.dirty || id.touched)) {\r\n <mat-error>ID required</mat-error>\r\n } @if ($any(id).errors?.maxLength && (id.dirty || id.touched)) {\r\n <mat-error>ID too long</mat-error>\r\n }\r\n <button\r\n mat-icon-button\r\n type=\"button\"\r\n matSuffix\r\n (click)=\"resetId()\"\r\n [disabled]=\"!id.value\"\r\n >\r\n <mat-icon class=\"mat-warn\">close</mat-icon>\r\n </button>\r\n <button\r\n mat-icon-button\r\n type=\"button\"\r\n matSuffix\r\n (click)=\"pickId()\"\r\n [disabled]=\"idForm.invalid\"\r\n >\r\n <mat-icon class=\"mat-primary\">check_circle</mat-icon>\r\n </button>\r\n </mat-form-field>\r\n </form>\r\n </div>\r\n <!-- table -->\r\n <table>\r\n <thead>\r\n <th></th>\r\n <th>source</th>\r\n <th>value</th>\r\n </thead>\r\n <tbody>\r\n <!-- pin -->\r\n <tr class=\"fit-width\">\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n (click)=\"appendIdComponent('pin')\"\r\n >\r\n <mat-icon class=\"mat-primary\">add_circle</mat-icon>\r\n </button>\r\n </td>\r\n <td>pin</td>\r\n <td>{{ info!.pin.value }}</td>\r\n </tr>\r\n <!-- item ID -->\r\n <tr>\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n (click)=\"appendIdComponent('itemId')\"\r\n >\r\n <mat-icon class=\"mat-primary\">add_circle</mat-icon>\r\n </button>\r\n </td>\r\n <td>item ID</td>\r\n <td>{{ info!.item?.id }}</td>\r\n </tr>\r\n <!-- item title -->\r\n <tr>\r\n <td></td>\r\n <td>item title</td>\r\n <td>{{ info!.item?.title }}</td>\r\n </tr>\r\n <!-- part ID -->\r\n <tr>\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n (click)=\"appendIdComponent('partId')\"\r\n >\r\n <mat-icon class=\"mat-primary\">add_circle</mat-icon>\r\n </button>\r\n </td>\r\n <td>part ID</td>\r\n <td>{{ info!.part?.id }}</td>\r\n </tr>\r\n <!-- part type ID -->\r\n <tr>\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n (click)=\"appendIdComponent('partTypeId')\"\r\n >\r\n <mat-icon class=\"mat-primary\">add_circle</mat-icon>\r\n </button>\r\n </td>\r\n <td>part type ID</td>\r\n <td>{{ info!.part?.typeId }}</td>\r\n </tr>\r\n <!-- part role ID -->\r\n <tr>\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n (click)=\"appendIdComponent('partRoleId')\"\r\n >\r\n <mat-icon class=\"mat-primary\">add_circle</mat-icon>\r\n </button>\r\n </td>\r\n <td>part role ID</td>\r\n <td>{{ info!.part?.roleId }}</td>\r\n </tr>\r\n <!-- part's metadata -->\r\n @for (m of info!.part?.metadata; track m; let i = $index) {\r\n <tr>\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n (click)=\"appendIdComponent('metadata', i)\"\r\n >\r\n <mat-icon class=\"mat-primary\">add_circle</mat-icon>\r\n </button>\r\n </td>\r\n <td class=\"metadata\">{{ m.name }}</td>\r\n <td class=\"metadata\">{{ m.value }}</td>\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n </mat-expansion-panel>\r\n }\r\n</div>\r\n", styles: [".metadata{color:#4a3001}table{border:1px solid silver;border-radius:6px;padding:4px;margin-top:8px}tr:nth-child(odd){background-color:#f0f0f0}th{font-weight:400;text-align:left;color:silver}td.fit-width{width:1px;white-space:nowrap}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type:
1181
+ // material
1182
+ MatButtonModule }, { kind: "component", type: i3.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "component", type: i4$1.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i4$1.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i6$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6$1.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6$1.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i6$1.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i7.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i8$1.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i9.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i9.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type:
1183
+ // bricks
1184
+ RefLookupComponent, selector: "cadmus-ref-lookup", inputs: ["label", "limit", "baseFilter", "service", "item", "required", "hasMore", "linkTemplate", "optDialog", "options"], outputs: ["itemChange", "optionsChange", "moreRequest"] }] });
1048
1185
  }
1049
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: PinTargetLookupComponent, decorators: [{
1186
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: ScopedPinLookupComponent, decorators: [{
1050
1187
  type: Component,
1051
- args: [{ selector: 'cadmus-pin-target-lookup', imports: [
1188
+ args: [{ selector: 'cadmus-scoped-pin-lookup', imports: [
1052
1189
  FormsModule,
1053
1190
  ReactiveFormsModule,
1054
- ClipboardModule,
1191
+ // material
1055
1192
  MatButtonModule,
1056
- MatCheckboxModule,
1057
1193
  MatExpansionModule,
1058
1194
  MatFormFieldModule,
1059
1195
  MatIconModule,
1060
1196
  MatInputModule,
1061
1197
  MatSelectModule,
1198
+ // bricks
1062
1199
  RefLookupComponent,
1063
- RefLookupSetComponent,
1064
- FlatLookupPipe,
1065
- ], template: "<form [formGroup]=\"form\" (submit)=\"save()\">\r\n <div class=\"form-row\">\r\n <!-- external -->\r\n <mat-checkbox [formControl]=\"external\">external</mat-checkbox>\r\n <!-- mode switcher -->\r\n @if (!external.value) {\r\n <div>\r\n @if (canSwitchMode()) {\r\n <mat-checkbox [formControl]=\"byTypeMode\"> by type</mat-checkbox>\r\n }\r\n </div>\r\n }\r\n </div>\r\n\r\n <div class=\"form-row\">\r\n <!-- label -->\r\n <div>\r\n @if (external.value || canEditTarget()) {\r\n <mat-form-field>\r\n <mat-label>label</mat-label>\r\n <input matInput [formControl]=\"label\" />\r\n @if ($any(label).errors?.required && (label.dirty || label.touched)) {\r\n <mat-error>label required</mat-error>\r\n } @if ( $any(label).errors?.maxLength && (label.dirty || label.touched)\r\n ) {\r\n <mat-error>label too long</mat-error>\r\n }\r\n </mat-form-field>\r\n } @if (!external.value && !canEditTarget() && label.value) {\r\n <div class=\"info\"><span class=\"label\">label</span>{{ label.value }}</div>\r\n }\r\n </div>\r\n\r\n <!-- gid -->\r\n <div>\r\n @if (external.value || canEditTarget()) {\r\n <mat-form-field>\r\n <mat-label>GID</mat-label>\r\n <input matInput [formControl]=\"gid\" />\r\n @if ($any(gid).errors?.required && (gid.dirty || gid.touched)) {\r\n <mat-error>GID required</mat-error>\r\n } @if ($any(gid).errors?.maxLength && (gid.dirty || gid.touched)) {\r\n <mat-error>GID too long</mat-error>\r\n }\r\n </mat-form-field>\r\n } @if (!external.value && !canEditTarget() && gid.value) {\r\n <div class=\"info\">\r\n <span class=\"label\">GID</span> <span class=\"gid\">{{ gid.value }}</span>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n\r\n <!-- external lookup set -->\r\n @if (external.value && extLookupConfigs().length) {\r\n <div>\r\n <cadmus-ref-lookup-set\r\n [configs]=\"extLookupConfigs()\"\r\n (itemChange)=\"onExtItemChange($event)\"\r\n (moreRequest)=\"onExtMoreRequest($event)\"\r\n (configChange)=\"onExtConfigChange($any($event))\"\r\n ></cadmus-ref-lookup-set>\r\n </div>\r\n }\r\n\r\n <!-- BY ITEM -->\r\n @if (!external.value) {\r\n <div>\r\n <div class=\"form-row\">\r\n @if (!byTypeMode.value) {\r\n <fieldset class=\"form-row\">\r\n <legend>pin filters</legend>\r\n <!-- item filter -->\r\n <cadmus-ref-lookup\r\n [service]=\"itemLookupService\"\r\n label=\"item\"\r\n (itemChange)=\"onItemLookupChange($event)\"\r\n ></cadmus-ref-lookup>\r\n <!-- part filter -->\r\n @if (itemParts.length) {\r\n <mat-form-field>\r\n <mat-label>part</mat-label>\r\n <mat-select [formControl]=\"itemPart\">\r\n <mat-option [value]=\"null\">(any)</mat-option>\r\n @for (p of itemParts; track p) {\r\n <mat-option [value]=\"p\">{{\r\n p.typeId | flatLookup : modelEntries : \"id\" : \"value\"\r\n }}</mat-option>\r\n }\r\n </mat-select>\r\n </mat-form-field>\r\n }\r\n </fieldset>\r\n }\r\n <!-- BY TYPE -->\r\n @if (byTypeMode.value) {\r\n <div>\r\n <!-- par type filter -->\r\n @if (partTypeKeys.length) {\r\n <mat-form-field>\r\n <mat-label>part type</mat-label>\r\n <mat-select [formControl]=\"partTypeKey\">\r\n @for (k of partTypeKeys; track k) {\r\n <mat-option [value]=\"k\">{{ k }}</mat-option>\r\n }\r\n </mat-select>\r\n </mat-form-field>\r\n }\r\n </div>\r\n }\r\n <!-- PIN -->\r\n @if (partTypeKey.value) {\r\n <div>\r\n <!-- pin lookup -->\r\n <cadmus-ref-lookup\r\n [service]=\"pinLookupService\"\r\n [baseFilter]=\"filter\"\r\n [options]=\"pinFilterOptions\"\r\n label=\"pin\"\r\n (itemChange)=\"onPinLookupChange($event)\"\r\n />\r\n </div>\r\n }\r\n </div>\r\n <!-- data -->\r\n @if (lookupData?.pin?.name) {\r\n <mat-expansion-panel id=\"data\">\r\n <mat-expansion-panel-header>pin data</mat-expansion-panel-header>\r\n <!-- table -->\r\n <table>\r\n <thead>\r\n <th></th>\r\n <th>source</th>\r\n <th>value</th>\r\n </thead>\r\n <tbody>\r\n <!-- pin -->\r\n @if (lookupData?.pin?.value) {\r\n <tr>\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n [cdkCopyToClipboard]=\"lookupData!.pin!.value\"\r\n (cdkCopyToClipboardCopied)=\"onCopied()\"\r\n >\r\n <mat-icon class=\"mat-primary\">content_copy</mat-icon>\r\n </button>\r\n </td>\r\n <td>pin</td>\r\n <td>{{ lookupData!.pin.value }}</td>\r\n </tr>\r\n }\r\n <!-- item ID -->\r\n @if (lookupData?.pin?.itemId) {\r\n <tr>\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n [cdkCopyToClipboard]=\"lookupData!.pin!.itemId\"\r\n (cdkCopyToClipboardCopied)=\"onCopied()\"\r\n >\r\n <mat-icon class=\"mat-primary\">content_copy</mat-icon>\r\n </button>\r\n </td>\r\n <td>item ID</td>\r\n <td>{{ lookupData!.pin.itemId }}</td>\r\n </tr>\r\n }\r\n <!-- item title -->\r\n @if (lookupData?.item?.title) {\r\n <tr>\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n [cdkCopyToClipboard]=\"lookupData!.item!.title\"\r\n (cdkCopyToClipboardCopied)=\"onCopied()\"\r\n >\r\n <mat-icon class=\"mat-primary\">content_copy</mat-icon>\r\n </button>\r\n </td>\r\n <td>item title</td>\r\n <td>{{ lookupData!.item!.title }}</td>\r\n </tr>\r\n }\r\n <!-- part ID -->\r\n @if (lookupData?.pin?.partId) {\r\n <tr>\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n [cdkCopyToClipboard]=\"lookupData!.pin!.partId\"\r\n (cdkCopyToClipboardCopied)=\"onCopied()\"\r\n >\r\n <mat-icon class=\"mat-primary\">content_copy</mat-icon>\r\n </button>\r\n </td>\r\n <td>part ID</td>\r\n <td>{{ lookupData!.pin.partId }}</td>\r\n </tr>\r\n }\r\n <!-- part type ID -->\r\n @if (lookupData?.pin?.partTypeId) {\r\n <tr>\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n [cdkCopyToClipboard]=\"lookupData!.pin!.partTypeId\"\r\n (cdkCopyToClipboardCopied)=\"onCopied()\"\r\n >\r\n <mat-icon class=\"mat-primary\">content_copy</mat-icon>\r\n </button>\r\n </td>\r\n <td>part type ID</td>\r\n <td>{{ lookupData!.pin!.partTypeId }}</td>\r\n </tr>\r\n }\r\n <!-- part role ID -->\r\n @if (lookupData?.pin?.roleId) {\r\n <tr>\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n [cdkCopyToClipboard]=\"lookupData!.pin!.roleId!\"\r\n (cdkCopyToClipboardCopied)=\"onCopied()\"\r\n >\r\n <mat-icon class=\"mat-primary\">content_copy</mat-icon>\r\n </button>\r\n </td>\r\n <td>part role ID</td>\r\n <td>{{ lookupData!.pin!.roleId }}</td>\r\n </tr>\r\n }\r\n <!-- part's metadata -->\r\n @for ( m of lookupData?.metaPart?.metadata || []; track m; let i =\r\n $index) {\r\n <tr>\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n [cdkCopyToClipboard]=\"m.value\"\r\n (cdkCopyToClipboardCopied)=\"onCopied()\"\r\n >\r\n <mat-icon class=\"mat-primary\">content_copy</mat-icon>\r\n </button>\r\n </td>\r\n <td class=\"metadata\">{{ m.name }}</td>\r\n <td class=\"metadata\">{{ m.value }}</td>\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n </mat-expansion-panel>\r\n }\r\n </div>\r\n }\r\n\r\n <!-- buttons -->\r\n <div class=\"button-row\" id=\"toolbar\">\r\n <button mat-icon-button type=\"button\" (click)=\"close()\">\r\n <mat-icon class=\"mat-warn\">close</mat-icon>\r\n </button>\r\n <button mat-flat-button type=\"submit\" [disabled]=\"form.invalid\">\r\n <mat-icon>check_circle</mat-icon>\r\n target\r\n </button>\r\n </div>\r\n</form>\r\n", styles: [".metadata{color:#4a3001}.info{border:1px solid silver;border-radius:6px;background-color:silver;color:#fff;padding:4px;margin:8px 0}.info .label{background-color:#fff;color:silver;margin:0 6px}#data{margin:8px 0}table{border:1px solid silver;border-radius:6px;padding:4px;margin-top:8px}tr:nth-child(odd){background-color:#f0f0f0}th{font-weight:400;text-align:left;color:silver}.form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}.button-row{display:flex;align-items:center;flex-wrap:wrap}.label{border:1px solid silver;border-radius:6px;padding:4px}fieldset{border:1px solid silver;border-radius:6px;padding:8px;margin-bottom:8px}legend{color:silver}div#toolbar{margin-top:8px}\n"] }]
1066
- }], ctorParameters: () => [{ type: undefined, decorators: [{
1200
+ ], template: "<div>\r\n <!-- lookup -->\r\n <div>\r\n <form [formGroup]=\"keyForm\" class=\"form-row\">\r\n <!-- key -->\r\n @if (keys.length > 1) {\r\n <mat-form-field>\r\n <mat-label>type</mat-label>\r\n <mat-select [formControl]=\"key\">\r\n @for (k of keys; track k) {\r\n <mat-option [value]=\"k\">{{ k }}</mat-option>\r\n }\r\n </mat-select>\r\n @if ($any(key).errors?.required && (key.dirty || key.touched)) {\r\n <mat-error>type required</mat-error>\r\n }\r\n </mat-form-field>\r\n }\r\n <cadmus-ref-lookup\r\n [service]=\"lookupService\"\r\n label=\"pin\"\r\n [options]=\"key.value ? lookupDefs[key.value] : undefined\"\r\n (itemChange)=\"onItemChange($event)\"\r\n />\r\n </form>\r\n </div>\r\n\r\n <!-- builder -->\r\n @if (info) {\r\n <mat-expansion-panel [expanded]=\"info\" [disabled]=\"!info\">\r\n <mat-expansion-panel-header>ID builder</mat-expansion-panel-header>\r\n <!-- ID -->\r\n <div>\r\n <form [formGroup]=\"idForm\" (submit)=\"pickId()\">\r\n <mat-form-field style=\"width: 100%\">\r\n <input matInput [formControl]=\"id\" />\r\n @if ($any(id).errors?.required && (id.dirty || id.touched)) {\r\n <mat-error>ID required</mat-error>\r\n } @if ($any(id).errors?.maxLength && (id.dirty || id.touched)) {\r\n <mat-error>ID too long</mat-error>\r\n }\r\n <button\r\n mat-icon-button\r\n type=\"button\"\r\n matSuffix\r\n (click)=\"resetId()\"\r\n [disabled]=\"!id.value\"\r\n >\r\n <mat-icon class=\"mat-warn\">close</mat-icon>\r\n </button>\r\n <button\r\n mat-icon-button\r\n type=\"button\"\r\n matSuffix\r\n (click)=\"pickId()\"\r\n [disabled]=\"idForm.invalid\"\r\n >\r\n <mat-icon class=\"mat-primary\">check_circle</mat-icon>\r\n </button>\r\n </mat-form-field>\r\n </form>\r\n </div>\r\n <!-- table -->\r\n <table>\r\n <thead>\r\n <th></th>\r\n <th>source</th>\r\n <th>value</th>\r\n </thead>\r\n <tbody>\r\n <!-- pin -->\r\n <tr class=\"fit-width\">\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n (click)=\"appendIdComponent('pin')\"\r\n >\r\n <mat-icon class=\"mat-primary\">add_circle</mat-icon>\r\n </button>\r\n </td>\r\n <td>pin</td>\r\n <td>{{ info!.pin.value }}</td>\r\n </tr>\r\n <!-- item ID -->\r\n <tr>\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n (click)=\"appendIdComponent('itemId')\"\r\n >\r\n <mat-icon class=\"mat-primary\">add_circle</mat-icon>\r\n </button>\r\n </td>\r\n <td>item ID</td>\r\n <td>{{ info!.item?.id }}</td>\r\n </tr>\r\n <!-- item title -->\r\n <tr>\r\n <td></td>\r\n <td>item title</td>\r\n <td>{{ info!.item?.title }}</td>\r\n </tr>\r\n <!-- part ID -->\r\n <tr>\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n (click)=\"appendIdComponent('partId')\"\r\n >\r\n <mat-icon class=\"mat-primary\">add_circle</mat-icon>\r\n </button>\r\n </td>\r\n <td>part ID</td>\r\n <td>{{ info!.part?.id }}</td>\r\n </tr>\r\n <!-- part type ID -->\r\n <tr>\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n (click)=\"appendIdComponent('partTypeId')\"\r\n >\r\n <mat-icon class=\"mat-primary\">add_circle</mat-icon>\r\n </button>\r\n </td>\r\n <td>part type ID</td>\r\n <td>{{ info!.part?.typeId }}</td>\r\n </tr>\r\n <!-- part role ID -->\r\n <tr>\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n (click)=\"appendIdComponent('partRoleId')\"\r\n >\r\n <mat-icon class=\"mat-primary\">add_circle</mat-icon>\r\n </button>\r\n </td>\r\n <td>part role ID</td>\r\n <td>{{ info!.part?.roleId }}</td>\r\n </tr>\r\n <!-- part's metadata -->\r\n @for (m of info!.part?.metadata; track m; let i = $index) {\r\n <tr>\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n (click)=\"appendIdComponent('metadata', i)\"\r\n >\r\n <mat-icon class=\"mat-primary\">add_circle</mat-icon>\r\n </button>\r\n </td>\r\n <td class=\"metadata\">{{ m.name }}</td>\r\n <td class=\"metadata\">{{ m.value }}</td>\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n </mat-expansion-panel>\r\n }\r\n</div>\r\n", styles: [".metadata{color:#4a3001}table{border:1px solid silver;border-radius:6px;padding:4px;margin-top:8px}tr:nth-child(odd){background-color:#f0f0f0}th{font-weight:400;text-align:left;color:silver}td.fit-width{width:1px;white-space:nowrap}\n"] }]
1201
+ }], ctorParameters: () => [{ type: i1$1.FormBuilder }, { type: i1.ItemService }, { type: PinRefLookupService }, { type: undefined, decorators: [{
1067
1202
  type: Inject,
1068
1203
  args: ['indexLookupDefinitions']
1069
- }] }, { type: ItemRefLookupService }, { type: PinRefLookupService }, { type: i1.ItemService }, { type: i1.ThesaurusService }, { type: i4$1.MatSnackBar }, { type: i1$1.FormBuilder }] });
1204
+ }] }] });
1070
1205
 
1071
1206
  /**
1072
- * The key to be used to retrieve the external lookup configs from the
1073
- * settings storage. This is equal to the selector of
1074
- * AssertedCompositeIdComponent plus ".configs".
1075
- */
1076
- const ASSERTED_COMPOSITE_ID_CONFIGS_KEY = 'cadmus-refs-asserted-composite-id.configs';
1077
- /**
1078
- * An asserted composite ID editor. This allows the user to edit an asserted
1079
- * composite ID, which can be an external ID or a lookup ID.
1207
+ * Asserted ID editor component.
1080
1208
  */
1081
- class AssertedCompositeIdComponent {
1209
+ class AssertedIdComponent {
1082
1210
  lookupService;
1083
1211
  lookupDefs;
1084
1212
  _sub;
1085
1213
  _updatingForm;
1086
- extLookupConfigs;
1087
- targetExpanded = false;
1088
- // form
1089
- target;
1090
- scope;
1091
1214
  tag;
1215
+ value;
1216
+ label;
1217
+ scope;
1092
1218
  assertion;
1093
1219
  form;
1220
+ lookupExpanded;
1094
1221
  // asserted-id-scopes
1095
1222
  idScopeEntries = input();
1096
1223
  // asserted-id-tags
@@ -1102,71 +1229,40 @@ class AssertedCompositeIdComponent {
1102
1229
  // doc-reference-tags
1103
1230
  refTagEntries = input();
1104
1231
  /**
1105
- * The ID being edited.
1232
+ * The asserted ID being edited.
1106
1233
  */
1107
1234
  id = model();
1108
1235
  /**
1109
- * True if when a new ID is set it should be internal rather than
1110
- * external by default.
1236
+ * True to hide the pin-based EID lookup UI.
1111
1237
  */
1112
- internalDefault = input();
1238
+ noEidLookup = input();
1113
1239
  /**
1114
- * True if the UI has a submit button.
1240
+ * True to show the submit button.
1115
1241
  */
1116
1242
  hasSubmit = input();
1117
1243
  /**
1118
- * True when the internal UI preselected mode should be by type rather than
1119
- * by item. User can change mode unless modeSwitching is false.
1120
- */
1121
- pinByTypeMode = input();
1122
- /**
1123
- * True when the user can switch between by-type and by-item mode in
1124
- * the internal UI.
1125
- */
1126
- canSwitchMode = input();
1127
- /**
1128
- * True when the user can edit the target's gid/label for internal targets.
1129
- */
1130
- canEditTarget = input();
1131
- /**
1132
- * The lookup definitions to be used for the by-type lookup in the internal UI.
1133
- * If not specified, the lookup definitions will be got via injection
1134
- * when available; if the injected definitions are empty, the
1135
- * lookup definitions will be built from the model-types thesaurus;
1136
- * if this is not available either, the by-type lookup will be
1137
- * disabled.
1138
- */
1139
- lookupDefinitions = input();
1140
- /**
1141
- * The default part type key to be used.
1142
- */
1143
- defaultPartTypeKey = input();
1144
- /**
1145
- * Emitted whenever the user requests to close the editor.
1244
+ * Emitted when the editor is closed.
1146
1245
  */
1147
1246
  editorClose = output();
1148
- /**
1149
- * Emitted when the user requests more.
1150
- */
1151
- extMoreRequest = output();
1152
- constructor(formBuilder, lookupService, lookupDefs, settings) {
1247
+ constructor(formBuilder, lookupService, lookupDefs) {
1153
1248
  this.lookupService = lookupService;
1154
1249
  this.lookupDefs = lookupDefs;
1155
- // form
1156
- this.target = formBuilder.control(null, Validators.required);
1157
- this.scope = formBuilder.control(null, Validators.maxLength(500));
1158
1250
  this.tag = formBuilder.control(null, Validators.maxLength(50));
1251
+ this.value = formBuilder.control(null, [
1252
+ Validators.required,
1253
+ Validators.maxLength(500),
1254
+ ]);
1255
+ this.label = formBuilder.control(null, Validators.maxLength(500));
1256
+ this.scope = formBuilder.control(null, Validators.maxLength(500));
1159
1257
  this.assertion = formBuilder.control(null);
1160
1258
  this.form = formBuilder.group({
1161
- target: this.target,
1162
- scope: this.scope,
1163
1259
  tag: this.tag,
1260
+ value: this.value,
1261
+ label: this.label,
1262
+ scope: this.scope,
1164
1263
  assertion: this.assertion,
1165
1264
  });
1166
- // external lookup configs
1167
- this.extLookupConfigs =
1168
- settings.retrieve(ASSERTED_COMPOSITE_ID_CONFIGS_KEY) ||
1169
- [];
1265
+ this.lookupExpanded = false;
1170
1266
  // when id changes, update form
1171
1267
  effect(() => {
1172
1268
  this.updateForm(this.id());
@@ -1174,7 +1270,7 @@ class AssertedCompositeIdComponent {
1174
1270
  }
1175
1271
  ngOnInit() {
1176
1272
  this._sub = this.form.valueChanges
1177
- .pipe(debounceTime(300))
1273
+ .pipe(debounceTime$1(300))
1178
1274
  .subscribe((_) => {
1179
1275
  if (!this._updatingForm) {
1180
1276
  this.emitIdChange();
@@ -1187,40 +1283,33 @@ class AssertedCompositeIdComponent {
1187
1283
  onAssertionChange(assertion) {
1188
1284
  this.assertion.setValue(assertion || null);
1189
1285
  }
1190
- onTargetChange(target) {
1191
- this.target.setValue(target);
1192
- this.target.markAsDirty();
1193
- this.target.updateValueAndValidity();
1194
- if (this.form.valid) {
1195
- this.targetExpanded = false;
1196
- }
1286
+ onIdPick(id) {
1287
+ this.value.setValue(id);
1288
+ this.value.markAsDirty();
1289
+ this.value.updateValueAndValidity();
1290
+ this.lookupExpanded = false;
1197
1291
  }
1198
- updateForm(id) {
1292
+ updateForm(value) {
1199
1293
  this._updatingForm = true;
1200
- if (!id) {
1294
+ if (!value) {
1201
1295
  this.form.reset();
1202
1296
  }
1203
1297
  else {
1204
- this.target.setValue(id.target);
1205
- this.scope.setValue(id.scope || null);
1206
- this.tag.setValue(id.tag || null);
1207
- this.assertion.setValue(id.assertion || null);
1298
+ this.tag.setValue(value.tag || null);
1299
+ this.value.setValue(value.value);
1300
+ this.label.setValue(value.label || null);
1301
+ this.scope.setValue(value.scope);
1302
+ this.assertion.setValue(value.assertion || null);
1208
1303
  this.form.markAsPristine();
1209
1304
  }
1210
1305
  this._updatingForm = false;
1211
1306
  }
1212
1307
  getId() {
1213
- const external = !this.target.value?.name;
1214
- const target = this.target.value;
1215
1308
  return {
1216
- target: external
1217
- ? {
1218
- gid: target?.gid || '',
1219
- label: target?.label || target?.gid || '',
1220
- }
1221
- : target,
1222
- scope: this.scope.value?.trim() || '',
1223
1309
  tag: this.tag.value?.trim(),
1310
+ value: this.value.value?.trim() || '',
1311
+ label: this.label.value?.trim() || undefined,
1312
+ scope: this.scope.value?.trim() || '',
1224
1313
  assertion: this.assertion.value || undefined,
1225
1314
  };
1226
1315
  }
@@ -1229,20 +1318,6 @@ class AssertedCompositeIdComponent {
1229
1318
  this.id.set(this.getId());
1230
1319
  }
1231
1320
  }
1232
- onEditorClose() {
1233
- this.targetExpanded = false;
1234
- }
1235
- onExtMoreRequest(event) {
1236
- this.extMoreRequest.emit(event);
1237
- }
1238
- onExtLookupConfigChange(config) {
1239
- if (!this.scope.value ||
1240
- this.extLookupConfigs.some((c) => c.name === this.scope.value)) {
1241
- this.scope.setValue(config.name || null);
1242
- this.scope.markAsDirty();
1243
- this.scope.updateValueAndValidity();
1244
- }
1245
- }
1246
1321
  cancel() {
1247
1322
  this.editorClose.emit();
1248
1323
  }
@@ -1251,48 +1326,45 @@ class AssertedCompositeIdComponent {
1251
1326
  this.id.set(this.getId());
1252
1327
  }
1253
1328
  }
1254
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: AssertedCompositeIdComponent, deps: [{ token: i1$1.FormBuilder }, { token: PinRefLookupService }, { token: 'indexLookupDefinitions' }, { token: i3$1.RamStorageService }], target: i0.ɵɵFactoryTarget.Component });
1255
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.0", type: AssertedCompositeIdComponent, isStandalone: true, selector: "cadmus-refs-asserted-composite-id", inputs: { idScopeEntries: { classPropertyName: "idScopeEntries", publicName: "idScopeEntries", isSignal: true, isRequired: false, transformFunction: null }, idTagEntries: { classPropertyName: "idTagEntries", publicName: "idTagEntries", isSignal: true, isRequired: false, transformFunction: null }, assTagEntries: { classPropertyName: "assTagEntries", publicName: "assTagEntries", isSignal: true, isRequired: false, transformFunction: null }, refTypeEntries: { classPropertyName: "refTypeEntries", publicName: "refTypeEntries", isSignal: true, isRequired: false, transformFunction: null }, refTagEntries: { classPropertyName: "refTagEntries", publicName: "refTagEntries", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, internalDefault: { classPropertyName: "internalDefault", publicName: "internalDefault", isSignal: true, isRequired: false, transformFunction: null }, hasSubmit: { classPropertyName: "hasSubmit", publicName: "hasSubmit", isSignal: true, isRequired: false, transformFunction: null }, pinByTypeMode: { classPropertyName: "pinByTypeMode", publicName: "pinByTypeMode", isSignal: true, isRequired: false, transformFunction: null }, canSwitchMode: { classPropertyName: "canSwitchMode", publicName: "canSwitchMode", isSignal: true, isRequired: false, transformFunction: null }, canEditTarget: { classPropertyName: "canEditTarget", publicName: "canEditTarget", isSignal: true, isRequired: false, transformFunction: null }, lookupDefinitions: { classPropertyName: "lookupDefinitions", publicName: "lookupDefinitions", isSignal: true, isRequired: false, transformFunction: null }, defaultPartTypeKey: { classPropertyName: "defaultPartTypeKey", publicName: "defaultPartTypeKey", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { id: "idChange", editorClose: "editorClose", extMoreRequest: "extMoreRequest" }, ngImport: i0, template: "<form [formGroup]=\"form\" (submit)=\"save()\">\n <div>\n <div class=\"form-row\">\n <!-- tag (bound) -->\n @if (idTagEntries()?.length) {\n <mat-form-field class=\"short-text\">\n <mat-label>tag</mat-label>\n <mat-select [formControl]=\"tag\">\n @for (e of idTagEntries(); track e) {\n <mat-option [value]=\"e.id\">{{ e.value }}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n }\n <!-- tag (free) -->\n @else {\n <mat-form-field class=\"short-text\">\n <mat-label>tag</mat-label>\n <input matInput [formControl]=\"tag\" />\n @if ($any(tag.errors)?.maxLength && (tag.dirty || tag.touched)) {\n <mat-error>tag too long</mat-error>\n }\n </mat-form-field>\n }\n\n <!-- scope (bound) -->\n @if (idScopeEntries()?.length) {\n <mat-form-field class=\"short-text\">\n <mat-label>scope</mat-label>\n <mat-select [formControl]=\"scope\">\n @for (e of idScopeEntries(); track e) {\n <mat-option [value]=\"e.id\">{{ e.value }}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n }\n <!-- scope (free) -->\n @else {\n <mat-form-field class=\"short-text\">\n <mat-label>scope</mat-label>\n <input matInput [formControl]=\"scope\" />\n @if ( $any(scope.errors)?.maxLength && (scope.dirty || scope.touched) )\n {\n <mat-error>scope too long</mat-error>\n }\n </mat-form-field>\n }\n\n <!-- label and GID -->\n @if (target.value?.label) {\n <div class=\"info\">\n <span class=\"label\">label</span>{{ target.value?.label }}\n </div>\n } @if (target.value?.gid) {\n <div class=\"info\">\n <span class=\"label\">GID</span>{{ target.value?.gid }}\n </div>\n }\n </div>\n\n <!-- target -->\n <div class=\"boxed\">\n <mat-expansion-panel [(expanded)]=\"targetExpanded\">\n <mat-expansion-panel-header>target</mat-expansion-panel-header>\n <cadmus-pin-target-lookup\n [pinByTypeMode]=\"pinByTypeMode()\"\n [canSwitchMode]=\"canSwitchMode()\"\n [canEditTarget]=\"canEditTarget()\"\n [lookupDefinitions]=\"lookupDefinitions()\"\n [defaultPartTypeKey]=\"defaultPartTypeKey()\"\n [target]=\"target.value || undefined\"\n [internalDefault]=\"internalDefault()\"\n [extLookupConfigs]=\"extLookupConfigs\"\n (targetChange)=\"onTargetChange($event)\"\n (editorClose)=\"onEditorClose()\"\n (extMoreRequest)=\"onExtMoreRequest($event)\"\n (extLookupConfigChange)=\"onExtLookupConfigChange($event)\"\n />\n </mat-expansion-panel>\n </div>\n\n <!-- assertion -->\n <br />\n <div class=\"boxed\">\n <mat-expansion-panel>\n <mat-expansion-panel-header>assertion</mat-expansion-panel-header>\n <cadmus-refs-assertion\n [assTagEntries]=\"assTagEntries()\"\n [refTypeEntries]=\"refTypeEntries()\"\n [refTagEntries]=\"refTagEntries()\"\n [assertion]=\"assertion.value || undefined\"\n (assertionChange)=\"onAssertionChange($event)\"\n >\n </cadmus-refs-assertion>\n </mat-expansion-panel>\n </div>\n </div>\n\n <!-- buttons -->\n @if (hasSubmit()) {\n <div>\n <button\n mat-icon-button\n type=\"button\"\n (click)=\"cancel()\"\n [disabled]=\"!this.target.value?.gid || !this.target.value?.label\"\n >\n <mat-icon class=\"mat-warn\">close</mat-icon>\n </button>\n <button mat-icon-button type=\"submit\" [disabled]=\"form.invalid\">\n <mat-icon class=\"mat-primary\">check_circle</mat-icon>\n </button>\n </div>\n }\n</form>\n", styles: [".form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}.boxed{border:1px solid silver;border-radius:6px;padding:6px}.short-text{width:8em}.pin-info{font-size:90%;color:silver}fieldset{border:1px solid silver;border-radius:6px;padding:6px}.info{border:1px solid silver;border-radius:6px;background-color:silver;color:#fff;padding:4px}.info .label{background-color:#fff;color:silver;margin:0 6px}@media only screen and (max-width: 959px){div#container{grid-template-rows:1fr auto;grid-template-columns:1fr;grid-template-areas:\"editor\" \"lookup\"}}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "component", type: i4.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i4.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i7.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i8.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i9.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i9.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "component", type: AssertionComponent, selector: "cadmus-refs-assertion", inputs: ["assTagEntries", "refTypeEntries", "refTagEntries", "assertion"], outputs: ["assertionChange"] }, { kind: "component", type: PinTargetLookupComponent, selector: "cadmus-pin-target-lookup", inputs: ["pinByTypeMode", "canSwitchMode", "canEditTarget", "lookupDefinitions", "extLookupConfigs", "internalDefault", "target", "defaultPartTypeKey"], outputs: ["pinByTypeModeChange", "canSwitchModeChange", "lookupDefinitionsChange", "targetChange", "editorClose", "extMoreRequest", "extLookupConfigChange"] }] });
1329
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: AssertedIdComponent, deps: [{ token: i1$1.FormBuilder }, { token: PinRefLookupService }, { token: 'indexLookupDefinitions' }], target: i0.ɵɵFactoryTarget.Component });
1330
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.0", type: AssertedIdComponent, isStandalone: true, selector: "cadmus-refs-asserted-id", inputs: { idScopeEntries: { classPropertyName: "idScopeEntries", publicName: "idScopeEntries", isSignal: true, isRequired: false, transformFunction: null }, idTagEntries: { classPropertyName: "idTagEntries", publicName: "idTagEntries", isSignal: true, isRequired: false, transformFunction: null }, assTagEntries: { classPropertyName: "assTagEntries", publicName: "assTagEntries", isSignal: true, isRequired: false, transformFunction: null }, refTypeEntries: { classPropertyName: "refTypeEntries", publicName: "refTypeEntries", isSignal: true, isRequired: false, transformFunction: null }, refTagEntries: { classPropertyName: "refTagEntries", publicName: "refTagEntries", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, noEidLookup: { classPropertyName: "noEidLookup", publicName: "noEidLookup", isSignal: true, isRequired: false, transformFunction: null }, hasSubmit: { classPropertyName: "hasSubmit", publicName: "hasSubmit", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { id: "idChange", editorClose: "editorClose" }, ngImport: i0, template: "<form [formGroup]=\"form\" (submit)=\"save()\">\r\n <div>\r\n <div class=\"form-row\">\r\n <!-- tag (bound) -->\r\n @if (idTagEntries()?.length) {\r\n <mat-form-field>\r\n <mat-label>tag</mat-label>\r\n <mat-select [formControl]=\"tag\">\r\n @for (e of idTagEntries(); track e) {\r\n <mat-option [value]=\"e.id\">{{ e.value }}</mat-option>\r\n }\r\n </mat-select>\r\n </mat-form-field>\r\n }\r\n <!-- tag (free) -->\r\n @else {\r\n <mat-form-field>\r\n <mat-label>tag</mat-label>\r\n <input matInput [formControl]=\"tag\" />\r\n @if ($any(tag.errors)?.maxLength && (tag.dirty || tag.touched)) {\r\n <mat-error>tag too long</mat-error>\r\n }\r\n </mat-form-field>\r\n }\r\n\r\n <!-- scope (bound) -->\r\n @if (idScopeEntries()?.length) {\r\n <mat-form-field>\r\n <mat-label>scope</mat-label>\r\n <mat-select [formControl]=\"scope\">\r\n @for (e of idScopeEntries(); track e) {\r\n <mat-option [value]=\"e.id\">{{ e.value }}</mat-option>\r\n }\r\n </mat-select>\r\n </mat-form-field>\r\n }\r\n <!-- scope (free) -->\r\n @else {\r\n <mat-form-field>\r\n <mat-label>scope</mat-label>\r\n <input matInput [formControl]=\"scope\" />\r\n @if ($any(scope.errors)?.maxLength && (scope.dirty || scope.touched)) {\r\n <mat-error>scope too long</mat-error>\r\n }\r\n </mat-form-field>\r\n }\r\n\r\n <!-- value -->\r\n <mat-form-field>\r\n <mat-label>value</mat-label>\r\n <input matInput [formControl]=\"value\" />\r\n @if ($any(value.errors)?.required && (value.dirty || value.touched)) {\r\n <mat-error>value required</mat-error>\r\n } @if ($any(value.errors)?.maxLength && (value.dirty || value.touched))\r\n {\r\n <mat-error>value too long</mat-error>\r\n }\r\n </mat-form-field>\r\n\r\n <!-- label -->\r\n <mat-form-field>\r\n <mat-label>label</mat-label>\r\n <input matInput [formControl]=\"label\" />\r\n @if ($any(label.errors)?.maxLength && (label.dirty || label.touched)) {\r\n <mat-error>label too long</mat-error>\r\n }\r\n </mat-form-field>\r\n\r\n <!-- lookup -->\r\n @if (!noEidLookup()) {\r\n <div>\r\n <mat-expansion-panel [(expanded)]=\"lookupExpanded\">\r\n <mat-expansion-panel-header>lookup</mat-expansion-panel-header>\r\n <cadmus-scoped-pin-lookup (idPick)=\"onIdPick($event)\" />\r\n </mat-expansion-panel>\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- assertion -->\r\n <mat-expansion-panel>\r\n <mat-expansion-panel-header>assertion</mat-expansion-panel-header>\r\n <cadmus-refs-assertion\r\n [assTagEntries]=\"assTagEntries()\"\r\n [refTypeEntries]=\"refTypeEntries()\"\r\n [refTagEntries]=\"refTagEntries()\"\r\n [assertion]=\"assertion.value || undefined\"\r\n (assertionChange)=\"onAssertionChange($event)\"\r\n />\r\n </mat-expansion-panel>\r\n </div>\r\n\r\n <!-- buttons -->\r\n @if (hasSubmit()) {\r\n <div>\r\n <button mat-icon-button type=\"button\" (click)=\"cancel()\">\r\n <mat-icon class=\"mat-warn\">close</mat-icon>\r\n </button>\r\n <button mat-icon-button type=\"submit\" [disabled]=\"form.invalid\">\r\n <mat-icon class=\"mat-primary\">check_circle</mat-icon>\r\n </button>\r\n </div>\r\n }\r\n</form>\r\n", styles: [".form-row{display:flex;gap:8px;align-items:flex-start;flex-wrap:wrap}.form-row *{flex:0 0 auto}.pin-info{font-size:90%;color:silver}fieldset{border:1px solid silver;border-radius:6px;padding:6px}@media only screen and (max-width: 959px){div#container{grid-template-rows:1fr auto;grid-template-columns:1fr;grid-template-areas:\"editor\" \"lookup\"}}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type:
1331
+ // material
1332
+ MatButtonModule }, { kind: "component", type: i3.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "component", type: i4$1.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i4$1.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i6$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6$1.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6$1.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i7.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i8$1.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i9.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i9.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type:
1333
+ // bricks
1334
+ AssertionComponent, selector: "cadmus-refs-assertion", inputs: ["assTagEntries", "refTypeEntries", "refTagEntries", "assertion"], outputs: ["assertionChange"] }, { kind: "component", type: ScopedPinLookupComponent, selector: "cadmus-scoped-pin-lookup", outputs: ["idPick"] }] });
1256
1335
  }
1257
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: AssertedCompositeIdComponent, decorators: [{
1336
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: AssertedIdComponent, decorators: [{
1258
1337
  type: Component,
1259
- args: [{ selector: 'cadmus-refs-asserted-composite-id', imports: [
1338
+ args: [{ selector: 'cadmus-refs-asserted-id', imports: [
1339
+ FormsModule,
1260
1340
  ReactiveFormsModule,
1341
+ // material
1261
1342
  MatButtonModule,
1262
1343
  MatExpansionModule,
1263
1344
  MatFormFieldModule,
1264
1345
  MatIconModule,
1265
1346
  MatInputModule,
1266
1347
  MatSelectModule,
1267
- MatTooltipModule,
1348
+ // bricks
1268
1349
  AssertionComponent,
1269
- PinTargetLookupComponent,
1270
- ], template: "<form [formGroup]=\"form\" (submit)=\"save()\">\n <div>\n <div class=\"form-row\">\n <!-- tag (bound) -->\n @if (idTagEntries()?.length) {\n <mat-form-field class=\"short-text\">\n <mat-label>tag</mat-label>\n <mat-select [formControl]=\"tag\">\n @for (e of idTagEntries(); track e) {\n <mat-option [value]=\"e.id\">{{ e.value }}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n }\n <!-- tag (free) -->\n @else {\n <mat-form-field class=\"short-text\">\n <mat-label>tag</mat-label>\n <input matInput [formControl]=\"tag\" />\n @if ($any(tag.errors)?.maxLength && (tag.dirty || tag.touched)) {\n <mat-error>tag too long</mat-error>\n }\n </mat-form-field>\n }\n\n <!-- scope (bound) -->\n @if (idScopeEntries()?.length) {\n <mat-form-field class=\"short-text\">\n <mat-label>scope</mat-label>\n <mat-select [formControl]=\"scope\">\n @for (e of idScopeEntries(); track e) {\n <mat-option [value]=\"e.id\">{{ e.value }}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n }\n <!-- scope (free) -->\n @else {\n <mat-form-field class=\"short-text\">\n <mat-label>scope</mat-label>\n <input matInput [formControl]=\"scope\" />\n @if ( $any(scope.errors)?.maxLength && (scope.dirty || scope.touched) )\n {\n <mat-error>scope too long</mat-error>\n }\n </mat-form-field>\n }\n\n <!-- label and GID -->\n @if (target.value?.label) {\n <div class=\"info\">\n <span class=\"label\">label</span>{{ target.value?.label }}\n </div>\n } @if (target.value?.gid) {\n <div class=\"info\">\n <span class=\"label\">GID</span>{{ target.value?.gid }}\n </div>\n }\n </div>\n\n <!-- target -->\n <div class=\"boxed\">\n <mat-expansion-panel [(expanded)]=\"targetExpanded\">\n <mat-expansion-panel-header>target</mat-expansion-panel-header>\n <cadmus-pin-target-lookup\n [pinByTypeMode]=\"pinByTypeMode()\"\n [canSwitchMode]=\"canSwitchMode()\"\n [canEditTarget]=\"canEditTarget()\"\n [lookupDefinitions]=\"lookupDefinitions()\"\n [defaultPartTypeKey]=\"defaultPartTypeKey()\"\n [target]=\"target.value || undefined\"\n [internalDefault]=\"internalDefault()\"\n [extLookupConfigs]=\"extLookupConfigs\"\n (targetChange)=\"onTargetChange($event)\"\n (editorClose)=\"onEditorClose()\"\n (extMoreRequest)=\"onExtMoreRequest($event)\"\n (extLookupConfigChange)=\"onExtLookupConfigChange($event)\"\n />\n </mat-expansion-panel>\n </div>\n\n <!-- assertion -->\n <br />\n <div class=\"boxed\">\n <mat-expansion-panel>\n <mat-expansion-panel-header>assertion</mat-expansion-panel-header>\n <cadmus-refs-assertion\n [assTagEntries]=\"assTagEntries()\"\n [refTypeEntries]=\"refTypeEntries()\"\n [refTagEntries]=\"refTagEntries()\"\n [assertion]=\"assertion.value || undefined\"\n (assertionChange)=\"onAssertionChange($event)\"\n >\n </cadmus-refs-assertion>\n </mat-expansion-panel>\n </div>\n </div>\n\n <!-- buttons -->\n @if (hasSubmit()) {\n <div>\n <button\n mat-icon-button\n type=\"button\"\n (click)=\"cancel()\"\n [disabled]=\"!this.target.value?.gid || !this.target.value?.label\"\n >\n <mat-icon class=\"mat-warn\">close</mat-icon>\n </button>\n <button mat-icon-button type=\"submit\" [disabled]=\"form.invalid\">\n <mat-icon class=\"mat-primary\">check_circle</mat-icon>\n </button>\n </div>\n }\n</form>\n", styles: [".form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}.boxed{border:1px solid silver;border-radius:6px;padding:6px}.short-text{width:8em}.pin-info{font-size:90%;color:silver}fieldset{border:1px solid silver;border-radius:6px;padding:6px}.info{border:1px solid silver;border-radius:6px;background-color:silver;color:#fff;padding:4px}.info .label{background-color:#fff;color:silver;margin:0 6px}@media only screen and (max-width: 959px){div#container{grid-template-rows:1fr auto;grid-template-columns:1fr;grid-template-areas:\"editor\" \"lookup\"}}\n"] }]
1350
+ ScopedPinLookupComponent,
1351
+ ], template: "<form [formGroup]=\"form\" (submit)=\"save()\">\r\n <div>\r\n <div class=\"form-row\">\r\n <!-- tag (bound) -->\r\n @if (idTagEntries()?.length) {\r\n <mat-form-field>\r\n <mat-label>tag</mat-label>\r\n <mat-select [formControl]=\"tag\">\r\n @for (e of idTagEntries(); track e) {\r\n <mat-option [value]=\"e.id\">{{ e.value }}</mat-option>\r\n }\r\n </mat-select>\r\n </mat-form-field>\r\n }\r\n <!-- tag (free) -->\r\n @else {\r\n <mat-form-field>\r\n <mat-label>tag</mat-label>\r\n <input matInput [formControl]=\"tag\" />\r\n @if ($any(tag.errors)?.maxLength && (tag.dirty || tag.touched)) {\r\n <mat-error>tag too long</mat-error>\r\n }\r\n </mat-form-field>\r\n }\r\n\r\n <!-- scope (bound) -->\r\n @if (idScopeEntries()?.length) {\r\n <mat-form-field>\r\n <mat-label>scope</mat-label>\r\n <mat-select [formControl]=\"scope\">\r\n @for (e of idScopeEntries(); track e) {\r\n <mat-option [value]=\"e.id\">{{ e.value }}</mat-option>\r\n }\r\n </mat-select>\r\n </mat-form-field>\r\n }\r\n <!-- scope (free) -->\r\n @else {\r\n <mat-form-field>\r\n <mat-label>scope</mat-label>\r\n <input matInput [formControl]=\"scope\" />\r\n @if ($any(scope.errors)?.maxLength && (scope.dirty || scope.touched)) {\r\n <mat-error>scope too long</mat-error>\r\n }\r\n </mat-form-field>\r\n }\r\n\r\n <!-- value -->\r\n <mat-form-field>\r\n <mat-label>value</mat-label>\r\n <input matInput [formControl]=\"value\" />\r\n @if ($any(value.errors)?.required && (value.dirty || value.touched)) {\r\n <mat-error>value required</mat-error>\r\n } @if ($any(value.errors)?.maxLength && (value.dirty || value.touched))\r\n {\r\n <mat-error>value too long</mat-error>\r\n }\r\n </mat-form-field>\r\n\r\n <!-- label -->\r\n <mat-form-field>\r\n <mat-label>label</mat-label>\r\n <input matInput [formControl]=\"label\" />\r\n @if ($any(label.errors)?.maxLength && (label.dirty || label.touched)) {\r\n <mat-error>label too long</mat-error>\r\n }\r\n </mat-form-field>\r\n\r\n <!-- lookup -->\r\n @if (!noEidLookup()) {\r\n <div>\r\n <mat-expansion-panel [(expanded)]=\"lookupExpanded\">\r\n <mat-expansion-panel-header>lookup</mat-expansion-panel-header>\r\n <cadmus-scoped-pin-lookup (idPick)=\"onIdPick($event)\" />\r\n </mat-expansion-panel>\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- assertion -->\r\n <mat-expansion-panel>\r\n <mat-expansion-panel-header>assertion</mat-expansion-panel-header>\r\n <cadmus-refs-assertion\r\n [assTagEntries]=\"assTagEntries()\"\r\n [refTypeEntries]=\"refTypeEntries()\"\r\n [refTagEntries]=\"refTagEntries()\"\r\n [assertion]=\"assertion.value || undefined\"\r\n (assertionChange)=\"onAssertionChange($event)\"\r\n />\r\n </mat-expansion-panel>\r\n </div>\r\n\r\n <!-- buttons -->\r\n @if (hasSubmit()) {\r\n <div>\r\n <button mat-icon-button type=\"button\" (click)=\"cancel()\">\r\n <mat-icon class=\"mat-warn\">close</mat-icon>\r\n </button>\r\n <button mat-icon-button type=\"submit\" [disabled]=\"form.invalid\">\r\n <mat-icon class=\"mat-primary\">check_circle</mat-icon>\r\n </button>\r\n </div>\r\n }\r\n</form>\r\n", styles: [".form-row{display:flex;gap:8px;align-items:flex-start;flex-wrap:wrap}.form-row *{flex:0 0 auto}.pin-info{font-size:90%;color:silver}fieldset{border:1px solid silver;border-radius:6px;padding:6px}@media only screen and (max-width: 959px){div#container{grid-template-rows:1fr auto;grid-template-columns:1fr;grid-template-areas:\"editor\" \"lookup\"}}\n"] }]
1271
1352
  }], ctorParameters: () => [{ type: i1$1.FormBuilder }, { type: PinRefLookupService }, { type: undefined, decorators: [{
1272
1353
  type: Inject,
1273
1354
  args: ['indexLookupDefinitions']
1274
- }] }, { type: i3$1.RamStorageService }] });
1355
+ }] }] });
1275
1356
 
1276
1357
  /**
1277
- * Asserted composite IDs editor.
1358
+ * Asserted IDs editor.
1278
1359
  */
1279
- class AssertedCompositeIdsComponent {
1360
+ class AssertedIdsComponent {
1280
1361
  _dialogService;
1281
- _ids;
1282
1362
  _editedIndex;
1283
1363
  edited;
1284
1364
  /**
1285
1365
  * The asserted IDs.
1286
1366
  */
1287
- get ids() {
1288
- return this._ids;
1289
- }
1290
- set ids(value) {
1291
- if (this._ids !== value) {
1292
- this._ids = value || [];
1293
- this.updateForm(value);
1294
- }
1295
- }
1367
+ ids = model([]);
1296
1368
  // asserted-id-scopes
1297
1369
  idScopeEntries = input();
1298
1370
  // asserted-id-tags
@@ -1303,53 +1375,20 @@ class AssertedCompositeIdsComponent {
1303
1375
  refTypeEntries = input();
1304
1376
  // doc-reference-tags
1305
1377
  refTagEntries = input();
1306
- /**
1307
- * True when the internal UI preselected mode should be by type rather than
1308
- * by item. User can change mode unless modeSwitching is false.
1309
- */
1310
- pinByTypeMode = input();
1311
- /**
1312
- * True when the user can switch between by-type and by-item mode in
1313
- * the internal UI.
1314
- */
1315
- canSwitchMode = input();
1316
- /**
1317
- * True when the user can edit the target's gid/label for internal targets.
1318
- */
1319
- canEditTarget = input();
1320
- /**
1321
- * The lookup definitions to be used for the by-type lookup in the internal UI.
1322
- * If not specified, the lookup definitions will be got via injection
1323
- * when available; if the injected definitions are empty, the
1324
- * lookup definitions will be built from the model-types thesaurus;
1325
- * if this is not available either, the by-type lookup will be
1326
- * disabled.
1327
- */
1328
- lookupDefinitions = input();
1329
- /**
1330
- * The default part type key.
1331
- */
1332
- defaultPartTypeKey = input();
1333
- /**
1334
- * True if when a new ID is set it should be internal rather than
1335
- * external by default.
1336
- */
1337
- internalDefault = input();
1338
- /**
1339
- * Emitted whenever any ID changes.
1340
- */
1341
- idsChange = output();
1342
1378
  entries;
1343
1379
  form;
1344
1380
  constructor(formBuilder, _dialogService) {
1345
1381
  this._dialogService = _dialogService;
1346
- this._ids = [];
1347
1382
  this._editedIndex = -1;
1348
1383
  this.entries = formBuilder.control([], { nonNullable: true });
1349
1384
  // form
1350
1385
  this.form = formBuilder.group({
1351
1386
  ids: this.entries,
1352
1387
  });
1388
+ // when ids change, update form
1389
+ effect(() => {
1390
+ this.updateForm(this.ids());
1391
+ });
1353
1392
  }
1354
1393
  updateForm(ids) {
1355
1394
  if (!ids?.length) {
@@ -1360,12 +1399,10 @@ class AssertedCompositeIdsComponent {
1360
1399
  this.entries.updateValueAndValidity();
1361
1400
  this.form.markAsPristine();
1362
1401
  }
1363
- emitIdsChange() {
1364
- this.idsChange.emit(this.entries.value);
1365
- }
1366
1402
  addId() {
1367
1403
  this.editId({
1368
- target: { gid: '', label: '' },
1404
+ scope: '',
1405
+ value: '',
1369
1406
  }, -1);
1370
1407
  }
1371
1408
  editId(id, index) {
@@ -1403,7 +1440,7 @@ class AssertedCompositeIdsComponent {
1403
1440
  this.entries.setValue(entries);
1404
1441
  this.entries.markAsDirty();
1405
1442
  this.entries.updateValueAndValidity();
1406
- this.emitIdsChange();
1443
+ this.ids.set(this.entries.value);
1407
1444
  }
1408
1445
  });
1409
1446
  }
@@ -1418,7 +1455,7 @@ class AssertedCompositeIdsComponent {
1418
1455
  this.entries.setValue(entries);
1419
1456
  this.entries.markAsDirty();
1420
1457
  this.entries.updateValueAndValidity();
1421
- this.emitIdsChange();
1458
+ this.ids.set(this.entries.value);
1422
1459
  }
1423
1460
  moveIdDown(index) {
1424
1461
  if (index + 1 >= this.entries.value.length) {
@@ -1431,31 +1468,33 @@ class AssertedCompositeIdsComponent {
1431
1468
  this.entries.setValue(entries);
1432
1469
  this.entries.markAsDirty();
1433
1470
  this.entries.updateValueAndValidity();
1434
- this.emitIdsChange();
1471
+ this.ids.set(this.entries.value);
1435
1472
  }
1436
1473
  onIdChange(id) {
1437
1474
  this.saveId(id);
1438
- this.emitIdsChange();
1475
+ this.ids.set(this.entries.value);
1439
1476
  }
1440
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: AssertedCompositeIdsComponent, deps: [{ token: i1$1.FormBuilder }, { token: i2.DialogService }], target: i0.ɵɵFactoryTarget.Component });
1441
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.0", type: AssertedCompositeIdsComponent, isStandalone: true, selector: "cadmus-refs-asserted-composite-ids", inputs: { ids: { classPropertyName: "ids", publicName: "ids", isSignal: false, isRequired: false, transformFunction: null }, idScopeEntries: { classPropertyName: "idScopeEntries", publicName: "idScopeEntries", isSignal: true, isRequired: false, transformFunction: null }, idTagEntries: { classPropertyName: "idTagEntries", publicName: "idTagEntries", isSignal: true, isRequired: false, transformFunction: null }, assTagEntries: { classPropertyName: "assTagEntries", publicName: "assTagEntries", isSignal: true, isRequired: false, transformFunction: null }, refTypeEntries: { classPropertyName: "refTypeEntries", publicName: "refTypeEntries", isSignal: true, isRequired: false, transformFunction: null }, refTagEntries: { classPropertyName: "refTagEntries", publicName: "refTagEntries", isSignal: true, isRequired: false, transformFunction: null }, pinByTypeMode: { classPropertyName: "pinByTypeMode", publicName: "pinByTypeMode", isSignal: true, isRequired: false, transformFunction: null }, canSwitchMode: { classPropertyName: "canSwitchMode", publicName: "canSwitchMode", isSignal: true, isRequired: false, transformFunction: null }, canEditTarget: { classPropertyName: "canEditTarget", publicName: "canEditTarget", isSignal: true, isRequired: false, transformFunction: null }, lookupDefinitions: { classPropertyName: "lookupDefinitions", publicName: "lookupDefinitions", isSignal: true, isRequired: false, transformFunction: null }, defaultPartTypeKey: { classPropertyName: "defaultPartTypeKey", publicName: "defaultPartTypeKey", isSignal: true, isRequired: false, transformFunction: null }, internalDefault: { classPropertyName: "internalDefault", publicName: "internalDefault", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { idsChange: "idsChange" }, ngImport: i0, template: "<form [formGroup]=\"form\">\r\n <!-- buttons -->\r\n <button type=\"button\" class=\"mat-primary\" mat-flat-button (click)=\"addId()\">\r\n <mat-icon>add_circle</mat-icon> ID\r\n </button>\r\n <!-- list -->\r\n @if (entries.value.length) {\r\n <table>\r\n <thead>\r\n <tr>\r\n <th></th>\r\n <th>scope</th>\r\n <th>label</th>\r\n <th>gid</th>\r\n <th>ass.</th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for ( entry of entries.value; track entry; let i = $index; let first =\r\n $first; let last = $last) {\r\n <tr [class.selected]=\"entry === edited\">\r\n <td class=\"fit-width\">\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Edit this ID\"\r\n (click)=\"editId(entry, i)\"\r\n >\r\n <mat-icon class=\"mat-primary\">edit</mat-icon>\r\n </button>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Move this ID up\"\r\n [disabled]=\"first\"\r\n (click)=\"moveIdUp(i)\"\r\n >\r\n <mat-icon>arrow_upward</mat-icon>\r\n </button>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Move this ID down\"\r\n [disabled]=\"last\"\r\n (click)=\"moveIdDown(i)\"\r\n >\r\n <mat-icon>arrow_downward</mat-icon>\r\n </button>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Delete this ID\"\r\n (click)=\"deleteId(i)\"\r\n >\r\n <mat-icon class=\"mat-warn\">remove_circle</mat-icon>\r\n </button>\r\n </td>\r\n <td>{{ entry.scope }}</td>\r\n <td>{{ entry?.target?.label }}</td>\r\n <td>{{ entry?.target?.gid }}</td>\r\n <td>{{ entry?.assertion ? \"Y\" : \"N\" }}</td>\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n }\r\n\r\n <!-- editor -->\r\n <mat-expansion-panel [expanded]=\"edited\" [disabled]=\"!edited\">\r\n <mat-expansion-panel-header\r\n >ID {{ edited?.target?.label }}</mat-expansion-panel-header\r\n >\r\n <cadmus-refs-asserted-composite-id\r\n [idScopeEntries]=\"idScopeEntries()\"\r\n [idTagEntries]=\"idTagEntries()\"\r\n [assTagEntries]=\"assTagEntries()\"\r\n [refTypeEntries]=\"refTypeEntries()\"\r\n [refTagEntries]=\"refTagEntries()\"\r\n [hasSubmit]=\"true\"\r\n [pinByTypeMode]=\"pinByTypeMode()\"\r\n [canSwitchMode]=\"canSwitchMode()\"\r\n [canEditTarget]=\"canEditTarget()\"\r\n [lookupDefinitions]=\"lookupDefinitions()\"\r\n [defaultPartTypeKey]=\"defaultPartTypeKey()\"\r\n [internalDefault]=\"internalDefault()\"\r\n [id]=\"edited\"\r\n (idChange)=\"onIdChange($event)\"\r\n (editorClose)=\"closeId()\"\r\n />\r\n </mat-expansion-panel>\r\n</form>\r\n", styles: ["table{width:100%;border-collapse:collapse}tbody tr:nth-child(odd){background-color:#e2e2e2}th{text-align:left;font-weight:400;color:silver}td.fit-width{width:1px;white-space:nowrap}tr.selected{background-color:#d0d0d0!important}fieldset{border:1px solid silver;border-radius:6px;padding:6px}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i3.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "component", type: i4.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i4.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i7.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "component", type: AssertedCompositeIdComponent, selector: "cadmus-refs-asserted-composite-id", inputs: ["idScopeEntries", "idTagEntries", "assTagEntries", "refTypeEntries", "refTagEntries", "id", "internalDefault", "hasSubmit", "pinByTypeMode", "canSwitchMode", "canEditTarget", "lookupDefinitions", "defaultPartTypeKey"], outputs: ["idChange", "editorClose", "extMoreRequest"] }] });
1477
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: AssertedIdsComponent, deps: [{ token: i1$1.FormBuilder }, { token: i2.DialogService }], target: i0.ɵɵFactoryTarget.Component });
1478
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.0", type: AssertedIdsComponent, isStandalone: true, selector: "cadmus-refs-asserted-ids", inputs: { ids: { classPropertyName: "ids", publicName: "ids", isSignal: true, isRequired: false, transformFunction: null }, idScopeEntries: { classPropertyName: "idScopeEntries", publicName: "idScopeEntries", isSignal: true, isRequired: false, transformFunction: null }, idTagEntries: { classPropertyName: "idTagEntries", publicName: "idTagEntries", isSignal: true, isRequired: false, transformFunction: null }, assTagEntries: { classPropertyName: "assTagEntries", publicName: "assTagEntries", isSignal: true, isRequired: false, transformFunction: null }, refTypeEntries: { classPropertyName: "refTypeEntries", publicName: "refTypeEntries", isSignal: true, isRequired: false, transformFunction: null }, refTagEntries: { classPropertyName: "refTagEntries", publicName: "refTagEntries", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { ids: "idsChange" }, ngImport: i0, template: "<form [formGroup]=\"form\">\r\n <div>\r\n <button type=\"button\" mat-flat-button class=\"mat-primary\" (click)=\"addId()\">\r\n <mat-icon>add_circle</mat-icon> ID\r\n </button>\r\n </div>\r\n @if (entries.value.length) {\r\n <table>\r\n <thead>\r\n <tr>\r\n <th></th>\r\n <th>scope</th>\r\n <th>value</th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for ( entry of entries.value; track entry; let i = $index; let first =\r\n $first; let last = $last) {\r\n <tr [class.selected]=\"entry === edited\">\r\n <td class=\"fit-width\">\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Edit this ID\"\r\n (click)=\"editId(entry, i)\"\r\n >\r\n <mat-icon class=\"mat-primary\">edit</mat-icon>\r\n </button>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Move this ID up\"\r\n [disabled]=\"first\"\r\n (click)=\"moveIdUp(i)\"\r\n >\r\n <mat-icon>arrow_upward</mat-icon>\r\n </button>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Move this ID down\"\r\n [disabled]=\"last\"\r\n (click)=\"moveIdDown(i)\"\r\n >\r\n <mat-icon>arrow_downward</mat-icon>\r\n </button>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Delete this ID\"\r\n (click)=\"deleteId(i)\"\r\n >\r\n <mat-icon class=\"mat-warn\">remove_circle</mat-icon>\r\n </button>\r\n </td>\r\n <td>{{ entry.scope }}</td>\r\n <td>{{ entry.value }}</td>\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n }\r\n\r\n <mat-expansion-panel [expanded]=\"edited\" [disabled]=\"!edited\">\r\n <mat-expansion-panel-header\r\n >ID {{ edited?.value }}</mat-expansion-panel-header\r\n >\r\n <cadmus-refs-asserted-id\r\n [idScopeEntries]=\"idScopeEntries()\"\r\n [idTagEntries]=\"idTagEntries()\"\r\n [assTagEntries]=\"assTagEntries()\"\r\n [refTypeEntries]=\"refTypeEntries()\"\r\n [refTagEntries]=\"refTagEntries()\"\r\n [hasSubmit]=\"true\"\r\n [id]=\"edited\"\r\n (idChange)=\"onIdChange($event)\"\r\n (editorClose)=\"closeId()\"\r\n />\r\n </mat-expansion-panel>\r\n</form>\r\n", styles: ["table{width:100%;border-collapse:collapse}tbody tr:nth-child(odd){background-color:#e2e2e2}th{text-align:left;font-weight:400;color:silver}td.fit-width{width:1px;white-space:nowrap}tr.selected{background-color:#d0d0d0!important}fieldset{border:1px solid silver;border-radius:6px;padding:6px}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type:
1479
+ // material
1480
+ MatButtonModule }, { kind: "component", type: i3.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i3.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "component", type: i4$1.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i4$1.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i7.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i14.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type:
1481
+ // bricks
1482
+ AssertedIdComponent, selector: "cadmus-refs-asserted-id", inputs: ["idScopeEntries", "idTagEntries", "assTagEntries", "refTypeEntries", "refTagEntries", "id", "noEidLookup", "hasSubmit"], outputs: ["idChange", "editorClose"] }] });
1442
1483
  }
1443
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: AssertedCompositeIdsComponent, decorators: [{
1484
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: AssertedIdsComponent, decorators: [{
1444
1485
  type: Component,
1445
- args: [{ selector: 'cadmus-refs-asserted-composite-ids', imports: [
1486
+ args: [{ selector: 'cadmus-refs-asserted-ids', imports: [
1446
1487
  FormsModule,
1447
1488
  ReactiveFormsModule,
1489
+ // material
1448
1490
  MatButtonModule,
1449
- MatCheckboxModule,
1450
1491
  MatExpansionModule,
1451
- MatFormFieldModule,
1452
1492
  MatIconModule,
1453
- MatInputModule,
1454
- AssertedCompositeIdComponent,
1455
- ], template: "<form [formGroup]=\"form\">\r\n <!-- buttons -->\r\n <button type=\"button\" class=\"mat-primary\" mat-flat-button (click)=\"addId()\">\r\n <mat-icon>add_circle</mat-icon> ID\r\n </button>\r\n <!-- list -->\r\n @if (entries.value.length) {\r\n <table>\r\n <thead>\r\n <tr>\r\n <th></th>\r\n <th>scope</th>\r\n <th>label</th>\r\n <th>gid</th>\r\n <th>ass.</th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for ( entry of entries.value; track entry; let i = $index; let first =\r\n $first; let last = $last) {\r\n <tr [class.selected]=\"entry === edited\">\r\n <td class=\"fit-width\">\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Edit this ID\"\r\n (click)=\"editId(entry, i)\"\r\n >\r\n <mat-icon class=\"mat-primary\">edit</mat-icon>\r\n </button>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Move this ID up\"\r\n [disabled]=\"first\"\r\n (click)=\"moveIdUp(i)\"\r\n >\r\n <mat-icon>arrow_upward</mat-icon>\r\n </button>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Move this ID down\"\r\n [disabled]=\"last\"\r\n (click)=\"moveIdDown(i)\"\r\n >\r\n <mat-icon>arrow_downward</mat-icon>\r\n </button>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Delete this ID\"\r\n (click)=\"deleteId(i)\"\r\n >\r\n <mat-icon class=\"mat-warn\">remove_circle</mat-icon>\r\n </button>\r\n </td>\r\n <td>{{ entry.scope }}</td>\r\n <td>{{ entry?.target?.label }}</td>\r\n <td>{{ entry?.target?.gid }}</td>\r\n <td>{{ entry?.assertion ? \"Y\" : \"N\" }}</td>\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n }\r\n\r\n <!-- editor -->\r\n <mat-expansion-panel [expanded]=\"edited\" [disabled]=\"!edited\">\r\n <mat-expansion-panel-header\r\n >ID {{ edited?.target?.label }}</mat-expansion-panel-header\r\n >\r\n <cadmus-refs-asserted-composite-id\r\n [idScopeEntries]=\"idScopeEntries()\"\r\n [idTagEntries]=\"idTagEntries()\"\r\n [assTagEntries]=\"assTagEntries()\"\r\n [refTypeEntries]=\"refTypeEntries()\"\r\n [refTagEntries]=\"refTagEntries()\"\r\n [hasSubmit]=\"true\"\r\n [pinByTypeMode]=\"pinByTypeMode()\"\r\n [canSwitchMode]=\"canSwitchMode()\"\r\n [canEditTarget]=\"canEditTarget()\"\r\n [lookupDefinitions]=\"lookupDefinitions()\"\r\n [defaultPartTypeKey]=\"defaultPartTypeKey()\"\r\n [internalDefault]=\"internalDefault()\"\r\n [id]=\"edited\"\r\n (idChange)=\"onIdChange($event)\"\r\n (editorClose)=\"closeId()\"\r\n />\r\n </mat-expansion-panel>\r\n</form>\r\n", styles: ["table{width:100%;border-collapse:collapse}tbody tr:nth-child(odd){background-color:#e2e2e2}th{text-align:left;font-weight:400;color:silver}td.fit-width{width:1px;white-space:nowrap}tr.selected{background-color:#d0d0d0!important}fieldset{border:1px solid silver;border-radius:6px;padding:6px}\n"] }]
1456
- }], ctorParameters: () => [{ type: i1$1.FormBuilder }, { type: i2.DialogService }], propDecorators: { ids: [{
1457
- type: Input
1458
- }] } });
1493
+ MatTooltipModule,
1494
+ // bricks
1495
+ AssertedIdComponent
1496
+ ], template: "<form [formGroup]=\"form\">\r\n <div>\r\n <button type=\"button\" mat-flat-button class=\"mat-primary\" (click)=\"addId()\">\r\n <mat-icon>add_circle</mat-icon> ID\r\n </button>\r\n </div>\r\n @if (entries.value.length) {\r\n <table>\r\n <thead>\r\n <tr>\r\n <th></th>\r\n <th>scope</th>\r\n <th>value</th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for ( entry of entries.value; track entry; let i = $index; let first =\r\n $first; let last = $last) {\r\n <tr [class.selected]=\"entry === edited\">\r\n <td class=\"fit-width\">\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Edit this ID\"\r\n (click)=\"editId(entry, i)\"\r\n >\r\n <mat-icon class=\"mat-primary\">edit</mat-icon>\r\n </button>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Move this ID up\"\r\n [disabled]=\"first\"\r\n (click)=\"moveIdUp(i)\"\r\n >\r\n <mat-icon>arrow_upward</mat-icon>\r\n </button>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Move this ID down\"\r\n [disabled]=\"last\"\r\n (click)=\"moveIdDown(i)\"\r\n >\r\n <mat-icon>arrow_downward</mat-icon>\r\n </button>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Delete this ID\"\r\n (click)=\"deleteId(i)\"\r\n >\r\n <mat-icon class=\"mat-warn\">remove_circle</mat-icon>\r\n </button>\r\n </td>\r\n <td>{{ entry.scope }}</td>\r\n <td>{{ entry.value }}</td>\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n }\r\n\r\n <mat-expansion-panel [expanded]=\"edited\" [disabled]=\"!edited\">\r\n <mat-expansion-panel-header\r\n >ID {{ edited?.value }}</mat-expansion-panel-header\r\n >\r\n <cadmus-refs-asserted-id\r\n [idScopeEntries]=\"idScopeEntries()\"\r\n [idTagEntries]=\"idTagEntries()\"\r\n [assTagEntries]=\"assTagEntries()\"\r\n [refTypeEntries]=\"refTypeEntries()\"\r\n [refTagEntries]=\"refTagEntries()\"\r\n [hasSubmit]=\"true\"\r\n [id]=\"edited\"\r\n (idChange)=\"onIdChange($event)\"\r\n (editorClose)=\"closeId()\"\r\n />\r\n </mat-expansion-panel>\r\n</form>\r\n", styles: ["table{width:100%;border-collapse:collapse}tbody tr:nth-child(odd){background-color:#e2e2e2}th{text-align:left;font-weight:400;color:silver}td.fit-width{width:1px;white-space:nowrap}tr.selected{background-color:#d0d0d0!important}fieldset{border:1px solid silver;border-radius:6px;padding:6px}\n"] }]
1497
+ }], ctorParameters: () => [{ type: i1$1.FormBuilder }, { type: i2.DialogService }] });
1459
1498
 
1460
1499
  /*
1461
1500
  * Public API Surface of cadmus-refs-asserted-ids