@myrmidon/cadmus-thesaurus-store 0.0.2 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -109,6 +109,37 @@ An editable paged tree browser for thesaurus entries. Editing happens in memory
|
|
|
109
109
|
|
|
110
110
|
## History
|
|
111
111
|
|
|
112
|
+
### 0.0.4
|
|
113
|
+
|
|
114
|
+
- 2026-01-31: added logging to thesaurus tree browser to diagnose issues in certain scenarios.
|
|
115
|
+
|
|
116
|
+
### 0.0.3
|
|
117
|
+
|
|
118
|
+
- 2026-01-31: fixes to thesaurus browser and editable thesaurus browser. The ThesaurusTreeComponent wasn't updating when data arrived because of an Angular effect timing issue:
|
|
119
|
+
|
|
120
|
+
- The @if (service() && entries()?.length) guard in thesaurus-tree.component.html:3 only creates cadmus-thesaurus-browser once entries has data
|
|
121
|
+
- When the component is created, the effect() in the constructor is scheduled (not run immediately)
|
|
122
|
+
- Angular completes the initial render with empty nodes() signal
|
|
123
|
+
- The effect then runs, loads data, and updates the nodes signal via RxJS subscription callbacks
|
|
124
|
+
- But subscription callbacks run outside Angular's change detection zone, so no re-render is triggered
|
|
125
|
+
- On component close, Angular's final change detection cycle picks up the changes, causing the "flash"
|
|
126
|
+
|
|
127
|
+
Solution: added ChangeDetectorRef.markForCheck() calls in the subscription callbacks (thesaurus-browser.component.ts:121-137) to explicitly notify Angular when signals are updated from async contexts.
|
|
128
|
+
|
|
129
|
+
The fix needed to address:
|
|
130
|
+
|
|
131
|
+
Signal writes inside effect execution: When subscribing to a BehaviorSubject inside an effect(), the subscription callback executes synchronously (BehaviorSubject emits its current value immediately on subscribe). This means signal writes like this.nodes.set(nodes) occur during the effect's execution.
|
|
132
|
+
|
|
133
|
+
Inconsistent markForCheck() calls: The original fix only added markForCheck() in the effect's subscriptions and the initial load's .finally(), but left other async callbacks (expand, collapse, page change, filter change) without it.
|
|
134
|
+
|
|
135
|
+
The issue appears in newer Angular apps because they may use:
|
|
136
|
+
|
|
137
|
+
- Zoneless change detection (Angular 18+)
|
|
138
|
+
- OnPush change detection as default in project configuration
|
|
139
|
+
- Different timing of change detection cycles
|
|
140
|
+
|
|
141
|
+
When RxJS subscription callbacks update Angular signals, they run outside Angular's reactive tracking context. Without explicit notification via markForCheck(), Angular may not know to re-render the component.
|
|
142
|
+
|
|
112
143
|
### 0.0.2
|
|
113
144
|
|
|
114
145
|
- 2026-01-31: fixes to thesaurus browser and editable thesaurus browser replacing `ngOnInit` with `effect` and using signals instead of observables to avoid having side effects in computed signals.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { inject, model, signal, effect, Component, Optional, Inject, input, output, computed, untracked } from '@angular/core';
|
|
2
|
+
import { inject, model, signal, effect, Component, Optional, Inject, ChangeDetectorRef, input, output, computed, untracked } from '@angular/core';
|
|
3
3
|
import * as i1 from '@angular/forms';
|
|
4
4
|
import { FormBuilder, ReactiveFormsModule, FormControl, Validators, FormGroup, FormsModule } from '@angular/forms';
|
|
5
5
|
import * as i1$1 from '@angular/material/dialog';
|
|
@@ -216,6 +216,7 @@ class EditableThesaurusBrowserComponent {
|
|
|
216
216
|
this._dialog = inject(MatDialog);
|
|
217
217
|
this._snackBar = inject(MatSnackBar);
|
|
218
218
|
this._dialogService = inject(DialogService);
|
|
219
|
+
this._cdr = inject(ChangeDetectorRef);
|
|
219
220
|
/**
|
|
220
221
|
* The editable service to use to load the nodes.
|
|
221
222
|
*/
|
|
@@ -260,7 +261,7 @@ class EditableThesaurusBrowserComponent {
|
|
|
260
261
|
this.form = new FormGroup({
|
|
261
262
|
label: this.label,
|
|
262
263
|
});
|
|
263
|
-
// Use effect to react to service/store changes
|
|
264
|
+
// Use effect to react to service/store changes.
|
|
264
265
|
effect(() => {
|
|
265
266
|
const currentStore = this.store();
|
|
266
267
|
const currentService = this.service();
|
|
@@ -273,22 +274,29 @@ class EditableThesaurusBrowserComponent {
|
|
|
273
274
|
this.filter.set({});
|
|
274
275
|
return;
|
|
275
276
|
}
|
|
276
|
-
// Subscribe to store's observables and update signals
|
|
277
|
+
// Subscribe to store's observables and update signals.
|
|
278
|
+
// markForCheck() is required because subscription callbacks run outside
|
|
279
|
+
// Angular's reactive context, and some Angular apps use OnPush change
|
|
280
|
+
// detection or zoneless mode.
|
|
277
281
|
this._nodesSub = currentStore.nodes$.subscribe((nodes) => {
|
|
278
282
|
this.nodes.set(nodes);
|
|
283
|
+
this._cdr.markForCheck();
|
|
279
284
|
});
|
|
280
285
|
this._filterSub = currentStore.filter$.subscribe((filter) => {
|
|
281
286
|
this.filter.set(filter);
|
|
287
|
+
this._cdr.markForCheck();
|
|
282
288
|
});
|
|
283
289
|
// Subscribe to changes state
|
|
284
290
|
this._changesSub = currentService.hasChanges$.subscribe((hasChanges) => {
|
|
285
291
|
this.changesStateChange.emit(hasChanges);
|
|
292
|
+
this._cdr.markForCheck();
|
|
286
293
|
});
|
|
287
294
|
// Load nodes if store is empty
|
|
288
295
|
if (!currentStore.getNodes().length) {
|
|
289
296
|
this.loading.set(true);
|
|
290
297
|
currentStore.setFilter({}).finally(() => {
|
|
291
298
|
this.loading.set(false);
|
|
299
|
+
this._cdr.markForCheck();
|
|
292
300
|
});
|
|
293
301
|
}
|
|
294
302
|
});
|
|
@@ -305,6 +313,7 @@ class EditableThesaurusBrowserComponent {
|
|
|
305
313
|
this.loading.set(true);
|
|
306
314
|
store.reset().finally(() => {
|
|
307
315
|
this.loading.set(false);
|
|
316
|
+
this._cdr.markForCheck();
|
|
308
317
|
});
|
|
309
318
|
}
|
|
310
319
|
onToggleExpanded(node) {
|
|
@@ -315,11 +324,13 @@ class EditableThesaurusBrowserComponent {
|
|
|
315
324
|
if (node.expanded) {
|
|
316
325
|
store.collapse(node.id).finally(() => {
|
|
317
326
|
this.loading.set(false);
|
|
327
|
+
this._cdr.markForCheck();
|
|
318
328
|
});
|
|
319
329
|
}
|
|
320
330
|
else {
|
|
321
331
|
store.expand(node.id).finally(() => {
|
|
322
332
|
this.loading.set(false);
|
|
333
|
+
this._cdr.markForCheck();
|
|
323
334
|
});
|
|
324
335
|
}
|
|
325
336
|
}
|
|
@@ -330,6 +341,7 @@ class EditableThesaurusBrowserComponent {
|
|
|
330
341
|
this.loading.set(true);
|
|
331
342
|
store.changePage(request.node.id, request.paging.pageNumber).finally(() => {
|
|
332
343
|
this.loading.set(false);
|
|
344
|
+
this._cdr.markForCheck();
|
|
333
345
|
});
|
|
334
346
|
}
|
|
335
347
|
onFilterChange(filter) {
|
|
@@ -340,6 +352,7 @@ class EditableThesaurusBrowserComponent {
|
|
|
340
352
|
this.loading.set(true);
|
|
341
353
|
store.setFilter(filter || {}).finally(() => {
|
|
342
354
|
this.loading.set(false);
|
|
355
|
+
this._cdr.markForCheck();
|
|
343
356
|
});
|
|
344
357
|
}
|
|
345
358
|
onEditFilterRequest(node) {
|
|
@@ -710,7 +723,9 @@ class StaticThesaurusPagedTreeStoreService {
|
|
|
710
723
|
* @param hasMockRoot Whether the root node is a mock node. Not used here.
|
|
711
724
|
*/
|
|
712
725
|
getNodes(filter, pageNumber, pageSize, hasMockRoot) {
|
|
726
|
+
console.log('[StaticThesaurusService] getNodes called, entries count:', this._entries.length, 'filter:', filter);
|
|
713
727
|
this.ensureNodes();
|
|
728
|
+
console.log('[StaticThesaurusService] after ensureNodes, _nodes count:', this._nodes.length);
|
|
714
729
|
// apply filtering
|
|
715
730
|
let nodes = this._nodes.filter((n) => {
|
|
716
731
|
// filter by parentId (required by tree structure)
|
|
@@ -735,6 +750,7 @@ class StaticThesaurusPagedTreeStoreService {
|
|
|
735
750
|
});
|
|
736
751
|
// page and return
|
|
737
752
|
const paged = nodes.slice((pageNumber - 1) * pageSize, pageNumber * pageSize);
|
|
753
|
+
console.log('[StaticThesaurusService] getNodes returning', paged.length, 'items (filtered from', nodes.length, 'total root nodes)');
|
|
738
754
|
return of({
|
|
739
755
|
items: paged,
|
|
740
756
|
pageNumber: pageNumber,
|
|
@@ -753,6 +769,7 @@ class StaticThesaurusPagedTreeStoreService {
|
|
|
753
769
|
class ThesaurusBrowserComponent {
|
|
754
770
|
constructor() {
|
|
755
771
|
this._dialog = inject(MatDialog);
|
|
772
|
+
this._cdr = inject(ChangeDetectorRef);
|
|
756
773
|
/**
|
|
757
774
|
* The service to use to load the nodes.
|
|
758
775
|
*/
|
|
@@ -785,24 +802,43 @@ class ThesaurusBrowserComponent {
|
|
|
785
802
|
this.form = new FormGroup({
|
|
786
803
|
label: this.label,
|
|
787
804
|
});
|
|
788
|
-
// Use effect to react to service/store changes
|
|
805
|
+
// Use effect to react to service/store changes.
|
|
789
806
|
effect(() => {
|
|
790
807
|
const currentStore = this.store();
|
|
808
|
+
console.log('[ThesaurusBrowser] effect triggered, store:', currentStore ? 'exists' : 'null');
|
|
791
809
|
// Unsubscribe from previous store's observables
|
|
792
810
|
this._nodesSub?.unsubscribe();
|
|
793
811
|
this._filterSub?.unsubscribe();
|
|
794
|
-
// Subscribe to new store's observables and update signals
|
|
812
|
+
// Subscribe to new store's observables and update signals.
|
|
813
|
+
// markForCheck() is required because subscription callbacks run outside
|
|
814
|
+
// Angular's reactive context, and some Angular apps use OnPush change
|
|
815
|
+
// detection or zoneless mode.
|
|
795
816
|
this._nodesSub = currentStore.nodes$.subscribe((nodes) => {
|
|
817
|
+
console.log('[ThesaurusBrowser] nodes$ emitted, count:', nodes.length, 'nodes:', nodes.map((n) => n.label).slice(0, 3));
|
|
796
818
|
this.nodes.set(nodes);
|
|
819
|
+
console.log('[ThesaurusBrowser] nodes signal set, calling markForCheck');
|
|
820
|
+
this._cdr.markForCheck();
|
|
797
821
|
});
|
|
798
822
|
this._filterSub = currentStore.filter$.subscribe((filter) => {
|
|
823
|
+
console.log('[ThesaurusBrowser] filter$ emitted:', filter);
|
|
799
824
|
this.filter.set(filter);
|
|
825
|
+
this._cdr.markForCheck();
|
|
800
826
|
});
|
|
801
827
|
// Load nodes if store is empty
|
|
802
|
-
|
|
828
|
+
const storeNodes = currentStore.getNodes();
|
|
829
|
+
console.log('[ThesaurusBrowser] store.getNodes() count:', storeNodes.length);
|
|
830
|
+
if (!storeNodes.length) {
|
|
831
|
+
console.log('[ThesaurusBrowser] store is empty, calling setFilter to load');
|
|
803
832
|
this.loading.set(true);
|
|
804
|
-
currentStore
|
|
833
|
+
currentStore
|
|
834
|
+
.setFilter({})
|
|
835
|
+
.then(() => {
|
|
836
|
+
console.log('[ThesaurusBrowser] setFilter resolved, store nodes:', currentStore.getNodes().length);
|
|
837
|
+
})
|
|
838
|
+
.finally(() => {
|
|
839
|
+
console.log('[ThesaurusBrowser] setFilter finally, setting loading=false');
|
|
805
840
|
this.loading.set(false);
|
|
841
|
+
this._cdr.markForCheck();
|
|
806
842
|
});
|
|
807
843
|
}
|
|
808
844
|
});
|
|
@@ -817,6 +853,7 @@ class ThesaurusBrowserComponent {
|
|
|
817
853
|
.reset()
|
|
818
854
|
.finally(() => {
|
|
819
855
|
this.loading.set(false);
|
|
856
|
+
this._cdr.markForCheck();
|
|
820
857
|
});
|
|
821
858
|
}
|
|
822
859
|
onToggleExpanded(node) {
|
|
@@ -826,6 +863,7 @@ class ThesaurusBrowserComponent {
|
|
|
826
863
|
.collapse(node.id)
|
|
827
864
|
.finally(() => {
|
|
828
865
|
this.loading.set(false);
|
|
866
|
+
this._cdr.markForCheck();
|
|
829
867
|
});
|
|
830
868
|
}
|
|
831
869
|
else {
|
|
@@ -833,6 +871,7 @@ class ThesaurusBrowserComponent {
|
|
|
833
871
|
.expand(node.id)
|
|
834
872
|
.finally(() => {
|
|
835
873
|
this.loading.set(false);
|
|
874
|
+
this._cdr.markForCheck();
|
|
836
875
|
});
|
|
837
876
|
}
|
|
838
877
|
}
|
|
@@ -842,6 +881,7 @@ class ThesaurusBrowserComponent {
|
|
|
842
881
|
.changePage(request.node.id, request.paging.pageNumber)
|
|
843
882
|
.finally(() => {
|
|
844
883
|
this.loading.set(false);
|
|
884
|
+
this._cdr.markForCheck();
|
|
845
885
|
});
|
|
846
886
|
}
|
|
847
887
|
onFilterChange(filter) {
|
|
@@ -851,6 +891,7 @@ class ThesaurusBrowserComponent {
|
|
|
851
891
|
.setFilter(filter || {})
|
|
852
892
|
.finally(() => {
|
|
853
893
|
this.loading.set(false);
|
|
894
|
+
this._cdr.markForCheck();
|
|
854
895
|
});
|
|
855
896
|
}
|
|
856
897
|
onEditFilterRequest(node) {
|
|
@@ -944,12 +985,29 @@ class ThesaurusTreeComponent {
|
|
|
944
985
|
*/
|
|
945
986
|
this.service = computed(() => {
|
|
946
987
|
const entries = this.entries();
|
|
988
|
+
console.log('[ThesaurusTree] service computed, entries count:', entries?.length ?? 0);
|
|
947
989
|
return new StaticThesaurusPagedTreeStoreService(entries || [], this.renderLabel());
|
|
948
990
|
}, ...(ngDevMode ? [{ debugName: "service" }] : []));
|
|
991
|
+
/**
|
|
992
|
+
* Debug: tracks when the template condition would show the browser.
|
|
993
|
+
*/
|
|
994
|
+
this.shouldShowBrowser = computed(() => {
|
|
995
|
+
const svc = this.service();
|
|
996
|
+
const entries = this.entries();
|
|
997
|
+
const result = !!(svc && entries?.length);
|
|
998
|
+
console.log('[ThesaurusTree] shouldShowBrowser computed:', result, '(service:', !!svc, ', entries:', entries?.length ?? 0, ')');
|
|
999
|
+
return result;
|
|
1000
|
+
}, ...(ngDevMode ? [{ debugName: "shouldShowBrowser" }] : []));
|
|
949
1001
|
/**
|
|
950
1002
|
* The filter component class to use.
|
|
951
1003
|
*/
|
|
952
1004
|
this.filterComponent = ThesaurusPagedTreeFilterComponent;
|
|
1005
|
+
// Debug effect to trace when entries input changes
|
|
1006
|
+
effect(() => {
|
|
1007
|
+
const entries = this.entries();
|
|
1008
|
+
const svc = this.service();
|
|
1009
|
+
console.log('[ThesaurusTree] effect: entries changed, count:', entries?.length ?? 0, 'service:', svc ? 'exists' : 'null');
|
|
1010
|
+
});
|
|
953
1011
|
}
|
|
954
1012
|
onNodePick(node) {
|
|
955
1013
|
// only allow selection of leaf nodes (nodes without children)
|
|
@@ -962,12 +1020,12 @@ class ThesaurusTreeComponent {
|
|
|
962
1020
|
}
|
|
963
1021
|
}
|
|
964
1022
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: ThesaurusTreeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
965
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.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 (
|
|
1023
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.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 (shouldShowBrowser()) {\r\n <div class=\"tree-wrapper\">\r\n <cadmus-thesaurus-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: ThesaurusBrowserComponent, selector: "cadmus-thesaurus-browser", inputs: ["service"], outputs: ["nodePick"] }] }); }
|
|
966
1024
|
}
|
|
967
1025
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: ThesaurusTreeComponent, decorators: [{
|
|
968
1026
|
type: Component,
|
|
969
|
-
args: [{ selector: 'cadmus-thesaurus-tree', imports: [FormsModule, ReactiveFormsModule, ThesaurusBrowserComponent], template: "<div>\r\n <!-- tree -->\r\n @if (
|
|
970
|
-
}], propDecorators: { entries: [{ type: i0.Input, args: [{ isSignal: true, alias: "entries", required: false }] }], renderLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "renderLabel", required: false }] }], entryChange: [{ type: i0.Output, args: ["entryChange"] }] } });
|
|
1027
|
+
args: [{ selector: 'cadmus-thesaurus-tree', imports: [FormsModule, ReactiveFormsModule, ThesaurusBrowserComponent], template: "<div>\r\n <!-- tree -->\r\n @if (shouldShowBrowser()) {\r\n <div class=\"tree-wrapper\">\r\n <cadmus-thesaurus-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"] }]
|
|
1028
|
+
}], ctorParameters: () => [], propDecorators: { entries: [{ type: i0.Input, args: [{ isSignal: true, alias: "entries", required: false }] }], renderLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "renderLabel", required: false }] }], entryChange: [{ type: i0.Output, args: ["entryChange"] }] } });
|
|
971
1029
|
|
|
972
1030
|
/**
|
|
973
1031
|
* The prefix added to custom entries' IDs.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"myrmidon-cadmus-thesaurus-store.mjs","sources":["../../../../projects/myrmidon/cadmus-thesaurus-store/src/lib/components/thesaurus-paged-tree-filter/thesaurus-paged-tree-filter.component.ts","../../../../projects/myrmidon/cadmus-thesaurus-store/src/lib/components/thesaurus-paged-tree-filter/thesaurus-paged-tree-filter.component.html","../../../../projects/myrmidon/cadmus-thesaurus-store/src/lib/components/thesaurus-entry-editor/thesaurus-entry-editor.component.ts","../../../../projects/myrmidon/cadmus-thesaurus-store/src/lib/components/thesaurus-entry-editor/thesaurus-entry-editor.component.html","../../../../projects/myrmidon/cadmus-thesaurus-store/src/lib/components/editable-thesaurus-browser/editable-thesaurus-browser.component.ts","../../../../projects/myrmidon/cadmus-thesaurus-store/src/lib/components/editable-thesaurus-browser/editable-thesaurus-browser.component.html","../../../../projects/myrmidon/cadmus-thesaurus-store/src/lib/services/static-thesaurus-paged-tree-store.service.ts","../../../../projects/myrmidon/cadmus-thesaurus-store/src/lib/components/thesaurus-browser/thesaurus-browser.component.ts","../../../../projects/myrmidon/cadmus-thesaurus-store/src/lib/components/thesaurus-browser/thesaurus-browser.component.html","../../../../projects/myrmidon/cadmus-thesaurus-store/src/lib/components/thesaurus-tree/thesaurus-tree.component.ts","../../../../projects/myrmidon/cadmus-thesaurus-store/src/lib/components/thesaurus-tree/thesaurus-tree.component.html","../../../../projects/myrmidon/cadmus-thesaurus-store/src/lib/components/thesaurus-entries-picker/thesaurus-entries-picker.component.ts","../../../../projects/myrmidon/cadmus-thesaurus-store/src/lib/components/thesaurus-entries-picker/thesaurus-entries-picker.component.html","../../../../projects/myrmidon/cadmus-thesaurus-store/src/lib/services/editable-static-thesaurus-paged-tree-store.service.ts","../../../../projects/myrmidon/cadmus-thesaurus-store/src/public-api.ts","../../../../projects/myrmidon/cadmus-thesaurus-store/src/myrmidon-cadmus-thesaurus-store.ts"],"sourcesContent":["import {\r\n Component,\r\n effect,\r\n inject,\r\n model,\r\n OnInit,\r\n signal,\r\n} from '@angular/core';\r\nimport {\r\n FormBuilder,\r\n FormControl,\r\n FormGroup,\r\n ReactiveFormsModule,\r\n} from '@angular/forms';\r\nimport { MatButtonModule } from '@angular/material/button';\r\nimport { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';\r\nimport { MatFormFieldModule } from '@angular/material/form-field';\r\nimport { MatIconModule } from '@angular/material/icon';\r\nimport { MatInputModule } from '@angular/material/input';\r\nimport { MatTooltipModule } from '@angular/material/tooltip';\r\n\r\nimport { ThesaurusEntryNodeFilter } from '../../services/static-thesaurus-paged-tree-store.service';\r\n\r\n/**\r\n * A filter to be used for thesaurus paged tree browsers.\r\n */\r\n@Component({\r\n selector: 'cadmus-thesaurus-paged-tree-filter',\r\n imports: [\r\n ReactiveFormsModule,\r\n MatButtonModule,\r\n MatFormFieldModule,\r\n MatInputModule,\r\n MatIconModule,\r\n MatTooltipModule,\r\n ],\r\n templateUrl: './thesaurus-paged-tree-filter.component.html',\r\n styleUrl: './thesaurus-paged-tree-filter.component.css',\r\n})\r\nexport class ThesaurusPagedTreeFilterComponent implements OnInit {\r\n public readonly dialogRef = inject<\r\n MatDialogRef<ThesaurusPagedTreeFilterComponent>\r\n >(MatDialogRef, {\r\n optional: true,\r\n });\r\n public readonly data = inject(MAT_DIALOG_DATA, { optional: true });\r\n\r\n /**\r\n * The filter.\r\n */\r\n public readonly filter = model<ThesaurusEntryNodeFilter | null | undefined>();\r\n\r\n public readonly wrapped = signal<boolean>(false);\r\n\r\n public label: FormControl<string | null>;\r\n public form: FormGroup;\r\n\r\n constructor() {\r\n const formBuilder = inject(FormBuilder);\r\n const data = this.data;\r\n\r\n // form\r\n this.label = formBuilder.control<string | null>(null);\r\n this.form = formBuilder.group({\r\n label: this.label,\r\n });\r\n // bind dialog data if any\r\n if (this.dialogRef) {\r\n this.wrapped.set(true);\r\n if (data) {\r\n this.filter.set(data.filter);\r\n }\r\n } else {\r\n this.wrapped.set(false);\r\n }\r\n\r\n // update form when filter changes\r\n effect(() => {\r\n this.updateForm(this.filter());\r\n });\r\n }\r\n\r\n public ngOnInit(): void {\r\n this.updateForm(this.filter());\r\n }\r\n\r\n private updateForm(filter?: ThesaurusEntryNodeFilter | null): void {\r\n if (!filter) {\r\n this.form.reset();\r\n return;\r\n }\r\n this.label.setValue(filter.label ?? null);\r\n this.form.markAsPristine();\r\n }\r\n\r\n private getFilter(): ThesaurusEntryNodeFilter {\r\n return {\r\n label: this.label.value ?? undefined,\r\n };\r\n }\r\n\r\n public reset(): void {\r\n this.form.reset();\r\n this.filter.set(null);\r\n this.dialogRef?.close(null);\r\n }\r\n\r\n public apply(): void {\r\n const filter = this.getFilter();\r\n this.filter.set(filter);\r\n this.dialogRef?.close(filter);\r\n }\r\n}\r\n","<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\r\n <!-- buttons -->\r\n <div class=\"button-row\">\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Reset\"\r\n (click)=\"reset()\"\r\n >\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 </div>\r\n</form>\r\n","import { Component, Inject, input, model, Optional } from '@angular/core';\r\nimport {\r\n FormBuilder,\r\n FormControl,\r\n FormGroup,\r\n ReactiveFormsModule,\r\n Validators,\r\n AbstractControl,\r\n ValidationErrors,\r\n} from '@angular/forms';\r\nimport { MatButtonModule } from '@angular/material/button';\r\nimport {\r\n MatDialogRef,\r\n MAT_DIALOG_DATA,\r\n MatDialogConfig,\r\n} from '@angular/material/dialog';\r\nimport { MatFormFieldModule } from '@angular/material/form-field';\r\nimport { MatIconModule } from '@angular/material/icon';\r\nimport { MatInputModule } from '@angular/material/input';\r\nimport { MatTooltipModule } from '@angular/material/tooltip';\r\n\r\n/**\r\n * An edited thesaurus entry.\r\n */\r\nexport interface EditedThesEntry {\r\n id: string;\r\n value: string;\r\n /**\r\n * True if this entry belongs to a hierarchical thesaurus. When this is true,\r\n * and parentId is set, the parentId field will be used as the prefix for the\r\n * id field when creating a new entry.\r\n */\r\n hierarchical?: boolean;\r\n /**\r\n * The ID of the parent entry, if any.\r\n */\r\n parentId?: string;\r\n /**\r\n * If true, the id field is read-only. This is used when editing an existing\r\n * entry so you cannot change its ID.\r\n */\r\n idLocked?: boolean;\r\n /**\r\n * Function used to check if the given ID exists. This is used when\r\n * creating a new entry to ensure it does not duplicate an existing ID.\r\n * @param id The ID to check.\r\n * @returns True if exists.\r\n */\r\n idExists?: (id: string) => boolean;\r\n}\r\n\r\nexport interface PayloadMatDialogConfig<T> extends MatDialogConfig {\r\n payload?: T;\r\n}\r\n\r\n/**\r\n * A dialog component to edit a thesaurus entry.\r\n */\r\n@Component({\r\n selector: 'cadmus-thesaurus-entry-editor',\r\n imports: [\r\n ReactiveFormsModule,\r\n MatButtonModule,\r\n MatFormFieldModule,\r\n MatIconModule,\r\n MatInputModule,\r\n MatTooltipModule,\r\n ],\r\n templateUrl: './thesaurus-entry-editor.component.html',\r\n styleUrl: './thesaurus-entry-editor.component.scss',\r\n})\r\nexport class ThesEntryEditorComponent {\r\n public readonly entry = model<EditedThesEntry | undefined>();\r\n public wrapped = false;\r\n\r\n public id: FormControl<string>;\r\n public value: FormControl<string>;\r\n public form: FormGroup;\r\n\r\n constructor(\r\n @Optional()\r\n public dialogRef: MatDialogRef<ThesEntryEditorComponent>,\r\n @Optional()\r\n @Inject(MAT_DIALOG_DATA)\r\n public data: PayloadMatDialogConfig<EditedThesEntry>,\r\n formBuilder: FormBuilder\r\n ) {\r\n // bind to data properties if any\r\n if (data) {\r\n this.entry.set(data as EditedThesEntry);\r\n this.wrapped = true;\r\n }\r\n\r\n // custom validator for ID existence\r\n const idExistsValidator = (\r\n control: AbstractControl\r\n ): ValidationErrors | null => {\r\n const entry = this.entry();\r\n if (!entry || entry.idLocked || !entry.idExists) {\r\n return null;\r\n }\r\n const id = control.value?.trim();\r\n if (!id) {\r\n return null;\r\n }\r\n // if editing, allow the current id (do not check against itself)\r\n if (entry.id === id) {\r\n return null;\r\n }\r\n return entry.idExists(id) ? { idExists: true } : null;\r\n };\r\n\r\n // custom validator for hierarchical ID prefix\r\n const hierarchicalIdValidator = (\r\n control: AbstractControl\r\n ): ValidationErrors | null => {\r\n const entry = this.entry();\r\n if (!entry || entry.idLocked || !entry.hierarchical || !entry.parentId) {\r\n return null;\r\n }\r\n const id = control.value?.trim();\r\n if (!id) {\r\n return null;\r\n }\r\n const prefix = entry.parentId + '.';\r\n if (!id.startsWith(prefix) || id.length <= prefix.length) {\r\n return { hierarchicalPrefix: { requiredPrefix: prefix } };\r\n }\r\n return null;\r\n };\r\n\r\n // form controls\r\n this.id = new FormControl<string>((data as EditedThesEntry)?.id || '', {\r\n nonNullable: true,\r\n validators: [\r\n Validators.required,\r\n Validators.maxLength(300),\r\n idExistsValidator,\r\n hierarchicalIdValidator,\r\n ],\r\n });\r\n this.value = new FormControl<string>(\r\n (data as EditedThesEntry)?.value || '',\r\n {\r\n nonNullable: true,\r\n validators: [Validators.required, Validators.maxLength(500)],\r\n }\r\n );\r\n this.form = formBuilder.group({\r\n id: this.id,\r\n value: this.value,\r\n });\r\n }\r\n\r\n cancel(): void {\r\n this.dialogRef?.close();\r\n }\r\n\r\n save(): void {\r\n if (this.form.invalid) {\r\n return;\r\n }\r\n const old = this.entry()!;\r\n\r\n // save data and close the dialog\r\n this.dialogRef?.close({\r\n id: old.idLocked ? old.id : this.id.value?.trim(),\r\n value: this.value.value?.trim(),\r\n } as EditedThesEntry);\r\n }\r\n}\r\n","<form [formGroup]=\"form\" (submit)=\"save()\" [class.wrapped]=\"wrapped\">\r\n <fieldset>\r\n <legend>entry</legend>\r\n <div class=\"form-row\">\r\n <!-- id -->\r\n @if (entry()!.idLocked) {\r\n <span class=\"readonly\">{{ entry()!.id }}</span>\r\n } @else {\r\n <mat-form-field>\r\n <mat-label>ID</mat-label>\r\n <input matInput [formControl]=\"id\" />\r\n @if ($any(id).errors?.required && (id.dirty || id.touched)) {\r\n <mat-error>ID required</mat-error>\r\n } @if ($any(id).errors?.maxLength && (id.dirty || id.touched)) {\r\n <mat-error>ID too long</mat-error>\r\n } @if ($any(id).errors?.idExists && (id.dirty || id.touched)) {\r\n <mat-error>ID already exists</mat-error>\r\n } @if ($any(id).errors?.requiredPrefix && (id.dirty || id.touched)) {\r\n <mat-error>ID must start with \"{{ entry()!.parentId }}.\"</mat-error>\r\n }\r\n <!-- hint -->\r\n @if (entry()?.parentId) {\r\n <mat-hint>parent: {{ entry()!.parentId }}</mat-hint>\r\n }\r\n </mat-form-field>\r\n }\r\n <!-- value -->\r\n <mat-form-field>\r\n <mat-label>value</mat-label>\r\n <input matInput [formControl]=\"value\" />\r\n @if ($any(value).errors?.required && (value.dirty || value.touched)) {\r\n <mat-error>value required</mat-error>\r\n } @if ($any(value).errors?.maxLength && (value.dirty || value.touched))\r\n {\r\n <mat-error>value too long</mat-error>\r\n }\r\n </mat-form-field>\r\n </div>\r\n <!-- buttons -->\r\n <div>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Discard changes\"\r\n (click)=\"cancel()\"\r\n >\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=\"Accept changes\"\r\n [disabled]=\"form.invalid || form.pristine\"\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","import {\r\n Component,\r\n OnDestroy,\r\n computed,\r\n effect,\r\n inject,\r\n input,\r\n output,\r\n signal,\r\n} from '@angular/core';\r\nimport { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';\r\nimport { Subscription } from 'rxjs';\r\n\r\nimport { MatDialog } from '@angular/material/dialog';\r\nimport { MatProgressBarModule } from '@angular/material/progress-bar';\r\nimport { MatButtonModule } from '@angular/material/button';\r\nimport { MatCheckboxModule } from '@angular/material/checkbox';\r\nimport { MatIconModule } from '@angular/material/icon';\r\nimport { MatTooltipModule } from '@angular/material/tooltip';\r\nimport { MatInputModule } from '@angular/material/input';\r\nimport { MatFormFieldModule } from '@angular/material/form-field';\r\nimport { MatMenuModule } from '@angular/material/menu';\r\nimport { MatSnackBar } from '@angular/material/snack-bar';\r\n\r\nimport { DialogService } from '@myrmidon/ngx-mat-tools';\r\nimport {\r\n BrowserTreeNodeComponent,\r\n PagedTreeStore,\r\n PageChangeRequest,\r\n} from '@myrmidon/paged-data-browsers';\r\n\r\nimport { ThesaurusPagedTreeFilterComponent } from '../thesaurus-paged-tree-filter/thesaurus-paged-tree-filter.component';\r\nimport {\r\n ThesaurusEntryNodeFilter,\r\n ThesaurusEntryPagedTreeNode,\r\n} from '../../services/static-thesaurus-paged-tree-store.service';\r\nimport {\r\n EditedThesEntry,\r\n ThesEntryEditorComponent,\r\n} from '../thesaurus-entry-editor/thesaurus-entry-editor.component';\r\nimport { EditableStaticThesaurusPagedTreeStoreService } from '../../services/editable-static-thesaurus-paged-tree-store.service';\r\n\r\n/**\r\n * An editable paged tree browser for thesaurus entries. Editing happens in memory\r\n * and when complete, the changes can be committed to the underlying data store\r\n * via the EditableStaticThesaurusPagedTreeStoreService.\r\n */\r\n@Component({\r\n selector: 'cadmus-editable-thesaurus-browser',\r\n imports: [\r\n ReactiveFormsModule,\r\n MatButtonModule,\r\n MatCheckboxModule,\r\n MatFormFieldModule,\r\n MatIconModule,\r\n MatInputModule,\r\n MatMenuModule,\r\n MatProgressBarModule,\r\n MatTooltipModule,\r\n ThesaurusPagedTreeFilterComponent,\r\n BrowserTreeNodeComponent,\r\n ],\r\n templateUrl: './editable-thesaurus-browser.component.html',\r\n styleUrls: ['./editable-thesaurus-browser.component.scss'],\r\n})\r\nexport class EditableThesaurusBrowserComponent implements OnDestroy {\r\n private _dialog = inject(MatDialog);\r\n private _snackBar = inject(MatSnackBar);\r\n private _dialogService = inject(DialogService);\r\n private _nodesSub?: Subscription;\r\n private _filterSub?: Subscription;\r\n private _changesSub?: Subscription;\r\n\r\n /**\r\n * The editable service to use to load the nodes.\r\n */\r\n public readonly service =\r\n input<EditableStaticThesaurusPagedTreeStoreService>();\r\n\r\n /**\r\n * True to show the tree root nodes filter.\r\n */\r\n public readonly hasRootFilter = input<boolean>(false);\r\n\r\n /**\r\n * Emitted when a node is clicked.\r\n */\r\n public readonly nodePick = output<ThesaurusEntryPagedTreeNode>();\r\n\r\n /**\r\n * Emitted when the changes state changes.\r\n */\r\n public readonly changesStateChange = output<boolean>();\r\n\r\n /**\r\n * The store instance, built from the service.\r\n */\r\n public readonly store = computed(() => {\r\n const service = this.service();\r\n if (!service) {\r\n return null;\r\n }\r\n return new PagedTreeStore<\r\n ThesaurusEntryPagedTreeNode,\r\n ThesaurusEntryNodeFilter\r\n >(service);\r\n });\r\n\r\n public readonly loading = signal<boolean>(false);\r\n public readonly selectedNode = signal<ThesaurusEntryPagedTreeNode | null>(\r\n null,\r\n );\r\n\r\n // Signals for reactive data binding (replacing observables with async pipe)\r\n public readonly nodes = signal<readonly ThesaurusEntryPagedTreeNode[]>([]);\r\n public readonly filter = signal<Readonly<ThesaurusEntryNodeFilter>>({});\r\n\r\n public debug: FormControl<boolean> = new FormControl(false, {\r\n nonNullable: true,\r\n });\r\n public hideLoc: FormControl<boolean> = new FormControl(false, {\r\n nonNullable: true,\r\n });\r\n public hideFilter: FormControl<boolean> = new FormControl(false, {\r\n nonNullable: true,\r\n });\r\n\r\n public label: FormControl<string | null> = new FormControl(null);\r\n public form = new FormGroup({\r\n label: this.label,\r\n });\r\n\r\n constructor() {\r\n // Use effect to react to service/store changes\r\n effect(() => {\r\n const currentStore = this.store();\r\n const currentService = this.service();\r\n\r\n // Cleanup previous subscriptions\r\n this._nodesSub?.unsubscribe();\r\n this._filterSub?.unsubscribe();\r\n this._changesSub?.unsubscribe();\r\n\r\n if (!currentStore || !currentService) {\r\n this.nodes.set([]);\r\n this.filter.set({});\r\n return;\r\n }\r\n\r\n // Subscribe to store's observables and update signals\r\n this._nodesSub = currentStore.nodes$.subscribe((nodes) => {\r\n this.nodes.set(nodes);\r\n });\r\n this._filterSub = currentStore.filter$.subscribe((filter) => {\r\n this.filter.set(filter);\r\n });\r\n\r\n // Subscribe to changes state\r\n this._changesSub = currentService.hasChanges$.subscribe((hasChanges) => {\r\n this.changesStateChange.emit(hasChanges);\r\n });\r\n\r\n // Load nodes if store is empty\r\n if (!currentStore.getNodes().length) {\r\n this.loading.set(true);\r\n currentStore.setFilter({}).finally(() => {\r\n this.loading.set(false);\r\n });\r\n }\r\n });\r\n }\r\n\r\n public ngOnDestroy(): void {\r\n this._nodesSub?.unsubscribe();\r\n this._filterSub?.unsubscribe();\r\n this._changesSub?.unsubscribe();\r\n }\r\n\r\n public reset(): void {\r\n const store = this.store();\r\n if (!store) return;\r\n\r\n this.loading.set(true);\r\n store.reset().finally(() => {\r\n this.loading.set(false);\r\n });\r\n }\r\n\r\n public onToggleExpanded(node: ThesaurusEntryPagedTreeNode): void {\r\n const store = this.store();\r\n if (!store) return;\r\n\r\n this.loading.set(true);\r\n if (node.expanded) {\r\n store.collapse(node.id).finally(() => {\r\n this.loading.set(false);\r\n });\r\n } else {\r\n store.expand(node.id).finally(() => {\r\n this.loading.set(false);\r\n });\r\n }\r\n }\r\n\r\n public onPageChangeRequest(request: PageChangeRequest): void {\r\n const store = this.store();\r\n if (!store) return;\r\n\r\n this.loading.set(true);\r\n store.changePage(request.node.id, request.paging.pageNumber).finally(() => {\r\n this.loading.set(false);\r\n });\r\n }\r\n\r\n public onFilterChange(\r\n filter: ThesaurusEntryNodeFilter | null | undefined,\r\n ): void {\r\n const store = this.store();\r\n if (!store) return;\r\n\r\n console.log('filter change', filter);\r\n this.loading.set(true);\r\n store.setFilter(filter || {}).finally(() => {\r\n this.loading.set(false);\r\n });\r\n }\r\n\r\n public onEditFilterRequest(node: ThesaurusEntryPagedTreeNode): void {\r\n const store = this.store();\r\n if (!store) return;\r\n\r\n const dialogRef = this._dialog.open(ThesaurusPagedTreeFilterComponent, {\r\n data: {\r\n filter: node.filter,\r\n },\r\n });\r\n dialogRef.afterClosed().subscribe((filter) => {\r\n if (filter === null) {\r\n store.setNodeFilter(node.id, null);\r\n } else if (filter) {\r\n store.setNodeFilter(node.id, filter);\r\n }\r\n });\r\n }\r\n\r\n public expandAll(): void {\r\n const store = this.store();\r\n if (!store) return;\r\n store.expandAll();\r\n }\r\n\r\n public collapseAll(): void {\r\n const store = this.store();\r\n if (!store) return;\r\n store.collapseAll();\r\n }\r\n\r\n public clear(): void {\r\n const store = this.store();\r\n if (!store) return;\r\n store.clear();\r\n }\r\n\r\n public onNodeClick(node: ThesaurusEntryPagedTreeNode): void {\r\n this.selectedNode.set(node);\r\n if (!node.hasChildren) {\r\n this.nodePick.emit(node);\r\n }\r\n }\r\n\r\n public findLabels(): void {\r\n const store = this.store();\r\n if (!store || !this.label.value) return;\r\n store.findLabels(this.label.value);\r\n }\r\n\r\n public removeHilites(): void {\r\n const store = this.store();\r\n if (!store) return;\r\n store.removeHilites();\r\n }\r\n\r\n // editing operations\r\n private editEntry(entry: EditedThesEntry): Promise<EditedThesEntry | null> {\r\n return new Promise((resolve) => {\r\n const dialogRef = this._dialog.open(ThesEntryEditorComponent, {\r\n data: entry,\r\n });\r\n\r\n dialogRef.afterClosed().subscribe((result) => {\r\n resolve(result);\r\n });\r\n });\r\n }\r\n\r\n public async addChild(): Promise<void> {\r\n const store = this.store();\r\n const selected = this.selectedNode();\r\n if (!store || !selected) {\r\n this._snackBar.open('Please select a node first', 'Close', {\r\n duration: 2000,\r\n });\r\n return;\r\n }\r\n\r\n // get the current entries to check for duplicates\r\n const currentService = this.service();\r\n if (!currentService) return;\r\n\r\n // determine the parent ID for the new child\r\n const parentKey = selected.key; // original entry ID\r\n\r\n // edit the new entry\r\n const newEntry = await this.editEntry({\r\n id: '',\r\n value: '',\r\n hierarchical: true,\r\n parentId: parentKey,\r\n idExists: (id: string) =>\r\n currentService.getCurrentEntries().some((e) => e.id === id),\r\n });\r\n if (!newEntry) {\r\n return;\r\n }\r\n\r\n store\r\n .addChild(selected.id, {\r\n label: newEntry.value,\r\n y: 0, // will be calculated by the store\r\n x: 0, // will be calculated by the store\r\n tag: selected.tag,\r\n })\r\n .then((result) => {\r\n if (result) {\r\n // update the temporary node with the user-provided ID,\r\n // this will be handled in the service's nodeToEntry method\r\n (result as any)._userProvidedId = newEntry.id;\r\n this._snackBar.open('Child added successfully', 'Close', {\r\n duration: 2000,\r\n });\r\n }\r\n });\r\n }\r\n\r\n public async addSibling(): Promise<void> {\r\n const store = this.store();\r\n const selected = this.selectedNode();\r\n if (!store || !selected) {\r\n this._snackBar.open('Please select a node first', 'Close', {\r\n duration: 2000,\r\n });\r\n return;\r\n }\r\n\r\n // get the current entries to check for duplicates\r\n const currentService = this.service();\r\n if (!currentService) return;\r\n\r\n const selectedKey = (selected as any).key; // original entry ID\r\n\r\n // determine the parent ID for the new sibling\r\n const selectedParts = selectedKey.split('.');\r\n const parentKey =\r\n selectedParts.length > 1 ? selectedParts.slice(0, -1).join('.') : '';\r\n\r\n const newEntry = await this.editEntry({\r\n id: '',\r\n value: '',\r\n hierarchical: true,\r\n parentId: parentKey,\r\n idExists: (id: string) =>\r\n currentService.getCurrentEntries().some((e) => e.id === id),\r\n });\r\n if (!newEntry) {\r\n return;\r\n }\r\n\r\n // check that the new ID has the same depth\r\n if (newEntry.id.split('.').length !== selectedParts.length) {\r\n this._snackBar.open(\r\n `Sibling must have same depth as \"${selectedKey}\"`,\r\n 'Close',\r\n { duration: 3000 },\r\n );\r\n return;\r\n }\r\n\r\n store\r\n .addSibling(selected.id, {\r\n label: newEntry.value,\r\n tag: selected.tag,\r\n })\r\n .then((result) => {\r\n if (result) {\r\n // update the temporary node with the user-provided ID\r\n (result as any)._userProvidedId = newEntry.id;\r\n this._snackBar.open('Sibling added successfully', 'Close', {\r\n duration: 2000,\r\n });\r\n }\r\n });\r\n }\r\n\r\n public removeNode(): void {\r\n const store = this.store();\r\n const selected = this.selectedNode();\r\n if (!store || !selected) {\r\n this._snackBar.open('Please select a node first', 'Close', {\r\n duration: 2000,\r\n });\r\n return;\r\n }\r\n\r\n const selectedKey = (selected as any).key || `temp_${selected.id}`;\r\n this._dialogService\r\n .confirm(\r\n 'Confirm Deletion',\r\n `Delete \"${selectedKey}\" (${selected.label}) and all its descendants?`,\r\n )\r\n .subscribe((result) => {\r\n if (!result) {\r\n return;\r\n }\r\n store.removeNode(selected.id).then((result) => {\r\n if (result) {\r\n this.selectedNode.set(null);\r\n this._snackBar.open('Node removed successfully', 'Close', {\r\n duration: 2000,\r\n });\r\n }\r\n });\r\n });\r\n }\r\n\r\n public async editNode(): Promise<void> {\r\n const currentService = this.service();\r\n if (!currentService) return;\r\n\r\n const store = this.store();\r\n const selected = this.selectedNode();\r\n if (!store || !selected) {\r\n this._snackBar.open('Please select a node first', 'Close', {\r\n duration: 2000,\r\n });\r\n return;\r\n }\r\n\r\n const selectedKey = selected.key;\r\n const isNewNode = selected.id < 0; // temporary ID means it's a new node\r\n\r\n const newEntry = await this.editEntry({\r\n id: selectedKey || '',\r\n value: selected.label,\r\n idLocked: !isNewNode,\r\n idExists: (id: string) =>\r\n currentService.getCurrentEntries().some((entry) => entry.id === id),\r\n });\r\n if (!newEntry) return;\r\n\r\n store\r\n .replaceNode(selected.id, {\r\n label: newEntry.value,\r\n tag: selected.tag,\r\n })\r\n .then((result) => {\r\n if (result) {\r\n // update the temporary node with the user-provided ID if it's a new node\r\n if (isNewNode) {\r\n (result as any)._userProvidedId = newEntry.id;\r\n }\r\n this._snackBar.open('Node updated successfully', 'Close', {\r\n duration: 2000,\r\n });\r\n }\r\n });\r\n }\r\n}\r\n","<div id=\"container\">\r\n <!-- filters -->\r\n <div id=\"filters\" class=\"form-row\">\r\n <form [formGroup]=\"form\" (submit)=\"findLabels()\">\r\n <fieldset>\r\n <legend>finder</legend>\r\n <div 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 {\r\n <mat-error>label required</mat-error>\r\n }\r\n </mat-form-field>\r\n <div class=\"form-row\" style=\"gap: 0\">\r\n <button type=\"submit\" mat-icon-button class=\"mat-primary\">\r\n <mat-icon>search</mat-icon>\r\n </button>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n (click)=\"removeHilites()\"\r\n class=\"mat-warn\"\r\n >\r\n <mat-icon>clear</mat-icon>\r\n </button>\r\n </div>\r\n </div>\r\n </fieldset>\r\n </form>\r\n @if (hasRootFilter()) {\r\n <fieldset>\r\n <legend>global filter</legend>\r\n <cadmus-thesaurus-paged-tree-filter\r\n [filter]=\"filter()\"\r\n (filterChange)=\"onFilterChange($event)\"\r\n />\r\n </fieldset>\r\n }\r\n </div>\r\n\r\n <!-- editing actions -->\r\n <div class=\"editing-actions\">\r\n <button\r\n type=\"button\"\r\n mat-raised-button\r\n color=\"primary\"\r\n [disabled]=\"!selectedNode()\"\r\n [matMenuTriggerFor]=\"addMenu\"\r\n >\r\n <mat-icon>add</mat-icon>\r\n add\r\n </button>\r\n\r\n <mat-menu #addMenu=\"matMenu\">\r\n <button type=\"button\" mat-menu-item (click)=\"addChild()\">\r\n <mat-icon>subdirectory_arrow_right</mat-icon>\r\n add child\r\n </button>\r\n <button type=\"button\" mat-menu-item (click)=\"addSibling()\">\r\n <mat-icon>arrow_right_alt</mat-icon>\r\n add sibling\r\n </button>\r\n </mat-menu>\r\n\r\n <button\r\n type=\"button\"\r\n mat-stroked-button\r\n color=\"accent\"\r\n [disabled]=\"!selectedNode()\"\r\n (click)=\"editNode()\"\r\n >\r\n <mat-icon>edit</mat-icon>\r\n edit\r\n </button>\r\n\r\n <button\r\n type=\"button\"\r\n mat-stroked-button\r\n color=\"warn\"\r\n [disabled]=\"!selectedNode()\"\r\n (click)=\"removeNode()\"\r\n >\r\n <mat-icon>delete</mat-icon>\r\n remove\r\n </button>\r\n\r\n @if (selectedNode()) {\r\n <span class=\"selected-info\"> selected: {{ selectedNode()!.label }} </span>\r\n }\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(); as nodeList) {\r\n <div>\r\n @for (node of nodeList; track node.id; let i = $index) {\r\n <div\r\n class=\"button-row\"\r\n [class.hilite]=\"node.hilite\"\r\n [class.selected]=\"selectedNode()?.id === node.id\"\r\n (click)=\"onNodeClick(node)\"\r\n >\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 < nodeList.length &&\r\n nodeList[i + 1].paging.pageCount > 1\r\n ? nodeList[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 </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","import { Observable, of } from 'rxjs';\r\n\r\nimport { DataPage } from '@myrmidon/ngx-tools';\r\nimport {\r\n PagedTreeNode,\r\n PagedTreeStoreService,\r\n TreeNodeFilter,\r\n} from '@myrmidon/paged-data-browsers';\r\nimport { ThesaurusEntry } from '@myrmidon/cadmus-core';\r\n\r\n/**\r\n * The filter for thesaurus entry nodes. The only filtered property is\r\n * the node's label.\r\n */\r\nexport interface ThesaurusEntryNodeFilter extends TreeNodeFilter {\r\n label?: string;\r\n}\r\n\r\n/**\r\n * The tree node for thesaurus entries in a paging tree node.\r\n */\r\nexport interface ThesaurusEntryPagedTreeNode extends PagedTreeNode<ThesaurusEntryNodeFilter> {\r\n key: string; // entry.id\r\n value: string; // entry.value (not rendered; the rendered value is in label)\r\n}\r\n\r\n/**\r\n * A label rendering function which removes from a label\r\n * all the characters past the last colon, trimming the result.\r\n * This is a typical rendering when dealing with hierarchical\r\n * thesaurus entries, e.g. \"furniture: table: color\", where\r\n * we can shorten the label to just \"color\", as \"furniture\"\r\n * and \"table\" are its ancestors.\r\n */\r\nexport function renderLabelFromLastColon(label: string): string {\r\n if (!label) {\r\n return label;\r\n }\r\n const i = label.lastIndexOf(':');\r\n return i > -1 && i + 1 < label.length ? label.substring(i + 1).trim() : label;\r\n}\r\n\r\ninterface NumberedEntry extends ThesaurusEntry {\r\n n: number;\r\n}\r\n\r\n/**\r\n * A static paged tree store service for thesaurus entries.\r\n * This builds tree nodes from all the thesaurus entries from a specific\r\n * thesaurus, assuming that entry IDs are hierarchical and\r\n * separated by dots (.).\r\n * Nodes are received all at once for a thesaurus, so this is essentially\r\n * an adapter to the paged tree store service interface.\r\n * The entries are a flat list where hierarchy is implied by the IDs:\r\n * for instance, \"animal.mammal.dog\" is a child of \"animal.mammal\"\r\n * which is a child of \"animal\". Numeric IDs are added to each node\r\n * based on the order of entries to ensure stable IDs.\r\n * The label of each node can be rendered as-is from the entry value,\r\n * or a custom rendering function can be provided to the constructor.\r\n */\r\nexport class StaticThesaurusPagedTreeStoreService implements PagedTreeStoreService<ThesaurusEntryNodeFilter> {\r\n private _nodes: ThesaurusEntryPagedTreeNode[] = [];\r\n private _built = false;\r\n private readonly _entries: NumberedEntry[];\r\n\r\n /**\r\n * Constructor.\r\n * @param entries The thesaurus entries.\r\n * @param _renderLabel An optional function to render the label\r\n * of each node.\r\n */\r\n constructor(\r\n entries: ThesaurusEntry[],\r\n private _renderLabel?: (label: string) => string,\r\n ) {\r\n // assign a number to each entry for stable IDs\r\n this._entries = entries.map((entry, index) => ({\r\n ...entry,\r\n n: index + 1,\r\n }));\r\n }\r\n\r\n /**\r\n * Ensure that nodes have been built from entries.\r\n */\r\n private ensureNodes(): void {\r\n // lazily build the nodes only once\r\n if (this._built) {\r\n return;\r\n }\r\n\r\n // create a map of sibling numbers (x) where:\r\n // - key=node.id (0 is used for the virtual root);\r\n // - value=max x value for that parent.\r\n const xMap = new Map<number, number>();\r\n\r\n // build nodes from entries\r\n for (const entry of this._entries) {\r\n const hasDot = entry.id.includes('.');\r\n const keyParts = entry.id.split('.');\r\n\r\n // create the node\r\n const node: ThesaurusEntryPagedTreeNode = {\r\n id: entry.n,\r\n label:\r\n hasDot && this._renderLabel\r\n ? this._renderLabel(entry.value)\r\n : entry.value,\r\n key: entry.id,\r\n value: entry.value,\r\n paging: { pageNumber: 0, pageCount: 0, total: 0 },\r\n y: hasDot ? keyParts.length : 1,\r\n x: 0, // will be set later\r\n parentId: undefined, // will be set later\r\n hasChildren: false, // will be set later\r\n };\r\n\r\n // if it has a dot, find its parent and set parentId\r\n if (hasDot) {\r\n // build the parent key\r\n const parentKey = keyParts.slice(0, keyParts.length - 1).join('.');\r\n // find the parent node with that key\r\n const parentNode = this._nodes.find((n) => n.key === parentKey);\r\n // if found, set parentId and x in child and hasChildren in parent\r\n if (parentNode) {\r\n node.parentId = parentNode.id;\r\n parentNode.hasChildren = true;\r\n if (xMap.has(parentNode.id)) {\r\n xMap.set(parentNode.id, xMap.get(parentNode.id)! + 1);\r\n } else {\r\n xMap.set(parentNode.id, 1);\r\n }\r\n node.x = xMap.get(parentNode.id)!;\r\n } else {\r\n // parent not found, treat as root\r\n if (xMap.has(0)) {\r\n xMap.set(0, xMap.get(0)! + 1);\r\n } else {\r\n xMap.set(0, 1);\r\n }\r\n node.x = xMap.get(0)!;\r\n }\r\n } else {\r\n // else it's a root node\r\n if (xMap.has(0)) {\r\n xMap.set(0, xMap.get(0)! + 1);\r\n } else {\r\n xMap.set(0, 1);\r\n }\r\n node.x = xMap.get(0)!;\r\n }\r\n\r\n this._nodes.push(node);\r\n }\r\n\r\n this._built = true;\r\n }\r\n\r\n /**\r\n * Get the specified page of nodes.\r\n * @param filter The filter.\r\n * @param pageNumber The page number.\r\n * @param pageSize The page size.\r\n * @param hasMockRoot Whether the root node is a mock node. Not used here.\r\n */\r\n public getNodes(\r\n filter: ThesaurusEntryNodeFilter,\r\n pageNumber: number,\r\n pageSize: number,\r\n hasMockRoot?: boolean,\r\n ): Observable<DataPage<ThesaurusEntryPagedTreeNode>> {\r\n this.ensureNodes();\r\n\r\n // apply filtering\r\n let nodes = this._nodes.filter((n) => {\r\n // filter by parentId (required by tree structure)\r\n if (filter.parentId !== undefined && filter.parentId !== null) {\r\n if (n.parentId !== filter.parentId) {\r\n return false;\r\n }\r\n } else {\r\n if (n.parentId) {\r\n return false;\r\n }\r\n }\r\n\r\n // filter by label\r\n if (filter.label) {\r\n const filterValue = filter.label.toLowerCase();\r\n if (!n.label.toLowerCase().includes(filterValue)) {\r\n return false;\r\n }\r\n }\r\n return true;\r\n });\r\n\r\n // page and return\r\n const paged = nodes.slice(\r\n (pageNumber - 1) * pageSize,\r\n pageNumber * pageSize,\r\n );\r\n return of({\r\n items: paged,\r\n pageNumber: pageNumber,\r\n pageSize: pageSize,\r\n pageCount: Math.ceil(nodes.length / pageSize),\r\n total: nodes.length,\r\n });\r\n }\r\n}\r\n","import {\r\n Component,\r\n OnDestroy,\r\n computed,\r\n effect,\r\n inject,\r\n input,\r\n output,\r\n signal,\r\n} from '@angular/core';\r\nimport { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';\r\nimport { Subscription } from 'rxjs';\r\n\r\nimport { MatDialog } from '@angular/material/dialog';\r\nimport { MatProgressBarModule } from '@angular/material/progress-bar';\r\nimport { MatButtonModule } from '@angular/material/button';\r\nimport { MatCheckboxModule } from '@angular/material/checkbox';\r\nimport { MatIconModule } from '@angular/material/icon';\r\nimport { MatTooltipModule } from '@angular/material/tooltip';\r\nimport { MatInputModule } from '@angular/material/input';\r\nimport { MatFormFieldModule } from '@angular/material/form-field';\r\n\r\nimport {\r\n BrowserTreeNodeComponent,\r\n PagedTreeStore,\r\n PageChangeRequest,\r\n} from '@myrmidon/paged-data-browsers';\r\n\r\nimport {\r\n renderLabelFromLastColon,\r\n StaticThesaurusPagedTreeStoreService,\r\n ThesaurusEntryNodeFilter,\r\n ThesaurusEntryPagedTreeNode,\r\n} from '../../services/static-thesaurus-paged-tree-store.service';\r\nimport { ThesaurusPagedTreeFilterComponent }\r\n from '../thesaurus-paged-tree-filter/thesaurus-paged-tree-filter.component';\r\n\r\n/**\r\n * A readonly paged tree browser for thesaurus entries. This is a lower-level component\r\n * used as an adapter between the generic paged tree browser and the thesaurus entries\r\n * data model.\r\n */\r\n@Component({\r\n selector: 'cadmus-thesaurus-browser',\r\n imports: [\r\n ReactiveFormsModule,\r\n MatButtonModule,\r\n MatCheckboxModule,\r\n MatFormFieldModule,\r\n MatIconModule,\r\n MatInputModule,\r\n MatProgressBarModule,\r\n MatTooltipModule,\r\n ThesaurusPagedTreeFilterComponent,\r\n BrowserTreeNodeComponent,\r\n ],\r\n templateUrl: './thesaurus-browser.component.html',\r\n styleUrl: './thesaurus-browser.component.scss',\r\n})\r\nexport class ThesaurusBrowserComponent implements OnDestroy {\r\n private _dialog = inject(MatDialog);\r\n private _nodesSub?: Subscription;\r\n private _filterSub?: Subscription;\r\n\r\n /**\r\n * The service to use to load the nodes.\r\n */\r\n public readonly service = input<StaticThesaurusPagedTreeStoreService>(\r\n new StaticThesaurusPagedTreeStoreService([], renderLabelFromLastColon)\r\n );\r\n\r\n /**\r\n * Emitted when a node is clicked.\r\n */\r\n public readonly nodePick = output<ThesaurusEntryPagedTreeNode>();\r\n\r\n /**\r\n * The store instance, built from the service.\r\n */\r\n public readonly store = computed(() => {\r\n const service = this.service();\r\n return new PagedTreeStore<\r\n ThesaurusEntryPagedTreeNode,\r\n ThesaurusEntryNodeFilter\r\n >(service);\r\n });\r\n\r\n public readonly loading = signal<boolean>(false);\r\n\r\n // Signals for reactive data binding (replacing observables with async pipe)\r\n public readonly nodes = signal<readonly ThesaurusEntryPagedTreeNode[]>([]);\r\n public readonly filter = signal<Readonly<ThesaurusEntryNodeFilter>>({});\r\n\r\n public debug: FormControl<boolean> = new FormControl(false, {\r\n nonNullable: true,\r\n });\r\n public hideLoc: FormControl<boolean> = new FormControl(false, {\r\n nonNullable: true,\r\n });\r\n public hideFilter: FormControl<boolean> = new FormControl(false, {\r\n nonNullable: true,\r\n });\r\n\r\n public label: FormControl<string | null> = new FormControl(null);\r\n public form = new FormGroup({\r\n label: this.label,\r\n });\r\n\r\n constructor() {\r\n // Use effect to react to service/store changes\r\n effect(() => {\r\n const currentStore = this.store();\r\n\r\n // Unsubscribe from previous store's observables\r\n this._nodesSub?.unsubscribe();\r\n this._filterSub?.unsubscribe();\r\n\r\n // Subscribe to new store's observables and update signals\r\n this._nodesSub = currentStore.nodes$.subscribe((nodes) => {\r\n this.nodes.set(nodes);\r\n });\r\n this._filterSub = currentStore.filter$.subscribe((filter) => {\r\n this.filter.set(filter);\r\n });\r\n\r\n // Load nodes if store is empty\r\n if (!currentStore.getNodes().length) {\r\n this.loading.set(true);\r\n currentStore.setFilter({}).finally(() => {\r\n this.loading.set(false);\r\n });\r\n }\r\n });\r\n }\r\n\r\n public ngOnDestroy(): void {\r\n this._nodesSub?.unsubscribe();\r\n this._filterSub?.unsubscribe();\r\n }\r\n\r\n public reset(): void {\r\n this.loading.set(true);\r\n this.store()\r\n .reset()\r\n .finally(() => {\r\n this.loading.set(false);\r\n });\r\n }\r\n\r\n public onToggleExpanded(node: ThesaurusEntryPagedTreeNode): void {\r\n this.loading.set(true);\r\n if (node.expanded) {\r\n this.store()\r\n .collapse(node.id)\r\n .finally(() => {\r\n this.loading.set(false);\r\n });\r\n } else {\r\n this.store()\r\n .expand(node.id)\r\n .finally(() => {\r\n this.loading.set(false);\r\n });\r\n }\r\n }\r\n\r\n public onPageChangeRequest(request: PageChangeRequest): void {\r\n this.loading.set(true);\r\n this.store()\r\n .changePage(request.node.id, request.paging.pageNumber)\r\n .finally(() => {\r\n this.loading.set(false);\r\n });\r\n }\r\n\r\n public onFilterChange(filter: ThesaurusEntryNodeFilter | null | undefined): void {\r\n console.log('filter change', filter);\r\n this.loading.set(true);\r\n this.store()\r\n .setFilter(filter || {})\r\n .finally(() => {\r\n this.loading.set(false);\r\n });\r\n }\r\n\r\n public onEditFilterRequest(node: ThesaurusEntryPagedTreeNode): void {\r\n const dialogRef = this._dialog.open(ThesaurusPagedTreeFilterComponent, {\r\n data: {\r\n filter: node.filter,\r\n },\r\n });\r\n dialogRef.afterClosed().subscribe((filter) => {\r\n // undefined = user dismissed without changes\r\n if (filter === null) {\r\n this.store().setNodeFilter(node.id, null);\r\n } else if (filter) {\r\n this.store().setNodeFilter(node.id, filter);\r\n }\r\n });\r\n }\r\n\r\n public expandAll(): void {\r\n this.store().expandAll();\r\n }\r\n\r\n public collapseAll(): void {\r\n this.store().collapseAll();\r\n }\r\n\r\n public clear(): void {\r\n this.store().clear();\r\n }\r\n\r\n public onNodeClick(node: ThesaurusEntryPagedTreeNode): void {\r\n if (!node.hasChildren) {\r\n this.nodePick.emit(node);\r\n }\r\n }\r\n\r\n public findLabels(): void {\r\n if (!this.label.value) {\r\n return;\r\n }\r\n this.store().findLabels(this.label.value);\r\n }\r\n\r\n public removeHilites(): void {\r\n this.store().removeHilites();\r\n }\r\n}\r\n","<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\r\n type=\"button\"\r\n mat-icon-button\r\n (click)=\"removeHilites()\"\r\n class=\"mat-warn\"\r\n >\r\n <mat-icon>clear</mat-icon>\r\n </button>\r\n </form>\r\n <fieldset>\r\n <legend>filter</legend>\r\n <cadmus-thesaurus-paged-tree-filter\r\n [filter]=\"filter()\"\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(); as nodeList) {\r\n <div>\r\n @for (node of nodeList; 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 < nodeList.length &&\r\n nodeList[i + 1].paging.pageCount > 1\r\n ? nodeList[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","import { Component, computed, input, output, Type } from '@angular/core';\r\nimport { FormsModule, ReactiveFormsModule } from '@angular/forms';\r\nimport { ThesaurusEntry } from '@myrmidon/cadmus-core';\r\n\r\nimport { ThesaurusPagedTreeFilterComponent } from '../thesaurus-paged-tree-filter/thesaurus-paged-tree-filter.component';\r\nimport {\r\n renderLabelFromLastColon,\r\n StaticThesaurusPagedTreeStoreService,\r\n ThesaurusEntryPagedTreeNode,\r\n} from '../../services/static-thesaurus-paged-tree-store.service';\r\nimport { ThesaurusBrowserComponent } from '../thesaurus-browser/thesaurus-browser.component';\r\n\r\n/**\r\n * Thesaurus tree component.\r\n * This component displays a set of hierarchical thesaurus entries\r\n * in a tree, provided that each entry marks its hierarchy with\r\n * dots. For instance, say you have the hierarchy \"furniture\" -\r\n * \"type\" - \"color\". You might have an entry whose ID is\r\n * \"furniture.table.red\", with a sibling \"furniture.table.green\",\r\n * and a parent \"furniture.table\". This parent is there only to\r\n * provide a label to the parent node, but only leaf nodes can be\r\n * picked by the user. Whenever one is picked, the entryChange\r\n * event is emitted.\r\n */\r\n@Component({\r\n selector: 'cadmus-thesaurus-tree',\r\n templateUrl: './thesaurus-tree.component.html',\r\n styleUrls: ['./thesaurus-tree.component.css'],\r\n imports: [FormsModule, ReactiveFormsModule, ThesaurusBrowserComponent],\r\n})\r\nexport class ThesaurusTreeComponent {\r\n /**\r\n * The thesaurus entries.\r\n */\r\n public readonly entries = input<ThesaurusEntry[]>();\r\n\r\n /**\r\n * The optional node label rendering function. Note that even if you\r\n * specify a label renderer function, the entryChange event always\r\n * emits the original label.\r\n */\r\n public readonly renderLabel = input<(label: string) => string>(\r\n renderLabelFromLastColon,\r\n );\r\n\r\n /**\r\n * Fired when a thesaurus entry is selected.\r\n */\r\n public readonly entryChange = output<ThesaurusEntry>();\r\n\r\n /**\r\n * The tree store service, dependent on the current entries and renderLabel.\r\n */\r\n public readonly service = computed<StaticThesaurusPagedTreeStoreService>(() => {\r\n const entries = this.entries();\r\n return new StaticThesaurusPagedTreeStoreService(\r\n entries || [],\r\n this.renderLabel(),\r\n );\r\n });\r\n\r\n /**\r\n * The filter component class to use.\r\n */\r\n public readonly filterComponent: Type<ThesaurusPagedTreeFilterComponent> =\r\n ThesaurusPagedTreeFilterComponent;\r\n\r\n public onNodePick(node: ThesaurusEntryPagedTreeNode): void {\r\n // only allow selection of leaf nodes (nodes without children)\r\n if (!node.hasChildren) {\r\n // find the original entry\r\n const entry = this.entries()?.find((e) => e.id === node.key);\r\n if (entry) {\r\n this.entryChange.emit(entry);\r\n }\r\n }\r\n }\r\n}\r\n","<div>\r\n <!-- tree -->\r\n @if (service() && entries()?.length) {\r\n <div class=\"tree-wrapper\">\r\n <cadmus-thesaurus-browser\r\n [service]=\"service()\"\r\n (nodePick)=\"onNodePick($event)\"\r\n />\r\n </div>\r\n }\r\n</div>\r\n","import {\r\n Component,\r\n computed,\r\n effect,\r\n input,\r\n model,\r\n untracked,\r\n} from '@angular/core';\r\nimport { ThesaurusEntry } from '@myrmidon/cadmus-core';\r\nimport {\r\n FormBuilder,\r\n FormControl,\r\n FormGroup,\r\n ReactiveFormsModule,\r\n Validators,\r\n} from '@angular/forms';\r\n\r\nimport {\r\n CdkDragDrop,\r\n CdkDropList,\r\n CdkDrag,\r\n moveItemInArray,\r\n} from '@angular/cdk/drag-drop';\r\nimport {\r\n MatChipListbox,\r\n MatChipOption,\r\n MatChipRemove,\r\n} from '@angular/material/chips';\r\nimport { MatExpansionPanel } from '@angular/material/expansion';\r\nimport { MatFormField } from '@angular/material/form-field';\r\nimport { MatIcon } from '@angular/material/icon';\r\nimport { MatIconButton } from '@angular/material/button';\r\nimport { MatInput } from '@angular/material/input';\r\nimport { MatTooltip } from '@angular/material/tooltip';\r\n\r\nimport { renderLabelFromLastColon } from '../../services/static-thesaurus-paged-tree-store.service';\r\nimport { ThesaurusTreeComponent } from '../thesaurus-tree/thesaurus-tree.component';\r\n\r\n/**\r\n * The prefix added to custom entries' IDs.\r\n */\r\nexport const CUSTOM_ENTRY_PREFIX = '$';\r\n\r\n/**\r\n * A picker component for thesaurus entries.\r\n * This component allows picking one or more entries from a given thesaurus.\r\n * In its collapsed state, it shows the picked entries as chips; when\r\n * expanded, it shows the thesaurus tree to pick from. Custom entries\r\n * (not in the thesaurus) can be optionally allowed.\r\n */\r\n@Component({\r\n selector: 'cadmus-thesaurus-entries-picker',\r\n imports: [\r\n ReactiveFormsModule,\r\n CdkDropList,\r\n CdkDrag,\r\n MatChipListbox,\r\n MatChipOption,\r\n MatChipRemove,\r\n MatExpansionPanel,\r\n MatFormField,\r\n MatIconButton,\r\n MatIcon,\r\n MatInput,\r\n MatTooltip,\r\n ThesaurusTreeComponent,\r\n ],\r\n templateUrl: './thesaurus-entries-picker.component.html',\r\n styleUrl: './thesaurus-entries-picker.component.css',\r\n})\r\nexport class ThesaurusEntriesPickerComponent {\r\n /**\r\n * The thesaurus entries to pick from (required).\r\n */\r\n public readonly availableEntries = input.required<ThesaurusEntry[]>();\r\n\r\n /**\r\n * The picked entries.\r\n */\r\n public readonly entries = model<ThesaurusEntry[]>([]);\r\n\r\n /**\r\n * True to show the entries with labels shortened according to\r\n * their hierarchy.\r\n */\r\n public readonly hierarchicLabels = input<boolean>(false);\r\n\r\n /**\r\n * True to automatically sort the picked entries (disables drag-and-drop).\r\n * When false, entries can be manually reordered via drag-and-drop.\r\n */\r\n public readonly autoSort = input<boolean>(false);\r\n\r\n /**\r\n * True to allow custom values (not in the entries list).\r\n */\r\n public readonly allowCustom = input<boolean>(false);\r\n\r\n /**\r\n * The minimum number of entries to pick.\r\n */\r\n public readonly minEntries = input<number>(0);\r\n\r\n /**\r\n * The maximum number of entries to pick (0=unlimited).\r\n */\r\n public readonly maxEntries = input<number>(0);\r\n\r\n /**\r\n * True when the picker is expanded (showing the entries list).\r\n */\r\n public readonly expanded = model<boolean>(false);\r\n\r\n /**\r\n * The message to show when there are no picked entries.\r\n */\r\n public readonly emptyMessage = input<string>('no entries');\r\n\r\n /**\r\n * The number of remaining entries that can be picked (0=unlimited).\r\n * This is displayed only if maxEntries > 1.\r\n */\r\n public readonly remaining = computed(() => {\r\n if (this.maxEntries() > 0) {\r\n return this.maxEntries() - this.entries().length;\r\n }\r\n return 0;\r\n });\r\n\r\n public id: FormControl<string>;\r\n public value: FormControl<string>;\r\n public form: FormGroup;\r\n\r\n constructor(formBuilder: FormBuilder) {\r\n this.id = formBuilder.control<string>('', {\r\n validators: [Validators.required, Validators.maxLength(100)],\r\n nonNullable: true,\r\n });\r\n this.value = formBuilder.control<string>('', {\r\n validators: [Validators.required, Validators.maxLength(500)],\r\n nonNullable: true,\r\n });\r\n this.form = formBuilder.group({\r\n id: this.id,\r\n value: this.value,\r\n });\r\n // if auto-sort is turned on and we have entries, sort them\r\n effect(() => {\r\n // only track autoSort() changes, not entries()\r\n const shouldSort = this.autoSort();\r\n\r\n if (shouldSort) {\r\n // use untracked to read entries without creating a dependency\r\n const currentEntries = untracked(() => this.entries());\r\n if (currentEntries.length > 1) {\r\n const entries = [...currentEntries];\r\n this.sortEntries(entries);\r\n this.entries.set(entries);\r\n }\r\n }\r\n });\r\n }\r\n\r\n // need arrow function to use 'this'\r\n public renderLabel = (label: string): string => {\r\n return this.hierarchicLabels() ? renderLabelFromLastColon(label) : label;\r\n };\r\n\r\n private sortEntries(entries: ThesaurusEntry[]) {\r\n entries.sort((a: ThesaurusEntry, b: ThesaurusEntry) => {\r\n const aIsCustom = a.id?.startsWith(CUSTOM_ENTRY_PREFIX) ?? false;\r\n const bIsCustom = b.id?.startsWith(CUSTOM_ENTRY_PREFIX) ?? false;\r\n if (aIsCustom !== bIsCustom) {\r\n // place custom entries after non-custom ones\r\n return aIsCustom ? 1 : -1;\r\n }\r\n // same kind: sort by label/value\r\n return a.value.localeCompare(b.value);\r\n });\r\n }\r\n\r\n public onEntryChange(entry: ThesaurusEntry): void {\r\n // check if already present\r\n if (this.entries().some((e: ThesaurusEntry) => e.id === entry.id)) {\r\n return;\r\n }\r\n // check if limit is reached\r\n if (this.maxEntries() && this.entries().length >= this.maxEntries()) {\r\n return;\r\n }\r\n\r\n const entries = [...this.entries()];\r\n entries.push(entry);\r\n if (this.autoSort()) {\r\n this.sortEntries(entries);\r\n }\r\n this.entries.set(entries);\r\n }\r\n\r\n public addCustomEntry(): void {\r\n if (this.form.invalid) {\r\n return;\r\n }\r\n\r\n // create the custom entry\r\n const customEntry: ThesaurusEntry = {\r\n id: CUSTOM_ENTRY_PREFIX + this.id.value,\r\n value: this.value.value,\r\n };\r\n\r\n // check if already present\r\n if (this.entries().some((e: ThesaurusEntry) => e.id === customEntry.id)) {\r\n return;\r\n }\r\n // check if limit is reached\r\n if (this.maxEntries() && this.entries().length >= this.maxEntries()) {\r\n return;\r\n }\r\n const entries = [...this.entries()];\r\n entries.push(customEntry);\r\n if (this.autoSort()) {\r\n this.sortEntries(entries);\r\n }\r\n this.entries.set(entries);\r\n this.form.reset();\r\n }\r\n\r\n public removeEntry(entry: ThesaurusEntry): void {\r\n const entries = [...this.entries().filter((e) => e.id !== entry.id)];\r\n this.entries.set(entries);\r\n }\r\n\r\n public clear(): void {\r\n this.entries.set([]);\r\n // if min > 0, expand the picker\r\n if (this.minEntries() > 0 && !this.expanded()) {\r\n setTimeout(() => {\r\n this.expanded.set(true);\r\n }, 0);\r\n }\r\n }\r\n\r\n public onDrop(event: CdkDragDrop<ThesaurusEntry[]>): void {\r\n const entries = [...this.entries()];\r\n moveItemInArray(entries, event.previousIndex, event.currentIndex);\r\n this.entries.set(entries);\r\n }\r\n}\r\n","<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","import { Observable, of } from 'rxjs';\r\n\r\nimport { DataPage } from '@myrmidon/ngx-tools';\r\n\r\nimport {\r\n EditablePagedTreeStoreServiceBase,\r\n ChangeOperation,\r\n ChangeOperationType,\r\n TreeNode,\r\n} from '@myrmidon/paged-data-browsers';\r\nimport { ThesaurusEntry } from '@myrmidon/cadmus-core';\r\n\r\nimport {\r\n StaticThesaurusPagedTreeStoreService,\r\n ThesaurusEntryNodeFilter,\r\n ThesaurusEntryPagedTreeNode,\r\n} from './static-thesaurus-paged-tree-store.service';\r\n\r\n/**\r\n * Editable version of the static thesaurus paged tree store service.\r\n * This service allows editing operations on the flat ThesaurusEntry list\r\n * while maintaining the tree structure implied by the hierarchical IDs.\r\n */\r\nexport class EditableStaticThesaurusPagedTreeStoreService\r\n extends EditablePagedTreeStoreServiceBase<ThesaurusEntryNodeFilter> {\r\n private _entries: ThesaurusEntry[];\r\n private _staticService: StaticThesaurusPagedTreeStoreService;\r\n private _renderLabel?: (label: string) => string;\r\n\r\n constructor(\r\n entries: ThesaurusEntry[],\r\n renderLabel?: (label: string) => string,\r\n ) {\r\n super();\r\n this._entries = [...entries];\r\n this._renderLabel = renderLabel;\r\n this._staticService = new StaticThesaurusPagedTreeStoreService(\r\n this._entries,\r\n renderLabel,\r\n );\r\n }\r\n\r\n protected override fetchNodes(\r\n filter: ThesaurusEntryNodeFilter,\r\n pageNumber: number,\r\n pageSize: number,\r\n hasMockRoot?: boolean,\r\n ): Observable<DataPage<TreeNode>> {\r\n // update the static service with current entries and delegate,\r\n // preserving the renderLabel function\r\n this._staticService = new StaticThesaurusPagedTreeStoreService(\r\n this._entries,\r\n this._renderLabel,\r\n );\r\n return this._staticService.getNodes(\r\n filter,\r\n pageNumber,\r\n pageSize,\r\n hasMockRoot,\r\n );\r\n }\r\n\r\n protected override persistChanges(\r\n changes: ChangeOperation[],\r\n ): Observable<Map<number, number>> {\r\n console.log('=== SAVING CHANGES ===');\r\n console.log('Changes to persist:', changes);\r\n\r\n const idMap = new Map<number, number>();\r\n\r\n // process changes to update the flat entries list\r\n for (const change of changes) {\r\n switch (change.type) {\r\n case ChangeOperationType.ADD:\r\n if (change.node) {\r\n const newEntry = this.nodeToEntry(change.node);\r\n if (newEntry) {\r\n const existingIndex = this._entries.findIndex(\r\n (e) => e.id === newEntry.id,\r\n );\r\n if (existingIndex === -1) {\r\n this._entries.push(newEntry);\r\n\r\n // map temporary ID to the new permanent ID (array index + 1)\r\n if (change.node.id < 0) {\r\n const permanentId = this._entries.length;\r\n idMap.set(change.node.id, permanentId);\r\n }\r\n console.log('Added entry:', newEntry);\r\n } else {\r\n console.log('Entry already exists, skipping:', newEntry.id);\r\n }\r\n }\r\n }\r\n break;\r\n\r\n case ChangeOperationType.REMOVE:\r\n if (change.originalNode) {\r\n // use the 'key' property which contains the ThesaurusEntry string ID\r\n const nodeWithKey =\r\n change.originalNode as ThesaurusEntryPagedTreeNode;\r\n const entryKey = nodeWithKey.key;\r\n\r\n if (entryKey) {\r\n this.removeEntryAndDescendants(entryKey);\r\n console.log('Removed entry and descendants:', entryKey);\r\n } else {\r\n console.warn('Node missing key property:', change.originalNode);\r\n }\r\n } else if (change.id < 0) {\r\n console.log(\r\n 'Removed temporary node that was never persisted:',\r\n change.id,\r\n );\r\n } else {\r\n console.warn(\r\n 'Remove operation missing originalNode for ID:',\r\n change.id,\r\n );\r\n }\r\n break;\r\n\r\n case ChangeOperationType.UPDATE:\r\n if (change.node && change.originalNode) {\r\n const nodeWithKey =\r\n change.originalNode as ThesaurusEntryPagedTreeNode;\r\n const entryKey = nodeWithKey.key;\r\n\r\n if (entryKey) {\r\n const entryToUpdate = this._entries.find(\r\n (e) => e.id === entryKey,\r\n );\r\n\r\n if (entryToUpdate) {\r\n const updatedEntry = this.nodeToEntry(change.node);\r\n if (updatedEntry) {\r\n // preserve the original hierarchical ID\r\n updatedEntry.id = entryToUpdate.id;\r\n const index = this._entries.findIndex(\r\n (e) => e.id === entryToUpdate.id,\r\n );\r\n if (index !== -1) {\r\n this._entries[index] = updatedEntry;\r\n console.log('Updated entry:', updatedEntry);\r\n }\r\n }\r\n } else {\r\n console.warn(\r\n 'Could not find entry to update with key:',\r\n entryKey,\r\n );\r\n }\r\n } else {\r\n console.warn(\r\n 'Update node missing key property:',\r\n change.originalNode,\r\n );\r\n }\r\n } else if (change.id < 0) {\r\n console.log('Updated temporary node:', change.id);\r\n }\r\n break;\r\n }\r\n }\r\n\r\n // Validate no duplicate IDs\r\n const ids = this._entries.map((e) => e.id);\r\n const duplicates = ids.filter((id, index) => ids.indexOf(id) !== index);\r\n if (duplicates.length > 0) {\r\n console.error('Duplicate IDs found:', duplicates);\r\n }\r\n\r\n console.log('Final entries after changes:', this._entries);\r\n console.log('ID mappings:', idMap);\r\n console.log('=== END SAVING CHANGES ===');\r\n\r\n return of(idMap);\r\n }\r\n\r\n /**\r\n * Convert a TreeNode back to a ThesaurusEntry.\r\n */\r\n private nodeToEntry(node: TreeNode): ThesaurusEntry | null {\r\n // For nodes with the key property, use it directly\r\n const nodeWithKey = node as any;\r\n if (nodeWithKey.key) {\r\n return {\r\n id: nodeWithKey.key,\r\n value: node.label,\r\n };\r\n }\r\n\r\n // For temporary nodes (negative IDs), construct a hierarchical ID\r\n if (node.id < 0) {\r\n // Check for user-provided ID\r\n const userProvidedId = nodeWithKey._userProvidedId;\r\n\r\n if (userProvidedId) {\r\n return {\r\n id: userProvidedId,\r\n value: node.label,\r\n };\r\n }\r\n\r\n // Find parent to construct the ID\r\n if (node.parentId) {\r\n const parentNode = this._nodes.get(node.parentId) as any;\r\n const parentKey = parentNode?.key;\r\n if (parentKey) {\r\n return {\r\n id: `${parentKey}.temp${Math.abs(node.id)}`,\r\n value: node.label,\r\n };\r\n }\r\n }\r\n\r\n // No parent, create a root-level temporary entry\r\n return {\r\n id: `temp${Math.abs(node.id)}`,\r\n value: node.label,\r\n };\r\n }\r\n\r\n console.warn('Could not convert node to entry:', node);\r\n return null;\r\n }\r\n\r\n /**\r\n * Remove an entry and all its descendants from the entries list.\r\n */\r\n private removeEntryAndDescendants(entryId: string): void {\r\n const toRemove: string[] = [];\r\n\r\n // find the entry and all its descendants\r\n for (const entry of this._entries) {\r\n if (entry.id === entryId || entry.id.startsWith(entryId + '.')) {\r\n toRemove.push(entry.id);\r\n }\r\n }\r\n\r\n // remove them from the list\r\n for (const id of toRemove) {\r\n const index = this._entries.findIndex((e) => e.id === id);\r\n if (index !== -1) {\r\n this._entries.splice(index, 1);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Get current entries (for demonstration purposes).\r\n */\r\n public getCurrentEntries(): ThesaurusEntry[] {\r\n return [...this._entries];\r\n }\r\n}\r\n","/*\r\n * Public API Surface of cadmus-thesaurus-store\r\n */\r\n\r\nexport * from './lib/components/editable-thesaurus-browser/editable-thesaurus-browser.component';\r\nexport * from './lib/components/thesaurus-entries-picker/thesaurus-entries-picker.component';\r\nexport * from './lib/components/thesaurus-entry-editor/thesaurus-entry-editor.component';\r\nexport * from './lib/components/thesaurus-browser/thesaurus-browser.component';\r\nexport * from './lib/components/thesaurus-paged-tree-filter/thesaurus-paged-tree-filter.component';\r\nexport * from './lib/components/thesaurus-tree/thesaurus-tree.component';\r\n\r\nexport * from './lib/services/editable-static-thesaurus-paged-tree-store.service';\r\nexport * from './lib/services/static-thesaurus-paged-tree-store.service';\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":["i3","i4","i6","i2","i7"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"myrmidon-cadmus-thesaurus-store.mjs","sources":["../../../../projects/myrmidon/cadmus-thesaurus-store/src/lib/components/thesaurus-paged-tree-filter/thesaurus-paged-tree-filter.component.ts","../../../../projects/myrmidon/cadmus-thesaurus-store/src/lib/components/thesaurus-paged-tree-filter/thesaurus-paged-tree-filter.component.html","../../../../projects/myrmidon/cadmus-thesaurus-store/src/lib/components/thesaurus-entry-editor/thesaurus-entry-editor.component.ts","../../../../projects/myrmidon/cadmus-thesaurus-store/src/lib/components/thesaurus-entry-editor/thesaurus-entry-editor.component.html","../../../../projects/myrmidon/cadmus-thesaurus-store/src/lib/components/editable-thesaurus-browser/editable-thesaurus-browser.component.ts","../../../../projects/myrmidon/cadmus-thesaurus-store/src/lib/components/editable-thesaurus-browser/editable-thesaurus-browser.component.html","../../../../projects/myrmidon/cadmus-thesaurus-store/src/lib/services/static-thesaurus-paged-tree-store.service.ts","../../../../projects/myrmidon/cadmus-thesaurus-store/src/lib/components/thesaurus-browser/thesaurus-browser.component.ts","../../../../projects/myrmidon/cadmus-thesaurus-store/src/lib/components/thesaurus-browser/thesaurus-browser.component.html","../../../../projects/myrmidon/cadmus-thesaurus-store/src/lib/components/thesaurus-tree/thesaurus-tree.component.ts","../../../../projects/myrmidon/cadmus-thesaurus-store/src/lib/components/thesaurus-tree/thesaurus-tree.component.html","../../../../projects/myrmidon/cadmus-thesaurus-store/src/lib/components/thesaurus-entries-picker/thesaurus-entries-picker.component.ts","../../../../projects/myrmidon/cadmus-thesaurus-store/src/lib/components/thesaurus-entries-picker/thesaurus-entries-picker.component.html","../../../../projects/myrmidon/cadmus-thesaurus-store/src/lib/services/editable-static-thesaurus-paged-tree-store.service.ts","../../../../projects/myrmidon/cadmus-thesaurus-store/src/public-api.ts","../../../../projects/myrmidon/cadmus-thesaurus-store/src/myrmidon-cadmus-thesaurus-store.ts"],"sourcesContent":["import {\r\n Component,\r\n effect,\r\n inject,\r\n model,\r\n OnInit,\r\n signal,\r\n} from '@angular/core';\r\nimport {\r\n FormBuilder,\r\n FormControl,\r\n FormGroup,\r\n ReactiveFormsModule,\r\n} from '@angular/forms';\r\nimport { MatButtonModule } from '@angular/material/button';\r\nimport { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';\r\nimport { MatFormFieldModule } from '@angular/material/form-field';\r\nimport { MatIconModule } from '@angular/material/icon';\r\nimport { MatInputModule } from '@angular/material/input';\r\nimport { MatTooltipModule } from '@angular/material/tooltip';\r\n\r\nimport { ThesaurusEntryNodeFilter } from '../../services/static-thesaurus-paged-tree-store.service';\r\n\r\n/**\r\n * A filter to be used for thesaurus paged tree browsers.\r\n */\r\n@Component({\r\n selector: 'cadmus-thesaurus-paged-tree-filter',\r\n imports: [\r\n ReactiveFormsModule,\r\n MatButtonModule,\r\n MatFormFieldModule,\r\n MatInputModule,\r\n MatIconModule,\r\n MatTooltipModule,\r\n ],\r\n templateUrl: './thesaurus-paged-tree-filter.component.html',\r\n styleUrl: './thesaurus-paged-tree-filter.component.css',\r\n})\r\nexport class ThesaurusPagedTreeFilterComponent implements OnInit {\r\n public readonly dialogRef = inject<\r\n MatDialogRef<ThesaurusPagedTreeFilterComponent>\r\n >(MatDialogRef, {\r\n optional: true,\r\n });\r\n public readonly data = inject(MAT_DIALOG_DATA, { optional: true });\r\n\r\n /**\r\n * The filter.\r\n */\r\n public readonly filter = model<ThesaurusEntryNodeFilter | null | undefined>();\r\n\r\n public readonly wrapped = signal<boolean>(false);\r\n\r\n public label: FormControl<string | null>;\r\n public form: FormGroup;\r\n\r\n constructor() {\r\n const formBuilder = inject(FormBuilder);\r\n const data = this.data;\r\n\r\n // form\r\n this.label = formBuilder.control<string | null>(null);\r\n this.form = formBuilder.group({\r\n label: this.label,\r\n });\r\n // bind dialog data if any\r\n if (this.dialogRef) {\r\n this.wrapped.set(true);\r\n if (data) {\r\n this.filter.set(data.filter);\r\n }\r\n } else {\r\n this.wrapped.set(false);\r\n }\r\n\r\n // update form when filter changes\r\n effect(() => {\r\n this.updateForm(this.filter());\r\n });\r\n }\r\n\r\n public ngOnInit(): void {\r\n this.updateForm(this.filter());\r\n }\r\n\r\n private updateForm(filter?: ThesaurusEntryNodeFilter | null): void {\r\n if (!filter) {\r\n this.form.reset();\r\n return;\r\n }\r\n this.label.setValue(filter.label ?? null);\r\n this.form.markAsPristine();\r\n }\r\n\r\n private getFilter(): ThesaurusEntryNodeFilter {\r\n return {\r\n label: this.label.value ?? undefined,\r\n };\r\n }\r\n\r\n public reset(): void {\r\n this.form.reset();\r\n this.filter.set(null);\r\n this.dialogRef?.close(null);\r\n }\r\n\r\n public apply(): void {\r\n const filter = this.getFilter();\r\n this.filter.set(filter);\r\n this.dialogRef?.close(filter);\r\n }\r\n}\r\n","<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\r\n <!-- buttons -->\r\n <div class=\"button-row\">\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Reset\"\r\n (click)=\"reset()\"\r\n >\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 </div>\r\n</form>\r\n","import { Component, Inject, input, model, Optional } from '@angular/core';\r\nimport {\r\n FormBuilder,\r\n FormControl,\r\n FormGroup,\r\n ReactiveFormsModule,\r\n Validators,\r\n AbstractControl,\r\n ValidationErrors,\r\n} from '@angular/forms';\r\nimport { MatButtonModule } from '@angular/material/button';\r\nimport {\r\n MatDialogRef,\r\n MAT_DIALOG_DATA,\r\n MatDialogConfig,\r\n} from '@angular/material/dialog';\r\nimport { MatFormFieldModule } from '@angular/material/form-field';\r\nimport { MatIconModule } from '@angular/material/icon';\r\nimport { MatInputModule } from '@angular/material/input';\r\nimport { MatTooltipModule } from '@angular/material/tooltip';\r\n\r\n/**\r\n * An edited thesaurus entry.\r\n */\r\nexport interface EditedThesEntry {\r\n id: string;\r\n value: string;\r\n /**\r\n * True if this entry belongs to a hierarchical thesaurus. When this is true,\r\n * and parentId is set, the parentId field will be used as the prefix for the\r\n * id field when creating a new entry.\r\n */\r\n hierarchical?: boolean;\r\n /**\r\n * The ID of the parent entry, if any.\r\n */\r\n parentId?: string;\r\n /**\r\n * If true, the id field is read-only. This is used when editing an existing\r\n * entry so you cannot change its ID.\r\n */\r\n idLocked?: boolean;\r\n /**\r\n * Function used to check if the given ID exists. This is used when\r\n * creating a new entry to ensure it does not duplicate an existing ID.\r\n * @param id The ID to check.\r\n * @returns True if exists.\r\n */\r\n idExists?: (id: string) => boolean;\r\n}\r\n\r\nexport interface PayloadMatDialogConfig<T> extends MatDialogConfig {\r\n payload?: T;\r\n}\r\n\r\n/**\r\n * A dialog component to edit a thesaurus entry.\r\n */\r\n@Component({\r\n selector: 'cadmus-thesaurus-entry-editor',\r\n imports: [\r\n ReactiveFormsModule,\r\n MatButtonModule,\r\n MatFormFieldModule,\r\n MatIconModule,\r\n MatInputModule,\r\n MatTooltipModule,\r\n ],\r\n templateUrl: './thesaurus-entry-editor.component.html',\r\n styleUrl: './thesaurus-entry-editor.component.scss',\r\n})\r\nexport class ThesEntryEditorComponent {\r\n public readonly entry = model<EditedThesEntry | undefined>();\r\n public wrapped = false;\r\n\r\n public id: FormControl<string>;\r\n public value: FormControl<string>;\r\n public form: FormGroup;\r\n\r\n constructor(\r\n @Optional()\r\n public dialogRef: MatDialogRef<ThesEntryEditorComponent>,\r\n @Optional()\r\n @Inject(MAT_DIALOG_DATA)\r\n public data: PayloadMatDialogConfig<EditedThesEntry>,\r\n formBuilder: FormBuilder\r\n ) {\r\n // bind to data properties if any\r\n if (data) {\r\n this.entry.set(data as EditedThesEntry);\r\n this.wrapped = true;\r\n }\r\n\r\n // custom validator for ID existence\r\n const idExistsValidator = (\r\n control: AbstractControl\r\n ): ValidationErrors | null => {\r\n const entry = this.entry();\r\n if (!entry || entry.idLocked || !entry.idExists) {\r\n return null;\r\n }\r\n const id = control.value?.trim();\r\n if (!id) {\r\n return null;\r\n }\r\n // if editing, allow the current id (do not check against itself)\r\n if (entry.id === id) {\r\n return null;\r\n }\r\n return entry.idExists(id) ? { idExists: true } : null;\r\n };\r\n\r\n // custom validator for hierarchical ID prefix\r\n const hierarchicalIdValidator = (\r\n control: AbstractControl\r\n ): ValidationErrors | null => {\r\n const entry = this.entry();\r\n if (!entry || entry.idLocked || !entry.hierarchical || !entry.parentId) {\r\n return null;\r\n }\r\n const id = control.value?.trim();\r\n if (!id) {\r\n return null;\r\n }\r\n const prefix = entry.parentId + '.';\r\n if (!id.startsWith(prefix) || id.length <= prefix.length) {\r\n return { hierarchicalPrefix: { requiredPrefix: prefix } };\r\n }\r\n return null;\r\n };\r\n\r\n // form controls\r\n this.id = new FormControl<string>((data as EditedThesEntry)?.id || '', {\r\n nonNullable: true,\r\n validators: [\r\n Validators.required,\r\n Validators.maxLength(300),\r\n idExistsValidator,\r\n hierarchicalIdValidator,\r\n ],\r\n });\r\n this.value = new FormControl<string>(\r\n (data as EditedThesEntry)?.value || '',\r\n {\r\n nonNullable: true,\r\n validators: [Validators.required, Validators.maxLength(500)],\r\n }\r\n );\r\n this.form = formBuilder.group({\r\n id: this.id,\r\n value: this.value,\r\n });\r\n }\r\n\r\n cancel(): void {\r\n this.dialogRef?.close();\r\n }\r\n\r\n save(): void {\r\n if (this.form.invalid) {\r\n return;\r\n }\r\n const old = this.entry()!;\r\n\r\n // save data and close the dialog\r\n this.dialogRef?.close({\r\n id: old.idLocked ? old.id : this.id.value?.trim(),\r\n value: this.value.value?.trim(),\r\n } as EditedThesEntry);\r\n }\r\n}\r\n","<form [formGroup]=\"form\" (submit)=\"save()\" [class.wrapped]=\"wrapped\">\r\n <fieldset>\r\n <legend>entry</legend>\r\n <div class=\"form-row\">\r\n <!-- id -->\r\n @if (entry()!.idLocked) {\r\n <span class=\"readonly\">{{ entry()!.id }}</span>\r\n } @else {\r\n <mat-form-field>\r\n <mat-label>ID</mat-label>\r\n <input matInput [formControl]=\"id\" />\r\n @if ($any(id).errors?.required && (id.dirty || id.touched)) {\r\n <mat-error>ID required</mat-error>\r\n } @if ($any(id).errors?.maxLength && (id.dirty || id.touched)) {\r\n <mat-error>ID too long</mat-error>\r\n } @if ($any(id).errors?.idExists && (id.dirty || id.touched)) {\r\n <mat-error>ID already exists</mat-error>\r\n } @if ($any(id).errors?.requiredPrefix && (id.dirty || id.touched)) {\r\n <mat-error>ID must start with \"{{ entry()!.parentId }}.\"</mat-error>\r\n }\r\n <!-- hint -->\r\n @if (entry()?.parentId) {\r\n <mat-hint>parent: {{ entry()!.parentId }}</mat-hint>\r\n }\r\n </mat-form-field>\r\n }\r\n <!-- value -->\r\n <mat-form-field>\r\n <mat-label>value</mat-label>\r\n <input matInput [formControl]=\"value\" />\r\n @if ($any(value).errors?.required && (value.dirty || value.touched)) {\r\n <mat-error>value required</mat-error>\r\n } @if ($any(value).errors?.maxLength && (value.dirty || value.touched))\r\n {\r\n <mat-error>value too long</mat-error>\r\n }\r\n </mat-form-field>\r\n </div>\r\n <!-- buttons -->\r\n <div>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Discard changes\"\r\n (click)=\"cancel()\"\r\n >\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=\"Accept changes\"\r\n [disabled]=\"form.invalid || form.pristine\"\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","import {\r\n ChangeDetectorRef,\r\n Component,\r\n OnDestroy,\r\n computed,\r\n effect,\r\n inject,\r\n input,\r\n output,\r\n signal,\r\n} from '@angular/core';\r\nimport { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';\r\nimport { Subscription } from 'rxjs';\r\n\r\nimport { MatDialog } from '@angular/material/dialog';\r\nimport { MatProgressBarModule } from '@angular/material/progress-bar';\r\nimport { MatButtonModule } from '@angular/material/button';\r\nimport { MatCheckboxModule } from '@angular/material/checkbox';\r\nimport { MatIconModule } from '@angular/material/icon';\r\nimport { MatTooltipModule } from '@angular/material/tooltip';\r\nimport { MatInputModule } from '@angular/material/input';\r\nimport { MatFormFieldModule } from '@angular/material/form-field';\r\nimport { MatMenuModule } from '@angular/material/menu';\r\nimport { MatSnackBar } from '@angular/material/snack-bar';\r\n\r\nimport { DialogService } from '@myrmidon/ngx-mat-tools';\r\nimport {\r\n BrowserTreeNodeComponent,\r\n PagedTreeStore,\r\n PageChangeRequest,\r\n} from '@myrmidon/paged-data-browsers';\r\n\r\nimport { ThesaurusPagedTreeFilterComponent } from '../thesaurus-paged-tree-filter/thesaurus-paged-tree-filter.component';\r\nimport {\r\n ThesaurusEntryNodeFilter,\r\n ThesaurusEntryPagedTreeNode,\r\n} from '../../services/static-thesaurus-paged-tree-store.service';\r\nimport {\r\n EditedThesEntry,\r\n ThesEntryEditorComponent,\r\n} from '../thesaurus-entry-editor/thesaurus-entry-editor.component';\r\nimport { EditableStaticThesaurusPagedTreeStoreService } from '../../services/editable-static-thesaurus-paged-tree-store.service';\r\n\r\n/**\r\n * An editable paged tree browser for thesaurus entries. Editing happens in memory\r\n * and when complete, the changes can be committed to the underlying data store\r\n * via the EditableStaticThesaurusPagedTreeStoreService.\r\n */\r\n@Component({\r\n selector: 'cadmus-editable-thesaurus-browser',\r\n imports: [\r\n ReactiveFormsModule,\r\n MatButtonModule,\r\n MatCheckboxModule,\r\n MatFormFieldModule,\r\n MatIconModule,\r\n MatInputModule,\r\n MatMenuModule,\r\n MatProgressBarModule,\r\n MatTooltipModule,\r\n ThesaurusPagedTreeFilterComponent,\r\n BrowserTreeNodeComponent,\r\n ],\r\n templateUrl: './editable-thesaurus-browser.component.html',\r\n styleUrls: ['./editable-thesaurus-browser.component.scss'],\r\n})\r\nexport class EditableThesaurusBrowserComponent implements OnDestroy {\r\n private _dialog = inject(MatDialog);\r\n private _snackBar = inject(MatSnackBar);\r\n private _dialogService = inject(DialogService);\r\n private _cdr = inject(ChangeDetectorRef);\r\n private _nodesSub?: Subscription;\r\n private _filterSub?: Subscription;\r\n private _changesSub?: Subscription;\r\n\r\n /**\r\n * The editable service to use to load the nodes.\r\n */\r\n public readonly service =\r\n input<EditableStaticThesaurusPagedTreeStoreService>();\r\n\r\n /**\r\n * True to show the tree root nodes filter.\r\n */\r\n public readonly hasRootFilter = input<boolean>(false);\r\n\r\n /**\r\n * Emitted when a node is clicked.\r\n */\r\n public readonly nodePick = output<ThesaurusEntryPagedTreeNode>();\r\n\r\n /**\r\n * Emitted when the changes state changes.\r\n */\r\n public readonly changesStateChange = output<boolean>();\r\n\r\n /**\r\n * The store instance, built from the service.\r\n */\r\n public readonly store = computed(() => {\r\n const service = this.service();\r\n if (!service) {\r\n return null;\r\n }\r\n return new PagedTreeStore<\r\n ThesaurusEntryPagedTreeNode,\r\n ThesaurusEntryNodeFilter\r\n >(service);\r\n });\r\n\r\n public readonly loading = signal<boolean>(false);\r\n public readonly selectedNode = signal<ThesaurusEntryPagedTreeNode | null>(\r\n null,\r\n );\r\n\r\n // Signals for reactive data binding (replacing observables with async pipe)\r\n public readonly nodes = signal<readonly ThesaurusEntryPagedTreeNode[]>([]);\r\n public readonly filter = signal<Readonly<ThesaurusEntryNodeFilter>>({});\r\n\r\n public debug: FormControl<boolean> = new FormControl(false, {\r\n nonNullable: true,\r\n });\r\n public hideLoc: FormControl<boolean> = new FormControl(false, {\r\n nonNullable: true,\r\n });\r\n public hideFilter: FormControl<boolean> = new FormControl(false, {\r\n nonNullable: true,\r\n });\r\n\r\n public label: FormControl<string | null> = new FormControl(null);\r\n public form = new FormGroup({\r\n label: this.label,\r\n });\r\n\r\n constructor() {\r\n // Use effect to react to service/store changes.\r\n effect(() => {\r\n const currentStore = this.store();\r\n const currentService = this.service();\r\n\r\n // Cleanup previous subscriptions\r\n this._nodesSub?.unsubscribe();\r\n this._filterSub?.unsubscribe();\r\n this._changesSub?.unsubscribe();\r\n\r\n if (!currentStore || !currentService) {\r\n this.nodes.set([]);\r\n this.filter.set({});\r\n return;\r\n }\r\n\r\n // Subscribe to store's observables and update signals.\r\n // markForCheck() is required because subscription callbacks run outside\r\n // Angular's reactive context, and some Angular apps use OnPush change\r\n // detection or zoneless mode.\r\n this._nodesSub = currentStore.nodes$.subscribe((nodes) => {\r\n this.nodes.set(nodes);\r\n this._cdr.markForCheck();\r\n });\r\n this._filterSub = currentStore.filter$.subscribe((filter) => {\r\n this.filter.set(filter);\r\n this._cdr.markForCheck();\r\n });\r\n\r\n // Subscribe to changes state\r\n this._changesSub = currentService.hasChanges$.subscribe((hasChanges) => {\r\n this.changesStateChange.emit(hasChanges);\r\n this._cdr.markForCheck();\r\n });\r\n\r\n // Load nodes if store is empty\r\n if (!currentStore.getNodes().length) {\r\n this.loading.set(true);\r\n currentStore.setFilter({}).finally(() => {\r\n this.loading.set(false);\r\n this._cdr.markForCheck();\r\n });\r\n }\r\n });\r\n }\r\n\r\n public ngOnDestroy(): void {\r\n this._nodesSub?.unsubscribe();\r\n this._filterSub?.unsubscribe();\r\n this._changesSub?.unsubscribe();\r\n }\r\n\r\n public reset(): void {\r\n const store = this.store();\r\n if (!store) return;\r\n\r\n this.loading.set(true);\r\n store.reset().finally(() => {\r\n this.loading.set(false);\r\n this._cdr.markForCheck();\r\n });\r\n }\r\n\r\n public onToggleExpanded(node: ThesaurusEntryPagedTreeNode): void {\r\n const store = this.store();\r\n if (!store) return;\r\n\r\n this.loading.set(true);\r\n if (node.expanded) {\r\n store.collapse(node.id).finally(() => {\r\n this.loading.set(false);\r\n this._cdr.markForCheck();\r\n });\r\n } else {\r\n store.expand(node.id).finally(() => {\r\n this.loading.set(false);\r\n this._cdr.markForCheck();\r\n });\r\n }\r\n }\r\n\r\n public onPageChangeRequest(request: PageChangeRequest): void {\r\n const store = this.store();\r\n if (!store) return;\r\n\r\n this.loading.set(true);\r\n store.changePage(request.node.id, request.paging.pageNumber).finally(() => {\r\n this.loading.set(false);\r\n this._cdr.markForCheck();\r\n });\r\n }\r\n\r\n public onFilterChange(\r\n filter: ThesaurusEntryNodeFilter | null | undefined,\r\n ): void {\r\n const store = this.store();\r\n if (!store) return;\r\n\r\n console.log('filter change', filter);\r\n this.loading.set(true);\r\n store.setFilter(filter || {}).finally(() => {\r\n this.loading.set(false);\r\n this._cdr.markForCheck();\r\n });\r\n }\r\n\r\n public onEditFilterRequest(node: ThesaurusEntryPagedTreeNode): void {\r\n const store = this.store();\r\n if (!store) return;\r\n\r\n const dialogRef = this._dialog.open(ThesaurusPagedTreeFilterComponent, {\r\n data: {\r\n filter: node.filter,\r\n },\r\n });\r\n dialogRef.afterClosed().subscribe((filter) => {\r\n if (filter === null) {\r\n store.setNodeFilter(node.id, null);\r\n } else if (filter) {\r\n store.setNodeFilter(node.id, filter);\r\n }\r\n });\r\n }\r\n\r\n public expandAll(): void {\r\n const store = this.store();\r\n if (!store) return;\r\n store.expandAll();\r\n }\r\n\r\n public collapseAll(): void {\r\n const store = this.store();\r\n if (!store) return;\r\n store.collapseAll();\r\n }\r\n\r\n public clear(): void {\r\n const store = this.store();\r\n if (!store) return;\r\n store.clear();\r\n }\r\n\r\n public onNodeClick(node: ThesaurusEntryPagedTreeNode): void {\r\n this.selectedNode.set(node);\r\n if (!node.hasChildren) {\r\n this.nodePick.emit(node);\r\n }\r\n }\r\n\r\n public findLabels(): void {\r\n const store = this.store();\r\n if (!store || !this.label.value) return;\r\n store.findLabels(this.label.value);\r\n }\r\n\r\n public removeHilites(): void {\r\n const store = this.store();\r\n if (!store) return;\r\n store.removeHilites();\r\n }\r\n\r\n // editing operations\r\n private editEntry(entry: EditedThesEntry): Promise<EditedThesEntry | null> {\r\n return new Promise((resolve) => {\r\n const dialogRef = this._dialog.open(ThesEntryEditorComponent, {\r\n data: entry,\r\n });\r\n\r\n dialogRef.afterClosed().subscribe((result) => {\r\n resolve(result);\r\n });\r\n });\r\n }\r\n\r\n public async addChild(): Promise<void> {\r\n const store = this.store();\r\n const selected = this.selectedNode();\r\n if (!store || !selected) {\r\n this._snackBar.open('Please select a node first', 'Close', {\r\n duration: 2000,\r\n });\r\n return;\r\n }\r\n\r\n // get the current entries to check for duplicates\r\n const currentService = this.service();\r\n if (!currentService) return;\r\n\r\n // determine the parent ID for the new child\r\n const parentKey = selected.key; // original entry ID\r\n\r\n // edit the new entry\r\n const newEntry = await this.editEntry({\r\n id: '',\r\n value: '',\r\n hierarchical: true,\r\n parentId: parentKey,\r\n idExists: (id: string) =>\r\n currentService.getCurrentEntries().some((e) => e.id === id),\r\n });\r\n if (!newEntry) {\r\n return;\r\n }\r\n\r\n store\r\n .addChild(selected.id, {\r\n label: newEntry.value,\r\n y: 0, // will be calculated by the store\r\n x: 0, // will be calculated by the store\r\n tag: selected.tag,\r\n })\r\n .then((result) => {\r\n if (result) {\r\n // update the temporary node with the user-provided ID,\r\n // this will be handled in the service's nodeToEntry method\r\n (result as any)._userProvidedId = newEntry.id;\r\n this._snackBar.open('Child added successfully', 'Close', {\r\n duration: 2000,\r\n });\r\n }\r\n });\r\n }\r\n\r\n public async addSibling(): Promise<void> {\r\n const store = this.store();\r\n const selected = this.selectedNode();\r\n if (!store || !selected) {\r\n this._snackBar.open('Please select a node first', 'Close', {\r\n duration: 2000,\r\n });\r\n return;\r\n }\r\n\r\n // get the current entries to check for duplicates\r\n const currentService = this.service();\r\n if (!currentService) return;\r\n\r\n const selectedKey = (selected as any).key; // original entry ID\r\n\r\n // determine the parent ID for the new sibling\r\n const selectedParts = selectedKey.split('.');\r\n const parentKey =\r\n selectedParts.length > 1 ? selectedParts.slice(0, -1).join('.') : '';\r\n\r\n const newEntry = await this.editEntry({\r\n id: '',\r\n value: '',\r\n hierarchical: true,\r\n parentId: parentKey,\r\n idExists: (id: string) =>\r\n currentService.getCurrentEntries().some((e) => e.id === id),\r\n });\r\n if (!newEntry) {\r\n return;\r\n }\r\n\r\n // check that the new ID has the same depth\r\n if (newEntry.id.split('.').length !== selectedParts.length) {\r\n this._snackBar.open(\r\n `Sibling must have same depth as \"${selectedKey}\"`,\r\n 'Close',\r\n { duration: 3000 },\r\n );\r\n return;\r\n }\r\n\r\n store\r\n .addSibling(selected.id, {\r\n label: newEntry.value,\r\n tag: selected.tag,\r\n })\r\n .then((result) => {\r\n if (result) {\r\n // update the temporary node with the user-provided ID\r\n (result as any)._userProvidedId = newEntry.id;\r\n this._snackBar.open('Sibling added successfully', 'Close', {\r\n duration: 2000,\r\n });\r\n }\r\n });\r\n }\r\n\r\n public removeNode(): void {\r\n const store = this.store();\r\n const selected = this.selectedNode();\r\n if (!store || !selected) {\r\n this._snackBar.open('Please select a node first', 'Close', {\r\n duration: 2000,\r\n });\r\n return;\r\n }\r\n\r\n const selectedKey = (selected as any).key || `temp_${selected.id}`;\r\n this._dialogService\r\n .confirm(\r\n 'Confirm Deletion',\r\n `Delete \"${selectedKey}\" (${selected.label}) and all its descendants?`,\r\n )\r\n .subscribe((result) => {\r\n if (!result) {\r\n return;\r\n }\r\n store.removeNode(selected.id).then((result) => {\r\n if (result) {\r\n this.selectedNode.set(null);\r\n this._snackBar.open('Node removed successfully', 'Close', {\r\n duration: 2000,\r\n });\r\n }\r\n });\r\n });\r\n }\r\n\r\n public async editNode(): Promise<void> {\r\n const currentService = this.service();\r\n if (!currentService) return;\r\n\r\n const store = this.store();\r\n const selected = this.selectedNode();\r\n if (!store || !selected) {\r\n this._snackBar.open('Please select a node first', 'Close', {\r\n duration: 2000,\r\n });\r\n return;\r\n }\r\n\r\n const selectedKey = selected.key;\r\n const isNewNode = selected.id < 0; // temporary ID means it's a new node\r\n\r\n const newEntry = await this.editEntry({\r\n id: selectedKey || '',\r\n value: selected.label,\r\n idLocked: !isNewNode,\r\n idExists: (id: string) =>\r\n currentService.getCurrentEntries().some((entry) => entry.id === id),\r\n });\r\n if (!newEntry) return;\r\n\r\n store\r\n .replaceNode(selected.id, {\r\n label: newEntry.value,\r\n tag: selected.tag,\r\n })\r\n .then((result) => {\r\n if (result) {\r\n // update the temporary node with the user-provided ID if it's a new node\r\n if (isNewNode) {\r\n (result as any)._userProvidedId = newEntry.id;\r\n }\r\n this._snackBar.open('Node updated successfully', 'Close', {\r\n duration: 2000,\r\n });\r\n }\r\n });\r\n }\r\n}\r\n","<div id=\"container\">\r\n <!-- filters -->\r\n <div id=\"filters\" class=\"form-row\">\r\n <form [formGroup]=\"form\" (submit)=\"findLabels()\">\r\n <fieldset>\r\n <legend>finder</legend>\r\n <div 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 {\r\n <mat-error>label required</mat-error>\r\n }\r\n </mat-form-field>\r\n <div class=\"form-row\" style=\"gap: 0\">\r\n <button type=\"submit\" mat-icon-button class=\"mat-primary\">\r\n <mat-icon>search</mat-icon>\r\n </button>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n (click)=\"removeHilites()\"\r\n class=\"mat-warn\"\r\n >\r\n <mat-icon>clear</mat-icon>\r\n </button>\r\n </div>\r\n </div>\r\n </fieldset>\r\n </form>\r\n @if (hasRootFilter()) {\r\n <fieldset>\r\n <legend>global filter</legend>\r\n <cadmus-thesaurus-paged-tree-filter\r\n [filter]=\"filter()\"\r\n (filterChange)=\"onFilterChange($event)\"\r\n />\r\n </fieldset>\r\n }\r\n </div>\r\n\r\n <!-- editing actions -->\r\n <div class=\"editing-actions\">\r\n <button\r\n type=\"button\"\r\n mat-raised-button\r\n color=\"primary\"\r\n [disabled]=\"!selectedNode()\"\r\n [matMenuTriggerFor]=\"addMenu\"\r\n >\r\n <mat-icon>add</mat-icon>\r\n add\r\n </button>\r\n\r\n <mat-menu #addMenu=\"matMenu\">\r\n <button type=\"button\" mat-menu-item (click)=\"addChild()\">\r\n <mat-icon>subdirectory_arrow_right</mat-icon>\r\n add child\r\n </button>\r\n <button type=\"button\" mat-menu-item (click)=\"addSibling()\">\r\n <mat-icon>arrow_right_alt</mat-icon>\r\n add sibling\r\n </button>\r\n </mat-menu>\r\n\r\n <button\r\n type=\"button\"\r\n mat-stroked-button\r\n color=\"accent\"\r\n [disabled]=\"!selectedNode()\"\r\n (click)=\"editNode()\"\r\n >\r\n <mat-icon>edit</mat-icon>\r\n edit\r\n </button>\r\n\r\n <button\r\n type=\"button\"\r\n mat-stroked-button\r\n color=\"warn\"\r\n [disabled]=\"!selectedNode()\"\r\n (click)=\"removeNode()\"\r\n >\r\n <mat-icon>delete</mat-icon>\r\n remove\r\n </button>\r\n\r\n @if (selectedNode()) {\r\n <span class=\"selected-info\"> selected: {{ selectedNode()!.label }} </span>\r\n }\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(); as nodeList) {\r\n <div>\r\n @for (node of nodeList; track node.id; let i = $index) {\r\n <div\r\n class=\"button-row\"\r\n [class.hilite]=\"node.hilite\"\r\n [class.selected]=\"selectedNode()?.id === node.id\"\r\n (click)=\"onNodeClick(node)\"\r\n >\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 < nodeList.length &&\r\n nodeList[i + 1].paging.pageCount > 1\r\n ? nodeList[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 </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","import { Observable, of } from 'rxjs';\r\n\r\nimport { DataPage } from '@myrmidon/ngx-tools';\r\nimport {\r\n PagedTreeNode,\r\n PagedTreeStoreService,\r\n TreeNodeFilter,\r\n} from '@myrmidon/paged-data-browsers';\r\nimport { ThesaurusEntry } from '@myrmidon/cadmus-core';\r\n\r\n/**\r\n * The filter for thesaurus entry nodes. The only filtered property is\r\n * the node's label.\r\n */\r\nexport interface ThesaurusEntryNodeFilter extends TreeNodeFilter {\r\n label?: string;\r\n}\r\n\r\n/**\r\n * The tree node for thesaurus entries in a paging tree node.\r\n */\r\nexport interface ThesaurusEntryPagedTreeNode extends PagedTreeNode<ThesaurusEntryNodeFilter> {\r\n key: string; // entry.id\r\n value: string; // entry.value (not rendered; the rendered value is in label)\r\n}\r\n\r\n/**\r\n * A label rendering function which removes from a label\r\n * all the characters past the last colon, trimming the result.\r\n * This is a typical rendering when dealing with hierarchical\r\n * thesaurus entries, e.g. \"furniture: table: color\", where\r\n * we can shorten the label to just \"color\", as \"furniture\"\r\n * and \"table\" are its ancestors.\r\n */\r\nexport function renderLabelFromLastColon(label: string): string {\r\n if (!label) {\r\n return label;\r\n }\r\n const i = label.lastIndexOf(':');\r\n return i > -1 && i + 1 < label.length ? label.substring(i + 1).trim() : label;\r\n}\r\n\r\ninterface NumberedEntry extends ThesaurusEntry {\r\n n: number;\r\n}\r\n\r\n/**\r\n * A static paged tree store service for thesaurus entries.\r\n * This builds tree nodes from all the thesaurus entries from a specific\r\n * thesaurus, assuming that entry IDs are hierarchical and\r\n * separated by dots (.).\r\n * Nodes are received all at once for a thesaurus, so this is essentially\r\n * an adapter to the paged tree store service interface.\r\n * The entries are a flat list where hierarchy is implied by the IDs:\r\n * for instance, \"animal.mammal.dog\" is a child of \"animal.mammal\"\r\n * which is a child of \"animal\". Numeric IDs are added to each node\r\n * based on the order of entries to ensure stable IDs.\r\n * The label of each node can be rendered as-is from the entry value,\r\n * or a custom rendering function can be provided to the constructor.\r\n */\r\nexport class StaticThesaurusPagedTreeStoreService implements PagedTreeStoreService<ThesaurusEntryNodeFilter> {\r\n private _nodes: ThesaurusEntryPagedTreeNode[] = [];\r\n private _built = false;\r\n private readonly _entries: NumberedEntry[];\r\n\r\n /**\r\n * Constructor.\r\n * @param entries The thesaurus entries.\r\n * @param _renderLabel An optional function to render the label\r\n * of each node.\r\n */\r\n constructor(\r\n entries: ThesaurusEntry[],\r\n private _renderLabel?: (label: string) => string,\r\n ) {\r\n // assign a number to each entry for stable IDs\r\n this._entries = entries.map((entry, index) => ({\r\n ...entry,\r\n n: index + 1,\r\n }));\r\n }\r\n\r\n /**\r\n * Ensure that nodes have been built from entries.\r\n */\r\n private ensureNodes(): void {\r\n // lazily build the nodes only once\r\n if (this._built) {\r\n return;\r\n }\r\n\r\n // create a map of sibling numbers (x) where:\r\n // - key=node.id (0 is used for the virtual root);\r\n // - value=max x value for that parent.\r\n const xMap = new Map<number, number>();\r\n\r\n // build nodes from entries\r\n for (const entry of this._entries) {\r\n const hasDot = entry.id.includes('.');\r\n const keyParts = entry.id.split('.');\r\n\r\n // create the node\r\n const node: ThesaurusEntryPagedTreeNode = {\r\n id: entry.n,\r\n label:\r\n hasDot && this._renderLabel\r\n ? this._renderLabel(entry.value)\r\n : entry.value,\r\n key: entry.id,\r\n value: entry.value,\r\n paging: { pageNumber: 0, pageCount: 0, total: 0 },\r\n y: hasDot ? keyParts.length : 1,\r\n x: 0, // will be set later\r\n parentId: undefined, // will be set later\r\n hasChildren: false, // will be set later\r\n };\r\n\r\n // if it has a dot, find its parent and set parentId\r\n if (hasDot) {\r\n // build the parent key\r\n const parentKey = keyParts.slice(0, keyParts.length - 1).join('.');\r\n // find the parent node with that key\r\n const parentNode = this._nodes.find((n) => n.key === parentKey);\r\n // if found, set parentId and x in child and hasChildren in parent\r\n if (parentNode) {\r\n node.parentId = parentNode.id;\r\n parentNode.hasChildren = true;\r\n if (xMap.has(parentNode.id)) {\r\n xMap.set(parentNode.id, xMap.get(parentNode.id)! + 1);\r\n } else {\r\n xMap.set(parentNode.id, 1);\r\n }\r\n node.x = xMap.get(parentNode.id)!;\r\n } else {\r\n // parent not found, treat as root\r\n if (xMap.has(0)) {\r\n xMap.set(0, xMap.get(0)! + 1);\r\n } else {\r\n xMap.set(0, 1);\r\n }\r\n node.x = xMap.get(0)!;\r\n }\r\n } else {\r\n // else it's a root node\r\n if (xMap.has(0)) {\r\n xMap.set(0, xMap.get(0)! + 1);\r\n } else {\r\n xMap.set(0, 1);\r\n }\r\n node.x = xMap.get(0)!;\r\n }\r\n\r\n this._nodes.push(node);\r\n }\r\n\r\n this._built = true;\r\n }\r\n\r\n /**\r\n * Get the specified page of nodes.\r\n * @param filter The filter.\r\n * @param pageNumber The page number.\r\n * @param pageSize The page size.\r\n * @param hasMockRoot Whether the root node is a mock node. Not used here.\r\n */\r\n public getNodes(\r\n filter: ThesaurusEntryNodeFilter,\r\n pageNumber: number,\r\n pageSize: number,\r\n hasMockRoot?: boolean,\r\n ): Observable<DataPage<ThesaurusEntryPagedTreeNode>> {\r\n console.log('[StaticThesaurusService] getNodes called, entries count:', this._entries.length, 'filter:', filter);\r\n this.ensureNodes();\r\n console.log('[StaticThesaurusService] after ensureNodes, _nodes count:', this._nodes.length);\r\n\r\n // apply filtering\r\n let nodes = this._nodes.filter((n) => {\r\n // filter by parentId (required by tree structure)\r\n if (filter.parentId !== undefined && filter.parentId !== null) {\r\n if (n.parentId !== filter.parentId) {\r\n return false;\r\n }\r\n } else {\r\n if (n.parentId) {\r\n return false;\r\n }\r\n }\r\n\r\n // filter by label\r\n if (filter.label) {\r\n const filterValue = filter.label.toLowerCase();\r\n if (!n.label.toLowerCase().includes(filterValue)) {\r\n return false;\r\n }\r\n }\r\n return true;\r\n });\r\n\r\n // page and return\r\n const paged = nodes.slice(\r\n (pageNumber - 1) * pageSize,\r\n pageNumber * pageSize,\r\n );\r\n console.log('[StaticThesaurusService] getNodes returning', paged.length, 'items (filtered from', nodes.length, 'total root nodes)');\r\n return of({\r\n items: paged,\r\n pageNumber: pageNumber,\r\n pageSize: pageSize,\r\n pageCount: Math.ceil(nodes.length / pageSize),\r\n total: nodes.length,\r\n });\r\n }\r\n}\r\n","import {\r\n ChangeDetectorRef,\r\n Component,\r\n OnDestroy,\r\n computed,\r\n effect,\r\n inject,\r\n input,\r\n output,\r\n signal,\r\n} from '@angular/core';\r\nimport { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';\r\nimport { Subscription } from 'rxjs';\r\n\r\nimport { MatDialog } from '@angular/material/dialog';\r\nimport { MatProgressBarModule } from '@angular/material/progress-bar';\r\nimport { MatButtonModule } from '@angular/material/button';\r\nimport { MatCheckboxModule } from '@angular/material/checkbox';\r\nimport { MatIconModule } from '@angular/material/icon';\r\nimport { MatTooltipModule } from '@angular/material/tooltip';\r\nimport { MatInputModule } from '@angular/material/input';\r\nimport { MatFormFieldModule } from '@angular/material/form-field';\r\n\r\nimport {\r\n BrowserTreeNodeComponent,\r\n PagedTreeStore,\r\n PageChangeRequest,\r\n} from '@myrmidon/paged-data-browsers';\r\n\r\nimport {\r\n renderLabelFromLastColon,\r\n StaticThesaurusPagedTreeStoreService,\r\n ThesaurusEntryNodeFilter,\r\n ThesaurusEntryPagedTreeNode,\r\n} from '../../services/static-thesaurus-paged-tree-store.service';\r\nimport { ThesaurusPagedTreeFilterComponent } from '../thesaurus-paged-tree-filter/thesaurus-paged-tree-filter.component';\r\n\r\n/**\r\n * A readonly paged tree browser for thesaurus entries. This is a lower-level component\r\n * used as an adapter between the generic paged tree browser and the thesaurus entries\r\n * data model.\r\n */\r\n@Component({\r\n selector: 'cadmus-thesaurus-browser',\r\n imports: [\r\n ReactiveFormsModule,\r\n MatButtonModule,\r\n MatCheckboxModule,\r\n MatFormFieldModule,\r\n MatIconModule,\r\n MatInputModule,\r\n MatProgressBarModule,\r\n MatTooltipModule,\r\n ThesaurusPagedTreeFilterComponent,\r\n BrowserTreeNodeComponent,\r\n ],\r\n templateUrl: './thesaurus-browser.component.html',\r\n styleUrl: './thesaurus-browser.component.scss',\r\n})\r\nexport class ThesaurusBrowserComponent implements OnDestroy {\r\n private _dialog = inject(MatDialog);\r\n private _cdr = inject(ChangeDetectorRef);\r\n private _nodesSub?: Subscription;\r\n private _filterSub?: Subscription;\r\n\r\n /**\r\n * The service to use to load the nodes.\r\n */\r\n public readonly service = input<StaticThesaurusPagedTreeStoreService>(\r\n new StaticThesaurusPagedTreeStoreService([], renderLabelFromLastColon),\r\n );\r\n\r\n /**\r\n * Emitted when a node is clicked.\r\n */\r\n public readonly nodePick = output<ThesaurusEntryPagedTreeNode>();\r\n\r\n /**\r\n * The store instance, built from the service.\r\n */\r\n public readonly store = computed(() => {\r\n const service = this.service();\r\n return new PagedTreeStore<\r\n ThesaurusEntryPagedTreeNode,\r\n ThesaurusEntryNodeFilter\r\n >(service);\r\n });\r\n\r\n public readonly loading = signal<boolean>(false);\r\n\r\n // Signals for reactive data binding (replacing observables with async pipe)\r\n public readonly nodes = signal<readonly ThesaurusEntryPagedTreeNode[]>([]);\r\n public readonly filter = signal<Readonly<ThesaurusEntryNodeFilter>>({});\r\n\r\n public debug: FormControl<boolean> = new FormControl(false, {\r\n nonNullable: true,\r\n });\r\n public hideLoc: FormControl<boolean> = new FormControl(false, {\r\n nonNullable: true,\r\n });\r\n public hideFilter: FormControl<boolean> = new FormControl(false, {\r\n nonNullable: true,\r\n });\r\n\r\n public label: FormControl<string | null> = new FormControl(null);\r\n public form = new FormGroup({\r\n label: this.label,\r\n });\r\n\r\n constructor() {\r\n // Use effect to react to service/store changes.\r\n effect(() => {\r\n const currentStore = this.store();\r\n console.log(\r\n '[ThesaurusBrowser] effect triggered, store:',\r\n currentStore ? 'exists' : 'null',\r\n );\r\n\r\n // Unsubscribe from previous store's observables\r\n this._nodesSub?.unsubscribe();\r\n this._filterSub?.unsubscribe();\r\n\r\n // Subscribe to new store's observables and update signals.\r\n // markForCheck() is required because subscription callbacks run outside\r\n // Angular's reactive context, and some Angular apps use OnPush change\r\n // detection or zoneless mode.\r\n this._nodesSub = currentStore.nodes$.subscribe((nodes) => {\r\n console.log(\r\n '[ThesaurusBrowser] nodes$ emitted, count:',\r\n nodes.length,\r\n 'nodes:',\r\n nodes.map((n) => n.label).slice(0, 3),\r\n );\r\n this.nodes.set(nodes);\r\n console.log(\r\n '[ThesaurusBrowser] nodes signal set, calling markForCheck',\r\n );\r\n this._cdr.markForCheck();\r\n });\r\n this._filterSub = currentStore.filter$.subscribe((filter) => {\r\n console.log('[ThesaurusBrowser] filter$ emitted:', filter);\r\n this.filter.set(filter);\r\n this._cdr.markForCheck();\r\n });\r\n\r\n // Load nodes if store is empty\r\n const storeNodes = currentStore.getNodes();\r\n console.log(\r\n '[ThesaurusBrowser] store.getNodes() count:',\r\n storeNodes.length,\r\n );\r\n if (!storeNodes.length) {\r\n console.log(\r\n '[ThesaurusBrowser] store is empty, calling setFilter to load',\r\n );\r\n this.loading.set(true);\r\n currentStore\r\n .setFilter({})\r\n .then(() => {\r\n console.log(\r\n '[ThesaurusBrowser] setFilter resolved, store nodes:',\r\n currentStore.getNodes().length,\r\n );\r\n })\r\n .finally(() => {\r\n console.log(\r\n '[ThesaurusBrowser] setFilter finally, setting loading=false',\r\n );\r\n this.loading.set(false);\r\n this._cdr.markForCheck();\r\n });\r\n }\r\n });\r\n }\r\n\r\n public ngOnDestroy(): void {\r\n this._nodesSub?.unsubscribe();\r\n this._filterSub?.unsubscribe();\r\n }\r\n\r\n public reset(): void {\r\n this.loading.set(true);\r\n this.store()\r\n .reset()\r\n .finally(() => {\r\n this.loading.set(false);\r\n this._cdr.markForCheck();\r\n });\r\n }\r\n\r\n public onToggleExpanded(node: ThesaurusEntryPagedTreeNode): void {\r\n this.loading.set(true);\r\n if (node.expanded) {\r\n this.store()\r\n .collapse(node.id)\r\n .finally(() => {\r\n this.loading.set(false);\r\n this._cdr.markForCheck();\r\n });\r\n } else {\r\n this.store()\r\n .expand(node.id)\r\n .finally(() => {\r\n this.loading.set(false);\r\n this._cdr.markForCheck();\r\n });\r\n }\r\n }\r\n\r\n public onPageChangeRequest(request: PageChangeRequest): void {\r\n this.loading.set(true);\r\n this.store()\r\n .changePage(request.node.id, request.paging.pageNumber)\r\n .finally(() => {\r\n this.loading.set(false);\r\n this._cdr.markForCheck();\r\n });\r\n }\r\n\r\n public onFilterChange(\r\n filter: ThesaurusEntryNodeFilter | null | undefined,\r\n ): void {\r\n console.log('filter change', filter);\r\n this.loading.set(true);\r\n this.store()\r\n .setFilter(filter || {})\r\n .finally(() => {\r\n this.loading.set(false);\r\n this._cdr.markForCheck();\r\n });\r\n }\r\n\r\n public onEditFilterRequest(node: ThesaurusEntryPagedTreeNode): void {\r\n const dialogRef = this._dialog.open(ThesaurusPagedTreeFilterComponent, {\r\n data: {\r\n filter: node.filter,\r\n },\r\n });\r\n dialogRef.afterClosed().subscribe((filter) => {\r\n // undefined = user dismissed without changes\r\n if (filter === null) {\r\n this.store().setNodeFilter(node.id, null);\r\n } else if (filter) {\r\n this.store().setNodeFilter(node.id, filter);\r\n }\r\n });\r\n }\r\n\r\n public expandAll(): void {\r\n this.store().expandAll();\r\n }\r\n\r\n public collapseAll(): void {\r\n this.store().collapseAll();\r\n }\r\n\r\n public clear(): void {\r\n this.store().clear();\r\n }\r\n\r\n public onNodeClick(node: ThesaurusEntryPagedTreeNode): void {\r\n if (!node.hasChildren) {\r\n this.nodePick.emit(node);\r\n }\r\n }\r\n\r\n public findLabels(): void {\r\n if (!this.label.value) {\r\n return;\r\n }\r\n this.store().findLabels(this.label.value);\r\n }\r\n\r\n public removeHilites(): void {\r\n this.store().removeHilites();\r\n }\r\n}\r\n","<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\r\n type=\"button\"\r\n mat-icon-button\r\n (click)=\"removeHilites()\"\r\n class=\"mat-warn\"\r\n >\r\n <mat-icon>clear</mat-icon>\r\n </button>\r\n </form>\r\n <fieldset>\r\n <legend>filter</legend>\r\n <cadmus-thesaurus-paged-tree-filter\r\n [filter]=\"filter()\"\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(); as nodeList) {\r\n <div>\r\n @for (node of nodeList; 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 < nodeList.length &&\r\n nodeList[i + 1].paging.pageCount > 1\r\n ? nodeList[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","import { Component, computed, effect, input, output, Type } from '@angular/core';\r\nimport { FormsModule, ReactiveFormsModule } from '@angular/forms';\r\nimport { ThesaurusEntry } from '@myrmidon/cadmus-core';\r\n\r\nimport { ThesaurusPagedTreeFilterComponent } from '../thesaurus-paged-tree-filter/thesaurus-paged-tree-filter.component';\r\nimport {\r\n renderLabelFromLastColon,\r\n StaticThesaurusPagedTreeStoreService,\r\n ThesaurusEntryPagedTreeNode,\r\n} from '../../services/static-thesaurus-paged-tree-store.service';\r\nimport { ThesaurusBrowserComponent } from '../thesaurus-browser/thesaurus-browser.component';\r\n\r\n/**\r\n * Thesaurus tree component.\r\n * This component displays a set of hierarchical thesaurus entries\r\n * in a tree, provided that each entry marks its hierarchy with\r\n * dots. For instance, say you have the hierarchy \"furniture\" -\r\n * \"type\" - \"color\". You might have an entry whose ID is\r\n * \"furniture.table.red\", with a sibling \"furniture.table.green\",\r\n * and a parent \"furniture.table\". This parent is there only to\r\n * provide a label to the parent node, but only leaf nodes can be\r\n * picked by the user. Whenever one is picked, the entryChange\r\n * event is emitted.\r\n */\r\n@Component({\r\n selector: 'cadmus-thesaurus-tree',\r\n templateUrl: './thesaurus-tree.component.html',\r\n styleUrls: ['./thesaurus-tree.component.css'],\r\n imports: [FormsModule, ReactiveFormsModule, ThesaurusBrowserComponent],\r\n})\r\nexport class ThesaurusTreeComponent {\r\n /**\r\n * The thesaurus entries.\r\n */\r\n public readonly entries = input<ThesaurusEntry[]>();\r\n\r\n /**\r\n * The optional node label rendering function. Note that even if you\r\n * specify a label renderer function, the entryChange event always\r\n * emits the original label.\r\n */\r\n public readonly renderLabel = input<(label: string) => string>(\r\n renderLabelFromLastColon,\r\n );\r\n\r\n /**\r\n * Fired when a thesaurus entry is selected.\r\n */\r\n public readonly entryChange = output<ThesaurusEntry>();\r\n\r\n /**\r\n * The tree store service, dependent on the current entries and renderLabel.\r\n */\r\n public readonly service = computed<StaticThesaurusPagedTreeStoreService>(() => {\r\n const entries = this.entries();\r\n console.log('[ThesaurusTree] service computed, entries count:', entries?.length ?? 0);\r\n return new StaticThesaurusPagedTreeStoreService(\r\n entries || [],\r\n this.renderLabel(),\r\n );\r\n });\r\n\r\n /**\r\n * Debug: tracks when the template condition would show the browser.\r\n */\r\n public readonly shouldShowBrowser = computed(() => {\r\n const svc = this.service();\r\n const entries = this.entries();\r\n const result = !!(svc && entries?.length);\r\n console.log('[ThesaurusTree] shouldShowBrowser computed:', result, '(service:', !!svc, ', entries:', entries?.length ?? 0, ')');\r\n return result;\r\n });\r\n\r\n constructor() {\r\n // Debug effect to trace when entries input changes\r\n effect(() => {\r\n const entries = this.entries();\r\n const svc = this.service();\r\n console.log('[ThesaurusTree] effect: entries changed, count:', entries?.length ?? 0, 'service:', svc ? 'exists' : 'null');\r\n });\r\n }\r\n\r\n /**\r\n * The filter component class to use.\r\n */\r\n public readonly filterComponent: Type<ThesaurusPagedTreeFilterComponent> =\r\n ThesaurusPagedTreeFilterComponent;\r\n\r\n public onNodePick(node: ThesaurusEntryPagedTreeNode): void {\r\n // only allow selection of leaf nodes (nodes without children)\r\n if (!node.hasChildren) {\r\n // find the original entry\r\n const entry = this.entries()?.find((e) => e.id === node.key);\r\n if (entry) {\r\n this.entryChange.emit(entry);\r\n }\r\n }\r\n }\r\n}\r\n","<div>\r\n <!-- tree -->\r\n @if (shouldShowBrowser()) {\r\n <div class=\"tree-wrapper\">\r\n <cadmus-thesaurus-browser\r\n [service]=\"service()\"\r\n (nodePick)=\"onNodePick($event)\"\r\n />\r\n </div>\r\n }\r\n</div>\r\n","import {\r\n Component,\r\n computed,\r\n effect,\r\n input,\r\n model,\r\n untracked,\r\n} from '@angular/core';\r\nimport { ThesaurusEntry } from '@myrmidon/cadmus-core';\r\nimport {\r\n FormBuilder,\r\n FormControl,\r\n FormGroup,\r\n ReactiveFormsModule,\r\n Validators,\r\n} from '@angular/forms';\r\n\r\nimport {\r\n CdkDragDrop,\r\n CdkDropList,\r\n CdkDrag,\r\n moveItemInArray,\r\n} from '@angular/cdk/drag-drop';\r\nimport {\r\n MatChipListbox,\r\n MatChipOption,\r\n MatChipRemove,\r\n} from '@angular/material/chips';\r\nimport { MatExpansionPanel } from '@angular/material/expansion';\r\nimport { MatFormField } from '@angular/material/form-field';\r\nimport { MatIcon } from '@angular/material/icon';\r\nimport { MatIconButton } from '@angular/material/button';\r\nimport { MatInput } from '@angular/material/input';\r\nimport { MatTooltip } from '@angular/material/tooltip';\r\n\r\nimport { renderLabelFromLastColon } from '../../services/static-thesaurus-paged-tree-store.service';\r\nimport { ThesaurusTreeComponent } from '../thesaurus-tree/thesaurus-tree.component';\r\n\r\n/**\r\n * The prefix added to custom entries' IDs.\r\n */\r\nexport const CUSTOM_ENTRY_PREFIX = '$';\r\n\r\n/**\r\n * A picker component for thesaurus entries.\r\n * This component allows picking one or more entries from a given thesaurus.\r\n * In its collapsed state, it shows the picked entries as chips; when\r\n * expanded, it shows the thesaurus tree to pick from. Custom entries\r\n * (not in the thesaurus) can be optionally allowed.\r\n */\r\n@Component({\r\n selector: 'cadmus-thesaurus-entries-picker',\r\n imports: [\r\n ReactiveFormsModule,\r\n CdkDropList,\r\n CdkDrag,\r\n MatChipListbox,\r\n MatChipOption,\r\n MatChipRemove,\r\n MatExpansionPanel,\r\n MatFormField,\r\n MatIconButton,\r\n MatIcon,\r\n MatInput,\r\n MatTooltip,\r\n ThesaurusTreeComponent,\r\n ],\r\n templateUrl: './thesaurus-entries-picker.component.html',\r\n styleUrl: './thesaurus-entries-picker.component.css',\r\n})\r\nexport class ThesaurusEntriesPickerComponent {\r\n /**\r\n * The thesaurus entries to pick from (required).\r\n */\r\n public readonly availableEntries = input.required<ThesaurusEntry[]>();\r\n\r\n /**\r\n * The picked entries.\r\n */\r\n public readonly entries = model<ThesaurusEntry[]>([]);\r\n\r\n /**\r\n * True to show the entries with labels shortened according to\r\n * their hierarchy.\r\n */\r\n public readonly hierarchicLabels = input<boolean>(false);\r\n\r\n /**\r\n * True to automatically sort the picked entries (disables drag-and-drop).\r\n * When false, entries can be manually reordered via drag-and-drop.\r\n */\r\n public readonly autoSort = input<boolean>(false);\r\n\r\n /**\r\n * True to allow custom values (not in the entries list).\r\n */\r\n public readonly allowCustom = input<boolean>(false);\r\n\r\n /**\r\n * The minimum number of entries to pick.\r\n */\r\n public readonly minEntries = input<number>(0);\r\n\r\n /**\r\n * The maximum number of entries to pick (0=unlimited).\r\n */\r\n public readonly maxEntries = input<number>(0);\r\n\r\n /**\r\n * True when the picker is expanded (showing the entries list).\r\n */\r\n public readonly expanded = model<boolean>(false);\r\n\r\n /**\r\n * The message to show when there are no picked entries.\r\n */\r\n public readonly emptyMessage = input<string>('no entries');\r\n\r\n /**\r\n * The number of remaining entries that can be picked (0=unlimited).\r\n * This is displayed only if maxEntries > 1.\r\n */\r\n public readonly remaining = computed(() => {\r\n if (this.maxEntries() > 0) {\r\n return this.maxEntries() - this.entries().length;\r\n }\r\n return 0;\r\n });\r\n\r\n public id: FormControl<string>;\r\n public value: FormControl<string>;\r\n public form: FormGroup;\r\n\r\n constructor(formBuilder: FormBuilder) {\r\n this.id = formBuilder.control<string>('', {\r\n validators: [Validators.required, Validators.maxLength(100)],\r\n nonNullable: true,\r\n });\r\n this.value = formBuilder.control<string>('', {\r\n validators: [Validators.required, Validators.maxLength(500)],\r\n nonNullable: true,\r\n });\r\n this.form = formBuilder.group({\r\n id: this.id,\r\n value: this.value,\r\n });\r\n // if auto-sort is turned on and we have entries, sort them\r\n effect(() => {\r\n // only track autoSort() changes, not entries()\r\n const shouldSort = this.autoSort();\r\n\r\n if (shouldSort) {\r\n // use untracked to read entries without creating a dependency\r\n const currentEntries = untracked(() => this.entries());\r\n if (currentEntries.length > 1) {\r\n const entries = [...currentEntries];\r\n this.sortEntries(entries);\r\n this.entries.set(entries);\r\n }\r\n }\r\n });\r\n }\r\n\r\n // need arrow function to use 'this'\r\n public renderLabel = (label: string): string => {\r\n return this.hierarchicLabels() ? renderLabelFromLastColon(label) : label;\r\n };\r\n\r\n private sortEntries(entries: ThesaurusEntry[]) {\r\n entries.sort((a: ThesaurusEntry, b: ThesaurusEntry) => {\r\n const aIsCustom = a.id?.startsWith(CUSTOM_ENTRY_PREFIX) ?? false;\r\n const bIsCustom = b.id?.startsWith(CUSTOM_ENTRY_PREFIX) ?? false;\r\n if (aIsCustom !== bIsCustom) {\r\n // place custom entries after non-custom ones\r\n return aIsCustom ? 1 : -1;\r\n }\r\n // same kind: sort by label/value\r\n return a.value.localeCompare(b.value);\r\n });\r\n }\r\n\r\n public onEntryChange(entry: ThesaurusEntry): void {\r\n // check if already present\r\n if (this.entries().some((e: ThesaurusEntry) => e.id === entry.id)) {\r\n return;\r\n }\r\n // check if limit is reached\r\n if (this.maxEntries() && this.entries().length >= this.maxEntries()) {\r\n return;\r\n }\r\n\r\n const entries = [...this.entries()];\r\n entries.push(entry);\r\n if (this.autoSort()) {\r\n this.sortEntries(entries);\r\n }\r\n this.entries.set(entries);\r\n }\r\n\r\n public addCustomEntry(): void {\r\n if (this.form.invalid) {\r\n return;\r\n }\r\n\r\n // create the custom entry\r\n const customEntry: ThesaurusEntry = {\r\n id: CUSTOM_ENTRY_PREFIX + this.id.value,\r\n value: this.value.value,\r\n };\r\n\r\n // check if already present\r\n if (this.entries().some((e: ThesaurusEntry) => e.id === customEntry.id)) {\r\n return;\r\n }\r\n // check if limit is reached\r\n if (this.maxEntries() && this.entries().length >= this.maxEntries()) {\r\n return;\r\n }\r\n const entries = [...this.entries()];\r\n entries.push(customEntry);\r\n if (this.autoSort()) {\r\n this.sortEntries(entries);\r\n }\r\n this.entries.set(entries);\r\n this.form.reset();\r\n }\r\n\r\n public removeEntry(entry: ThesaurusEntry): void {\r\n const entries = [...this.entries().filter((e) => e.id !== entry.id)];\r\n this.entries.set(entries);\r\n }\r\n\r\n public clear(): void {\r\n this.entries.set([]);\r\n // if min > 0, expand the picker\r\n if (this.minEntries() > 0 && !this.expanded()) {\r\n setTimeout(() => {\r\n this.expanded.set(true);\r\n }, 0);\r\n }\r\n }\r\n\r\n public onDrop(event: CdkDragDrop<ThesaurusEntry[]>): void {\r\n const entries = [...this.entries()];\r\n moveItemInArray(entries, event.previousIndex, event.currentIndex);\r\n this.entries.set(entries);\r\n }\r\n}\r\n","<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","import { Observable, of } from 'rxjs';\r\n\r\nimport { DataPage } from '@myrmidon/ngx-tools';\r\n\r\nimport {\r\n EditablePagedTreeStoreServiceBase,\r\n ChangeOperation,\r\n ChangeOperationType,\r\n TreeNode,\r\n} from '@myrmidon/paged-data-browsers';\r\nimport { ThesaurusEntry } from '@myrmidon/cadmus-core';\r\n\r\nimport {\r\n StaticThesaurusPagedTreeStoreService,\r\n ThesaurusEntryNodeFilter,\r\n ThesaurusEntryPagedTreeNode,\r\n} from './static-thesaurus-paged-tree-store.service';\r\n\r\n/**\r\n * Editable version of the static thesaurus paged tree store service.\r\n * This service allows editing operations on the flat ThesaurusEntry list\r\n * while maintaining the tree structure implied by the hierarchical IDs.\r\n */\r\nexport class EditableStaticThesaurusPagedTreeStoreService\r\n extends EditablePagedTreeStoreServiceBase<ThesaurusEntryNodeFilter> {\r\n private _entries: ThesaurusEntry[];\r\n private _staticService: StaticThesaurusPagedTreeStoreService;\r\n private _renderLabel?: (label: string) => string;\r\n\r\n constructor(\r\n entries: ThesaurusEntry[],\r\n renderLabel?: (label: string) => string,\r\n ) {\r\n super();\r\n this._entries = [...entries];\r\n this._renderLabel = renderLabel;\r\n this._staticService = new StaticThesaurusPagedTreeStoreService(\r\n this._entries,\r\n renderLabel,\r\n );\r\n }\r\n\r\n protected override fetchNodes(\r\n filter: ThesaurusEntryNodeFilter,\r\n pageNumber: number,\r\n pageSize: number,\r\n hasMockRoot?: boolean,\r\n ): Observable<DataPage<TreeNode>> {\r\n // update the static service with current entries and delegate,\r\n // preserving the renderLabel function\r\n this._staticService = new StaticThesaurusPagedTreeStoreService(\r\n this._entries,\r\n this._renderLabel,\r\n );\r\n return this._staticService.getNodes(\r\n filter,\r\n pageNumber,\r\n pageSize,\r\n hasMockRoot,\r\n );\r\n }\r\n\r\n protected override persistChanges(\r\n changes: ChangeOperation[],\r\n ): Observable<Map<number, number>> {\r\n console.log('=== SAVING CHANGES ===');\r\n console.log('Changes to persist:', changes);\r\n\r\n const idMap = new Map<number, number>();\r\n\r\n // process changes to update the flat entries list\r\n for (const change of changes) {\r\n switch (change.type) {\r\n case ChangeOperationType.ADD:\r\n if (change.node) {\r\n const newEntry = this.nodeToEntry(change.node);\r\n if (newEntry) {\r\n const existingIndex = this._entries.findIndex(\r\n (e) => e.id === newEntry.id,\r\n );\r\n if (existingIndex === -1) {\r\n this._entries.push(newEntry);\r\n\r\n // map temporary ID to the new permanent ID (array index + 1)\r\n if (change.node.id < 0) {\r\n const permanentId = this._entries.length;\r\n idMap.set(change.node.id, permanentId);\r\n }\r\n console.log('Added entry:', newEntry);\r\n } else {\r\n console.log('Entry already exists, skipping:', newEntry.id);\r\n }\r\n }\r\n }\r\n break;\r\n\r\n case ChangeOperationType.REMOVE:\r\n if (change.originalNode) {\r\n // use the 'key' property which contains the ThesaurusEntry string ID\r\n const nodeWithKey =\r\n change.originalNode as ThesaurusEntryPagedTreeNode;\r\n const entryKey = nodeWithKey.key;\r\n\r\n if (entryKey) {\r\n this.removeEntryAndDescendants(entryKey);\r\n console.log('Removed entry and descendants:', entryKey);\r\n } else {\r\n console.warn('Node missing key property:', change.originalNode);\r\n }\r\n } else if (change.id < 0) {\r\n console.log(\r\n 'Removed temporary node that was never persisted:',\r\n change.id,\r\n );\r\n } else {\r\n console.warn(\r\n 'Remove operation missing originalNode for ID:',\r\n change.id,\r\n );\r\n }\r\n break;\r\n\r\n case ChangeOperationType.UPDATE:\r\n if (change.node && change.originalNode) {\r\n const nodeWithKey =\r\n change.originalNode as ThesaurusEntryPagedTreeNode;\r\n const entryKey = nodeWithKey.key;\r\n\r\n if (entryKey) {\r\n const entryToUpdate = this._entries.find(\r\n (e) => e.id === entryKey,\r\n );\r\n\r\n if (entryToUpdate) {\r\n const updatedEntry = this.nodeToEntry(change.node);\r\n if (updatedEntry) {\r\n // preserve the original hierarchical ID\r\n updatedEntry.id = entryToUpdate.id;\r\n const index = this._entries.findIndex(\r\n (e) => e.id === entryToUpdate.id,\r\n );\r\n if (index !== -1) {\r\n this._entries[index] = updatedEntry;\r\n console.log('Updated entry:', updatedEntry);\r\n }\r\n }\r\n } else {\r\n console.warn(\r\n 'Could not find entry to update with key:',\r\n entryKey,\r\n );\r\n }\r\n } else {\r\n console.warn(\r\n 'Update node missing key property:',\r\n change.originalNode,\r\n );\r\n }\r\n } else if (change.id < 0) {\r\n console.log('Updated temporary node:', change.id);\r\n }\r\n break;\r\n }\r\n }\r\n\r\n // Validate no duplicate IDs\r\n const ids = this._entries.map((e) => e.id);\r\n const duplicates = ids.filter((id, index) => ids.indexOf(id) !== index);\r\n if (duplicates.length > 0) {\r\n console.error('Duplicate IDs found:', duplicates);\r\n }\r\n\r\n console.log('Final entries after changes:', this._entries);\r\n console.log('ID mappings:', idMap);\r\n console.log('=== END SAVING CHANGES ===');\r\n\r\n return of(idMap);\r\n }\r\n\r\n /**\r\n * Convert a TreeNode back to a ThesaurusEntry.\r\n */\r\n private nodeToEntry(node: TreeNode): ThesaurusEntry | null {\r\n // For nodes with the key property, use it directly\r\n const nodeWithKey = node as any;\r\n if (nodeWithKey.key) {\r\n return {\r\n id: nodeWithKey.key,\r\n value: node.label,\r\n };\r\n }\r\n\r\n // For temporary nodes (negative IDs), construct a hierarchical ID\r\n if (node.id < 0) {\r\n // Check for user-provided ID\r\n const userProvidedId = nodeWithKey._userProvidedId;\r\n\r\n if (userProvidedId) {\r\n return {\r\n id: userProvidedId,\r\n value: node.label,\r\n };\r\n }\r\n\r\n // Find parent to construct the ID\r\n if (node.parentId) {\r\n const parentNode = this._nodes.get(node.parentId) as any;\r\n const parentKey = parentNode?.key;\r\n if (parentKey) {\r\n return {\r\n id: `${parentKey}.temp${Math.abs(node.id)}`,\r\n value: node.label,\r\n };\r\n }\r\n }\r\n\r\n // No parent, create a root-level temporary entry\r\n return {\r\n id: `temp${Math.abs(node.id)}`,\r\n value: node.label,\r\n };\r\n }\r\n\r\n console.warn('Could not convert node to entry:', node);\r\n return null;\r\n }\r\n\r\n /**\r\n * Remove an entry and all its descendants from the entries list.\r\n */\r\n private removeEntryAndDescendants(entryId: string): void {\r\n const toRemove: string[] = [];\r\n\r\n // find the entry and all its descendants\r\n for (const entry of this._entries) {\r\n if (entry.id === entryId || entry.id.startsWith(entryId + '.')) {\r\n toRemove.push(entry.id);\r\n }\r\n }\r\n\r\n // remove them from the list\r\n for (const id of toRemove) {\r\n const index = this._entries.findIndex((e) => e.id === id);\r\n if (index !== -1) {\r\n this._entries.splice(index, 1);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Get current entries (for demonstration purposes).\r\n */\r\n public getCurrentEntries(): ThesaurusEntry[] {\r\n return [...this._entries];\r\n }\r\n}\r\n","/*\r\n * Public API Surface of cadmus-thesaurus-store\r\n */\r\n\r\nexport * from './lib/components/editable-thesaurus-browser/editable-thesaurus-browser.component';\r\nexport * from './lib/components/thesaurus-entries-picker/thesaurus-entries-picker.component';\r\nexport * from './lib/components/thesaurus-entry-editor/thesaurus-entry-editor.component';\r\nexport * from './lib/components/thesaurus-browser/thesaurus-browser.component';\r\nexport * from './lib/components/thesaurus-paged-tree-filter/thesaurus-paged-tree-filter.component';\r\nexport * from './lib/components/thesaurus-tree/thesaurus-tree.component';\r\n\r\nexport * from './lib/services/editable-static-thesaurus-paged-tree-store.service';\r\nexport * from './lib/services/static-thesaurus-paged-tree-store.service';\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":["i3","i4","i6","i2","i7"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -106,6 +106,7 @@ declare class EditableThesaurusBrowserComponent implements OnDestroy {
|
|
|
106
106
|
private _dialog;
|
|
107
107
|
private _snackBar;
|
|
108
108
|
private _dialogService;
|
|
109
|
+
private _cdr;
|
|
109
110
|
private _nodesSub?;
|
|
110
111
|
private _filterSub?;
|
|
111
112
|
private _changesSub?;
|
|
@@ -289,6 +290,7 @@ declare class ThesEntryEditorComponent {
|
|
|
289
290
|
*/
|
|
290
291
|
declare class ThesaurusBrowserComponent implements OnDestroy {
|
|
291
292
|
private _dialog;
|
|
293
|
+
private _cdr;
|
|
292
294
|
private _nodesSub?;
|
|
293
295
|
private _filterSub?;
|
|
294
296
|
/**
|
|
@@ -384,6 +386,11 @@ declare class ThesaurusTreeComponent {
|
|
|
384
386
|
* The tree store service, dependent on the current entries and renderLabel.
|
|
385
387
|
*/
|
|
386
388
|
readonly service: _angular_core.Signal<StaticThesaurusPagedTreeStoreService>;
|
|
389
|
+
/**
|
|
390
|
+
* Debug: tracks when the template condition would show the browser.
|
|
391
|
+
*/
|
|
392
|
+
readonly shouldShowBrowser: _angular_core.Signal<boolean>;
|
|
393
|
+
constructor();
|
|
387
394
|
/**
|
|
388
395
|
* The filter component class to use.
|
|
389
396
|
*/
|