@planeasyinc/le-angular 0.0.20 → 0.0.21

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.
@@ -1,9 +1,9 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { InjectionToken, inject, signal, Injectable, computed, effect, untracked, Directive, input, ChangeDetectionStrategy, Component, output, forwardRef, ViewContainerRef, Injector, Renderer2, ElementRef, DestroyRef, viewChild } from '@angular/core';
3
3
  import { HttpContextToken, HttpClient, HttpContext, HttpRequest, HttpEventType } from '@angular/common/http';
4
- import { map, filter, distinctUntilChanged, BehaviorSubject, Subject, takeUntil, firstValueFrom, of, tap, catchError, from, concatMap, finalize, fromEvent, startWith } from 'rxjs';
4
+ import { map, filter, distinctUntilChanged, Subject, takeUntil, BehaviorSubject, 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, UpperCasePipe, DatePipe, ViewportScroller } from '@angular/common';
6
+ import { Location, UpperCasePipe, JsonPipe, 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';
@@ -11,11 +11,11 @@ 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
13
  import { DialogModule } from '@angular/cdk/dialog';
14
- import { CdkMenuTrigger, CdkMenu, CdkMenuItem } from '@angular/cdk/menu';
15
- import { A11yModule } from '@angular/cdk/a11y';
16
14
  import { Overlay } from '@angular/cdk/overlay';
17
15
  import { NestedTreeControl, CdkTree, CdkNestedTreeNode, CdkTreeNodeDef, CdkTreeNodeOutlet, CdkTreeNodeToggle } from '@angular/cdk/tree';
18
16
  import { ArrayDataSource, SelectionModel } from '@angular/cdk/collections';
17
+ import { CdkMenuTrigger, CdkMenu, CdkMenuItem } from '@angular/cdk/menu';
18
+ import { A11yModule } from '@angular/cdk/a11y';
19
19
  import { adaptOld } from '@planeasyinc/fe-adapters-old';
20
20
  import { adaptSections } from '@planeasyinc/fe-adapters-sections';
21
21
  import { createEngine } from '@planeasyinc/fe-core';
@@ -599,245 +599,50 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImpo
599
599
  }, template: "@for (child of node().children; track child.id) {\n <le-node [node]=\"child\" [config]=\"config()\" (event)=\"event.emit($event)\"></le-node>\n}\n" }]
600
600
  }] });
601
601
 
