@planeasyinc/le-angular 0.0.12 → 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 (28) hide show
  1. package/dist/fesm2022/planeasyinc-le-angular.mjs +141 -89
  2. package/dist/fesm2022/planeasyinc-le-angular.mjs.map +1 -1
  3. package/dist/lib/components/node/node.component.d.ts +4 -1
  4. package/dist/lib/components/side-panel/side-panel.component.d.ts +14 -3
  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-side-panel.service.d.ts +5 -6
  10. package/dist/lib/types/le-table.d.ts +14 -0
  11. package/dist/lib/types/le-tabs.d.ts +27 -0
  12. package/dist/lib/types/le-tree.d.ts +5 -0
  13. package/dist/lib/views/block-view/block-view.component.d.ts +13 -0
  14. package/dist/lib/views/chart-view/chart-view.component.d.ts +4 -1
  15. package/dist/lib/views/form-view/form-renderer.component.d.ts +4 -1
  16. package/dist/lib/views/form-view/form-view.component.d.ts +4 -1
  17. package/dist/lib/views/gird-col-view/grid-col-view.component.d.ts +4 -1
  18. package/dist/lib/views/gird-view/grid-view.component.d.ts +4 -1
  19. package/dist/lib/views/section-view/section-view.component.d.ts +4 -1
  20. package/dist/lib/views/table-view/table-view-cell.directive.d.ts +1 -1
  21. package/dist/lib/views/table-view/table-view.component.d.ts +6 -13
  22. package/dist/lib/views/tree-view/tree-view.component.d.ts +12 -0
  23. package/dist/lib/views/tree-view/tree-view.utils.d.ts +2 -0
  24. package/dist/styles/styles.scss +68 -0
  25. package/package.json +2 -2
  26. package/dist/lib/components/dialog/dialog.component.d.ts +0 -7
  27. package/dist/lib/services/le-dialog.service.d.ts +0 -10
  28. package/dist/lib/types/le-dialog.d.ts +0 -12
@@ -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
11
  import { ComponentPortal, CdkPortalOutlet, TemplatePortal } from '@angular/cdk/portal';
12
12
  import { DataSource, CdkTable, CdkColumnDef, CdkHeaderCell, CdkHeaderCellDef, CdkCell, CdkCellDef, CdkHeaderRowDef, CdkHeaderRow, CdkRow, CdkRowDef } from '@angular/cdk/table';
13
- import { DIALOG_DATA, Dialog, DialogModule } from '@angular/cdk/dialog';
13
+ import { DialogModule } from '@angular/cdk/dialog';
14
14
  import { CdkMenuTrigger, CdkMenu, CdkMenuItem } from '@angular/cdk/menu';
15
15
  import { A11yModule } from '@angular/cdk/a11y';
16
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';
17
19
  import { adaptOld } from '@planeasyinc/fe-adapters-old';
18
20
  import { adaptSections } from '@planeasyinc/fe-adapters-sections';
19
21
  import { createEngine } from '@planeasyinc/fe-core';
20
22
  import { FeFieldHost } from '@planeasyinc/fe-angular';
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
 
@@ -214,8 +215,8 @@ class LEDataService {
214
215
  }
215
216
  setView(node, skipLocationChange) {
216
217
  this._view.set(node);
217
- window.scrollTo({ top: 0, behavior: 'smooth' });
218
218
  if (!skipLocationChange) {
219
+ window.scrollTo({ top: 0, behavior: 'smooth' });
219
220
  this.leNavigationService.navigate(node);
220
221
  }
221
222
  }
@@ -398,14 +399,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImpo
398
399
  }]
399
400
  }] });
400
401
 
401
- const history = {
402
- name: 'history',
403
- viewBox: '0 -960 960 960',
404
- content: [
405
- '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',
406
- ],
407
- };
408
-
409
402
  const close = {
410
403
  name: 'close',
411
404
  viewBox: '0 -960 960 960',
@@ -438,12 +431,20 @@ const chevron = {
438
431
  ]
439
432
  };
440
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
+
441
442
  const ICONS_MAP = {
442
443
  chevron: chevron,
443
444
  'arrow-down': arrowDown,
444
445
  sort: sort,
445
446
  close: close,
446
- history: history,
447
+ info: info
447
448
  };
448
449
 
449
450
  class LeIconComponent {
@@ -1000,92 +1001,109 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImpo
1000
1001
  }]
1001
1002
  }], ctorParameters: () => [] });
1002
1003
 
1003
- class DialogComponent {
1004
- data = inject(DIALOG_DATA);
1005
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: DialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1006
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: DialogComponent, isStandalone: true, selector: "ng-component", ngImport: i0, template: `
1007
- @if (data.node) {
1008
- <le-node [node]="data.node" [config]="data.config"></le-node>
1009
- }
1010
- `, isInline: true, dependencies: [{ kind: "component", type: i0.forwardRef(() => NodeComponent), selector: "le-node", inputs: ["node", "config"], outputs: ["event"] }] });
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 });
1011
1036
  }
