@myrmidon/cadmus-ui 15.0.0 → 15.1.0
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 +425 -212
- package/fesm2022/myrmidon-cadmus-ui.mjs.map +1 -1
- package/index.d.ts +132 -57
- package/package.json +1 -1
|
@@ -1,24 +1,32 @@
|
|
|
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 } 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, 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 { MatDialogRef, MAT_DIALOG_DATA, MatDialog } from '@angular/material/dialog';
|
|
27
|
+
import * as i7 from '@angular/material/progress-bar';
|
|
28
|
+
import { MatProgressBarModule } from '@angular/material/progress-bar';
|
|
29
|
+
import { PagedTreeStore, BrowserTreeNodeComponent } from '@myrmidon/paged-data-browsers';
|
|
22
30
|
import { AppRepository } from '@myrmidon/cadmus-state';
|
|
23
31
|
import * as i1$3 from '@myrmidon/auth-jwt-login';
|
|
24
32
|
|
|
@@ -427,7 +435,7 @@ class LayerHintsComponent {
|
|
|
427
435
|
});
|
|
428
436
|
}
|
|
429
437
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: LayerHintsComponent, deps: [{ token: i1$1.FormBuilder }, { token: i2.DialogService }], target: i0.ɵɵFactoryTarget.Component });
|
|
430
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.0", 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 [
|
|
438
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.0", 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
439
|
}
|
|
432
440
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: LayerHintsComponent, decorators: [{
|
|
433
441
|
type: Component,
|
|
@@ -439,7 +447,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.0", ngImpor
|
|
|
439
447
|
MatIcon,
|
|
440
448
|
MatCheckbox,
|
|
441
449
|
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 [
|
|
450
|
+
], 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
451
|
}], ctorParameters: () => [{ type: i1$1.FormBuilder }, { type: i2.DialogService }] });
|
|
444
452
|
|
|
445
453
|
/**
|
|
@@ -589,6 +597,387 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.0", ngImpor
|
|
|
589
597
|
args: ['indexLookupDefinitions']
|
|
590
598
|
}] }] });
|
|
591
599
|
|
|
600
|
+
/**
|
|
601
|
+
* A label rendering function which removes from a label
|
|
602
|
+
* all the characters past the last colon, trimming the result.
|
|
603
|
+
* This is a typical rendering when dealing with hierarchical
|
|
604
|
+
* thesaurus entries, e.g. "furniture: table: color", where
|
|
605
|
+
* we can shorten the label to just "color", as "furniture"
|
|
606
|
+
* and "table" are its ancestors.
|
|
607
|
+
*/
|
|
608
|
+
const renderLabelFromLastColon = (label) => {
|
|
609
|
+
if (!label) {
|
|
610
|
+
return label;
|
|
611
|
+
}
|
|
612
|
+
const i = label.lastIndexOf(':');
|
|
613
|
+
return i > -1 && i + 1 < label.length ? label.substring(i + 1).trim() : label;
|
|
614
|
+
};
|
|
615
|
+
/**
|
|
616
|
+
* A static paged tree store service for thesaurus entries.
|
|
617
|
+
* This builds the tree nodes from the thesaurus entries, assuming
|
|
618
|
+
* that entry IDs are hierarchical and separated by dots (.).
|
|
619
|
+
*/
|
|
620
|
+
class StaticThesPagedTreeStoreService {
|
|
621
|
+
_renderLabel;
|
|
622
|
+
_nodes = [];
|
|
623
|
+
_built = false;
|
|
624
|
+
_entries;
|
|
625
|
+
constructor(entries, _renderLabel) {
|
|
626
|
+
this._renderLabel = _renderLabel;
|
|
627
|
+
// assign a number to each entry for stable IDs
|
|
628
|
+
this._entries = entries.map((entry, index) => ({
|
|
629
|
+
...entry,
|
|
630
|
+
n: index + 1,
|
|
631
|
+
}));
|
|
632
|
+
}
|
|
633
|
+
ensureNodes() {
|
|
634
|
+
// lazily build the nodes only once
|
|
635
|
+
if (this._built) {
|
|
636
|
+
return;
|
|
637
|
+
}
|
|
638
|
+
// map where key is node.id and value is max x value for that parent
|
|
639
|
+
// (0 is used for the virtual root)
|
|
640
|
+
const xMap = new Map();
|
|
641
|
+
for (const entry of this._entries) {
|
|
642
|
+
const hasDot = entry.id.includes('.');
|
|
643
|
+
const keyParts = entry.id.split('.');
|
|
644
|
+
// create the node
|
|
645
|
+
const node = {
|
|
646
|
+
id: entry.n,
|
|
647
|
+
label: hasDot && this._renderLabel
|
|
648
|
+
? this._renderLabel(entry.value)
|
|
649
|
+
: entry.value,
|
|
650
|
+
key: entry.id,
|
|
651
|
+
value: entry.value,
|
|
652
|
+
paging: { pageNumber: 0, pageCount: 0, total: 0 },
|
|
653
|
+
y: hasDot ? keyParts.length : 1,
|
|
654
|
+
x: 0, // will be set later
|
|
655
|
+
parentId: undefined, // will be set later
|
|
656
|
+
hasChildren: false, // will be set later
|
|
657
|
+
};
|
|
658
|
+
// if it has a dot, find its parent and set parentId
|
|
659
|
+
if (hasDot) {
|
|
660
|
+
// build the parent key
|
|
661
|
+
const parentKey = keyParts.slice(0, keyParts.length - 1).join('.');
|
|
662
|
+
// find the parent node with that key
|
|
663
|
+
const parentNode = this._nodes.find((n) => n.key === parentKey);
|
|
664
|
+
// if found, set parentId and x in child and hasChildren in parent
|
|
665
|
+
if (parentNode) {
|
|
666
|
+
node.parentId = parentNode.id;
|
|
667
|
+
parentNode.hasChildren = true;
|
|
668
|
+
if (xMap.has(parentNode.id)) {
|
|
669
|
+
xMap.set(parentNode.id, xMap.get(parentNode.id) + 1);
|
|
670
|
+
}
|
|
671
|
+
else {
|
|
672
|
+
xMap.set(parentNode.id, 1);
|
|
673
|
+
}
|
|
674
|
+
node.x = xMap.get(parentNode.id);
|
|
675
|
+
}
|
|
676
|
+
else {
|
|
677
|
+
// parent not found, treat as root
|
|
678
|
+
if (xMap.has(0)) {
|
|
679
|
+
xMap.set(0, xMap.get(0) + 1);
|
|
680
|
+
}
|
|
681
|
+
else {
|
|
682
|
+
xMap.set(0, 1);
|
|
683
|
+
}
|
|
684
|
+
node.x = xMap.get(0);
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
else {
|
|
688
|
+
// else it's a root node
|
|
689
|
+
if (xMap.has(0)) {
|
|
690
|
+
xMap.set(0, xMap.get(0) + 1);
|
|
691
|
+
}
|
|
692
|
+
else {
|
|
693
|
+
xMap.set(0, 1);
|
|
694
|
+
}
|
|
695
|
+
node.x = xMap.get(0);
|
|
696
|
+
}
|
|
697
|
+
this._nodes.push(node);
|
|
698
|
+
}
|
|
699
|
+
this._built = true;
|
|
700
|
+
}
|
|
701
|
+
/**
|
|
702
|
+
* Get the specified page of nodes.
|
|
703
|
+
* @param filter The filter.
|
|
704
|
+
* @param pageNumber The page number.
|
|
705
|
+
* @param pageSize The page size.
|
|
706
|
+
* @param hasMockRoot Whether the root node is a mock node. Not used here.
|
|
707
|
+
*/
|
|
708
|
+
getNodes(filter, pageNumber, pageSize, hasMockRoot) {
|
|
709
|
+
this.ensureNodes();
|
|
710
|
+
// apply filtering
|
|
711
|
+
let nodes = this._nodes.filter((n) => {
|
|
712
|
+
if (filter.parentId !== undefined && filter.parentId !== null) {
|
|
713
|
+
if (n.parentId !== filter.parentId) {
|
|
714
|
+
return false;
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
else {
|
|
718
|
+
if (n.parentId) {
|
|
719
|
+
return false;
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
if (filter.label) {
|
|
723
|
+
const filterValue = filter.label.toLowerCase();
|
|
724
|
+
if (!n.label.toLowerCase().includes(filterValue)) {
|
|
725
|
+
return false;
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
return true;
|
|
729
|
+
});
|
|
730
|
+
// apply paging
|
|
731
|
+
const startIndex = (pageNumber - 1) * pageSize;
|
|
732
|
+
const endIndex = startIndex + pageSize;
|
|
733
|
+
const pagedNodes = nodes.slice(startIndex, endIndex);
|
|
734
|
+
// page and return
|
|
735
|
+
const paged = nodes.slice((pageNumber - 1) * pageSize, pageNumber * pageSize);
|
|
736
|
+
return of({
|
|
737
|
+
items: paged,
|
|
738
|
+
pageNumber: pageNumber,
|
|
739
|
+
pageSize: pageSize,
|
|
740
|
+
pageCount: Math.ceil(nodes.length / pageSize),
|
|
741
|
+
total: nodes.length,
|
|
742
|
+
});
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
/**
|
|
747
|
+
* A filter to be used for thesaurus paged tree browsers.
|
|
748
|
+
*/
|
|
749
|
+
class ThesPagedTreeFilterComponent {
|
|
750
|
+
dialogRef = inject(MatDialogRef, {
|
|
751
|
+
optional: true,
|
|
752
|
+
});
|
|
753
|
+
data = inject(MAT_DIALOG_DATA, { optional: true });
|
|
754
|
+
/**
|
|
755
|
+
* The filter.
|
|
756
|
+
*/
|
|
757
|
+
filter = model(...(ngDevMode ? [undefined, { debugName: "filter" }] : []));
|
|
758
|
+
wrapped = signal(false, ...(ngDevMode ? [{ debugName: "wrapped" }] : []));
|
|
759
|
+
label;
|
|
760
|
+
form;
|
|
761
|
+
constructor() {
|
|
762
|
+
const formBuilder = inject(FormBuilder);
|
|
763
|
+
const data = this.data;
|
|
764
|
+
// form
|
|
765
|
+
this.label = formBuilder.control(null);
|
|
766
|
+
this.form = formBuilder.group({
|
|
767
|
+
label: this.label,
|
|
768
|
+
});
|
|
769
|
+
// bind dialog data if any
|
|
770
|
+
if (this.dialogRef) {
|
|
771
|
+
this.wrapped.set(true);
|
|
772
|
+
if (data) {
|
|
773
|
+
this.filter.set(data.filter);
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
else {
|
|
777
|
+
this.wrapped.set(false);
|
|
778
|
+
}
|
|
779
|
+
// update form when filter changes
|
|
780
|
+
effect(() => {
|
|
781
|
+
this.updateForm(this.filter());
|
|
782
|
+
});
|
|
783
|
+
}
|
|
784
|
+
ngOnInit() {
|
|
785
|
+
this.updateForm(this.filter());
|
|
786
|
+
}
|
|
787
|
+
updateForm(filter) {
|
|
788
|
+
if (!filter) {
|
|
789
|
+
this.form.reset();
|
|
790
|
+
return;
|
|
791
|
+
}
|
|
792
|
+
this.label.setValue(filter.label ?? null);
|
|
793
|
+
this.form.markAsPristine();
|
|
794
|
+
}
|
|
795
|
+
getFilter() {
|
|
796
|
+
return {
|
|
797
|
+
label: this.label.value ?? undefined,
|
|
798
|
+
};
|
|
799
|
+
}
|
|
800
|
+
reset() {
|
|
801
|
+
this.form.reset();
|
|
802
|
+
this.filter.set(null);
|
|
803
|
+
this.dialogRef?.close(null);
|
|
804
|
+
}
|
|
805
|
+
apply() {
|
|
806
|
+
this.filter.set(this.getFilter());
|
|
807
|
+
this.dialogRef?.close(this.filter());
|
|
808
|
+
}
|
|
809
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: ThesPagedTreeFilterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
810
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.0", 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"] }] });
|
|
811
|
+
}
|
|
812
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: ThesPagedTreeFilterComponent, decorators: [{
|
|
813
|
+
type: Component,
|
|
814
|
+
args: [{ selector: 'cadmus-thes-paged-tree-filter', imports: [
|
|
815
|
+
ReactiveFormsModule,
|
|
816
|
+
MatButtonModule,
|
|
817
|
+
MatFormFieldModule,
|
|
818
|
+
MatInputModule,
|
|
819
|
+
MatIconModule,
|
|
820
|
+
MatTooltipModule,
|
|
821
|
+
], 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"] }]
|
|
822
|
+
}], ctorParameters: () => [] });
|
|
823
|
+
|
|
824
|
+
class ThesPagedTreeBrowserComponent {
|
|
825
|
+
_dialog = inject(MatDialog);
|
|
826
|
+
_sub;
|
|
827
|
+
/**
|
|
828
|
+
* The service to use to load the nodes.
|
|
829
|
+
*/
|
|
830
|
+
service = input(new StaticThesPagedTreeStoreService([], renderLabelFromLastColon), ...(ngDevMode ? [{ debugName: "service" }] : []));
|
|
831
|
+
/**
|
|
832
|
+
* Emitted when a node is clicked.
|
|
833
|
+
*/
|
|
834
|
+
nodePick = output();
|
|
835
|
+
/**
|
|
836
|
+
* The store instance, built from the service.
|
|
837
|
+
*/
|
|
838
|
+
store = computed(() => {
|
|
839
|
+
const service = this.service();
|
|
840
|
+
const store = new PagedTreeStore(service);
|
|
841
|
+
this.nodes$ = store.nodes$;
|
|
842
|
+
this.filter$ = store.filter$;
|
|
843
|
+
return store;
|
|
844
|
+
}, ...(ngDevMode ? [{ debugName: "store" }] : []));
|
|
845
|
+
loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
|
|
846
|
+
debug = new FormControl(false, {
|
|
847
|
+
nonNullable: true,
|
|
848
|
+
});
|
|
849
|
+
hideLoc = new FormControl(false, {
|
|
850
|
+
nonNullable: true,
|
|
851
|
+
});
|
|
852
|
+
hideFilter = new FormControl(false, {
|
|
853
|
+
nonNullable: true,
|
|
854
|
+
});
|
|
855
|
+
filter$;
|
|
856
|
+
nodes$;
|
|
857
|
+
label = new FormControl(null);
|
|
858
|
+
form = new FormGroup({
|
|
859
|
+
label: this.label,
|
|
860
|
+
});
|
|
861
|
+
constructor() {
|
|
862
|
+
const store = this.store();
|
|
863
|
+
this.nodes$ = store.nodes$;
|
|
864
|
+
this.filter$ = store.filter$;
|
|
865
|
+
}
|
|
866
|
+
ngOnInit() {
|
|
867
|
+
if (!this.store().getNodes().length) {
|
|
868
|
+
this.loading.set(true);
|
|
869
|
+
this.store()
|
|
870
|
+
.setFilter({})
|
|
871
|
+
.finally(() => {
|
|
872
|
+
this.loading.set(false);
|
|
873
|
+
console.log('nodes loaded', this.store().getNodes());
|
|
874
|
+
});
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
ngOnDestroy() {
|
|
878
|
+
this._sub?.unsubscribe();
|
|
879
|
+
}
|
|
880
|
+
reset() {
|
|
881
|
+
this.loading.set(true);
|
|
882
|
+
this.store()
|
|
883
|
+
.reset()
|
|
884
|
+
.finally(() => {
|
|
885
|
+
this.loading.set(false);
|
|
886
|
+
});
|
|
887
|
+
}
|
|
888
|
+
onToggleExpanded(node) {
|
|
889
|
+
this.loading.set(true);
|
|
890
|
+
if (node.expanded) {
|
|
891
|
+
this.store()
|
|
892
|
+
.collapse(node.id)
|
|
893
|
+
.finally(() => {
|
|
894
|
+
this.loading.set(false);
|
|
895
|
+
});
|
|
896
|
+
}
|
|
897
|
+
else {
|
|
898
|
+
this.store()
|
|
899
|
+
.expand(node.id)
|
|
900
|
+
.finally(() => {
|
|
901
|
+
this.loading.set(false);
|
|
902
|
+
});
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
onPageChangeRequest(request) {
|
|
906
|
+
this.loading.set(true);
|
|
907
|
+
this.store()
|
|
908
|
+
.changePage(request.node.id, request.paging.pageNumber)
|
|
909
|
+
.finally(() => {
|
|
910
|
+
this.loading.set(false);
|
|
911
|
+
});
|
|
912
|
+
}
|
|
913
|
+
onFilterChange(filter) {
|
|
914
|
+
console.log('filter change', filter);
|
|
915
|
+
this.loading.set(true);
|
|
916
|
+
this.store()
|
|
917
|
+
.setFilter(filter || {})
|
|
918
|
+
.finally(() => {
|
|
919
|
+
this.loading.set(false);
|
|
920
|
+
});
|
|
921
|
+
}
|
|
922
|
+
onEditFilterRequest(node) {
|
|
923
|
+
const dialogRef = this._dialog.open(ThesPagedTreeFilterComponent, {
|
|
924
|
+
data: {
|
|
925
|
+
filter: node.filter,
|
|
926
|
+
},
|
|
927
|
+
});
|
|
928
|
+
dialogRef.afterClosed().subscribe((filter) => {
|
|
929
|
+
// undefined = user dismissed without changes
|
|
930
|
+
if (filter === null) {
|
|
931
|
+
this.store().setNodeFilter(node.id, null);
|
|
932
|
+
}
|
|
933
|
+
else if (filter) {
|
|
934
|
+
this.store().setNodeFilter(node.id, filter);
|
|
935
|
+
}
|
|
936
|
+
});
|
|
937
|
+
}
|
|
938
|
+
expandAll() {
|
|
939
|
+
this.store().expandAll();
|
|
940
|
+
}
|
|
941
|
+
collapseAll() {
|
|
942
|
+
this.store().collapseAll();
|
|
943
|
+
}
|
|
944
|
+
clear() {
|
|
945
|
+
this.store().clear();
|
|
946
|
+
}
|
|
947
|
+
onNodeClick(node) {
|
|
948
|
+
if (!node.hasChildren) {
|
|
949
|
+
this.nodePick.emit(node);
|
|
950
|
+
}
|
|
951
|
+
}
|
|
952
|
+
findLabels() {
|
|
953
|
+
if (!this.label.value) {
|
|
954
|
+
return;
|
|
955
|
+
}
|
|
956
|
+
this.store().findLabels(this.label.value);
|
|
957
|
+
}
|
|
958
|
+
removeHilites() {
|
|
959
|
+
this.store().removeHilites();
|
|
960
|
+
}
|
|
961
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: ThesPagedTreeBrowserComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
962
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.0", 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" }] });
|
|
963
|
+
}
|
|
964
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: ThesPagedTreeBrowserComponent, decorators: [{
|
|
965
|
+
type: Component,
|
|
966
|
+
args: [{ selector: 'cadmus-thes-paged-tree-browser', imports: [
|
|
967
|
+
AsyncPipe,
|
|
968
|
+
ReactiveFormsModule,
|
|
969
|
+
MatButtonModule,
|
|
970
|
+
MatCheckboxModule,
|
|
971
|
+
MatFormFieldModule,
|
|
972
|
+
MatIconModule,
|
|
973
|
+
MatInputModule,
|
|
974
|
+
MatProgressBarModule,
|
|
975
|
+
MatTooltipModule,
|
|
976
|
+
ThesPagedTreeFilterComponent,
|
|
977
|
+
BrowserTreeNodeComponent,
|
|
978
|
+
], 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"] }]
|
|
979
|
+
}], ctorParameters: () => [] });
|
|
980
|
+
|
|
592
981
|
var PartBadgeType;
|
|
593
982
|
(function (PartBadgeType) {
|
|
594
983
|
PartBadgeType[PartBadgeType["partAndRole"] = 0] = "partAndRole";
|
|
@@ -711,21 +1100,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.0", ngImpor
|
|
|
711
1100
|
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
1101
|
}], ctorParameters: () => [{ type: i1$2.FacetService }, { type: ColorService }] });
|
|
713
1102
|
|
|
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
1103
|
/**
|
|
730
1104
|
* Thesaurus tree component.
|
|
731
1105
|
* This component displays a set of hierarchical thesaurus entries
|
|
@@ -744,203 +1118,42 @@ class ThesaurusTreeComponent {
|
|
|
744
1118
|
* The thesaurus entries.
|
|
745
1119
|
*/
|
|
746
1120
|
entries = input(...(ngDevMode ? [undefined, { debugName: "entries" }] : []));
|
|
747
|
-
/**
|
|
748
|
-
* The label for the root node.
|
|
749
|
-
*/
|
|
750
|
-
rootLabel = input('-', ...(ngDevMode ? [{ debugName: "rootLabel" }] : []));
|
|
751
1121
|
/**
|
|
752
1122
|
* The optional node label rendering function.
|
|
753
1123
|
*/
|
|
754
|
-
renderLabel = input(...(ngDevMode ? [
|
|
1124
|
+
renderLabel = input(renderLabelFromLastColon, ...(ngDevMode ? [{ debugName: "renderLabel" }] : []));
|
|
755
1125
|
/**
|
|
756
1126
|
* Fired when a thesaurus entry is selected.
|
|
757
1127
|
*/
|
|
758
1128
|
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
1129
|
/**
|
|
849
|
-
*
|
|
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.
|
|
1130
|
+
* The tree store service, dependent on the current entries and renderLabel.
|
|
854
1131
|
*/
|
|
855
|
-
|
|
856
|
-
const
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
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;
|
|
1132
|
+
service = computed(() => {
|
|
1133
|
+
const entries = this.entries();
|
|
1134
|
+
return new StaticThesPagedTreeStoreService(entries || [], this.renderLabel());
|
|
1135
|
+
}, ...(ngDevMode ? [{ debugName: "service" }] : []));
|
|
1136
|
+
/**
|
|
1137
|
+
* The filter component class to use.
|
|
1138
|
+
*/
|
|
1139
|
+
filterComponent = ThesPagedTreeFilterComponent;
|
|
1140
|
+
onNodePick(node) {
|
|
1141
|
+
// only allow selection of leaf nodes (nodes without children)
|
|
1142
|
+
if (!node.hasChildren) {
|
|
1143
|
+
// find the original entry
|
|
1144
|
+
const entry = this.entries()?.find((e) => e.id === node.key);
|
|
1145
|
+
if (entry) {
|
|
1146
|
+
this.entryChange.emit(entry);
|
|
1147
|
+
}
|
|
916
1148
|
}
|
|
917
|
-
return this.foundNodes?.length > 0 && this.foundNodes.indexOf(node) > -1;
|
|
918
1149
|
}
|
|
919
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: ThesaurusTreeComponent, deps: [
|
|
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 },
|
|
1150
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: ThesaurusTreeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1151
|
+
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 }, 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"] }] });
|
|
921
1152
|
}
|
|
922
1153
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: ThesaurusTreeComponent, decorators: [{
|
|
923
1154
|
type: Component,
|
|
924
|
-
args: [{ selector: 'cadmus-thesaurus-tree', imports: [
|
|
925
|
-
|
|
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 }] });
|
|
1155
|
+
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"] }]
|
|
1156
|
+
}] });
|
|
944
1157
|
|
|
945
1158
|
/**
|
|
946
1159
|
* Base class for part/fragment editors dumb components.
|
|
@@ -1325,5 +1538,5 @@ const extractPristineChanges = (control) => {
|
|
|
1325
1538
|
* Generated bundle index. Do not edit.
|
|
1326
1539
|
*/
|
|
1327
1540
|
|
|
1328
|
-
export { CloseSaveButtonsComponent, ColorService, CustomValidators, DecoratedTokenTextComponent, ErrorListComponent, FacetBadgeComponent, FlagsBadgeComponent, JsonValidators, LayerHintsComponent, LookupPinComponent, ModelEditorComponentBase, PartBadgeComponent, PartBadgeType, ThesaurusTreeComponent, UserRefLookupService, extractPristineChanges, extractTouchedChanges, getPartIdName, renderLabelFromLastColon };
|
|
1541
|
+
export { CloseSaveButtonsComponent, ColorService, CustomValidators, DecoratedTokenTextComponent, ErrorListComponent, FacetBadgeComponent, FlagsBadgeComponent, JsonValidators, LayerHintsComponent, LookupPinComponent, ModelEditorComponentBase, PartBadgeComponent, PartBadgeType, StaticThesPagedTreeStoreService, ThesPagedTreeBrowserComponent, ThesaurusTreeComponent, UserRefLookupService, extractPristineChanges, extractTouchedChanges, getPartIdName, renderLabelFromLastColon };
|
|
1329
1542
|
//# sourceMappingURL=myrmidon-cadmus-ui.mjs.map
|