602
- class TableDataSource extends DataSource {
603
- data;
604
- get count() {
605
- return this.data.value.length;
606
- }
607
- constructor(data = []) {
608
- super();
609
- this.data = new BehaviorSubject(data);
610
- }
611
- getValueByIndex(index) {
612
- return this.data.value[index];
613
- }
614
- connect() {
615
- return this.data;
616
- }
617
- disconnect() { }
618
- }
619
-
620
- class TableViewPaginationComponent {
621
- pageSize = input.required();
622
- pageSizeOptions = input.required();
623
- entriesCount = input.required();
624
- pageChange = output();
625
- selectedPageSize = signal(0);
626
- selectedPageIndex = signal(0);
627
- entriesRange = computed(() => {
628
- const selectedPageIndex = this.selectedPageIndex();
629
- const pageSize = this.pageSize();
630
- const count = this.entriesCount();
631
- const rangeStart = selectedPageIndex * pageSize;
632
- const rangeEnd = rangeStart + pageSize;
633
- return {
634
- start: rangeStart,
635
- end: rangeEnd > count ? count : rangeEnd,
636
- };
637
- });
638
- constructor() {
639
- this.setEffects();
640
- }
641
- onPageSizeChange(option) {
642
- this.selectedPageSize.set(option);
643
- }
644
- onNavigateClick(param) {
645
- this.selectedPageIndex.update((index) => {
646
- if (param === 'prev' && this.canNavigatePrev(index)) {
647
- return index - 1;
648
- }
649
- if (param === 'next' && this.canNavigateNext(index)) {
650
- return index + 1;
651
- }
652
- return index;
653
- });
654
- }
655
- canNavigatePrev(index = this.selectedPageIndex()) {
656
- return index > 0;
657
- }
658
- canNavigateNext(index = this.selectedPageIndex()) {
659
- return index < this.getLastPageIndex();
660
- }
661
- setEffects() {
662
- effect(() => {
663
- const pageSize = this.pageSize();
664
- untracked(() => {
665
- this.selectedPageSize.set(pageSize);
666
- });
667
- });
668
- effect(() => {
669
- const pageSize = this.selectedPageSize();
670
- untracked(() => {
671
- const selectedPageIndex = this.selectedPageIndex();
672
- const pageIndex = this.getPageIndexOnPageSizeChange();
673
- if (selectedPageIndex !== pageIndex) {
674
- this.selectedPageIndex.set(pageIndex);
675
- }
676
- else {
677
- this.pageChange.emit({
678
- pageSize: pageSize,
679
- pageIndex: pageIndex,
680
- });
681
- }
682
- });
683
- });
684
- effect(() => {
685
- const index = this.selectedPageIndex();
686
- untracked(() => {
687
- this.pageChange.emit({
688
- pageSize: this.selectedPageSize(),
689
- pageIndex: index,
690
- });
691
- });
692
- });
693
- }
694
- /**
695
- * @return page index or last available page index for selected page size
696
- */
697
- getPageIndexOnPageSizeChange() {
698
- const selectedPageIndex = this.selectedPageIndex();
699
- const lasPageIndex = this.getLastPageIndex();
700
- return selectedPageIndex > lasPageIndex ? lasPageIndex : selectedPageIndex;
701
- }
702
- /**
703
- * @return last available page index
704
- */
705
- getLastPageIndex() {
706
- const count = this.entriesCount();
707
- if (count === 0)
708
- return 0;
709
- return Math.ceil(count / this.selectedPageSize()) - 1;
710
- }
711
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: TableViewPaginationComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
712
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: TableViewPaginationComponent, isStandalone: true, selector: "table-view-pagination", inputs: { pageSize: { classPropertyName: "pageSize", publicName: "pageSize", isSignal: true, isRequired: true, transformFunction: null }, pageSizeOptions: { classPropertyName: "pageSizeOptions", publicName: "pageSizeOptions", isSignal: true, isRequired: true, transformFunction: null }, entriesCount: { classPropertyName: "entriesCount", publicName: "entriesCount", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { pageChange: "pageChange" }, ngImport: i0, template: "<div class=\"le-pagination\">\n <div class=\"le-pagination-options\">\n <span>Items per page:</span>\n\n <button [cdkMenuTriggerFor]=\"optionsMenu\" class=\"le-button\">\n {{ selectedPageSize() }}\n\n <le-icon name=\"arrow-down\"></le-icon>\n </button>\n\n <ng-template #optionsMenu>\n <div class=\"le-pagination-option-list\" cdkMenu>\n @for (option of pageSizeOptions(); track option) {\n <button cdkMenuItem class=\"le-pagination-option-item\" (click)=\"onPageSizeChange(option)\">\n {{ option }}\n </button>\n }\n </div>\n </ng-template>\n </div>\n\n <div class=\"spacer\"></div>\n\n <div class=\"le-pagination-range\">\n {{ entriesRange().start }} - {{ entriesRange().end }} of {{ entriesCount() }}\n </div>\n\n <div class=\"le-pagination-navigation\">\n <button\n class=\"le-navigation le-navigation-prev\"\n [tabindex]=\"canNavigatePrev() ? 0 : -1\"\n [disabled]=\"!canNavigatePrev()\"\n (click)=\"onNavigateClick('prev')\"\n >\n <le-icon class=\"le-chevron le-chevron--left\" name=\"chevron\"></le-icon>\n </button>\n\n <button\n class=\"le-navigation le-navigation-next\"\n [tabindex]=\"canNavigateNext() ? 0 : -1\"\n [disabled]=\"!canNavigateNext()\"\n (click)=\"onNavigateClick('next')\"\n >\n <le-icon class=\"le-chevron le-chevron--right\" name=\"chevron\"></le-icon>\n </button>\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: CdkMenuTrigger, selector: "[cdkMenuTriggerFor]", inputs: ["cdkMenuTriggerFor", "cdkMenuPosition", "cdkMenuTriggerData"], outputs: ["cdkMenuOpened", "cdkMenuClosed"], exportAs: ["cdkMenuTriggerFor"] }, { kind: "directive", type: CdkMenu, selector: "[cdkMenu]", outputs: ["closed"], exportAs: ["cdkMenu"] }, { kind: "directive", type: CdkMenuItem, selector: "[cdkMenuItem]", inputs: ["cdkMenuItemDisabled", "cdkMenuitemTypeaheadLabel"], outputs: ["cdkMenuItemTriggered"], exportAs: ["cdkMenuItem"] }, { kind: "ngmodule", type: A11yModule }, { kind: "component", type: LeIconComponent, selector: "le-icon", inputs: ["name", "size"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
713
- }
714
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: TableViewPaginationComponent, decorators: [{
715
- type: Component,
716
- args: [{ selector: 'table-view-pagination', imports: [CdkMenuTrigger, CdkMenu, CdkMenuItem, A11yModule, LeIconComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"le-pagination\">\n <div class=\"le-pagination-options\">\n <span>Items per page:</span>\n\n <button [cdkMenuTriggerFor]=\"optionsMenu\" class=\"le-button\">\n {{ selectedPageSize() }}\n\n <le-icon name=\"arrow-down\"></le-icon>\n </button>\n\n <ng-template #optionsMenu>\n <div class=\"le-pagination-option-list\" cdkMenu>\n @for (option of pageSizeOptions(); track option) {\n <button cdkMenuItem class=\"le-pagination-option-item\" (click)=\"onPageSizeChange(option)\">\n {{ option }}\n </button>\n }\n </div>\n </ng-template>\n </div>\n\n <div class=\"spacer\"></div>\n\n <div class=\"le-pagination-range\">\n {{ entriesRange().start }} - {{ entriesRange().end }} of {{ entriesCount() }}\n </div>\n\n <div class=\"le-pagination-navigation\">\n <button\n class=\"le-navigation le-navigation-prev\"\n [tabindex]=\"canNavigatePrev() ? 0 : -1\"\n [disabled]=\"!canNavigatePrev()\"\n (click)=\"onNavigateClick('prev')\"\n >\n <le-icon class=\"le-chevron le-chevron--left\" name=\"chevron\"></le-icon>\n </button>\n\n <button\n class=\"le-navigation le-navigation-next\"\n [tabindex]=\"canNavigateNext() ? 0 : -1\"\n [disabled]=\"!canNavigateNext()\"\n (click)=\"onNavigateClick('next')\"\n >\n <le-icon class=\"le-chevron le-chevron--right\" name=\"chevron\"></le-icon>\n </button>\n </div>\n</div>\n" }]
717
- }], ctorParameters: () => [] });
718
-
719
- const isPlaceholder$1 = (value) => {
720
- return value.startsWith('{') && value.endsWith('}');
721
- };
722
- const mapSortStringToSort = (sort) => {
723
- return sort.startsWith('-') ? [sort.slice(1), 'desc'] : [sort, 'desc'];
724
- };
725
- const mapSortStringListToSortMap = (sortList) => {
726
- return sortList.reduce((acc, sort) => {
727
- const { 0: key, 1: value } = mapSortStringToSort(sort);
728
- acc.set(key, value);
729
- return acc;
730
- }, new Map());
731
- };
732
- const mapSortMapToSortStringList = (sortMap) => {
733
- return [...sortMap].reduce((acc, sort) => {
734
- const prefix = sort[1] === 'asc' ? '' : '-';
735
- acc.push(`${prefix}${sort[0]}`);
736
- return acc;
737
- }, []);
738
- };
739
- const mapFiltersToFilterString = (filters) => {
740
- return Object.entries(filters)
741
- .reduce((acc, filter) => {
742
- return acc.concat(`filter[${filter[0]}]=${filter[1]}`);
743
- }, [])
744
- .join('&');
745
- };
746
- const buildRequestContext = (params, ctx) => {
747
- const requestContext = {};
748
- if (ctx.hasPagination && params.pageIndex !== undefined) {
749
- requestContext['pageIndex'] = params.pageIndex;
750
- requestContext['pageSize'] = params.pageSize;
751
- }
752
- if (ctx.isSortable && params.sort) {
753
- requestContext['sort'] = params.sort;
754
- }
755
- if (params.filters && Object.keys(params.filters).length > 0) {
756
- requestContext['filters'] = params.filters;
602
+ const flattenNodes = (nodes) => {
603
+ const flattenedNodes = [];
604
+ for (const node of nodes) {
605
+ flattenedNodes.push(node);
606
+ if (node.leafs) {
607
+ flattenedNodes.push(...flattenNodes(node.leafs));
608
+ }
757
609
  }
758
- return requestContext;
610
+ return flattenedNodes;
759
611
  };
760
- const buildRequestBody = (params) => {
761
- const body = {};
762
- if (params.sort?.length) {
763
- body['ordering'] = params.sort;
764
- }
765
- if (params.filters && Object.keys(params.filters).length > 0) {
766
- body['filters'] = params.filters;
767
- }
768
- if (params.pageIndex !== undefined) {
769
- body['page'] = params.pageIndex + 1;
770
- }
771
- if (params.pageSize) {
772
- body['page_size'] = params.pageSize;
612
+ const toTree = (obj, label) => {
613
+ if (obj !== null && typeof obj === 'object') {
614
+ const entries = Array.isArray(obj)
615
+ ? obj.map((v, i) => toTree(v, String(i)))
616
+ : Object.entries(obj).map((item) => toTree(item[1], item[0]));
617
+ return { label, leafs: entries };
773
618
  }
774
- return body;
619
+ return { label, value: obj };
775
620
  };
776
- const buildQueryString = (params) => {
777
- const query = [];
778
- if (params.pageIndex !== undefined) {
779
- query.push(`page=${params.pageIndex + 1}`);
780
- }
781
- if (params.pageSize) {
782
- query.push(`page_size=${params.pageSize}`);
783
- }
784
- if (params.sort?.length) {
785
- query.push(`ordering=${params.sort.join(',')}`);
786
- }
787
- if (params.filters && Object.keys(params.filters).length > 0) {
788
- query.push(mapFiltersToFilterString(params.filters));
789
- }
790
- return query.filter((item) => !!item).join('&');
621
+ const mapObjectToTree = (data) => {
622
+ return Object.entries(data).map((item) => toTree(item[1], item[0]));
791
623
  };
792
624
 
793
- class LoadingViewComponent {
794
- headerHeight = input(0);
795
- rowHeight = input(40);
796
- rowCount = input(1);
797
- rows = computed(() => {
798
- return new Array(this.rowCount()).fill(null).map((_, i) => i);
625
+ class TreeViewComponent {
626
+ treeControl = new NestedTreeControl((node) => node.leafs);
627
+ data = input();
628
+ source = computed(() => {
629
+ return new ArrayDataSource(mapObjectToTree(this.data() ?? {}));
799
630
  });
800
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: LoadingViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
801
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: LoadingViewComponent, isStandalone: true, selector: "app-loading-view", inputs: { headerHeight: { classPropertyName: "headerHeight", publicName: "headerHeight", isSignal: true, isRequired: false, transformFunction: null }, rowHeight: { classPropertyName: "rowHeight", publicName: "rowHeight", isSignal: true, isRequired: false, transformFunction: null }, rowCount: { classPropertyName: "rowCount", publicName: "rowCount", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"preloader\">\n @if (headerHeight()) {\n <div class=\"preloader-row\" [style.height.px]=\"headerHeight()\"></div>\n }\n\n @for (row of rows(); track row) {\n <div class=\"preloader-row\" [style.height.px]=\"rowHeight()\"></div>\n }\n</div>\n", styles: [".preloader{display:flex;flex-direction:column;width:100%;gap:8px}.preloader-row{background:#f5f5f5 no-repeat;animation:pulse 1.5s cubic-bezier(.4,0,.2,1) infinite;animation-delay:.5s}@keyframes pulse{0%{opacity:1}50%{opacity:.5}to{opacity:1}}\n"] });
802
- }
803
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: LoadingViewComponent, decorators: [{
804
- type: Component,
805
- args: [{ selector: 'app-loading-view', template: "<div class=\"preloader\">\n @if (headerHeight()) {\n <div class=\"preloader-row\" [style.height.px]=\"headerHeight()\"></div>\n }\n\n @for (row of rows(); track row) {\n <div class=\"preloader-row\" [style.height.px]=\"rowHeight()\"></div>\n }\n</div>\n", styles: [".preloader{display:flex;flex-direction:column;width:100%;gap:8px}.preloader-row{background:#f5f5f5 no-repeat;animation:pulse 1.5s cubic-bezier(.4,0,.2,1) infinite;animation-delay:.5s}@keyframes pulse{0%{opacity:1}50%{opacity:.5}to{opacity:1}}\n"] }]
806
- }] });
807
-
808
- class TableViewActions {
809
- actions = input();
810
- actionClicked = output();
811
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: TableViewActions, deps: [], target: i0.ɵɵFactoryTarget.Component });
812
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: TableViewActions, isStandalone: true, selector: "table-view-actions", inputs: { actions: { classPropertyName: "actions", publicName: "actions", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { actionClicked: "actionClicked" }, host: { properties: { "class.le-table-view-actions": "true" } }, ngImport: i0, template: `
813
- @for (action of actions(); track action) {
814
- <button
815
- class="le-button le-button-flat le-button--success"
816
- (click)="actionClicked.emit(action)"
817
- >
818
- {{ action.label }}
819
- </button>
820
- }
821
- `, isInline: true });
631
+ hasChild = (_, node) => !!node.leafs && node.leafs.length > 0;
632
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: TreeViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
633
+ 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 });
822
634
  }
823
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: TableViewActions, decorators: [{
635
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: TreeViewComponent, decorators: [{
824
636
  type: Component,
825
- args: [{
826
- selector: 'table-view-actions',
827
- template: `
828
- @for (action of actions(); track action) {
829
- <button
830
- class="le-button le-button-flat le-button--success"
831
- (click)="actionClicked.emit(action)"
832
- >
833
- {{ action.label }}
834
- </button>
835
- }
836
- `,
837
- host: {
838
- '[class.le-table-view-actions]': 'true',
839
- },
840
- }]
637
+ args: [{ selector: 'le-tree-view', imports: [
638
+ CdkTree,
639
+ CdkNestedTreeNode,
640
+ CdkTreeNodeDef,
641
+ CdkTreeNodeOutlet,
642
+ LeIconComponent,
643
+ CdkTreeNodeToggle,
644
+ UpperCasePipe,
645
+ ], 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" }]
841
646
  }] });
842
647
 
843
648
  class StringTemplate {
@@ -993,59 +798,13 @@ class TableViewCellDirective {
993
798
  }
994
799
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: TableViewCellDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
995
800
  static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.2.21", type: TableViewCellDirective, isStandalone: true, selector: "[tableViewCell]", inputs: { type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: true, transformFunction: null }, column: { classPropertyName: "column", publicName: "column", isSignal: true, isRequired: false, transformFunction: null }, metadata: { classPropertyName: "metadata", publicName: "metadata", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { clicked: "clicked" }, ngImport: i0 });
996
- }
997
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: TableViewCellDirective, decorators: [{
998
- type: Directive,
999
- args: [{
1000
- selector: '[tableViewCell]',
1001
- }]
1002
- }], ctorParameters: () => [] });
1003
-
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 });
1036
- }
1037
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: TreeViewComponent, decorators: [{
1038
- type: Component,
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" }]
1048
- }] });
801
+ }
802
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: TableViewCellDirective, decorators: [{
803
+ type: Directive,
804
+ args: [{
805
+ selector: '[tableViewCell]',
806
+ }]
807
+ }], ctorParameters: () => [] });
1049
808
 
