@myrmidon/cadmus-ui 15.0.0 → 15.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/myrmidon-cadmus-ui.mjs +681 -277
- package/fesm2022/myrmidon-cadmus-ui.mjs.map +1 -1
- package/index.d.ts +203 -57
- package/package.json +2 -2
|
@@ -1,24 +1,35 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { input, output, Component, signal, effect, ViewChild, Injectable, Inject, model, computed,
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
2
|
+
import { input, output, Component, signal, effect, ViewChild, Injectable, Inject, inject, model, computed, untracked } from '@angular/core';
|
|
3
|
+
import * as i2$1 from '@angular/material/button';
|
|
4
|
+
import { MatButton, MatIconButton, MatButtonModule } from '@angular/material/button';
|
|
5
|
+
import * as i5 from '@angular/material/icon';
|
|
6
|
+
import { MatIcon, MatIconModule } from '@angular/material/icon';
|
|
5
7
|
import { SafeHtmlPipe, deepCopy } from '@myrmidon/ngx-tools';
|
|
6
8
|
import * as i1 from '@myrmidon/cadmus-core';
|
|
7
|
-
import
|
|
9
|
+
import * as i6 from '@angular/material/tooltip';
|
|
10
|
+
import { MatTooltip, MatTooltipModule } from '@angular/material/tooltip';
|
|
8
11
|
import * as i1$1 from '@angular/forms';
|
|
9
|
-
import { FormsModule, ReactiveFormsModule, PristineChangeEvent } from '@angular/forms';
|
|
10
|
-
import
|
|
12
|
+
import { FormsModule, ReactiveFormsModule, FormBuilder, FormControl, FormGroup, Validators, PristineChangeEvent } from '@angular/forms';
|
|
13
|
+
import * as i3 from '@angular/material/checkbox';
|
|
14
|
+
import { MatCheckbox, MatCheckboxModule } from '@angular/material/checkbox';
|
|
11
15
|
import * as i2 from '@myrmidon/ngx-mat-tools';
|
|
12
|
-
import { AsyncPipe
|
|
16
|
+
import { AsyncPipe } from '@angular/common';
|
|
13
17
|
import { of, BehaviorSubject, map as map$1, Subject } from 'rxjs';
|
|
14
18
|
import { debounceTime, distinctUntilChanged, switchMap, map, take } from 'rxjs/operators';
|
|
15
19
|
import { MatAutocomplete, MatAutocompleteTrigger } from '@angular/material/autocomplete';
|
|
16
20
|
import { MatOption } from '@angular/material/core';
|
|
17
|
-
import
|
|
18
|
-
import {
|
|
21
|
+
import * as i4 from '@angular/material/form-field';
|
|
22
|
+
import { MatFormField, MatFormFieldModule } from '@angular/material/form-field';
|
|
23
|
+
import * as i4$1 from '@angular/material/input';
|
|
24
|
+
import { MatInput, MatInputModule } from '@angular/material/input';
|
|
19
25
|
import * as i1$2 from '@myrmidon/cadmus-api';
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
26
|
+
import { moveItemInArray, CdkDropList, CdkDrag } from '@angular/cdk/drag-drop';
|
|
27
|
+
import { MatChipListbox, MatChipOption, MatChipRemove } from '@angular/material/chips';
|
|
28
|
+
import { MatExpansionPanel } from '@angular/material/expansion';
|
|
29
|
+
import { MatDialogRef, MAT_DIALOG_DATA, MatDialog } from '@angular/material/dialog';
|
|
30
|
+
import * as i7 from '@angular/material/progress-bar';
|
|
31
|
+
import { MatProgressBarModule } from '@angular/material/progress-bar';
|
|
32
|
+
import { PagedTreeStore, BrowserTreeNodeComponent } from '@myrmidon/paged-data-browsers';
|
|
22
33
|
import { AppRepository } from '@myrmidon/cadmus-state';
|
|
23
34
|
import * as i1$3 from '@myrmidon/auth-jwt-login';
|
|
24
35
|
|
|
@@ -29,10 +40,10 @@ class CloseSaveButtonsComponent {
|
|
|
29
40
|
close() {
|
|
30
41
|
this.closeRequest.emit();
|
|
31
42
|
}
|
|
32
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.
|
|
33
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.
|
|
43
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: CloseSaveButtonsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
44
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.3", type: CloseSaveButtonsComponent, isStandalone: true, selector: "cadmus-close-save-buttons", inputs: { form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: false, transformFunction: null }, noSave: { classPropertyName: "noSave", publicName: "noSave", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closeRequest: "closeRequest" }, ngImport: i0, template: "@if (form()) {\n<div class=\"form-row\">\n <button type=\"button\" mat-flat-button class=\"mat-warn\" (click)=\"close()\">\n <mat-icon>cancel</mat-icon>\n close\n </button>\n @if (!noSave()) {\n <button\n type=\"submit\"\n [disabled]=\"form()?.invalid\"\n mat-flat-button\n class=\"mat-primary\"\n >\n <mat-icon>check_circle</mat-icon>\n save\n </button>\n }\n</div>\n}\n", styles: [".form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}\n"], dependencies: [{ kind: "component", type: 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: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }] });
|
|
34
45
|
}
|
|
35
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.
|
|
46
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: CloseSaveButtonsComponent, decorators: [{
|
|
36
47
|
type: Component,
|
|
37
48
|
args: [{ selector: 'cadmus-close-save-buttons', imports: [MatButton, MatIcon], template: "@if (form()) {\n<div class=\"form-row\">\n <button type=\"button\" mat-flat-button class=\"mat-warn\" (click)=\"close()\">\n <mat-icon>cancel</mat-icon>\n close\n </button>\n @if (!noSave()) {\n <button\n type=\"submit\"\n [disabled]=\"form()?.invalid\"\n mat-flat-button\n class=\"mat-primary\"\n >\n <mat-icon>check_circle</mat-icon>\n save\n </button>\n }\n</div>\n}\n", styles: [".form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}\n"] }]
|
|
38
49
|
}] });
|
|
@@ -69,10 +80,10 @@ class DecoratedTokenTextComponent {
|
|
|
69
80
|
decorate(text, locations, selectedLocation) {
|
|
70
81
|
this.text.set(this._textLayerService.render(text, locations, selectedLocation));
|
|
71
82
|
}
|
|
72
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.
|
|
73
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.
|
|
83
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: DecoratedTokenTextComponent, deps: [{ token: i1.TextLayerService }], target: i0.ɵɵFactoryTarget.Component });
|
|
84
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.3", type: DecoratedTokenTextComponent, isStandalone: true, selector: "cadmus-decorated-token-text", inputs: { baseText: { classPropertyName: "baseText", publicName: "baseText", isSignal: true, isRequired: false, transformFunction: null }, locations: { classPropertyName: "locations", publicName: "locations", isSignal: true, isRequired: false, transformFunction: null }, selectedLocation: { classPropertyName: "selectedLocation", publicName: "selectedLocation", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "_textElement", first: true, predicate: ["textElem"], descendants: true }], ngImport: i0, template: "<div [innerHtml]=\"text() | safeHtml : 'html'\" id=\"text\" #textElem></div>\r\n", styles: [":host ::ng-deep div#text{counter-reset:text-y-counter}:host ::ng-deep div#text p:before{content:counter(text-y-counter);counter-increment:text-y-counter;margin-right:6px;color:#a0a0a0}:host ::ng-deep span.fr{background-color:#ff0;border:1px solid silver;border-radius:6px;padding:0 4px}:host ::ng-deep span.fr-sel{background-color:orange;font-weight:700;border:1px solid #404040}\n"], dependencies: [{ kind: "pipe", type: SafeHtmlPipe, name: "safeHtml" }] });
|
|
74
85
|
}
|
|
75
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.
|
|
86
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: DecoratedTokenTextComponent, decorators: [{
|
|
76
87
|
type: Component,
|
|
77
88
|
args: [{ selector: 'cadmus-decorated-token-text', imports: [SafeHtmlPipe], template: "<div [innerHtml]=\"text() | safeHtml : 'html'\" id=\"text\" #textElem></div>\r\n", styles: [":host ::ng-deep div#text{counter-reset:text-y-counter}:host ::ng-deep div#text p:before{content:counter(text-y-counter);counter-increment:text-y-counter;margin-right:6px;color:#a0a0a0}:host ::ng-deep span.fr{background-color:#ff0;border:1px solid silver;border-radius:6px;padding:0 4px}:host ::ng-deep span.fr-sel{background-color:orange;font-weight:700;border:1px solid #404040}\n"] }]
|
|
78
89
|
}], ctorParameters: () => [{ type: i1.TextLayerService }], propDecorators: { _textElement: [{
|
|
@@ -82,10 +93,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.0", ngImpor
|
|
|
82
93
|
|
|
83
94
|
class ErrorListComponent {
|
|
84
95
|
errors = input(...(ngDevMode ? [undefined, { debugName: "errors" }] : []));
|
|
85
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.
|
|
86
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.
|
|
96
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: ErrorListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
97
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.3", type: ErrorListComponent, isStandalone: true, selector: "cadmus-error-list", inputs: { errors: { classPropertyName: "errors", publicName: "errors", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if (errors()?.length) {\n <ul>\n @for (error of errors(); track error) {\n <li class=\"error\">{{error}}</li>\n }\n </ul>\n}\n", styles: [".error{color:red}\n"] });
|
|
87
98
|
}
|
|
88
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.
|
|
99
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: ErrorListComponent, decorators: [{
|
|
89
100
|
type: Component,
|
|
90
101
|
args: [{ selector: 'cadmus-error-list', template: "@if (errors()?.length) {\n <ul>\n @for (error of errors(); track error) {\n <li class=\"error\">{{error}}</li>\n }\n </ul>\n}\n", styles: [".error{color:red}\n"] }]
|
|
91
102
|
}] });
|
|
@@ -233,10 +244,10 @@ class ColorService {
|
|
|
233
244
|
const rgb = this.hslToRgb(h, s, l);
|
|
234
245
|
return this.rgbToString(rgb.r, rgb.g, rgb.b);
|
|
235
246
|
}
|
|
236
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.
|
|
237
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.
|
|
247
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: ColorService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
248
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: ColorService, providedIn: 'root' });
|
|
238
249
|
}
|
|
239
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.
|
|
250
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: ColorService, decorators: [{
|
|
240
251
|
type: Injectable,
|
|
241
252
|
args: [{
|
|
242
253
|
providedIn: 'root',
|
|
@@ -317,10 +328,10 @@ class FacetBadgeComponent {
|
|
|
317
328
|
this.contrastColor.set(this._colorService.getContrastColor(this.color()));
|
|
318
329
|
this.tip.set(this.getFacetTip(data?.facetId || '') ?? undefined);
|
|
319
330
|
}
|
|
320
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.
|
|
321
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.
|
|
331
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: FacetBadgeComponent, deps: [{ token: ColorService }], target: i0.ɵɵFactoryTarget.Component });
|
|
332
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.3", type: FacetBadgeComponent, isStandalone: true, selector: "cadmus-facet-badge", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<span\r\n class=\"model-type\"\r\n [style.background-color]=\"color()\"\r\n [style.color]=\"contrastColor()\"\r\n matTooltip=\"{{ tip() }}\"\r\n >{{ data().facetId }}\r\n</span>\r\n", styles: ["span.model-type{padding:4px;border-radius:6px}\n"], dependencies: [{ kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }] });
|
|
322
333
|
}
|
|
323
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.
|
|
334
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: FacetBadgeComponent, decorators: [{
|
|
324
335
|
type: Component,
|
|
325
336
|
args: [{ selector: 'cadmus-facet-badge', imports: [MatTooltip], template: "<span\r\n class=\"model-type\"\r\n [style.background-color]=\"color()\"\r\n [style.color]=\"contrastColor()\"\r\n matTooltip=\"{{ tip() }}\"\r\n >{{ data().facetId }}\r\n</span>\r\n", styles: ["span.model-type{padding:4px;border-radius:6px}\n"] }]
|
|
326
337
|
}], ctorParameters: () => [{ type: ColorService }] });
|
|
@@ -346,10 +357,10 @@ class FlagsBadgeComponent {
|
|
|
346
357
|
return def.id & data.flags;
|
|
347
358
|
}));
|
|
348
359
|
}
|
|
349
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.
|
|
350
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.
|
|
360
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: FlagsBadgeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
361
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.3", type: FlagsBadgeComponent, isStandalone: true, selector: "cadmus-flags-badge", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div>\r\n @for (def of badgeFlags(); track def.id) {\r\n <span\r\n class=\"badge-flag\"\r\n [style.color]=\"'#' + def.colorKey\"\r\n [matTooltip]=\"def.label\"\r\n >\r\n @if (def.isAdmin) { ◆ } @else { ⬤ }\r\n </span>\r\n }\r\n</div>\r\n", styles: ["span.badge-flag{font-size:1rem;cursor:default}\n"], dependencies: [{ kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }] });
|
|
351
362
|
}
|
|
352
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.
|
|
363
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: FlagsBadgeComponent, decorators: [{
|
|
353
364
|
type: Component,
|
|
354
365
|
args: [{ selector: 'cadmus-flags-badge', imports: [MatTooltip], template: "<div>\r\n @for (def of badgeFlags(); track def.id) {\r\n <span\r\n class=\"badge-flag\"\r\n [style.color]=\"'#' + def.colorKey\"\r\n [matTooltip]=\"def.label\"\r\n >\r\n @if (def.isAdmin) { ◆ } @else { ⬤ }\r\n </span>\r\n }\r\n</div>\r\n", styles: ["span.badge-flag{font-size:1rem;cursor:default}\n"] }]
|
|
355
366
|
}], ctorParameters: () => [] });
|
|
@@ -426,10 +437,10 @@ class LayerHintsComponent {
|
|
|
426
437
|
}
|
|
427
438
|
});
|
|
428
439
|
}
|
|
429
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.
|
|
430
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.
|
|
440
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: LayerHintsComponent, deps: [{ token: i1$1.FormBuilder }, { token: i2.DialogService }], target: i0.ɵɵFactoryTarget.Component });
|
|
441
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.3", type: LayerHintsComponent, isStandalone: true, selector: "cadmus-layer-hints", inputs: { hints: { classPropertyName: "hints", publicName: "hints", isSignal: true, isRequired: false, transformFunction: null }, targetLocation: { classPropertyName: "targetLocation", publicName: "targetLocation", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { requestEdit: "requestEdit", requestDelete: "requestDelete", requestMove: "requestMove", requestPatch: "requestPatch" }, ngImport: i0, template: "@if (hints().length) {\r\n<form [formGroup]=\"form\" (submit)=\"emitRequestPatch()\">\r\n <table class=\"patches\">\r\n <thead>\r\n <tr>\r\n <th></th>\r\n <th>location</th>\r\n <th>description</th>\r\n <th>patch</th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (hint of hints(); track hint; let i = $index) {\r\n <tr>\r\n @if (!readonly()) {\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Edit this fragment\"\r\n [disabled]=\"disabled()\"\r\n >\r\n <mat-icon>edit</mat-icon>\r\n </button>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Move this fragment to {{ targetLocation() }}\"\r\n [disabled]=\"\r\n disabled() ||\r\n !targetLocation() ||\r\n targetLocation() === hint.location\r\n \"\r\n (click)=\"emitRequestMove(hint)\"\r\n >\r\n <mat-icon>arrow_forward</mat-icon>\r\n </button>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Delete this fragment\"\r\n [disabled]=\"disabled()\"\r\n (click)=\"emitRequestDelete(hint)\"\r\n >\r\n <mat-icon class=\"mat-warn\">delete</mat-icon>\r\n </button>\r\n </td>\r\n }\r\n <td>{{ hint.location }}</td>\r\n <td>{{ hint.description }}</td>\r\n <td>\r\n @if (hint.patchOperation) {\r\n <mat-checkbox\r\n matTooltip=\"Apply this patch\"\r\n [formControl]=\"checks.at(i)\"\r\n >\r\n {{ hint.patchOperation }}\r\n </mat-checkbox>\r\n }\r\n </td>\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n @if (targetLocation()) {\r\n <div>move target: {{ targetLocation() }}</div>\r\n }\r\n <button\r\n type=\"submit\"\r\n mat-flat-button\r\n [disabled]=\"readonly() || disabled() || form.invalid\"\r\n >\r\n apply patches\r\n </button>\r\n</form>\r\n}\r\n", styles: ["table.patches th{font-weight:400;color:#bdbdbd}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { 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: "component", type: MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: 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: "component", type: 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"] }] });
|
|
431
442
|
}
|
|
432
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.
|
|
443
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: LayerHintsComponent, decorators: [{
|
|
433
444
|
type: Component,
|
|
434
445
|
args: [{ selector: 'cadmus-layer-hints', imports: [
|
|
435
446
|
FormsModule,
|
|
@@ -439,7 +450,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.0", ngImpor
|
|
|
439
450
|
MatIcon,
|
|
440
451
|
MatCheckbox,
|
|
441
452
|
MatButton,
|
|
442
|
-
], template: "@if (hints().length) {\r\n<form [formGroup]=\"form\" (submit)=\"emitRequestPatch()\">\r\n <table class=\"patches\">\r\n <thead>\r\n <tr>\r\n <th></th>\r\n <th>location</th>\r\n <th>description</th>\r\n <th>patch</th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (hint of hints(); track hint; let i = $index) {\r\n <tr>\r\n @if (!readonly()) {\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Edit this fragment\"\r\n [disabled]=\"disabled()\"\r\n >\r\n <mat-icon>edit</mat-icon>\r\n </button>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Move this fragment to {{ targetLocation() }}\"\r\n [disabled]=\"\r\n disabled() ||\r\n !targetLocation() ||\r\n targetLocation() === hint.location\r\n \"\r\n (click)=\"emitRequestMove(hint)\"\r\n >\r\n <mat-icon>arrow_forward</mat-icon>\r\n </button>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Delete this fragment\"\r\n [disabled]=\"disabled()\"\r\n (click)=\"emitRequestDelete(hint)\"\r\n >\r\n <mat-icon class=\"mat-warn\">delete</mat-icon>\r\n </button>\r\n </td>\r\n }\r\n <td>{{ hint.location }}</td>\r\n <td>{{ hint.description }}</td>\r\n <td>\r\n @if (hint.patchOperation) {\r\n <mat-checkbox\r\n matTooltip=\"Apply this patch\"\r\n [
|
|
453
|
+
], template: "@if (hints().length) {\r\n<form [formGroup]=\"form\" (submit)=\"emitRequestPatch()\">\r\n <table class=\"patches\">\r\n <thead>\r\n <tr>\r\n <th></th>\r\n <th>location</th>\r\n <th>description</th>\r\n <th>patch</th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (hint of hints(); track hint; let i = $index) {\r\n <tr>\r\n @if (!readonly()) {\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Edit this fragment\"\r\n [disabled]=\"disabled()\"\r\n >\r\n <mat-icon>edit</mat-icon>\r\n </button>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Move this fragment to {{ targetLocation() }}\"\r\n [disabled]=\"\r\n disabled() ||\r\n !targetLocation() ||\r\n targetLocation() === hint.location\r\n \"\r\n (click)=\"emitRequestMove(hint)\"\r\n >\r\n <mat-icon>arrow_forward</mat-icon>\r\n </button>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Delete this fragment\"\r\n [disabled]=\"disabled()\"\r\n (click)=\"emitRequestDelete(hint)\"\r\n >\r\n <mat-icon class=\"mat-warn\">delete</mat-icon>\r\n </button>\r\n </td>\r\n }\r\n <td>{{ hint.location }}</td>\r\n <td>{{ hint.description }}</td>\r\n <td>\r\n @if (hint.patchOperation) {\r\n <mat-checkbox\r\n matTooltip=\"Apply this patch\"\r\n [formControl]=\"checks.at(i)\"\r\n >\r\n {{ hint.patchOperation }}\r\n </mat-checkbox>\r\n }\r\n </td>\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n @if (targetLocation()) {\r\n <div>move target: {{ targetLocation() }}</div>\r\n }\r\n <button\r\n type=\"submit\"\r\n mat-flat-button\r\n [disabled]=\"readonly() || disabled() || form.invalid\"\r\n >\r\n apply patches\r\n </button>\r\n</form>\r\n}\r\n", styles: ["table.patches th{font-weight:400;color:#bdbdbd}\n"] }]
|
|
443
454
|
}], ctorParameters: () => [{ type: i1$1.FormBuilder }, { type: i2.DialogService }] });
|
|
444
455
|
|
|
445
456
|
/**
|
|
@@ -566,10 +577,10 @@ class LookupPinComponent {
|
|
|
566
577
|
this.clear();
|
|
567
578
|
}
|
|
568
579
|
}
|
|
569
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.
|
|
570
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.
|
|
580
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: LookupPinComponent, deps: [{ token: i1$1.UntypedFormBuilder }, { token: i1$2.ItemService }, { token: 'indexLookupDefinitions' }], target: i0.ɵɵFactoryTarget.Component });
|
|
581
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.3", type: LookupPinComponent, isStandalone: true, selector: "cadmus-lookup-pin", inputs: { initialValue: { classPropertyName: "initialValue", publicName: "initialValue", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, limit: { classPropertyName: "limit", publicName: "limit", isSignal: true, isRequired: false, transformFunction: null }, resetOnPick: { classPropertyName: "resetOnPick", publicName: "resetOnPick", isSignal: true, isRequired: false, transformFunction: null }, lookupKey: { classPropertyName: "lookupKey", publicName: "lookupKey", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { entryChange: "entryChange" }, ngImport: i0, template: "<form [formGroup]=\"form\">\r\n <mat-autocomplete #lookupAuto=\"matAutocomplete\" [displayWith]=\"entryToName\">\r\n @for (entry of entries$ | async; track entry) {\r\n <mat-option [value]=\"entry\" (onSelectionChange)=\"pickEntry(entry)\">\r\n {{ entry?.value }}\r\n </mat-option>\r\n }\r\n </mat-autocomplete>\r\n\r\n <mat-form-field>\r\n <input\r\n matInput\r\n type=\"text\"\r\n [placeholder]=\"label()\"\r\n [formControl]=\"lookup\"\r\n [matAutocomplete]=\"lookupAuto\"\r\n />\r\n </mat-form-field>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n (click)=\"clear()\"\r\n [disabled]=\"!entry()\"\r\n matTooltip=\"Clear\"\r\n >\r\n <mat-icon class=\"mat-warn\">clear</mat-icon>\r\n </button>\r\n</form>\r\n", styles: [""], 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: "component", type: MatAutocomplete, selector: "mat-autocomplete", inputs: ["aria-label", "aria-labelledby", "displayWith", "autoActiveFirstOption", "autoSelectActiveOption", "requireSelection", "panelWidth", "disableRipple", "class", "hideSingleSelectionIndicator"], outputs: ["optionSelected", "opened", "closed", "optionActivated"], exportAs: ["matAutocomplete"] }, { kind: "component", type: MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: 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: "directive", type: MatAutocompleteTrigger, selector: "input[matAutocomplete], textarea[matAutocomplete]", inputs: ["matAutocomplete", "matAutocompletePosition", "matAutocompleteConnectedTo", "autocomplete", "matAutocompleteDisabled"], exportAs: ["matAutocompleteTrigger"] }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "pipe", type: AsyncPipe, name: "async" }] });
|
|
571
582
|
}
|
|
572
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.
|
|
583
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: LookupPinComponent, decorators: [{
|
|
573
584
|
type: Component,
|
|
574
585
|
args: [{ selector: 'cadmus-lookup-pin', imports: [
|
|
575
586
|
FormsModule,
|
|
@@ -589,6 +600,630 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.0", ngImpor
|
|
|
589
600
|
args: ['indexLookupDefinitions']
|
|
590
601
|
}] }] });
|
|
591
602
|
|
|
603
|
+
/**
|
|
604
|
+
* A label rendering function which removes from a label
|
|
605
|
+
* all the characters past the last colon, trimming the result.
|
|
606
|
+
* This is a typical rendering when dealing with hierarchical
|
|
607
|
+
* thesaurus entries, e.g. "furniture: table: color", where
|
|
608
|
+
* we can shorten the label to just "color", as "furniture"
|
|
609
|
+
* and "table" are its ancestors.
|
|
610
|
+
*/
|
|
611
|
+
const renderLabelFromLastColon = (label) => {
|
|
612
|
+
if (!label) {
|
|
613
|
+
return label;
|
|
614
|
+
}
|
|
615
|
+
const i = label.lastIndexOf(':');
|
|
616
|
+
return i > -1 && i + 1 < label.length ? label.substring(i + 1).trim() : label;
|
|
617
|
+
};
|
|
618
|
+
/**
|
|
619
|
+
* A static paged tree store service for thesaurus entries.
|
|
620
|
+
* This builds the tree nodes from the thesaurus entries, assuming
|
|
621
|
+
* that entry IDs are hierarchical and separated by dots (.).
|
|
622
|
+
*/
|
|
623
|
+
class StaticThesPagedTreeStoreService {
|
|
624
|
+
_renderLabel;
|
|
625
|
+
_nodes = [];
|
|
626
|
+
_built = false;
|
|
627
|
+
_entries;
|
|
628
|
+
constructor(entries, _renderLabel) {
|
|
629
|
+
this._renderLabel = _renderLabel;
|
|
630
|
+
// assign a number to each entry for stable IDs
|
|
631
|
+
this._entries = entries.map((entry, index) => ({
|
|
632
|
+
...entry,
|
|
633
|
+
n: index + 1,
|
|
634
|
+
}));
|
|
635
|
+
}
|
|
636
|
+
ensureNodes() {
|
|
637
|
+
// lazily build the nodes only once
|
|
638
|
+
if (this._built) {
|
|
639
|
+
return;
|
|
640
|
+
}
|
|
641
|
+
// map where key is node.id and value is max x value for that parent
|
|
642
|
+
// (0 is used for the virtual root)
|
|
643
|
+
const xMap = new Map();
|
|
644
|
+
for (const entry of this._entries) {
|
|
645
|
+
const hasDot = entry.id.includes('.');
|
|
646
|
+
const keyParts = entry.id.split('.');
|
|
647
|
+
// create the node
|
|
648
|
+
const node = {
|
|
649
|
+
id: entry.n,
|
|
650
|
+
label: hasDot && this._renderLabel
|
|
651
|
+
? this._renderLabel(entry.value)
|
|
652
|
+
: entry.value,
|
|
653
|
+
key: entry.id,
|
|
654
|
+
value: entry.value,
|
|
655
|
+
paging: { pageNumber: 0, pageCount: 0, total: 0 },
|
|
656
|
+
y: hasDot ? keyParts.length : 1,
|
|
657
|
+
x: 0, // will be set later
|
|
658
|
+
parentId: undefined, // will be set later
|
|
659
|
+
hasChildren: false, // will be set later
|
|
660
|
+
};
|
|
661
|
+
// if it has a dot, find its parent and set parentId
|
|
662
|
+
if (hasDot) {
|
|
663
|
+
// build the parent key
|
|
664
|
+
const parentKey = keyParts.slice(0, keyParts.length - 1).join('.');
|
|
665
|
+
// find the parent node with that key
|
|
666
|
+
const parentNode = this._nodes.find((n) => n.key === parentKey);
|
|
667
|
+
// if found, set parentId and x in child and hasChildren in parent
|
|
668
|
+
if (parentNode) {
|
|
669
|
+
node.parentId = parentNode.id;
|
|
670
|
+
parentNode.hasChildren = true;
|
|
671
|
+
if (xMap.has(parentNode.id)) {
|
|
672
|
+
xMap.set(parentNode.id, xMap.get(parentNode.id) + 1);
|
|
673
|
+
}
|
|
674
|
+
else {
|
|
675
|
+
xMap.set(parentNode.id, 1);
|
|
676
|
+
}
|
|
677
|
+
node.x = xMap.get(parentNode.id);
|
|
678
|
+
}
|
|
679
|
+
else {
|
|
680
|
+
// parent not found, treat as root
|
|
681
|
+
if (xMap.has(0)) {
|
|
682
|
+
xMap.set(0, xMap.get(0) + 1);
|
|
683
|
+
}
|
|
684
|
+
else {
|
|
685
|
+
xMap.set(0, 1);
|
|
686
|
+
}
|
|
687
|
+
node.x = xMap.get(0);
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
else {
|
|
691
|
+
// else it's a root node
|
|
692
|
+
if (xMap.has(0)) {
|
|
693
|
+
xMap.set(0, xMap.get(0) + 1);
|
|
694
|
+
}
|
|
695
|
+
else {
|
|
696
|
+
xMap.set(0, 1);
|
|
697
|
+
}
|
|
698
|
+
node.x = xMap.get(0);
|
|
699
|
+
}
|
|
700
|
+
this._nodes.push(node);
|
|
701
|
+
}
|
|
702
|
+
this._built = true;
|
|
703
|
+
}
|
|
704
|
+
/**
|
|
705
|
+
* Get the specified page of nodes.
|
|
706
|
+
* @param filter The filter.
|
|
707
|
+
* @param pageNumber The page number.
|
|
708
|
+
* @param pageSize The page size.
|
|
709
|
+
* @param hasMockRoot Whether the root node is a mock node. Not used here.
|
|
710
|
+
*/
|
|
711
|
+
getNodes(filter, pageNumber, pageSize, hasMockRoot) {
|
|
712
|
+
this.ensureNodes();
|
|
713
|
+
// apply filtering
|
|
714
|
+
let nodes = this._nodes.filter((n) => {
|
|
715
|
+
if (filter.parentId !== undefined && filter.parentId !== null) {
|
|
716
|
+
if (n.parentId !== filter.parentId) {
|
|
717
|
+
return false;
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
else {
|
|
721
|
+
if (n.parentId) {
|
|
722
|
+
return false;
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
if (filter.label) {
|
|
726
|
+
const filterValue = filter.label.toLowerCase();
|
|
727
|
+
if (!n.label.toLowerCase().includes(filterValue)) {
|
|
728
|
+
return false;
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
return true;
|
|
732
|
+
});
|
|
733
|
+
// apply paging
|
|
734
|
+
const startIndex = (pageNumber - 1) * pageSize;
|
|
735
|
+
const endIndex = startIndex + pageSize;
|
|
736
|
+
const pagedNodes = nodes.slice(startIndex, endIndex);
|
|
737
|
+
// page and return
|
|
738
|
+
const paged = nodes.slice((pageNumber - 1) * pageSize, pageNumber * pageSize);
|
|
739
|
+
return of({
|
|
740
|
+
items: paged,
|
|
741
|
+
pageNumber: pageNumber,
|
|
742
|
+
pageSize: pageSize,
|
|
743
|
+
pageCount: Math.ceil(nodes.length / pageSize),
|
|
744
|
+
total: nodes.length,
|
|
745
|
+
});
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
/**
|
|
750
|
+
* A filter to be used for thesaurus paged tree browsers.
|
|
751
|
+
*/
|
|
752
|
+
class ThesPagedTreeFilterComponent {
|
|
753
|
+
dialogRef = inject(MatDialogRef, {
|
|
754
|
+
optional: true,
|
|
755
|
+
});
|
|
756
|
+
data = inject(MAT_DIALOG_DATA, { optional: true });
|
|
757
|
+
/**
|
|
758
|
+
* The filter.
|
|
759
|
+
*/
|
|
760
|
+
filter = model(...(ngDevMode ? [undefined, { debugName: "filter" }] : []));
|
|
761
|
+
wrapped = signal(false, ...(ngDevMode ? [{ debugName: "wrapped" }] : []));
|
|
762
|
+
label;
|
|
763
|
+
form;
|
|
764
|
+
constructor() {
|
|
765
|
+
const formBuilder = inject(FormBuilder);
|
|
766
|
+
const data = this.data;
|
|
767
|
+
// form
|
|
768
|
+
this.label = formBuilder.control(null);
|
|
769
|
+
this.form = formBuilder.group({
|
|
770
|
+
label: this.label,
|
|
771
|
+
});
|
|
772
|
+
// bind dialog data if any
|
|
773
|
+
if (this.dialogRef) {
|
|
774
|
+
this.wrapped.set(true);
|
|
775
|
+
if (data) {
|
|
776
|
+
this.filter.set(data.filter);
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
else {
|
|
780
|
+
this.wrapped.set(false);
|
|
781
|
+
}
|
|
782
|
+
// update form when filter changes
|
|
783
|
+
effect(() => {
|
|
784
|
+
this.updateForm(this.filter());
|
|
785
|
+
});
|
|
786
|
+
}
|
|
787
|
+
ngOnInit() {
|
|
788
|
+
this.updateForm(this.filter());
|
|
789
|
+
}
|
|
790
|
+
updateForm(filter) {
|
|
791
|
+
if (!filter) {
|
|
792
|
+
this.form.reset();
|
|
793
|
+
return;
|
|
794
|
+
}
|
|
795
|
+
this.label.setValue(filter.label ?? null);
|
|
796
|
+
this.form.markAsPristine();
|
|
797
|
+
}
|
|
798
|
+
getFilter() {
|
|
799
|
+
return {
|
|
800
|
+
label: this.label.value ?? undefined,
|
|
801
|
+
};
|
|
802
|
+
}
|
|
803
|
+
reset() {
|
|
804
|
+
this.form.reset();
|
|
805
|
+
this.filter.set(null);
|
|
806
|
+
this.dialogRef?.close(null);
|
|
807
|
+
}
|
|
808
|
+
apply() {
|
|
809
|
+
this.filter.set(this.getFilter());
|
|
810
|
+
this.dialogRef?.close(this.filter());
|
|
811
|
+
}
|
|
812
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: ThesPagedTreeFilterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
813
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.3", type: ThesPagedTreeFilterComponent, isStandalone: true, selector: "cadmus-thes-paged-tree-filter", inputs: { filter: { classPropertyName: "filter", publicName: "filter", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { filter: "filterChange" }, ngImport: i0, template: "<form\r\n [formGroup]=\"form\"\r\n [style.margin.px]=\"wrapped() ? 16 : 0\"\r\n (submit)=\"apply()\"\r\n>\r\n <div class=\"form-row\">\r\n <!-- label -->\r\n <mat-form-field>\r\n <input matInput placeholder=\"label\" [formControl]=\"label\" />\r\n </mat-form-field>\r\n </div>\r\n\r\n <div class=\"form-row\">\r\n <!-- buttons -->\r\n <button type=\"button\" mat-icon-button matTooltip=\"Reset\" (click)=\"reset()\">\r\n <mat-icon class=\"mat-warn\">clear</mat-icon>\r\n </button>\r\n <button\r\n type=\"submit\"\r\n mat-icon-button\r\n matTooltip=\"Apply\"\r\n [disabled]=\"form.invalid\"\r\n >\r\n <mat-icon class=\"mat-primary\">check_circle</mat-icon>\r\n </button>\r\n </div>\r\n</form>\r\n", styles: ["form{margin:16px}.form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}.nr{width:6em}fieldset{border:1px solid silver;border-radius:6px;padding:8px 16px;margin:8px 0}legend{color:silver}th{text-align:left;font-weight:400}#tag-selector{width:8em}.tag-chip{border:2px solid transparent;border-radius:6px}\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: i2$1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i4$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: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i6.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }] });
|
|
814
|
+
}
|
|
815
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: ThesPagedTreeFilterComponent, decorators: [{
|
|
816
|
+
type: Component,
|
|
817
|
+
args: [{ selector: 'cadmus-thes-paged-tree-filter', imports: [
|
|
818
|
+
ReactiveFormsModule,
|
|
819
|
+
MatButtonModule,
|
|
820
|
+
MatFormFieldModule,
|
|
821
|
+
MatInputModule,
|
|
822
|
+
MatIconModule,
|
|
823
|
+
MatTooltipModule,
|
|
824
|
+
], template: "<form\r\n [formGroup]=\"form\"\r\n [style.margin.px]=\"wrapped() ? 16 : 0\"\r\n (submit)=\"apply()\"\r\n>\r\n <div class=\"form-row\">\r\n <!-- label -->\r\n <mat-form-field>\r\n <input matInput placeholder=\"label\" [formControl]=\"label\" />\r\n </mat-form-field>\r\n </div>\r\n\r\n <div class=\"form-row\">\r\n <!-- buttons -->\r\n <button type=\"button\" mat-icon-button matTooltip=\"Reset\" (click)=\"reset()\">\r\n <mat-icon class=\"mat-warn\">clear</mat-icon>\r\n </button>\r\n <button\r\n type=\"submit\"\r\n mat-icon-button\r\n matTooltip=\"Apply\"\r\n [disabled]=\"form.invalid\"\r\n >\r\n <mat-icon class=\"mat-primary\">check_circle</mat-icon>\r\n </button>\r\n </div>\r\n</form>\r\n", styles: ["form{margin:16px}.form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}.nr{width:6em}fieldset{border:1px solid silver;border-radius:6px;padding:8px 16px;margin:8px 0}legend{color:silver}th{text-align:left;font-weight:400}#tag-selector{width:8em}.tag-chip{border:2px solid transparent;border-radius:6px}\n"] }]
|
|
825
|
+
}], ctorParameters: () => [] });
|
|
826
|
+
|
|
827
|
+
class ThesPagedTreeBrowserComponent {
|
|
828
|
+
_dialog = inject(MatDialog);
|
|
829
|
+
_sub;
|
|
830
|
+
/**
|
|
831
|
+
* The service to use to load the nodes.
|
|
832
|
+
*/
|
|
833
|
+
service = input(new StaticThesPagedTreeStoreService([], renderLabelFromLastColon), ...(ngDevMode ? [{ debugName: "service" }] : []));
|
|
834
|
+
/**
|
|
835
|
+
* Emitted when a node is clicked.
|
|
836
|
+
*/
|
|
837
|
+
nodePick = output();
|
|
838
|
+
/**
|
|
839
|
+
* The store instance, built from the service.
|
|
840
|
+
*/
|
|
841
|
+
store = computed(() => {
|
|
842
|
+
const service = this.service();
|
|
843
|
+
const store = new PagedTreeStore(service);
|
|
844
|
+
this.nodes$ = store.nodes$;
|
|
845
|
+
this.filter$ = store.filter$;
|
|
846
|
+
return store;
|
|
847
|
+
}, ...(ngDevMode ? [{ debugName: "store" }] : []));
|
|
848
|
+
loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
|
|
849
|
+
debug = new FormControl(false, {
|
|
850
|
+
nonNullable: true,
|
|
851
|
+
});
|
|
852
|
+
hideLoc = new FormControl(false, {
|
|
853
|
+
nonNullable: true,
|
|
854
|
+
});
|
|
855
|
+
hideFilter = new FormControl(false, {
|
|
856
|
+
nonNullable: true,
|
|
857
|
+
});
|
|
858
|
+
filter$;
|
|
859
|
+
nodes$;
|
|
860
|
+
label = new FormControl(null);
|
|
861
|
+
form = new FormGroup({
|
|
862
|
+
label: this.label,
|
|
863
|
+
});
|
|
864
|
+
constructor() {
|
|
865
|
+
const store = this.store();
|
|
866
|
+
this.nodes$ = store.nodes$;
|
|
867
|
+
this.filter$ = store.filter$;
|
|
868
|
+
}
|
|
869
|
+
ngOnInit() {
|
|
870
|
+
if (!this.store().getNodes().length) {
|
|
871
|
+
this.loading.set(true);
|
|
872
|
+
this.store()
|
|
873
|
+
.setFilter({})
|
|
874
|
+
.finally(() => {
|
|
875
|
+
this.loading.set(false);
|
|
876
|
+
console.log('nodes loaded', this.store().getNodes());
|
|
877
|
+
});
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
ngOnDestroy() {
|
|
881
|
+
this._sub?.unsubscribe();
|
|
882
|
+
}
|
|
883
|
+
reset() {
|
|
884
|
+
this.loading.set(true);
|
|
885
|
+
this.store()
|
|
886
|
+
.reset()
|
|
887
|
+
.finally(() => {
|
|
888
|
+
this.loading.set(false);
|
|
889
|
+
});
|
|
890
|
+
}
|
|
891
|
+
onToggleExpanded(node) {
|
|
892
|
+
this.loading.set(true);
|
|
893
|
+
if (node.expanded) {
|
|
894
|
+
this.store()
|
|
895
|
+
.collapse(node.id)
|
|
896
|
+
.finally(() => {
|
|
897
|
+
this.loading.set(false);
|
|
898
|
+
});
|
|
899
|
+
}
|
|
900
|
+
else {
|
|
901
|
+
this.store()
|
|
902
|
+
.expand(node.id)
|
|
903
|
+
.finally(() => {
|
|
904
|
+
this.loading.set(false);
|
|
905
|
+
});
|
|
906
|
+
}
|
|
907
|
+
}
|
|
908
|
+
onPageChangeRequest(request) {
|
|
909
|
+
this.loading.set(true);
|
|
910
|
+
this.store()
|
|
911
|
+
.changePage(request.node.id, request.paging.pageNumber)
|
|
912
|
+
.finally(() => {
|
|
913
|
+
this.loading.set(false);
|
|
914
|
+
});
|
|
915
|
+
}
|
|
916
|
+
onFilterChange(filter) {
|
|
917
|
+
console.log('filter change', filter);
|
|
918
|
+
this.loading.set(true);
|
|
919
|
+
this.store()
|
|
920
|
+
.setFilter(filter || {})
|
|
921
|
+
.finally(() => {
|
|
922
|
+
this.loading.set(false);
|
|
923
|
+
});
|
|
924
|
+
}
|
|
925
|
+
onEditFilterRequest(node) {
|
|
926
|
+
const dialogRef = this._dialog.open(ThesPagedTreeFilterComponent, {
|
|
927
|
+
data: {
|
|
928
|
+
filter: node.filter,
|
|
929
|
+
},
|
|
930
|
+
});
|
|
931
|
+
dialogRef.afterClosed().subscribe((filter) => {
|
|
932
|
+
// undefined = user dismissed without changes
|
|
933
|
+
if (filter === null) {
|
|
934
|
+
this.store().setNodeFilter(node.id, null);
|
|
935
|
+
}
|
|
936
|
+
else if (filter) {
|
|
937
|
+
this.store().setNodeFilter(node.id, filter);
|
|
938
|
+
}
|
|
939
|
+
});
|
|
940
|
+
}
|
|
941
|
+
expandAll() {
|
|
942
|
+
this.store().expandAll();
|
|
943
|
+
}
|
|
944
|
+
collapseAll() {
|
|
945
|
+
this.store().collapseAll();
|
|
946
|
+
}
|
|
947
|
+
clear() {
|
|
948
|
+
this.store().clear();
|
|
949
|
+
}
|
|
950
|
+
onNodeClick(node) {
|
|
951
|
+
if (!node.hasChildren) {
|
|
952
|
+
this.nodePick.emit(node);
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
findLabels() {
|
|
956
|
+
if (!this.label.value) {
|
|
957
|
+
return;
|
|
958
|
+
}
|
|
959
|
+
this.store().findLabels(this.label.value);
|
|
960
|
+
}
|
|
961
|
+
removeHilites() {
|
|
962
|
+
this.store().removeHilites();
|
|
963
|
+
}
|
|
964
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: ThesPagedTreeBrowserComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
965
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.3", type: ThesPagedTreeBrowserComponent, isStandalone: true, selector: "cadmus-thes-paged-tree-browser", inputs: { service: { classPropertyName: "service", publicName: "service", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { nodePick: "nodePick" }, ngImport: i0, template: "<div id=\"container\">\r\n <!-- filters -->\r\n <div id=\"filters\" class=\"form-row\">\r\n <form [formGroup]=\"form\" (submit)=\"findLabels()\" class=\"form-row\">\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 }\r\n </mat-form-field>\r\n <button type=\"submit\" mat-icon-button class=\"mat-primary\">\r\n <mat-icon>search</mat-icon>\r\n </button>\r\n <button type=\"button\" mat-icon-button (click)=\"removeHilites()\">\r\n <mat-icon class=\"mat-warn\">clear</mat-icon>\r\n </button>\r\n </form>\r\n <fieldset>\r\n <legend>filter</legend>\r\n <cadmus-thes-paged-tree-filter\r\n [filter]=\"filter$ | async\"\r\n (filterChange)=\"onFilterChange($event)\"\r\n />\r\n </fieldset>\r\n </div>\r\n\r\n <!-- tree -->\r\n <div id=\"tree\">\r\n <!-- progress -->\r\n @if (loading()) {\r\n <div>\r\n <mat-progress-bar mode=\"indeterminate\"></mat-progress-bar>\r\n </div>\r\n }\r\n <!-- nodes -->\r\n @if (nodes$ | async; as nodes) {\r\n <div>\r\n @for (node of nodes; track node.id; let i = $index) {\r\n <div class=\"button-row\" [class.hilite]=\"node.hilite\">\r\n <pdb-browser-tree-node\r\n [node]=\"node\"\r\n [debug]=\"debug.value\"\r\n [paging]=\"\r\n node.expanded &&\r\n i + 1 < nodes.length &&\r\n nodes[i + 1].paging.pageCount > 1\r\n ? nodes[i + 1].paging\r\n : undefined\r\n \"\r\n [hideFilter]=\"hideFilter.value\"\r\n [hideLoc]=\"hideLoc.value\"\r\n (toggleExpandedRequest)=\"onToggleExpanded($any($event))\"\r\n (changePageRequest)=\"onPageChangeRequest($event)\"\r\n (editNodeFilterRequest)=\"onEditFilterRequest($any($event))\"\r\n />\r\n @if (!node.hasChildren) {\r\n <button type=\"button\" mat-icon-button (click)=\"onNodeClick(node)\">\r\n <mat-icon class=\"mat-primary\">check_circle</mat-icon>\r\n </button>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n <div class=\"form-row\">\r\n <mat-checkbox [formControl]=\"debug\">debug</mat-checkbox>\r\n <mat-checkbox [formControl]=\"hideFilter\">no filter</mat-checkbox>\r\n <mat-checkbox [formControl]=\"hideLoc\">no loc.</mat-checkbox>\r\n <button\r\n type=\"button\"\r\n mat-flat-button\r\n (click)=\"collapseAll()\"\r\n style=\"margin-left: 24px\"\r\n >\r\n collapse\r\n </button>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: ["form{margin:16px}.form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}.nr{width:6em}fieldset{border:1px solid silver;border-radius:6px;padding:8px 16px;margin:8px 0}legend{color:silver}th{text-align:left;font-weight:400}#tag-selector{width:8em}.tag-chip{border:2px solid transparent;border-radius:6px}.button-row{display:flex;align-items:center;flex-wrap:wrap}.button-row *{flex:0 0 auto}.hilite{background-color:#ffffe0;border:2px solid gold;border-radius:6px;padding:2px 4px}\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: i2$1.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: i2$1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i3.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: MatFormFieldModule }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatLabel, selector: "mat-label" }, { kind: "directive", type: i4.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i4$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: MatProgressBarModule }, { kind: "component", type: i7.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "component", type: ThesPagedTreeFilterComponent, selector: "cadmus-thes-paged-tree-filter", inputs: ["filter"], outputs: ["filterChange"] }, { kind: "component", type: BrowserTreeNodeComponent, selector: "pdb-browser-tree-node", inputs: ["node", "paging", "debug", "hideLabel", "hideLoc", "hidePaging", "hideFilter", "indentSize", "rangeWidth"], outputs: ["toggleExpandedRequest", "changePageRequest", "editNodeFilterRequest"] }, { kind: "pipe", type: AsyncPipe, name: "async" }] });
|
|
966
|
+
}
|
|
967
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: ThesPagedTreeBrowserComponent, decorators: [{
|
|
968
|
+
type: Component,
|
|
969
|
+
args: [{ selector: 'cadmus-thes-paged-tree-browser', imports: [
|
|
970
|
+
AsyncPipe,
|
|
971
|
+
ReactiveFormsModule,
|
|
972
|
+
MatButtonModule,
|
|
973
|
+
MatCheckboxModule,
|
|
974
|
+
MatFormFieldModule,
|
|
975
|
+
MatIconModule,
|
|
976
|
+
MatInputModule,
|
|
977
|
+
MatProgressBarModule,
|
|
978
|
+
MatTooltipModule,
|
|
979
|
+
ThesPagedTreeFilterComponent,
|
|
980
|
+
BrowserTreeNodeComponent,
|
|
981
|
+
], template: "<div id=\"container\">\r\n <!-- filters -->\r\n <div id=\"filters\" class=\"form-row\">\r\n <form [formGroup]=\"form\" (submit)=\"findLabels()\" class=\"form-row\">\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 }\r\n </mat-form-field>\r\n <button type=\"submit\" mat-icon-button class=\"mat-primary\">\r\n <mat-icon>search</mat-icon>\r\n </button>\r\n <button type=\"button\" mat-icon-button (click)=\"removeHilites()\">\r\n <mat-icon class=\"mat-warn\">clear</mat-icon>\r\n </button>\r\n </form>\r\n <fieldset>\r\n <legend>filter</legend>\r\n <cadmus-thes-paged-tree-filter\r\n [filter]=\"filter$ | async\"\r\n (filterChange)=\"onFilterChange($event)\"\r\n />\r\n </fieldset>\r\n </div>\r\n\r\n <!-- tree -->\r\n <div id=\"tree\">\r\n <!-- progress -->\r\n @if (loading()) {\r\n <div>\r\n <mat-progress-bar mode=\"indeterminate\"></mat-progress-bar>\r\n </div>\r\n }\r\n <!-- nodes -->\r\n @if (nodes$ | async; as nodes) {\r\n <div>\r\n @for (node of nodes; track node.id; let i = $index) {\r\n <div class=\"button-row\" [class.hilite]=\"node.hilite\">\r\n <pdb-browser-tree-node\r\n [node]=\"node\"\r\n [debug]=\"debug.value\"\r\n [paging]=\"\r\n node.expanded &&\r\n i + 1 < nodes.length &&\r\n nodes[i + 1].paging.pageCount > 1\r\n ? nodes[i + 1].paging\r\n : undefined\r\n \"\r\n [hideFilter]=\"hideFilter.value\"\r\n [hideLoc]=\"hideLoc.value\"\r\n (toggleExpandedRequest)=\"onToggleExpanded($any($event))\"\r\n (changePageRequest)=\"onPageChangeRequest($event)\"\r\n (editNodeFilterRequest)=\"onEditFilterRequest($any($event))\"\r\n />\r\n @if (!node.hasChildren) {\r\n <button type=\"button\" mat-icon-button (click)=\"onNodeClick(node)\">\r\n <mat-icon class=\"mat-primary\">check_circle</mat-icon>\r\n </button>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n <div class=\"form-row\">\r\n <mat-checkbox [formControl]=\"debug\">debug</mat-checkbox>\r\n <mat-checkbox [formControl]=\"hideFilter\">no filter</mat-checkbox>\r\n <mat-checkbox [formControl]=\"hideLoc\">no loc.</mat-checkbox>\r\n <button\r\n type=\"button\"\r\n mat-flat-button\r\n (click)=\"collapseAll()\"\r\n style=\"margin-left: 24px\"\r\n >\r\n collapse\r\n </button>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: ["form{margin:16px}.form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}.nr{width:6em}fieldset{border:1px solid silver;border-radius:6px;padding:8px 16px;margin:8px 0}legend{color:silver}th{text-align:left;font-weight:400}#tag-selector{width:8em}.tag-chip{border:2px solid transparent;border-radius:6px}.button-row{display:flex;align-items:center;flex-wrap:wrap}.button-row *{flex:0 0 auto}.hilite{background-color:#ffffe0;border:2px solid gold;border-radius:6px;padding:2px 4px}\n"] }]
|
|
982
|
+
}], ctorParameters: () => [] });
|
|
983
|
+
|
|
984
|
+
/**
|
|
985
|
+
* Thesaurus tree component.
|
|
986
|
+
* This component displays a set of hierarchical thesaurus entries
|
|
987
|
+
* in a tree, provided that each entry marks its hierarchy with
|
|
988
|
+
* dots. For instance, say you have the hierarchy "furniture" -
|
|
989
|
+
* "type" - "color". You might have an entry whose ID is
|
|
990
|
+
* "furniture.table.red", with a sibling "furniture.table.green",
|
|
991
|
+
* and a parent "furniture.table". This parent is there only to
|
|
992
|
+
* provide a label to the parent node, but only leaf nodes can be
|
|
993
|
+
* picked by the user. Whenever one is picked, the entryChange
|
|
994
|
+
* event is emitted. Note that even if you specify a label renderer
|
|
995
|
+
* function, the event always emits the original label.
|
|
996
|
+
*/
|
|
997
|
+
class ThesaurusTreeComponent {
|
|
998
|
+
/**
|
|
999
|
+
* The thesaurus entries.
|
|
1000
|
+
*/
|
|
1001
|
+
entries = input(...(ngDevMode ? [undefined, { debugName: "entries" }] : []));
|
|
1002
|
+
/**
|
|
1003
|
+
* The optional node label rendering function.
|
|
1004
|
+
*/
|
|
1005
|
+
renderLabel = input(renderLabelFromLastColon, ...(ngDevMode ? [{ debugName: "renderLabel" }] : []));
|
|
1006
|
+
/**
|
|
1007
|
+
* Fired when a thesaurus entry is selected.
|
|
1008
|
+
*/
|
|
1009
|
+
entryChange = output();
|
|
1010
|
+
/**
|
|
1011
|
+
* The tree store service, dependent on the current entries and renderLabel.
|
|
1012
|
+
*/
|
|
1013
|
+
service = computed(() => {
|
|
1014
|
+
const entries = this.entries();
|
|
1015
|
+
return new StaticThesPagedTreeStoreService(entries || [], this.renderLabel());
|
|
1016
|
+
}, ...(ngDevMode ? [{ debugName: "service" }] : []));
|
|
1017
|
+
/**
|
|
1018
|
+
* The filter component class to use.
|
|
1019
|
+
*/
|
|
1020
|
+
filterComponent = ThesPagedTreeFilterComponent;
|
|
1021
|
+
onNodePick(node) {
|
|
1022
|
+
// only allow selection of leaf nodes (nodes without children)
|
|
1023
|
+
if (!node.hasChildren) {
|
|
1024
|
+
// find the original entry
|
|
1025
|
+
const entry = this.entries()?.find((e) => e.id === node.key);
|
|
1026
|
+
if (entry) {
|
|
1027
|
+
this.entryChange.emit(entry);
|
|
1028
|
+
}
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: ThesaurusTreeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1032
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.3", type: ThesaurusTreeComponent, isStandalone: true, selector: "cadmus-thesaurus-tree", inputs: { entries: { classPropertyName: "entries", publicName: "entries", isSignal: true, isRequired: false, transformFunction: null }, renderLabel: { classPropertyName: "renderLabel", publicName: "renderLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { entryChange: "entryChange" }, ngImport: i0, template: "<div>\r\n <!-- tree -->\r\n @if (service() && entries()?.length) {\r\n <div class=\"tree-wrapper\">\r\n <cadmus-thes-paged-tree-browser\r\n [service]=\"service()\"\r\n (nodePick)=\"onNodePick($event)\"\r\n />\r\n </div>\r\n }\r\n</div>\r\n", styles: [".th-tree-progress-bar{margin-left:30px}.th-tree-nested-node{padding-left:30px}mat-tree{margin-left:40px}.mat-tree-node{padding:0;background-color:#fff}.mat-nested-tree-node{top:-24px}ul,li{list-style:none;margin:0;padding:0}li.th-tree-container{border-bottom:0}ul{padding-left:40px}li{padding-left:40px;border:1px dotted grey;border-width:0 0 1px 1px;position:relative;top:-24px}li.mat-tree-node,li div{margin:0;position:relative;top:24px}li ul{border-top:1px dotted grey;margin-left:-40px;padding-left:60px}.mat-nested-tree-node:last-child ul{border-left:1px solid white;margin-left:-41px}.mat-mdc-icon-button{z-index:100}span.found-count{margin:0 4px;padding:2px 4px;color:#fff;background-color:#0cc078;border-radius:6px}span.not-found-count{margin:0 4px;padding:2px 4px;color:#fff;background-color:#fb6962;border-radius:6px}.hilite{background-color:#fdfd96}.filter-field{width:100%;margin-bottom:1rem}.tree-container{border:1px solid #e0e0e0;border-radius:4px;overflow:auto;max-height:500px}.tree-wrapper{border:1px solid #e0e0e0;border-radius:4px;overflow:hidden;background:#fff}.no-entries{text-align:center;padding:2rem;color:#666;font-style:italic;border:1px solid #e0e0e0;border-radius:4px;background:#f9f9f9}.no-entries p{margin:0}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "component", type: ThesPagedTreeBrowserComponent, selector: "cadmus-thes-paged-tree-browser", inputs: ["service"], outputs: ["nodePick"] }] });
|
|
1033
|
+
}
|
|
1034
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: ThesaurusTreeComponent, decorators: [{
|
|
1035
|
+
type: Component,
|
|
1036
|
+
args: [{ selector: 'cadmus-thesaurus-tree', imports: [FormsModule, ReactiveFormsModule, ThesPagedTreeBrowserComponent], template: "<div>\r\n <!-- tree -->\r\n @if (service() && entries()?.length) {\r\n <div class=\"tree-wrapper\">\r\n <cadmus-thes-paged-tree-browser\r\n [service]=\"service()\"\r\n (nodePick)=\"onNodePick($event)\"\r\n />\r\n </div>\r\n }\r\n</div>\r\n", styles: [".th-tree-progress-bar{margin-left:30px}.th-tree-nested-node{padding-left:30px}mat-tree{margin-left:40px}.mat-tree-node{padding:0;background-color:#fff}.mat-nested-tree-node{top:-24px}ul,li{list-style:none;margin:0;padding:0}li.th-tree-container{border-bottom:0}ul{padding-left:40px}li{padding-left:40px;border:1px dotted grey;border-width:0 0 1px 1px;position:relative;top:-24px}li.mat-tree-node,li div{margin:0;position:relative;top:24px}li ul{border-top:1px dotted grey;margin-left:-40px;padding-left:60px}.mat-nested-tree-node:last-child ul{border-left:1px solid white;margin-left:-41px}.mat-mdc-icon-button{z-index:100}span.found-count{margin:0 4px;padding:2px 4px;color:#fff;background-color:#0cc078;border-radius:6px}span.not-found-count{margin:0 4px;padding:2px 4px;color:#fff;background-color:#fb6962;border-radius:6px}.hilite{background-color:#fdfd96}.filter-field{width:100%;margin-bottom:1rem}.tree-container{border:1px solid #e0e0e0;border-radius:4px;overflow:auto;max-height:500px}.tree-wrapper{border:1px solid #e0e0e0;border-radius:4px;overflow:hidden;background:#fff}.no-entries{text-align:center;padding:2rem;color:#666;font-style:italic;border:1px solid #e0e0e0;border-radius:4px;background:#f9f9f9}.no-entries p{margin:0}\n"] }]
|
|
1037
|
+
}] });
|
|
1038
|
+
|
|
1039
|
+
/**
|
|
1040
|
+
* The prefix added to custom entries' IDs.
|
|
1041
|
+
*/
|
|
1042
|
+
const CUSTOM_ENTRY_PREFIX = '$';
|
|
1043
|
+
/**
|
|
1044
|
+
* A picker component for thesaurus entries.
|
|
1045
|
+
* This component allows picking one or more entries from a given thesaurus.
|
|
1046
|
+
* In its collapsed state, it shows the picked entries as chips; when
|
|
1047
|
+
* expanded, it shows the thesaurus tree to pick from. Custom entries
|
|
1048
|
+
* (not in the thesaurus) can be optionally allowed.
|
|
1049
|
+
*/
|
|
1050
|
+
class ThesEntriesPickerComponent {
|
|
1051
|
+
/**
|
|
1052
|
+
* The thesaurus entries to pick from (required).
|
|
1053
|
+
*/
|
|
1054
|
+
availableEntries = input.required(...(ngDevMode ? [{ debugName: "availableEntries" }] : []));
|
|
1055
|
+
/**
|
|
1056
|
+
* The picked entries.
|
|
1057
|
+
*/
|
|
1058
|
+
entries = model([], ...(ngDevMode ? [{ debugName: "entries" }] : []));
|
|
1059
|
+
/**
|
|
1060
|
+
* True to show the entries with labels shortened according to
|
|
1061
|
+
* their hierarchy.
|
|
1062
|
+
*/
|
|
1063
|
+
hierarchicLabels = input(false, ...(ngDevMode ? [{ debugName: "hierarchicLabels" }] : []));
|
|
1064
|
+
/**
|
|
1065
|
+
* True to automatically sort entries (disables drag-and-drop).
|
|
1066
|
+
* When false, entries can be manually reordered via drag-and-drop.
|
|
1067
|
+
*/
|
|
1068
|
+
autoSort = input(false, ...(ngDevMode ? [{ debugName: "autoSort" }] : []));
|
|
1069
|
+
/**
|
|
1070
|
+
* True to allow custom values (not in the entries list).
|
|
1071
|
+
*/
|
|
1072
|
+
allowCustom = input(false, ...(ngDevMode ? [{ debugName: "allowCustom" }] : []));
|
|
1073
|
+
/**
|
|
1074
|
+
* The minimum number of entries to pick.
|
|
1075
|
+
*/
|
|
1076
|
+
minEntries = input(0, ...(ngDevMode ? [{ debugName: "minEntries" }] : []));
|
|
1077
|
+
/**
|
|
1078
|
+
* The maximum number of entries to pick (0=unlimited).
|
|
1079
|
+
*/
|
|
1080
|
+
maxEntries = input(0, ...(ngDevMode ? [{ debugName: "maxEntries" }] : []));
|
|
1081
|
+
/**
|
|
1082
|
+
* True when the picker is expanded (showing the entries list).
|
|
1083
|
+
*/
|
|
1084
|
+
expanded = model(false, ...(ngDevMode ? [{ debugName: "expanded" }] : []));
|
|
1085
|
+
/**
|
|
1086
|
+
* The message to show when there are no picked entries.
|
|
1087
|
+
*/
|
|
1088
|
+
emptyMessage = input('no entries', ...(ngDevMode ? [{ debugName: "emptyMessage" }] : []));
|
|
1089
|
+
/**
|
|
1090
|
+
* The number of remaining entries that can be picked (0=unlimited).
|
|
1091
|
+
* This is displayed only if maxEntries > 1.
|
|
1092
|
+
*/
|
|
1093
|
+
remaining = computed(() => {
|
|
1094
|
+
if (this.maxEntries() > 0) {
|
|
1095
|
+
return this.maxEntries() - this.entries().length;
|
|
1096
|
+
}
|
|
1097
|
+
return 0;
|
|
1098
|
+
}, ...(ngDevMode ? [{ debugName: "remaining" }] : []));
|
|
1099
|
+
id;
|
|
1100
|
+
value;
|
|
1101
|
+
form;
|
|
1102
|
+
constructor(formBuilder) {
|
|
1103
|
+
this.id = formBuilder.control('', {
|
|
1104
|
+
validators: [Validators.required, Validators.maxLength(100)],
|
|
1105
|
+
nonNullable: true,
|
|
1106
|
+
});
|
|
1107
|
+
this.value = formBuilder.control('', {
|
|
1108
|
+
validators: [Validators.required, Validators.maxLength(500)],
|
|
1109
|
+
nonNullable: true,
|
|
1110
|
+
});
|
|
1111
|
+
this.form = formBuilder.group({
|
|
1112
|
+
id: this.id,
|
|
1113
|
+
value: this.value,
|
|
1114
|
+
});
|
|
1115
|
+
// if auto-sort is turned on and we have entries, sort them
|
|
1116
|
+
effect(() => {
|
|
1117
|
+
// only track autoSort() changes, not entries()
|
|
1118
|
+
const shouldSort = this.autoSort();
|
|
1119
|
+
if (shouldSort) {
|
|
1120
|
+
// use untracked to read entries without creating a dependency
|
|
1121
|
+
const currentEntries = untracked(() => this.entries());
|
|
1122
|
+
if (currentEntries.length > 1) {
|
|
1123
|
+
const entries = [...currentEntries];
|
|
1124
|
+
this.sortEntries(entries);
|
|
1125
|
+
this.entries.set(entries);
|
|
1126
|
+
}
|
|
1127
|
+
}
|
|
1128
|
+
}, { allowSignalWrites: true });
|
|
1129
|
+
}
|
|
1130
|
+
// need arrow function to use 'this'
|
|
1131
|
+
renderLabel = (label) => {
|
|
1132
|
+
return this.hierarchicLabels() ? renderLabelFromLastColon(label) : label;
|
|
1133
|
+
};
|
|
1134
|
+
sortEntries(entries) {
|
|
1135
|
+
entries.sort((a, b) => {
|
|
1136
|
+
const aIsCustom = a.id?.startsWith(CUSTOM_ENTRY_PREFIX) ?? false;
|
|
1137
|
+
const bIsCustom = b.id?.startsWith(CUSTOM_ENTRY_PREFIX) ?? false;
|
|
1138
|
+
if (aIsCustom !== bIsCustom) {
|
|
1139
|
+
// place custom entries after non-custom ones
|
|
1140
|
+
return aIsCustom ? 1 : -1;
|
|
1141
|
+
}
|
|
1142
|
+
// same kind: sort by label/value
|
|
1143
|
+
return a.value.localeCompare(b.value);
|
|
1144
|
+
});
|
|
1145
|
+
}
|
|
1146
|
+
onEntryChange(entry) {
|
|
1147
|
+
// check if already present
|
|
1148
|
+
if (this.entries().some((e) => e.id === entry.id)) {
|
|
1149
|
+
return;
|
|
1150
|
+
}
|
|
1151
|
+
// check if limit is reached
|
|
1152
|
+
if (this.maxEntries() && this.entries().length >= this.maxEntries()) {
|
|
1153
|
+
return;
|
|
1154
|
+
}
|
|
1155
|
+
const entries = [...this.entries()];
|
|
1156
|
+
entries.push(entry);
|
|
1157
|
+
if (this.autoSort()) {
|
|
1158
|
+
this.sortEntries(entries);
|
|
1159
|
+
}
|
|
1160
|
+
this.entries.set(entries);
|
|
1161
|
+
}
|
|
1162
|
+
addCustomEntry() {
|
|
1163
|
+
if (this.form.invalid) {
|
|
1164
|
+
return;
|
|
1165
|
+
}
|
|
1166
|
+
// create the custom entry
|
|
1167
|
+
const customEntry = {
|
|
1168
|
+
id: CUSTOM_ENTRY_PREFIX + this.id.value,
|
|
1169
|
+
value: this.value.value,
|
|
1170
|
+
};
|
|
1171
|
+
// check if already present
|
|
1172
|
+
if (this.entries().some((e) => e.id === customEntry.id)) {
|
|
1173
|
+
return;
|
|
1174
|
+
}
|
|
1175
|
+
// check if limit is reached
|
|
1176
|
+
if (this.maxEntries() && this.entries().length >= this.maxEntries()) {
|
|
1177
|
+
return;
|
|
1178
|
+
}
|
|
1179
|
+
const entries = [...this.entries()];
|
|
1180
|
+
entries.push(customEntry);
|
|
1181
|
+
if (this.autoSort()) {
|
|
1182
|
+
this.sortEntries(entries);
|
|
1183
|
+
}
|
|
1184
|
+
this.entries.set(entries);
|
|
1185
|
+
this.form.reset();
|
|
1186
|
+
}
|
|
1187
|
+
removeEntry(entry) {
|
|
1188
|
+
const entries = [...this.entries().filter((e) => e.id !== entry.id)];
|
|
1189
|
+
this.entries.set(entries);
|
|
1190
|
+
}
|
|
1191
|
+
clear() {
|
|
1192
|
+
this.entries.set([]);
|
|
1193
|
+
// if min > 0, expand the picker
|
|
1194
|
+
if (this.minEntries() > 0 && !this.expanded()) {
|
|
1195
|
+
setTimeout(() => {
|
|
1196
|
+
this.expanded.set(true);
|
|
1197
|
+
}, 0);
|
|
1198
|
+
}
|
|
1199
|
+
}
|
|
1200
|
+
onDrop(event) {
|
|
1201
|
+
const entries = [...this.entries()];
|
|
1202
|
+
moveItemInArray(entries, event.previousIndex, event.currentIndex);
|
|
1203
|
+
this.entries.set(entries);
|
|
1204
|
+
}
|
|
1205
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: ThesEntriesPickerComponent, deps: [{ token: i1$1.FormBuilder }], target: i0.ɵɵFactoryTarget.Component });
|
|
1206
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.3", type: ThesEntriesPickerComponent, isStandalone: true, selector: "cadmus-thes-entries-picker", inputs: { availableEntries: { classPropertyName: "availableEntries", publicName: "availableEntries", isSignal: true, isRequired: true, transformFunction: null }, entries: { classPropertyName: "entries", publicName: "entries", isSignal: true, isRequired: false, transformFunction: null }, hierarchicLabels: { classPropertyName: "hierarchicLabels", publicName: "hierarchicLabels", isSignal: true, isRequired: false, transformFunction: null }, autoSort: { classPropertyName: "autoSort", publicName: "autoSort", isSignal: true, isRequired: false, transformFunction: null }, allowCustom: { classPropertyName: "allowCustom", publicName: "allowCustom", isSignal: true, isRequired: false, transformFunction: null }, minEntries: { classPropertyName: "minEntries", publicName: "minEntries", isSignal: true, isRequired: false, transformFunction: null }, maxEntries: { classPropertyName: "maxEntries", publicName: "maxEntries", isSignal: true, isRequired: false, transformFunction: null }, expanded: { classPropertyName: "expanded", publicName: "expanded", isSignal: true, isRequired: false, transformFunction: null }, emptyMessage: { classPropertyName: "emptyMessage", publicName: "emptyMessage", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { entries: "entriesChange", expanded: "expandedChange" }, ngImport: i0, template: "<div id=\"container\">\r\n <!-- picked entries -->\r\n <div id=\"picked\" class=\"form-row\">\r\n <!-- count -->\r\n <span class=\"nr\" [class.error]=\"entries().length < minEntries()\">{{\r\n entries().length\r\n }}</span>\r\n <!-- max-->\r\n @if (maxEntries() > 1) {\r\n <span class=\"muted\">/{{ maxEntries() }}</span>\r\n @if (remaining()) {\r\n <span class=\"muted\">: -{{ remaining() }}</span>\r\n } }\r\n <!-- min -->\r\n @if (minEntries()) {\r\n <!-- min with error -->\r\n @if (entries().length < minEntries()) {\r\n <span class=\"error\"> (min {{ minEntries() }})</span>\r\n }\r\n <!-- min without error -->\r\n @else {\r\n <span class=\"muted\"> (min {{ minEntries() }})</span>\r\n } }\r\n <!-- list -->\r\n <mat-chip-listbox\r\n [cdkDropListDisabled]=\"autoSort()\"\r\n cdkDropList\r\n cdkDropListOrientation=\"horizontal\"\r\n (cdkDropListDropped)=\"onDrop($event)\"\r\n class=\"chip-list\"\r\n >\r\n @for (e of entries(); track e.id; let idx = $index) {\r\n <div class=\"chip-wrapper\">\r\n <mat-chip-option\r\n [cdkDragDisabled]=\"autoSort()\"\r\n cdkDrag\r\n [class.error]=\"!allowCustom() && e.id.startsWith('$')\"\r\n >\r\n {{ renderLabel(e.value) }}\r\n <button\r\n type=\"button\"\r\n matChipRemove\r\n (click)=\"removeEntry(e)\"\r\n aria-label=\"Remove entry\"\r\n >\r\n <mat-icon class=\"mat-warn\">cancel</mat-icon>\r\n </button>\r\n </mat-chip-option>\r\n </div>\r\n } @empty {\r\n <span class=\"muted empty-message\">{{ emptyMessage() }}</span>\r\n }\r\n </mat-chip-listbox>\r\n\r\n <!-- clear -->\r\n @if (entries().length > 0) {\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Remove all entries\"\r\n (click)=\"clear()\"\r\n [disabled]=\"entries().length === 0\"\r\n >\r\n <mat-icon class=\"mat-warn\">clear</mat-icon>\r\n </button>\r\n }\r\n <!-- toggler -->\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Toggle picker\"\r\n (click)=\"expanded.set(!expanded())\"\r\n >\r\n @if (expanded()) {\r\n <mat-icon class=\"mat-primary\">publish</mat-icon>\r\n } @if (!expanded()) {\r\n <mat-icon class=\"mat-primary\">get_app</mat-icon>\r\n }\r\n </button>\r\n </div>\r\n\r\n <!-- entries picker -->\r\n <div id=\"picker\">\r\n <mat-expansion-panel\r\n [expanded]=\"expanded()\"\r\n (expandedChange)=\"expanded.set($event)\"\r\n >\r\n <div>\r\n <fieldset>\r\n <legend>available</legend>\r\n <cadmus-thesaurus-tree\r\n [entries]=\"availableEntries()\"\r\n [renderLabel]=\"renderLabel\"\r\n (entryChange)=\"onEntryChange($event)\"\r\n />\r\n </fieldset>\r\n </div>\r\n @if (allowCustom()) {\r\n <div>\r\n <form [formGroup]=\"form\" (submit)=\"addCustomEntry()\">\r\n <fieldset>\r\n <legend>custom</legend>\r\n <div class=\"form-row\">\r\n <mat-form-field>\r\n <input\r\n matInput\r\n type=\"text\"\r\n [formControl]=\"id\"\r\n placeholder=\"ID\"\r\n />\r\n </mat-form-field>\r\n <mat-form-field>\r\n <input\r\n matInput\r\n type=\"text\"\r\n [formControl]=\"value\"\r\n placeholder=\"label\"\r\n />\r\n </mat-form-field>\r\n <button\r\n type=\"submit\"\r\n mat-icon-button\r\n matTooltip=\"Add custom entry\"\r\n [disabled]=\"\r\n !form.valid ||\r\n (maxEntries() > 0 && entries().length >= maxEntries())\r\n \"\r\n >\r\n <mat-icon class=\"mat-primary\">check_circle</mat-icon>\r\n </button>\r\n </div>\r\n </fieldset>\r\n </form>\r\n </div>\r\n }\r\n </mat-expansion-panel>\r\n </div>\r\n</div>\r\n", styles: ["#container{width:100%}.form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}.error{color:#8b0000}.nr{font-weight:700}.muted{color:gray}fieldset{border:1px solid silver;border-radius:8px;padding:8px 16px}.chip-list{display:flex;flex-wrap:wrap;gap:4px;align-items:center;padding:4px}.chip-wrapper{display:inline-flex;position:relative;margin:2px}.chip-list mat-chip-option:not([cdkDragDisabled]){cursor:grab}.chip-list mat-chip-option:not([cdkDragDisabled]):active{cursor:grabbing}.chip-list mat-chip-option[cdkDragDisabled]{cursor:default}.chip-list .empty-message{margin-left:0}.chip-list mat-chip-option.mat-mdc-chip-selected{background-color:inherit}.chip-list mat-chip-option:not(.error).mat-mdc-chip-selected{background-color:#e0e0e0}mat-chip-option.error{background-color:#ffebee!important;border:1px solid darkred}.cdk-drag-preview{opacity:.95;box-shadow:0 8px 20px #0006;transform:rotate(3deg)}.drag-placeholder{width:4px;background:#1976d2;border-radius:2px;height:36px;box-shadow:0 0 8px #1976d299;animation:pulse .5s ease-in-out infinite}@keyframes pulse{0%,to{opacity:.6;transform:scaleY(1)}50%{opacity:1;transform:scaleY(1.1)}}.chip-list .cdk-drag-placeholder{opacity:0;width:4px;min-width:4px}.chip-wrapper{transition:transform .25s cubic-bezier(0,0,.2,1)}.cdk-drop-list-dragging .chip-wrapper:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}.cdk-drop-list-dragging .chip-wrapper{will-change:transform}\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: "directive", type: CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "component", type: MatChipListbox, selector: "mat-chip-listbox", inputs: ["multiple", "aria-orientation", "selectable", "compareWith", "required", "hideSingleSelectionIndicator", "value"], outputs: ["change"] }, { kind: "component", type: MatChipOption, selector: "mat-basic-chip-option, [mat-basic-chip-option], mat-chip-option, [mat-chip-option]", inputs: ["selectable", "selected"], outputs: ["selectionChange"] }, { kind: "directive", type: MatChipRemove, selector: "[matChipRemove]" }, { kind: "component", type: MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: 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: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: ThesaurusTreeComponent, selector: "cadmus-thesaurus-tree", inputs: ["entries", "renderLabel"], outputs: ["entryChange"] }] });
|
|
1207
|
+
}
|
|
1208
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: ThesEntriesPickerComponent, decorators: [{
|
|
1209
|
+
type: Component,
|
|
1210
|
+
args: [{ selector: 'cadmus-thes-entries-picker', imports: [
|
|
1211
|
+
ReactiveFormsModule,
|
|
1212
|
+
CdkDropList,
|
|
1213
|
+
CdkDrag,
|
|
1214
|
+
MatChipListbox,
|
|
1215
|
+
MatChipOption,
|
|
1216
|
+
MatChipRemove,
|
|
1217
|
+
MatExpansionPanel,
|
|
1218
|
+
MatFormField,
|
|
1219
|
+
MatIconButton,
|
|
1220
|
+
MatIcon,
|
|
1221
|
+
MatInput,
|
|
1222
|
+
MatTooltip,
|
|
1223
|
+
ThesaurusTreeComponent,
|
|
1224
|
+
], template: "<div id=\"container\">\r\n <!-- picked entries -->\r\n <div id=\"picked\" class=\"form-row\">\r\n <!-- count -->\r\n <span class=\"nr\" [class.error]=\"entries().length < minEntries()\">{{\r\n entries().length\r\n }}</span>\r\n <!-- max-->\r\n @if (maxEntries() > 1) {\r\n <span class=\"muted\">/{{ maxEntries() }}</span>\r\n @if (remaining()) {\r\n <span class=\"muted\">: -{{ remaining() }}</span>\r\n } }\r\n <!-- min -->\r\n @if (minEntries()) {\r\n <!-- min with error -->\r\n @if (entries().length < minEntries()) {\r\n <span class=\"error\"> (min {{ minEntries() }})</span>\r\n }\r\n <!-- min without error -->\r\n @else {\r\n <span class=\"muted\"> (min {{ minEntries() }})</span>\r\n } }\r\n <!-- list -->\r\n <mat-chip-listbox\r\n [cdkDropListDisabled]=\"autoSort()\"\r\n cdkDropList\r\n cdkDropListOrientation=\"horizontal\"\r\n (cdkDropListDropped)=\"onDrop($event)\"\r\n class=\"chip-list\"\r\n >\r\n @for (e of entries(); track e.id; let idx = $index) {\r\n <div class=\"chip-wrapper\">\r\n <mat-chip-option\r\n [cdkDragDisabled]=\"autoSort()\"\r\n cdkDrag\r\n [class.error]=\"!allowCustom() && e.id.startsWith('$')\"\r\n >\r\n {{ renderLabel(e.value) }}\r\n <button\r\n type=\"button\"\r\n matChipRemove\r\n (click)=\"removeEntry(e)\"\r\n aria-label=\"Remove entry\"\r\n >\r\n <mat-icon class=\"mat-warn\">cancel</mat-icon>\r\n </button>\r\n </mat-chip-option>\r\n </div>\r\n } @empty {\r\n <span class=\"muted empty-message\">{{ emptyMessage() }}</span>\r\n }\r\n </mat-chip-listbox>\r\n\r\n <!-- clear -->\r\n @if (entries().length > 0) {\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Remove all entries\"\r\n (click)=\"clear()\"\r\n [disabled]=\"entries().length === 0\"\r\n >\r\n <mat-icon class=\"mat-warn\">clear</mat-icon>\r\n </button>\r\n }\r\n <!-- toggler -->\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Toggle picker\"\r\n (click)=\"expanded.set(!expanded())\"\r\n >\r\n @if (expanded()) {\r\n <mat-icon class=\"mat-primary\">publish</mat-icon>\r\n } @if (!expanded()) {\r\n <mat-icon class=\"mat-primary\">get_app</mat-icon>\r\n }\r\n </button>\r\n </div>\r\n\r\n <!-- entries picker -->\r\n <div id=\"picker\">\r\n <mat-expansion-panel\r\n [expanded]=\"expanded()\"\r\n (expandedChange)=\"expanded.set($event)\"\r\n >\r\n <div>\r\n <fieldset>\r\n <legend>available</legend>\r\n <cadmus-thesaurus-tree\r\n [entries]=\"availableEntries()\"\r\n [renderLabel]=\"renderLabel\"\r\n (entryChange)=\"onEntryChange($event)\"\r\n />\r\n </fieldset>\r\n </div>\r\n @if (allowCustom()) {\r\n <div>\r\n <form [formGroup]=\"form\" (submit)=\"addCustomEntry()\">\r\n <fieldset>\r\n <legend>custom</legend>\r\n <div class=\"form-row\">\r\n <mat-form-field>\r\n <input\r\n matInput\r\n type=\"text\"\r\n [formControl]=\"id\"\r\n placeholder=\"ID\"\r\n />\r\n </mat-form-field>\r\n <mat-form-field>\r\n <input\r\n matInput\r\n type=\"text\"\r\n [formControl]=\"value\"\r\n placeholder=\"label\"\r\n />\r\n </mat-form-field>\r\n <button\r\n type=\"submit\"\r\n mat-icon-button\r\n matTooltip=\"Add custom entry\"\r\n [disabled]=\"\r\n !form.valid ||\r\n (maxEntries() > 0 && entries().length >= maxEntries())\r\n \"\r\n >\r\n <mat-icon class=\"mat-primary\">check_circle</mat-icon>\r\n </button>\r\n </div>\r\n </fieldset>\r\n </form>\r\n </div>\r\n }\r\n </mat-expansion-panel>\r\n </div>\r\n</div>\r\n", styles: ["#container{width:100%}.form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}.error{color:#8b0000}.nr{font-weight:700}.muted{color:gray}fieldset{border:1px solid silver;border-radius:8px;padding:8px 16px}.chip-list{display:flex;flex-wrap:wrap;gap:4px;align-items:center;padding:4px}.chip-wrapper{display:inline-flex;position:relative;margin:2px}.chip-list mat-chip-option:not([cdkDragDisabled]){cursor:grab}.chip-list mat-chip-option:not([cdkDragDisabled]):active{cursor:grabbing}.chip-list mat-chip-option[cdkDragDisabled]{cursor:default}.chip-list .empty-message{margin-left:0}.chip-list mat-chip-option.mat-mdc-chip-selected{background-color:inherit}.chip-list mat-chip-option:not(.error).mat-mdc-chip-selected{background-color:#e0e0e0}mat-chip-option.error{background-color:#ffebee!important;border:1px solid darkred}.cdk-drag-preview{opacity:.95;box-shadow:0 8px 20px #0006;transform:rotate(3deg)}.drag-placeholder{width:4px;background:#1976d2;border-radius:2px;height:36px;box-shadow:0 0 8px #1976d299;animation:pulse .5s ease-in-out infinite}@keyframes pulse{0%,to{opacity:.6;transform:scaleY(1)}50%{opacity:1;transform:scaleY(1.1)}}.chip-list .cdk-drag-placeholder{opacity:0;width:4px;min-width:4px}.chip-wrapper{transition:transform .25s cubic-bezier(0,0,.2,1)}.cdk-drop-list-dragging .chip-wrapper:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}.cdk-drop-list-dragging .chip-wrapper{will-change:transform}\n"] }]
|
|
1225
|
+
}], ctorParameters: () => [{ type: i1$1.FormBuilder }] });
|
|
1226
|
+
|
|
592
1227
|
var PartBadgeType;
|
|
593
1228
|
(function (PartBadgeType) {
|
|
594
1229
|
PartBadgeType[PartBadgeType["partAndRole"] = 0] = "partAndRole";
|
|
@@ -703,245 +1338,14 @@ class PartBadgeComponent {
|
|
|
703
1338
|
}
|
|
704
1339
|
this.contrastColor.set(this._colorService.getContrastColor(this.color()));
|
|
705
1340
|
}
|
|
706
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.
|
|
707
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.
|
|
1341
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: PartBadgeComponent, deps: [{ token: i1$2.FacetService }, { token: ColorService }], target: i0.ɵɵFactoryTarget.Component });
|
|
1342
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.3", type: PartBadgeComponent, isStandalone: true, selector: "cadmus-part-badge", inputs: { badgeType: { classPropertyName: "badgeType", publicName: "badgeType", isSignal: true, isRequired: false, transformFunction: null }, typeThesaurus: { classPropertyName: "typeThesaurus", publicName: "typeThesaurus", isSignal: true, isRequired: false, transformFunction: null }, facetDefinition: { classPropertyName: "facetDefinition", publicName: "facetDefinition", isSignal: true, isRequired: false, transformFunction: null }, partTypeIds: { classPropertyName: "partTypeIds", publicName: "partTypeIds", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if (badgeType() !== 2) {\r\n<span\r\n class=\"part-badge\"\r\n [style.background-color]=\"color()\"\r\n [style.color]=\"contrastColor()\"\r\n>\r\n {{ typeName() }}\r\n</span>\r\n} @if (badgeType() !== 1 && roleName()) {\r\n<span class=\"role-badge\">\r\n {{ roleName() }}\r\n</span>\r\n}\r\n", styles: [".part-badge{padding:4px;border-radius:6px}.role-badge{padding:4px;border:1px solid silver;border-radius:6px}\n"] });
|
|
708
1343
|
}
|
|
709
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.
|
|
1344
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: PartBadgeComponent, decorators: [{
|
|
710
1345
|
type: Component,
|
|
711
1346
|
args: [{ selector: 'cadmus-part-badge', template: "@if (badgeType() !== 2) {\r\n<span\r\n class=\"part-badge\"\r\n [style.background-color]=\"color()\"\r\n [style.color]=\"contrastColor()\"\r\n>\r\n {{ typeName() }}\r\n</span>\r\n} @if (badgeType() !== 1 && roleName()) {\r\n<span class=\"role-badge\">\r\n {{ roleName() }}\r\n</span>\r\n}\r\n", styles: [".part-badge{padding:4px;border-radius:6px}.role-badge{padding:4px;border:1px solid silver;border-radius:6px}\n"] }]
|
|
712
1347
|
}], ctorParameters: () => [{ type: i1$2.FacetService }, { type: ColorService }] });
|
|
713
1348
|
|
|
714
|
-
/**
|
|
715
|
-
* A label rendering function which removes from a label
|
|
716
|
-
* all the characters past the last colon, trimming the result.
|
|
717
|
-
* This is a typical rendering when dealing with hierarchical
|
|
718
|
-
* thesaurus entries, e.g. "furniture: table: color", where
|
|
719
|
-
* we can shorten the label to just "color", as "furniture"
|
|
720
|
-
* and "table" are its ancestors.
|
|
721
|
-
*/
|
|
722
|
-
const renderLabelFromLastColon = (label) => {
|
|
723
|
-
if (!label) {
|
|
724
|
-
return label;
|
|
725
|
-
}
|
|
726
|
-
const i = label.lastIndexOf(':');
|
|
727
|
-
return i > -1 && i + 1 < label.length ? label.substring(i + 1).trim() : label;
|
|
728
|
-
};
|
|
729
|
-
/**
|
|
730
|
-
* Thesaurus tree component.
|
|
731
|
-
* This component displays a set of hierarchical thesaurus entries
|
|
732
|
-
* in a tree, provided that each entry marks its hierarchy with
|
|
733
|
-
* dots. For instance, say you have the hierarchy "furniture" -
|
|
734
|
-
* "type" - "color". You might have an entry whose ID is
|
|
735
|
-
* "furniture.table.red", with a sibling "furniture.table.green",
|
|
736
|
-
* and a parent "furniture.table". This parent is there only to
|
|
737
|
-
* provide a label to the parent node, but only leaf nodes can be
|
|
738
|
-
* picked by the user. Whenever one is picked, the entryChange
|
|
739
|
-
* event is emitted. Note that even if you specify a label renderer
|
|
740
|
-
* function, the event always emits the original label.
|
|
741
|
-
*/
|
|
742
|
-
class ThesaurusTreeComponent {
|
|
743
|
-
/**
|
|
744
|
-
* The thesaurus entries.
|
|
745
|
-
*/
|
|
746
|
-
entries = input(...(ngDevMode ? [undefined, { debugName: "entries" }] : []));
|
|
747
|
-
/**
|
|
748
|
-
* The label for the root node.
|
|
749
|
-
*/
|
|
750
|
-
rootLabel = input('-', ...(ngDevMode ? [{ debugName: "rootLabel" }] : []));
|
|
751
|
-
/**
|
|
752
|
-
* The optional node label rendering function.
|
|
753
|
-
*/
|
|
754
|
-
renderLabel = input(...(ngDevMode ? [undefined, { debugName: "renderLabel" }] : []));
|
|
755
|
-
/**
|
|
756
|
-
* Fired when a thesaurus entry is selected.
|
|
757
|
-
*/
|
|
758
|
-
entryChange = output();
|
|
759
|
-
root;
|
|
760
|
-
// TODO: use childrenAccessor: https://material.angular.io/cdk/tree/examples
|
|
761
|
-
treeControl;
|
|
762
|
-
treeDataSource;
|
|
763
|
-
filter;
|
|
764
|
-
form;
|
|
765
|
-
foundNodes;
|
|
766
|
-
hasChildren = (index, node) => {
|
|
767
|
-
return node && node.children && node.children.length > 0;
|
|
768
|
-
};
|
|
769
|
-
isRoot = (index, node) => {
|
|
770
|
-
return node && node.id === '@root';
|
|
771
|
-
};
|
|
772
|
-
constructor(formBuilder) {
|
|
773
|
-
// tree
|
|
774
|
-
this.treeControl = new NestedTreeControl((node) => node.children);
|
|
775
|
-
this.treeDataSource = new MatTreeNestedDataSource();
|
|
776
|
-
this.root = { id: '@root', label: '-', children: [] };
|
|
777
|
-
// filter
|
|
778
|
-
this.filter = formBuilder.control(null);
|
|
779
|
-
this.form = formBuilder.group({
|
|
780
|
-
filter: this.filter,
|
|
781
|
-
});
|
|
782
|
-
effect(() => {
|
|
783
|
-
this.initTree(this.entries());
|
|
784
|
-
});
|
|
785
|
-
}
|
|
786
|
-
ngOnInit() {
|
|
787
|
-
this.initTree();
|
|
788
|
-
}
|
|
789
|
-
initTree(entries) {
|
|
790
|
-
this.foundNodes = undefined;
|
|
791
|
-
this.root = this.buildTreeModel(entries || []);
|
|
792
|
-
this.treeDataSource.data = [this.root];
|
|
793
|
-
// https://github.com/angular/components/issues/12469
|
|
794
|
-
this.treeControl.dataNodes = this.treeDataSource.data;
|
|
795
|
-
}
|
|
796
|
-
getLabel(label) {
|
|
797
|
-
const renderer = this.renderLabel();
|
|
798
|
-
return renderer ? renderer(label) : label;
|
|
799
|
-
}
|
|
800
|
-
addNode(entry, separator, root) {
|
|
801
|
-
const components = entry.id.split(separator);
|
|
802
|
-
// walk the tree up to the last existing component
|
|
803
|
-
let i = 0;
|
|
804
|
-
let node = root;
|
|
805
|
-
const idParts = [];
|
|
806
|
-
// for each component:
|
|
807
|
-
while (i < components.length) {
|
|
808
|
-
idParts.push(components[i]);
|
|
809
|
-
// stop walking when the node has no more children
|
|
810
|
-
if (!node.children) {
|
|
811
|
-
break;
|
|
812
|
-
}
|
|
813
|
-
// find target among children
|
|
814
|
-
const targetId = idParts.join(separator);
|
|
815
|
-
const existing = node.children.find((c) => {
|
|
816
|
-
return c.id === targetId;
|
|
817
|
-
});
|
|
818
|
-
if (existing) {
|
|
819
|
-
node = existing;
|
|
820
|
-
i++;
|
|
821
|
-
}
|
|
822
|
-
else {
|
|
823
|
-
break;
|
|
824
|
-
}
|
|
825
|
-
}
|
|
826
|
-
// node is now the last existing component; use it as the ancestor
|
|
827
|
-
// for all the remaining components (starting from i)
|
|
828
|
-
while (i < components.length) {
|
|
829
|
-
if (!node.children) {
|
|
830
|
-
node.children = [];
|
|
831
|
-
}
|
|
832
|
-
const isLast = i + 1 === components.length;
|
|
833
|
-
const label = isLast ? entry.value : components[i];
|
|
834
|
-
const child = {
|
|
835
|
-
label: isLast ? this.getLabel(label) : label,
|
|
836
|
-
id: isLast ? entry.id : idParts.join(separator),
|
|
837
|
-
parent: node,
|
|
838
|
-
children: [],
|
|
839
|
-
};
|
|
840
|
-
if (label !== child.label) {
|
|
841
|
-
child.originalLabel = label;
|
|
842
|
-
}
|
|
843
|
-
node.children.push(child);
|
|
844
|
-
node = child;
|
|
845
|
-
i++;
|
|
846
|
-
}
|
|
847
|
-
}
|
|
848
|
-
/**
|
|
849
|
-
* Build a tree model from a list of name=value pairs,
|
|
850
|
-
* where each value can include one or more components separated by
|
|
851
|
-
* the specified separator.
|
|
852
|
-
* @param entries The entries to add.
|
|
853
|
-
* @param separator string The separator string to use for values.
|
|
854
|
-
*/
|
|
855
|
-
buildTreeModel(entries, separator = '.') {
|
|
856
|
-
const root = {
|
|
857
|
-
id: '@root',
|
|
858
|
-
label: this.rootLabel() || '-',
|
|
859
|
-
};
|
|
860
|
-
if (!entries) {
|
|
861
|
-
return root;
|
|
862
|
-
}
|
|
863
|
-
entries.forEach((entry) => {
|
|
864
|
-
this.addNode(entry, separator, root);
|
|
865
|
-
});
|
|
866
|
-
return root;
|
|
867
|
-
}
|
|
868
|
-
onTreeNodeClick(node) {
|
|
869
|
-
if (node.children && node.children.length > 0) {
|
|
870
|
-
return;
|
|
871
|
-
}
|
|
872
|
-
this.entryChange.emit({
|
|
873
|
-
id: node.id,
|
|
874
|
-
value: node.originalLabel || node.label,
|
|
875
|
-
});
|
|
876
|
-
}
|
|
877
|
-
expandAll() {
|
|
878
|
-
this.treeControl.expandAll();
|
|
879
|
-
}
|
|
880
|
-
collapseAll() {
|
|
881
|
-
this.treeControl.collapseAll();
|
|
882
|
-
}
|
|
883
|
-
expandFromNode(node) {
|
|
884
|
-
while (node.parent) {
|
|
885
|
-
node = node.parent;
|
|
886
|
-
this.treeControl.expand(node);
|
|
887
|
-
}
|
|
888
|
-
}
|
|
889
|
-
expandMatchingNodes(node, filter, found) {
|
|
890
|
-
if (node.label.toLowerCase().includes(filter)) {
|
|
891
|
-
found.push(node);
|
|
892
|
-
this.expandFromNode(node);
|
|
893
|
-
}
|
|
894
|
-
if (node.children?.length) {
|
|
895
|
-
node.children.forEach((child) => {
|
|
896
|
-
this.expandMatchingNodes(child, filter, found);
|
|
897
|
-
});
|
|
898
|
-
}
|
|
899
|
-
}
|
|
900
|
-
find() {
|
|
901
|
-
if (!this.filter.value?.length) {
|
|
902
|
-
return;
|
|
903
|
-
}
|
|
904
|
-
this.treeControl.collapseAll();
|
|
905
|
-
const foundNodes = [];
|
|
906
|
-
this.expandMatchingNodes(this.treeDataSource.data[0], this.filter.value.toLowerCase(), foundNodes);
|
|
907
|
-
this.foundNodes = foundNodes;
|
|
908
|
-
}
|
|
909
|
-
resetFilter() {
|
|
910
|
-
this.filter.reset();
|
|
911
|
-
this.foundNodes = undefined;
|
|
912
|
-
}
|
|
913
|
-
isFoundNode(node) {
|
|
914
|
-
if (!this.foundNodes) {
|
|
915
|
-
return false;
|
|
916
|
-
}
|
|
917
|
-
return this.foundNodes?.length > 0 && this.foundNodes.indexOf(node) > -1;
|
|
918
|
-
}
|
|
919
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: ThesaurusTreeComponent, deps: [{ token: i1$1.FormBuilder }], target: i0.ɵɵFactoryTarget.Component });
|
|
920
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.0", type: ThesaurusTreeComponent, isStandalone: true, selector: "cadmus-thesaurus-tree", inputs: { entries: { classPropertyName: "entries", publicName: "entries", isSignal: true, isRequired: false, transformFunction: null }, rootLabel: { classPropertyName: "rootLabel", publicName: "rootLabel", isSignal: true, isRequired: false, transformFunction: null }, renderLabel: { classPropertyName: "renderLabel", publicName: "renderLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { entryChange: "entryChange" }, ngImport: i0, template: "<form [formGroup]=\"form\" (submit)=\"find()\">\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Expand all\"\r\n (click)=\"expandAll()\"\r\n >\r\n <mat-icon>unfold_more</mat-icon>\r\n </button>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Collapse all\"\r\n (click)=\"collapseAll()\"\r\n >\r\n <mat-icon>unfold_less</mat-icon>\r\n </button>\r\n <mat-form-field>\r\n <mat-label>find</mat-label>\r\n <input matInput [formControl]=\"filter\" />\r\n <button type=\"button\" matSuffix mat-icon-button (click)=\"resetFilter()\">\r\n <mat-icon class=\"mat-warn\">clear</mat-icon>\r\n </button>\r\n </mat-form-field>\r\n @if (foundNodes) {\r\n <span\r\n [class.found-count]=\"foundNodes.length\"\r\n [class.not-found-count]=\"foundNodes.length === 0\"\r\n >{{ foundNodes.length }}</span\r\n >\r\n }\r\n</form>\r\n<mat-tree\r\n [dataSource]=\"treeDataSource\"\r\n [treeControl]=\"treeControl\"\r\n class=\"th-tree\"\r\n>\r\n <!-- leaf node -->\r\n <mat-tree-node *matTreeNodeDef=\"let node\" matTreeNodeToggle>\r\n <li>\r\n <div class=\"mat-tree-node\">\r\n <a\r\n mat-button\r\n (click)=\"onTreeNodeClick(node)\"\r\n [class.hilite]=\"isFoundNode(node)\"\r\n >\r\n {{ node.label }}\r\n </a>\r\n </div>\r\n </li>\r\n </mat-tree-node>\r\n\r\n <!-- root node -->\r\n <mat-nested-tree-node *matTreeNodeDef=\"let node; when: isRoot\">\r\n <div class=\"mat-tree-node\">\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTreeNodeToggle\r\n [attr.aria-label]=\"'Toggle ' + node.label\"\r\n >\r\n <mat-icon>\r\n {{ treeControl.isExpanded(node) ? \"expand_more\" : \"chevron_right\" }}\r\n </mat-icon>\r\n </button>\r\n {{ node.label }}\r\n </div>\r\n <ul class=\"tree-nested-node\">\r\n @if (treeControl.isExpanded(node)) {\r\n <div>\r\n <ng-container matTreeNodeOutlet></ng-container>\r\n </div>\r\n }\r\n </ul>\r\n </mat-nested-tree-node>\r\n\r\n <!-- parent node -->\r\n <mat-nested-tree-node *matTreeNodeDef=\"let node; when: hasChildren\">\r\n <li class=\"tree-container\">\r\n <div class=\"mat-tree-node\">\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTreeNodeToggle\r\n [attr.aria-label]=\"'Toggle ' + node.label\"\r\n >\r\n <mat-icon>\r\n {{ treeControl.isExpanded(node) ? \"expand_more\" : \"chevron_right\" }}\r\n </mat-icon>\r\n </button>\r\n <a mat-button (click)=\"onTreeNodeClick(node)\">\r\n {{ node.label }}\r\n </a>\r\n </div>\r\n <ul class=\"tree-nested-node\">\r\n @if (treeControl.isExpanded(node)) {\r\n <div>\r\n <ng-container matTreeNodeOutlet></ng-container>\r\n </div>\r\n }\r\n </ul>\r\n </li>\r\n </mat-nested-tree-node>\r\n</mat-tree>\r\n", styles: [".th-tree-progress-bar{margin-left:30px}.th-tree-nested-node{padding-left:30px}mat-tree{margin-left:40px}.mat-tree-node{padding:0;background-color:#fff}.mat-nested-tree-node{top:-24px}ul,li{list-style:none;margin:0;padding:0}li.th-tree-container{border-bottom:0}ul{padding-left:40px}li{padding-left:40px;border:1px dotted grey;border-width:0 0 1px 1px;position:relative;top:-24px}li.mat-tree-node,li div{margin:0;position:relative;top:24px}li ul{border-top:1px dotted grey;margin-left:-40px;padding-left:60px}.mat-nested-tree-node:last-child ul{border-left:1px solid white;margin-left:-41px}.mat-mdc-icon-button{z-index:100}span.found-count{margin:0 4px;padding:2px 4px;color:#fff;background-color:#0cc078;border-radius:6px}span.not-found-count{margin:0 4px;padding:2px 4px;color:#fff;background-color:#fb6962;border-radius:6px}.hilite{background-color:#fdfd96}\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: "component", type: MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: MatLabel, selector: "mat-label" }, { kind: "directive", type: 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: "directive", type: MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "component", type: MatTree, selector: "mat-tree", exportAs: ["matTree"] }, { kind: "directive", type: MatTreeNodeDef, selector: "[matTreeNodeDef]", inputs: ["matTreeNodeDefWhen", "matTreeNode"] }, { kind: "directive", type: MatTreeNode, selector: "mat-tree-node", inputs: ["tabIndex", "disabled"], outputs: ["activation", "expandedChange"], exportAs: ["matTreeNode"] }, { kind: "directive", type: MatTreeNodeToggle, selector: "[matTreeNodeToggle]", inputs: ["matTreeNodeToggleRecursive"] }, { kind: "component", type: MatAnchor, 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: "directive", type: MatNestedTreeNode, selector: "mat-nested-tree-node", inputs: ["matNestedTreeNode", "disabled", "tabIndex"], outputs: ["activation", "expandedChange"], exportAs: ["matNestedTreeNode"] }, { kind: "directive", type: MatTreeNodeOutlet, selector: "[matTreeNodeOutlet]" }] });
|
|
921
|
-
}
|
|
922
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: ThesaurusTreeComponent, decorators: [{
|
|
923
|
-
type: Component,
|
|
924
|
-
args: [{ selector: 'cadmus-thesaurus-tree', imports: [
|
|
925
|
-
FormsModule,
|
|
926
|
-
ReactiveFormsModule,
|
|
927
|
-
MatIconButton,
|
|
928
|
-
MatTooltip,
|
|
929
|
-
MatIcon,
|
|
930
|
-
MatFormField,
|
|
931
|
-
MatLabel,
|
|
932
|
-
MatInput,
|
|
933
|
-
MatSuffix,
|
|
934
|
-
NgClass,
|
|
935
|
-
MatTree,
|
|
936
|
-
MatTreeNodeDef,
|
|
937
|
-
MatTreeNode,
|
|
938
|
-
MatTreeNodeToggle,
|
|
939
|
-
MatAnchor,
|
|
940
|
-
MatNestedTreeNode,
|
|
941
|
-
MatTreeNodeOutlet,
|
|
942
|
-
], template: "<form [formGroup]=\"form\" (submit)=\"find()\">\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Expand all\"\r\n (click)=\"expandAll()\"\r\n >\r\n <mat-icon>unfold_more</mat-icon>\r\n </button>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Collapse all\"\r\n (click)=\"collapseAll()\"\r\n >\r\n <mat-icon>unfold_less</mat-icon>\r\n </button>\r\n <mat-form-field>\r\n <mat-label>find</mat-label>\r\n <input matInput [formControl]=\"filter\" />\r\n <button type=\"button\" matSuffix mat-icon-button (click)=\"resetFilter()\">\r\n <mat-icon class=\"mat-warn\">clear</mat-icon>\r\n </button>\r\n </mat-form-field>\r\n @if (foundNodes) {\r\n <span\r\n [class.found-count]=\"foundNodes.length\"\r\n [class.not-found-count]=\"foundNodes.length === 0\"\r\n >{{ foundNodes.length }}</span\r\n >\r\n }\r\n</form>\r\n<mat-tree\r\n [dataSource]=\"treeDataSource\"\r\n [treeControl]=\"treeControl\"\r\n class=\"th-tree\"\r\n>\r\n <!-- leaf node -->\r\n <mat-tree-node *matTreeNodeDef=\"let node\" matTreeNodeToggle>\r\n <li>\r\n <div class=\"mat-tree-node\">\r\n <a\r\n mat-button\r\n (click)=\"onTreeNodeClick(node)\"\r\n [class.hilite]=\"isFoundNode(node)\"\r\n >\r\n {{ node.label }}\r\n </a>\r\n </div>\r\n </li>\r\n </mat-tree-node>\r\n\r\n <!-- root node -->\r\n <mat-nested-tree-node *matTreeNodeDef=\"let node; when: isRoot\">\r\n <div class=\"mat-tree-node\">\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTreeNodeToggle\r\n [attr.aria-label]=\"'Toggle ' + node.label\"\r\n >\r\n <mat-icon>\r\n {{ treeControl.isExpanded(node) ? \"expand_more\" : \"chevron_right\" }}\r\n </mat-icon>\r\n </button>\r\n {{ node.label }}\r\n </div>\r\n <ul class=\"tree-nested-node\">\r\n @if (treeControl.isExpanded(node)) {\r\n <div>\r\n <ng-container matTreeNodeOutlet></ng-container>\r\n </div>\r\n }\r\n </ul>\r\n </mat-nested-tree-node>\r\n\r\n <!-- parent node -->\r\n <mat-nested-tree-node *matTreeNodeDef=\"let node; when: hasChildren\">\r\n <li class=\"tree-container\">\r\n <div class=\"mat-tree-node\">\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTreeNodeToggle\r\n [attr.aria-label]=\"'Toggle ' + node.label\"\r\n >\r\n <mat-icon>\r\n {{ treeControl.isExpanded(node) ? \"expand_more\" : \"chevron_right\" }}\r\n </mat-icon>\r\n </button>\r\n <a mat-button (click)=\"onTreeNodeClick(node)\">\r\n {{ node.label }}\r\n </a>\r\n </div>\r\n <ul class=\"tree-nested-node\">\r\n @if (treeControl.isExpanded(node)) {\r\n <div>\r\n <ng-container matTreeNodeOutlet></ng-container>\r\n </div>\r\n }\r\n </ul>\r\n </li>\r\n </mat-nested-tree-node>\r\n</mat-tree>\r\n", styles: [".th-tree-progress-bar{margin-left:30px}.th-tree-nested-node{padding-left:30px}mat-tree{margin-left:40px}.mat-tree-node{padding:0;background-color:#fff}.mat-nested-tree-node{top:-24px}ul,li{list-style:none;margin:0;padding:0}li.th-tree-container{border-bottom:0}ul{padding-left:40px}li{padding-left:40px;border:1px dotted grey;border-width:0 0 1px 1px;position:relative;top:-24px}li.mat-tree-node,li div{margin:0;position:relative;top:24px}li ul{border-top:1px dotted grey;margin-left:-40px;padding-left:60px}.mat-nested-tree-node:last-child ul{border-left:1px solid white;margin-left:-41px}.mat-mdc-icon-button{z-index:100}span.found-count{margin:0 4px;padding:2px 4px;color:#fff;background-color:#0cc078;border-radius:6px}span.not-found-count{margin:0 4px;padding:2px 4px;color:#fff;background-color:#fb6962;border-radius:6px}.hilite{background-color:#fdfd96}\n"] }]
|
|
943
|
-
}], ctorParameters: () => [{ type: i1$1.FormBuilder }] });
|
|
944
|
-
|
|
945
1349
|
/**
|
|
946
1350
|
* Base class for part/fragment editors dumb components.
|
|
947
1351
|
* The model type is the templated argument T.
|
|
@@ -1173,10 +1577,10 @@ class ModelEditorComponentBase {
|
|
|
1173
1577
|
// the form is no more dirty
|
|
1174
1578
|
this.form.markAsPristine();
|
|
1175
1579
|
}
|
|
1176
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.
|
|
1177
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.
|
|
1580
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: ModelEditorComponentBase, deps: [{ token: i1$3.AuthJwtService }, { token: i1$1.FormBuilder }], target: i0.ɵɵFactoryTarget.Component });
|
|
1581
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.3", type: ModelEditorComponentBase, isStandalone: false, selector: "ng-component", inputs: { identity: { classPropertyName: "identity", publicName: "identity", isSignal: true, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { data: "dataChange", dirtyChange: "dirtyChange", editorClose: "editorClose" }, ngImport: i0, template: '', isInline: true });
|
|
1178
1582
|
}
|
|
1179
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.
|
|
1583
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: ModelEditorComponentBase, decorators: [{
|
|
1180
1584
|
type: Component,
|
|
1181
1585
|
args: [{
|
|
1182
1586
|
template: '',
|
|
@@ -1258,10 +1662,10 @@ class UserRefLookupService {
|
|
|
1258
1662
|
getName(item) {
|
|
1259
1663
|
return item?.user?.userName;
|
|
1260
1664
|
}
|
|
1261
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.
|
|
1262
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.
|
|
1665
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: UserRefLookupService, deps: [{ token: i1$2.UserService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1666
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: UserRefLookupService, providedIn: 'root' });
|
|
1263
1667
|
}
|
|
1264
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.
|
|
1668
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: UserRefLookupService, decorators: [{
|
|
1265
1669
|
type: Injectable,
|
|
1266
1670
|
args: [{
|
|
1267
1671
|
providedIn: 'root',
|
|
@@ -1325,5 +1729,5 @@ const extractPristineChanges = (control) => {
|
|
|
1325
1729
|
* Generated bundle index. Do not edit.
|
|
1326
1730
|
*/
|
|
1327
1731
|
|
|
1328
|
-
export { CloseSaveButtonsComponent, ColorService, CustomValidators, DecoratedTokenTextComponent, ErrorListComponent, FacetBadgeComponent, FlagsBadgeComponent, JsonValidators, LayerHintsComponent, LookupPinComponent, ModelEditorComponentBase, PartBadgeComponent, PartBadgeType, ThesaurusTreeComponent, UserRefLookupService, extractPristineChanges, extractTouchedChanges, getPartIdName, renderLabelFromLastColon };
|
|
1732
|
+
export { CUSTOM_ENTRY_PREFIX, CloseSaveButtonsComponent, ColorService, CustomValidators, DecoratedTokenTextComponent, ErrorListComponent, FacetBadgeComponent, FlagsBadgeComponent, JsonValidators, LayerHintsComponent, LookupPinComponent, ModelEditorComponentBase, PartBadgeComponent, PartBadgeType, StaticThesPagedTreeStoreService, ThesEntriesPickerComponent, ThesPagedTreeBrowserComponent, ThesaurusTreeComponent, UserRefLookupService, extractPristineChanges, extractTouchedChanges, getPartIdName, renderLabelFromLastColon };
|
|
1329
1733
|
//# sourceMappingURL=myrmidon-cadmus-ui.mjs.map
|