@myrmidon/cadmus-refs-asserted-ids 10.0.0 → 10.0.2

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 { RefLookupComponent, RefLookupSetComponent, LOOKUP_CONFIGS_KEY } from '@myrmidon/cadmus-refs-lookup';
22
+ import { map, of, distinctUntilChanged, debounceTime, forkJoin, take } from 'rxjs';
23
+ import * as i6 from '@angular/cdk/clipboard';
26
24
  import { ClipboardModule } from '@angular/cdk/clipboard';
27
- import * as i8$1 from '@angular/material/checkbox';
25
+ import * as i8 from '@angular/material/checkbox';
28
26
  import { MatCheckboxModule } from '@angular/material/checkbox';
29
27
  import * as i3$1 from '@myrmidon/ngx-tools';
30
28
  import { FlatLookupPipe } from '@myrmidon/ngx-tools';
31
- import * as i4$1 from '@angular/material/snack-bar';
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,537 @@ 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());
317
- });
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,
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
+ ]);
376
+ }
377
+ else {
378
+ this.label.setValidators([Validators.maxLength(300)]);
325
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('');
437
+ }
438
+ getTarget() {
439
+ if (this.external.value) {
440
+ return {
441
+ gid: this.gid.value || '',
442
+ label: this.label.value || '',
443
+ };
444
+ }
445
+ else {
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);
339
593
  }
340
- updateForm(value) {
341
- this._updatingForm = true;
342
- if (!value) {
343
- this.form.reset();
344
- }
345
- 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();
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
+ * An asserted composite ID editor. This allows the user to edit an asserted
664
+ * composite ID, which can be an external ID or a lookup ID.
401
665
  */
402
- class AssertedIdsComponent {
403
- _dialogService;
404
- _editedIndex;
405
- edited;
406
- /**
407
- * The asserted IDs.
408
- */
409
- ids = model([]);
666
+ class AssertedCompositeIdComponent {
667
+ lookupService;
668
+ lookupDefs;
669
+ _sub;
670
+ _updatingForm;
671
+ extLookupConfigs;
672
+ targetExpanded = false;
673
+ // form
674
+ target;
675
+ scope;
676
+ tag;
677
+ assertion;
678
+ form;
410
679
  // asserted-id-scopes
411
680
  idScopeEntries = input();
412
681
  // asserted-id-tags
@@ -415,682 +684,533 @@ class AssertedIdsComponent {
415
684
  assTagEntries = input();
416
685
  // doc-reference-types
417
686
  refTypeEntries = input();
418
- // doc-reference-tags
419
- 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;
687
+ // doc-reference-tags
688
+ refTagEntries = input();
580
689
  /**
581
- * True when the by-type pin lookup mode is active.
582
- * User can change mode unless modeSwitching is false.
690
+ * The ID being edited.
583
691
  */
584
- pinByTypeMode = model();
692
+ id = model();
585
693
  /**
586
- * True when the user can switch between by-type and by-item mode.
694
+ * True if when a new ID is set it should be internal rather than
695
+ * external by default.
587
696
  */
588
- canSwitchMode = model();
697
+ internalDefault = input();
589
698
  /**
590
- * True when the user can edit the target's gid/label for internal
591
- * targets.
699
+ * True if the UI has a submit button.
592
700
  */
593
- canEditTarget = input();
701
+ hasSubmit = input();
594
702
  /**
595
- * The lookup definitions to be used for the by-type lookup. If
596
- * not specified, the lookup definitions will be got via injection
597
- * when available; if the injected definitions are empty, the
598
- * lookup definitions will be built from the model-types thesaurus;
599
- * if this is not available either, the by-type lookup will be
600
- * disabled.
703
+ * True when the internal UI preselected mode should be by type rather than
704
+ * by item. User can change mode unless modeSwitching is false.
601
705
  */
602
- lookupDefinitions = model();
706
+ pinByTypeMode = input();
603
707
  /**
604
- * The optional configurations for using external lookup services.
708
+ * True when the user can switch between by-type and by-item mode in
709
+ * the internal UI.
605
710
  */
606
- extLookupConfigs = input([]);
711
+ canSwitchMode = input();
607
712
  /**
608
- * True if when a new target is set it should be internal rather than
609
- * external by default.
713
+ * True when the user can edit the target's gid/label for internal targets.
610
714
  */
611
- internalDefault = input();
715
+ canEditTarget = input();
612
716
  /**
613
- * The target to be edited.
717
+ * The lookup definitions to be used for the by-type lookup in the internal UI.
718
+ * If not specified, the lookup definitions will be got via injection
719
+ * when available; if the injected definitions are empty, the
720
+ * lookup definitions will be built from the model-types thesaurus;
721
+ * if this is not available either, the by-type lookup will be
722
+ * disabled.
614
723
  */
615
- target = model();
724
+ lookupDefinitions = input();
616
725
  /**
617
- * The default value for part type key when the by-type mode is active.
726
+ * The default part type key to be used.
618
727
  */
619
728
  defaultPartTypeKey = input();
620
729
  /**
621
- * Emitted when user closes the editor.
730
+ * Emitted whenever the user requests to close the editor.
622
731
  */
623
732
  editorClose = output();
624
733
  /**
625
- * Emitted when the user requests more items from an external lookup.
734
+ * Emitted when the user requests more.
626
735
  */
627
736
  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
- };
737
+ constructor(formBuilder, lookupService, lookupDefs, settings) {
738
+ this.lookupService = lookupService;
739
+ this.lookupDefs = lookupDefs;
667
740
  // 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 });
741
+ this.target = formBuilder.control(null, Validators.required);
742
+ this.scope = formBuilder.control(null, Validators.maxLength(500));
743
+ this.tag = formBuilder.control(null, Validators.maxLength(50));
744
+ this.assertion = formBuilder.control(null);
681
745
  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
- }
746
+ target: this.target,
747
+ scope: this.scope,
748
+ tag: this.tag,
749
+ assertion: this.assertion,
701
750
  });
702
- // when target changes, update form
751
+ // external lookup configs
752
+ this.extLookupConfigs =
753
+ settings.retrieve(LOOKUP_CONFIGS_KEY) || [];
754
+ // when id changes, update form
703
755
  effect(() => {
704
- if (this._noFormUpdate) {
705
- this._noFormUpdate = false;
706
- return;
707
- }
708
- console.log('target changed', this.target());
709
- this.updateForm(this.target());
756
+ this.updateForm(this.id());
710
757
  });
711
758
  }
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
759
  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)]);