1050
809
  class BlockViewComponent {
1051
810
  data = input.required();
@@ -1216,6 +975,247 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImpo
1216
975
  }]
1217
976
  }] });
1218
977
 
978
+ class TableViewPaginationComponent {
979
+ pageSize = input.required();
980
+ pageSizeOptions = input.required();
981
+ entriesCount = input.required();
982
+ pageChange = output();
983
+ selectedPageSize = signal(0);
984
+ selectedPageIndex = signal(0);
985
+ entriesRange = computed(() => {
986
+ const selectedPageIndex = this.selectedPageIndex();
987
+ const pageSize = this.pageSize();
988
+ const count = this.entriesCount();
989
+ const rangeStart = selectedPageIndex * pageSize;
990
+ const rangeEnd = rangeStart + pageSize;
991
+ return {
992
+ start: rangeStart,
993
+ end: rangeEnd > count ? count : rangeEnd,
994
+ };
995
+ });
996
+ constructor() {
997
+ this.setEffects();
998
+ }
999
+ onPageSizeChange(option) {
1000
+ this.selectedPageSize.set(option);
1001
+ }
1002
+ onNavigateClick(param) {
1003
+ this.selectedPageIndex.update((index) => {
1004
+ if (param === 'prev' && this.canNavigatePrev(index)) {
1005
+ return index - 1;
1006
+ }
1007
+ if (param === 'next' && this.canNavigateNext(index)) {
1008
+ return index + 1;
1009
+ }
1010
+ return index;
1011
+ });
1012
+ }
1013
+ canNavigatePrev(index = this.selectedPageIndex()) {
1014
+ return index > 0;
1015
+ }
1016
+ canNavigateNext(index = this.selectedPageIndex()) {
1017
+ return index < this.getLastPageIndex();
1018
+ }
1019
+ setEffects() {
1020
+ effect(() => {
1021
+ const pageSize = this.pageSize();
1022
+ untracked(() => {
1023
+ this.selectedPageSize.set(pageSize);
1024
+ });
1025
+ });
1026
+ effect(() => {
1027
+ const pageSize = this.selectedPageSize();
1028
+ untracked(() => {
1029
+ const selectedPageIndex = this.selectedPageIndex();
1030
+ const pageIndex = this.getPageIndexOnPageSizeChange();
1031
+ if (selectedPageIndex !== pageIndex) {
1032
+ this.selectedPageIndex.set(pageIndex);
1033
+ }
1034
+ else {
1035
+ this.pageChange.emit({
1036
+ pageSize: pageSize,
1037
+ pageIndex: pageIndex,
1038
+ });
1039
+ }
1040
+ });
1041
+ });
1042
+ effect(() => {
1043
+ const index = this.selectedPageIndex();
1044
+ untracked(() => {
1045
+ this.pageChange.emit({
1046
+ pageSize: this.selectedPageSize(),
1047
+ pageIndex: index,
1048
+ });
1049
+ });
1050
+ });
1051
+ }
1052
+ /**
1053
+ * @return page index or last available page index for selected page size
1054
+ */
1055
+ getPageIndexOnPageSizeChange() {
1056
+ const selectedPageIndex = this.selectedPageIndex();
1057
+ const lasPageIndex = this.getLastPageIndex();
1058
+ return selectedPageIndex > lasPageIndex ? lasPageIndex : selectedPageIndex;
1059
+ }
1060
+ /**
1061
+ * @return last available page index
1062
+ */
1063
+ getLastPageIndex() {
1064
+ const count = this.entriesCount();
1065
+ if (count === 0)
1066
+ return 0;
1067
+ return Math.ceil(count / this.selectedPageSize()) - 1;
1068
+ }
1069
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: TableViewPaginationComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1070
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: TableViewPaginationComponent, isStandalone: true, selector: "table-view-pagination", inputs: { pageSize: { classPropertyName: "pageSize", publicName: "pageSize", isSignal: true, isRequired: true, transformFunction: null }, pageSizeOptions: { classPropertyName: "pageSizeOptions", publicName: "pageSizeOptions", isSignal: true, isRequired: true, transformFunction: null }, entriesCount: { classPropertyName: "entriesCount", publicName: "entriesCount", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { pageChange: "pageChange" }, ngImport: i0, template: "<div class=\"le-pagination\">\n <div class=\"le-pagination-options\">\n <span>Items per page:</span>\n\n <button [cdkMenuTriggerFor]=\"optionsMenu\" class=\"le-button\">\n {{ selectedPageSize() }}\n\n <le-icon name=\"arrow-down\"></le-icon>\n </button>\n\n <ng-template #optionsMenu>\n <div class=\"le-pagination-option-list\" cdkMenu>\n @for (option of pageSizeOptions(); track option) {\n <button cdkMenuItem class=\"le-pagination-option-item\" (click)=\"onPageSizeChange(option)\">\n {{ option }}\n </button>\n }\n </div>\n </ng-template>\n </div>\n\n <div class=\"spacer\"></div>\n\n <div class=\"le-pagination-range\">\n {{ entriesRange().start }} - {{ entriesRange().end }} of {{ entriesCount() }}\n </div>\n\n <div class=\"le-pagination-navigation\">\n <button\n class=\"le-navigation le-navigation-prev\"\n [tabindex]=\"canNavigatePrev() ? 0 : -1\"\n [disabled]=\"!canNavigatePrev()\"\n (click)=\"onNavigateClick('prev')\"\n >\n <le-icon class=\"le-chevron le-chevron--left\" name=\"chevron\"></le-icon>\n </button>\n\n <button\n class=\"le-navigation le-navigation-next\"\n [tabindex]=\"canNavigateNext() ? 0 : -1\"\n [disabled]=\"!canNavigateNext()\"\n (click)=\"onNavigateClick('next')\"\n >\n <le-icon class=\"le-chevron le-chevron--right\" name=\"chevron\"></le-icon>\n </button>\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: CdkMenuTrigger, selector: "[cdkMenuTriggerFor]", inputs: ["cdkMenuTriggerFor", "cdkMenuPosition", "cdkMenuTriggerData"], outputs: ["cdkMenuOpened", "cdkMenuClosed"], exportAs: ["cdkMenuTriggerFor"] }, { kind: "directive", type: CdkMenu, selector: "[cdkMenu]", outputs: ["closed"], exportAs: ["cdkMenu"] }, { kind: "directive", type: CdkMenuItem, selector: "[cdkMenuItem]", inputs: ["cdkMenuItemDisabled", "cdkMenuitemTypeaheadLabel"], outputs: ["cdkMenuItemTriggered"], exportAs: ["cdkMenuItem"] }, { kind: "ngmodule", type: A11yModule }, { kind: "component", type: LeIconComponent, selector: "le-icon", inputs: ["name", "size"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1071
+ }
1072
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: TableViewPaginationComponent, decorators: [{
1073
+ type: Component,
1074
+ args: [{ selector: 'table-view-pagination', imports: [CdkMenuTrigger, CdkMenu, CdkMenuItem, A11yModule, LeIconComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"le-pagination\">\n <div class=\"le-pagination-options\">\n <span>Items per page:</span>\n\n <button [cdkMenuTriggerFor]=\"optionsMenu\" class=\"le-button\">\n {{ selectedPageSize() }}\n\n <le-icon name=\"arrow-down\"></le-icon>\n </button>\n\n <ng-template #optionsMenu>\n <div class=\"le-pagination-option-list\" cdkMenu>\n @for (option of pageSizeOptions(); track option) {\n <button cdkMenuItem class=\"le-pagination-option-item\" (click)=\"onPageSizeChange(option)\">\n {{ option }}\n </button>\n }\n </div>\n </ng-template>\n </div>\n\n <div class=\"spacer\"></div>\n\n <div class=\"le-pagination-range\">\n {{ entriesRange().start }} - {{ entriesRange().end }} of {{ entriesCount() }}\n </div>\n\n <div class=\"le-pagination-navigation\">\n <button\n class=\"le-navigation le-navigation-prev\"\n [tabindex]=\"canNavigatePrev() ? 0 : -1\"\n [disabled]=\"!canNavigatePrev()\"\n (click)=\"onNavigateClick('prev')\"\n >\n <le-icon class=\"le-chevron le-chevron--left\" name=\"chevron\"></le-icon>\n </button>\n\n <button\n class=\"le-navigation le-navigation-next\"\n [tabindex]=\"canNavigateNext() ? 0 : -1\"\n [disabled]=\"!canNavigateNext()\"\n (click)=\"onNavigateClick('next')\"\n >\n <le-icon class=\"le-chevron le-chevron--right\" name=\"chevron\"></le-icon>\n </button>\n </div>\n</div>\n" }]
1075
+ }], ctorParameters: () => [] });
1076
+
1077
+ class LoadingViewComponent {
1078
+ headerHeight = input(0);
1079
+ rowHeight = input(40);
1080
+ rowCount = input(1);
1081
+ rows = computed(() => {
1082
+ return new Array(this.rowCount()).fill(null).map((_, i) => i);
1083
+ });
1084
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: LoadingViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1085
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: LoadingViewComponent, isStandalone: true, selector: "app-loading-view", inputs: { headerHeight: { classPropertyName: "headerHeight", publicName: "headerHeight", isSignal: true, isRequired: false, transformFunction: null }, rowHeight: { classPropertyName: "rowHeight", publicName: "rowHeight", isSignal: true, isRequired: false, transformFunction: null }, rowCount: { classPropertyName: "rowCount", publicName: "rowCount", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"preloader\">\n @if (headerHeight()) {\n <div class=\"preloader-row\" [style.height.px]=\"headerHeight()\"></div>\n }\n\n @for (row of rows(); track row) {\n <div class=\"preloader-row\" [style.height.px]=\"rowHeight()\"></div>\n }\n</div>\n", styles: [".preloader{display:flex;flex-direction:column;width:100%;gap:8px}.preloader-row{background:#f5f5f5 no-repeat;animation:pulse 1.5s cubic-bezier(.4,0,.2,1) infinite;animation-delay:.5s}@keyframes pulse{0%{opacity:1}50%{opacity:.5}to{opacity:1}}\n"] });
1086
+ }
1087
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: LoadingViewComponent, decorators: [{
1088
+ type: Component,
1089
+ args: [{ selector: 'app-loading-view', template: "<div class=\"preloader\">\n @if (headerHeight()) {\n <div class=\"preloader-row\" [style.height.px]=\"headerHeight()\"></div>\n }\n\n @for (row of rows(); track row) {\n <div class=\"preloader-row\" [style.height.px]=\"rowHeight()\"></div>\n }\n</div>\n", styles: [".preloader{display:flex;flex-direction:column;width:100%;gap:8px}.preloader-row{background:#f5f5f5 no-repeat;animation:pulse 1.5s cubic-bezier(.4,0,.2,1) infinite;animation-delay:.5s}@keyframes pulse{0%{opacity:1}50%{opacity:.5}to{opacity:1}}\n"] }]
1090
+ }] });
1091
+
1092
+ class TableViewActions {
1093
+ actions = input();
1094
+ actionClicked = output();
1095
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: TableViewActions, deps: [], target: i0.ɵɵFactoryTarget.Component });
1096
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: TableViewActions, isStandalone: true, selector: "table-view-actions", inputs: { actions: { classPropertyName: "actions", publicName: "actions", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { actionClicked: "actionClicked" }, host: { properties: { "class.le-table-view-actions": "true" } }, ngImport: i0, template: `
1097
+ @for (action of actions(); track action) {
1098
+ <button
1099
+ class="le-button le-button-flat le-button--success"
1100
+ (click)="actionClicked.emit(action)"
1101
+ >
1102
+ {{ action.label }}
1103
+ </button>
1104
+ }
1105
+ `, isInline: true });
1106
+ }
1107
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: TableViewActions, decorators: [{
1108
+ type: Component,
1109
+ args: [{
1110
+ selector: 'table-view-actions',
1111
+ template: `
1112
+ @for (action of actions(); track action) {
1113
+ <button
1114
+ class="le-button le-button-flat le-button--success"
1115
+ (click)="actionClicked.emit(action)"
1116
+ >
1117
+ {{ action.label }}
1118
+ </button>
1119
+ }
1120
+ `,
1121
+ host: {
1122
+ '[class.le-table-view-actions]': 'true',
1123
+ },
1124
+ }]
1125
+ }] });
1126
+
1127
+ class TableDataSource extends DataSource {
1128
+ data;
1129
+ get count() {
1130
+ return this.data.value.length;
1131
+ }
1132
+ constructor(data = []) {
1133
+ super();
1134
+ this.data = new BehaviorSubject(data);
1135
+ }
1136
+ getValueByIndex(index) {
1137
+ return this.data.value[index];
1138
+ }
1139
+ connect() {
1140
+ return this.data;
1141
+ }
1142
+ disconnect() { }
1143
+ }
1144
+
1145
+ const isPlaceholder$1 = (value) => {
1146
+ return value.startsWith('{') && value.endsWith('}');
1147
+ };
1148
+ const mapSortStringToSort = (sort) => {
1149
+ return sort.startsWith('-') ? [sort.slice(1), 'desc'] : [sort, 'desc'];
1150
+ };
1151
+ const mapSortStringListToSortMap = (sortList) => {
1152
+ return sortList.reduce((acc, sort) => {
1153
+ const { 0: key, 1: value } = mapSortStringToSort(sort);
1154
+ acc.set(key, value);
1155
+ return acc;
1156
+ }, new Map());
1157
+ };
1158
+ const mapSortMapToSortStringList = (sortMap) => {
1159
+ return [...sortMap].reduce((acc, sort) => {
1160
+ const prefix = sort[1] === 'asc' ? '' : '-';
1161
+ acc.push(`${prefix}${sort[0]}`);
1162
+ return acc;
1163
+ }, []);
1164
+ };
1165
+ const mapFiltersToFilterString = (filters) => {
1166
+ return Object.entries(filters)
1167
+ .reduce((acc, filter) => {
1168
+ return acc.concat(`filter[${filter[0]}]=${filter[1]}`);
1169
+ }, [])
1170
+ .join('&');
1171
+ };
1172
+ const buildRequestContext = (params, ctx) => {
1173
+ const requestContext = {};
1174
+ if (ctx.hasPagination && params.pageIndex !== undefined) {
1175
+ requestContext['pageIndex'] = params.pageIndex;
1176
+ requestContext['pageSize'] = params.pageSize;
1177
+ }
1178
+ if (ctx.isSortable && params.sort) {
1179
+ requestContext['sort'] = params.sort;
1180
+ }
1181
+ if (params.filters && Object.keys(params.filters).length > 0) {
1182
+ requestContext['filters'] = params.filters;
1183
+ }
1184
+ return requestContext;
1185
+ };
1186
+ const buildRequestBody = (params) => {
1187
+ const body = {};
1188
+ if (params.sort?.length) {
1189
+ body['ordering'] = params.sort;
1190
+ }
1191
+ if (params.filters && Object.keys(params.filters).length > 0) {
1192
+ body['filters'] = params.filters;
1193
+ }
1194
+ if (params.pageIndex !== undefined) {
1195
+ body['page'] = params.pageIndex + 1;
1196
+ }
1197
+ if (params.pageSize) {
1198
+ body['page_size'] = params.pageSize;
1199
+ }
1200
+ return body;
1201
+ };
1202
+ const buildQueryString = (params) => {
1203
+ const query = [];
1204
+ if (params.pageIndex !== undefined) {
1205
+ query.push(`page=${params.pageIndex + 1}`);
1206
+ }
1207
+ if (params.pageSize) {
1208
+ query.push(`page_size=${params.pageSize}`);
1209
+ }
1210
+ if (params.sort?.length) {
1211
+ query.push(`ordering=${params.sort.join(',')}`);
1212
+ }
1213
+ if (params.filters && Object.keys(params.filters).length > 0) {
1214
+ query.push(mapFiltersToFilterString(params.filters));
1215
+ }
1216
+ return query.filter((item) => !!item).join('&');
1217
+ };
1218
+
1219
1219
  class TableViewComponent {
1220
1220
  apiService = inject(LEApiService);
1221
1221
  dataService = inject(LEDataService);
@@ -1243,7 +1243,7 @@ class TableViewComponent {
1243
1243
  const firstRow = this.data().getValueByIndex(0);
1244
1244
  const columnKeys = this.columns().map((column) => column.key);
1245
1245
  const hasVersion = !!(firstRow && firstRow._metadata && firstRow._metadata.object_version);
1246
- if (!this.config()?.hideInfo) {
1246
+ if (firstRow && !this.config()?.hideInfo) {
1247
1247
  result.push('info');
1248
1248
  }
1249
1249
  result.push(...columnKeys);
@@ -1757,10 +1757,20 @@ const mapFormValuesToJSON = (values) => {
1757
1757
  return JSON.stringify(values, null, 2);
1758
1758
  };
1759
1759
  const mapJSONToFormValues = (json) => {
1760
+ // Check if it's a string and try to parse it
1760
1761
  if (typeof json === 'string') {
1761
- return JSON.parse(json);
1762
+ try {
1763
+ return JSON.parse(json);
1764
+ }
1765
+ catch {
1766
+ throw new Error('The json string is not valid JSON');
1767
+ }
1762
1768
  }
1763
- throw new Error('The `json` parameter is not a valid JSON');
1769
+ // Check if it's a plain object (not null, not array, not other types)
1770
+ if (json !== null && typeof json === 'object' && !Array.isArray(json)) {
1771
+ return json;
1772
+ }
1773
+ throw new Error('The json parameter is not a valid JSON object');
1764
1774
  };
1765
1775
  const getTabJSONControl = (control, engine) => {
1766
1776
  let result;
@@ -2131,15 +2141,20 @@ class FormViewComponent {
2131
2141
  const engine = this._engine();
2132
2142
  try {
2133
2143
  if (isTabJSON(action.source)) {
2134
- const values = mapJSONToFormValues(getTabJSONControl(action.source, engine).value);
2135
- Object.entries(values).forEach(({ 0: key, 1: value }) => {
2136
- engine.values.set(key, value);
2137
- });
2144
+ const jsonTabControl = getTabJSONControl(action.source, engine);
2145
+ if (jsonTabControl) {
2146
+ const values = mapJSONToFormValues(jsonTabControl.value);
2147
+ Object.entries(values).forEach(({ 0: key, 1: value }) => {
2148
+ engine.values.set(key, value);
2149
+ });
2150
+ }
2138
2151
  }
2139
2152
  else {
2140
- const target = getTabJSONControl(action.target, engine);
2141
- const value = mapFormValuesToJSON(getTabFormValues(action.source, target, engine));
2142
- engine.values.set(target.id, value);
2153
+ const jsonTabControl = getTabJSONControl(action.target, engine);
2154
+ if (jsonTabControl) {
2155
+ const value = mapFormValuesToJSON(getTabFormValues(action.source, jsonTabControl, engine));
2156
+ engine.values.set(jsonTabControl.id, value);
2157
+ }
2143
2158
  }
2144
2159
  }
2145
2160
  catch (e) {