@planeasyinc/le-angular 0.0.11 → 0.0.12

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.
@@ -8,16 +8,16 @@ 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
13
  import { DIALOG_DATA, Dialog, 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';
15
17
  import { adaptOld } from '@planeasyinc/fe-adapters-old';
16
18
  import { adaptSections } from '@planeasyinc/fe-adapters-sections';
17
19
  import { createEngine } from '@planeasyinc/fe-core';
18
20
  import { FeFieldHost } from '@planeasyinc/fe-angular';
19
- import { Overlay } from '@angular/cdk/overlay';
20
- import { ComponentPortal, TemplatePortal } from '@angular/cdk/portal';
21
21
  import { SelectionModel } from '@angular/cdk/collections';
22
22
  import * as i1 from '@angular/forms';
23
23
  import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
@@ -199,22 +199,25 @@ class LEDataService {
199
199
  parentPath = this._parentPath.asReadonly();
200
200
  config = this._config.asReadonly();
201
201
  customCss = this._customCss.asReadonly();
202
- constructor() {
202
+ registerEffects() {
203
203
  effect(() => {
204
204
  const node = this.leNavigationService.node();
205
205
  if (!node)
206
206
  return;
207
207
  untracked(() => {
208
208
  const view = this.view();
209
- if (node.id === view.id)
209
+ if (node.id === view?.id)
210
210
  return;
211
211
  this._view.set(node);
212
212
  });
213
213
  });
214
214
  }
215
- setView(node) {
215
+ setView(node, skipLocationChange) {
216
216
  this._view.set(node);
217
- this.leNavigationService.navigate(node);
217
+ window.scrollTo({ top: 0, behavior: 'smooth' });
218
+ if (!skipLocationChange) {
219
+ this.leNavigationService.navigate(node);
220
+ }
218
221
  }
219
222
  requestConfig(force) {
220
223
  if (this._config() && !force) {
@@ -249,6 +252,8 @@ class LEDataService {
249
252
  }
250
253
  }
251
254
  getNodeById(id, node = this._config()) {
255
+ if (!node)
256
+ return null;
252
257
  if (node.id === id) {
253
258
  return node;
254
259
  }
@@ -283,7 +288,7 @@ class LEDataService {
283
288
  }
284
289
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: LEDataService, decorators: [{
285
290
  type: Injectable
286
- }], ctorParameters: () => [] });
291
+ }] });
287
292
 
288
293
  class LEFiltersService {
289
294
  _shown = signal(false);
@@ -569,8 +574,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImpo
569
574
  class ChartViewComponent {
570
575
  node = input.required();
571
576
  config = input();
577
+ event = output();
572
578
  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" });
579
+ 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
580
  }
575
581
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: ChartViewComponent, decorators: [{
576
582
  type: Component,
@@ -580,15 +586,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImpo
580
586
  class GridComponent {
581
587
  node = input.required();
582
588
  config = input();
589
+ event = output();
583
590
  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"] }] });
591
+ 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
592
  }
586
593
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: GridComponent, decorators: [{
587
594
  type: Component,
588
595
  args: [{ selector: 'grid-view', imports: [forwardRef(() => NodeComponent)], host: {
589
596
  '[class.le-gird-view]': 'true',
590
597
  '[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" }]
598
+ }, 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
599
  }] });
593
600
 
594
601
  class TableDataSource extends DataSource {
@@ -996,11 +1003,22 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImpo
996
1003
  class DialogComponent {
997
1004
  data = inject(DIALOG_DATA);
998
1005
  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"] }] });
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"] }] });
1000
1011
  }
1001
1012
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: DialogComponent, decorators: [{
1002
1013
  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" }]
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
+ }]
1004
1022
  }] });
1005
1023
 
1006
1024
  class LeDialogService {
@@ -1026,14 +1044,159 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImpo
1026
1044
  }]
1027
1045
  }] });
1028
1046
 
