@planeasyinc/le-angular 0.0.11 → 0.0.13

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.
Files changed (29) hide show
  1. package/dist/fesm2022/planeasyinc-le-angular.mjs +363 -80
  2. package/dist/fesm2022/planeasyinc-le-angular.mjs.map +1 -1
  3. package/dist/lib/components/node/node.component.d.ts +9 -1
  4. package/dist/lib/components/side-panel/side-panel.component.d.ts +24 -0
  5. package/dist/lib/icons/icons-map.d.ts +1 -1
  6. package/dist/lib/icons/le-icon.component.d.ts +1 -1
  7. package/dist/lib/icons/svg/index.d.ts +1 -1
  8. package/dist/lib/icons/svg/{history.d.ts → info.d.ts} +1 -1
  9. package/dist/lib/services/le-data.service.d.ts +2 -2
  10. package/dist/lib/services/le-side-panel.service.d.ts +31 -0
  11. package/dist/lib/types/le-table.d.ts +14 -0
  12. package/dist/lib/types/le-tabs.d.ts +27 -0
  13. package/dist/lib/types/le-tree.d.ts +5 -0
  14. package/dist/lib/views/block-view/block-view.component.d.ts +13 -0
  15. package/dist/lib/views/chart-view/chart-view.component.d.ts +5 -1
  16. package/dist/lib/views/form-view/form-renderer.component.d.ts +6 -1
  17. package/dist/lib/views/form-view/form-view.component.d.ts +6 -1
  18. package/dist/lib/views/gird-col-view/grid-col-view.component.d.ts +5 -1
  19. package/dist/lib/views/gird-view/grid-view.component.d.ts +5 -1
  20. package/dist/lib/views/section-view/section-view.component.d.ts +5 -1
  21. package/dist/lib/views/table-view/table-view-cell.directive.d.ts +1 -1
  22. package/dist/lib/views/table-view/table-view.component.d.ts +11 -13
  23. package/dist/lib/views/tree-view/tree-view.component.d.ts +12 -0
  24. package/dist/lib/views/tree-view/tree-view.utils.d.ts +2 -0
  25. package/dist/styles/styles.scss +93 -0
  26. package/package.json +3 -3
  27. package/dist/lib/components/dialog/dialog.component.d.ts +0 -7
  28. package/dist/lib/services/le-dialog.service.d.ts +0 -10
  29. package/dist/lib/types/le-dialog.d.ts +0 -13
@@ -3,22 +3,23 @@ import { InjectionToken, inject, signal, Injectable, computed, effect, untracked
3
3
  import { HttpContextToken, HttpClient, HttpContext, HttpRequest, HttpEventType } from '@angular/common/http';
4
4
  import { map, filter, distinctUntilChanged, BehaviorSubject, Subject, takeUntil, firstValueFrom, of, tap, catchError, from, concatMap, finalize, fromEvent, startWith } from 'rxjs';
5
5
  import { decodeJwt, UrlFragmentBuilder, normalizeConfig } from '@planeasyinc/le-core';
6
- import { Location, JsonPipe, DatePipe, ViewportScroller } from '@angular/common';
6
+ import { Location, JsonPipe, UpperCasePipe, DatePipe, ViewportScroller } from '@angular/common';
7
7
  import { CdkDrag } from '@angular/cdk/drag-drop';
8
8
  import { BreakpointObserver, Breakpoints } from '@angular/cdk/layout';
9
9
  import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
10
10
  import { coerceNumberProperty } from '@angular/cdk/coercion';
11
+ import { ComponentPortal, CdkPortalOutlet, TemplatePortal } from '@angular/cdk/portal';
11
12
  import { DataSource, CdkTable, CdkColumnDef, CdkHeaderCell, CdkHeaderCellDef, CdkCell, CdkCellDef, CdkHeaderRowDef, CdkHeaderRow, CdkRow, CdkRowDef } from '@angular/cdk/table';
12
- import { DIALOG_DATA, Dialog, DialogModule } from '@angular/cdk/dialog';
13
+ import { DialogModule } from '@angular/cdk/dialog';
13
14
  import { CdkMenuTrigger, CdkMenu, CdkMenuItem } from '@angular/cdk/menu';
14
15
  import { A11yModule } from '@angular/cdk/a11y';
16
+ import { Overlay } from '@angular/cdk/overlay';
17
+ import { NestedTreeControl, CdkTree, CdkNestedTreeNode, CdkTreeNodeDef, CdkTreeNodeOutlet, CdkTreeNodeToggle } from '@angular/cdk/tree';
18
+ import { ArrayDataSource, SelectionModel } from '@angular/cdk/collections';
15
19
  import { adaptOld } from '@planeasyinc/fe-adapters-old';
16
20
  import { adaptSections } from '@planeasyinc/fe-adapters-sections';
17
21
  import { createEngine } from '@planeasyinc/fe-core';
18
22
  import { FeFieldHost } from '@planeasyinc/fe-angular';
19
- import { Overlay } from '@angular/cdk/overlay';
20
- import { ComponentPortal, TemplatePortal } from '@angular/cdk/portal';
21
- import { SelectionModel } from '@angular/cdk/collections';
22
23
  import * as i1 from '@angular/forms';
23
24
  import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
24
25
 
@@ -199,22 +200,25 @@ class LEDataService {
199
200
  parentPath = this._parentPath.asReadonly();
200
201
  config = this._config.asReadonly();
201
202
  customCss = this._customCss.asReadonly();
202
- constructor() {
203
+ registerEffects() {
203
204
  effect(() => {
204
205
  const node = this.leNavigationService.node();
205
206
  if (!node)
206
207
  return;
207
208
  untracked(() => {
208
209
  const view = this.view();
209
- if (node.id === view.id)
210
+ if (node.id === view?.id)
210
211
  return;
211
212
  this._view.set(node);
212
213
  });
213
214
  });
214
215
  }
215
- setView(node) {
216
+ setView(node, skipLocationChange) {
216
217
  this._view.set(node);
217
- this.leNavigationService.navigate(node);
218
+ if (!skipLocationChange) {
219
+ window.scrollTo({ top: 0, behavior: 'smooth' });
220
+ this.leNavigationService.navigate(node);
221
+ }
218
222
  }
219
223
  requestConfig(force) {
220
224
  if (this._config() && !force) {
@@ -249,6 +253,8 @@ class LEDataService {
249
253
  }
250
254
  }
251
255
  getNodeById(id, node = this._config()) {
256
+ if (!node)
257
+ return null;
252
258
  if (node.id === id) {
253
259
  return node;
254
260
  }
@@ -283,7 +289,7 @@ class LEDataService {
283
289
  }
284
290
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: LEDataService, decorators: [{
285
291
  type: Injectable
286
- }], ctorParameters: () => [] });
292
+ }] });
287
293
 
288
294
  class LEFiltersService {
289
295
  _shown = signal(false);
@@ -393,14 +399,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImpo
393
399
  }]
394
400
  }] });
395
401
 
396
- const history = {
397
- name: 'history',
398
- viewBox: '0 -960 960 960',
399
- content: [
400
- 'M480-120q-138 0-240.5-91.5T122-440h82q14 104 92.5 172T480-200q117 0 198.5-81.5T760-480q0-117-81.5-198.5T480-760q-69 0-129 32t-101 88h110v80H120v-240h80v94q51-64 124.5-99T480-840q75 0 140.5 28.5t114 77q48.5 48.5 77 114T840-480q0 75-28.5 140.5t-77 114q-48.5 48.5-114 77T480-120Zm112-192L440-464v-216h80v184l128 128-56 56Z',
401
- ],
402
- };
403
-
404
402
  const close = {
405
403
  name: 'close',
406
404
  viewBox: '0 -960 960 960',
@@ -433,12 +431,20 @@ const chevron = {
433
431
  ]
434
432
  };
435
433
 
434
+ const info = {
435
+ name: 'info',
436
+ viewBox: '0 -960 960 960',
437
+ content: [
438
+ 'M440-280h80v-240h-80v240Zm68.5-331.5Q520-623 520-640t-11.5-28.5Q497-680 480-680t-28.5 11.5Q440-657 440-640t11.5 28.5Q463-600 480-600t28.5-11.5ZM480-80q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z',
439
+ ],
440
+ };
441
+
436
442
  const ICONS_MAP = {
437
443
  chevron: chevron,
438
444
  'arrow-down': arrowDown,
439
445
  sort: sort,
440
446
  close: close,
441
- history: history,
447
+ info: info
442
448
  };
443
449
 
444
450
  class LeIconComponent {
@@ -569,8 +575,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImpo
569
575
  class ChartViewComponent {
570
576
  node = input.required();
571
577
  config = input();
578
+ event = output();
572
579
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: ChartViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
573
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.2.21", type: ChartViewComponent, isStandalone: true, selector: "chart-view", inputs: { node: { classPropertyName: "node", publicName: "node", isSignal: true, isRequired: true, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<h2>{{ node()?.title }}</h2>\n" });
580
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.2.21", type: ChartViewComponent, isStandalone: true, selector: "chart-view", inputs: { node: { classPropertyName: "node", publicName: "node", isSignal: true, isRequired: true, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { event: "event" }, ngImport: i0, template: "<h2>{{ node()?.title }}</h2>\n" });
574
581
  }
575
582
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: ChartViewComponent, decorators: [{
576
583
  type: Component,
@@ -580,15 +587,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImpo
580
587
  class GridComponent {
581
588
  node = input.required();
582
589
  config = input();
590
+ event = output();
583
591
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: GridComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
584
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: GridComponent, isStandalone: true, selector: "grid-view", inputs: { node: { classPropertyName: "node", publicName: "node", isSignal: true, isRequired: true, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.le-gird-view": "true", "style.grid-template-columns": "node().layout.columns ?? 1" } }, ngImport: i0, template: "@for (child of node().children; track child.id) {\n <le-node [node]=\"child\" [config]=\"config()\"></le-node>\n}\n", dependencies: [{ kind: "component", type: i0.forwardRef(() => NodeComponent), selector: "le-node", inputs: ["node", "config"] }] });
592
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: GridComponent, isStandalone: true, selector: "grid-view", inputs: { node: { classPropertyName: "node", publicName: "node", isSignal: true, isRequired: true, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { event: "event" }, host: { properties: { "class.le-gird-view": "true", "style.grid-template-columns": "node().layout.columns ?? 1" } }, ngImport: i0, template: "@for (child of node().children; track child.id) {\n <le-node [node]=\"child\" [config]=\"config()\" (event)=\"event.emit($event)\"></le-node>\n}\n", dependencies: [{ kind: "component", type: i0.forwardRef(() => NodeComponent), selector: "le-node", inputs: ["node", "config"], outputs: ["event"] }] });
585
593
  }
586
594
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: GridComponent, decorators: [{
587
595
  type: Component,
588
596
  args: [{ selector: 'grid-view', imports: [forwardRef(() => NodeComponent)], host: {
589
597
  '[class.le-gird-view]': 'true',
590
598
  '[style.grid-template-columns]': 'node().layout.columns ?? 1',
591
- }, template: "@for (child of node().children; track child.id) {\n <le-node [node]=\"child\" [config]=\"config()\"></le-node>\n}\n" }]
599
+ }, template: "@for (child of node().children; track child.id) {\n <le-node [node]=\"child\" [config]=\"config()\" (event)=\"event.emit($event)\"></le-node>\n}\n" }]
592
600
  }] });