1012
- 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: [{
1013
1038
  type: Component,
1014
- args: [{
1015
- template: `
1016
- @if (data.node) {
1017
- <le-node [node]="data.node" [config]="data.config"></le-node>
1018
- }
1019
- `,
1020
- imports: [forwardRef(() => NodeComponent)],
1021
- }]
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" }]
1022
1048
  }] });
1023
1049
 
1024
- class LeDialogService {
1025
- dialog = inject(Dialog);
1026
- open(data, config = {}) {
1027
- const dialogRef = this.dialog.open(DialogComponent, {
1028
- maxWidth: '80vw',
1029
- maxHeight: '80vh',
1030
- minWidth: '40vw',
1031
- panelClass: 'le-dialog-container',
1032
- data,
1033
- injector: config?.injector,
1034
- });
1035
- return dialogRef.closed;
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' });
1036
1057
  }
1037
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: LeDialogService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1038
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: LeDialogService, providedIn: 'root' });
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"] }] });
1039
1060
  }
1040
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: LeDialogService, decorators: [{
1041
- type: Injectable,
1042
- args: [{
1043
- providedIn: 'root',
1044
- }]
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" }]
1045
1064
  }] });
1046
1065
 
1047
1066
  class SidePanelComponent {
1048
1067
  dataService = inject(LEDataService);
1068
+ _selectedTab = signal(0);
1049
1069
  data = input.required();
1050
1070
  config = input();
1051
1071
  event = output();
1052
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
+ });
1053
1081
  constructor() {
1054
1082
  effect(() => {
1055
1083
  const data = this.data();
1056
1084
  untracked(() => {
1057
- if (!data.node)
1058
- return;
1059
- this.dataService.setView(data.node, true);
1085
+ if (data.node) {
1086
+ this.dataService.setView(data.node, true);
1087
+ }
1060
1088
  });
1061
1089
  });
1062
1090
  }
1063
1091
  onEvent(event) {
1064
1092
  this.event.emit(event);
1065
1093
  }
1066
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SidePanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1067
- 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], ngImport: i0, template: `
1068
- @if (node(); as node) {
1069
- <le-node [node]="node" [config]="data()?.config" (event)="onEvent($event)"></le-node>
1094
+ onTabClick(index) {
1095
+ this._selectedTab.set(index);
1070
1096
  }
1071
- `, isInline: true, dependencies: [{ kind: "component", type: i0.forwardRef(() => NodeComponent), selector: "le-node", inputs: ["node", "config"], outputs: ["event"] }] });
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"] }] });
1072
1099
  }
1073
1100
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SidePanelComponent, decorators: [{
1074
1101
  type: Component,
1075
- args: [{
1076
- template: `
1077
- @if (node(); as node) {
1078
- <le-node [node]="node" [config]="data()?.config" (event)="onEvent($event)"></le-node>
1079
- }
1080
- `,
1081
- host: {
1102
+ args: [{ host: {
1082
1103
  '[style.width]': '"100%"',
1083
1104
  '[style.overflow]': '"auto"',
1084
1105
  '[style.padding]': '"0 16px"',
1085
- },
1086
- imports: [forwardRef(() => NodeComponent)],
1087
- providers: [LEDataService],
1088
- }]
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" }]
1089
1107
  }], ctorParameters: () => [] });
1090
1108
 
1091
1109
  const positionMap = {
@@ -1116,14 +1134,14 @@ class LeSidePanelService {
1116
1134
  next: () => {
1117
1135
  this.overlayRef?.addPanelClass(this.getClosedClass(config));
1118
1136
  this.delayed(() => this.hide());
1119
- }
1137
+ },
1120
1138
  });
1121
1139
  const componentRef = this.overlayRef.attach(new ComponentPortal(SidePanelComponent, null, config.injector));
1122
1140
  componentRef.setInput('data', data);
1123
1141
  this.delayed(() => this.overlayRef?.removePanelClass(this.getClosedClass(config)));