760
+ this._sub = this.form.valueChanges
761
+ .pipe(debounceTime$1(300))
762
+ .subscribe((_) => {
763
+ if (!this._updatingForm) {
764
+ this.emitIdChange();
800
765
  }
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
766
  });
818
767
  }
819
768
  ngOnDestroy() {
820
- for (let i = 0; i < this._subs.length; i++) {
821
- this._subs[i].unsubscribe();
769
+ this._sub?.unsubscribe();
770
+ }
771
+ onAssertionChange(assertion) {
772
+ this.assertion.setValue(assertion || null);
773
+ }
774
+ onTargetChange(target) {
775
+ this.target.setValue(target);
776
+ this.target.markAsDirty();
777
+ this.target.updateValueAndValidity();
778
+ if (this.form.valid) {
779
+ this.targetExpanded = false;
822
780
  }
823
781
  }
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;
782
+ updateForm(id) {
783
+ this._updatingForm = true;
784
+ if (!id) {
785
+ this.form.reset();
830
786
  }
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;
787
+ else {
788
+ this.target.setValue(id.target);
789
+ this.scope.setValue(id.scope || null);
790
+ this.tag.setValue(id.tag || null);
791
+ this.assertion.setValue(id.assertion || null);
792
+ this.form.markAsPristine();
838
793
  }
839
- const sb = [];
840
- // pin value
841
- if (this.lookupData.pin.value) {
842
- sb.push(this.lookupData.pin.value);
843
- sb.push(' | ');
794
+ this._updatingForm = false;
795
+ }
796
+ getId() {
797
+ const external = !this.target.value?.name;
798
+ const target = this.target.value;
799
+ return {
800
+ target: external
801
+ ? {
802
+ gid: target?.gid || '',
803
+ label: target?.label || target?.gid || '',
804
+ }
805
+ : target,
806
+ scope: this.scope.value?.trim() || '',
807
+ tag: this.tag.value?.trim(),
808
+ assertion: this.assertion.value || undefined,
809
+ };
810
+ }
811
+ emitIdChange() {
812
+ if (!this.hasSubmit()) {
813
+ this.id.set(this.getId());
844
814
  }
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(')');
815
+ }
816
+ onEditorClose() {
817
+ this.targetExpanded = false;
818
+ }
819
+ onExtMoreRequest(event) {
820
+ this.extMoreRequest.emit(event);
821
+ }
822
+ onExtLookupConfigChange(config) {
823
+ if (!this.scope.value ||
824
+ this.extLookupConfigs.some((c) => c.name === this.scope.value)) {
825
+ this.scope.setValue(config.name || null);
826
+ this.scope.markAsDirty();
827
+ this.scope.updateValueAndValidity();
856
828
  }
857
- return sb.join('');
858
829
  }
859
- getTarget() {
860
- if (this.external.value) {
861
- return {
862
- gid: this.gid.value || '',
863
- label: this.label.value || '',
864
- };
830
+ cancel() {
831
+ this.editorClose.emit();
832
+ }
833
+ save() {
834
+ if (this.form.valid) {
835
+ this.id.set(this.getId());
865
836
  }
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
- };
837
+ }
838
+ 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 });
839
+ 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:
840
+ // material
841
+ 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:
842
+ // bricks
843
+ AssertionComponent, selector: "cadmus-refs-assertion", inputs: ["assTagEntries", "refTypeEntries", "refTagEntries", "assertion"], outputs: ["assertionChange"] }, { kind: "component", type:
844
+ // local
845
+ PinTargetLookupComponent, selector: "cadmus-pin-target-lookup", inputs: ["pinByTypeMode", "canSwitchMode", "canEditTarget", "lookupDefinitions", "extLookupConfigs", "internalDefault", "target", "defaultPartTypeKey"], outputs: ["pinByTypeModeChange", "canSwitchModeChange", "lookupDefinitionsChange", "targetChange", "editorClose", "extMoreRequest", "extLookupConfigChange"] }] });
846
+ }
847
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: AssertedCompositeIdComponent, decorators: [{
848
+ type: Component,
849
+ args: [{ selector: 'cadmus-refs-asserted-composite-id', imports: [
850
+ ReactiveFormsModule,
851
+ // material
852
+ MatButtonModule,
853
+ MatExpansionModule,
854
+ MatFormFieldModule,
855
+ MatIconModule,
856
+ MatInputModule,
857
+ MatSelectModule,
858
+ MatTooltipModule,
859
+ // bricks
860
+ AssertionComponent,
861
+ // local
862
+ PinTargetLookupComponent,
863
+ ], 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"] }]
864
+ }], ctorParameters: () => [{ type: i1$1.FormBuilder }, { type: PinRefLookupService }, { type: undefined, decorators: [{
865
+ type: Inject,
866
+ args: ['indexLookupDefinitions']
867
+ }] }, { type: i3$1.RamStorageService }] });
868
+
869
+ /**
870
+ * Asserted composite IDs editor.
871
+ */
872
+ class AssertedCompositeIdsComponent {
873
+ _dialogService;
874
+ _ids;
875
+ _editedIndex;
876
+ edited;
877
+ /**
878
+ * The asserted IDs.
879
+ */
880
+ get ids() {
881
+ return this._ids;
882
+ }
883
+ set ids(value) {
884
+ if (this._ids !== value) {
885
+ this._ids = value || [];
886
+ this.updateForm(value);
878
887
  }
879
888
  }
880
- emitChange() {
881
- this._noFormUpdate = true;
882
- this.target.set(this.getTarget());
889
+ // asserted-id-scopes
890
+ idScopeEntries = input();
891
+ // asserted-id-tags
892
+ idTagEntries = input();
893
+ // assertion-tags
894
+ assTagEntries = input();
895
+ // doc-reference-types
896
+ refTypeEntries = input();
897
+ // doc-reference-tags
898
+ refTagEntries = input();
899
+ /**
900
+ * True when the internal UI preselected mode should be by type rather than
901
+ * by item. User can change mode unless modeSwitching is false.
902
+ */
903
+ pinByTypeMode = input();
904
+ /**
905
+ * True when the user can switch between by-type and by-item mode in
906
+ * the internal UI.
907
+ */
908
+ canSwitchMode = input();
909
+ /**
910
+ * True when the user can edit the target's gid/label for internal targets.
911
+ */
912
+ canEditTarget = input();
913
+ /**
914
+ * The lookup definitions to be used for the by-type lookup in the internal UI.
915
+ * If not specified, the lookup definitions will be got via injection
916
+ * when available; if the injected definitions are empty, the
917
+ * lookup definitions will be built from the model-types thesaurus;
918
+ * if this is not available either, the by-type lookup will be
919
+ * disabled.
920
+ */
921
+ lookupDefinitions = input();
922
+ /**
923
+ * The default part type key.
924
+ */
925
+ defaultPartTypeKey = input();
926
+ /**
927
+ * True if when a new ID is set it should be internal rather than
928
+ * external by default.
929
+ */
930
+ internalDefault = input();
931
+ /**
932
+ * Emitted whenever any ID changes.
933
+ */
934
+ idsChange = output();
935
+ entries;
936
+ form;
937
+ constructor(formBuilder, _dialogService) {
938
+ this._dialogService = _dialogService;
939
+ this._ids = [];
940
+ this._editedIndex = -1;
941
+ this.entries = formBuilder.control([], { nonNullable: true });
942
+ // form
943
+ this.form = formBuilder.group({
944
+ ids: this.entries,
945
+ });
883
946
  }
884
- updateTarget(noEmit = false) {
885
- if (this._noTargetUpdate) {
947
+ updateForm(ids) {
948
+ if (!ids?.length) {
949
+ this.form.reset();
886
950
  return;
887
951
  }
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();
952
+ this.entries.setValue(ids, { emitEvent: false });
953
+ this.entries.updateValueAndValidity();
954
+ this.form.markAsPristine();
955
+ }
956
+ emitIdsChange() {
957
+ this.idsChange.emit(this.entries.value);
958
+ }
959
+ addId() {
960
+ this.editId({
961
+ target: { gid: '', label: '' },
962
+ }, -1);
963
+ }
964
+ editId(id, index) {
965
+ this._editedIndex = index;
966
+ this.edited = id;
967
+ }
968
+ closeId() {
969
+ this._editedIndex = -1;
970
+ this.edited = undefined;
971
+ }
972
+ saveId(entry) {
973
+ const entries = [...this.entries.value];
974
+ if (this._editedIndex === -1) {
975
+ entries.push(entry);
895
976
  }
896
- if (!noEmit) {
897
- this.emitChange();
977
+ else {
978
+ entries.splice(this._editedIndex, 1, entry);
898
979
  }
980
+ this.entries.setValue(entries);
981
+ this.entries.markAsDirty();
982
+ this.entries.updateValueAndValidity();
983
+ this.closeId();
984
+ }
985
+ deleteId(index) {
986
+ this._dialogService
987
+ .confirm('Confirmation', 'Delete ID?')
988
+ .pipe(take(1))
989
+ .subscribe((yes) => {
990
+ if (yes) {
991
+ if (this._editedIndex === index) {
992
+ this.closeId();
993
+ }
994
+ const entries = [...this.entries.value];
995
+ entries.splice(index, 1);
996
+ this.entries.setValue(entries);
997
+ this.entries.markAsDirty();
998
+ this.entries.updateValueAndValidity();
999
+ this.emitIdsChange();
1000
+ }
1001
+ });
899
1002
  }
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();
1003
+ moveIdUp(index) {
1004
+ if (index < 1) {
908
1005
  return;
909
1006
  }
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();
1007
+ const entry = this.entries.value[index];
1008
+ const entries = [...this.entries.value];
1009
+ entries.splice(index, 1);
1010
+ entries.splice(index - 1, 0, entry);
1011
+ this.entries.setValue(entries);
1012
+ this.entries.markAsDirty();
1013
+ this.entries.updateValueAndValidity();
1014
+ this.emitIdsChange();
1015
+ }
1016
+ moveIdDown(index) {
1017
+ if (index + 1 >= this.entries.value.length) {
1018
+ return;
948
1019
  }
1020
+ const entry = this.entries.value[index];
1021
+ const entries = [...this.entries.value];
1022
+ entries.splice(index, 1);
1023
+ entries.splice(index + 1, 0, entry);
1024
+ this.entries.setValue(entries);
1025
+ this.entries.markAsDirty();
1026
+ this.entries.updateValueAndValidity();
1027
+ this.emitIdsChange();
1028
+ }
1029
+ onIdChange(id) {
1030
+ this.saveId(id);
1031
+ this.emitIdsChange();
949
1032
  }
1033
+ 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 });
1034
+ 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"] }] });
1035
+ }
1036
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: AssertedCompositeIdsComponent, decorators: [{
1037
+ type: Component,
1038
+ args: [{ selector: 'cadmus-refs-asserted-composite-ids', imports: [
1039
+ FormsModule,
1040
+ ReactiveFormsModule,
1041
+ MatButtonModule,
1042
+ MatCheckboxModule,
1043
+ MatExpansionModule,
1044
+ MatFormFieldModule,
1045
+ MatIconModule,
1046
+ MatInputModule,
1047
+ AssertedCompositeIdComponent,
1048
+ ], 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"] }]
1049
+ }], ctorParameters: () => [{ type: i1$1.FormBuilder }, { type: i2.DialogService }], propDecorators: { ids: [{
1050
+ type: Input
1051
+ }] } });
1052
+
1053
+ // from Cadmus general parts
1054
+ const METADATA_PART_ID = 'it.vedph.metadata';
1055
+ /*
1056
+ * Scoped pin-based lookup component. This component provides a list
1057
+ * of pin-based searches, with a lookup control. Whenever the user
1058
+ * picks a pin value, he gets the details about its item and part, and
1059
+ * item's metadata part, if any. He can then use these data to build
1060
+ * some EID by variously assembling these components.
1061
+ */
1062
+ class ScopedPinLookupComponent {
1063
+ _itemService;
1064
+ lookupService;
1065
+ lookupDefs;
1066
+ // lookup
1067
+ key;
1068
+ keyForm;
1069
+ keys;
1070
+ info;
1071
+ // builder
1072
+ id;
1073
+ idForm;
950
1074
  /**
951
- * Called when the item lookup changes (item is looked up
952
- * by its title).
953
- *
954
- * @param item The item got from lookup.
1075
+ * Emitted whenever the user picks an ID.
955
1076
  */
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
- },
1077
+ idPick = output();
1078
+ constructor(formBuilder, _itemService, lookupService, lookupDefs) {
1079
+ this._itemService = _itemService;
1080
+ this.lookupService = lookupService;
1081
+ this.lookupDefs = lookupDefs;
1082
+ // lookup
1083
+ // keys are all the defined lookup searches
1084
+ this.keys = Object.keys(lookupDefs);
1085
+ // the selected key defines the lookup scope
1086
+ this.key = formBuilder.control(null);
1087
+ this.keyForm = formBuilder.group({
1088
+ key: this.key,
1089
+ });
1090
+ // id
1091
+ this.id = formBuilder.control(null, [
1092
+ Validators.required,
1093
+ Validators.maxLength(300),
1094
+ ]);
1095
+ this.idForm = formBuilder.group({
1096
+ id: this.id,
975
1097
  });
976
1098
  }
977
- loadItemInfo(pin) {
978
- if (!pin) {
979
- return;
1099
+ ngOnInit() {
1100
+ // pre-select a unique key
1101
+ if (this.keys.length === 1) {
1102
+ this.key.setValue(this.keys[0]);
1103
+ this.key.markAsDirty();
1104
+ this.key.updateValueAndValidity();
980
1105
  }
1106
+ }
1107
+ onItemChange(item) {
1108
+ const info = {
1109
+ pin: item,
1110
+ };
1111
+ // lookup item and its metadata part if any
981
1112
  forkJoin({
982
- item: this._itemService.getItem(pin.itemId, false, true),
983
- part: this._itemService.getPartFromTypeAndRole(pin.itemId, METADATA_PART_ID, undefined, true),
1113
+ item: item
1114
+ ? this._itemService.getItem(item.itemId, false, true)
1115
+ : of(null),
1116
+ part: item
1117
+ ? this._itemService.getPartFromTypeAndRole(item.itemId, METADATA_PART_ID, undefined, true)
1118
+ : of(null),
984
1119
  })
985
1120
  .pipe(take(1))
986
1121
  .subscribe({
987
1122
  next: (result) => {
988
- this.lookupData = {
989
- pin: pin,
990
- item: result.item,
991
- metaPart: result.part,
992
- };
993
- this.updateTarget(true);
1123
+ if (result.item) {
1124
+ info.item = result.item;
1125
+ info.part = result.part;
1126
+ this.info = info;
1127
+ }
994
1128
  },
995
1129
  error: (error) => {
996
- this.lookupData = undefined;
997
- console.error('Error loading item/metadata', error);
1130
+ console.error(error ? JSON.stringify(error) : 'Error loading item/metadata');
998
1131
  },
999
1132
  });
1000
1133
  }
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
- });
1023
- }
1024
- }
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();
1134
+ appendIdComponent(type, metaIndex = -1) {
1135
+ let id = this.id.value || '';
1136
+ switch (type) {
1137
+ case 'pin':
1138
+ id += this.info?.pin.value;
1139
+ break;
1140
+ case 'itemId':
1141
+ id += this.info.item?.id || '';
1142
+ break;
1143
+ case 'partId':
1144
+ id += this.info.part?.id || '';
1145
+ break;
1146
+ case 'partTypeId':
1147
+ id += this.info.part?.typeId || '';
1148
+ break;
1149
+ case 'partRoleId':
1150
+ id += this.info.part?.roleId || '';
1151
+ break;
1152
+ case 'metadata':
1153
+ id += this.info.part.metadata[metaIndex].value;
1154
+ break;
1155
+ }
1156
+ this.id.setValue(id);
1157
+ this.id.markAsDirty();
1158
+ this.id.updateValueAndValidity();
1038
1159
  }