593
601
 
594
602
  class TableDataSource extends DataSource {
@@ -993,33 +1001,215 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImpo
993
1001
  }]
994
1002
  }], ctorParameters: () => [] });
995
1003
 
996
- class DialogComponent {
997
- data = inject(DIALOG_DATA);
998
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: DialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
999
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: DialogComponent, isStandalone: true, selector: "ng-component", ngImport: i0, template: "@if (data.title) {\n <div>{{ data.title }}</div>\n}\n\n@if (data.node) {\n <le-node [node]=\"data.node\" [config]=\"data.config\"></le-node>\n}\n", dependencies: [{ kind: "component", type: i0.forwardRef(() => NodeComponent), selector: "le-node", inputs: ["node", "config"] }] });
1004
+ const flattenNodes = (nodes) => {
1005
+ const flattenedNodes = [];
1006
+ for (const node of nodes) {
1007
+ flattenedNodes.push(node);
1008
+ if (node.leafs) {
1009
+ flattenedNodes.push(...flattenNodes(node.leafs));
1010
+ }
1011
+ }
1012
+ return flattenedNodes;
1013
+ };
1014
+ const toTree = (obj, label) => {
1015
+ if (obj !== null && typeof obj === 'object') {
1016
+ const entries = Array.isArray(obj)
1017
+ ? obj.map((v, i) => toTree(v, String(i)))
1018
+ : Object.entries(obj).map((item) => toTree(item[1], item[0]));
1019
+ return { label, leafs: entries };
1020
+ }
1021
+ return { label, value: obj };
1022
+ };
1023
+ const mapObjectToTree = (data) => {
1024
+ return Object.entries(data).map((item) => toTree(item[1], item[0]));
1025
+ };
1026
+
1027
+ class TreeViewComponent {
1028
+ treeControl = new NestedTreeControl((node) => node.leafs);
1029
+ data = input();
1030
+ source = computed(() => {
1031
+ return new ArrayDataSource(mapObjectToTree(this.data() ?? {}));
1032
+ });
1033
+ hasChild = (_, node) => !!node.leafs && node.leafs.length > 0;
1034
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: TreeViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1035
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.2.21", type: TreeViewComponent, isStandalone: true, selector: "le-tree-view", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<cdk-tree [dataSource]=\"source()\" [treeControl]=\"treeControl\">\n <!-- Tree node template for leaf nodes -->\n <cdk-nested-tree-node *cdkTreeNodeDef=\"let node\" class=\"le-tree-node\">\n <div class=\"le-tree-row\">\n <b>{{node.label | uppercase}}</b>: &nbsp;&nbsp;&nbsp; {{node.value}}\n </div>\n </cdk-nested-tree-node>\n\n <!-- Tree node template for expandable nodes -->\n <cdk-nested-tree-node *cdkTreeNodeDef=\"let node; when: hasChild\" class=\"le-tree-node\">\n\n <a class=\"le-tree-row\" [class.le-tree-row--expanded]=\"treeControl.isExpanded(node)\" [attr.aria-label]=\"'Toggle ' + node.label\" cdkTreeNodeToggle>\n <b>{{node.label | uppercase}}</b>:\n\n <le-icon class=\"le-tree-chevron\" name=\"chevron\"></le-icon>\n </a>\n\n <div [class.le-tree-invisible]=\"!treeControl.isExpanded(node)\">\n <ng-container cdkTreeNodeOutlet></ng-container>\n </div>\n </cdk-nested-tree-node>\n</cdk-tree>\n", dependencies: [{ kind: "component", type: CdkTree, selector: "cdk-tree", inputs: ["dataSource", "treeControl", "trackBy"], exportAs: ["cdkTree"] }, { kind: "directive", type: CdkNestedTreeNode, selector: "cdk-nested-tree-node", exportAs: ["cdkNestedTreeNode"] }, { kind: "directive", type: CdkTreeNodeDef, selector: "[cdkTreeNodeDef]", inputs: ["cdkTreeNodeDefWhen"] }, { kind: "directive", type: CdkTreeNodeOutlet, selector: "[cdkTreeNodeOutlet]" }, { kind: "component", type: LeIconComponent, selector: "le-icon", inputs: ["name", "size"] }, { kind: "directive", type: CdkTreeNodeToggle, selector: "[cdkTreeNodeToggle]", inputs: ["cdkTreeNodeToggleRecursive"] }, { kind: "pipe", type: UpperCasePipe, name: "uppercase" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1000
1036
  }
1001
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: DialogComponent, decorators: [{
1037
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: TreeViewComponent, decorators: [{
1002
1038
  type: Component,
1003
- args: [{ imports: [forwardRef(() => NodeComponent)], template: "@if (data.title) {\n <div>{{ data.title }}</div>\n}\n\n@if (data.node) {\n <le-node [node]=\"data.node\" [config]=\"data.config\"></le-node>\n}\n" }]
1039
+ args: [{ selector: 'le-tree-view', imports: [
1040
+ CdkTree,
1041
+ CdkNestedTreeNode,
1042
+ CdkTreeNodeDef,
1043
+ CdkTreeNodeOutlet,
1044
+ LeIconComponent,
1045
+ CdkTreeNodeToggle,
1046
+ UpperCasePipe,
1047
+ ], changeDetection: ChangeDetectionStrategy.OnPush, template: "<cdk-tree [dataSource]=\"source()\" [treeControl]=\"treeControl\">\n <!-- Tree node template for leaf nodes -->\n <cdk-nested-tree-node *cdkTreeNodeDef=\"let node\" class=\"le-tree-node\">\n <div class=\"le-tree-row\">\n <b>{{node.label | uppercase}}</b>: &nbsp;&nbsp;&nbsp; {{node.value}}\n </div>\n </cdk-nested-tree-node>\n\n <!-- Tree node template for expandable nodes -->\n <cdk-nested-tree-node *cdkTreeNodeDef=\"let node; when: hasChild\" class=\"le-tree-node\">\n\n <a class=\"le-tree-row\" [class.le-tree-row--expanded]=\"treeControl.isExpanded(node)\" [attr.aria-label]=\"'Toggle ' + node.label\" cdkTreeNodeToggle>\n <b>{{node.label | uppercase}}</b>:\n\n <le-icon class=\"le-tree-chevron\" name=\"chevron\"></le-icon>\n </a>\n\n <div [class.le-tree-invisible]=\"!treeControl.isExpanded(node)\">\n <ng-container cdkTreeNodeOutlet></ng-container>\n </div>\n </cdk-nested-tree-node>\n</cdk-tree>\n" }]
1004
1048
  }] });
1005
1049
 
1006
- class LeDialogService {
1007
- dialog = inject(Dialog);
1008
- open(data, config = {}) {
1009
- const dialogRef = this.dialog.open(DialogComponent, {
1010
- maxWidth: '80vw',
1011
- maxHeight: '80vh',
1012
- minWidth: '40vw',
1013
- panelClass: 'le-dialog-container',
1014
- data,
1015
- injector: config?.injector,
1050
+ class BlockViewComponent {
1051
+ data = input.required();
1052
+ columns = input.required();
1053
+ event = output();
1054
+ onCellClicked(data) {
1055
+ this.event.emit({ type: 'cell_clicked', data });
1056
+ this.event.emit({ type: 'close' });
1057
+ }
1058
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: BlockViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1059
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: BlockViewComponent, isStandalone: true, selector: "le-block-view", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: true, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { event: "event" }, ngImport: i0, template: "<div class=\"block-view\">\n @for (column of columns(); track column) {\n <div class=\"block-view-item\">\n <div class=\"block-view-label\">\n {{column.label}}\n </div>\n\n <div class=\"block-view-value\">\n @if (data(); as row) {\n <ng-template\n tableViewCell\n [data]=\"row[column.key]\"\n [type]=\"column.column_format?.cellTemplate\"\n [column]=\"column\"\n [metadata]=\"row._metadata\"\n (clicked)=\"onCellClicked($event)\"\n ></ng-template>\n }\n </div>\n </div>\n }\n</div>\n", dependencies: [{ kind: "directive", type: TableViewCellDirective, selector: "[tableViewCell]", inputs: ["type", "data", "column", "metadata"], outputs: ["clicked"] }] });
1060
+ }
1061
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: BlockViewComponent, decorators: [{
1062
+ type: Component,
1063
+ args: [{ selector: 'le-block-view', imports: [TableViewCellDirective], template: "<div class=\"block-view\">\n @for (column of columns(); track column) {\n <div class=\"block-view-item\">\n <div class=\"block-view-label\">\n {{column.label}}\n </div>\n\n <div class=\"block-view-value\">\n @if (data(); as row) {\n <ng-template\n tableViewCell\n [data]=\"row[column.key]\"\n [type]=\"column.column_format?.cellTemplate\"\n [column]=\"column\"\n [metadata]=\"row._metadata\"\n (clicked)=\"onCellClicked($event)\"\n ></ng-template>\n }\n </div>\n </div>\n }\n</div>\n" }]
1064
+ }] });
1065
+
1066
+ class SidePanelComponent {
1067
+ dataService = inject(LEDataService);
1068
+ _selectedTab = signal(0);
1069
+ data = input.required();
1070
+ config = input();
1071
+ event = output();
1072
+ node = this.dataService.view;
1073
+ tabs = computed(() => {
1074
+ const data = this.data();
1075
+ return data.tabs.length ? data.tabs : undefined;
1076
+ });
1077
+ selectedTabIndex = this._selectedTab.asReadonly();
1078
+ selectedTab = computed(() => {
1079
+ return this.tabs()?.[this.selectedTabIndex()];
1080
+ });
1081
+ constructor() {
1082
+ effect(() => {
1083
+ const data = this.data();
1084
+ untracked(() => {
1085
+ if (data.node) {
1086
+ this.dataService.setView(data.node, true);
1087
+ }
1088
+ });
1089
+ });
1090
+ }
1091
+ onEvent(event) {
1092
+ this.event.emit(event);
1093
+ }
1094
+ onTabClick(index) {
1095
+ this._selectedTab.set(index);
1096
+ }
1097
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SidePanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1098
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: SidePanelComponent, isStandalone: true, selector: "ng-component", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: true, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { event: "event" }, host: { properties: { "style.width": "\"100%\"", "style.overflow": "\"auto\"", "style.padding": "\"0 16px\"" } }, providers: [LEDataService, LEFiltersService], ngImport: i0, template: "@if (node(); as node) {\n <le-node [node]=\"node\" [config]=\"data()?.config\" (event)=\"onEvent($event)\"></le-node>\n}\n\n@if (tabs(); as tabs) {\n <div class=\"le-tabs-nav\">\n @for (tab of tabs; track tab.type; let idx = $index) {\n <button\n class=\"le-button le-button-flat le-button--success\"\n [attr.aria-label]=\"'Select ' + tab.type\"\n [class.le-button--success]=\"selectedTabIndex() === idx\"\n (click)=\"onTabClick(idx)\"\n >\n {{ tab.label }}\n </button>\n }\n <span class=\"spacer\"></span>\n\n <button\n aria-label=\"Close side panel\"\n class=\"le-button le-button-flat\"\n (click)=\"event.emit({ type: 'close' })\"\n >Close</button>\n </div>\n}\n\n@if (selectedTab(); as selectedTab) {\n <div class=\"le-tabs-content\">\n @switch (selectedTab.type) {\n @case ('tree') {\n <le-tree-view [data]=\"selectedTab.data\"></le-tree-view>\n }\n @case ('table') {\n <le-node\n [node]=\"selectedTab.data\"\n [config]=\"data()?.config\"\n (event)=\"onEvent($event)\"\n ></le-node>\n }\n @case ('block') {\n <le-block-view\n [data]=\"selectedTab.data\"\n [columns]=\"selectedTab.columns\"\n (event)=\"onEvent($event)\"\n ></le-block-view>\n }\n }\n </div>\n}\n", dependencies: [{ kind: "component", type: i0.forwardRef(() => NodeComponent), selector: "le-node", inputs: ["node", "config"], outputs: ["event"] }, { kind: "component", type: i0.forwardRef(() => TreeViewComponent), selector: "le-tree-view", inputs: ["data"] }, { kind: "component", type: i0.forwardRef(() => BlockViewComponent), selector: "le-block-view", inputs: ["data", "columns"], outputs: ["event"] }] });
1099
+ }
1100
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SidePanelComponent, decorators: [{
1101
+ type: Component,
1102
+ args: [{ host: {
1103
+ '[style.width]': '"100%"',
1104
+ '[style.overflow]': '"auto"',
1105
+ '[style.padding]': '"0 16px"',
1106
+ }, imports: [forwardRef(() => NodeComponent), TreeViewComponent, BlockViewComponent], providers: [LEDataService, LEFiltersService], template: "@if (node(); as node) {\n <le-node [node]=\"node\" [config]=\"data()?.config\" (event)=\"onEvent($event)\"></le-node>\n}\n\n@if (tabs(); as tabs) {\n <div class=\"le-tabs-nav\">\n @for (tab of tabs; track tab.type; let idx = $index) {\n <button\n class=\"le-button le-button-flat le-button--success\"\n [attr.aria-label]=\"'Select ' + tab.type\"\n [class.le-button--success]=\"selectedTabIndex() === idx\"\n (click)=\"onTabClick(idx)\"\n >\n {{ tab.label }}\n </button>\n }\n <span class=\"spacer\"></span>\n\n <button\n aria-label=\"Close side panel\"\n class=\"le-button le-button-flat\"\n (click)=\"event.emit({ type: 'close' })\"\n >Close</button>\n </div>\n}\n\n@if (selectedTab(); as selectedTab) {\n <div class=\"le-tabs-content\">\n @switch (selectedTab.type) {\n @case ('tree') {\n <le-tree-view [data]=\"selectedTab.data\"></le-tree-view>\n }\n @case ('table') {\n <le-node\n [node]=\"selectedTab.data\"\n [config]=\"data()?.config\"\n (event)=\"onEvent($event)\"\n ></le-node>\n }\n @case ('block') {\n <le-block-view\n [data]=\"selectedTab.data\"\n [columns]=\"selectedTab.columns\"\n (event)=\"onEvent($event)\"\n ></le-block-view>\n }\n }\n </div>\n}\n" }]
1107
+ }], ctorParameters: () => [] });
1108
+
1109
+ const positionMap = {
1110
+ right: (position) => position.right().top('0'),
1111
+ left: (position) => position.left().top('0'),
1112
+ top: (position) => position.top('0'),
1113
+ bottom: (position) => position.bottom('0'),
1114
+ };
1115
+ class LeSidePanelService {
1116
+ overlay = inject(Overlay);
1117
+ breakpointObserver = inject(BreakpointObserver);
1118
+ overlayRef;
1119
+ output = new Subject();
1120
+ show(data, config) {
1121
+ if (this.overlayRef)
1122
+ this.hide();
1123
+ const destroy$ = new Subject();
1124
+ this.overlayRef = this.overlay.create({
1125
+ width: this.getWidth(config),
1126
+ height: this.getHeight(config),
1127
+ panelClass: 'le-side-panel',
1128
+ hasBackdrop: config.hasBackdrop ?? true,
1129
+ positionStrategy: this.getPositionStrategy(config),
1130
+ scrollStrategy: this.overlay.scrollStrategies.reposition(),
1016
1131
  });
1017
- return dialogRef.closed;
1132
+ this.overlayRef.addPanelClass(this.getClosedClass(config));
1133
+ this.overlayRef?.outsidePointerEvents().subscribe({
1134
+ next: () => {
1135
+ this.overlayRef?.addPanelClass(this.getClosedClass(config));
1136
+ this.delayed(() => this.hide());
1137
+ },
1138
+ });
1139
+ const componentRef = this.overlayRef.attach(new ComponentPortal(SidePanelComponent, null, config.injector));
1140
+ componentRef.setInput('data', data);
1141
+ this.delayed(() => this.overlayRef?.removePanelClass(this.getClosedClass(config)));
1142
+ const sub = componentRef.instance.event.subscribe((event) => {
1143
+ this.output.next(event);
1144
+ if (event.type === 'close') {
1145
+ this.overlayRef?.addPanelClass(this.getClosedClass(config));
1146
+ this.delayed(() => this.hide());
1147
+ }
1148
+ });
1149
+ componentRef.onDestroy(() => {
1150
+ sub.unsubscribe();
1151
+ destroy$.next();
1152
+ destroy$.complete();
1153
+ });
1154
+ return this.output.pipe(takeUntil(destroy$));
1155
+ }
1156
+ hide() {
1157
+ this.overlayRef?.dispose();
1158
+ this.overlayRef = undefined;
1159
+ }
1160
+ delayed(fn) {
1161
+ setTimeout(() => fn(), 300);
1162
+ }
1163
+ getHeight(config) {
1164
+ if (config.height) {
1165
+ return config.height;
1166
+ }
1167
+ if (config.position === 'top' || config.position === 'bottom') {
1168
+ if (this.breakpointObserver.isMatched(Breakpoints.XSmall)) {
1169
+ return '80vh';
1170
+ }
1171
+ else if (this.breakpointObserver.isMatched(Breakpoints.Small)) {
1172
+ return '60vh';
1173
+ }
1174
+ else {
1175
+ return '40vh';
1176
+ }
1177
+ }
1178
+ return '100vh';
1018
1179
  }
1019
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: LeDialogService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1020
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: LeDialogService, providedIn: 'root' });
1180
+ getWidth(config) {
1181
+ if (config.width) {
1182
+ return config.width;
1183
+ }
1184
+ if (config.position === 'left' || config.position === 'right') {
1185
+ if (this.breakpointObserver.isMatched(Breakpoints.XSmall)) {
1186
+ return '80vw';
1187
+ }
1188
+ else if (this.breakpointObserver.isMatched(Breakpoints.Small)) {
1189
+ return '60vw';
1190
+ }
1191
+ else {
1192
+ return '40vw';
1193
+ }
1194
+ }
1195
+ else {
1196
+ return '100vw';
1197
+ }
1198
+ }
1199
+ getClosedClass(config) {
1200
+ return `le-side-panel--${config.position}`;
1201
+ }
1202
+ getPositionStrategy({ position }) {
1203
+ let positionStrategy = this.overlay.position().global();
1204
+ if (positionMap[position]) {
1205
+ return positionMap[position](positionStrategy);
1206
+ }
1207
+ return positionStrategy;
1208
+ }
1209
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: LeSidePanelService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1210
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: LeSidePanelService, providedIn: 'root' });
1021
1211
  }