1124
- const sub = componentRef.instance.event.subscribe((value) => {
1125
- this.output.next(value);
1126
- if (value === 'close') {
1142
+ const sub = componentRef.instance.event.subscribe((event) => {
1143
+ this.output.next(event);
1144
+ if (event.type === 'close') {
1127
1145
  this.overlayRef?.addPanelClass(this.getClosedClass(config));
1128
1146
  this.delayed(() => this.hide());
1129
1147
  }
@@ -1146,6 +1164,17 @@ class LeSidePanelService {
1146
1164
  if (config.height) {
1147
1165
  return config.height;
1148
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
+ }
1149
1178
  return '100vh';
1150
1179
  }
1151
1180
  getWidth(config) {
@@ -1191,7 +1220,6 @@ class TableViewComponent {
1191
1220
  apiService = inject(LEApiService);
1192
1221
  dataService = inject(LEDataService);
1193
1222
  filtersService = inject(LEFiltersService);
1194
- dialogService = inject(LeDialogService);
1195
1223
  sidePanelService = inject(LeSidePanelService);
1196
1224
  injector = inject(Injector);
1197
1225
  node = input.required();
@@ -1215,8 +1243,8 @@ class TableViewComponent {
1215
1243
  const firstRow = this.data().getValueByIndex(0);
1216
1244
  const columnKeys = this.columns().map((column) => column.key);
1217
1245
  const hasVersion = !!(firstRow && firstRow._metadata && firstRow._metadata.object_version);
1218
- if (!this.config()?.hideMetadata && hasVersion) {
1219
- result.push('versions');
1246
+ if (!this.config()?.hideInfo) {
1247
+ result.push('info');
1220
1248
  }
1221
1249
  result.push(...columnKeys);
1222
1250
  if (hasVersion) {
@@ -1279,13 +1307,12 @@ class TableViewComponent {
1279
1307
  const actions = this.node().actions?.onRowClick ?? [];
1280
1308
  actions.forEach((action) => this.processRowClickAction(action, row));
1281
1309
  }
1282
- onRowVersionClick(event, row) {
1310
+ onRowInfoClick(event, row) {
1283
1311
  event.preventDefault();
1284
1312
  event.stopImmediatePropagation();
1285
1313
  const node = {
1286
1314
  id: row._metadata.lakehouse_address,
1287
1315
  type: 'table',
1288
- title: 'Versions',
1289
1316
  dataSource: {
1290
1317
  kind: 'object',
1291
1318
  entity: row._metadata.lakehouse_address,
@@ -1297,9 +1324,30 @@ class TableViewComponent {
1297
1324
  },
1298
1325
  },
1299
1326
  };
1300
- this.dialogService
1301
- .open({ node, config: { hideFilters: true, hideMetadata: true, showCloseButton: true } }, { injector: this.injector })
1302
- .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
+ });
1303
1351
  }
1304
1352
  onCellClicked(data) {
1305
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}`;
@@ -1319,12 +1367,16 @@ class TableViewComponent {
1319
1367
  node.controlSource.params = this.interpolateRowValues(node.controlSource.params, row);
1320
1368
  }
1321
1369
  this.sidePanelService
1322
- .show({ node, config: { hasCloseButton: true, skipLocationChange: true } }, {
1370
+ .show({
1371
+ node,
1372
+ tabs: [],
1373
+ config: { hasCloseButton: true, skipLocationChange: true },
1374
+ }, {
1323
1375
  position: 'right',
1324
1376
  injector: this.injector,
1325
1377
  })
1326
- .subscribe((value) => {
1327
- if (value === 'refresh') {
1378
+ .subscribe((event) => {
1379
+ if (event.type === 'refresh') {
1328
1380
  this.forceFetch();
1329
1381
  }
1330
1382
  });
@@ -1482,7 +1534,7 @@ class TableViewComponent {
1482
1534
  }
1483
1535
  }
1484
1536
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: TableViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1485
- 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: "<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 });
1486
1538
  }
1487
1539
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: TableViewComponent, decorators: [{
1488
1540
  type: Component,
@@ -1504,7 +1556,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImpo
1504
1556
  LeIconComponent,
1505
1557
  DialogModule,
1506
1558
  DatePipe,
1507
- ], 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" }]
1508
1560
  }], ctorParameters: () => [] });
1509
1561
 
1510
1562
  const isSectionsSchema = (raw) => {
@@ -1544,11 +1596,11 @@ class FormRendererComponent {
1544
1596
  });
1545
1597
  }
1546
1598
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: FormRendererComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1547
- 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('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 });
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 });
1548
1600
  }
1549
1601
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: FormRendererComponent, decorators: [{
1550
1602
  type: Component,
1551
- 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('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" }]
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" }]
1552
1604
  }], ctorParameters: () => [] });
1553
1605
 
1554
1606
  const isPlaceholder = (value) => {
@@ -1930,8 +1982,8 @@ class FormViewComponent {
1930
1982
  },
1931
1983
  update_table: (action) => {
1932
1984
  const node = this.mapUpdateTableActionToTableNode(action.data_source);
1933
- this.event.emit('refresh');
1934
- this.event.emit('close');
1985
+ this.event.emit({ type: 'refresh' });
1986
+ this.event.emit({ type: 'close' });
1935
1987
  this.setView(node);
1936
1988
  return of(null);
1937
1989
  },