@myrmidon/cadmus-thesaurus-store 0.0.2 → 0.0.3

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,33 @@ An editable paged tree browser for thesaurus entries. Editing happens in memory
109
109
 
110
110
  ## History
111
111
 
112
+ ### 0.0.3
113
+
114
+ - 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:
115
+
116
+ - The @if (service() && entries()?.length) guard in thesaurus-tree.component.html:3 only creates cadmus-thesaurus-browser once entries has data
117
+ - When the component is created, the effect() in the constructor is scheduled (not run immediately)
118
+ - Angular completes the initial render with empty nodes() signal
119
+ - The effect then runs, loads data, and updates the nodes signal via RxJS subscription callbacks
120
+ - But subscription callbacks run outside Angular's change detection zone, so no re-render is triggered
121
+ - On component close, Angular's final change detection cycle picks up the changes, causing the "flash"
122
+
123
+ 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.
124
+
125
+ The fix needed to address:
126
+
127
+ 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, which requires { allowSignalWrites: true }.
128
+
129
+ 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.
130
+
131
+ The issue appears in newer Angular apps because they may use:
132
+
133
+ - Zoneless change detection (Angular 18+)
134
+ - OnPush change detection as default in project configuration
135
+ - Different timing of change detection cycles
136
+
137
+ 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.
138
+
112
139
  ### 0.0.2
113
140
 
114
141
  - 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,9 @@ 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.
265
+ // allowSignalWrites is required because we update signals from subscription callbacks
266
+ // that execute synchronously (BehaviorSubject emits immediately on subscribe).
264
267
  effect(() => {
265
268
  const currentStore = this.store();
266
269
  const currentService = this.service();
@@ -273,25 +276,32 @@ class EditableThesaurusBrowserComponent {
273
276
  this.filter.set({});
274
277
  return;
275
278
  }
276
- // Subscribe to store's observables and update signals
279
+ // Subscribe to store's observables and update signals.
280
+ // markForCheck() is required because subscription callbacks run outside
281
+ // Angular's reactive context, and some Angular apps use OnPush change
282
+ // detection or zoneless mode.
277
283
  this._nodesSub = currentStore.nodes$.subscribe((nodes) => {
278
284
  this.nodes.set(nodes);
285
+ this._cdr.markForCheck();
279
286
  });
280
287
  this._filterSub = currentStore.filter$.subscribe((filter) => {
281
288
  this.filter.set(filter);
289
+ this._cdr.markForCheck();
282
290
  });
283
291
  // Subscribe to changes state
284
292
  this._changesSub = currentService.hasChanges$.subscribe((hasChanges) => {
285
293
  this.changesStateChange.emit(hasChanges);
294
+ this._cdr.markForCheck();
286
295
  });
287
296
  // Load nodes if store is empty
288
297
  if (!currentStore.getNodes().length) {
289
298
  this.loading.set(true);
290
299
  currentStore.setFilter({}).finally(() => {
291
300
  this.loading.set(false);
301
+ this._cdr.markForCheck();
292
302
  });
293
303
  }
294
- });
304
+ }, { allowSignalWrites: true });
295
305
  }