1047
+ class SidePanelComponent {
1048
+ dataService = inject(LEDataService);
1049
+ data = input.required();
1050
+ config = input();
1051
+ event = output();
1052
+ node = this.dataService.view;
1053
+ constructor() {
1054
+ effect(() => {
1055
+ const data = this.data();
1056
+ untracked(() => {
1057
+ if (!data.node)
1058
+ return;
1059
+ this.dataService.setView(data.node, true);
1060
+ });
1061
+ });
1062
+ }
1063
+ onEvent(event) {
1064
+ this.event.emit(event);
1065
+ }
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>
1070
+ }
1071
+ `, isInline: true, dependencies: [{ kind: "component", type: i0.forwardRef(() => NodeComponent), selector: "le-node", inputs: ["node", "config"], outputs: ["event"] }] });
1072
+ }
1073
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SidePanelComponent, decorators: [{
1074
+ 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: {
1082
+ '[style.width]': '"100%"',
1083
+ '[style.overflow]': '"auto"',
1084
+ '[style.padding]': '"0 16px"',
1085
+ },
1086
+ imports: [forwardRef(() => NodeComponent)],
1087
+ providers: [LEDataService],
1088
+ }]
1089
+ }], ctorParameters: () => [] });
1090
+
1091
+ const positionMap = {
1092
+ right: (position) => position.right().top('0'),
1093
+ left: (position) => position.left().top('0'),
1094
+ top: (position) => position.top('0'),
1095
+ bottom: (position) => position.bottom('0'),
1096
+ };
1097
+ class LeSidePanelService {
1098
+ overlay = inject(Overlay);
1099
+ breakpointObserver = inject(BreakpointObserver);
1100
+ overlayRef;
1101
+ output = new Subject();
1102
+ show(data, config) {
1103
+ if (this.overlayRef)
1104
+ this.hide();
1105
+ const destroy$ = new Subject();
1106
+ this.overlayRef = this.overlay.create({
1107
+ width: this.getWidth(config),
1108
+ height: this.getHeight(config),
1109
+ panelClass: 'le-side-panel',
1110
+ hasBackdrop: config.hasBackdrop ?? true,
1111
+ positionStrategy: this.getPositionStrategy(config),
1112
+ scrollStrategy: this.overlay.scrollStrategies.reposition(),
1113
+ });
1114
+ this.overlayRef.addPanelClass(this.getClosedClass(config));
1115
+ this.overlayRef?.outsidePointerEvents().subscribe({
1116
+ next: () => {
1117
+ this.overlayRef?.addPanelClass(this.getClosedClass(config));
1118
+ this.delayed(() => this.hide());
1119
+ }
1120
+ });
1121
+ const componentRef = this.overlayRef.attach(new ComponentPortal(SidePanelComponent, null, config.injector));
1122
+ componentRef.setInput('data', data);
1123
+ 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') {
1127
+ this.overlayRef?.addPanelClass(this.getClosedClass(config));
1128
+ this.delayed(() => this.hide());
1129
+ }
1130
+ });
1131
+ componentRef.onDestroy(() => {
1132
+ sub.unsubscribe();
1133
+ destroy$.next();
1134
+ destroy$.complete();
1135
+ });
1136
+ return this.output.pipe(takeUntil(destroy$));
1137
+ }
1138
+ hide() {
1139
+ this.overlayRef?.dispose();
1140
+ this.overlayRef = undefined;
1141
+ }
1142
+ delayed(fn) {
1143
+ setTimeout(() => fn(), 300);
1144
+ }
1145
+ getHeight(config) {
1146
+ if (config.height) {
1147
+ return config.height;
1148
+ }
1149
+ return '100vh';
1150
+ }
1151
+ getWidth(config) {
1152
+ if (config.width) {
1153
+ return config.width;
1154
+ }
1155
+ if (config.position === 'left' || config.position === 'right') {
1156
+ if (this.breakpointObserver.isMatched(Breakpoints.XSmall)) {
1157
+ return '80vw';
1158
+ }
1159
+ else if (this.breakpointObserver.isMatched(Breakpoints.Small)) {
1160
+ return '60vw';
1161
+ }
1162
+ else {
1163
+ return '40vw';
1164
+ }
1165
+ }
1166
+ else {
1167
+ return '100vw';
1168
+ }
1169
+ }
1170
+ getClosedClass(config) {
1171
+ return `le-side-panel--${config.position}`;
1172
+ }
1173
+ getPositionStrategy({ position }) {
1174
+ let positionStrategy = this.overlay.position().global();
1175
+ if (positionMap[position]) {
1176
+ return positionMap[position](positionStrategy);
1177
+ }
1178
+ return positionStrategy;
1179
+ }
1180
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: LeSidePanelService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1181
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: LeSidePanelService, providedIn: 'root' });
1182
+ }
1183
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: LeSidePanelService, decorators: [{
1184
+ type: Injectable,
1185
+ args: [{
1186
+ providedIn: 'root',
1187
+ }]
1188
+ }] });
1189
+
1029
1190
  class TableViewComponent {
1030
1191
  apiService = inject(LEApiService);
1031
1192
  dataService = inject(LEDataService);
1032
1193
  filtersService = inject(LEFiltersService);
1033
1194
  dialogService = inject(LeDialogService);
1195
+ sidePanelService = inject(LeSidePanelService);
1034
1196
  injector = inject(Injector);
1035
1197
  node = input.required();
1036
1198
  config = input();
1199
+ event = output();
1037
1200
  _columns = signal([]);
1038
1201
  _data = signal(new TableDataSource());
1039
1202
  _total = signal(0);
@@ -1114,7 +1277,7 @@ class TableViewComponent {
1114
1277
  }
1115
1278
  onRowClick(row) {
1116
1279
  const actions = this.node().actions?.onRowClick ?? [];
1117
- actions.forEach((action) => this.processTableAction(action, row));
1280
+ actions.forEach((action) => this.processRowClickAction(action, row));
1118
1281
  }
1119
1282
  onRowVersionClick(event, row) {
1120
1283
  event.preventDefault();
@@ -1140,7 +1303,7 @@ class TableViewComponent {
1140
1303
  }
1141
1304
  onCellClicked(data) {
1142
1305
  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({
1306
+ this.setView({
1144
1307
  id: path,
1145
1308
  type: 'form',
1146
1309
  controlSource: {
@@ -1149,22 +1312,41 @@ class TableViewComponent {
1149
1312
  },
1150
1313
  });
1151
1314
  }
1152
- processTableAction(action, row) {
1315
+ processRowClickAction(action, row) {
1316
+ const { type, node } = action;
1317
+ if (type === 'open_sidebar' && 'controlSource' in node) {
1318
+ if (node.controlSource?.params) {
1319
+ node.controlSource.params = this.interpolateRowValues(node.controlSource.params, row);
1320
+ }
1321
+ this.sidePanelService
1322
+ .show({ node, config: { hasCloseButton: true, skipLocationChange: true } }, {
1323
+ position: 'right',
1324
+ injector: this.injector,
1325
+ })
1326
+ .subscribe((value) => {
1327
+ if (value === 'refresh') {
1328
+ this.forceFetch();
1329
+ }
1330
+ });
1331
+ }
1332
+ }
1333
+ processTableAction(action) {
1153
1334
  if (action.type === 'update_form') {
1154
1335
  const dataSource = action.dataSource;
1155
- this.dataService.setView({
1336
+ this.setView({
1156
1337
  id: action.type,
1157
1338
  type: 'form',
1158
1339
  controlSource: {
1159
1340
  kind: dataSource.kind,
1160
1341
  entity: dataSource.entity,
1161
- params: dataSource?.params
1162
- ? this.interpolateRowValues(dataSource.params, row)
1163
- : undefined,
1342
+ params: dataSource?.params,
1164
1343
  },
1165
1344
  });
1166
1345
  }
1167
1346
  }
1347
+ setView(node) {
1348
+ this.dataService.setView(node, !!this.config()?.skipLocationChange);
1349
+ }
1168
1350
  setPagination(pagination) {
1169
1351
  this._pageSize.set(pagination?.pageSize ?? 0);
1170
1352
  this._pageSizeOptions.set(pagination?.options ?? []);
@@ -1280,8 +1462,27 @@ class TableViewComponent {
1280
1462
  });
1281
1463
  });
1282
1464
  }
1465
+ forceFetch() {
1466
+ const node = this.node();
1467
+ const pageSize = this.pageSize();
1468
+ const pageIndex = this.pageIndex();
1469
+ const sort = this._sortMap();
1470
+ const filters = this.filtersService.selection();
1471
+ if (node?.dataSource) {
1472
+ const ctx = buildRequestContext({
1473
+ pageSize,
1474
+ pageIndex,
1475
+ sort: mapSortMapToSortStringList(sort),
1476
+ filters,
1477
+ }, {
1478
+ isSortable: this.isSortingEnabled(),
1479
+ hasPagination: !!this.pageSize(),
1480
+ });
1481
+ this.getTableData(node, ctx);
1482
+ }
1483
+ }
1283
1484
  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 });
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 });
1285
1486
  }
1286
1487
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: TableViewComponent, decorators: [{
1287
1488
  type: Component,
@@ -1331,6 +1532,8 @@ class FormRendererComponent {
1331
1532
  sections = input.required();
1332
1533
  topLevelControls = input([]);
1333
1534
  customCss = input();
1535
+ config = input();
1536
+ event = output();
1334
1537
  constructor() {
1335
1538
  this.renderer.appendChild(this.ref.nativeElement, this.styleRef);
1336
1539
  this.destroyRef.onDestroy(() => {
@@ -1341,11 +1544,11 @@ class FormRendererComponent {
1341
1544
  });
1342
1545
  }
1343
1546
  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 });
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 });
1345
1548
  }
1346
1549
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: FormRendererComponent, decorators: [{
1347
1550
  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" }]
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" }]
1349
1552
  }], ctorParameters: () => [] });
1350
1553
 
1351
1554
  const isPlaceholder = (value) => {
@@ -1721,13 +1924,15 @@ class FormViewComponent {
1721
1924
  update_form: (action) => {
1722
1925
  const node = this.mapUpdateFormActionToFormNode(action.control_source);
1723
1926
  if (node) {
1724
- this.dataService.setView(node);
1927
+ this.setView(node);
1725
1928
  }
1726
1929
  return of(null);
1727
1930
  },
1728
1931
  update_table: (action) => {
1729
1932
  const node = this.mapUpdateTableActionToTableNode(action.data_source);
1730
- this.dataService.setView(node);
1933
+ this.event.emit('refresh');
1934
+ this.event.emit('close');
1935
+ this.setView(node);
1731
1936
  return of(null);
1732
1937
  },
1733
1938
  update_value: (action, response) => {
@@ -1763,6 +1968,7 @@ class FormViewComponent {
1763
1968
  };
1764
1969
  node = input.required();
1765
1970
  config = input();
1971
+ event = output();
1766
1972
  isLoading = this._isLoading.asReadonly();
1767
1973
  data = computed(() => {
1768
1974
  const engine = this._engine();
@@ -1817,6 +2023,9 @@ class FormViewComponent {
1817
2023
  this.processActionList(action.actions);
1818
2024
  });
1819
2025
  }
2026
+ setView(node) {
2027
+ this.dataService.setView(node, !!this.config()?.skipLocationChange);
2028
+ }
1820
2029
  processAction(action, response) {
1821
2030
  return this._actionHandlers[action.type](action, response);
1822
2031
  }
@@ -1889,52 +2098,73 @@ class FormViewComponent {
1889
2098
  .subscribe();
1890
2099
  }
1891
2100
  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 });
2101
+ 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
2102
  }
1894
2103
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: FormViewComponent, decorators: [{
1895
2104
  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" }]
2105
+ 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
2106
  }], ctorParameters: () => [] });
1898
2107
 
1899
2108
  class SectionComponent {
1900
2109
  node = input.required();
1901
2110
  config = input();
2111
+ event = output();
1902
2112
  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"] }] });
2113
+ 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
2114
  }
1905
2115
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SectionComponent, decorators: [{
1906
2116
  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" }]
2117
+ 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
2118
  }] });
1909
2119
 
1910
2120
  class GridColViewComponent {
1911
2121
  node = input.required();
1912
2122
  config = input();
2123
+ event = output();
1913
2124
  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"] }] });
2125
+ 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
2126
  }
1916
2127
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: GridColViewComponent, decorators: [{
1917
2128
  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" }]
2129
+ 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
2130
  }] });
1920
2131
 
2132
+ const NODE_COMPONENTS = {
2133
+ section: SectionComponent,
2134
+ grid: GridComponent,
2135
+ grid_col: GridColViewComponent,
2136
+ form: FormViewComponent,
2137
+ table: TableViewComponent,
2138
+ chart: ChartViewComponent,
2139
+ };
1921
2140
  class NodeComponent {
1922
2141
  node = input.required();
1923
2142
  config = input();
2143
+ event = output();
2144
+ componentPortal;
2145
+ constructor() {
2146
+ effect(() => {
2147
+ this.componentPortal = new ComponentPortal(NODE_COMPONENTS[this.node().type]);
2148
+ });
2149
+ }
2150
+ onPortalAttached(ref) {
2151
+ const componentRef = ref;
2152
+ componentRef.setInput('node', this.node());
2153
+ componentRef.setInput('config', this.config());
2154
+ const sub = componentRef.instance.event.subscribe((event) => {
2155
+ this.event.emit(event);
2156
+ });
2157
+ componentRef.onDestroy(() => {
2158
+ sub.unsubscribe();
2159
+ });
2160
+ }
1924
2161
  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 });
2162
+ 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
2163
  }
1927
2164
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: NodeComponent, decorators: [{
1928
2165
  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
- }] });
2166
+ 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" }]
2167
+ }], ctorParameters: () => [] });
1938
2168
 
1939
2169
  class FiltersComponent {
1940
2170
  filtersService = inject(LEFiltersService);
@@ -2138,6 +2368,7 @@ class LeContainerComponent {
2138
2368
  constructor() {
2139
2369
  this.listenAuthState();
2140
2370
  this.listenPageInit();
2371
+ this.dataService.registerEffects();
2141
2372
  }
2142
2373
  onSelectionChange(view) {
2143
2374
  this.dataService.setView(view);
@@ -2167,7 +2398,7 @@ class LeContainerComponent {
2167
2398
  });
2168
2399
  }
2169
2400
  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" }] });
2401
+ 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
2402
  }
2172
2403
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: LeContainerComponent, decorators: [{
2173
2404
  type: Component,