@myrmidon/paged-data-browsers 1.1.1 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +92 -0
- package/esm2022/lib/components/browser-tree-node/browser-tree-node.component.mjs +11 -5
- package/esm2022/lib/components/compact-pager/compact-pager.component.mjs +3 -3
- package/esm2022/lib/components/range-view/range-view.component.mjs +3 -3
- package/esm2022/lib/paged-data-browsers.module.mjs +4 -4
- package/esm2022/lib/services/paged-tree.store.mjs +60 -86
- package/fesm2022/myrmidon-paged-data-browsers.mjs +79 -99
- package/fesm2022/myrmidon-paged-data-browsers.mjs.map +1 -1
- package/lib/components/browser-tree-node/browser-tree-node.component.d.ts +5 -1
- package/lib/services/paged-tree.store.d.ts +42 -29
- package/package.json +1 -1
|
@@ -12,7 +12,7 @@ import * as i5 from '@angular/material/tooltip';
|
|
|
12
12
|
import { MatTooltipModule } from '@angular/material/tooltip';
|
|
13
13
|
import * as i8 from '@myrmidon/ng-tools';
|
|
14
14
|
import { NgToolsModule } from '@myrmidon/ng-tools';
|
|
15
|
-
import { BehaviorSubject, of, tap,
|
|
15
|
+
import { BehaviorSubject, of, tap, forkJoin } from 'rxjs';
|
|
16
16
|
import { ReactiveFormsModule } from '@angular/forms';
|
|
17
17
|
import { MatChipsModule } from '@angular/material/chips';
|
|
18
18
|
import { MatDialogModule } from '@angular/material/dialog';
|
|
@@ -53,10 +53,10 @@ class CompactPagerComponent {
|
|
|
53
53
|
this.pagingChange.emit(this.paging);
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.
|
|
57
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.
|
|
56
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.6", ngImport: i0, type: CompactPagerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
57
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.6", type: CompactPagerComponent, selector: "pdb-compact-pager", inputs: { paging: "paging" }, outputs: { pagingChange: "pagingChange" }, ngImport: i0, template: "@if (paging.pageCount) {\n <div class=\"form-row\">\n <span id=\"pages\">{{ paging.pageNumber }}/{{ paging.pageCount }}</span>\n <button\n type=\"button\"\n mat-icon-button\n (click)=\"onFirst()\"\n [disabled]=\"paging.pageNumber < 2\"\n >\n <mat-icon>first_page</mat-icon>\n </button>\n <button\n type=\"button\"\n mat-icon-button\n (click)=\"onPrevious()\"\n [disabled]=\"paging.pageNumber < 2\"\n >\n <mat-icon>navigate_before</mat-icon>\n </button>\n <button\n type=\"button\"\n mat-icon-button\n (click)=\"onNext()\"\n [disabled]=\"paging.pageNumber === paging.pageCount\"\n >\n <mat-icon>navigate_next</mat-icon>\n </button>\n <button\n type=\"button\"\n mat-icon-button\n (click)=\"onLast()\"\n [disabled]=\"paging.pageNumber === paging.pageCount\"\n >\n <mat-icon>last_page</mat-icon>\n </button>\n <span id=\"total\">{{ paging.total }} </span>\n </div>\n}\n", styles: ["#pages,#total{color:silver}.form-row{display:flex;gap:2px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}\n"], dependencies: [{ kind: "component", type: i1.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }] }); }
|
|
58
58
|
}
|
|
59
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.
|
|
59
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.6", ngImport: i0, type: CompactPagerComponent, decorators: [{
|
|
60
60
|
type: Component,
|
|
61
61
|
args: [{ selector: 'pdb-compact-pager', template: "@if (paging.pageCount) {\n <div class=\"form-row\">\n <span id=\"pages\">{{ paging.pageNumber }}/{{ paging.pageCount }}</span>\n <button\n type=\"button\"\n mat-icon-button\n (click)=\"onFirst()\"\n [disabled]=\"paging.pageNumber < 2\"\n >\n <mat-icon>first_page</mat-icon>\n </button>\n <button\n type=\"button\"\n mat-icon-button\n (click)=\"onPrevious()\"\n [disabled]=\"paging.pageNumber < 2\"\n >\n <mat-icon>navigate_before</mat-icon>\n </button>\n <button\n type=\"button\"\n mat-icon-button\n (click)=\"onNext()\"\n [disabled]=\"paging.pageNumber === paging.pageCount\"\n >\n <mat-icon>navigate_next</mat-icon>\n </button>\n <button\n type=\"button\"\n mat-icon-button\n (click)=\"onLast()\"\n [disabled]=\"paging.pageNumber === paging.pageCount\"\n >\n <mat-icon>last_page</mat-icon>\n </button>\n <span id=\"total\">{{ paging.total }} </span>\n </div>\n}\n", styles: ["#pages,#total{color:silver}.form-row{display:flex;gap:2px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}\n"] }]
|
|
62
62
|
}], ctorParameters: () => [], propDecorators: { paging: [{
|
|
@@ -82,10 +82,10 @@ class RangeViewComponent {
|
|
|
82
82
|
((rangeStart + rangeWidth) / domainWidth) * this.width,
|
|
83
83
|
];
|
|
84
84
|
}
|
|
85
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.
|
|
86
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.
|
|
85
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.6", ngImport: i0, type: RangeViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
86
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.6", type: RangeViewComponent, selector: "pdb-range-view", inputs: { domain: "domain", range: "range", width: "width", height: "height" }, usesOnChanges: true, ngImport: i0, template: "<svg [attr.width]=\"width\" [attr.height]=\"height\">\n <rect id=\"rdomain\" [attr.width]=\"width\" [attr.height]=\"height\" />\n <rect\n id=\"rrange\"\n [attr.x]=\"scaledRange[0]\"\n [attr.y]=\"0\"\n [attr.width]=\"scaledRange[1] - scaledRange[0]\"\n [attr.height]=\"height\"\n />\n</svg>\n", styles: ["#rdomain{fill:#d3d3d3;stroke-width:3;stroke:#c1ba9b}#rrange{fill:#91aad3;stroke-width:3}\n"] }); }
|
|
87
87
|
}
|
|
88
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.
|
|
88
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.6", ngImport: i0, type: RangeViewComponent, decorators: [{
|
|
89
89
|
type: Component,
|
|
90
90
|
args: [{ selector: 'pdb-range-view', template: "<svg [attr.width]=\"width\" [attr.height]=\"height\">\n <rect id=\"rdomain\" [attr.width]=\"width\" [attr.height]=\"height\" />\n <rect\n id=\"rrange\"\n [attr.x]=\"scaledRange[0]\"\n [attr.y]=\"0\"\n [attr.width]=\"scaledRange[1] - scaledRange[0]\"\n [attr.height]=\"height\"\n />\n</svg>\n", styles: ["#rdomain{fill:#d3d3d3;stroke-width:3;stroke:#c1ba9b}#rrange{fill:#91aad3;stroke-width:3}\n"] }]
|
|
91
91
|
}], ctorParameters: () => [], propDecorators: { domain: [{
|
|
@@ -121,6 +121,10 @@ class BrowserTreeNodeComponent {
|
|
|
121
121
|
this._node = value;
|
|
122
122
|
}
|
|
123
123
|
constructor() {
|
|
124
|
+
/**
|
|
125
|
+
* The indent size for the node's children.
|
|
126
|
+
*/
|
|
127
|
+
this.indentSize = 30;
|
|
124
128
|
this.toggleExpandedRequest = new EventEmitter();
|
|
125
129
|
this.changePageRequest = new EventEmitter();
|
|
126
130
|
this.editNodeFilterRequest = new EventEmitter();
|
|
@@ -142,12 +146,12 @@ class BrowserTreeNodeComponent {
|
|
|
142
146
|
this.editNodeFilterRequest.emit(this._node);
|
|
143
147
|
}
|
|
144
148
|
}
|
|
145
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.
|
|
146
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.
|
|
149
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.6", ngImport: i0, type: BrowserTreeNodeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
150
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.6", type: BrowserTreeNodeComponent, selector: "pdb-browser-tree-node", inputs: { node: "node", paging: "paging", debug: "debug", hideLabel: "hideLabel", hidePaging: "hidePaging", indentSize: "indentSize" }, outputs: { toggleExpandedRequest: "toggleExpandedRequest", changePageRequest: "changePageRequest", editNodeFilterRequest: "editNodeFilterRequest" }, ngImport: i0, template: "@if (node) {\n<div id=\"node\" [style.margin-left.px]=\"(node.y - 1) * indentSize\">\n <!-- pager -->\n @if ($any(node).expanded && paging && paging.pageCount > 1) {\n <div id=\"pager\" [style.display]=\"hidePaging ? 'inherit' : 'block'\">\n <pdb-compact-pager\n [paging]=\"paging\"\n (pagingChange)=\"onPagingChange($any(node), $event)\"\n />\n <pdb-range-view\n [width]=\"250\"\n [domain]=\"[0, paging.pageCount]\"\n [range]=\"[paging.pageNumber - 1, paging.pageNumber]\"\n />\n </div>\n }\n <!-- node -->\n <div class=\"form-row\">\n <!-- expand/collapse button -->\n <button\n type=\"button\"\n mat-icon-button\n [matTooltip]=\"$any(node).expanded ? 'Collapse' : 'Expand'\"\n [disabled]=\"node.hasChildren === false\"\n (click)=\"onToggleExpanded()\"\n >\n <mat-icon class=\"mat-primary\">{{\n node.hasChildren === true || node.hasChildren === undefined\n ? $any(node).expanded\n ? \"expand_less\"\n : \"expand_more\"\n : \"stop\"\n }}</mat-icon>\n </button>\n\n <!-- tag -->\n @if (!hideLabel) {\n <span\n class=\"tag\"\n [ngStyle]=\"{\n 'background-color': (node.tag | stringToColor),\n color: node.tag | stringToColor | colorToContrast\n }\"\n >{{ node.tag }}</span\n >\n\n <!-- loc and label -->\n <span class=\"loc\">{{ node.y }}.{{ node.x }}</span> - {{ node.label }}\n }\n\n <!-- PROJECTED NODE -->\n <ng-content></ng-content>\n\n <!-- debug -->\n @if (debug) {\n <span class=\"debug\"\n >#{{ node.id }}\n <span\n >| {{ $any(node).paging.pageNumber }}/{{\n $any(node).paging.pageCount\n }}\n ({{ $any(node).paging.total }})</span\n ></span\n >\n }\n\n <!-- filter -->\n @if (!$any(node).filter && node.y) {\n <div class=\"muted\">\n <button\n type=\"button\"\n mat-icon-button\n matTooltip=\"Add filter\"\n (click)=\"onEditFilter()\"\n >\n <mat-icon>filter_list</mat-icon>\n </button>\n </div>\n } @if ($any(node).filter && node.y) {\n <div class=\"muted\">\n <button type=\"button\" mat-icon-button (click)=\"onEditFilter()\">\n <mat-icon [matBadge]=\"$any(node).filter ? 'F' : ''\"\n >filter_alt</mat-icon\n >\n </button>\n </div>\n }\n </div>\n</div>\n}\n", styles: [".form-row{display:flex;gap:8px;align-items:center}.form-row *{flex:0 0 auto}.form-row span{flex:0 1 auto;white-space:normal}#node #pager{display:none}#node:hover #pager{display:block}#node{margin-bottom:4px;padding:4px 6px;border:1px solid #98a8d4;border-radius:6px}#node:hover{background-color:#d6dee9}span.loc{font-size:.85em;color:#666;vertical-align:middle}span.tag{border:1px solid #aaa;border-radius:4px;padding:0 4px}fieldset{border:1px solid silver;border-radius:6px;padding:4px 6px;margin:4px 0}legend{color:silver}.muted{opacity:.3}.muted:hover{opacity:1}.debug{font-size:.85em;color:#9c3d3e}\n"], dependencies: [{ kind: "directive", type: i1$1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i2$1.MatBadge, selector: "[matBadge]", inputs: ["matBadgeColor", "matBadgeOverlap", "matBadgeDisabled", "matBadgePosition", "matBadge", "matBadgeDescription", "matBadgeSize", "matBadgeHidden"] }, { kind: "component", type: i1.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i5.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: CompactPagerComponent, selector: "pdb-compact-pager", inputs: ["paging"], outputs: ["pagingChange"] }, { kind: "component", type: RangeViewComponent, selector: "pdb-range-view", inputs: ["domain", "range", "width", "height"] }, { kind: "pipe", type: i8.ColorToContrastPipe, name: "colorToContrast" }, { kind: "pipe", type: i8.StringToColorPipe, name: "stringToColor" }] }); }
|
|
147
151
|
}
|
|
148
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.
|
|
152
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.6", ngImport: i0, type: BrowserTreeNodeComponent, decorators: [{
|
|
149
153
|
type: Component,
|
|
150
|
-
args: [{ selector: 'pdb-browser-tree-node', template: "@if (node) {\n<div id=\"node\" [style.margin-left.px]=\"(node.y - 1)
|
|
154
|
+
args: [{ selector: 'pdb-browser-tree-node', template: "@if (node) {\n<div id=\"node\" [style.margin-left.px]=\"(node.y - 1) * indentSize\">\n <!-- pager -->\n @if ($any(node).expanded && paging && paging.pageCount > 1) {\n <div id=\"pager\" [style.display]=\"hidePaging ? 'inherit' : 'block'\">\n <pdb-compact-pager\n [paging]=\"paging\"\n (pagingChange)=\"onPagingChange($any(node), $event)\"\n />\n <pdb-range-view\n [width]=\"250\"\n [domain]=\"[0, paging.pageCount]\"\n [range]=\"[paging.pageNumber - 1, paging.pageNumber]\"\n />\n </div>\n }\n <!-- node -->\n <div class=\"form-row\">\n <!-- expand/collapse button -->\n <button\n type=\"button\"\n mat-icon-button\n [matTooltip]=\"$any(node).expanded ? 'Collapse' : 'Expand'\"\n [disabled]=\"node.hasChildren === false\"\n (click)=\"onToggleExpanded()\"\n >\n <mat-icon class=\"mat-primary\">{{\n node.hasChildren === true || node.hasChildren === undefined\n ? $any(node).expanded\n ? \"expand_less\"\n : \"expand_more\"\n : \"stop\"\n }}</mat-icon>\n </button>\n\n <!-- tag -->\n @if (!hideLabel) {\n <span\n class=\"tag\"\n [ngStyle]=\"{\n 'background-color': (node.tag | stringToColor),\n color: node.tag | stringToColor | colorToContrast\n }\"\n >{{ node.tag }}</span\n >\n\n <!-- loc and label -->\n <span class=\"loc\">{{ node.y }}.{{ node.x }}</span> - {{ node.label }}\n }\n\n <!-- PROJECTED NODE -->\n <ng-content></ng-content>\n\n <!-- debug -->\n @if (debug) {\n <span class=\"debug\"\n >#{{ node.id }}\n <span\n >| {{ $any(node).paging.pageNumber }}/{{\n $any(node).paging.pageCount\n }}\n ({{ $any(node).paging.total }})</span\n ></span\n >\n }\n\n <!-- filter -->\n @if (!$any(node).filter && node.y) {\n <div class=\"muted\">\n <button\n type=\"button\"\n mat-icon-button\n matTooltip=\"Add filter\"\n (click)=\"onEditFilter()\"\n >\n <mat-icon>filter_list</mat-icon>\n </button>\n </div>\n } @if ($any(node).filter && node.y) {\n <div class=\"muted\">\n <button type=\"button\" mat-icon-button (click)=\"onEditFilter()\">\n <mat-icon [matBadge]=\"$any(node).filter ? 'F' : ''\"\n >filter_alt</mat-icon\n >\n </button>\n </div>\n }\n </div>\n</div>\n}\n", styles: [".form-row{display:flex;gap:8px;align-items:center}.form-row *{flex:0 0 auto}.form-row span{flex:0 1 auto;white-space:normal}#node #pager{display:none}#node:hover #pager{display:block}#node{margin-bottom:4px;padding:4px 6px;border:1px solid #98a8d4;border-radius:6px}#node:hover{background-color:#d6dee9}span.loc{font-size:.85em;color:#666;vertical-align:middle}span.tag{border:1px solid #aaa;border-radius:4px;padding:0 4px}fieldset{border:1px solid silver;border-radius:6px;padding:4px 6px;margin:4px 0}legend{color:silver}.muted{opacity:.3}.muted:hover{opacity:1}.debug{font-size:.85em;color:#9c3d3e}\n"] }]
|
|
151
155
|
}], ctorParameters: () => [], propDecorators: { node: [{
|
|
152
156
|
type: Input
|
|
153
157
|
}], paging: [{
|
|
@@ -158,6 +162,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.1.3", ngImpor
|
|
|
158
162
|
type: Input
|
|
159
163
|
}], hidePaging: [{
|
|
160
164
|
type: Input
|
|
165
|
+
}], indentSize: [{
|
|
166
|
+
type: Input
|
|
161
167
|
}], toggleExpandedRequest: [{
|
|
162
168
|
type: Output
|
|
163
169
|
}], changePageRequest: [{
|
|
@@ -464,7 +470,7 @@ class PagedTreeStore {
|
|
|
464
470
|
return;
|
|
465
471
|
}
|
|
466
472
|
this._pageSize = value;
|
|
467
|
-
this.reset(
|
|
473
|
+
this.reset();
|
|
468
474
|
}
|
|
469
475
|
/**
|
|
470
476
|
* Create an instance of the store.
|
|
@@ -476,21 +482,12 @@ class PagedTreeStore {
|
|
|
476
482
|
this._pageSize = options.pageSize;
|
|
477
483
|
this._cache = new LRUCache(options.cacheSize);
|
|
478
484
|
this._customCacheKeyBuilder = options.buildCacheKey;
|
|
479
|
-
this._radixLabel = '(root)';
|
|
480
|
-
this._roots = [];
|
|
481
485
|
this._nodes$ = new BehaviorSubject([]);
|
|
482
486
|
this.nodes$ = this._nodes$.asObservable();
|
|
483
|
-
this._tags$ = new BehaviorSubject([]);
|
|
484
|
-
this.tags$ = this._tags$.asObservable();
|
|
485
487
|
this._filter$ = new BehaviorSubject({});
|
|
486
488
|
this.filter$ = this._filter$.asObservable();
|
|
487
489
|
this._dirty = true;
|
|
488
|
-
this.
|
|
489
|
-
}
|
|
490
|
-
updateTags() {
|
|
491
|
-
this._service.getTags().subscribe((tags) => {
|
|
492
|
-
this._tags$.next(tags);
|
|
493
|
-
});
|
|
490
|
+
this._hasMockRoot = options.hasMockRoot || false;
|
|
494
491
|
}
|
|
495
492
|
/**
|
|
496
493
|
* Gets the global filter, eventually overridden with values
|
|
@@ -506,6 +503,13 @@ class PagedTreeStore {
|
|
|
506
503
|
}
|
|
507
504
|
: this._filter$.value;
|
|
508
505
|
}
|
|
506
|
+
/**
|
|
507
|
+
* Checks if this store is empty.
|
|
508
|
+
* @returns True if this store is empty.
|
|
509
|
+
*/
|
|
510
|
+
isEmpty() {
|
|
511
|
+
return this._nodes$.value.length === 0;
|
|
512
|
+
}
|
|
509
513
|
/**
|
|
510
514
|
* Gets all the nodes in the store.
|
|
511
515
|
* @returns The nodes.
|
|
@@ -514,11 +518,11 @@ class PagedTreeStore {
|
|
|
514
518
|
return this._nodes$.value;
|
|
515
519
|
}
|
|
516
520
|
/**
|
|
517
|
-
*
|
|
518
|
-
* @returns The
|
|
521
|
+
* Get the root node of the tree.
|
|
522
|
+
* @returns The root node of the tree or undefined if empty.
|
|
519
523
|
*/
|
|
520
|
-
|
|
521
|
-
return this.
|
|
524
|
+
getRootNode() {
|
|
525
|
+
return this._nodes$.value[0];
|
|
522
526
|
}
|
|
523
527
|
/**
|
|
524
528
|
* Build the cache key for the given page number and filter.
|
|
@@ -535,6 +539,13 @@ class PagedTreeStore {
|
|
|
535
539
|
}
|
|
536
540
|
return JSON.stringify({ pageNumber, ...filter });
|
|
537
541
|
}
|
|
542
|
+
/**
|
|
543
|
+
* Get the specified page of nodes, either from cache or from the server.
|
|
544
|
+
* When the page is retrieved from the server, it is stored in cache.
|
|
545
|
+
* @param filter The filter to apply.
|
|
546
|
+
* @param pageNumber The page number to get.
|
|
547
|
+
* @returns Observable of the page of nodes.
|
|
548
|
+
*/
|
|
538
549
|
getPageFromCacheOrServer(filter, pageNumber) {
|
|
539
550
|
const key = this.buildCacheKey(pageNumber, filter);
|
|
540
551
|
const pageInCache = this._cache.get(key);
|
|
@@ -542,11 +553,19 @@ class PagedTreeStore {
|
|
|
542
553
|
return of(pageInCache);
|
|
543
554
|
}
|
|
544
555
|
else {
|
|
545
|
-
return this._service
|
|
556
|
+
return this._service
|
|
557
|
+
.getNodes(filter, pageNumber, this._pageSize, this._hasMockRoot)
|
|
558
|
+
.pipe(tap((page) => {
|
|
546
559
|
this._cache.put(key, page, 0);
|
|
547
560
|
}));
|
|
548
561
|
}
|
|
549
562
|
}
|
|
563
|
+
/**
|
|
564
|
+
* Create paged tree nodes from a page of tree nodes, by providing further
|
|
565
|
+
* metadata like page number, page count and total items.
|
|
566
|
+
* @param page The page to create nodes from.
|
|
567
|
+
* @returns Paged nodes.
|
|
568
|
+
*/
|
|
550
569
|
createPageNodes(page) {
|
|
551
570
|
return page.items.map((n) => {
|
|
552
571
|
return {
|
|
@@ -564,94 +583,44 @@ class PagedTreeStore {
|
|
|
564
583
|
* Sets the filter for this store. Whenever the filter is set,
|
|
565
584
|
* the store is reset.
|
|
566
585
|
* @param filter The filter.
|
|
567
|
-
* @param radixLabel The label of the radix node, if this needs to be set.
|
|
568
586
|
* @returns true if tree was changed, false otherwise.
|
|
569
587
|
*/
|
|
570
|
-
setFilter(filter
|
|
588
|
+
setFilter(filter) {
|
|
571
589
|
if (this._filter$.value === filter) {
|
|
572
590
|
return Promise.resolve(false);
|
|
573
591
|
}
|
|
574
592
|
this._filter$.next(filter);
|
|
575
593
|
this._dirty = true;
|
|
576
|
-
return this.reset(
|
|
594
|
+
return this.reset();
|
|
577
595
|
}
|
|
578
596
|
/**
|
|
579
597
|
* Reset the store, loading the root nodes and their children.
|
|
580
|
-
* @param label The label of the radix node.
|
|
581
598
|
* @returns true if tree was changed, false otherwise.
|
|
582
599
|
*/
|
|
583
|
-
reset(
|
|
600
|
+
reset() {
|
|
584
601
|
if (!this._dirty) {
|
|
585
602
|
return Promise.resolve(false);
|
|
586
603
|
}
|
|
587
604
|
this._cache.clear();
|
|
588
605
|
const filter = this._filter$.value;
|
|
589
|
-
this._radix = {
|
|
590
|
-
id: 0,
|
|
591
|
-
y: 0,
|
|
592
|
-
x: 1,
|
|
593
|
-
label: label,
|
|
594
|
-
paging: {
|
|
595
|
-
pageNumber: 0,
|
|
596
|
-
pageCount: 0,
|
|
597
|
-
total: 0,
|
|
598
|
-
},
|
|
599
|
-
};
|
|
600
606
|
return new Promise((resolve, reject) => {
|
|
601
607
|
this._service
|
|
602
|
-
.
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
this._roots = [];
|
|
607
|
-
return of([]);
|
|
608
|
-
}
|
|
609
|
-
else {
|
|
610
|
-
// got roots, set them and get their children
|
|
611
|
-
this._roots = nodes.map((node) => ({
|
|
612
|
-
...node,
|
|
613
|
-
paging: {
|
|
614
|
-
pageNumber: 1,
|
|
615
|
-
pageCount: 1,
|
|
616
|
-
total: 1,
|
|
617
|
-
},
|
|
618
|
-
}));
|
|
619
|
-
// fetch children for each root node
|
|
620
|
-
return forkJoin(this._roots.map((root) => this.getPageFromCacheOrServer({ ...filter, parentId: root.id }, 1)));
|
|
621
|
-
}
|
|
622
|
-
}))
|
|
608
|
+
.getNodes({
|
|
609
|
+
...filter,
|
|
610
|
+
parentId: undefined,
|
|
611
|
+
}, 1, this._pageSize, this._hasMockRoot)
|
|
623
612
|
.subscribe({
|
|
624
|
-
next: (
|
|
625
|
-
this.
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
pageNumber: 1,
|
|
632
|
-
pageCount: 1,
|
|
633
|
-
total: pages.length,
|
|
634
|
-
};
|
|
635
|
-
// roots
|
|
636
|
-
this._roots.forEach((root, i) => {
|
|
637
|
-
root.hasChildren = !!pages[i].total;
|
|
638
|
-
root.expanded = !!pages[i].total;
|
|
639
|
-
});
|
|
640
|
-
const nodes = this._roots.flatMap((root, i) => [
|
|
641
|
-
root,
|
|
642
|
-
...this.createPageNodes(pages[i]),
|
|
643
|
-
]);
|
|
644
|
-
this._nodes$.next([this._radix, ...nodes]);
|
|
645
|
-
resolve(true);
|
|
646
|
-
}
|
|
647
|
-
else {
|
|
648
|
-
this._roots.forEach((root) => {
|
|
649
|
-
root.hasChildren = false;
|
|
650
|
-
root.expanded = false;
|
|
613
|
+
next: (page) => {
|
|
614
|
+
this._nodes$.next(this.createPageNodes(page));
|
|
615
|
+
// get the children of each node thus calculating their hasChildren property
|
|
616
|
+
const childrenObservables = this._nodes$.value.map((node) => this.getPageFromCacheOrServer({ ...filter, parentId: node.id }, 1));
|
|
617
|
+
forkJoin(childrenObservables).subscribe((childrenPages) => {
|
|
618
|
+
childrenPages.forEach((page, i) => {
|
|
619
|
+
this._nodes$.value[i].hasChildren = page.total > 0;
|
|
651
620
|
});
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
621
|
+
});
|
|
622
|
+
this._dirty = false;
|
|
623
|
+
resolve(true);
|
|
655
624
|
},
|
|
656
625
|
error: (error) => {
|
|
657
626
|
reject(error);
|
|
@@ -719,6 +688,12 @@ class PagedTreeStore {
|
|
|
719
688
|
});
|
|
720
689
|
});
|
|
721
690
|
}
|
|
691
|
+
/**
|
|
692
|
+
* Expand all the descendants of the node with the specified ID.
|
|
693
|
+
*
|
|
694
|
+
* @param id The ID of the node to expand.
|
|
695
|
+
* @returns Promise.
|
|
696
|
+
*/
|
|
722
697
|
expandAll(id) {
|
|
723
698
|
if (!id) {
|
|
724
699
|
return Promise.resolve(false);
|
|
@@ -854,7 +829,12 @@ class PagedTreeStore {
|
|
|
854
829
|
* Collapse all the nodes in the store.
|
|
855
830
|
*/
|
|
856
831
|
collapseAll() {
|
|
857
|
-
this.
|
|
832
|
+
if (this.isEmpty()) {
|
|
833
|
+
return;
|
|
834
|
+
}
|
|
835
|
+
// collapse the first node
|
|
836
|
+
const root = this._nodes$.value[0];
|
|
837
|
+
this.collapse(root.id);
|
|
858
838
|
}
|
|
859
839
|
/**
|
|
860
840
|
* Clear the cache.
|
|
@@ -875,8 +855,8 @@ class PagedTreeStore {
|
|
|
875
855
|
}
|
|
876
856
|
|
|
877
857
|
class PagedDataBrowsersModule {
|
|
878
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.
|
|
879
|
-
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.
|
|
858
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.6", ngImport: i0, type: PagedDataBrowsersModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
859
|
+
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.6", ngImport: i0, type: PagedDataBrowsersModule, declarations: [CompactPagerComponent,
|
|
880
860
|
RangeViewComponent,
|
|
881
861
|
BrowserTreeNodeComponent], imports: [CommonModule,
|
|
882
862
|
ReactiveFormsModule,
|
|
@@ -896,7 +876,7 @@ class PagedDataBrowsersModule {
|
|
|
896
876
|
NgToolsModule], exports: [CompactPagerComponent,
|
|
897
877
|
RangeViewComponent,
|
|
898
878
|
BrowserTreeNodeComponent] }); }
|
|
899
|
-
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.
|
|
879
|
+
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.6", ngImport: i0, type: PagedDataBrowsersModule, imports: [CommonModule,
|
|
900
880
|
ReactiveFormsModule,
|
|
901
881
|
// material
|
|
902
882
|
MatBadgeModule,
|
|
@@ -913,7 +893,7 @@ class PagedDataBrowsersModule {
|
|
|
913
893
|
// myrmidon
|
|
914
894
|
NgToolsModule] }); }
|
|
915
895
|
}
|
|
916
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.
|
|
896
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.6", ngImport: i0, type: PagedDataBrowsersModule, decorators: [{
|
|
917
897
|
type: NgModule,
|
|
918
898
|
args: [{
|
|
919
899
|
declarations: [
|