296
306
  ngOnDestroy() {
297
307
  this._nodesSub?.unsubscribe();
@@ -305,6 +315,7 @@ class EditableThesaurusBrowserComponent {
305
315
  this.loading.set(true);
306
316
  store.reset().finally(() => {
307
317
  this.loading.set(false);
318
+ this._cdr.markForCheck();
308
319
  });
309
320
  }
310
321
  onToggleExpanded(node) {
@@ -315,11 +326,13 @@ class EditableThesaurusBrowserComponent {
315
326
  if (node.expanded) {
316
327
  store.collapse(node.id).finally(() => {
317
328
  this.loading.set(false);
329
+ this._cdr.markForCheck();
318
330
  });
319
331
  }
320
332
  else {
321
333
  store.expand(node.id).finally(() => {
322
334
  this.loading.set(false);
335
+ this._cdr.markForCheck();
323
336
  });
324
337
  }
325
338
  }
@@ -330,6 +343,7 @@ class EditableThesaurusBrowserComponent {
330
343
  this.loading.set(true);
331
344
  store.changePage(request.node.id, request.paging.pageNumber).finally(() => {
332
345
  this.loading.set(false);
346
+ this._cdr.markForCheck();
333
347
  });
334
348
  }
335
349
  onFilterChange(filter) {
@@ -340,6 +354,7 @@ class EditableThesaurusBrowserComponent {
340
354
  this.loading.set(true);
341
355
  store.setFilter(filter || {}).finally(() => {
342
356
  this.loading.set(false);
357
+ this._cdr.markForCheck();
343
358
  });
344
359
  }
345
360
  onEditFilterRequest(node) {
@@ -753,6 +768,7 @@ class StaticThesaurusPagedTreeStoreService {
753
768
  class ThesaurusBrowserComponent {
754
769
  constructor() {
755
770
  this._dialog = inject(MatDialog);
771
+ this._cdr = inject(ChangeDetectorRef);
756
772
  /**
757
773
  * The service to use to load the nodes.
758
774
  */
@@ -785,27 +801,35 @@ class ThesaurusBrowserComponent {
785
801
  this.form = new FormGroup({
786
802
  label: this.label,
787
803
  });
788
- // Use effect to react to service/store changes
804
+ // Use effect to react to service/store changes.
805
+ // allowSignalWrites is required because we update signals from subscription callbacks
806
+ // that execute synchronously (BehaviorSubject emits immediately on subscribe).
789
807
  effect(() => {
790
808
  const currentStore = this.store();
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) => {
796
817
  this.nodes.set(nodes);
818
+ this._cdr.markForCheck();
797
819
  });
798
820
  this._filterSub = currentStore.filter$.subscribe((filter) => {
799
821
  this.filter.set(filter);
822
+ this._cdr.markForCheck();
800
823
  });
801
824
  // Load nodes if store is empty
802
825
  if (!currentStore.getNodes().length) {
803
826
  this.loading.set(true);
804
827
  currentStore.setFilter({}).finally(() => {
805
828
  this.loading.set(false);
829
+ this._cdr.markForCheck();
806
830
  });
807
831
  }
808
- });
832
+ }, { allowSignalWrites: true });
809
833
  }
810
834
  ngOnDestroy() {
811
835
  this._nodesSub?.unsubscribe();
@@ -817,6 +841,7 @@ class ThesaurusBrowserComponent {
817
841
  .reset()
818
842
  .finally(() => {
819
843
  this.loading.set(false);
844
+ this._cdr.markForCheck();
820
845
  });
821
846
  }
822
847
  onToggleExpanded(node) {
@@ -826,6 +851,7 @@ class ThesaurusBrowserComponent {
826
851
  .collapse(node.id)
827
852
  .finally(() => {
828
853
  this.loading.set(false);
854
+ this._cdr.markForCheck();
829
855
  });
830
856
  }
831
857
  else {
@@ -833,6 +859,7 @@ class ThesaurusBrowserComponent {
833
859
  .expand(node.id)
834
860
  .finally(() => {
835
861
  this.loading.set(false);
862
+ this._cdr.markForCheck();
836
863
  });
837
864
  }
838
865
  }
@@ -842,6 +869,7 @@ class ThesaurusBrowserComponent {
842
869
  .changePage(request.node.id, request.paging.pageNumber)
843
870
  .finally(() => {
844
871
  this.loading.set(false);
872
+ this._cdr.markForCheck();
845
873
  });
846
874
  }
847
875
  onFilterChange(filter) {
@@ -851,6 +879,7 @@ class ThesaurusBrowserComponent {
851
879
  .setFilter(filter || {})
852
880
  .finally(() => {
853
881
  this.loading.set(false);
882
+ this._cdr.markForCheck();
854
883
  });
855
884
  }
856
885
  onEditFilterRequest(node) {
@@ -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 // allowSignalWrites is required because we update signals from subscription callbacks\r\n // that execute synchronously (BehaviorSubject emits immediately on subscribe).\r\n effect(\r\n () => {\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 { allowSignalWrites: true }\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 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 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 }\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 _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 // allowSignalWrites is required because we update signals from subscription callbacks\r\n // that execute synchronously (BehaviorSubject emits immediately on subscribe).\r\n effect(\r\n () => {\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 // 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 // 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 { allowSignalWrites: true }\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(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 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, 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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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@myrmidon/cadmus-thesaurus-store",
3
- "version": "0.0.2",
3
+ "version": "0.0.3",
4
4
  "description": "Cadmus thesauri store components.",
5
5
  "keywords": [
6
6
  "Cadmus"
@@ -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
  /**