1022
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: LeDialogService, decorators: [{
1212
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: LeSidePanelService, decorators: [{
1023
1213
  type: Injectable,
1024
1214
  args: [{
1025
1215
  providedIn: 'root',
@@ -1030,10 +1220,11 @@ class TableViewComponent {
1030
1220
  apiService = inject(LEApiService);
1031
1221
  dataService = inject(LEDataService);
1032
1222
  filtersService = inject(LEFiltersService);
1033
- dialogService = inject(LeDialogService);
1223
+ sidePanelService = inject(LeSidePanelService);
1034
1224
  injector = inject(Injector);
1035
1225
  node = input.required();
1036
1226
  config = input();
1227
+ event = output();
1037
1228
  _columns = signal([]);
1038
1229
  _data = signal(new TableDataSource());
1039
1230
  _total = signal(0);
@@ -1052,8 +1243,8 @@ class TableViewComponent {
1052
1243
  const firstRow = this.data().getValueByIndex(0);
1053
1244
  const columnKeys = this.columns().map((column) => column.key);
1054
1245
  const hasVersion = !!(firstRow && firstRow._metadata && firstRow._metadata.object_version);
1055
- if (!this.config()?.hideMetadata && hasVersion) {
1056
- result.push('versions');
1246
+ if (!this.config()?.hideInfo) {
1247
+ result.push('info');
1057
1248
  }
1058
1249
  result.push(...columnKeys);
1059
1250
  if (hasVersion) {
@@ -1114,15 +1305,14 @@ class TableViewComponent {
1114
1305
  }
1115
1306
  onRowClick(row) {
1116
1307
  const actions = this.node().actions?.onRowClick ?? [];
1117
- actions.forEach((action) => this.processTableAction(action, row));
1308
+ actions.forEach((action) => this.processRowClickAction(action, row));
1118
1309
  }
1119
- onRowVersionClick(event, row) {
1310
+ onRowInfoClick(event, row) {
1120
1311
  event.preventDefault();
1121
1312
  event.stopImmediatePropagation();
1122
1313
  const node = {
1123
1314
  id: row._metadata.lakehouse_address,
1124
1315
  type: 'table',
1125
- title: 'Versions',
1126
1316
  dataSource: {
1127
1317
  kind: 'object',
1128
1318
  entity: row._metadata.lakehouse_address,
@@ -1134,13 +1324,34 @@ class TableViewComponent {
1134
1324
  },
1135
1325
  },
1136
1326
  };
1137
- this.dialogService
1138
- .open({ node, config: { hideFilters: true, hideMetadata: true, showCloseButton: true } }, { injector: this.injector })
1139
- .subscribe();
1327
+ this.sidePanelService
1328
+ .show({
1329
+ tabs: [
1330
+ { type: 'block', label: 'Object', data: row, columns: this._columns() },
1331
+ { type: 'tree', label: 'Metadata', data: row._metadata },
1332
+ { type: 'table', label: 'Versions', data: node },
1333
+ ],
1334
+ config: {
1335
+ hasCloseButton: true,
1336
+ skipLocationChange: true,
1337
+ hideFilters: true,
1338
+ hideInfo: true,
1339
+ },
1340
+ }, {
1341
+ position: 'bottom',
1342
+ injector: this.injector,
1343
+ })
1344
+ .subscribe({
1345
+ next: event => {
1346
+ if (event.type === 'cell_clicked') {
1347
+ this.onCellClicked(event.data);
1348
+ }
1349
+ }
1350
+ });
1140
1351
  }
1141
1352
  onCellClicked(data) {
1142
1353
  const path = `${data.ref.resource}%23${data.ref.class_name}%3A${data.ref.class_version}%3A${data.ref.object_id}%3A${data.ref.object_version}`;
1143
- this.dataService.setView({
1354
+ this.setView({
1144
1355
  id: path,
1145
1356
  type: 'form',
1146
1357
  controlSource: {
@@ -1149,22 +1360,45 @@ class TableViewComponent {
1149
1360
  },
1150
1361
  });
1151
1362
  }
1152
- processTableAction(action, row) {
1363
+ processRowClickAction(action, row) {
1364
+ const { type, node } = action;
1365
+ if (type === 'open_sidebar' && 'controlSource' in node) {
1366
+ if (node.controlSource?.params) {
1367
+ node.controlSource.params = this.interpolateRowValues(node.controlSource.params, row);
1368
+ }
1369
+ this.sidePanelService
1370
+ .show({
1371
+ node,
1372
+ tabs: [],
1373
+ config: { hasCloseButton: true, skipLocationChange: true },
1374
+ }, {
1375
+ position: 'right',
1376
+ injector: this.injector,
1377
+ })
1378
+ .subscribe((event) => {
1379
+ if (event.type === 'refresh') {
1380
+ this.forceFetch();
1381
+ }
1382
+ });
1383
+ }
1384
+ }
1385
+ processTableAction(action) {
1153
1386
  if (action.type === 'update_form') {
1154
1387
  const dataSource = action.dataSource;
1155
- this.dataService.setView({
1388
+ this.setView({
1156
1389
  id: action.type,
1157
1390
  type: 'form',
1158
1391
  controlSource: {
1159
1392
  kind: dataSource.kind,
1160
1393
  entity: dataSource.entity,
1161
- params: dataSource?.params
1162
- ? this.interpolateRowValues(dataSource.params, row)
1163
- : undefined,
1394
+ params: dataSource?.params,
1164
1395
  },
1165
1396
  });
1166
1397
  }
1167
1398
  }
1399
+ setView(node) {
1400
+ this.dataService.setView(node, !!this.config()?.skipLocationChange);
1401
+ }
1168
1402
  setPagination(pagination) {
1169
1403
  this._pageSize.set(pagination?.pageSize ?? 0);
1170
1404
  this._pageSizeOptions.set(pagination?.options ?? []);
@@ -1280,8 +1514,27 @@ class TableViewComponent {
1280
1514
  });
1281
1515
  });
1282
1516
  }
1517
+ forceFetch() {
1518
+ const node = this.node();
1519
+ const pageSize = this.pageSize();
1520
+ const pageIndex = this.pageIndex();
1521
+ const sort = this._sortMap();
1522
+ const filters = this.filtersService.selection();
1523
+ if (node?.dataSource) {
1524
+ const ctx = buildRequestContext({
1525
+ pageSize,
1526
+ pageIndex,
1527
+ sort: mapSortMapToSortStringList(sort),
1528
+ filters,
1529
+ }, {
1530
+ isSortable: this.isSortingEnabled(),
1531
+ hasPagination: !!this.pageSize(),
1532
+ });
1533
+ this.getTableData(node, ctx);
1534
+ }
1535
+ }
1283
1536
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: TableViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1284
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: TableViewComponent, isStandalone: true, selector: "table-view", inputs: { node: { classPropertyName: "node", publicName: "node", isSignal: true, isRequired: true, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"le-toolbar\">\n @if (node(); as node) {\n <h2>{{ node?.title }}</h2>\n\n\n <span class=\"spacer\"></span>\n\n @if (filters().length) {\n <button class=\"le-button\" (click)=\"onFiltersClick($event)\">Filters</button>\n }\n\n @if (node.actions?.tableActions) {\n <table-view-actions\n [actions]=\"node.actions!.tableActions\"\n (actionClicked)=\"onToolbarActionClick($event)\"\n ></table-view-actions>\n }\n }\n</div>\n\n@if (pageSize()) {\n <table-view-pagination\n [pageSize]=\"pageSize()\"\n [pageSizeOptions]=\"pageSizeOptions()\"\n [entriesCount]=\"entriesCount()\"\n (pageChange)=\"onPageChange($event)\"\n ></table-view-pagination>\n}\n\n<div class=\"le-table-container\">\n @if (displayedColumns().length) {\n <table cdk-table [dataSource]=\"data()\" class=\"le-table\" [class.le-table--loading]=\"isLoading()\">\n <!-- Version column -->\n <ng-container cdkColumnDef=\"versions\">\n <th class=\"le-table-header-cell le-table-icon-cell\" cdk-header-cell *cdkHeaderCellDef>\n <le-icon size=\"16\" class=\"le-icon\" name=\"history\"></le-icon>\n </th>\n\n <td class=\"le-table-cell le-table-icon-cell\" cdk-cell *cdkCellDef=\"let row\">\n <button class=\"le-button le-button-basic le-button--success\" aria-label=\"View versions\" (click)=\"onRowVersionClick($event, row)\">\n <le-icon size=\"16\" class=\"le-icon\" name=\"history\"></le-icon>\n </button>\n </td>\n </ng-container>\n <!-- Modified column -->\n <ng-container cdkColumnDef=\"modified\">\n <th class=\"le-table-header-cell\" cdk-header-cell *cdkHeaderCellDef>\n <div class=\"le-cell-content\">\n Modified\n </div>\n </th>\n\n <td class=\"le-table-cell\" cdk-cell *cdkCellDef=\"let row\">\n <span class=\"le-table-template le-template-string\">\n {{ row._metadata.updated_at | date:'medium' }}\n </span>\n </td>\n </ng-container>\n\n <!-- Columns -->\n @for (column of columns(); track column) {\n <ng-container [cdkColumnDef]=\"column.key\">\n <th\n class=\"le-table-header-cell\"\n cdk-header-cell\n *cdkHeaderCellDef\n [tabindex]=\"sortColumnKeys().has(column.key) ? 0 : -1\"\n [class.le-table-header-cell--sortable]=\"sortColumnKeys().has(column.key)\"\n (click)=\"sortColumnKeys().has(column.key) && onSortClick($event, column)\"\n >\n <div class=\"le-cell-content\">\n <ng-template\n tableViewCell\n [data]=\"column.label\"\n [type]=\"column.column_format?.headerTemplate\"\n ></ng-template>\n\n @if (sortColumnKeys().has(column.key)) {\n <div class=\"le-sort-container\">\n @if (sortMap().has(column.key)) {\n <div class=\"le-sort-icon\">\n <i\n class=\"le-sort-arrow\"\n [class.le-sort-arrow--asc]=\"sortMap().get(column.key) === 'asc'\"\n [class.le-sort-arrow--desc]=\"sortMap().get(column.key) === 'desc'\"\n ></i>\n </div>\n\n <div class=\"le-sort-order\">\n @if (sortOrder().has(column.key)) {\n <span>\n {{ sortOrder().get(column.key) }}\n </span>\n }\n </div>\n } @else {\n <le-icon name=\"sort\" class=\"le-sort-icon le-sort-icon--unfold\"></le-icon>\n }\n </div>\n }\n </div>\n </th>\n\n <td class=\"le-table-cell\" cdk-cell *cdkCellDef=\"let row\">\n <ng-template\n tableViewCell\n [data]=\"row[column.key]\"\n [type]=\"column.column_format?.cellTemplate\"\n [column]=\"column\"\n [metadata]=\"row._metadata\"\n (clicked)=\"onCellClicked($event)\"\n ></ng-template>\n </td>\n </ng-container>\n }\n\n <tr cdk-header-row class=\"le-header-row\" *cdkHeaderRowDef=\"displayedColumns()\"></tr>\n <tr\n cdk-row\n class=\"le-table-row\"\n [tabindex]=\"0\"\n [class.le-table-row--clickable]=\"hasRowClickAction()\"\n *cdkRowDef=\"let row; columns: displayedColumns()\"\n (click)=\"onRowClick(row)\"\n ></tr>\n </table>\n }\n</div>\n\n@if (data().count === 0) {\n @if (isLoading()) {\n <app-loading-view [headerHeight]=\"65\" [rowCount]=\"pageSize() || 10\"></app-loading-view>\n } @else {\n <div class=\"no-entities\">\n <span>No Entities</span>\n </div>\n }\n}\n", dependencies: [{ kind: "component", type: CdkTable, selector: "cdk-table, table[cdk-table]", inputs: ["trackBy", "dataSource", "multiTemplateDataRows", "fixedLayout"], outputs: ["contentChanged"], exportAs: ["cdkTable"] }, { kind: "directive", type: CdkColumnDef, selector: "[cdkColumnDef]", inputs: ["cdkColumnDef", "sticky", "stickyEnd"] }, { kind: "directive", type: CdkHeaderCell, selector: "cdk-header-cell, th[cdk-header-cell]" }, { kind: "directive", type: CdkHeaderCellDef, selector: "[cdkHeaderCellDef]" }, { kind: "directive", type: CdkCell, selector: "cdk-cell, td[cdk-cell]" }, { kind: "directive", type: CdkCellDef, selector: "[cdkCellDef]" }, { kind: "directive", type: CdkHeaderRowDef, selector: "[cdkHeaderRowDef]", inputs: ["cdkHeaderRowDef", "cdkHeaderRowDefSticky"] }, { kind: "component", type: CdkHeaderRow, selector: "cdk-header-row, tr[cdk-header-row]" }, { kind: "component", type: CdkRow, selector: "cdk-row, tr[cdk-row]" }, { kind: "directive", type: CdkRowDef, selector: "[cdkRowDef]", inputs: ["cdkRowDefColumns", "cdkRowDefWhen"] }, { kind: "component", type: TableViewPaginationComponent, selector: "table-view-pagination", inputs: ["pageSize", "pageSizeOptions", "entriesCount"], outputs: ["pageChange"] }, { kind: "component", type: LoadingViewComponent, selector: "app-loading-view", inputs: ["headerHeight", "rowHeight", "rowCount"] }, { kind: "component", type: TableViewActions, selector: "table-view-actions", inputs: ["actions"], outputs: ["actionClicked"] }, { kind: "directive", type: TableViewCellDirective, selector: "[tableViewCell]", inputs: ["type", "data", "column", "metadata"], outputs: ["clicked"] }, { kind: "component", type: LeIconComponent, selector: "le-icon", inputs: ["name", "size"] }, { kind: "ngmodule", type: DialogModule }, { kind: "pipe", type: DatePipe, name: "date" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1537
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: TableViewComponent, isStandalone: true, selector: "table-view", inputs: { node: { classPropertyName: "node", publicName: "node", isSignal: true, isRequired: true, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { event: "event" }, ngImport: i0, template: "@if (node()?.title || node()?.actions || filters().length) {\n <div class=\"le-toolbar\">\n @if (node(); as node) {\n <h2>{{ node?.title }}</h2>\n\n <span class=\"spacer\"></span>\n\n @if (filters().length) {\n <button class=\"le-button\" (click)=\"onFiltersClick($event)\">Filters</button>\n }\n\n @if (node.actions?.tableActions) {\n <table-view-actions\n [actions]=\"node.actions!.tableActions\"\n (actionClicked)=\"onToolbarActionClick($event)\"\n ></table-view-actions>\n }\n }\n </div>\n}\n\n@if (pageSize()) {\n <table-view-pagination\n [pageSize]=\"pageSize()\"\n [pageSizeOptions]=\"pageSizeOptions()\"\n [entriesCount]=\"entriesCount()\"\n (pageChange)=\"onPageChange($event)\"\n ></table-view-pagination>\n}\n\n<div class=\"le-table-container\">\n @if (displayedColumns().length) {\n <table cdk-table [dataSource]=\"data()\" class=\"le-table\" [class.le-table--loading]=\"isLoading()\">\n <!-- Info column -->\n <ng-container cdkColumnDef=\"info\">\n <th class=\"le-table-header-cell le-table-icon-cell\" cdk-header-cell *cdkHeaderCellDef>\n <le-icon size=\"16\" class=\"le-icon\" name=\"info\"></le-icon>\n </th>\n\n <td class=\"le-table-cell le-table-icon-cell\" cdk-cell *cdkCellDef=\"let row\">\n <button class=\"le-button le-button-basic le-button--success\" aria-label=\"View info\" (click)=\"onRowInfoClick($event, row)\">\n <le-icon size=\"16\" class=\"le-icon\" name=\"info\"></le-icon>\n </button>\n </td>\n </ng-container>\n <!-- Modified column -->\n <ng-container cdkColumnDef=\"modified\">\n <th class=\"le-table-header-cell\" cdk-header-cell *cdkHeaderCellDef>\n <div class=\"le-cell-content\">\n Modified\n </div>\n </th>\n\n <td class=\"le-table-cell\" cdk-cell *cdkCellDef=\"let row\">\n <span class=\"le-table-template le-template-string\">\n {{ row._metadata.updated_at | date:'medium' }}\n </span>\n </td>\n </ng-container>\n\n <!-- Columns -->\n @for (column of columns(); track column) {\n <ng-container [cdkColumnDef]=\"column.key\">\n <th\n class=\"le-table-header-cell\"\n cdk-header-cell\n *cdkHeaderCellDef\n [tabindex]=\"sortColumnKeys().has(column.key) ? 0 : -1\"\n [class.le-table-header-cell--sortable]=\"sortColumnKeys().has(column.key)\"\n (click)=\"sortColumnKeys().has(column.key) && onSortClick($event, column)\"\n >\n <div class=\"le-cell-content\">\n <ng-template\n tableViewCell\n [data]=\"column.label\"\n [type]=\"column.column_format?.headerTemplate\"\n ></ng-template>\n\n @if (sortColumnKeys().has(column.key)) {\n <div class=\"le-sort-container\">\n @if (sortMap().has(column.key)) {\n <div class=\"le-sort-icon\">\n <i\n class=\"le-sort-arrow\"\n [class.le-sort-arrow--asc]=\"sortMap().get(column.key) === 'asc'\"\n [class.le-sort-arrow--desc]=\"sortMap().get(column.key) === 'desc'\"\n ></i>\n </div>\n\n <div class=\"le-sort-order\">\n @if (sortOrder().has(column.key)) {\n <span>\n {{ sortOrder().get(column.key) }}\n </span>\n }\n </div>\n } @else {\n <le-icon name=\"sort\" class=\"le-sort-icon le-sort-icon--unfold\"></le-icon>\n }\n </div>\n }\n </div>\n </th>\n\n <td class=\"le-table-cell\" cdk-cell *cdkCellDef=\"let row\">\n <ng-template\n tableViewCell\n [data]=\"row[column.key]\"\n [type]=\"column.column_format?.cellTemplate\"\n [column]=\"column\"\n [metadata]=\"row._metadata\"\n (clicked)=\"onCellClicked($event)\"\n ></ng-template>\n </td>\n </ng-container>\n }\n\n <tr cdk-header-row class=\"le-header-row\" *cdkHeaderRowDef=\"displayedColumns()\"></tr>\n <tr\n cdk-row\n class=\"le-table-row\"\n [tabindex]=\"0\"\n [class.le-table-row--clickable]=\"hasRowClickAction()\"\n *cdkRowDef=\"let row; columns: displayedColumns()\"\n (click)=\"onRowClick(row)\"\n ></tr>\n </table>\n }\n</div>\n\n@if (data().count === 0) {\n @if (isLoading()) {\n <app-loading-view [headerHeight]=\"65\" [rowCount]=\"pageSize() || 10\"></app-loading-view>\n } @else {\n <div class=\"no-entities\">\n <span>No Entities</span>\n </div>\n }\n}\n", dependencies: [{ kind: "component", type: CdkTable, selector: "cdk-table, table[cdk-table]", inputs: ["trackBy", "dataSource", "multiTemplateDataRows", "fixedLayout"], outputs: ["contentChanged"], exportAs: ["cdkTable"] }, { kind: "directive", type: CdkColumnDef, selector: "[cdkColumnDef]", inputs: ["cdkColumnDef", "sticky", "stickyEnd"] }, { kind: "directive", type: CdkHeaderCell, selector: "cdk-header-cell, th[cdk-header-cell]" }, { kind: "directive", type: CdkHeaderCellDef, selector: "[cdkHeaderCellDef]" }, { kind: "directive", type: CdkCell, selector: "cdk-cell, td[cdk-cell]" }, { kind: "directive", type: CdkCellDef, selector: "[cdkCellDef]" }, { kind: "directive", type: CdkHeaderRowDef, selector: "[cdkHeaderRowDef]", inputs: ["cdkHeaderRowDef", "cdkHeaderRowDefSticky"] }, { kind: "component", type: CdkHeaderRow, selector: "cdk-header-row, tr[cdk-header-row]" }, { kind: "component", type: CdkRow, selector: "cdk-row, tr[cdk-row]" }, { kind: "directive", type: CdkRowDef, selector: "[cdkRowDef]", inputs: ["cdkRowDefColumns", "cdkRowDefWhen"] }, { kind: "component", type: TableViewPaginationComponent, selector: "table-view-pagination", inputs: ["pageSize", "pageSizeOptions", "entriesCount"], outputs: ["pageChange"] }, { kind: "component", type: LoadingViewComponent, selector: "app-loading-view", inputs: ["headerHeight", "rowHeight", "rowCount"] }, { kind: "component", type: TableViewActions, selector: "table-view-actions", inputs: ["actions"], outputs: ["actionClicked"] }, { kind: "directive", type: TableViewCellDirective, selector: "[tableViewCell]", inputs: ["type", "data", "column", "metadata"], outputs: ["clicked"] }, { kind: "component", type: LeIconComponent, selector: "le-icon", inputs: ["name", "size"] }, { kind: "ngmodule", type: DialogModule }, { kind: "pipe", type: DatePipe, name: "date" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1285
1538
  }
1286
1539
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: TableViewComponent, decorators: [{
1287
1540
  type: Component,
@@ -1303,7 +1556,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImpo
1303
1556
  LeIconComponent,
1304
1557
  DialogModule,
1305
1558
  DatePipe,
1306
- ], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"le-toolbar\">\n @if (node(); as node) {\n <h2>{{ node?.title }}</h2>\n\n\n <span class=\"spacer\"></span>\n\n @if (filters().length) {\n <button class=\"le-button\" (click)=\"onFiltersClick($event)\">Filters</button>\n }\n\n @if (node.actions?.tableActions) {\n <table-view-actions\n [actions]=\"node.actions!.tableActions\"\n (actionClicked)=\"onToolbarActionClick($event)\"\n ></table-view-actions>\n }\n }\n</div>\n\n@if (pageSize()) {\n <table-view-pagination\n [pageSize]=\"pageSize()\"\n [pageSizeOptions]=\"pageSizeOptions()\"\n [entriesCount]=\"entriesCount()\"\n (pageChange)=\"onPageChange($event)\"\n ></table-view-pagination>\n}\n\n<div class=\"le-table-container\">\n @if (displayedColumns().length) {\n <table cdk-table [dataSource]=\"data()\" class=\"le-table\" [class.le-table--loading]=\"isLoading()\">\n <!-- Version column -->\n <ng-container cdkColumnDef=\"versions\">\n <th class=\"le-table-header-cell le-table-icon-cell\" cdk-header-cell *cdkHeaderCellDef>\n <le-icon size=\"16\" class=\"le-icon\" name=\"history\"></le-icon>\n </th>\n\n <td class=\"le-table-cell le-table-icon-cell\" cdk-cell *cdkCellDef=\"let row\">\n <button class=\"le-button le-button-basic le-button--success\" aria-label=\"View versions\" (click)=\"onRowVersionClick($event, row)\">\n <le-icon size=\"16\" class=\"le-icon\" name=\"history\"></le-icon>\n </button>\n </td>\n </ng-container>\n <!-- Modified column -->\n <ng-container cdkColumnDef=\"modified\">\n <th class=\"le-table-header-cell\" cdk-header-cell *cdkHeaderCellDef>\n <div class=\"le-cell-content\">\n Modified\n </div>\n </th>\n\n <td class=\"le-table-cell\" cdk-cell *cdkCellDef=\"let row\">\n <span class=\"le-table-template le-template-string\">\n {{ row._metadata.updated_at | date:'medium' }}\n </span>\n </td>\n </ng-container>\n\n <!-- Columns -->\n @for (column of columns(); track column) {\n <ng-container [cdkColumnDef]=\"column.key\">\n <th\n class=\"le-table-header-cell\"\n cdk-header-cell\n *cdkHeaderCellDef\n [tabindex]=\"sortColumnKeys().has(column.key) ? 0 : -1\"\n [class.le-table-header-cell--sortable]=\"sortColumnKeys().has(column.key)\"\n (click)=\"sortColumnKeys().has(column.key) && onSortClick($event, column)\"\n >\n <div class=\"le-cell-content\">\n <ng-template\n tableViewCell\n [data]=\"column.label\"\n [type]=\"column.column_format?.headerTemplate\"\n ></ng-template>\n\n @if (sortColumnKeys().has(column.key)) {\n <div class=\"le-sort-container\">\n @if (sortMap().has(column.key)) {\n <div class=\"le-sort-icon\">\n <i\n class=\"le-sort-arrow\"\n [class.le-sort-arrow--asc]=\"sortMap().get(column.key) === 'asc'\"\n [class.le-sort-arrow--desc]=\"sortMap().get(column.key) === 'desc'\"\n ></i>\n </div>\n\n <div class=\"le-sort-order\">\n @if (sortOrder().has(column.key)) {\n <span>\n {{ sortOrder().get(column.key) }}\n </span>\n }\n </div>\n } @else {\n <le-icon name=\"sort\" class=\"le-sort-icon le-sort-icon--unfold\"></le-icon>\n }\n </div>\n }\n </div>\n </th>\n\n <td class=\"le-table-cell\" cdk-cell *cdkCellDef=\"let row\">\n <ng-template\n tableViewCell\n [data]=\"row[column.key]\"\n [type]=\"column.column_format?.cellTemplate\"\n [column]=\"column\"\n [metadata]=\"row._metadata\"\n (clicked)=\"onCellClicked($event)\"\n ></ng-template>\n </td>\n </ng-container>\n }\n\n <tr cdk-header-row class=\"le-header-row\" *cdkHeaderRowDef=\"displayedColumns()\"></tr>\n <tr\n cdk-row\n class=\"le-table-row\"\n [tabindex]=\"0\"\n [class.le-table-row--clickable]=\"hasRowClickAction()\"\n *cdkRowDef=\"let row; columns: displayedColumns()\"\n (click)=\"onRowClick(row)\"\n ></tr>\n </table>\n }\n</div>\n\n@if (data().count === 0) {\n @if (isLoading()) {\n <app-loading-view [headerHeight]=\"65\" [rowCount]=\"pageSize() || 10\"></app-loading-view>\n } @else {\n <div class=\"no-entities\">\n <span>No Entities</span>\n </div>\n }\n}\n" }]
1559
+ ], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (node()?.title || node()?.actions || filters().length) {\n <div class=\"le-toolbar\">\n @if (node(); as node) {\n <h2>{{ node?.title }}</h2>\n\n <span class=\"spacer\"></span>\n\n @if (filters().length) {\n <button class=\"le-button\" (click)=\"onFiltersClick($event)\">Filters</button>\n }\n\n @if (node.actions?.tableActions) {\n <table-view-actions\n [actions]=\"node.actions!.tableActions\"\n (actionClicked)=\"onToolbarActionClick($event)\"\n ></table-view-actions>\n }\n }\n </div>\n}\n\n@if (pageSize()) {\n <table-view-pagination\n [pageSize]=\"pageSize()\"\n [pageSizeOptions]=\"pageSizeOptions()\"\n [entriesCount]=\"entriesCount()\"\n (pageChange)=\"onPageChange($event)\"\n ></table-view-pagination>\n}\n\n<div class=\"le-table-container\">\n @if (displayedColumns().length) {\n <table cdk-table [dataSource]=\"data()\" class=\"le-table\" [class.le-table--loading]=\"isLoading()\">\n <!-- Info column -->\n <ng-container cdkColumnDef=\"info\">\n <th class=\"le-table-header-cell le-table-icon-cell\" cdk-header-cell *cdkHeaderCellDef>\n <le-icon size=\"16\" class=\"le-icon\" name=\"info\"></le-icon>\n </th>\n\n <td class=\"le-table-cell le-table-icon-cell\" cdk-cell *cdkCellDef=\"let row\">\n <button class=\"le-button le-button-basic le-button--success\" aria-label=\"View info\" (click)=\"onRowInfoClick($event, row)\">\n <le-icon size=\"16\" class=\"le-icon\" name=\"info\"></le-icon>\n </button>\n </td>\n </ng-container>\n <!-- Modified column -->\n <ng-container cdkColumnDef=\"modified\">\n <th class=\"le-table-header-cell\" cdk-header-cell *cdkHeaderCellDef>\n <div class=\"le-cell-content\">\n Modified\n </div>\n </th>\n\n <td class=\"le-table-cell\" cdk-cell *cdkCellDef=\"let row\">\n <span class=\"le-table-template le-template-string\">\n {{ row._metadata.updated_at | date:'medium' }}\n </span>\n </td>\n </ng-container>\n\n <!-- Columns -->\n @for (column of columns(); track column) {\n <ng-container [cdkColumnDef]=\"column.key\">\n <th\n class=\"le-table-header-cell\"\n cdk-header-cell\n *cdkHeaderCellDef\n [tabindex]=\"sortColumnKeys().has(column.key) ? 0 : -1\"\n [class.le-table-header-cell--sortable]=\"sortColumnKeys().has(column.key)\"\n (click)=\"sortColumnKeys().has(column.key) && onSortClick($event, column)\"\n >\n <div class=\"le-cell-content\">\n <ng-template\n tableViewCell\n [data]=\"column.label\"\n [type]=\"column.column_format?.headerTemplate\"\n ></ng-template>\n\n @if (sortColumnKeys().has(column.key)) {\n <div class=\"le-sort-container\">\n @if (sortMap().has(column.key)) {\n <div class=\"le-sort-icon\">\n <i\n class=\"le-sort-arrow\"\n [class.le-sort-arrow--asc]=\"sortMap().get(column.key) === 'asc'\"\n [class.le-sort-arrow--desc]=\"sortMap().get(column.key) === 'desc'\"\n ></i>\n </div>\n\n <div class=\"le-sort-order\">\n @if (sortOrder().has(column.key)) {\n <span>\n {{ sortOrder().get(column.key) }}\n </span>\n }\n </div>\n } @else {\n <le-icon name=\"sort\" class=\"le-sort-icon le-sort-icon--unfold\"></le-icon>\n }\n </div>\n }\n </div>\n </th>\n\n <td class=\"le-table-cell\" cdk-cell *cdkCellDef=\"let row\">\n <ng-template\n tableViewCell\n [data]=\"row[column.key]\"\n [type]=\"column.column_format?.cellTemplate\"\n [column]=\"column\"\n [metadata]=\"row._metadata\"\n (clicked)=\"onCellClicked($event)\"\n ></ng-template>\n </td>\n </ng-container>\n }\n\n <tr cdk-header-row class=\"le-header-row\" *cdkHeaderRowDef=\"displayedColumns()\"></tr>\n <tr\n cdk-row\n class=\"le-table-row\"\n [tabindex]=\"0\"\n [class.le-table-row--clickable]=\"hasRowClickAction()\"\n *cdkRowDef=\"let row; columns: displayedColumns()\"\n (click)=\"onRowClick(row)\"\n ></tr>\n </table>\n }\n</div>\n\n@if (data().count === 0) {\n @if (isLoading()) {\n <app-loading-view [headerHeight]=\"65\" [rowCount]=\"pageSize() || 10\"></app-loading-view>\n } @else {\n <div class=\"no-entities\">\n <span>No Entities</span>\n </div>\n }\n}\n" }]
1307
1560
  }], ctorParameters: () => [] });
1308
1561
 
1309
1562
  const isSectionsSchema = (raw) => {
@@ -1331,6 +1584,8 @@ class FormRendererComponent {
1331
1584
  sections = input.required();
1332
1585
  topLevelControls = input([]);
1333
1586
  customCss = input();
1587
+ config = input();
1588
+ event = output();
1334
1589
  constructor() {
1335
1590
  this.renderer.appendChild(this.ref.nativeElement, this.styleRef);
1336
1591
  this.destroyRef.onDestroy(() => {
@@ -1341,11 +1596,11 @@ class FormRendererComponent {
1341
1596
  });
1342
1597
  }
1343
1598
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: FormRendererComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1344
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: FormRendererComponent, isStandalone: true, selector: "le-form-renderer", inputs: { engine: { classPropertyName: "engine", publicName: "engine", isSignal: true, isRequired: true, transformFunction: null }, sections: { classPropertyName: "sections", publicName: "sections", isSignal: true, isRequired: true, transformFunction: null }, topLevelControls: { classPropertyName: "topLevelControls", publicName: "topLevelControls", isSignal: true, isRequired: false, transformFunction: null }, customCss: { classPropertyName: "customCss", publicName: "customCss", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"le-form-container\">\n @for (section of sections(); track section.id) {\n <section class=\"le-section\">\n <div class=\"le-section-title\">\n @if (section.label) {\n <h3>{{ section.label }}</h3>\n }\n </div>\n\n <div class=\"le-section-controls\">\n @for (control of section.controls; track control) {\n <fe-field [engine]=\"engine()\" [control]=\"control\"></fe-field>\n }\n </div>\n </section>\n }\n\n @if (topLevelControls()?.length) {\n <section class=\"le-top-level-controls\">\n @for (control of topLevelControls(); track control) {\n <fe-field [engine]=\"engine()\" [control]=\"control\"></fe-field>\n }\n </section>\n }\n</div>\n", dependencies: [{ kind: "component", type: FeFieldHost, selector: "fe-field", inputs: ["engine", "control"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1599
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: FormRendererComponent, isStandalone: true, selector: "le-form-renderer", inputs: { engine: { classPropertyName: "engine", publicName: "engine", isSignal: true, isRequired: true, transformFunction: null }, sections: { classPropertyName: "sections", publicName: "sections", isSignal: true, isRequired: true, transformFunction: null }, topLevelControls: { classPropertyName: "topLevelControls", publicName: "topLevelControls", isSignal: true, isRequired: false, transformFunction: null }, customCss: { classPropertyName: "customCss", publicName: "customCss", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { event: "event" }, ngImport: i0, template: "<div class=\"le-form-container\">\n @for (section of sections(); track section.id) {\n <section class=\"le-section\">\n <div class=\"le-toolbar\">\n @if (section.label) {\n <h3>{{ section.label }}</h3>\n }\n\n <span class=\"spacer\"></span>\n\n @if (config()?.hasCloseButton) {\n <button class=\"le-button\" aria-label=\"Close side panel\" (click)=\"event.emit({ type: 'close'})\">Close</button>\n }\n </div>\n\n <div class=\"le-section-controls\">\n @for (control of section.controls; track control) {\n <fe-field [engine]=\"engine()\" [control]=\"control\"></fe-field>\n }\n </div>\n </section>\n }\n\n @if (topLevelControls()?.length) {\n <section class=\"le-top-level-controls\">\n @for (control of topLevelControls(); track control) {\n <fe-field [engine]=\"engine()\" [control]=\"control\"></fe-field>\n }\n </section>\n }\n</div>\n", dependencies: [{ kind: "component", type: FeFieldHost, selector: "fe-field", inputs: ["engine", "control"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1345
1600
  }
1346
1601
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: FormRendererComponent, decorators: [{
1347
1602
  type: Component,
1348
- args: [{ selector: 'le-form-renderer', imports: [FeFieldHost], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"le-form-container\">\n @for (section of sections(); track section.id) {\n <section class=\"le-section\">\n <div class=\"le-section-title\">\n @if (section.label) {\n <h3>{{ section.label }}</h3>\n }\n </div>\n\n <div class=\"le-section-controls\">\n @for (control of section.controls; track control) {\n <fe-field [engine]=\"engine()\" [control]=\"control\"></fe-field>\n }\n </div>\n </section>\n }\n\n @if (topLevelControls()?.length) {\n <section class=\"le-top-level-controls\">\n @for (control of topLevelControls(); track control) {\n <fe-field [engine]=\"engine()\" [control]=\"control\"></fe-field>\n }\n </section>\n }\n</div>\n" }]
1603
+ args: [{ selector: 'le-form-renderer', imports: [FeFieldHost], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"le-form-container\">\n @for (section of sections(); track section.id) {\n <section class=\"le-section\">\n <div class=\"le-toolbar\">\n @if (section.label) {\n <h3>{{ section.label }}</h3>\n }\n\n <span class=\"spacer\"></span>\n\n @if (config()?.hasCloseButton) {\n <button class=\"le-button\" aria-label=\"Close side panel\" (click)=\"event.emit({ type: 'close'})\">Close</button>\n }\n </div>\n\n <div class=\"le-section-controls\">\n @for (control of section.controls; track control) {\n <fe-field [engine]=\"engine()\" [control]=\"control\"></fe-field>\n }\n </div>\n </section>\n }\n\n @if (topLevelControls()?.length) {\n <section class=\"le-top-level-controls\">\n @for (control of topLevelControls(); track control) {\n <fe-field [engine]=\"engine()\" [control]=\"control\"></fe-field>\n }\n </section>\n }\n</div>\n" }]
1349
1604
  }], ctorParameters: () => [] });
1350
1605
 
1351
1606
  const isPlaceholder = (value) => {
@@ -1721,13 +1976,15 @@ class FormViewComponent {
1721
1976
  update_form: (action) => {
1722
1977
  const node = this.mapUpdateFormActionToFormNode(action.control_source);
1723
1978
  if (node) {
1724
- this.dataService.setView(node);
1979
+ this.setView(node);
1725
1980
  }
1726
1981
  return of(null);
1727
1982
  },
1728
1983
  update_table: (action) => {
1729
1984
  const node = this.mapUpdateTableActionToTableNode(action.data_source);
1730
- this.dataService.setView(node);
1985
+ this.event.emit({ type: 'refresh' });
1986
+ this.event.emit({ type: 'close' });
1987
+ this.setView(node);
1731
1988
  return of(null);
1732
1989
  },
1733
1990
  update_value: (action, response) => {
@@ -1763,6 +2020,7 @@ class FormViewComponent {
1763
2020
  };
1764
2021
  node = input.required();
1765
2022
  config = input();
2023
+ event = output();
1766
2024
  isLoading = this._isLoading.asReadonly();
1767
2025
  data = computed(() => {
1768
2026
  const engine = this._engine();
@@ -1817,6 +2075,9 @@ class FormViewComponent {
1817
2075
  this.processActionList(action.actions);
1818
2076
  });
1819
2077
  }
2078
+ setView(node) {
2079
+ this.dataService.setView(node, !!this.config()?.skipLocationChange);
2080
+ }
1820
2081
  processAction(action, response) {
1821
2082
  return this._actionHandlers[action.type](action, response);
1822
2083
  }
@@ -1889,52 +2150,73 @@ class FormViewComponent {
1889
2150
  .subscribe();
1890
2151
  }
1891
2152
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: FormViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1892
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: FormViewComponent, isStandalone: true, selector: "form-view", inputs: { node: { classPropertyName: "node", publicName: "node", isSignal: true, isRequired: true, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null } }, providers: [FormViewAttachmentService], ngImport: i0, template: "<h2>{{ node()?.title }}</h2>\n\n@if (isLoading()) {\n <app-loading-view [rowCount]=\"5\"></app-loading-view>\n} @else {\n @if (data(); as data) {\n <le-form-renderer\n [engine]=\"data.engine\"\n [sections]=\"data.sections\"\n [customCss]=\"data.customCss\"\n [topLevelControls]=\"data.topLevelControls\"\n ></le-form-renderer>\n }\n}\n", dependencies: [{ kind: "component", type: LoadingViewComponent, selector: "app-loading-view", inputs: ["headerHeight", "rowHeight", "rowCount"] }, { kind: "component", type: FormRendererComponent, selector: "le-form-renderer", inputs: ["engine", "sections", "topLevelControls", "customCss"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2153
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: FormViewComponent, isStandalone: true, selector: "form-view", inputs: { node: { classPropertyName: "node", publicName: "node", isSignal: true, isRequired: true, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { event: "event" }, providers: [FormViewAttachmentService], ngImport: i0, template: "<h2>{{ node()?.title }}</h2>\n\n@if (isLoading()) {\n <app-loading-view [rowCount]=\"5\"></app-loading-view>\n} @else {\n @if (data(); as data) {\n <le-form-renderer\n [config]=\"config()\"\n [engine]=\"data.engine\"\n [sections]=\"data.sections\"\n [customCss]=\"data.customCss\"\n [topLevelControls]=\"data.topLevelControls\"\n (event)=\"event.emit($event)\"\n ></le-form-renderer>\n }\n}\n", dependencies: [{ kind: "component", type: LoadingViewComponent, selector: "app-loading-view", inputs: ["headerHeight", "rowHeight", "rowCount"] }, { kind: "component", type: FormRendererComponent, selector: "le-form-renderer", inputs: ["engine", "sections", "topLevelControls", "customCss", "config"], outputs: ["event"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1893
2154
  }
1894
2155
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: FormViewComponent, decorators: [{
1895
2156
  type: Component,
1896
- args: [{ selector: 'form-view', imports: [LoadingViewComponent, FormRendererComponent], changeDetection: ChangeDetectionStrategy.OnPush, providers: [FormViewAttachmentService], template: "<h2>{{ node()?.title }}</h2>\n\n@if (isLoading()) {\n <app-loading-view [rowCount]=\"5\"></app-loading-view>\n} @else {\n @if (data(); as data) {\n <le-form-renderer\n [engine]=\"data.engine\"\n [sections]=\"data.sections\"\n [customCss]=\"data.customCss\"\n [topLevelControls]=\"data.topLevelControls\"\n ></le-form-renderer>\n }\n}\n" }]
2157
+ args: [{ selector: 'form-view', imports: [LoadingViewComponent, FormRendererComponent], changeDetection: ChangeDetectionStrategy.OnPush, providers: [FormViewAttachmentService], template: "<h2>{{ node()?.title }}</h2>\n\n@if (isLoading()) {\n <app-loading-view [rowCount]=\"5\"></app-loading-view>\n} @else {\n @if (data(); as data) {\n <le-form-renderer\n [config]=\"config()\"\n [engine]=\"data.engine\"\n [sections]=\"data.sections\"\n [customCss]=\"data.customCss\"\n [topLevelControls]=\"data.topLevelControls\"\n (event)=\"event.emit($event)\"\n ></le-form-renderer>\n }\n}\n" }]
1897
2158
  }], ctorParameters: () => [] });
1898
2159
 
1899
2160
  class SectionComponent {
1900
2161
  node = input.required();
1901
2162
  config = input();
2163
+ event = output();
1902
2164
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SectionComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1903
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: SectionComponent, isStandalone: true, selector: "section-view", inputs: { node: { classPropertyName: "node", publicName: "node", isSignal: true, isRequired: true, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@for (child of node().children; track child.id) {\n <le-node [node]=\"child\" [config]=\"config()\"></le-node>\n}\n", dependencies: [{ kind: "component", type: i0.forwardRef(() => NodeComponent), selector: "le-node", inputs: ["node", "config"] }] });
2165
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: SectionComponent, isStandalone: true, selector: "section-view", inputs: { node: { classPropertyName: "node", publicName: "node", isSignal: true, isRequired: true, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { event: "event" }, ngImport: i0, template: "@for (child of node().children; track child.id) {\n <le-node [node]=\"child\" [config]=\"config()\" (event)=\"event.emit($event)\"></le-node>\n}\n", dependencies: [{ kind: "component", type: i0.forwardRef(() => NodeComponent), selector: "le-node", inputs: ["node", "config"], outputs: ["event"] }] });
1904
2166
  }
1905
2167
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SectionComponent, decorators: [{
1906
2168
  type: Component,
1907
- args: [{ selector: 'section-view', imports: [forwardRef(() => NodeComponent)], template: "@for (child of node().children; track child.id) {\n <le-node [node]=\"child\" [config]=\"config()\"></le-node>\n}\n" }]
2169
+ args: [{ selector: 'section-view', imports: [forwardRef(() => NodeComponent)], template: "@for (child of node().children; track child.id) {\n <le-node [node]=\"child\" [config]=\"config()\" (event)=\"event.emit($event)\"></le-node>\n}\n" }]
1908
2170
  }] });
1909
2171
 
1910
2172
  class GridColViewComponent {
1911
2173
  node = input.required();
1912
2174
  config = input();
2175
+ event = output();
1913
2176
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: GridColViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1914
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: GridColViewComponent, isStandalone: true, selector: "grid-col-view", inputs: { node: { classPropertyName: "node", publicName: "node", isSignal: true, isRequired: true, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@for (child of node().children; track child.id) {\n <le-node [node]=\"child\" [config]=\"config()\"></le-node>\n}\n", dependencies: [{ kind: "component", type: i0.forwardRef(() => NodeComponent), selector: "le-node", inputs: ["node", "config"] }] });
2177
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: GridColViewComponent, isStandalone: true, selector: "grid-col-view", inputs: { node: { classPropertyName: "node", publicName: "node", isSignal: true, isRequired: true, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { event: "event" }, ngImport: i0, template: "@for (child of node().children; track child.id) {\n <le-node [node]=\"child\" [config]=\"config()\" (event)=\"event.emit($event)\"></le-node>\n}\n", dependencies: [{ kind: "component", type: i0.forwardRef(() => NodeComponent), selector: "le-node", inputs: ["node", "config"], outputs: ["event"] }] });
1915
2178
  }
1916
2179
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: GridColViewComponent, decorators: [{
1917
2180
  type: Component,
1918
- args: [{ selector: 'grid-col-view', imports: [forwardRef(() => NodeComponent)], template: "@for (child of node().children; track child.id) {\n <le-node [node]=\"child\" [config]=\"config()\"></le-node>\n}\n" }]
2181
+ args: [{ selector: 'grid-col-view', imports: [forwardRef(() => NodeComponent)], template: "@for (child of node().children; track child.id) {\n <le-node [node]=\"child\" [config]=\"config()\" (event)=\"event.emit($event)\"></le-node>\n}\n" }]
1919
2182
  }] });
1920
2183
 
2184
+ const NODE_COMPONENTS = {
2185
+ section: SectionComponent,
2186
+ grid: GridComponent,
2187
+ grid_col: GridColViewComponent,
2188
+ form: FormViewComponent,
2189
+ table: TableViewComponent,
2190
+ chart: ChartViewComponent,
2191
+ };
1921
2192
  class NodeComponent {
1922
2193
  node = input.required();
1923
2194
  config = input();
2195
+ event = output();
2196
+ componentPortal;
2197
+ constructor() {
2198
+ effect(() => {
2199
+ this.componentPortal = new ComponentPortal(NODE_COMPONENTS[this.node().type]);
2200
+ });
2201
+ }
2202
+ onPortalAttached(ref) {
2203
+ const componentRef = ref;
2204
+ componentRef.setInput('node', this.node());
2205
+ componentRef.setInput('config', this.config());
2206
+ const sub = componentRef.instance.event.subscribe((event) => {
2207
+ this.event.emit(event);
2208
+ });
2209
+ componentRef.onDestroy(() => {
2210
+ sub.unsubscribe();
2211
+ });
2212
+ }
1924
2213
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: NodeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1925
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: NodeComponent, isStandalone: true, selector: "le-node", inputs: { node: { classPropertyName: "node", publicName: "node", isSignal: true, isRequired: true, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if (node(); as node) {\n @switch (node.type) {\n @case ('section') {\n <section-view [node]=\"node\" [config]=\"config()\"></section-view>\n }\n @case ('grid') {\n <grid-view [node]=\"node\" [config]=\"config()\"></grid-view>\n }\n @case ('grid_col') {\n <grid-col-view [node]=\"node\" [config]=\"config()\"></grid-col-view>\n }\n @case ('table') {\n <table-view [node]=\"node\" [config]=\"config()\"></table-view>\n }\n @case ('chart') {\n <chart-view [node]=\"node\" [config]=\"config()\"></chart-view>\n }\n @case ('form') {\n <form-view [node]=\"node\" [config]=\"config()\"></form-view>\n }\n }\n}\n", dependencies: [{ kind: "component", type: i0.forwardRef(() => ChartViewComponent), selector: "chart-view", inputs: ["node", "config"] }, { kind: "component", type: i0.forwardRef(() => GridComponent), selector: "grid-view", inputs: ["node", "config"] }, { kind: "component", type: i0.forwardRef(() => TableViewComponent), selector: "table-view", inputs: ["node", "config"] }, { kind: "component", type: i0.forwardRef(() => FormViewComponent), selector: "form-view", inputs: ["node", "config"] }, { kind: "component", type: i0.forwardRef(() => GridColViewComponent), selector: "grid-col-view", inputs: ["node", "config"] }, { kind: "component", type: i0.forwardRef(() => SectionComponent), selector: "section-view", inputs: ["node", "config"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2214
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.2.21", type: NodeComponent, isStandalone: true, selector: "le-node", inputs: { node: { classPropertyName: "node", publicName: "node", isSignal: true, isRequired: true, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { event: "event" }, ngImport: i0, template: "<ng-template\n [cdkPortalOutlet]=\"componentPortal\"\n (attached)=\"onPortalAttached($event)\">\n</ng-template>\n\n<!--@if (node(); as node) {-->\n<!-- @switch (node.type) {-->\n<!-- @case ('section') {-->\n<!-- <section-view [node]=\"node\" [config]=\"config()\" (event)=\"event.emit($event)\"></section-view>-->\n<!-- }-->\n<!-- @case ('grid') {-->\n<!-- <grid-view [node]=\"node\" [config]=\"config()\" (event)=\"event.emit($event)\"></grid-view>-->\n<!-- }-->\n<!-- @case ('grid_col') {-->\n<!-- <grid-col-view [node]=\"node\" [config]=\"config()\" (event)=\"event.emit($event)\"></grid-col-view>-->\n<!-- }-->\n<!-- @case ('table') {-->\n<!-- <table-view [node]=\"node\" [config]=\"config()\" (event)=\"event.emit($event)\"></table-view>-->\n<!-- }-->\n<!-- @case ('chart') {-->\n<!-- <chart-view [node]=\"node\" [config]=\"config()\" (event)=\"event.emit($event)\"></chart-view>-->\n<!-- }-->\n<!-- @case ('form') {-->\n<!-- <form-view [node]=\"node\" [config]=\"config()\" (event)=\"event.emit($event)\"></form-view>-->\n<!-- }-->\n<!-- }-->\n<!--}-->\n", dependencies: [{ kind: "directive", type: CdkPortalOutlet, selector: "[cdkPortalOutlet]", inputs: ["cdkPortalOutlet"], outputs: ["attached"], exportAs: ["cdkPortalOutlet"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1926
2215
  }
1927
2216
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: NodeComponent, decorators: [{
1928
2217
  type: Component,
1929
- args: [{ selector: 'le-node', imports: [
1930
- ChartViewComponent,
1931
- GridComponent,
1932
- TableViewComponent,
1933
- FormViewComponent,
1934
- GridColViewComponent,
1935
- forwardRef(() => SectionComponent),
1936
- ], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (node(); as node) {\n @switch (node.type) {\n @case ('section') {\n <section-view [node]=\"node\" [config]=\"config()\"></section-view>\n }\n @case ('grid') {\n <grid-view [node]=\"node\" [config]=\"config()\"></grid-view>\n }\n @case ('grid_col') {\n <grid-col-view [node]=\"node\" [config]=\"config()\"></grid-col-view>\n }\n @case ('table') {\n <table-view [node]=\"node\" [config]=\"config()\"></table-view>\n }\n @case ('chart') {\n <chart-view [node]=\"node\" [config]=\"config()\"></chart-view>\n }\n @case ('form') {\n <form-view [node]=\"node\" [config]=\"config()\"></form-view>\n }\n }\n}\n" }]
1937
- }] });
2218
+ args: [{ selector: 'le-node', imports: [CdkPortalOutlet], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-template\n [cdkPortalOutlet]=\"componentPortal\"\n (attached)=\"onPortalAttached($event)\">\n</ng-template>\n\n<!--@if (node(); as node) {-->\n<!-- @switch (node.type) {-->\n<!-- @case ('section') {-->\n<!-- <section-view [node]=\"node\" [config]=\"config()\" (event)=\"event.emit($event)\"></section-view>-->\n<!-- }-->\n<!-- @case ('grid') {-->\n<!-- <grid-view [node]=\"node\" [config]=\"config()\" (event)=\"event.emit($event)\"></grid-view>-->\n<!-- }-->\n<!-- @case ('grid_col') {-->\n<!-- <grid-col-view [node]=\"node\" [config]=\"config()\" (event)=\"event.emit($event)\"></grid-col-view>-->\n<!-- }-->\n<!-- @case ('table') {-->\n<!-- <table-view [node]=\"node\" [config]=\"config()\" (event)=\"event.emit($event)\"></table-view>-->\n<!-- }-->\n<!-- @case ('chart') {-->\n<!-- <chart-view [node]=\"node\" [config]=\"config()\" (event)=\"event.emit($event)\"></chart-view>-->\n<!-- }-->\n<!-- @case ('form') {-->\n<!-- <form-view [node]=\"node\" [config]=\"config()\" (event)=\"event.emit($event)\"></form-view>-->\n<!-- }-->\n<!-- }-->\n<!--}-->\n" }]
2219
+ }], ctorParameters: () => [] });
1938
2220
 
1939
2221
  class FiltersComponent {
1940
2222
  filtersService = inject(LEFiltersService);
@@ -2138,6 +2420,7 @@ class LeContainerComponent {
2138
2420
  constructor() {
2139
2421
  this.listenAuthState();
2140
2422
  this.listenPageInit();
2423
+ this.dataService.registerEffects();
2141
2424
  }
2142
2425
  onSelectionChange(view) {
2143
2426
  this.dataService.setView(view);
@@ -2167,7 +2450,7 @@ class LeContainerComponent {
2167
2450
  });
2168
2451
  }
2169
2452
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: LeContainerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2170
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: LeContainerComponent, isStandalone: true, selector: "le-container", providers: [LEDataService, LEApiService, LEFiltersService, LeNavigationService], viewQueries: [{ propertyName: "sidebar", first: true, predicate: SidebarComponent, descendants: true, isSignal: true }], ngImport: i0, template: "@if (data(); as data) {\n <le-sidebar\n [config]=\"data.config\"\n [view]=\"data.view\"\n (selectionChange)=\"onSelectionChange($event)\"\n >\n <le-filters>\n <le-node [node]=\"data.view\"></le-node>\n </le-filters>\n </le-sidebar>\n}\n", dependencies: [{ kind: "component", type: SidebarComponent, selector: "le-sidebar", inputs: ["config", "view"], outputs: ["selectionChange"] }, { kind: "component", type: NodeComponent, selector: "le-node", inputs: ["node", "config"] }, { kind: "component", type: FiltersComponent, selector: "le-filters" }] });
2453
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: LeContainerComponent, isStandalone: true, selector: "le-container", providers: [LEDataService, LEApiService, LEFiltersService, LeNavigationService], viewQueries: [{ propertyName: "sidebar", first: true, predicate: SidebarComponent, descendants: true, isSignal: true }], ngImport: i0, template: "@if (data(); as data) {\n <le-sidebar\n [config]=\"data.config\"\n [view]=\"data.view\"\n (selectionChange)=\"onSelectionChange($event)\"\n >\n <le-filters>\n <le-node [node]=\"data.view\"></le-node>\n </le-filters>\n </le-sidebar>\n}\n", dependencies: [{ kind: "component", type: SidebarComponent, selector: "le-sidebar", inputs: ["config", "view"], outputs: ["selectionChange"] }, { kind: "component", type: NodeComponent, selector: "le-node", inputs: ["node", "config"], outputs: ["event"] }, { kind: "component", type: FiltersComponent, selector: "le-filters" }] });
2171
2454
  }
2172
2455
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: LeContainerComponent, decorators: [{
2173
2456
  type: Component,