1039
- save() {
1040
- if (this.form.invalid) {
1160
+ pickId() {
1161
+ if (this.idForm.invalid) {
1041
1162
  return;
1042
1163
  }
1043
- this.target.set(this.getTarget());
1044
- this.emitChange();
1164
+ this.idPick.emit(this.id.value);
1165
+ this.info = undefined;
1166
+ }
1167
+ resetId() {
1168
+ this.id.reset();
1169
+ this.id.markAsDirty();
1170
+ this.id.updateValueAndValidity();
1045
1171
  }
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" }] });
1172
+ 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 });
1173
+ 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:
1174
+ // material
1175
+ 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:
1176
+ // bricks
1177
+ RefLookupComponent, selector: "cadmus-ref-lookup", inputs: ["label", "limit", "baseFilter", "service", "item", "required", "hasMore", "linkTemplate", "optDialog", "options"], outputs: ["itemChange", "optionsChange", "moreRequest"] }] });
1048
1178
  }
1049
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: PinTargetLookupComponent, decorators: [{
1179
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: ScopedPinLookupComponent, decorators: [{
1050
1180
  type: Component,
1051
- args: [{ selector: 'cadmus-pin-target-lookup', imports: [
1181
+ args: [{ selector: 'cadmus-scoped-pin-lookup', imports: [
1052
1182
  FormsModule,
1053
1183
  ReactiveFormsModule,
1054
- ClipboardModule,
1184
+ // material
1055
1185
  MatButtonModule,
1056
- MatCheckboxModule,
1057
1186
  MatExpansionModule,
1058
1187
  MatFormFieldModule,
1059
1188
  MatIconModule,
1060
1189
  MatInputModule,
1061
1190
  MatSelectModule,
1191
+ // bricks
1062
1192
  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: [{
1193
+ ], 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"] }]
1194
+ }], ctorParameters: () => [{ type: i1$1.FormBuilder }, { type: i1.ItemService }, { type: PinRefLookupService }, { type: undefined, decorators: [{
1067
1195
  type: Inject,
1068
1196
  args: ['indexLookupDefinitions']
1069
- }] }, { type: ItemRefLookupService }, { type: PinRefLookupService }, { type: i1.ItemService }, { type: i1.ThesaurusService }, { type: i4$1.MatSnackBar }, { type: i1$1.FormBuilder }] });
1197
+ }] }] });
1070
1198
 
1071
1199
  /**
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.
1200
+ * Asserted ID editor component.
1080
1201
  */
1081
- class AssertedCompositeIdComponent {
1202
+ class AssertedIdComponent {
1082
1203
  lookupService;
1083
1204
  lookupDefs;
1084
1205
  _sub;
1085
1206
  _updatingForm;
1086
- extLookupConfigs;
1087
- targetExpanded = false;
1088
- // form
1089
- target;
1090
- scope;
1091
1207
  tag;
1208
+ value;
1209
+ label;
1210
+ scope;
1092
1211
  assertion;
1093
1212
  form;
1213
+ lookupExpanded;
1094
1214
  // asserted-id-scopes
1095
1215
  idScopeEntries = input();
1096
1216
  // asserted-id-tags
@@ -1102,71 +1222,40 @@ class AssertedCompositeIdComponent {
1102
1222
  // doc-reference-tags
1103
1223
  refTagEntries = input();
1104
1224
  /**
1105
- * The ID being edited.
1225
+ * The asserted ID being edited.
1106
1226
  */
1107
1227
  id = model();
1108
1228
  /**
1109
- * True if when a new ID is set it should be internal rather than
1110
- * external by default.
1229
+ * True to hide the pin-based EID lookup UI.
1111
1230
  */
1112
- internalDefault = input();
1231
+ noEidLookup = input();
1113
1232
  /**
1114
- * True if the UI has a submit button.
1233
+ * True to show the submit button.
1115
1234
  */
1116
1235
  hasSubmit = input();
1117
1236
  /**
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.
1237
+ * Emitted when the editor is closed.
1146
1238
  */
1147
1239
  editorClose = output();
1148
- /**
1149
- * Emitted when the user requests more.
1150
- */
1151
- extMoreRequest = output();
1152
- constructor(formBuilder, lookupService, lookupDefs, settings) {
1240
+ constructor(formBuilder, lookupService, lookupDefs) {
1153
1241
  this.lookupService = lookupService;
1154
1242
  this.lookupDefs = lookupDefs;
1155
- // form
1156
- this.target = formBuilder.control(null, Validators.required);
1157
- this.scope = formBuilder.control(null, Validators.maxLength(500));
1158
1243
  this.tag = formBuilder.control(null, Validators.maxLength(50));
1244
+ this.value = formBuilder.control(null, [
1245
+ Validators.required,
1246
+ Validators.maxLength(500),
1247
+ ]);
1248
+ this.label = formBuilder.control(null, Validators.maxLength(500));
1249
+ this.scope = formBuilder.control(null, Validators.maxLength(500));
1159
1250
  this.assertion = formBuilder.control(null);
1160
1251
  this.form = formBuilder.group({
1161
- target: this.target,
1162
- scope: this.scope,
1163
1252
  tag: this.tag,
1253
+ value: this.value,
1254
+ label: this.label,
1255
+ scope: this.scope,
1164
1256
  assertion: this.assertion,
1165
1257
  });
1166
- // external lookup configs
1167
- this.extLookupConfigs =
1168
- settings.retrieve(ASSERTED_COMPOSITE_ID_CONFIGS_KEY) ||
1169
- [];
1258
+ this.lookupExpanded = false;
1170
1259
  // when id changes, update form
1171
1260
  effect(() => {
1172
1261
  this.updateForm(this.id());
@@ -1174,7 +1263,7 @@ class AssertedCompositeIdComponent {
1174
1263
  }
1175
1264
  ngOnInit() {
1176
1265
  this._sub = this.form.valueChanges
1177
- .pipe(debounceTime(300))
1266
+ .pipe(debounceTime$1(300))
1178
1267
  .subscribe((_) => {
1179
1268
  if (!this._updatingForm) {
1180
1269
  this.emitIdChange();
@@ -1187,40 +1276,33 @@ class AssertedCompositeIdComponent {
1187
1276
  onAssertionChange(assertion) {
1188
1277
  this.assertion.setValue(assertion || null);
1189
1278
  }
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
- }
1279
+ onIdPick(id) {
1280
+ this.value.setValue(id);
1281
+ this.value.markAsDirty();
1282
+ this.value.updateValueAndValidity();
1283
+ this.lookupExpanded = false;
1197
1284
  }
1198
- updateForm(id) {
1285
+ updateForm(value) {
1199
1286
  this._updatingForm = true;
1200
- if (!id) {
1287
+ if (!value) {
1201
1288
  this.form.reset();
1202
1289
  }
1203
1290
  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);
1291
+ this.tag.setValue(value.tag || null);
1292
+ this.value.setValue(value.value);
1293
+ this.label.setValue(value.label || null);
1294
+ this.scope.setValue(value.scope);
1295
+ this.assertion.setValue(value.assertion || null);
1208
1296
  this.form.markAsPristine();
1209
1297
  }
1210
1298
  this._updatingForm = false;
1211
1299
  }
1212
1300
  getId() {
1213
- const external = !this.target.value?.name;
1214
- const target = this.target.value;
1215
1301
  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
1302
  tag: this.tag.value?.trim(),
1303
+ value: this.value.value?.trim() || '',
1304
+ label: this.label.value?.trim() || undefined,
1305
+ scope: this.scope.value?.trim() || '',
1224
1306
  assertion: this.assertion.value || undefined,
1225
1307
  };
1226
1308
  }
@@ -1229,20 +1311,6 @@ class AssertedCompositeIdComponent {
1229
1311
  this.id.set(this.getId());
1230
1312
  }
1231
1313
  }
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
1314
  cancel() {
1247
1315
  this.editorClose.emit();
1248
1316
  }
@@ -1251,48 +1319,45 @@ class AssertedCompositeIdComponent {
1251
1319
  this.id.set(this.getId());
1252
1320
  }
1253
1321
  }
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"] }] });
1322
+ 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 });
1323
+ 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:
1324
+ // material
1325
+ 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:
1326
+ // bricks
1327
+ AssertionComponent, selector: "cadmus-refs-assertion", inputs: ["assTagEntries", "refTypeEntries", "refTagEntries", "assertion"], outputs: ["assertionChange"] }, { kind: "component", type: ScopedPinLookupComponent, selector: "cadmus-scoped-pin-lookup", outputs: ["idPick"] }] });
1256
1328
  }
1257
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: AssertedCompositeIdComponent, decorators: [{
1329
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: AssertedIdComponent, decorators: [{
1258
1330
  type: Component,
1259
- args: [{ selector: 'cadmus-refs-asserted-composite-id', imports: [
1331
+ args: [{ selector: 'cadmus-refs-asserted-id', imports: [
1332
+ FormsModule,
1260
1333
  ReactiveFormsModule,
1334
+ // material
1261
1335
  MatButtonModule,
1262
1336
  MatExpansionModule,
1263
1337
  MatFormFieldModule,
1264
1338
  MatIconModule,
1265
1339
  MatInputModule,
1266
1340
  MatSelectModule,
1267
- MatTooltipModule,
1341
+ // bricks
1268
1342
  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"] }]
1343
+ ScopedPinLookupComponent,
1344
+ ], 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
1345
  }], ctorParameters: () => [{ type: i1$1.FormBuilder }, { type: PinRefLookupService }, { type: undefined, decorators: [{
1272
1346
  type: Inject,
1273
1347
  args: ['indexLookupDefinitions']
1274
- }] }, { type: i3$1.RamStorageService }] });
1348
+ }] }] });
1275
1349
 
1276
1350
  /**
1277
- * Asserted composite IDs editor.
1351
+ * Asserted IDs editor.
1278
1352
  */
1279
- class AssertedCompositeIdsComponent {
1353
+ class AssertedIdsComponent {
1280
1354
  _dialogService;
1281
- _ids;
1282
1355
  _editedIndex;
1283
1356
  edited;
1284
1357
  /**
1285
1358
  * The asserted IDs.
1286
1359
  */
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
- }
1360
+ ids = model([]);
1296
1361
  // asserted-id-scopes
1297
1362
  idScopeEntries = input();
1298
1363
  // asserted-id-tags
@@ -1303,53 +1368,20 @@ class AssertedCompositeIdsComponent {
1303
1368
  refTypeEntries = input();
1304
1369
  // doc-reference-tags
1305
1370
  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
1371
  entries;
1343
1372
  form;
1344
1373
  constructor(formBuilder, _dialogService) {
1345
1374
  this._dialogService = _dialogService;
1346
- this._ids = [];
1347
1375
  this._editedIndex = -1;
1348
1376
  this.entries = formBuilder.control([], { nonNullable: true });
1349
1377
  // form
1350
1378
  this.form = formBuilder.group({
1351
1379
  ids: this.entries,
1352
1380
  });
1381
+ // when ids change, update form
1382
+ effect(() => {
1383
+ this.updateForm(this.ids());
1384
+ });
1353
1385
  }
1354
1386
  updateForm(ids) {
1355
1387
  if (!ids?.length) {
@@ -1360,12 +1392,10 @@ class AssertedCompositeIdsComponent {
1360
1392
  this.entries.updateValueAndValidity();
1361
1393
  this.form.markAsPristine();
1362
1394
  }
1363
- emitIdsChange() {
1364
- this.idsChange.emit(this.entries.value);
1365
- }
1366
1395
  addId() {
1367
1396
  this.editId({
1368
- target: { gid: '', label: '' },
1397
+ scope: '',
1398
+ value: '',
1369
1399
  }, -1);
1370
1400
  }
1371
1401
  editId(id, index) {
@@ -1403,7 +1433,7 @@ class AssertedCompositeIdsComponent {
1403
1433
  this.entries.setValue(entries);
1404
1434
  this.entries.markAsDirty();
1405
1435
  this.entries.updateValueAndValidity();
1406
- this.emitIdsChange();
1436
+ this.ids.set(this.entries.value);
1407
1437
  }
1408
1438
  });
1409
1439
  }
@@ -1418,7 +1448,7 @@ class AssertedCompositeIdsComponent {
1418
1448
  this.entries.setValue(entries);
1419
1449
  this.entries.markAsDirty();
1420
1450
  this.entries.updateValueAndValidity();
1421
- this.emitIdsChange();
1451
+ this.ids.set(this.entries.value);
1422
1452
  }
1423
1453
  moveIdDown(index) {
1424
1454
  if (index + 1 >= this.entries.value.length) {
@@ -1431,31 +1461,33 @@ class AssertedCompositeIdsComponent {
1431
1461
  this.entries.setValue(entries);
1432
1462
  this.entries.markAsDirty();
1433
1463
  this.entries.updateValueAndValidity();
1434
- this.emitIdsChange();
1464
+ this.ids.set(this.entries.value);
1435
1465
  }
1436
1466
  onIdChange(id) {
1437
1467
  this.saveId(id);
1438
- this.emitIdsChange();
1468
+ this.ids.set(this.entries.value);
1439
1469
  }
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"] }] });
1470
+ 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 });
1471
+ 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:
1472
+ // material
1473
+ 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:
1474
+ // bricks
1475
+ AssertedIdComponent, selector: "cadmus-refs-asserted-id", inputs: ["idScopeEntries", "idTagEntries", "assTagEntries", "refTypeEntries", "refTagEntries", "id", "noEidLookup", "hasSubmit"], outputs: ["idChange", "editorClose"] }] });
1442
1476
  }
