@myrmidon/paged-data-browsers 1.1.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +86 -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 +50 -89
- package/fesm2022/myrmidon-paged-data-browsers.mjs +69 -102
- 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 +33 -31
- package/package.json +2 -2
|
@@ -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.1.3", ngImport: i0, type: CompactPagerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
57
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.1.3", 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.1.3", 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.1.3", ngImport: i0, type: RangeViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
86
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.1.3", 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.1.3", 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.1.3", ngImport: i0, type: BrowserTreeNodeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
150
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.1.3", 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.1.3", ngImport: i0, type: BrowserTreeNodeComponent, decorators: [{
|
|
149
153
|
type: Component,
|
|
150
|
-
args: [{ selector: 'pdb-browser-tree-node', template: "@if (node) {\n
|
|
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.0.0", 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.
|
|
@@ -513,13 +517,6 @@ class PagedTreeStore {
|
|
|
513
517
|
getNodes() {
|
|
514
518
|
return this._nodes$.value;
|
|
515
519
|
}
|
|
516
|
-
/**
|
|
517
|
-
* Gets the list of nodes tags.
|
|
518
|
-
* @returns The tags.
|
|
519
|
-
*/
|
|
520
|
-
getTags() {
|
|
521
|
-
return this._tags$.value;
|
|
522
|
-
}
|
|
523
520
|
/**
|
|
524
521
|
* Build the cache key for the given page number and filter.
|
|
525
522
|
* The default implementation just returns a stringified object
|
|
@@ -535,6 +532,13 @@ class PagedTreeStore {
|
|
|
535
532
|
}
|
|
536
533
|
return JSON.stringify({ pageNumber, ...filter });
|
|
537
534
|
}
|
|
535
|
+
/**
|
|
536
|
+
* Get the specified page of nodes, either from cache or from the server.
|
|
537
|
+
* When the page is retrieved from the server, it is stored in cache.
|
|
538
|
+
* @param filter The filter to apply.
|
|
539
|
+
* @param pageNumber The page number to get.
|
|
540
|
+
* @returns Observable of the page of nodes.
|
|
541
|
+
*/
|
|
538
542
|
getPageFromCacheOrServer(filter, pageNumber) {
|
|
539
543
|
const key = this.buildCacheKey(pageNumber, filter);
|
|
540
544
|
const pageInCache = this._cache.get(key);
|
|
@@ -542,11 +546,19 @@ class PagedTreeStore {
|
|
|
542
546
|
return of(pageInCache);
|
|
543
547
|
}
|
|
544
548
|
else {
|
|
545
|
-
return this._service
|
|
549
|
+
return this._service
|
|
550
|
+
.getNodes(filter, pageNumber, this._pageSize, this._hasMockRoot)
|
|
551
|
+
.pipe(tap((page) => {
|
|
546
552
|
this._cache.put(key, page, 0);
|
|
547
553
|
}));
|
|
548
554
|
}
|
|
549
555
|
}
|
|
556
|
+
/**
|
|
557
|
+
* Create paged tree nodes from a page of tree nodes, by providing further
|
|
558
|
+
* metadata like page number, page count and total items.
|
|
559
|
+
* @param page The page to create nodes from.
|
|
560
|
+
* @returns Paged nodes.
|
|
561
|
+
*/
|
|
550
562
|
createPageNodes(page) {
|
|
551
563
|
return page.items.map((n) => {
|
|
552
564
|
return {
|
|
@@ -564,94 +576,44 @@ class PagedTreeStore {
|
|
|
564
576
|
* Sets the filter for this store. Whenever the filter is set,
|
|
565
577
|
* the store is reset.
|
|
566
578
|
* @param filter The filter.
|
|
567
|
-
* @param radixLabel The label of the radix node, if this needs to be set.
|
|
568
579
|
* @returns true if tree was changed, false otherwise.
|
|
569
580
|
*/
|
|
570
|
-
setFilter(filter
|
|
581
|
+
setFilter(filter) {
|
|
571
582
|
if (this._filter$.value === filter) {
|
|
572
583
|
return Promise.resolve(false);
|
|
573
584
|
}
|
|
574
585
|
this._filter$.next(filter);
|
|
575
586
|
this._dirty = true;
|
|
576
|
-
return this.reset(
|
|
587
|
+
return this.reset();
|
|
577
588
|
}
|
|
578
589
|
/**
|
|
579
590
|
* Reset the store, loading the root nodes and their children.
|
|
580
|
-
* @param label The label of the radix node.
|
|
581
591
|
* @returns true if tree was changed, false otherwise.
|
|
582
592
|
*/
|
|
583
|
-
reset(
|
|
593
|
+
reset() {
|
|
584
594
|
if (!this._dirty) {
|
|
585
595
|
return Promise.resolve(false);
|
|
586
596
|
}
|
|
587
597
|
this._cache.clear();
|
|
588
598
|
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
599
|
return new Promise((resolve, reject) => {
|
|
601
600
|
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
|
-
}))
|
|
601
|
+
.getNodes({
|
|
602
|
+
...filter,
|
|
603
|
+
parentId: undefined,
|
|
604
|
+
}, 1, this._pageSize, this._hasMockRoot)
|
|
623
605
|
.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;
|
|
606
|
+
next: (page) => {
|
|
607
|
+
this._nodes$.next(this.createPageNodes(page));
|
|
608
|
+
// get the children of each node thus calculating their hasChildren property
|
|
609
|
+
const childrenObservables = this._nodes$.value.map((node) => this.getPageFromCacheOrServer({ ...filter, parentId: node.id }, 1));
|
|
610
|
+
forkJoin(childrenObservables).subscribe((childrenPages) => {
|
|
611
|
+
childrenPages.forEach((page, i) => {
|
|
612
|
+
this._nodes$.value[i].hasChildren = page.total > 0;
|
|
651
613
|
});
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
614
|
+
});
|
|
615
|
+
this._dirty = false;
|
|
616
|
+
resolve(true);
|
|
655
617
|
},
|
|
656
618
|
error: (error) => {
|
|
657
619
|
reject(error);
|
|
@@ -854,7 +816,12 @@ class PagedTreeStore {
|
|
|
854
816
|
* Collapse all the nodes in the store.
|
|
855
817
|
*/
|
|
856
818
|
collapseAll() {
|
|
857
|
-
this.
|
|
819
|
+
if (this.isEmpty()) {
|
|
820
|
+
return;
|
|
821
|
+
}
|
|
822
|
+
// collapse the first node
|
|
823
|
+
const root = this._nodes$.value[0];
|
|
824
|
+
this.collapse(root.id);
|
|
858
825
|
}
|
|
859
826
|
/**
|
|
860
827
|
* Clear the cache.
|
|
@@ -875,8 +842,8 @@ class PagedTreeStore {
|
|
|
875
842
|
}
|
|
876
843
|
|
|
877
844
|
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.
|
|
845
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.1.3", ngImport: i0, type: PagedDataBrowsersModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
846
|
+
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.1.3", ngImport: i0, type: PagedDataBrowsersModule, declarations: [CompactPagerComponent,
|
|
880
847
|
RangeViewComponent,
|
|
881
848
|
BrowserTreeNodeComponent], imports: [CommonModule,
|
|
882
849
|
ReactiveFormsModule,
|
|
@@ -896,7 +863,7 @@ class PagedDataBrowsersModule {
|
|
|
896
863
|
NgToolsModule], exports: [CompactPagerComponent,
|
|
897
864
|
RangeViewComponent,
|
|
898
865
|
BrowserTreeNodeComponent] }); }
|
|
899
|
-
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.
|
|
866
|
+
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.1.3", ngImport: i0, type: PagedDataBrowsersModule, imports: [CommonModule,
|
|
900
867
|
ReactiveFormsModule,
|
|
901
868
|
// material
|
|
902
869
|
MatBadgeModule,
|
|
@@ -913,7 +880,7 @@ class PagedDataBrowsersModule {
|
|
|
913
880
|
// myrmidon
|
|
914
881
|
NgToolsModule] }); }
|
|
915
882
|
}
|
|
916
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.
|
|
883
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.1.3", ngImport: i0, type: PagedDataBrowsersModule, decorators: [{
|
|
917
884
|
type: NgModule,
|
|
918
885
|
args: [{
|
|
919
886
|
declarations: [
|