1443
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: AssertedCompositeIdsComponent, decorators: [{
1477
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: AssertedIdsComponent, decorators: [{
1444
1478
  type: Component,
1445
- args: [{ selector: 'cadmus-refs-asserted-composite-ids', imports: [
1479
+ args: [{ selector: 'cadmus-refs-asserted-ids', imports: [
1446
1480
  FormsModule,
1447
1481
  ReactiveFormsModule,
1482
+ // material
1448
1483
  MatButtonModule,
1449
- MatCheckboxModule,
1450
1484
  MatExpansionModule,
1451
- MatFormFieldModule,
1452
1485
  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
- }] } });
1486
+ MatTooltipModule,
1487
+ // bricks
1488
+ AssertedIdComponent
1489
+ ], 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"] }]
1490
+ }], ctorParameters: () => [{ type: i1$1.FormBuilder }, { type: i2.DialogService }] });
1459
1491
 
1460
1492
  /*
1461
1493
  * Public API Surface of cadmus-refs-asserted-ids
@@ -1465,5 +1497,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImpor
1465
1497
  * Generated bundle index. Do not edit.
1466
1498
  */
1467
1499
 
1468
- export { ASSERTED_COMPOSITE_ID_CONFIGS_KEY, AssertedCompositeIdComponent, AssertedCompositeIdsComponent, AssertedIdComponent, AssertedIdsComponent, ItemRefLookupService, PinRefLookupService, PinTargetLookupComponent, ScopedPinLookupComponent };
1500
+ export { AssertedCompositeIdComponent, AssertedCompositeIdsComponent, AssertedIdComponent, AssertedIdsComponent, ItemRefLookupService, PinRefLookupService, PinTargetLookupComponent, ScopedPinLookupComponent };
1469
1501
  //# sourceMappingURL=myrmidon-cadmus-refs-asserted-ids.mjs.map