cloud-ide-core 1.0.1 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/README.md +49 -10
  2. package/fesm2022/{cloud-ide-core-general-master-type.component-B26auJZw.mjs → cloud-ide-core-general-master-type.component-BNYoP_bS.mjs} +132 -134
  3. package/fesm2022/{cloud-ide-core-general-master-type.component-B26auJZw.mjs.map → cloud-ide-core-general-master-type.component-BNYoP_bS.mjs.map} +1 -1
  4. package/fesm2022/{cloud-ide-core-general-master-type.service-Ab64Jjps.mjs → cloud-ide-core-general-master-type.service-8JWTVijZ.mjs} +7 -7
  5. package/fesm2022/{cloud-ide-core-general-master-type.service-Ab64Jjps.mjs.map → cloud-ide-core-general-master-type.service-8JWTVijZ.mjs.map} +1 -1
  6. package/fesm2022/{cloud-ide-core-general-master.component-B6llTVoV.mjs → cloud-ide-core-general-master.component-CFGGHinl.mjs} +152 -154
  7. package/fesm2022/{cloud-ide-core-general-master.component-B6llTVoV.mjs.map → cloud-ide-core-general-master.component-CFGGHinl.mjs.map} +1 -1
  8. package/fesm2022/{cloud-ide-core-page-form.component-CaEca3mB.mjs → cloud-ide-core-page-form.component-vfE-LkTS.mjs} +25 -25
  9. package/fesm2022/{cloud-ide-core-page-form.component-CaEca3mB.mjs.map → cloud-ide-core-page-form.component-vfE-LkTS.mjs.map} +1 -1
  10. package/fesm2022/cloud-ide-core.mjs +1113 -1110
  11. package/fesm2022/cloud-ide-core.mjs.map +1 -1
  12. package/index.d.ts +1736 -3
  13. package/package.json +3 -5
  14. package/esm2022/cloud-ide-core.mjs +0 -5
  15. package/esm2022/lib/cloud-ide-core.component.mjs +0 -19
  16. package/esm2022/lib/cloud-ide-core.routes.mjs +0 -137
  17. package/esm2022/lib/cloud-ide-core.service.mjs +0 -14
  18. package/esm2022/lib/core/department-management/components/department-list/department-list.component.mjs +0 -768
  19. package/esm2022/lib/core/department-management/index.mjs +0 -5
  20. package/esm2022/lib/core/department-management/services/department-management.service.mjs +0 -187
  21. package/esm2022/lib/core/designation-management/components/designation-list/designation-list.component.mjs +0 -1122
  22. package/esm2022/lib/core/designation-management/index.mjs +0 -5
  23. package/esm2022/lib/core/designation-management/services/designation-management.service.mjs +0 -194
  24. package/esm2022/lib/core/general-master-management/components/general-master/general-master.component.mjs +0 -738
  25. package/esm2022/lib/core/general-master-management/components/general-master-type/general-master-type.component.mjs +0 -608
  26. package/esm2022/lib/core/general-master-management/services/general-master-type.service.mjs +0 -203
  27. package/esm2022/lib/core/general-master-management/services/general-master.service.mjs +0 -166
  28. package/esm2022/lib/core/grade-level-management/components/grade-level-list/grade-level-list.component.mjs +0 -794
  29. package/esm2022/lib/core/grade-level-management/index.mjs +0 -5
  30. package/esm2022/lib/core/grade-level-management/services/grade-level-management.service.mjs +0 -172
  31. package/esm2022/lib/core/menu-management/components/menu-list/menu-list.component.mjs +0 -1135
  32. package/esm2022/lib/core/menu-management/index.mjs +0 -10
  33. package/esm2022/lib/core/menu-management/interfaces/menu-item.interface.mjs +0 -11
  34. package/esm2022/lib/core/menu-management/mock-data/menu-items.json +0 -311
  35. package/esm2022/lib/core/menu-management/services/menu-management.service.mjs +0 -230
  36. package/esm2022/lib/core/page-management/components/page-controls/page-controls.component.mjs +0 -483
  37. package/esm2022/lib/core/page-management/components/page-form/page-form.component.mjs +0 -212
  38. package/esm2022/lib/core/page-management/components/page-list/page-list.component.mjs +0 -393
  39. package/esm2022/lib/core/page-management/components/page-theme/page-theme.component.mjs +0 -767
  40. package/esm2022/lib/core/page-management/index.mjs +0 -10
  41. package/esm2022/lib/core/page-management/services/page-controls.service.mjs +0 -136
  42. package/esm2022/lib/core/page-management/services/page-management.service.mjs +0 -98
  43. package/esm2022/lib/core/page-management/services/page-theme.service.mjs +0 -107
  44. package/esm2022/public-api.mjs +0 -17
  45. package/lib/cloud-ide-core.component.d.ts +0 -5
  46. package/lib/cloud-ide-core.routes.d.ts +0 -2
  47. package/lib/cloud-ide-core.service.d.ts +0 -6
  48. package/lib/core/department-management/components/department-list/department-list.component.d.ts +0 -178
  49. package/lib/core/department-management/index.d.ts +0 -2
  50. package/lib/core/department-management/services/department-management.service.d.ts +0 -68
  51. package/lib/core/designation-management/components/designation-list/designation-list.component.d.ts +0 -242
  52. package/lib/core/designation-management/index.d.ts +0 -2
  53. package/lib/core/designation-management/services/designation-management.service.d.ts +0 -69
  54. package/lib/core/general-master-management/components/general-master/general-master.component.d.ts +0 -167
  55. package/lib/core/general-master-management/components/general-master-type/general-master-type.component.d.ts +0 -129
  56. package/lib/core/general-master-management/services/general-master-type.service.d.ts +0 -75
  57. package/lib/core/general-master-management/services/general-master.service.d.ts +0 -62
  58. package/lib/core/grade-level-management/components/grade-level-list/grade-level-list.component.d.ts +0 -199
  59. package/lib/core/grade-level-management/index.d.ts +0 -2
  60. package/lib/core/grade-level-management/services/grade-level-management.service.d.ts +0 -69
  61. package/lib/core/menu-management/components/menu-list/menu-list.component.d.ts +0 -278
  62. package/lib/core/menu-management/index.d.ts +0 -3
  63. package/lib/core/menu-management/interfaces/menu-item.interface.d.ts +0 -30
  64. package/lib/core/menu-management/services/menu-management.service.d.ts +0 -85
  65. package/lib/core/page-management/components/page-controls/page-controls.component.d.ts +0 -126
  66. package/lib/core/page-management/components/page-form/page-form.component.d.ts +0 -35
  67. package/lib/core/page-management/components/page-list/page-list.component.d.ts +0 -91
  68. package/lib/core/page-management/components/page-theme/page-theme.component.d.ts +0 -189
  69. package/lib/core/page-management/index.d.ts +0 -6
  70. package/lib/core/page-management/services/page-controls.service.d.ts +0 -54
  71. package/lib/core/page-management/services/page-management.service.d.ts +0 -42
  72. package/lib/core/page-management/services/page-theme.service.d.ts +0 -43
  73. package/public-api.d.ts +0 -8
@@ -60,7 +60,7 @@ const coreRoutes = [
60
60
  },
61
61
  {
62
62
  path: 'page-form',
63
- loadComponent: () => import('./cloud-ide-core-page-form.component-CaEca3mB.mjs').then(c => c.PageFormComponent),
63
+ loadComponent: () => import('./cloud-ide-core-page-form.component-vfE-LkTS.mjs').then(c => c.PageFormComponent),
64
64
  title: 'Page Form',
65
65
  data: {
66
66
  reuseTab: true,
@@ -69,7 +69,7 @@ const coreRoutes = [
69
69
  },
70
70
  {
71
71
  path: 'page-form/:query',
72
- loadComponent: () => import('./cloud-ide-core-page-form.component-CaEca3mB.mjs').then(c => c.PageFormComponent),
72
+ loadComponent: () => import('./cloud-ide-core-page-form.component-vfE-LkTS.mjs').then(c => c.PageFormComponent),
73
73
  title: 'Page Form',
74
74
  data: {
75
75
  reuseTab: true,
@@ -114,7 +114,7 @@ const coreRoutes = [
114
114
  },
115
115
  {
116
116
  path: 'general_master_entry',
117
- loadComponent: () => import('./cloud-ide-core-general-master.component-B6llTVoV.mjs').then(c => c.GeneralMasterComponent),
117
+ loadComponent: () => import('./cloud-ide-core-general-master.component-CFGGHinl.mjs').then(c => c.GeneralMasterComponent),
118
118
  title: 'General Master Entry',
119
119
  data: {
120
120
  reuseTab: true,
@@ -123,7 +123,7 @@ const coreRoutes = [
123
123
  },
124
124
  {
125
125
  path: 'general_master_entry/:query',
126
- loadComponent: () => import('./cloud-ide-core-general-master.component-B6llTVoV.mjs').then(c => c.GeneralMasterComponent),
126
+ loadComponent: () => import('./cloud-ide-core-general-master.component-CFGGHinl.mjs').then(c => c.GeneralMasterComponent),
127
127
  title: 'General Master Entry',
128
128
  data: {
129
129
  reuseTab: true,
@@ -132,7 +132,7 @@ const coreRoutes = [
132
132
  },
133
133
  {
134
134
  path: 'general_type_entry',
135
- loadComponent: () => import('./cloud-ide-core-general-master-type.component-B26auJZw.mjs').then(c => c.GeneralMasterTypeComponent),
135
+ loadComponent: () => import('./cloud-ide-core-general-master-type.component-BNYoP_bS.mjs').then(c => c.GeneralMasterTypeComponent),
136
136
  title: 'General Type Entry',
137
137
  data: {
138
138
  reuseTab: true,
@@ -141,7 +141,7 @@ const coreRoutes = [
141
141
  },
142
142
  {
143
143
  path: 'general_type_entry/:query',
144
- loadComponent: () => import('./cloud-ide-core-general-master-type.component-B26auJZw.mjs').then(c => c.GeneralMasterTypeComponent),
144
+ loadComponent: () => import('./cloud-ide-core-general-master-type.component-BNYoP_bS.mjs').then(c => c.GeneralMasterTypeComponent),
145
145
  title: 'General Type Entry',
146
146
  data: {
147
147
  reuseTab: true,
@@ -152,10 +152,10 @@ const coreRoutes = [
152
152
 
153
153
  class CloudIdeCoreService {
154
154
  constructor() { }
155
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: CloudIdeCoreService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
156
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: CloudIdeCoreService, providedIn: 'root' }); }
155
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CloudIdeCoreService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
156
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CloudIdeCoreService, providedIn: 'root' });
157
157
  }
158
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: CloudIdeCoreService, decorators: [{
158
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CloudIdeCoreService, decorators: [{
159
159
  type: Injectable,
160
160
  args: [{
161
161
  providedIn: 'root'
@@ -163,14 +163,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImpor
163
163
  }], ctorParameters: () => [] });
164
164
 
165
165
  class CloudIdeCoreComponent {
166
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: CloudIdeCoreComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
167
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.7", type: CloudIdeCoreComponent, isStandalone: true, selector: "cide-core", ngImport: i0, template: `
166
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CloudIdeCoreComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
167
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.7", type: CloudIdeCoreComponent, isStandalone: true, selector: "cide-core", ngImport: i0, template: `
168
168
  <p>
169
169
  cloud-ide-core works!
170
170
  </p>
171
- `, isInline: true, styles: [""] }); }
171
+ `, isInline: true, styles: [""] });
172
172
  }
173
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: CloudIdeCoreComponent, decorators: [{
173
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CloudIdeCoreComponent, decorators: [{
174
174
  type: Component,
175
175
  args: [{ selector: 'cide-core', standalone: true, imports: [], template: `
176
176
  <p>
@@ -496,11 +496,12 @@ var mockMenuData = {
496
496
  };
497
497
 
498
498
  class MenuManagementService {
499
+ http;
500
+ apiUrl = `${coreRoutesUrl?.getSidebarMenues}`;
501
+ menuListSubject = new BehaviorSubject([]);
502
+ menuList$ = this.menuListSubject.asObservable();
499
503
  constructor(http) {
500
504
  this.http = http;
501
- this.apiUrl = `${coreRoutesUrl?.getSidebarMenues}`;
502
- this.menuListSubject = new BehaviorSubject([]);
503
- this.menuList$ = this.menuListSubject.asObservable();
504
505
  console.log('MenuManagementService initialized - using real API');
505
506
  }
506
507
  /**
@@ -708,10 +709,10 @@ class MenuManagementService {
708
709
  console.error('Menu Management Service Error:', errorMessage);
709
710
  return throwError(() => new Error(errorMessage));
710
711
  }
711
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: MenuManagementService, deps: [{ token: i1.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable }); }
712
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: MenuManagementService, providedIn: 'root' }); }
712
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: MenuManagementService, deps: [{ token: i1.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable });
713
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: MenuManagementService, providedIn: 'root' });
713
714
  }
714
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: MenuManagementService, decorators: [{
715
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: MenuManagementService, decorators: [{
715
716
  type: Injectable,
716
717
  args: [{
717
718
  providedIn: 'root'
@@ -719,6 +720,188 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImpor
719
720
  }], ctorParameters: () => [{ type: i1.HttpClient }] });
720
721
 
721
722
  class MenuListComponent {
723
+ // Dependency injection
724
+ destroyRef = inject(DestroyRef);
725
+ menuService = inject(MenuManagementService);
726
+ fb = inject(NonNullableFormBuilder);
727
+ router = inject(Router);
728
+ // Modern ViewChild signals for template renderers (Angular 20 approach)
729
+ menuDetailsRendererTemplate = viewChild.required('menuDetailsRendererTemplate');
730
+ menuTypeRendererTemplate = viewChild.required('menuTypeRendererTemplate');
731
+ actionsDropdownRendererTemplate = viewChild.required('actionsDropdownRendererTemplate');
732
+ // Make Math available in template
733
+ Math = Math;
734
+ // Signals for reactive state management
735
+ menuItems = signal([], ...(ngDevMode ? [{ debugName: "menuItems" }] : []));
736
+ loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
737
+ error = signal(null, ...(ngDevMode ? [{ debugName: "error" }] : []));
738
+ selectedItems = signal([], ...(ngDevMode ? [{ debugName: "selectedItems" }] : []));
739
+ searchTerm = signal('', ...(ngDevMode ? [{ debugName: "searchTerm" }] : []));
740
+ // Modern reactive forms with signals
741
+ selectedParentItem = signal(null, ...(ngDevMode ? [{ debugName: "selectedParentItem" }] : []));
742
+ // Retrieved menu item data
743
+ retrievedMenuItem = signal(null, ...(ngDevMode ? [{ debugName: "retrievedMenuItem" }] : []));
744
+ // Edit mode flag
745
+ isEditMode = signal(false, ...(ngDevMode ? [{ debugName: "isEditMode" }] : []));
746
+ // Drag order management
747
+ originalOrder = signal([], ...(ngDevMode ? [{ debugName: "originalOrder" }] : []));
748
+ hasOrderChanged = signal(false, ...(ngDevMode ? [{ debugName: "hasOrderChanged" }] : []));
749
+ // Server-side pagination state
750
+ currentPage = signal(1, ...(ngDevMode ? [{ debugName: "currentPage" }] : []));
751
+ pageSize = signal(10, ...(ngDevMode ? [{ debugName: "pageSize" }] : []));
752
+ totalItems = signal(0, ...(ngDevMode ? [{ debugName: "totalItems" }] : []));
753
+ // Modern reactive form with typed controls
754
+ quickAddForm = this.fb.group({
755
+ syme_title: this.fb.control('', [Validators.required, Validators.minLength(2), Validators.maxLength(100)]),
756
+ syme_desc: this.fb.control('', [Validators.maxLength(255)]),
757
+ syme_type: this.fb.control('module', [Validators.required]),
758
+ syme_id_syme: this.fb.control(''),
759
+ syme_path: this.fb.control('', [Validators.maxLength(255)]),
760
+ syme_icon: this.fb.control('', [Validators.maxLength(50)]),
761
+ syme_link: this.fb.control('', [Validators.maxLength(255)]),
762
+ syme_isactive: this.fb.control(true, [Validators.required]),
763
+ syme_order_by: this.fb.control(1, [Validators.required, Validators.min(1)])
764
+ });
765
+ // Menu type options for quick add - dynamic based on parent selection
766
+ menuTypeOptions = computed(() => {
767
+ if (this.selectedParentItem()) {
768
+ // When parent is selected, allow creating child types only
769
+ return [
770
+ { value: 'section', label: 'Section' },
771
+ { value: 'menu', label: 'Menu Item' },
772
+ { value: 'title', label: 'Title' }
773
+ ];
774
+ }
775
+ else {
776
+ // When no parent is selected, only allow module creation
777
+ return [
778
+ { value: 'module', label: 'Module' }
779
+ ];
780
+ }
781
+ }, ...(ngDevMode ? [{ debugName: "menuTypeOptions" }] : []));
782
+ // Grid configuration signal
783
+ gridConfig = signal({
784
+ id: 'menu-list-grid',
785
+ title: '',
786
+ subtitle: '',
787
+ columns: [
788
+ {
789
+ key: 'details',
790
+ header: 'Menu Item',
791
+ type: 'custom',
792
+ width: 'auto',
793
+ truncate: true,
794
+ align: 'left',
795
+ renderer: 'menuDetailsRenderer'
796
+ },
797
+ {
798
+ key: 'syme_type',
799
+ header: 'Type',
800
+ type: 'custom',
801
+ width: '120px',
802
+ truncate: false,
803
+ align: 'center',
804
+ renderer: 'menuTypeRenderer'
805
+ },
806
+ {
807
+ key: 'syme_path',
808
+ header: 'Path',
809
+ type: 'text',
810
+ width: '200px',
811
+ truncate: true,
812
+ align: 'left'
813
+ },
814
+ {
815
+ key: 'syme_order_by',
816
+ header: 'Order',
817
+ type: 'order',
818
+ width: '80px',
819
+ truncate: false,
820
+ align: 'center'
821
+ },
822
+ {
823
+ key: 'syme_isactive',
824
+ header: 'Status',
825
+ type: 'status',
826
+ width: '100px',
827
+ truncate: false,
828
+ align: 'center',
829
+ statusConfig: {
830
+ activeValue: true,
831
+ activeLabel: 'Active',
832
+ inactiveLabel: 'Inactive',
833
+ activeClass: 'tw-bg-green-100 tw-text-green-800',
834
+ inactiveClass: 'tw-bg-red-100 tw-text-red-800'
835
+ }
836
+ },
837
+ {
838
+ key: 'actions',
839
+ header: '',
840
+ type: 'custom',
841
+ width: '60px',
842
+ truncate: false,
843
+ align: 'center',
844
+ renderer: 'actionsDropdownRenderer'
845
+ }
846
+ ],
847
+ data: [],
848
+ trackBy: '_id',
849
+ pagination: {
850
+ enabled: true,
851
+ pageSize: 10,
852
+ pageSizeOptions: [10, 25, 50, 100],
853
+ showQuickJump: true,
854
+ showPageInfo: true,
855
+ showRefresh: true
856
+ },
857
+ search: {
858
+ enabled: true,
859
+ placeholder: 'Search menu items...',
860
+ searchableColumns: ['syme_title', 'syme_desc', 'syme_path'],
861
+ debounceMs: 300
862
+ },
863
+ loading: {
864
+ useDefer: true,
865
+ skeletonRows: 5,
866
+ showOverlay: false
867
+ },
868
+ scroll: {
869
+ enabled: true,
870
+ maxHeight: '',
871
+ minHeight: '',
872
+ stickyHeader: true,
873
+ virtualScroll: false,
874
+ rowHeight: 50
875
+ },
876
+ dragDrop: {
877
+ enabled: true,
878
+ orderField: 'syme_order_by',
879
+ dragClass: 'tw-opacity-50 tw-bg-blue-50',
880
+ dropClass: 'tw-bg-green-50'
881
+ },
882
+ responsive: true,
883
+ striped: false,
884
+ bordered: true,
885
+ compact: false,
886
+ tableClass: 'tw-table-fixed tw-w-full tw-rounded-none',
887
+ onRefresh: 'onMenuItemRefresh',
888
+ onRowReorder: 'onRowReorder',
889
+ tree: {
890
+ enabled: true,
891
+ primaryKey: '_id',
892
+ foreignKey: 'syme_id_syme',
893
+ childrenKey: 'children',
894
+ levelKey: 'level',
895
+ expandedKey: 'isExpanded',
896
+ hasChildrenKey: 'hasChildren'
897
+ }
898
+ }, ...(ngDevMode ? [{ debugName: "gridConfig" }] : []));
899
+ // Template renderers using Angular best practices
900
+ templateRenderers = computed(() => ({
901
+ menuDetailsRenderer: this.menuDetailsRendererTemplate(),
902
+ menuTypeRenderer: this.menuTypeRendererTemplate(),
903
+ actionsDropdownRenderer: this.actionsDropdownRendererTemplate()
904
+ }), ...(ngDevMode ? [{ debugName: "templateRenderers" }] : []));
722
905
  /**
723
906
  * Get template renderers for data grid
724
907
  * These templates are available for enhanced data grid components
@@ -726,6 +909,10 @@ class MenuListComponent {
726
909
  getTemplateRenderers() {
727
910
  return this.templateRenderers();
728
911
  }
912
+ // Mixed renderers (templates + string functions)
913
+ customRenderers = computed(() => ({
914
+ ...this.templateRenderers()
915
+ }), ...(ngDevMode ? [{ debugName: "customRenderers" }] : []));
729
916
  /**
730
917
  * Get custom renderers adapted for current data grid compatibility
731
918
  * Uses template-based renderers converted to string functions
@@ -734,216 +921,24 @@ class MenuListComponent {
734
921
  // This method is no longer needed since we're using templates directly
735
922
  return {};
736
923
  }
924
+ // Action handlers for grid actions
925
+ actionHandlers = {
926
+ onEditMenuItem: (row) => this.editMenuItem(row._id || ''),
927
+ onToggleMenuItem: (row) => this.toggleItemStatus(row._id || ''),
928
+ onDeleteMenuItem: (row) => this.deleteMenuItem(row._id || ''),
929
+ onMenuItemRowClick: (row) => this.onMenuItemRowClick(row),
930
+ onMenuItemRefresh: () => this.onMenuItemRefresh(),
931
+ onAddChild: (row) => this.onAddChild(row),
932
+ resetOrder: () => this.resetDragOrder(),
933
+ saveOrder: () => this.saveMenuOrder()
934
+ };
935
+ hasSelection = computed(() => this.selectedItems().length > 0, ...(ngDevMode ? [{ debugName: "hasSelection" }] : []));
936
+ // Pagination computed properties
937
+ totalPages = computed(() => Math.ceil(this.totalItems() / this.pageSize()), ...(ngDevMode ? [{ debugName: "totalPages" }] : []));
938
+ hasNextPage = computed(() => this.currentPage() < this.totalPages(), ...(ngDevMode ? [{ debugName: "hasNextPage" }] : []));
939
+ hasPreviousPage = computed(() => this.currentPage() > 1, ...(ngDevMode ? [{ debugName: "hasPreviousPage" }] : []));
737
940
  // Modern constructor with effects for initialization
738
941
  constructor() {
739
- // Dependency injection
740
- this.destroyRef = inject(DestroyRef);
741
- this.menuService = inject(MenuManagementService);
742
- this.fb = inject(NonNullableFormBuilder);
743
- this.router = inject(Router);
744
- // Modern ViewChild signals for template renderers (Angular 20 approach)
745
- this.menuDetailsRendererTemplate = viewChild.required('menuDetailsRendererTemplate');
746
- this.menuTypeRendererTemplate = viewChild.required('menuTypeRendererTemplate');
747
- this.actionsDropdownRendererTemplate = viewChild.required('actionsDropdownRendererTemplate');
748
- // Make Math available in template
749
- this.Math = Math;
750
- // Signals for reactive state management
751
- this.menuItems = signal([]);
752
- this.loading = signal(false);
753
- this.error = signal(null);
754
- this.selectedItems = signal([]);
755
- this.searchTerm = signal('');
756
- // Modern reactive forms with signals
757
- this.selectedParentItem = signal(null);
758
- // Retrieved menu item data
759
- this.retrievedMenuItem = signal(null);
760
- // Edit mode flag
761
- this.isEditMode = signal(false);
762
- // Drag order management
763
- this.originalOrder = signal([]);
764
- this.hasOrderChanged = signal(false);
765
- // Server-side pagination state
766
- this.currentPage = signal(1);
767
- this.pageSize = signal(10);
768
- this.totalItems = signal(0);
769
- // Modern reactive form with typed controls
770
- this.quickAddForm = this.fb.group({
771
- syme_title: this.fb.control('', [Validators.required, Validators.minLength(2), Validators.maxLength(100)]),
772
- syme_desc: this.fb.control('', [Validators.maxLength(255)]),
773
- syme_type: this.fb.control('module', [Validators.required]),
774
- syme_id_syme: this.fb.control(''),
775
- syme_path: this.fb.control('', [Validators.maxLength(255)]),
776
- syme_icon: this.fb.control('', [Validators.maxLength(50)]),
777
- syme_link: this.fb.control('', [Validators.maxLength(255)]),
778
- syme_isactive: this.fb.control(true, [Validators.required]),
779
- syme_order_by: this.fb.control(1, [Validators.required, Validators.min(1)])
780
- });
781
- // Menu type options for quick add - dynamic based on parent selection
782
- this.menuTypeOptions = computed(() => {
783
- if (this.selectedParentItem()) {
784
- // When parent is selected, allow creating child types only
785
- return [
786
- { value: 'section', label: 'Section' },
787
- { value: 'menu', label: 'Menu Item' },
788
- { value: 'title', label: 'Title' }
789
- ];
790
- }
791
- else {
792
- // When no parent is selected, only allow module creation
793
- return [
794
- { value: 'module', label: 'Module' }
795
- ];
796
- }
797
- });
798
- // Grid configuration signal
799
- this.gridConfig = signal({
800
- id: 'menu-list-grid',
801
- title: '',
802
- subtitle: '',
803
- columns: [
804
- {
805
- key: 'details',
806
- header: 'Menu Item',
807
- type: 'custom',
808
- width: 'auto',
809
- truncate: true,
810
- align: 'left',
811
- renderer: 'menuDetailsRenderer'
812
- },
813
- {
814
- key: 'syme_type',
815
- header: 'Type',
816
- type: 'custom',
817
- width: '120px',
818
- truncate: false,
819
- align: 'center',
820
- renderer: 'menuTypeRenderer'
821
- },
822
- {
823
- key: 'syme_path',
824
- header: 'Path',
825
- type: 'text',
826
- width: '200px',
827
- truncate: true,
828
- align: 'left'
829
- },
830
- {
831
- key: 'syme_order_by',
832
- header: 'Order',
833
- type: 'order',
834
- width: '80px',
835
- truncate: false,
836
- align: 'center'
837
- },
838
- {
839
- key: 'syme_isactive',
840
- header: 'Status',
841
- type: 'status',
842
- width: '100px',
843
- truncate: false,
844
- align: 'center',
845
- statusConfig: {
846
- activeValue: true,
847
- activeLabel: 'Active',
848
- inactiveLabel: 'Inactive',
849
- activeClass: 'tw-bg-green-100 tw-text-green-800',
850
- inactiveClass: 'tw-bg-red-100 tw-text-red-800'
851
- }
852
- },
853
- {
854
- key: 'actions',
855
- header: '',
856
- type: 'custom',
857
- width: '60px',
858
- truncate: false,
859
- align: 'center',
860
- renderer: 'actionsDropdownRenderer'
861
- }
862
- ],
863
- data: [],
864
- trackBy: '_id',
865
- pagination: {
866
- enabled: true,
867
- pageSize: 10,
868
- pageSizeOptions: [10, 25, 50, 100],
869
- showQuickJump: true,
870
- showPageInfo: true,
871
- showRefresh: true
872
- },
873
- search: {
874
- enabled: true,
875
- placeholder: 'Search menu items...',
876
- searchableColumns: ['syme_title', 'syme_desc', 'syme_path'],
877
- debounceMs: 300
878
- },
879
- loading: {
880
- useDefer: true,
881
- skeletonRows: 5,
882
- showOverlay: false
883
- },
884
- scroll: {
885
- enabled: true,
886
- maxHeight: '',
887
- minHeight: '',
888
- stickyHeader: true,
889
- virtualScroll: false,
890
- rowHeight: 50
891
- },
892
- dragDrop: {
893
- enabled: true,
894
- orderField: 'syme_order_by',
895
- dragClass: 'tw-opacity-50 tw-bg-blue-50',
896
- dropClass: 'tw-bg-green-50'
897
- },
898
- responsive: true,
899
- striped: false,
900
- bordered: true,
901
- compact: false,
902
- tableClass: 'tw-table-fixed tw-w-full tw-rounded-none',
903
- onRefresh: 'onMenuItemRefresh',
904
- onRowReorder: 'onRowReorder',
905
- tree: {
906
- enabled: true,
907
- primaryKey: '_id',
908
- foreignKey: 'syme_id_syme',
909
- childrenKey: 'children',
910
- levelKey: 'level',
911
- expandedKey: 'isExpanded',
912
- hasChildrenKey: 'hasChildren'
913
- }
914
- });
915
- // Template renderers using Angular best practices
916
- this.templateRenderers = computed(() => ({
917
- menuDetailsRenderer: this.menuDetailsRendererTemplate(),
918
- menuTypeRenderer: this.menuTypeRendererTemplate(),
919
- actionsDropdownRenderer: this.actionsDropdownRendererTemplate()
920
- }));
921
- // Mixed renderers (templates + string functions)
922
- this.customRenderers = computed(() => ({
923
- ...this.templateRenderers()
924
- }));
925
- // Action handlers for grid actions
926
- this.actionHandlers = {
927
- onEditMenuItem: (row) => this.editMenuItem(row._id || ''),
928
- onToggleMenuItem: (row) => this.toggleItemStatus(row._id || ''),
929
- onDeleteMenuItem: (row) => this.deleteMenuItem(row._id || ''),
930
- onMenuItemRowClick: (row) => this.onMenuItemRowClick(row),
931
- onMenuItemRefresh: () => this.onMenuItemRefresh(),
932
- onAddChild: (row) => this.onAddChild(row),
933
- resetOrder: () => this.resetDragOrder(),
934
- saveOrder: () => this.saveMenuOrder()
935
- };
936
- this.hasSelection = computed(() => this.selectedItems().length > 0);
937
- // Pagination computed properties
938
- this.totalPages = computed(() => Math.ceil(this.totalItems() / this.pageSize()));
939
- this.hasNextPage = computed(() => this.currentPage() < this.totalPages());
940
- this.hasPreviousPage = computed(() => this.currentPage() > 1);
941
- /**
942
- * Get default type based on parent selection (computed for reactivity)
943
- */
944
- this.getDefaultType = computed(() => {
945
- return this.selectedParentItem() ? 'section' : 'module';
946
- });
947
942
  // Initialize component once on construction
948
943
  this.initializeComponent();
949
944
  // Cleanup effect for event listeners
@@ -984,6 +979,12 @@ class MenuListComponent {
984
979
  window.handleMenuAction = this.handleMenuAction.bind(this);
985
980
  }
986
981
  }
982
+ /**
983
+ * Get default type based on parent selection (computed for reactivity)
984
+ */
985
+ getDefaultType = computed(() => {
986
+ return this.selectedParentItem() ? 'section' : 'module';
987
+ }, ...(ngDevMode ? [{ debugName: "getDefaultType" }] : []));
987
988
  /**
988
989
  * Load menu items from service
989
990
  */
@@ -1824,10 +1825,10 @@ class MenuListComponent {
1824
1825
  this.updateGridData(testData);
1825
1826
  console.log('✅ Test data loaded successfully');
1826
1827
  }
1827
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: MenuListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1828
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.7", type: MenuListComponent, isStandalone: true, selector: "cide-core-app-menu-list", viewQueries: [{ propertyName: "menuDetailsRendererTemplate", first: true, predicate: ["menuDetailsRendererTemplate"], descendants: true, isSignal: true }, { propertyName: "menuTypeRendererTemplate", first: true, predicate: ["menuTypeRendererTemplate"], descendants: true, isSignal: true }, { propertyName: "actionsDropdownRendererTemplate", first: true, predicate: ["actionsDropdownRendererTemplate"], descendants: true, isSignal: true }], ngImport: i0, template: "<!-- Menu List Container -->\n<div class=\"tw-table tw-w-full tw-h-full\">\n\n <!-- Quick Add Form Section -->\n <div class=\"tw-table-row tw-h-0\">\n <div class=\"tw-table-cell tw-px-6 tw-py-4 tw-border-b tw-border-gray-200 tw-bg-white\">\n <div class=\"tw-flex tw-items-center tw-justify-between tw-mb-3\">\n <div class=\"tw-flex tw-items-center tw-space-x-3\">\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-5 tw-h-5\">{{ isEditMode() ? 'edit' : 'add' }}</cide-ele-icon>\n <h6 class=\"tw-text-sm tw-font-medium tw-text-gray-900 tw-m-0\">{{ isEditMode() ? 'Edit Menu Item' : 'Quick Add Menu Item' }}</h6>\n </div>\n @if (selectedParentItem()) {\n <div class=\"tw-flex tw-items-center tw-space-x-3 tw-bg-blue-50 tw-border tw-border-blue-200 tw-px-4 tw-py-2 tw-rounded-lg\">\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-4 tw-h-4\">account_tree</cide-ele-icon>\n <div class=\"tw-flex tw-items-center tw-space-x-2\">\n <span class=\"tw-text-sm tw-text-blue-600 tw-font-medium\">{{ isEditMode() ? 'Parent:' : 'Creating child under:' }}</span>\n <span class=\"tw-text-sm tw-text-blue-800 tw-font-semibold\">{{ selectedParentItem()?.syme_title }}</span>\n </div>\n <button \n cideEleButton \n variant=\"ghost\" \n size=\"xs\" \n type=\"button\" \n (click)=\"clearSelectedParent()\" \n class=\"tw-text-blue-400 hover:tw-text-blue-600\">\n <svg class=\"tw-w-4 tw-h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M6 18L18 6M6 6l12 12\"/>\n </svg>\n </button>\n </div>\n }\n </div>\n \n <form [formGroup]=\"quickAddForm\" (ngSubmit)=\"quickAddMenuItem()\">\n <!-- First Row -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 lg:tw-grid-cols-4 tw-gap-3 tw-mb-3\">\n <!-- Menu Title -->\n <div>\n <cide-ele-input \n id=\"syme_title\" \n label=\"Title\" \n formControlName=\"syme_title\"\n size=\"sm\">\n </cide-ele-input>\n </div>\n \n <!-- Menu Type -->\n <div>\n <cide-ele-select \n label=\"Type*\" \n [options]=\"menuTypeOptions()\" \n formControlName=\"syme_type\"\n placeholder=\"Select type\"\n size=\"sm\">\n </cide-ele-select>\n </div>\n \n <!-- Icon -->\n <div>\n <cide-ele-input \n id=\"quickIcon\" \n type=\"text\"\n label=\"Icon\" \n formControlName=\"syme_icon\"\n placeholder=\"Icon name\"\n size=\"sm\">\n </cide-ele-input>\n </div>\n \n <!-- Active Status -->\n <div class=\"tw-flex tw-flex-col tw-justify-end\">\n <cide-ele-input \n id=\"quickIsActive\"\n type=\"checkbox\"\n label=\"Active\"\n formControlName=\"syme_isactive\"\n size=\"sm\">\n </cide-ele-input>\n </div>\n </div>\n \n <!-- Second Row -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 lg:tw-grid-cols-4 tw-gap-3 tw-items-end\">\n <!-- Description -->\n <div>\n <cide-ele-textarea \n id=\"syme_desc\" \n label=\"Description\" \n formControlName=\"syme_desc\"\n placeholder=\"Menu description\"\n rows=\"2\"\n size=\"sm\">\n </cide-ele-textarea>\n </div>\n \n <!-- Path -->\n <div>\n <cide-ele-input \n id=\"quickPath\" \n type=\"text\"\n label=\"Path\" \n formControlName=\"syme_path\"\n placeholder=\"/path/to/route\"\n size=\"sm\">\n </cide-ele-input>\n </div>\n \n <!-- Link -->\n <div>\n <cide-ele-input \n id=\"quickLink\" \n type=\"text\"\n label=\"Link\" \n formControlName=\"syme_link\"\n placeholder=\"External link\"\n size=\"sm\">\n </cide-ele-input>\n </div>\n \n <!-- Action Buttons -->\n <div class=\"tw-flex tw-flex-col tw-justify-end\">\n <div class=\"tw-flex tw-space-x-2\">\n <button \n cideEleButton \n variant=\"primary\" \n size=\"sm\" \n type=\"submit\"\n [disabled]=\"quickAddForm.invalid\"\n class=\"tw-px-2 tw-py-1 tw-w-20\">\n <cide-ele-icon size=\"xs\" class=\"tw-w-4 tw-h-4 tw-mr-1\">{{ isEditMode() ? 'edit' : 'add' }}</cide-ele-icon>\n {{ isEditMode() ? 'Update' : 'Add' }}\n </button>\n <button \n cideEleButton \n variant=\"outline\" \n size=\"sm\" \n type=\"button\"\n (click)=\"resetQuickAddForm()\"\n class=\"tw-px-2 tw-py-1 tw-w-16\">\n <cide-ele-icon size=\"xs\" class=\"tw-w-4 tw-h-4 tw-mr-1\">refresh</cide-ele-icon>\n Reset\n </button>\n </div>\n </div>\n </div>\n </form>\n </div>\n </div>\n\n <!-- Header Section with Filters -->\n <div class=\"tw-table-row tw-h-0\">\n <div class=\"tw-table-cell tw-px-6 tw-py-3 tw-border-b tw-border-gray-200 tw-bg-gray-50\">\n <div\n class=\"tw-flex tw-flex-col sm:tw-flex-row tw-justify-between tw-items-start sm:tw-items-center tw-space-y-3 sm:tw-space-y-0\">\n\n <!-- Title -->\n <div class=\"tw-flex tw-items-center tw-space-x-2\">\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-5 tw-h-5\">menu</cide-ele-icon>\n <h5 class=\"tw-text-base tw-font-medium tw-text-gray-900 tw-m-0\">Menu Management</h5>\n </div>\n\n <!-- Actions -->\n <div\n class=\"tw-flex tw-flex-col sm:tw-flex-row tw-items-start sm:tw-items-center tw-space-y-3 sm:tw-space-y-0 sm:tw-space-x-3\">\n <!-- Actions can be added here if needed -->\n </div>\n </div>\n\n <!-- Error Message -->\n @if (error()) {\n <div class=\"tw-mt-4 tw-p-4 tw-bg-red-50 tw-border tw-border-red-200 tw-rounded-md\">\n <div class=\"tw-flex tw-items-start\">\n <cide-ele-icon name=\"error\" class=\"tw-text-red-400 tw-w-5 tw-h-5 tw-mt-0.5 tw-flex-shrink-0\"></cide-ele-icon>\n <div class=\"tw-ml-3\">\n <h3 class=\"tw-text-sm tw-font-medium tw-text-red-800 tw-m-0\">Error</h3>\n <p class=\"tw-text-sm tw-text-red-700 tw-mt-1 tw-m-0\">{{ error() }}</p>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n\n <!-- Main Content Area -->\n <div class=\"tw-table-row\">\n <div class=\"tw-table-cell tw-h-full tw-relative\">\n\n <!-- Debug Information: Uncomment for development -->\n <!--\n <div class=\"tw-p-2 tw-bg-yellow-100 tw-text-xs tw-border-b tw-flex tw-justify-between tw-items-center\">\n <span>Debug: Loading: {{ loading() }} | Items Count: {{ menuItems().length }} | Total: {{ totalItems() }} | Error: {{ error() }}</span>\n <button cideEleButton variant=\"outline\" size=\"xs\" (click)=\"loadTestData()\" class=\"tw-ml-2\">\n Load Test Data\n </button>\n </div>\n -->\n \n <!-- Data Grid Component -->\n <div class=\"tw-h-full tw-overflow-auto\">\n \n <cide-ele-data-grid \n [config]=\"gridConfig()\" \n [templateRenderers]=\"getTemplateRenderers()\"\n [actionHandlers]=\"actionHandlers\"\n [serverSidePagination]=\"true\" \n [totalServerItems]=\"totalItems()\" \n [currentServerPage]=\"currentPage()\"\n [currentServerPageSize]=\"pageSize()\" \n [dragDropEnabled]=\"true\" \n (gridEvent)=\"onGridEvent($event)\">\n </cide-ele-data-grid>\n </div>\n\n\n </div>\n </div>\n\n</div>\n\n<!-- \n Angular Template References for Grid Renderers (Best Practice)\n \n These ng-template elements represent the Angular best practice for custom rendering.\n They provide:\n - Type safety with template context\n - Component lifecycle integration\n - Change detection optimization\n - Proper event handling\n - Accessibility features\n \n Note: Current data grid uses string renderers for compatibility.\n Templates are maintained for future component enhancement.\n-->\n\n\n\n<!-- Menu Details Renderer Template -->\n<ng-template #menuDetailsRendererTemplate let-row=\"row\" let-value=\"value\">\n <div class=\"tw-flex tw-items-center tw-min-w-0\">\n <!-- Menu Icon -->\n <div class=\"tw-flex-shrink-0\">\n <cide-ele-icon \n class=\"tw-text-gray-400\" \n size=\"xs\">\n {{ row.syme_icon || 'folder_open' }}\n </cide-ele-icon>\n </div>\n \n <!-- Menu Details -->\n <div class=\"tw-ml-3 tw-min-w-0 tw-flex-1\">\n <div class=\"tw-text-xs tw-font-medium tw-text-gray-900 tw-truncate\" \n [title]=\"row.syme_title\">\n {{ row.syme_title || 'Untitled' }}\n </div>\n @if (row.syme_desc) {\n <div class=\"tw-text-xs tw-text-gray-500 tw-truncate\" \n [title]=\"row.syme_desc\">\n {{ row.syme_desc }}\n </div>\n }\n </div>\n </div>\n</ng-template>\n\n<!-- Menu Type Renderer Template -->\n<ng-template #menuTypeRendererTemplate let-row=\"row\" let-value=\"value\">\n <span class=\"tw-inline-flex tw-items-center tw-px-2.5 tw-py-0.5 tw-rounded-full tw-text-xs tw-font-medium tw-whitespace-nowrap\"\n [ngClass]=\"getMenuTypeClass(row.syme_type)\">\n {{ getMenuTypeLabel(row.syme_type) }}\n </span>\n</ng-template>\n\n<!-- Actions Dropdown Renderer Template -->\n<ng-template #actionsDropdownRendererTemplate let-row=\"row\" let-value=\"value\">\n <cide-ele-dropdown \n [items]=\"getDropdownItems(row)\"\n [config]=\"{ triggerIcon: 'more_vert', triggerSize: 'sm' }\"\n (itemClick)=\"onDropdownItemClick($event, row)\">\n </cide-ele-dropdown>\n</ng-template>\n\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: FormsModule }, { kind: "component", type: CideEleDataGridComponent, selector: "cide-ele-data-grid", inputs: ["config", "customRenderers", "templateRenderers", "customFormatters", "actionHandlers", "serverSidePagination", "totalServerItems", "currentServerPage", "currentServerPageSize", "dragDropEnabled"], outputs: ["gridEvent"] }, { kind: "component", type: CideEleButtonComponent, selector: "button[cideEleButton], a[cideEleButton]", inputs: ["label", "variant", "size", "type", "shape", "elevation", "disabled", "id", "loading", "fullWidth", "leftIcon", "rightIcon", "customClass", "tooltip", "ariaLabel", "testId", "routerLink", "routerExtras", "preventDoubleClick", "animated"], outputs: ["btnClick", "doubleClick"] }, { kind: "component", type: CideInputComponent, selector: "cide-ele-input", inputs: ["fill", "label", "labelHide", "disabled", "clearInput", "labelPlacement", "labelDir", "placeholder", "leadingIcon", "trailingIcon", "helperText", "helperTextCollapse", "hideHelperAndErrorText", "errorText", "maxlength", "minlength", "required", "autocapitalize", "autocomplete", "type", "width", "id", "ngModel", "option", "min", "max", "size"], outputs: ["ngModelChange"] }, { kind: "component", type: CideSelectComponent, selector: "cide-ele-select", inputs: ["label", "labelHide", "placeholder", "helperText", "errorText", "required", "disabled", "id", "ngModel", "size", "fill", "labelPlacement", "labelDir", "leadingIcon", "trailingIcon", "clearInput", "options", "multiple", "searchable", "showSearchInput", "loading"], outputs: ["ngModelChange", "change", "searchChange"] }, { kind: "component", type: CideTextareaComponent, selector: "cide-ele-textarea", inputs: ["label", "labelHide", "placeholder", "helperText", "errorText", "required", "disabled", "minlength", "maxlength", "rows", "id", "ngModel", "size", "fill", "labelPlacement", "labelDir", "leadingIcon", "trailingIcon", "clearInput"], outputs: ["ngModelChange"] }, { kind: "component", type: CideIconComponent, selector: "cide-ele-icon", inputs: ["size", "type", "toolTip"] }, { kind: "component", type: CideEleDropdownComponent, selector: "cide-ele-dropdown", inputs: ["items", "config", "triggerTemplate", "menuTemplate"], outputs: ["itemClick", "dropdownToggle"] }] }); }
1828
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: MenuListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1829
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.7", type: MenuListComponent, isStandalone: true, selector: "cide-core-app-menu-list", viewQueries: [{ propertyName: "menuDetailsRendererTemplate", first: true, predicate: ["menuDetailsRendererTemplate"], descendants: true, isSignal: true }, { propertyName: "menuTypeRendererTemplate", first: true, predicate: ["menuTypeRendererTemplate"], descendants: true, isSignal: true }, { propertyName: "actionsDropdownRendererTemplate", first: true, predicate: ["actionsDropdownRendererTemplate"], descendants: true, isSignal: true }], ngImport: i0, template: "<!-- Menu List Container -->\n<div class=\"tw-table tw-w-full tw-h-full\">\n\n <!-- Quick Add Form Section -->\n <div class=\"tw-table-row tw-h-0\">\n <div class=\"tw-table-cell tw-px-6 tw-py-4 tw-border-b tw-border-gray-200 tw-bg-white\">\n <div class=\"tw-flex tw-items-center tw-justify-between tw-mb-3\">\n <div class=\"tw-flex tw-items-center tw-space-x-3\">\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-5 tw-h-5\">{{ isEditMode() ? 'edit' : 'add' }}</cide-ele-icon>\n <h6 class=\"tw-text-sm tw-font-medium tw-text-gray-900 tw-m-0\">{{ isEditMode() ? 'Edit Menu Item' : 'Quick Add Menu Item' }}</h6>\n </div>\n @if (selectedParentItem()) {\n <div class=\"tw-flex tw-items-center tw-space-x-3 tw-bg-blue-50 tw-border tw-border-blue-200 tw-px-4 tw-py-2 tw-rounded-lg\">\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-4 tw-h-4\">account_tree</cide-ele-icon>\n <div class=\"tw-flex tw-items-center tw-space-x-2\">\n <span class=\"tw-text-sm tw-text-blue-600 tw-font-medium\">{{ isEditMode() ? 'Parent:' : 'Creating child under:' }}</span>\n <span class=\"tw-text-sm tw-text-blue-800 tw-font-semibold\">{{ selectedParentItem()?.syme_title }}</span>\n </div>\n <button \n cideEleButton \n variant=\"ghost\" \n size=\"xs\" \n type=\"button\" \n (click)=\"clearSelectedParent()\" \n class=\"tw-text-blue-400 hover:tw-text-blue-600\">\n <svg class=\"tw-w-4 tw-h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M6 18L18 6M6 6l12 12\"/>\n </svg>\n </button>\n </div>\n }\n </div>\n \n <form [formGroup]=\"quickAddForm\" (ngSubmit)=\"quickAddMenuItem()\">\n <!-- First Row -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 lg:tw-grid-cols-4 tw-gap-3 tw-mb-3\">\n <!-- Menu Title -->\n <div>\n <cide-ele-input \n id=\"syme_title\" \n label=\"Title\" \n formControlName=\"syme_title\"\n size=\"sm\">\n </cide-ele-input>\n </div>\n \n <!-- Menu Type -->\n <div>\n <cide-ele-select \n label=\"Type*\" \n [options]=\"menuTypeOptions()\" \n formControlName=\"syme_type\"\n placeholder=\"Select type\"\n size=\"sm\">\n </cide-ele-select>\n </div>\n \n <!-- Icon -->\n <div>\n <cide-ele-input \n id=\"quickIcon\" \n type=\"text\"\n label=\"Icon\" \n formControlName=\"syme_icon\"\n placeholder=\"Icon name\"\n size=\"sm\">\n </cide-ele-input>\n </div>\n \n <!-- Active Status -->\n <div class=\"tw-flex tw-flex-col tw-justify-end\">\n <cide-ele-input \n id=\"quickIsActive\"\n type=\"checkbox\"\n label=\"Active\"\n formControlName=\"syme_isactive\"\n size=\"sm\">\n </cide-ele-input>\n </div>\n </div>\n \n <!-- Second Row -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 lg:tw-grid-cols-4 tw-gap-3 tw-items-end\">\n <!-- Description -->\n <div>\n <cide-ele-textarea \n id=\"syme_desc\" \n label=\"Description\" \n formControlName=\"syme_desc\"\n placeholder=\"Menu description\"\n rows=\"2\"\n size=\"sm\">\n </cide-ele-textarea>\n </div>\n \n <!-- Path -->\n <div>\n <cide-ele-input \n id=\"quickPath\" \n type=\"text\"\n label=\"Path\" \n formControlName=\"syme_path\"\n placeholder=\"/path/to/route\"\n size=\"sm\">\n </cide-ele-input>\n </div>\n \n <!-- Link -->\n <div>\n <cide-ele-input \n id=\"quickLink\" \n type=\"text\"\n label=\"Link\" \n formControlName=\"syme_link\"\n placeholder=\"External link\"\n size=\"sm\">\n </cide-ele-input>\n </div>\n \n <!-- Action Buttons -->\n <div class=\"tw-flex tw-flex-col tw-justify-end\">\n <div class=\"tw-flex tw-space-x-2\">\n <button \n cideEleButton \n variant=\"primary\" \n size=\"sm\" \n type=\"submit\"\n [disabled]=\"quickAddForm.invalid\"\n class=\"tw-px-2 tw-py-1 tw-w-20\">\n <cide-ele-icon size=\"xs\" class=\"tw-w-4 tw-h-4 tw-mr-1\">{{ isEditMode() ? 'edit' : 'add' }}</cide-ele-icon>\n {{ isEditMode() ? 'Update' : 'Add' }}\n </button>\n <button \n cideEleButton \n variant=\"outline\" \n size=\"sm\" \n type=\"button\"\n (click)=\"resetQuickAddForm()\"\n class=\"tw-px-2 tw-py-1 tw-w-16\">\n <cide-ele-icon size=\"xs\" class=\"tw-w-4 tw-h-4 tw-mr-1\">refresh</cide-ele-icon>\n Reset\n </button>\n </div>\n </div>\n </div>\n </form>\n </div>\n </div>\n\n <!-- Header Section with Filters -->\n <div class=\"tw-table-row tw-h-0\">\n <div class=\"tw-table-cell tw-px-6 tw-py-3 tw-border-b tw-border-gray-200 tw-bg-gray-50\">\n <div\n class=\"tw-flex tw-flex-col sm:tw-flex-row tw-justify-between tw-items-start sm:tw-items-center tw-space-y-3 sm:tw-space-y-0\">\n\n <!-- Title -->\n <div class=\"tw-flex tw-items-center tw-space-x-2\">\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-5 tw-h-5\">menu</cide-ele-icon>\n <h5 class=\"tw-text-base tw-font-medium tw-text-gray-900 tw-m-0\">Menu Management</h5>\n </div>\n\n <!-- Actions -->\n <div\n class=\"tw-flex tw-flex-col sm:tw-flex-row tw-items-start sm:tw-items-center tw-space-y-3 sm:tw-space-y-0 sm:tw-space-x-3\">\n <!-- Actions can be added here if needed -->\n </div>\n </div>\n\n <!-- Error Message -->\n @if (error()) {\n <div class=\"tw-mt-4 tw-p-4 tw-bg-red-50 tw-border tw-border-red-200 tw-rounded-md\">\n <div class=\"tw-flex tw-items-start\">\n <cide-ele-icon name=\"error\" class=\"tw-text-red-400 tw-w-5 tw-h-5 tw-mt-0.5 tw-flex-shrink-0\"></cide-ele-icon>\n <div class=\"tw-ml-3\">\n <h3 class=\"tw-text-sm tw-font-medium tw-text-red-800 tw-m-0\">Error</h3>\n <p class=\"tw-text-sm tw-text-red-700 tw-mt-1 tw-m-0\">{{ error() }}</p>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n\n <!-- Main Content Area -->\n <div class=\"tw-table-row\">\n <div class=\"tw-table-cell tw-h-full tw-relative\">\n\n <!-- Debug Information: Uncomment for development -->\n <!--\n <div class=\"tw-p-2 tw-bg-yellow-100 tw-text-xs tw-border-b tw-flex tw-justify-between tw-items-center\">\n <span>Debug: Loading: {{ loading() }} | Items Count: {{ menuItems().length }} | Total: {{ totalItems() }} | Error: {{ error() }}</span>\n <button cideEleButton variant=\"outline\" size=\"xs\" (click)=\"loadTestData()\" class=\"tw-ml-2\">\n Load Test Data\n </button>\n </div>\n -->\n \n <!-- Data Grid Component -->\n <div class=\"tw-h-full tw-overflow-auto\">\n \n <cide-ele-data-grid \n [config]=\"gridConfig()\" \n [templateRenderers]=\"getTemplateRenderers()\"\n [actionHandlers]=\"actionHandlers\"\n [serverSidePagination]=\"true\" \n [totalServerItems]=\"totalItems()\" \n [currentServerPage]=\"currentPage()\"\n [currentServerPageSize]=\"pageSize()\" \n [dragDropEnabled]=\"true\" \n (gridEvent)=\"onGridEvent($event)\">\n </cide-ele-data-grid>\n </div>\n\n\n </div>\n </div>\n\n</div>\n\n<!-- \n Angular Template References for Grid Renderers (Best Practice)\n \n These ng-template elements represent the Angular best practice for custom rendering.\n They provide:\n - Type safety with template context\n - Component lifecycle integration\n - Change detection optimization\n - Proper event handling\n - Accessibility features\n \n Note: Current data grid uses string renderers for compatibility.\n Templates are maintained for future component enhancement.\n-->\n\n\n\n<!-- Menu Details Renderer Template -->\n<ng-template #menuDetailsRendererTemplate let-row=\"row\" let-value=\"value\">\n <div class=\"tw-flex tw-items-center tw-min-w-0\">\n <!-- Menu Icon -->\n <div class=\"tw-flex-shrink-0\">\n <cide-ele-icon \n class=\"tw-text-gray-400\" \n size=\"xs\">\n {{ row.syme_icon || 'folder_open' }}\n </cide-ele-icon>\n </div>\n \n <!-- Menu Details -->\n <div class=\"tw-ml-3 tw-min-w-0 tw-flex-1\">\n <div class=\"tw-text-xs tw-font-medium tw-text-gray-900 tw-truncate\" \n [title]=\"row.syme_title\">\n {{ row.syme_title || 'Untitled' }}\n </div>\n @if (row.syme_desc) {\n <div class=\"tw-text-xs tw-text-gray-500 tw-truncate\" \n [title]=\"row.syme_desc\">\n {{ row.syme_desc }}\n </div>\n }\n </div>\n </div>\n</ng-template>\n\n<!-- Menu Type Renderer Template -->\n<ng-template #menuTypeRendererTemplate let-row=\"row\" let-value=\"value\">\n <span class=\"tw-inline-flex tw-items-center tw-px-2.5 tw-py-0.5 tw-rounded-full tw-text-xs tw-font-medium tw-whitespace-nowrap\"\n [ngClass]=\"getMenuTypeClass(row.syme_type)\">\n {{ getMenuTypeLabel(row.syme_type) }}\n </span>\n</ng-template>\n\n<!-- Actions Dropdown Renderer Template -->\n<ng-template #actionsDropdownRendererTemplate let-row=\"row\" let-value=\"value\">\n <cide-ele-dropdown \n [items]=\"getDropdownItems(row)\"\n [config]=\"{ triggerIcon: 'more_vert', triggerSize: 'sm' }\"\n (itemClick)=\"onDropdownItemClick($event, row)\">\n </cide-ele-dropdown>\n</ng-template>\n\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: FormsModule }, { kind: "component", type: CideEleDataGridComponent, selector: "cide-ele-data-grid", inputs: ["config", "customRenderers", "templateRenderers", "customFormatters", "actionHandlers", "serverSidePagination", "totalServerItems", "currentServerPage", "currentServerPageSize", "dragDropEnabled"], outputs: ["gridEvent"] }, { kind: "component", type: CideEleButtonComponent, selector: "button[cideEleButton], a[cideEleButton]", inputs: ["label", "variant", "size", "type", "shape", "elevation", "disabled", "id", "loading", "fullWidth", "leftIcon", "rightIcon", "customClass", "tooltip", "ariaLabel", "testId", "routerLink", "routerExtras", "preventDoubleClick", "animated"], outputs: ["btnClick", "doubleClick"] }, { kind: "component", type: CideInputComponent, selector: "cide-ele-input", inputs: ["fill", "label", "labelHide", "disabled", "clearInput", "labelPlacement", "labelDir", "placeholder", "leadingIcon", "trailingIcon", "helperText", "helperTextCollapse", "hideHelperAndErrorText", "errorText", "maxlength", "minlength", "required", "autocapitalize", "autocomplete", "type", "width", "id", "ngModel", "option", "min", "max", "size"], outputs: ["ngModelChange"] }, { kind: "component", type: CideSelectComponent, selector: "cide-ele-select", inputs: ["label", "labelHide", "placeholder", "helperText", "errorText", "required", "disabled", "id", "ngModel", "size", "fill", "labelPlacement", "labelDir", "leadingIcon", "trailingIcon", "clearInput", "options", "multiple", "searchable", "showSearchInput", "loading"], outputs: ["ngModelChange", "change", "searchChange"] }, { kind: "component", type: CideTextareaComponent, selector: "cide-ele-textarea", inputs: ["label", "labelHide", "placeholder", "helperText", "errorText", "required", "disabled", "minlength", "maxlength", "rows", "id", "ngModel", "size", "fill", "labelPlacement", "labelDir", "leadingIcon", "trailingIcon", "clearInput"], outputs: ["ngModelChange"] }, { kind: "component", type: CideIconComponent, selector: "cide-ele-icon", inputs: ["size", "type", "toolTip"] }, { kind: "component", type: CideEleDropdownComponent, selector: "cide-ele-dropdown", inputs: ["items", "config", "triggerTemplate", "menuTemplate"], outputs: ["itemClick", "dropdownToggle"] }] });
1829
1830
  }
1830
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: MenuListComponent, decorators: [{
1831
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: MenuListComponent, decorators: [{
1831
1832
  type: Component,
1832
1833
  args: [{ selector: 'cide-core-app-menu-list', standalone: true, imports: [
1833
1834
  CommonModule,
@@ -1865,10 +1866,11 @@ const MENU_TYPES = [
1865
1866
  // Components
1866
1867
 
1867
1868
  class DepartmentManagementService {
1869
+ http;
1870
+ departmentListSubject = new BehaviorSubject([]);
1871
+ departmentList$ = this.departmentListSubject.asObservable();
1868
1872
  constructor(http) {
1869
1873
  this.http = http;
1870
- this.departmentListSubject = new BehaviorSubject([]);
1871
- this.departmentList$ = this.departmentListSubject.asObservable();
1872
1874
  console.log('DepartmentManagementService initialized - using real API');
1873
1875
  }
1874
1876
  /**
@@ -2035,10 +2037,10 @@ class DepartmentManagementService {
2035
2037
  console.error('Department Management Service Error:', errorMessage);
2036
2038
  return throwError(() => new Error(errorMessage));
2037
2039
  }
2038
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: DepartmentManagementService, deps: [{ token: i1.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable }); }
2039
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: DepartmentManagementService, providedIn: 'root' }); }
2040
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: DepartmentManagementService, deps: [{ token: i1.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable });
2041
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: DepartmentManagementService, providedIn: 'root' });
2040
2042
  }
2041
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: DepartmentManagementService, decorators: [{
2043
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: DepartmentManagementService, decorators: [{
2042
2044
  type: Injectable,
2043
2045
  args: [{
2044
2046
  providedIn: 'root'
@@ -2046,182 +2048,182 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImpor
2046
2048
  }], ctorParameters: () => [{ type: i1.HttpClient }] });
2047
2049
 
2048
2050
  class DepartmentListComponent {
2051
+ // Dependency injection
2052
+ destroyRef = inject(DestroyRef);
2053
+ departmentService = inject(DepartmentManagementService);
2054
+ appState = inject(AppStateHelperService);
2055
+ fb = inject(NonNullableFormBuilder);
2056
+ router = inject(Router);
2057
+ confirmationService = inject(ConfirmationService);
2058
+ notificationService = inject(NotificationService);
2059
+ // Modern ViewChild signals for template renderers (Angular 20 approach)
2060
+ departmentDetailsRendererTemplate = viewChild.required('departmentDetailsRendererTemplate');
2061
+ departmentStatusRendererTemplate = viewChild.required('departmentStatusRendererTemplate');
2062
+ actionsDropdownRendererTemplate = viewChild.required('actionsDropdownRendererTemplate');
2063
+ // Make Math available in template
2064
+ Math = Math;
2065
+ // Signals for reactive state management
2066
+ departments = signal([], ...(ngDevMode ? [{ debugName: "departments" }] : []));
2067
+ loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
2068
+ error = signal(null, ...(ngDevMode ? [{ debugName: "error" }] : []));
2069
+ selectedItems = signal([], ...(ngDevMode ? [{ debugName: "selectedItems" }] : []));
2070
+ searchTerm = signal('', ...(ngDevMode ? [{ debugName: "searchTerm" }] : []));
2071
+ // Modern reactive forms with signals
2072
+ selectedParentDepartment = signal(null, ...(ngDevMode ? [{ debugName: "selectedParentDepartment" }] : []));
2073
+ // Retrieved department data
2074
+ retrievedDepartment = signal(null, ...(ngDevMode ? [{ debugName: "retrievedDepartment" }] : []));
2075
+ // Edit mode flag
2076
+ isEditMode = signal(false, ...(ngDevMode ? [{ debugName: "isEditMode" }] : []));
2077
+ // Server-side pagination state
2078
+ currentPage = signal(1, ...(ngDevMode ? [{ debugName: "currentPage" }] : []));
2079
+ pageSize = signal(10, ...(ngDevMode ? [{ debugName: "pageSize" }] : []));
2080
+ totalItems = signal(0, ...(ngDevMode ? [{ debugName: "totalItems" }] : []));
2081
+ // Modern reactive form with typed controls
2082
+ quickAddForm = this.fb.group({
2083
+ sydept_code: this.fb.control('', []),
2084
+ sydept_name: this.fb.control('', []),
2085
+ sydept_description: this.fb.control('', []),
2086
+ sydept_isactive: this.fb.control(true, []),
2087
+ sydept_department_id_sydept: this.fb.control(''),
2088
+ sydept_entity_id_syen: this.fb.control(this.appState.getActiveEntityId() || '', [])
2089
+ });
2090
+ // Grid configuration signal
2091
+ gridConfig = signal({
2092
+ id: 'department-list-grid',
2093
+ title: '',
2094
+ subtitle: '',
2095
+ columns: [
2096
+ {
2097
+ key: 'details',
2098
+ header: 'Department',
2099
+ type: 'custom',
2100
+ width: 'auto',
2101
+ truncate: true,
2102
+ align: 'left',
2103
+ renderer: 'departmentDetailsRenderer'
2104
+ },
2105
+ {
2106
+ key: 'sydept_code',
2107
+ header: 'Code',
2108
+ type: 'text',
2109
+ width: '120px',
2110
+ truncate: true,
2111
+ align: 'left'
2112
+ },
2113
+ {
2114
+ key: 'sydept_isactive',
2115
+ header: 'Status',
2116
+ type: 'custom',
2117
+ width: '100px',
2118
+ truncate: false,
2119
+ align: 'center',
2120
+ renderer: 'departmentStatusRenderer'
2121
+ },
2122
+ {
2123
+ key: 'actions',
2124
+ header: '',
2125
+ type: 'custom',
2126
+ width: '60px',
2127
+ truncate: false,
2128
+ align: 'center',
2129
+ renderer: 'actionsDropdownRenderer'
2130
+ }
2131
+ ],
2132
+ data: [],
2133
+ tree: {
2134
+ enabled: true,
2135
+ primaryKey: '_id',
2136
+ foreignKey: 'sydept_department_id_sydept',
2137
+ childrenKey: 'children',
2138
+ levelKey: 'level',
2139
+ expandedKey: 'expanded',
2140
+ hasChildrenKey: 'hasChildren'
2141
+ },
2142
+ trackBy: '_id',
2143
+ pagination: {
2144
+ enabled: false,
2145
+ pageSize: 10,
2146
+ pageSizeOptions: [10, 25, 50, 100],
2147
+ showQuickJump: true,
2148
+ showPageInfo: true,
2149
+ showRefresh: true
2150
+ },
2151
+ search: {
2152
+ enabled: true,
2153
+ placeholder: 'Search departments...',
2154
+ searchableColumns: ['sydept_name', 'sydept_code', 'sydept_description'],
2155
+ debounceMs: 300
2156
+ },
2157
+ loading: {
2158
+ useDefer: true,
2159
+ skeletonRows: 5,
2160
+ showOverlay: false
2161
+ },
2162
+ scroll: {
2163
+ enabled: true,
2164
+ maxHeight: '',
2165
+ minHeight: '',
2166
+ stickyHeader: true,
2167
+ virtualScroll: false,
2168
+ rowHeight: 50
2169
+ },
2170
+ responsive: true,
2171
+ striped: false,
2172
+ bordered: true,
2173
+ compact: false,
2174
+ tableClass: 'tw-table-fixed tw-w-full tw-rounded-none',
2175
+ onRefresh: 'onDepartmentRefresh'
2176
+ }, ...(ngDevMode ? [{ debugName: "gridConfig" }] : []));
2177
+ // Template renderers using Angular best practices
2178
+ templateRenderers = computed(() => ({
2179
+ departmentDetailsRenderer: this.departmentDetailsRendererTemplate(),
2180
+ departmentStatusRenderer: this.departmentStatusRendererTemplate(),
2181
+ actionsDropdownRenderer: this.actionsDropdownRendererTemplate()
2182
+ }), ...(ngDevMode ? [{ debugName: "templateRenderers" }] : []));
2049
2183
  /**
2050
2184
  * Get template renderers for data grid
2051
2185
  */
2052
2186
  getTemplateRenderers() {
2053
2187
  return this.templateRenderers();
2054
2188
  }
2189
+ // Mixed renderers (templates + string functions)
2190
+ customRenderers = computed(() => ({
2191
+ ...this.templateRenderers()
2192
+ }), ...(ngDevMode ? [{ debugName: "customRenderers" }] : []));
2055
2193
  /**
2056
2194
  * Get custom renderers adapted for current data grid compatibility
2057
2195
  */
2058
2196
  getCustomRenderers() {
2059
2197
  return {};
2060
2198
  }
2199
+ // Action handlers for grid actions
2200
+ actionHandlers = {
2201
+ onEditDepartment: (row) => this.editDepartment(row._id || ''),
2202
+ onToggleDepartment: (row) => this.toggleDepartmentStatus(row._id || ''),
2203
+ onDeleteDepartment: (row) => this.deleteDepartment(row._id || ''),
2204
+ onDepartmentRowClick: (row) => this.onDepartmentRowClick(row),
2205
+ onDepartmentRefresh: () => this.onDepartmentRefresh(),
2206
+ onAddChild: (row) => this.onAddChild(row)
2207
+ };
2208
+ // Computed properties
2209
+ filteredItems = computed(() => {
2210
+ const items = this.departments();
2211
+ const search = this.searchTerm()?.toLowerCase();
2212
+ if (!search)
2213
+ return items;
2214
+ return items.filter(item => {
2215
+ return item.sydept_name?.toLowerCase().includes(search) ||
2216
+ item.sydept_code?.toLowerCase().includes(search) ||
2217
+ item.sydept_description?.toLowerCase().includes(search);
2218
+ });
2219
+ }, ...(ngDevMode ? [{ debugName: "filteredItems" }] : []));
2220
+ hasSelection = computed(() => this.selectedItems().length > 0, ...(ngDevMode ? [{ debugName: "hasSelection" }] : []));
2221
+ // Pagination computed properties
2222
+ totalPages = computed(() => Math.ceil(this.totalItems() / this.pageSize()), ...(ngDevMode ? [{ debugName: "totalPages" }] : []));
2223
+ hasNextPage = computed(() => this.currentPage() < this.totalPages(), ...(ngDevMode ? [{ debugName: "hasNextPage" }] : []));
2224
+ hasPreviousPage = computed(() => this.currentPage() > 1, ...(ngDevMode ? [{ debugName: "hasPreviousPage" }] : []));
2061
2225
  // Modern constructor with effects for initialization
2062
2226
  constructor() {
2063
- // Dependency injection
2064
- this.destroyRef = inject(DestroyRef);
2065
- this.departmentService = inject(DepartmentManagementService);
2066
- this.appState = inject(AppStateHelperService);
2067
- this.fb = inject(NonNullableFormBuilder);
2068
- this.router = inject(Router);
2069
- this.confirmationService = inject(ConfirmationService);
2070
- this.notificationService = inject(NotificationService);
2071
- // Modern ViewChild signals for template renderers (Angular 20 approach)
2072
- this.departmentDetailsRendererTemplate = viewChild.required('departmentDetailsRendererTemplate');
2073
- this.departmentStatusRendererTemplate = viewChild.required('departmentStatusRendererTemplate');
2074
- this.actionsDropdownRendererTemplate = viewChild.required('actionsDropdownRendererTemplate');
2075
- // Make Math available in template
2076
- this.Math = Math;
2077
- // Signals for reactive state management
2078
- this.departments = signal([]);
2079
- this.loading = signal(false);
2080
- this.error = signal(null);
2081
- this.selectedItems = signal([]);
2082
- this.searchTerm = signal('');
2083
- // Modern reactive forms with signals
2084
- this.selectedParentDepartment = signal(null);
2085
- // Retrieved department data
2086
- this.retrievedDepartment = signal(null);
2087
- // Edit mode flag
2088
- this.isEditMode = signal(false);
2089
- // Server-side pagination state
2090
- this.currentPage = signal(1);
2091
- this.pageSize = signal(10);
2092
- this.totalItems = signal(0);
2093
- // Modern reactive form with typed controls
2094
- this.quickAddForm = this.fb.group({
2095
- sydept_code: this.fb.control('', []),
2096
- sydept_name: this.fb.control('', []),
2097
- sydept_description: this.fb.control('', []),
2098
- sydept_isactive: this.fb.control(true, []),
2099
- sydept_department_id_sydept: this.fb.control(''),
2100
- sydept_entity_id_syen: this.fb.control(this.appState.getActiveEntityId() || '', [])
2101
- });
2102
- // Grid configuration signal
2103
- this.gridConfig = signal({
2104
- id: 'department-list-grid',
2105
- title: '',
2106
- subtitle: '',
2107
- columns: [
2108
- {
2109
- key: 'details',
2110
- header: 'Department',
2111
- type: 'custom',
2112
- width: 'auto',
2113
- truncate: true,
2114
- align: 'left',
2115
- renderer: 'departmentDetailsRenderer'
2116
- },
2117
- {
2118
- key: 'sydept_code',
2119
- header: 'Code',
2120
- type: 'text',
2121
- width: '120px',
2122
- truncate: true,
2123
- align: 'left'
2124
- },
2125
- {
2126
- key: 'sydept_isactive',
2127
- header: 'Status',
2128
- type: 'custom',
2129
- width: '100px',
2130
- truncate: false,
2131
- align: 'center',
2132
- renderer: 'departmentStatusRenderer'
2133
- },
2134
- {
2135
- key: 'actions',
2136
- header: '',
2137
- type: 'custom',
2138
- width: '60px',
2139
- truncate: false,
2140
- align: 'center',
2141
- renderer: 'actionsDropdownRenderer'
2142
- }
2143
- ],
2144
- data: [],
2145
- tree: {
2146
- enabled: true,
2147
- primaryKey: '_id',
2148
- foreignKey: 'sydept_department_id_sydept',
2149
- childrenKey: 'children',
2150
- levelKey: 'level',
2151
- expandedKey: 'expanded',
2152
- hasChildrenKey: 'hasChildren'
2153
- },
2154
- trackBy: '_id',
2155
- pagination: {
2156
- enabled: false,
2157
- pageSize: 10,
2158
- pageSizeOptions: [10, 25, 50, 100],
2159
- showQuickJump: true,
2160
- showPageInfo: true,
2161
- showRefresh: true
2162
- },
2163
- search: {
2164
- enabled: true,
2165
- placeholder: 'Search departments...',
2166
- searchableColumns: ['sydept_name', 'sydept_code', 'sydept_description'],
2167
- debounceMs: 300
2168
- },
2169
- loading: {
2170
- useDefer: true,
2171
- skeletonRows: 5,
2172
- showOverlay: false
2173
- },
2174
- scroll: {
2175
- enabled: true,
2176
- maxHeight: '',
2177
- minHeight: '',
2178
- stickyHeader: true,
2179
- virtualScroll: false,
2180
- rowHeight: 50
2181
- },
2182
- responsive: true,
2183
- striped: false,
2184
- bordered: true,
2185
- compact: false,
2186
- tableClass: 'tw-table-fixed tw-w-full tw-rounded-none',
2187
- onRefresh: 'onDepartmentRefresh'
2188
- });
2189
- // Template renderers using Angular best practices
2190
- this.templateRenderers = computed(() => ({
2191
- departmentDetailsRenderer: this.departmentDetailsRendererTemplate(),
2192
- departmentStatusRenderer: this.departmentStatusRendererTemplate(),
2193
- actionsDropdownRenderer: this.actionsDropdownRendererTemplate()
2194
- }));
2195
- // Mixed renderers (templates + string functions)
2196
- this.customRenderers = computed(() => ({
2197
- ...this.templateRenderers()
2198
- }));
2199
- // Action handlers for grid actions
2200
- this.actionHandlers = {
2201
- onEditDepartment: (row) => this.editDepartment(row._id || ''),
2202
- onToggleDepartment: (row) => this.toggleDepartmentStatus(row._id || ''),
2203
- onDeleteDepartment: (row) => this.deleteDepartment(row._id || ''),
2204
- onDepartmentRowClick: (row) => this.onDepartmentRowClick(row),
2205
- onDepartmentRefresh: () => this.onDepartmentRefresh(),
2206
- onAddChild: (row) => this.onAddChild(row)
2207
- };
2208
- // Computed properties
2209
- this.filteredItems = computed(() => {
2210
- const items = this.departments();
2211
- const search = this.searchTerm()?.toLowerCase();
2212
- if (!search)
2213
- return items;
2214
- return items.filter(item => {
2215
- return item.sydept_name?.toLowerCase().includes(search) ||
2216
- item.sydept_code?.toLowerCase().includes(search) ||
2217
- item.sydept_description?.toLowerCase().includes(search);
2218
- });
2219
- });
2220
- this.hasSelection = computed(() => this.selectedItems().length > 0);
2221
- // Pagination computed properties
2222
- this.totalPages = computed(() => Math.ceil(this.totalItems() / this.pageSize()));
2223
- this.hasNextPage = computed(() => this.currentPage() < this.totalPages());
2224
- this.hasPreviousPage = computed(() => this.currentPage() > 1);
2225
2227
  this.initializeComponent();
2226
2228
  this.destroyRef.onDestroy(() => {
2227
2229
  this.cleanupEventListeners();
@@ -2783,10 +2785,10 @@ class DepartmentListComponent {
2783
2785
  trackByItemId(index, item) {
2784
2786
  return item._id || '';
2785
2787
  }
2786
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: DepartmentListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2787
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.7", type: DepartmentListComponent, isStandalone: true, selector: "cide-core-app-department-list", viewQueries: [{ propertyName: "departmentDetailsRendererTemplate", first: true, predicate: ["departmentDetailsRendererTemplate"], descendants: true, isSignal: true }, { propertyName: "departmentStatusRendererTemplate", first: true, predicate: ["departmentStatusRendererTemplate"], descendants: true, isSignal: true }, { propertyName: "actionsDropdownRendererTemplate", first: true, predicate: ["actionsDropdownRendererTemplate"], descendants: true, isSignal: true }], ngImport: i0, template: "<!-- Department List Container -->\n<div class=\"tw-table tw-w-full tw-h-full\">\n\n<!-- Global Notifications -->\n<cide-ele-global-notifications></cide-ele-global-notifications>\n\n <!-- Quick Add Form Section -->\n <div class=\"tw-table-row tw-h-0\">\n <div class=\"tw-table-cell tw-px-6 tw-py-4 tw-border-b tw-border-gray-200 tw-bg-white\">\n <div class=\"tw-flex tw-items-center tw-justify-between tw-mb-0\">\n <div class=\"tw-flex tw-items-center tw-space-x-3 tw-mb-3\">\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-5 tw-h-5\">{{ isEditMode() ? 'edit' : 'add' }}</cide-ele-icon>\n <h6 class=\"tw-text-sm tw-font-medium tw-text-gray-900 tw-m-0\">{{ isEditMode() ? 'Edit Department' : 'Quick Add Department' }}</h6>\n </div>\n @if (selectedParentDepartment()) {\n <div class=\"tw-flex tw-items-center tw-space-x-3 tw-bg-blue-50 tw-border tw-border-blue-200 tw-px-4 tw-py-1 tw-rounded-lg\">\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-4 tw-h-4\">account_tree</cide-ele-icon>\n <div class=\"tw-flex tw-items-center tw-space-x-2\">\n <span class=\"tw-text-sm tw-text-blue-600 tw-font-medium\">{{ isEditMode() ? 'Parent:' : 'Creating child under:' }}</span>\n <span class=\"tw-text-sm tw-text-blue-800 tw-font-semibold\">{{ selectedParentDepartment()?.sydept_name }}</span>\n </div>\n <button \n cideEleButton \n variant=\"ghost\" \n size=\"xs\" \n type=\"button\" \n (click)=\"clearSelectedParent()\" \n class=\"tw-text-blue-400 hover:tw-text-blue-600\">\n <svg class=\"tw-w-4 tw-h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M6 18L18 6M6 6l12 12\"/>\n </svg>\n </button>\n </div>\n }\n </div>\n \n <form [formGroup]=\"quickAddForm\" (ngSubmit)=\"quickAddDepartment()\">\n <!-- First Row -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 lg:tw-grid-cols-4 tw-gap-3 tw-mb-3\">\n <!-- Department Code -->\n <div>\n <cide-ele-input \n id=\"sydept_code\" \n label=\"Code*\" \n formControlName=\"sydept_code\"\n placeholder=\"DEPT001\"\n size=\"sm\">\n </cide-ele-input>\n </div>\n \n <!-- Department Name -->\n <div>\n <cide-ele-input \n id=\"sydept_name\" \n label=\"Name*\" \n formControlName=\"sydept_name\"\n placeholder=\"Department name\"\n size=\"sm\">\n </cide-ele-input>\n </div>\n \n\n \n <!-- Active Status -->\n <div class=\"tw-flex tw-flex-col tw-justify-end\">\n <cide-ele-input \n id=\"sydept_isactive\"\n type=\"checkbox\"\n label=\"Active\"\n formControlName=\"sydept_isactive\"\n size=\"sm\">\n </cide-ele-input>\n </div>\n </div>\n \n <!-- Second Row -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 lg:tw-grid-cols-4 tw-gap-3 tw-items-end\">\n <!-- Description -->\n <div>\n <cide-ele-textarea \n id=\"sydept_description\" \n label=\"Description\" \n formControlName=\"sydept_description\"\n placeholder=\"Department description\"\n rows=\"2\"\n size=\"sm\">\n </cide-ele-textarea>\n </div>\n \n\n \n <!-- Action Buttons -->\n <div class=\"tw-flex tw-flex-col tw-justify-end\">\n <div class=\"tw-flex tw-space-x-2\">\n <button \n cideEleButton \n variant=\"primary\" \n size=\"sm\" \n type=\"submit\"\n [disabled]=\"quickAddForm.invalid\"\n class=\"tw-px-2 tw-py-1 tw-w-20\">\n <cide-ele-icon size=\"xs\" class=\"tw-w-4 tw-h-4 tw-mr-1\">{{ isEditMode() ? 'edit' : 'add' }}</cide-ele-icon>\n {{ isEditMode() ? 'Update' : 'Add' }}\n </button>\n <button \n cideEleButton \n variant=\"outline\" \n size=\"sm\" \n type=\"button\"\n (click)=\"resetQuickAddForm()\"\n class=\"tw-px-2 tw-py-1 tw-w-16\">\n <cide-ele-icon size=\"xs\" class=\"tw-w-4 tw-h-4 tw-mr-1\">refresh</cide-ele-icon>\n Reset\n </button>\n </div>\n </div>\n </div>\n </form>\n </div>\n </div>\n\n <!-- Header Section with Filters -->\n <div class=\"tw-table-row tw-h-0\">\n <div class=\"tw-table-cell tw-px-6 tw-py-3 tw-border-b tw-border-gray-200 tw-bg-gray-50\">\n <div\n class=\"tw-flex tw-flex-col sm:tw-flex-row tw-justify-between tw-items-start sm:tw-items-center tw-space-y-3 sm:tw-space-y-0\">\n\n <!-- Title -->\n <div class=\"tw-flex tw-items-center tw-space-x-2\">\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-5 tw-h-5\">business</cide-ele-icon>\n <h5 class=\"tw-text-base tw-font-medium tw-text-gray-900 tw-m-0\">Department Management</h5>\n </div>\n\n <!-- Actions -->\n <div\n class=\"tw-flex tw-flex-col sm:tw-flex-row tw-items-start sm:tw-items-center tw-space-y-3 sm:tw-space-y-0 sm:tw-space-x-3\">\n <!-- Search functionality is handled by the data grid -->\n </div>\n </div>\n\n <!-- Error Message -->\n @if (error()) {\n <div class=\"tw-mt-4 tw-p-4 tw-bg-red-50 tw-border tw-border-red-200 tw-rounded-md\">\n <div class=\"tw-flex tw-items-start\">\n <cide-ele-icon name=\"error\" class=\"tw-text-red-400 tw-w-5 tw-h-5 tw-mt-0.5 tw-flex-shrink-0\"></cide-ele-icon>\n <div class=\"tw-ml-3\">\n <h3 class=\"tw-text-sm tw-font-medium tw-text-red-800 tw-m-0\">Error</h3>\n <p class=\"tw-text-sm tw-text-red-700 tw-mt-1 tw-m-0\">{{ error() }}</p>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n\n <!-- Main Content Area -->\n <div class=\"tw-table-row\">\n <div class=\"tw-table-cell tw-h-full tw-relative\">\n \n <!-- Data Grid Component -->\n <div class=\"tw-h-full tw-overflow-auto\">\n \n <cide-ele-data-grid \n [config]=\"gridConfig()\" \n [templateRenderers]=\"getTemplateRenderers()\"\n [actionHandlers]=\"actionHandlers\"\n [serverSidePagination]=\"true\" \n [totalServerItems]=\"totalItems()\" \n [currentServerPage]=\"currentPage()\"\n [currentServerPageSize]=\"pageSize()\" \n (gridEvent)=\"onGridEvent($event)\">\n </cide-ele-data-grid>\n </div>\n\n </div>\n </div>\n\n</div>\n\n<!-- Department Details Renderer Template -->\n<ng-template #departmentDetailsRendererTemplate let-row=\"row\" let-value=\"value\">\n <div class=\"tw-flex tw-items-center tw-min-w-0\">\n <!-- Department Icon -->\n <div class=\"tw-flex-shrink-0\">\n <cide-ele-icon \n class=\"tw-text-gray-400\" \n size=\"xs\">\n business\n </cide-ele-icon>\n </div>\n \n <!-- Department Details -->\n <div class=\"tw-ml-3 tw-min-w-0 tw-flex-1\">\n <div class=\"tw-text-sm tw-font-medium tw-text-gray-900 tw-truncate\" \n [title]=\"row.sydept_name\">\n {{ row.sydept_name || 'Untitled' }}\n </div>\n @if (row.sydept_description) {\n <div class=\"tw-text-xs tw-text-gray-500 tw-truncate\" \n [title]=\"row.sydept_description\">\n {{ row.sydept_description }}\n </div>\n }\n </div>\n </div>\n</ng-template>\n\n<!-- Department Status Renderer Template -->\n<ng-template #departmentStatusRendererTemplate let-row=\"row\" let-value=\"value\">\n <span class=\"tw-inline-flex tw-items-center tw-px-2.5 tw-py-0.5 tw-rounded-full tw-text-xs tw-font-medium tw-whitespace-nowrap\"\n [ngClass]=\"getStatusClass(row.sydept_isactive)\">\n {{ getStatusDisplay(row.sydept_isactive) }}\n </span>\n</ng-template>\n\n<!-- Actions Dropdown Renderer Template -->\n<ng-template #actionsDropdownRendererTemplate let-row=\"row\" let-value=\"value\">\n <cide-ele-dropdown \n [items]=\"getDropdownItems(row)\"\n [config]=\"{ triggerIcon: 'more_vert', triggerSize: 'sm' }\"\n (itemClick)=\"onDropdownItemClick($event, row)\">\n </cide-ele-dropdown>\n</ng-template> ", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: FormsModule }, { kind: "component", type: CideEleDataGridComponent, selector: "cide-ele-data-grid", inputs: ["config", "customRenderers", "templateRenderers", "customFormatters", "actionHandlers", "serverSidePagination", "totalServerItems", "currentServerPage", "currentServerPageSize", "dragDropEnabled"], outputs: ["gridEvent"] }, { kind: "component", type: CideEleButtonComponent, selector: "button[cideEleButton], a[cideEleButton]", inputs: ["label", "variant", "size", "type", "shape", "elevation", "disabled", "id", "loading", "fullWidth", "leftIcon", "rightIcon", "customClass", "tooltip", "ariaLabel", "testId", "routerLink", "routerExtras", "preventDoubleClick", "animated"], outputs: ["btnClick", "doubleClick"] }, { kind: "component", type: CideInputComponent, selector: "cide-ele-input", inputs: ["fill", "label", "labelHide", "disabled", "clearInput", "labelPlacement", "labelDir", "placeholder", "leadingIcon", "trailingIcon", "helperText", "helperTextCollapse", "hideHelperAndErrorText", "errorText", "maxlength", "minlength", "required", "autocapitalize", "autocomplete", "type", "width", "id", "ngModel", "option", "min", "max", "size"], outputs: ["ngModelChange"] }, { kind: "component", type: CideTextareaComponent, selector: "cide-ele-textarea", inputs: ["label", "labelHide", "placeholder", "helperText", "errorText", "required", "disabled", "minlength", "maxlength", "rows", "id", "ngModel", "size", "fill", "labelPlacement", "labelDir", "leadingIcon", "trailingIcon", "clearInput"], outputs: ["ngModelChange"] }, { kind: "component", type: CideIconComponent, selector: "cide-ele-icon", inputs: ["size", "type", "toolTip"] }, { kind: "component", type: CideEleDropdownComponent, selector: "cide-ele-dropdown", inputs: ["items", "config", "triggerTemplate", "menuTemplate"], outputs: ["itemClick", "dropdownToggle"] }, { kind: "component", type: CideEleGlobalNotificationsComponent, selector: "cide-ele-global-notifications" }] }); }
2788
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: DepartmentListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2789
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.7", type: DepartmentListComponent, isStandalone: true, selector: "cide-core-app-department-list", viewQueries: [{ propertyName: "departmentDetailsRendererTemplate", first: true, predicate: ["departmentDetailsRendererTemplate"], descendants: true, isSignal: true }, { propertyName: "departmentStatusRendererTemplate", first: true, predicate: ["departmentStatusRendererTemplate"], descendants: true, isSignal: true }, { propertyName: "actionsDropdownRendererTemplate", first: true, predicate: ["actionsDropdownRendererTemplate"], descendants: true, isSignal: true }], ngImport: i0, template: "<!-- Department List Container -->\n<div class=\"tw-table tw-w-full tw-h-full\">\n\n<!-- Global Notifications -->\n<cide-ele-global-notifications></cide-ele-global-notifications>\n\n <!-- Quick Add Form Section -->\n <div class=\"tw-table-row tw-h-0\">\n <div class=\"tw-table-cell tw-px-6 tw-py-4 tw-border-b tw-border-gray-200 tw-bg-white\">\n <div class=\"tw-flex tw-items-center tw-justify-between tw-mb-0\">\n <div class=\"tw-flex tw-items-center tw-space-x-3 tw-mb-3\">\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-5 tw-h-5\">{{ isEditMode() ? 'edit' : 'add' }}</cide-ele-icon>\n <h6 class=\"tw-text-sm tw-font-medium tw-text-gray-900 tw-m-0\">{{ isEditMode() ? 'Edit Department' : 'Quick Add Department' }}</h6>\n </div>\n @if (selectedParentDepartment()) {\n <div class=\"tw-flex tw-items-center tw-space-x-3 tw-bg-blue-50 tw-border tw-border-blue-200 tw-px-4 tw-py-1 tw-rounded-lg\">\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-4 tw-h-4\">account_tree</cide-ele-icon>\n <div class=\"tw-flex tw-items-center tw-space-x-2\">\n <span class=\"tw-text-sm tw-text-blue-600 tw-font-medium\">{{ isEditMode() ? 'Parent:' : 'Creating child under:' }}</span>\n <span class=\"tw-text-sm tw-text-blue-800 tw-font-semibold\">{{ selectedParentDepartment()?.sydept_name }}</span>\n </div>\n <button \n cideEleButton \n variant=\"ghost\" \n size=\"xs\" \n type=\"button\" \n (click)=\"clearSelectedParent()\" \n class=\"tw-text-blue-400 hover:tw-text-blue-600\">\n <svg class=\"tw-w-4 tw-h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M6 18L18 6M6 6l12 12\"/>\n </svg>\n </button>\n </div>\n }\n </div>\n \n <form [formGroup]=\"quickAddForm\" (ngSubmit)=\"quickAddDepartment()\">\n <!-- First Row -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 lg:tw-grid-cols-4 tw-gap-3 tw-mb-3\">\n <!-- Department Code -->\n <div>\n <cide-ele-input \n id=\"sydept_code\" \n label=\"Code*\" \n formControlName=\"sydept_code\"\n placeholder=\"DEPT001\"\n size=\"sm\">\n </cide-ele-input>\n </div>\n \n <!-- Department Name -->\n <div>\n <cide-ele-input \n id=\"sydept_name\" \n label=\"Name*\" \n formControlName=\"sydept_name\"\n placeholder=\"Department name\"\n size=\"sm\">\n </cide-ele-input>\n </div>\n \n\n \n <!-- Active Status -->\n <div class=\"tw-flex tw-flex-col tw-justify-end\">\n <cide-ele-input \n id=\"sydept_isactive\"\n type=\"checkbox\"\n label=\"Active\"\n formControlName=\"sydept_isactive\"\n size=\"sm\">\n </cide-ele-input>\n </div>\n </div>\n \n <!-- Second Row -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 lg:tw-grid-cols-4 tw-gap-3 tw-items-end\">\n <!-- Description -->\n <div>\n <cide-ele-textarea \n id=\"sydept_description\" \n label=\"Description\" \n formControlName=\"sydept_description\"\n placeholder=\"Department description\"\n rows=\"2\"\n size=\"sm\">\n </cide-ele-textarea>\n </div>\n \n\n \n <!-- Action Buttons -->\n <div class=\"tw-flex tw-flex-col tw-justify-end\">\n <div class=\"tw-flex tw-space-x-2\">\n <button \n cideEleButton \n variant=\"primary\" \n size=\"sm\" \n type=\"submit\"\n [disabled]=\"quickAddForm.invalid\"\n class=\"tw-px-2 tw-py-1 tw-w-20\">\n <cide-ele-icon size=\"xs\" class=\"tw-w-4 tw-h-4 tw-mr-1\">{{ isEditMode() ? 'edit' : 'add' }}</cide-ele-icon>\n {{ isEditMode() ? 'Update' : 'Add' }}\n </button>\n <button \n cideEleButton \n variant=\"outline\" \n size=\"sm\" \n type=\"button\"\n (click)=\"resetQuickAddForm()\"\n class=\"tw-px-2 tw-py-1 tw-w-16\">\n <cide-ele-icon size=\"xs\" class=\"tw-w-4 tw-h-4 tw-mr-1\">refresh</cide-ele-icon>\n Reset\n </button>\n </div>\n </div>\n </div>\n </form>\n </div>\n </div>\n\n <!-- Header Section with Filters -->\n <div class=\"tw-table-row tw-h-0\">\n <div class=\"tw-table-cell tw-px-6 tw-py-3 tw-border-b tw-border-gray-200 tw-bg-gray-50\">\n <div\n class=\"tw-flex tw-flex-col sm:tw-flex-row tw-justify-between tw-items-start sm:tw-items-center tw-space-y-3 sm:tw-space-y-0\">\n\n <!-- Title -->\n <div class=\"tw-flex tw-items-center tw-space-x-2\">\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-5 tw-h-5\">business</cide-ele-icon>\n <h5 class=\"tw-text-base tw-font-medium tw-text-gray-900 tw-m-0\">Department Management</h5>\n </div>\n\n <!-- Actions -->\n <div\n class=\"tw-flex tw-flex-col sm:tw-flex-row tw-items-start sm:tw-items-center tw-space-y-3 sm:tw-space-y-0 sm:tw-space-x-3\">\n <!-- Search functionality is handled by the data grid -->\n </div>\n </div>\n\n <!-- Error Message -->\n @if (error()) {\n <div class=\"tw-mt-4 tw-p-4 tw-bg-red-50 tw-border tw-border-red-200 tw-rounded-md\">\n <div class=\"tw-flex tw-items-start\">\n <cide-ele-icon name=\"error\" class=\"tw-text-red-400 tw-w-5 tw-h-5 tw-mt-0.5 tw-flex-shrink-0\"></cide-ele-icon>\n <div class=\"tw-ml-3\">\n <h3 class=\"tw-text-sm tw-font-medium tw-text-red-800 tw-m-0\">Error</h3>\n <p class=\"tw-text-sm tw-text-red-700 tw-mt-1 tw-m-0\">{{ error() }}</p>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n\n <!-- Main Content Area -->\n <div class=\"tw-table-row\">\n <div class=\"tw-table-cell tw-h-full tw-relative\">\n \n <!-- Data Grid Component -->\n <div class=\"tw-h-full tw-overflow-auto\">\n \n <cide-ele-data-grid \n [config]=\"gridConfig()\" \n [templateRenderers]=\"getTemplateRenderers()\"\n [actionHandlers]=\"actionHandlers\"\n [serverSidePagination]=\"true\" \n [totalServerItems]=\"totalItems()\" \n [currentServerPage]=\"currentPage()\"\n [currentServerPageSize]=\"pageSize()\" \n (gridEvent)=\"onGridEvent($event)\">\n </cide-ele-data-grid>\n </div>\n\n </div>\n </div>\n\n</div>\n\n<!-- Department Details Renderer Template -->\n<ng-template #departmentDetailsRendererTemplate let-row=\"row\" let-value=\"value\">\n <div class=\"tw-flex tw-items-center tw-min-w-0\">\n <!-- Department Icon -->\n <div class=\"tw-flex-shrink-0\">\n <cide-ele-icon \n class=\"tw-text-gray-400\" \n size=\"xs\">\n business\n </cide-ele-icon>\n </div>\n \n <!-- Department Details -->\n <div class=\"tw-ml-3 tw-min-w-0 tw-flex-1\">\n <div class=\"tw-text-sm tw-font-medium tw-text-gray-900 tw-truncate\" \n [title]=\"row.sydept_name\">\n {{ row.sydept_name || 'Untitled' }}\n </div>\n @if (row.sydept_description) {\n <div class=\"tw-text-xs tw-text-gray-500 tw-truncate\" \n [title]=\"row.sydept_description\">\n {{ row.sydept_description }}\n </div>\n }\n </div>\n </div>\n</ng-template>\n\n<!-- Department Status Renderer Template -->\n<ng-template #departmentStatusRendererTemplate let-row=\"row\" let-value=\"value\">\n <span class=\"tw-inline-flex tw-items-center tw-px-2.5 tw-py-0.5 tw-rounded-full tw-text-xs tw-font-medium tw-whitespace-nowrap\"\n [ngClass]=\"getStatusClass(row.sydept_isactive)\">\n {{ getStatusDisplay(row.sydept_isactive) }}\n </span>\n</ng-template>\n\n<!-- Actions Dropdown Renderer Template -->\n<ng-template #actionsDropdownRendererTemplate let-row=\"row\" let-value=\"value\">\n <cide-ele-dropdown \n [items]=\"getDropdownItems(row)\"\n [config]=\"{ triggerIcon: 'more_vert', triggerSize: 'sm' }\"\n (itemClick)=\"onDropdownItemClick($event, row)\">\n </cide-ele-dropdown>\n</ng-template> ", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: FormsModule }, { kind: "component", type: CideEleDataGridComponent, selector: "cide-ele-data-grid", inputs: ["config", "customRenderers", "templateRenderers", "customFormatters", "actionHandlers", "serverSidePagination", "totalServerItems", "currentServerPage", "currentServerPageSize", "dragDropEnabled"], outputs: ["gridEvent"] }, { kind: "component", type: CideEleButtonComponent, selector: "button[cideEleButton], a[cideEleButton]", inputs: ["label", "variant", "size", "type", "shape", "elevation", "disabled", "id", "loading", "fullWidth", "leftIcon", "rightIcon", "customClass", "tooltip", "ariaLabel", "testId", "routerLink", "routerExtras", "preventDoubleClick", "animated"], outputs: ["btnClick", "doubleClick"] }, { kind: "component", type: CideInputComponent, selector: "cide-ele-input", inputs: ["fill", "label", "labelHide", "disabled", "clearInput", "labelPlacement", "labelDir", "placeholder", "leadingIcon", "trailingIcon", "helperText", "helperTextCollapse", "hideHelperAndErrorText", "errorText", "maxlength", "minlength", "required", "autocapitalize", "autocomplete", "type", "width", "id", "ngModel", "option", "min", "max", "size"], outputs: ["ngModelChange"] }, { kind: "component", type: CideTextareaComponent, selector: "cide-ele-textarea", inputs: ["label", "labelHide", "placeholder", "helperText", "errorText", "required", "disabled", "minlength", "maxlength", "rows", "id", "ngModel", "size", "fill", "labelPlacement", "labelDir", "leadingIcon", "trailingIcon", "clearInput"], outputs: ["ngModelChange"] }, { kind: "component", type: CideIconComponent, selector: "cide-ele-icon", inputs: ["size", "type", "toolTip"] }, { kind: "component", type: CideEleDropdownComponent, selector: "cide-ele-dropdown", inputs: ["items", "config", "triggerTemplate", "menuTemplate"], outputs: ["itemClick", "dropdownToggle"] }, { kind: "component", type: CideEleGlobalNotificationsComponent, selector: "cide-ele-global-notifications" }] });
2788
2790
  }
2789
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: DepartmentListComponent, decorators: [{
2791
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: DepartmentListComponent, decorators: [{
2790
2792
  type: Component,
2791
2793
  args: [{ selector: 'cide-core-app-department-list', standalone: true, imports: [
2792
2794
  CommonModule,
@@ -2810,11 +2812,12 @@ var departmentList_component = /*#__PURE__*/Object.freeze({
2810
2812
  // Department Management Components
2811
2813
 
2812
2814
  class DesignationManagementService {
2815
+ http;
2816
+ apiUrl = `${coreRoutesUrl?.designation}`;
2817
+ designationListSubject = new BehaviorSubject([]);
2818
+ designationList$ = this.designationListSubject.asObservable();
2813
2819
  constructor(http) {
2814
2820
  this.http = http;
2815
- this.apiUrl = `${coreRoutesUrl?.designation}`;
2816
- this.designationListSubject = new BehaviorSubject([]);
2817
- this.designationList$ = this.designationListSubject.asObservable();
2818
2821
  console.log('DesignationManagementService initialized - using real API');
2819
2822
  }
2820
2823
  /**
@@ -2987,10 +2990,10 @@ class DesignationManagementService {
2987
2990
  console.error('Designation Management Service Error:', errorMessage);
2988
2991
  return throwError(() => new Error(errorMessage));
2989
2992
  }
2990
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: DesignationManagementService, deps: [{ token: i1.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable }); }
2991
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: DesignationManagementService, providedIn: 'root' }); }
2993
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: DesignationManagementService, deps: [{ token: i1.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable });
2994
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: DesignationManagementService, providedIn: 'root' });
2992
2995
  }
2993
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: DesignationManagementService, decorators: [{
2996
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: DesignationManagementService, decorators: [{
2994
2997
  type: Injectable,
2995
2998
  args: [{
2996
2999
  providedIn: 'root'
@@ -2998,11 +3001,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImpor
2998
3001
  }], ctorParameters: () => [{ type: i1.HttpClient }] });
2999
3002
 
3000
3003
  class GradeLevelManagementService {
3004
+ http;
3005
+ apiUrl = `${coreRoutesUrl?.gradeLevel}`;
3006
+ gradeLevelListSubject = new BehaviorSubject([]);
3007
+ gradeLevelList$ = this.gradeLevelListSubject.asObservable();
3001
3008
  constructor(http) {
3002
3009
  this.http = http;
3003
- this.apiUrl = `${coreRoutesUrl?.gradeLevel}`;
3004
- this.gradeLevelListSubject = new BehaviorSubject([]);
3005
- this.gradeLevelList$ = this.gradeLevelListSubject.asObservable();
3006
3010
  console.log('GradeLevelManagementService initialized - using real API');
3007
3011
  }
3008
3012
  /**
@@ -3153,10 +3157,10 @@ class GradeLevelManagementService {
3153
3157
  console.error('Grade Level Management Service Error:', errorMessage);
3154
3158
  return throwError(() => new Error(errorMessage));
3155
3159
  }
3156
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: GradeLevelManagementService, deps: [{ token: i1.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable }); }
3157
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: GradeLevelManagementService, providedIn: 'root' }); }
3160
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: GradeLevelManagementService, deps: [{ token: i1.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable });
3161
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: GradeLevelManagementService, providedIn: 'root' });
3158
3162
  }
3159
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: GradeLevelManagementService, decorators: [{
3163
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: GradeLevelManagementService, decorators: [{
3160
3164
  type: Injectable,
3161
3165
  args: [{
3162
3166
  providedIn: 'root'
@@ -3164,209 +3168,209 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImpor
3164
3168
  }], ctorParameters: () => [{ type: i1.HttpClient }] });
3165
3169
 
3166
3170
  class DesignationListComponent {
3171
+ // Dependency injection
3172
+ destroyRef = inject(DestroyRef);
3173
+ designationService = inject(DesignationManagementService);
3174
+ gradeLevelService = inject(GradeLevelManagementService);
3175
+ departmentService = inject(DepartmentManagementService);
3176
+ appState = inject(AppStateHelperService);
3177
+ fb = inject(NonNullableFormBuilder);
3178
+ router = inject(Router);
3179
+ // Modern ViewChild signals for template renderers (Angular 20 approach)
3180
+ designationDetailsRendererTemplate = viewChild.required('designationDetailsRendererTemplate');
3181
+ designationStatusRendererTemplate = viewChild.required('designationStatusRendererTemplate');
3182
+ actionsDropdownRendererTemplate = viewChild.required('actionsDropdownRendererTemplate');
3183
+ // Make Math available in template
3184
+ Math = Math;
3185
+ // Signals for reactive state management
3186
+ designations = signal([], ...(ngDevMode ? [{ debugName: "designations" }] : []));
3187
+ departments = signal([], ...(ngDevMode ? [{ debugName: "departments" }] : []));
3188
+ gradeLevels = signal([], ...(ngDevMode ? [{ debugName: "gradeLevels" }] : []));
3189
+ loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
3190
+ error = signal(null, ...(ngDevMode ? [{ debugName: "error" }] : []));
3191
+ selectedItems = signal([], ...(ngDevMode ? [{ debugName: "selectedItems" }] : []));
3192
+ searchTerm = signal('', ...(ngDevMode ? [{ debugName: "searchTerm" }] : []));
3193
+ // Modern reactive forms with signals
3194
+ selectedParentDesignation = signal(null, ...(ngDevMode ? [{ debugName: "selectedParentDesignation" }] : []));
3195
+ selectedParentDepartment = signal(null, ...(ngDevMode ? [{ debugName: "selectedParentDepartment" }] : []));
3196
+ // Retrieved designation data
3197
+ retrievedDesignation = signal(null, ...(ngDevMode ? [{ debugName: "retrievedDesignation" }] : []));
3198
+ // Edit mode flag
3199
+ isEditMode = signal(false, ...(ngDevMode ? [{ debugName: "isEditMode" }] : []));
3200
+ // Server-side pagination state
3201
+ currentPage = signal(1, ...(ngDevMode ? [{ debugName: "currentPage" }] : []));
3202
+ pageSize = signal(10, ...(ngDevMode ? [{ debugName: "pageSize" }] : []));
3203
+ totalItems = signal(0, ...(ngDevMode ? [{ debugName: "totalItems" }] : []));
3204
+ // Modern reactive form with typed controls
3205
+ quickAddForm = this.fb.group({
3206
+ sydsg_name: this.fb.control('', [Validators.required, Validators.minLength(1), Validators.maxLength(100)]),
3207
+ sydsg_code: this.fb.control('', [Validators.required, Validators.minLength(1), Validators.maxLength(20)]),
3208
+ sydsg_description: this.fb.control('', [Validators.maxLength(400)]),
3209
+ sydsg_prent_id_desg: this.fb.control(''),
3210
+ sydsg_department_id_sydpt: this.fb.control('', [Validators.required]),
3211
+ sydsg_grade_level_id_sydsgl: this.fb.control('', [Validators.required]),
3212
+ sydsg_isactive: this.fb.control(true, [Validators.required]),
3213
+ desg_entity_id_syen: this.fb.control(this.appState.getActiveEntityId() || '', [Validators.required])
3214
+ });
3215
+ // Grid configuration signal
3216
+ gridConfig = signal({
3217
+ id: 'designation-list-grid',
3218
+ title: '',
3219
+ subtitle: '',
3220
+ columns: [
3221
+ {
3222
+ key: 'details',
3223
+ header: 'Department/Designation',
3224
+ type: 'custom',
3225
+ width: 'auto',
3226
+ truncate: true,
3227
+ align: 'left',
3228
+ renderer: 'designationDetailsRenderer'
3229
+ },
3230
+ {
3231
+ key: 'code',
3232
+ header: 'Code',
3233
+ type: 'text',
3234
+ width: '120px',
3235
+ truncate: true,
3236
+ align: 'left'
3237
+ },
3238
+ {
3239
+ key: 'grade_level',
3240
+ header: 'Grade Level',
3241
+ type: 'text',
3242
+ width: '120px',
3243
+ truncate: true,
3244
+ align: 'left'
3245
+ },
3246
+ {
3247
+ key: 'status',
3248
+ header: 'Status',
3249
+ type: 'custom',
3250
+ width: '100px',
3251
+ truncate: false,
3252
+ align: 'center',
3253
+ renderer: 'designationStatusRenderer'
3254
+ },
3255
+ {
3256
+ key: 'actions',
3257
+ header: '',
3258
+ type: 'custom',
3259
+ width: '60px',
3260
+ truncate: false,
3261
+ align: 'center',
3262
+ renderer: 'actionsDropdownRenderer'
3263
+ }
3264
+ ],
3265
+ data: [],
3266
+ trackBy: '_id',
3267
+ tree: {
3268
+ enabled: true,
3269
+ primaryKey: '_id',
3270
+ foreignKey: 'parentId',
3271
+ childrenKey: 'children',
3272
+ levelKey: 'level',
3273
+ expandedKey: 'expanded',
3274
+ hasChildrenKey: 'hasChildren'
3275
+ },
3276
+ pagination: {
3277
+ enabled: true,
3278
+ pageSize: 10,
3279
+ pageSizeOptions: [10, 25, 50, 100],
3280
+ showQuickJump: true,
3281
+ showPageInfo: true,
3282
+ showRefresh: true
3283
+ },
3284
+ search: {
3285
+ enabled: true,
3286
+ placeholder: 'Search departments and designations...',
3287
+ searchableColumns: ['name', 'code', 'description'],
3288
+ debounceMs: 300
3289
+ },
3290
+ loading: {
3291
+ useDefer: true,
3292
+ skeletonRows: 5,
3293
+ showOverlay: false
3294
+ },
3295
+ scroll: {
3296
+ enabled: true,
3297
+ maxHeight: '',
3298
+ minHeight: '',
3299
+ stickyHeader: true,
3300
+ virtualScroll: false,
3301
+ rowHeight: 50
3302
+ },
3303
+ responsive: true,
3304
+ striped: false,
3305
+ bordered: true,
3306
+ compact: false,
3307
+ tableClass: 'tw-table-fixed tw-w-full tw-rounded-none',
3308
+ onRefresh: 'onDesignationRefresh'
3309
+ }, ...(ngDevMode ? [{ debugName: "gridConfig" }] : []));
3310
+ // Template renderers using Angular best practices
3311
+ templateRenderers = computed(() => ({
3312
+ designationDetailsRenderer: this.designationDetailsRendererTemplate(),
3313
+ designationStatusRenderer: this.designationStatusRendererTemplate(),
3314
+ actionsDropdownRenderer: this.actionsDropdownRendererTemplate()
3315
+ }), ...(ngDevMode ? [{ debugName: "templateRenderers" }] : []));
3167
3316
  /**
3168
3317
  * Get template renderers for data grid
3169
3318
  */
3170
3319
  getTemplateRenderers() {
3171
3320
  return this.templateRenderers();
3172
3321
  }
3322
+ // Mixed renderers (templates + string functions)
3323
+ customRenderers = computed(() => ({
3324
+ ...this.templateRenderers()
3325
+ }), ...(ngDevMode ? [{ debugName: "customRenderers" }] : []));
3173
3326
  /**
3174
3327
  * Get custom renderers adapted for current data grid compatibility
3175
3328
  */
3176
3329
  getCustomRenderers() {
3177
3330
  return {};
3178
3331
  }
3179
- // Modern constructor with effects for initialization
3180
- constructor() {
3181
- // Dependency injection
3182
- this.destroyRef = inject(DestroyRef);
3183
- this.designationService = inject(DesignationManagementService);
3184
- this.gradeLevelService = inject(GradeLevelManagementService);
3185
- this.departmentService = inject(DepartmentManagementService);
3186
- this.appState = inject(AppStateHelperService);
3187
- this.fb = inject(NonNullableFormBuilder);
3188
- this.router = inject(Router);
3189
- // Modern ViewChild signals for template renderers (Angular 20 approach)
3190
- this.designationDetailsRendererTemplate = viewChild.required('designationDetailsRendererTemplate');
3191
- this.designationStatusRendererTemplate = viewChild.required('designationStatusRendererTemplate');
3192
- this.actionsDropdownRendererTemplate = viewChild.required('actionsDropdownRendererTemplate');
3193
- // Make Math available in template
3194
- this.Math = Math;
3195
- // Signals for reactive state management
3196
- this.designations = signal([]);
3197
- this.departments = signal([]);
3198
- this.gradeLevels = signal([]);
3199
- this.loading = signal(false);
3200
- this.error = signal(null);
3201
- this.selectedItems = signal([]);
3202
- this.searchTerm = signal('');
3203
- // Modern reactive forms with signals
3204
- this.selectedParentDesignation = signal(null);
3205
- this.selectedParentDepartment = signal(null);
3206
- // Retrieved designation data
3207
- this.retrievedDesignation = signal(null);
3208
- // Edit mode flag
3209
- this.isEditMode = signal(false);
3210
- // Server-side pagination state
3211
- this.currentPage = signal(1);
3212
- this.pageSize = signal(10);
3213
- this.totalItems = signal(0);
3214
- // Modern reactive form with typed controls
3215
- this.quickAddForm = this.fb.group({
3216
- sydsg_name: this.fb.control('', [Validators.required, Validators.minLength(1), Validators.maxLength(100)]),
3217
- sydsg_code: this.fb.control('', [Validators.required, Validators.minLength(1), Validators.maxLength(20)]),
3218
- sydsg_description: this.fb.control('', [Validators.maxLength(400)]),
3219
- sydsg_prent_id_desg: this.fb.control(''),
3220
- sydsg_department_id_sydpt: this.fb.control('', [Validators.required]),
3221
- sydsg_grade_level_id_sydsgl: this.fb.control('', [Validators.required]),
3222
- sydsg_isactive: this.fb.control(true, [Validators.required]),
3223
- desg_entity_id_syen: this.fb.control(this.appState.getActiveEntityId() || '', [Validators.required])
3224
- });
3225
- // Grid configuration signal
3226
- this.gridConfig = signal({
3227
- id: 'designation-list-grid',
3228
- title: '',
3229
- subtitle: '',
3230
- columns: [
3231
- {
3232
- key: 'details',
3233
- header: 'Department/Designation',
3234
- type: 'custom',
3235
- width: 'auto',
3236
- truncate: true,
3237
- align: 'left',
3238
- renderer: 'designationDetailsRenderer'
3239
- },
3240
- {
3241
- key: 'code',
3242
- header: 'Code',
3243
- type: 'text',
3244
- width: '120px',
3245
- truncate: true,
3246
- align: 'left'
3247
- },
3248
- {
3249
- key: 'grade_level',
3250
- header: 'Grade Level',
3251
- type: 'text',
3252
- width: '120px',
3253
- truncate: true,
3254
- align: 'left'
3255
- },
3256
- {
3257
- key: 'status',
3258
- header: 'Status',
3259
- type: 'custom',
3260
- width: '100px',
3261
- truncate: false,
3262
- align: 'center',
3263
- renderer: 'designationStatusRenderer'
3264
- },
3265
- {
3266
- key: 'actions',
3267
- header: '',
3268
- type: 'custom',
3269
- width: '60px',
3270
- truncate: false,
3271
- align: 'center',
3272
- renderer: 'actionsDropdownRenderer'
3273
- }
3274
- ],
3275
- data: [],
3276
- trackBy: '_id',
3277
- tree: {
3278
- enabled: true,
3279
- primaryKey: '_id',
3280
- foreignKey: 'parentId',
3281
- childrenKey: 'children',
3282
- levelKey: 'level',
3283
- expandedKey: 'expanded',
3284
- hasChildrenKey: 'hasChildren'
3285
- },
3286
- pagination: {
3287
- enabled: true,
3288
- pageSize: 10,
3289
- pageSizeOptions: [10, 25, 50, 100],
3290
- showQuickJump: true,
3291
- showPageInfo: true,
3292
- showRefresh: true
3293
- },
3294
- search: {
3295
- enabled: true,
3296
- placeholder: 'Search departments and designations...',
3297
- searchableColumns: ['name', 'code', 'description'],
3298
- debounceMs: 300
3299
- },
3300
- loading: {
3301
- useDefer: true,
3302
- skeletonRows: 5,
3303
- showOverlay: false
3304
- },
3305
- scroll: {
3306
- enabled: true,
3307
- maxHeight: '',
3308
- minHeight: '',
3309
- stickyHeader: true,
3310
- virtualScroll: false,
3311
- rowHeight: 50
3312
- },
3313
- responsive: true,
3314
- striped: false,
3315
- bordered: true,
3316
- compact: false,
3317
- tableClass: 'tw-table-fixed tw-w-full tw-rounded-none',
3318
- onRefresh: 'onDesignationRefresh'
3332
+ // Action handlers for grid actions
3333
+ actionHandlers = {
3334
+ onEditDesignation: (row) => this.editDesignation(row._id || ''),
3335
+ onToggleDesignation: (row) => this.toggleDesignationStatus(row._id || ''),
3336
+ onDeleteDesignation: (row) => this.deleteDesignation(row._id || ''),
3337
+ onDesignationRowClick: (row) => this.onDesignationRowClick(row),
3338
+ onDesignationRefresh: () => this.onDesignationRefresh(),
3339
+ onAddChild: (row) => this.onAddChild(row)
3340
+ };
3341
+ // Computed properties
3342
+ filteredItems = computed(() => {
3343
+ const items = this.designations();
3344
+ const search = this.searchTerm()?.toLowerCase();
3345
+ if (!search)
3346
+ return items;
3347
+ return items.filter(item => {
3348
+ return item.sydsg_name?.toLowerCase().includes(search) ||
3349
+ item.sydsg_code?.toLowerCase().includes(search) ||
3350
+ item.sydsg_description?.toLowerCase().includes(search);
3319
3351
  });
3320
- // Template renderers using Angular best practices
3321
- this.templateRenderers = computed(() => ({
3322
- designationDetailsRenderer: this.designationDetailsRendererTemplate(),
3323
- designationStatusRenderer: this.designationStatusRendererTemplate(),
3324
- actionsDropdownRenderer: this.actionsDropdownRendererTemplate()
3352
+ }, ...(ngDevMode ? [{ debugName: "filteredItems" }] : []));
3353
+ hasSelection = computed(() => this.selectedItems().length > 0, ...(ngDevMode ? [{ debugName: "hasSelection" }] : []));
3354
+ // Pagination computed properties
3355
+ totalPages = computed(() => Math.ceil(this.totalItems() / this.pageSize()), ...(ngDevMode ? [{ debugName: "totalPages" }] : []));
3356
+ hasNextPage = computed(() => this.currentPage() < this.totalPages(), ...(ngDevMode ? [{ debugName: "hasNextPage" }] : []));
3357
+ hasPreviousPage = computed(() => this.currentPage() > 1, ...(ngDevMode ? [{ debugName: "hasPreviousPage" }] : []));
3358
+ // Grade level options for dropdown
3359
+ gradeLevelOptions = computed(() => {
3360
+ return this.gradeLevels().map(gradeLevel => ({
3361
+ value: gradeLevel._id || '',
3362
+ label: gradeLevel.sydsgl_name || 'Unknown'
3325
3363
  }));
3326
- // Mixed renderers (templates + string functions)
3327
- this.customRenderers = computed(() => ({
3328
- ...this.templateRenderers()
3364
+ }, ...(ngDevMode ? [{ debugName: "gradeLevelOptions" }] : []));
3365
+ // Department options for dropdown
3366
+ departmentOptions = computed(() => {
3367
+ return this.departments().map(department => ({
3368
+ value: department._id || '',
3369
+ label: department.sydept_name || 'Unknown'
3329
3370
  }));
3330
- // Action handlers for grid actions
3331
- this.actionHandlers = {
3332
- onEditDesignation: (row) => this.editDesignation(row._id || ''),
3333
- onToggleDesignation: (row) => this.toggleDesignationStatus(row._id || ''),
3334
- onDeleteDesignation: (row) => this.deleteDesignation(row._id || ''),
3335
- onDesignationRowClick: (row) => this.onDesignationRowClick(row),
3336
- onDesignationRefresh: () => this.onDesignationRefresh(),
3337
- onAddChild: (row) => this.onAddChild(row)
3338
- };
3339
- // Computed properties
3340
- this.filteredItems = computed(() => {
3341
- const items = this.designations();
3342
- const search = this.searchTerm()?.toLowerCase();
3343
- if (!search)
3344
- return items;
3345
- return items.filter(item => {
3346
- return item.sydsg_name?.toLowerCase().includes(search) ||
3347
- item.sydsg_code?.toLowerCase().includes(search) ||
3348
- item.sydsg_description?.toLowerCase().includes(search);
3349
- });
3350
- });
3351
- this.hasSelection = computed(() => this.selectedItems().length > 0);
3352
- // Pagination computed properties
3353
- this.totalPages = computed(() => Math.ceil(this.totalItems() / this.pageSize()));
3354
- this.hasNextPage = computed(() => this.currentPage() < this.totalPages());
3355
- this.hasPreviousPage = computed(() => this.currentPage() > 1);
3356
- // Grade level options for dropdown
3357
- this.gradeLevelOptions = computed(() => {
3358
- return this.gradeLevels().map(gradeLevel => ({
3359
- value: gradeLevel._id || '',
3360
- label: gradeLevel.sydsgl_name || 'Unknown'
3361
- }));
3362
- });
3363
- // Department options for dropdown
3364
- this.departmentOptions = computed(() => {
3365
- return this.departments().map(department => ({
3366
- value: department._id || '',
3367
- label: department.sydept_name || 'Unknown'
3368
- }));
3369
- });
3371
+ }, ...(ngDevMode ? [{ debugName: "departmentOptions" }] : []));
3372
+ // Modern constructor with effects for initialization
3373
+ constructor() {
3370
3374
  this.initializeComponent();
3371
3375
  this.destroyRef.onDestroy(() => {
3372
3376
  this.cleanupEventListeners();
@@ -4253,10 +4257,10 @@ class DesignationListComponent {
4253
4257
  trackByItemId(index, item) {
4254
4258
  return item._id || '';
4255
4259
  }
4256
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: DesignationListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
4257
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.7", type: DesignationListComponent, isStandalone: true, selector: "cide-core-app-designation-list", viewQueries: [{ propertyName: "designationDetailsRendererTemplate", first: true, predicate: ["designationDetailsRendererTemplate"], descendants: true, isSignal: true }, { propertyName: "designationStatusRendererTemplate", first: true, predicate: ["designationStatusRendererTemplate"], descendants: true, isSignal: true }, { propertyName: "actionsDropdownRendererTemplate", first: true, predicate: ["actionsDropdownRendererTemplate"], descendants: true, isSignal: true }], ngImport: i0, template: "<!-- Designation List Container -->\n<div class=\"tw-table tw-w-full tw-h-full\">\n\n <!-- Quick Add Form Section -->\n <div class=\"tw-table-row tw-h-0\">\n <div class=\"tw-table-cell tw-px-6 tw-py-4 tw-border-b tw-border-gray-200 tw-bg-white\">\n <div class=\"tw-flex tw-items-center tw-justify-between tw-mb-0\">\n <div class=\"tw-flex tw-items-center tw-space-x-3 tw-mb-3\">\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-5 tw-h-5\">{{ isEditMode() ? 'edit' : 'add' }}</cide-ele-icon>\n <h6 class=\"tw-text-sm tw-font-medium tw-text-gray-900 tw-m-0\">{{ isEditMode() ? 'Edit Designation' : 'Quick Add Designation' }}</h6>\n </div>\n @if (selectedParentDesignation()) {\n <div class=\"tw-flex tw-items-center tw-space-x-3 tw-bg-blue-50 tw-border tw-border-blue-200 tw-px-4 tw-py-1 tw-rounded-lg\">\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-4 tw-h-4\">account_tree</cide-ele-icon>\n <div class=\"tw-flex tw-items-center tw-space-x-2\">\n <span class=\"tw-text-sm tw-text-blue-600 tw-font-medium\">{{ isEditMode() ? 'Parent:' : 'Creating child under:' }}</span>\n <span class=\"tw-text-sm tw-text-blue-800 tw-font-semibold\">{{ selectedParentDesignation()?.sydsg_name }}</span>\n </div>\n <button \n cideEleButton \n variant=\"ghost\" \n size=\"xs\" \n type=\"button\" \n (click)=\"clearSelectedParent()\" \n class=\"tw-text-blue-400 hover:tw-text-blue-600\">\n <svg class=\"tw-w-4 tw-h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M6 18L18 6M6 6l12 12\"/>\n </svg>\n </button>\n </div>\n }\n @if (selectedParentDepartment()) {\n <div class=\"tw-flex tw-items-center tw-space-x-3 tw-bg-green-50 tw-border tw-border-green-200 tw-px-4 tw-py-1 tw-rounded-lg\">\n <cide-ele-icon class=\"tw-text-green-600 tw-w-4 tw-h-4\">business</cide-ele-icon>\n <div class=\"tw-flex tw-items-center tw-space-x-2\">\n <span class=\"tw-text-sm tw-text-green-600 tw-font-medium\">{{ isEditMode() ? 'Department:' : 'Department:' }}</span>\n <span class=\"tw-text-sm tw-text-green-800 tw-font-semibold\">{{ selectedParentDepartment()?.sydept_name }}</span>\n </div>\n <button \n cideEleButton \n variant=\"ghost\" \n size=\"xs\" \n type=\"button\" \n (click)=\"clearSelectedParentDepartment()\" \n class=\"tw-text-green-400 hover:tw-text-green-600\">\n <svg class=\"tw-w-4 tw-h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M6 18L18 6M6 6l12 12\"/>\n </svg>\n </button>\n </div>\n }\n </div>\n \n <form [formGroup]=\"quickAddForm\" (ngSubmit)=\"quickAddDesignation()\">\n <!-- First Row -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 lg:tw-grid-cols-5 tw-gap-3 tw-mb-3\">\n <!-- Designation Name -->\n <div>\n <cide-ele-input \n id=\"sydsg_name\" \n label=\"Name*\" \n formControlName=\"sydsg_name\"\n placeholder=\"Designation name\"\n size=\"sm\">\n </cide-ele-input>\n </div>\n \n <!-- Designation Code -->\n <div>\n <cide-ele-input \n id=\"sydsg_code\" \n label=\"Code*\" \n formControlName=\"sydsg_code\"\n placeholder=\"DESG001\"\n size=\"sm\">\n </cide-ele-input>\n </div>\n \n <!-- Grade Level -->\n <div>\n <cide-ele-select \n id=\"sydsg_grade_level_id_sydsgl\"\n label=\"Grade Level*\" \n [options]=\"gradeLevelOptions()\" \n formControlName=\"sydsg_grade_level_id_sydsgl\"\n placeholder=\"Select grade level\"\n size=\"sm\">\n </cide-ele-select>\n </div>\n \n <!-- Department -->\n <div>\n <cide-ele-select \n id=\"sydsg_department_id_sydpt\"\n label=\"Department*\" \n [options]=\"departmentOptions()\" \n formControlName=\"sydsg_department_id_sydpt\"\n placeholder=\"Select department\"\n size=\"sm\">\n </cide-ele-select>\n </div>\n \n <!-- Active Status -->\n <div class=\"tw-flex tw-flex-col tw-justify-end\">\n <cide-ele-input \n id=\"sydsg_isactive\"\n type=\"checkbox\"\n label=\"Active\"\n formControlName=\"sydsg_isactive\"\n size=\"sm\">\n </cide-ele-input>\n </div>\n </div>\n \n <!-- Second Row -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 lg:tw-grid-cols-4 tw-gap-3 tw-items-end\">\n <!-- Description -->\n <div>\n <cide-ele-textarea \n id=\"sydsg_description\" \n label=\"Description\" \n formControlName=\"sydsg_description\"\n placeholder=\"Designation description\"\n rows=\"2\"\n size=\"sm\">\n </cide-ele-textarea>\n </div>\n \n <!-- Entity ID (Hidden) -->\n <div class=\"tw-hidden\">\n <cide-ele-input \n id=\"desg_entity_id_syen\" \n label=\"Entity ID*\" \n formControlName=\"desg_entity_id_syen\"\n placeholder=\"Entity ID\"\n size=\"sm\">\n </cide-ele-input>\n </div>\n \n <!-- Action Buttons -->\n <div class=\"tw-flex tw-flex-col tw-justify-end\">\n <div class=\"tw-flex tw-space-x-2\">\n <button \n cideEleButton \n variant=\"primary\" \n size=\"sm\" \n type=\"submit\"\n [disabled]=\"quickAddForm.invalid\"\n class=\"tw-px-2 tw-py-1 tw-w-20\">\n <cide-ele-icon size=\"xs\" class=\"tw-w-4 tw-h-4 tw-mr-1\">{{ isEditMode() ? 'edit' : 'add' }}</cide-ele-icon>\n {{ isEditMode() ? 'Update' : 'Add' }}\n </button>\n <button \n cideEleButton \n variant=\"outline\" \n size=\"sm\" \n type=\"button\"\n (click)=\"resetQuickAddForm()\"\n class=\"tw-px-2 tw-py-1 tw-w-16\">\n <cide-ele-icon size=\"xs\" class=\"tw-w-4 tw-h-4 tw-mr-1\">refresh</cide-ele-icon>\n Reset\n </button>\n </div>\n </div>\n </div>\n </form>\n </div>\n </div>\n\n\n\n <!-- Header Section with Filters -->\n <div class=\"tw-table-row tw-h-0\">\n <div class=\"tw-table-cell tw-px-6 tw-py-3 tw-border-b tw-border-gray-200 tw-bg-gray-50\">\n <div\n class=\"tw-flex tw-flex-col sm:tw-flex-row tw-justify-between tw-items-start sm:tw-items-center tw-space-y-3 sm:tw-space-y-0\">\n\n <!-- Title -->\n <div class=\"tw-flex tw-items-center tw-space-x-2\">\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-5 tw-h-5\">work</cide-ele-icon>\n <h5 class=\"tw-text-base tw-font-medium tw-text-gray-900 tw-m-0\">Designation Management</h5>\n </div>\n\n <!-- Actions -->\n <div\n class=\"tw-flex tw-flex-col sm:tw-flex-row tw-items-start sm:tw-items-center tw-space-y-3 sm:tw-space-y-0 sm:tw-space-x-3\">\n <!-- Search functionality is handled by the data grid -->\n </div>\n </div>\n\n <!-- Error Message -->\n @if (error()) {\n <div class=\"tw-mt-4 tw-p-4 tw-bg-red-50 tw-border tw-border-red-200 tw-rounded-md\">\n <div class=\"tw-flex tw-items-start\">\n <cide-ele-icon name=\"error\" class=\"tw-text-red-400 tw-w-5 tw-h-5 tw-mt-0.5 tw-flex-shrink-0\"></cide-ele-icon>\n <div class=\"tw-ml-3\">\n <h3 class=\"tw-text-sm tw-font-medium tw-text-red-800 tw-m-0\">Error</h3>\n <p class=\"tw-text-sm tw-text-red-700 tw-mt-1 tw-m-0\">{{ error() }}</p>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n\n <!-- Main Content Area -->\n <div class=\"tw-table-row\">\n <div class=\"tw-table-cell tw-h-full tw-relative\">\n \n <!-- Data Grid Component -->\n <div class=\"tw-h-full tw-overflow-auto\">\n \n <cide-ele-data-grid \n [config]=\"gridConfig()\" \n [templateRenderers]=\"getTemplateRenderers()\"\n [actionHandlers]=\"actionHandlers\"\n [serverSidePagination]=\"true\" \n [totalServerItems]=\"totalItems()\" \n [currentServerPage]=\"currentPage()\"\n [currentServerPageSize]=\"pageSize()\" \n (gridEvent)=\"onGridEvent($event)\">\n </cide-ele-data-grid>\n </div>\n\n </div>\n </div>\n\n</div>\n\n<!-- Designation Details Renderer Template -->\n<ng-template #designationDetailsRendererTemplate let-row=\"row\" let-value=\"value\">\n <div class=\"tw-flex tw-items-center tw-min-w-0\">\n <!-- Dynamic Icon based on type -->\n <div class=\"tw-flex-shrink-0\">\n <cide-ele-icon \n [class]=\"row.type === 'department' ? 'tw-text-green-500' : 'tw-text-blue-500'\" \n size=\"xs\">\n {{ row.type === 'department' ? 'business' : 'work' }}\n </cide-ele-icon>\n </div>\n \n <!-- Details -->\n <div class=\"tw-ml-3 tw-min-w-0 tw-flex-1\">\n <div class=\"tw-flex tw-items-center tw-space-x-2\">\n <div class=\"tw-text-sm tw-font-medium tw-text-gray-900 tw-truncate\" \n [title]=\"row.name\">\n {{ row.name || 'Untitled' }}\n </div>\n @if (row.type === 'department') {\n <span class=\"tw-inline-flex tw-items-center tw-px-2 tw-py-0.5 tw-rounded-full tw-text-xs tw-font-medium tw-bg-green-100 tw-text-green-800\">\n Department\n </span>\n }\n </div>\n @if (row.description) {\n <div class=\"tw-text-xs tw-text-gray-500 tw-truncate\" \n [title]=\"row.description\">\n {{ row.description }}\n </div>\n }\n </div>\n </div>\n</ng-template>\n\n<!-- Designation Status Renderer Template -->\n<ng-template #designationStatusRendererTemplate let-row=\"row\" let-value=\"value\">\n <span class=\"tw-inline-flex tw-items-center tw-px-2.5 tw-py-0.5 tw-rounded-full tw-text-xs tw-font-medium tw-whitespace-nowrap\"\n [ngClass]=\"getStatusClass(row.status)\">\n {{ getStatusDisplay(row.status) }}\n </span>\n</ng-template>\n\n<!-- Actions Dropdown Renderer Template -->\n<ng-template #actionsDropdownRendererTemplate let-row=\"row\" let-value=\"value\">\n <cide-ele-dropdown \n [items]=\"getDropdownItems(row)\"\n [config]=\"{ triggerIcon: 'more_vert', triggerSize: 'sm' }\"\n (itemClick)=\"onDropdownItemClick($event, row)\">\n </cide-ele-dropdown>\n</ng-template> ", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: FormsModule }, { kind: "component", type: CideEleDataGridComponent, selector: "cide-ele-data-grid", inputs: ["config", "customRenderers", "templateRenderers", "customFormatters", "actionHandlers", "serverSidePagination", "totalServerItems", "currentServerPage", "currentServerPageSize", "dragDropEnabled"], outputs: ["gridEvent"] }, { kind: "component", type: CideEleButtonComponent, selector: "button[cideEleButton], a[cideEleButton]", inputs: ["label", "variant", "size", "type", "shape", "elevation", "disabled", "id", "loading", "fullWidth", "leftIcon", "rightIcon", "customClass", "tooltip", "ariaLabel", "testId", "routerLink", "routerExtras", "preventDoubleClick", "animated"], outputs: ["btnClick", "doubleClick"] }, { kind: "component", type: CideInputComponent, selector: "cide-ele-input", inputs: ["fill", "label", "labelHide", "disabled", "clearInput", "labelPlacement", "labelDir", "placeholder", "leadingIcon", "trailingIcon", "helperText", "helperTextCollapse", "hideHelperAndErrorText", "errorText", "maxlength", "minlength", "required", "autocapitalize", "autocomplete", "type", "width", "id", "ngModel", "option", "min", "max", "size"], outputs: ["ngModelChange"] }, { kind: "component", type: CideSelectComponent, selector: "cide-ele-select", inputs: ["label", "labelHide", "placeholder", "helperText", "errorText", "required", "disabled", "id", "ngModel", "size", "fill", "labelPlacement", "labelDir", "leadingIcon", "trailingIcon", "clearInput", "options", "multiple", "searchable", "showSearchInput", "loading"], outputs: ["ngModelChange", "change", "searchChange"] }, { kind: "component", type: CideTextareaComponent, selector: "cide-ele-textarea", inputs: ["label", "labelHide", "placeholder", "helperText", "errorText", "required", "disabled", "minlength", "maxlength", "rows", "id", "ngModel", "size", "fill", "labelPlacement", "labelDir", "leadingIcon", "trailingIcon", "clearInput"], outputs: ["ngModelChange"] }, { kind: "component", type: CideIconComponent, selector: "cide-ele-icon", inputs: ["size", "type", "toolTip"] }, { kind: "component", type: CideEleDropdownComponent, selector: "cide-ele-dropdown", inputs: ["items", "config", "triggerTemplate", "menuTemplate"], outputs: ["itemClick", "dropdownToggle"] }] }); }
4260
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: DesignationListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
4261
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.7", type: DesignationListComponent, isStandalone: true, selector: "cide-core-app-designation-list", viewQueries: [{ propertyName: "designationDetailsRendererTemplate", first: true, predicate: ["designationDetailsRendererTemplate"], descendants: true, isSignal: true }, { propertyName: "designationStatusRendererTemplate", first: true, predicate: ["designationStatusRendererTemplate"], descendants: true, isSignal: true }, { propertyName: "actionsDropdownRendererTemplate", first: true, predicate: ["actionsDropdownRendererTemplate"], descendants: true, isSignal: true }], ngImport: i0, template: "<!-- Designation List Container -->\n<div class=\"tw-table tw-w-full tw-h-full\">\n\n <!-- Quick Add Form Section -->\n <div class=\"tw-table-row tw-h-0\">\n <div class=\"tw-table-cell tw-px-6 tw-py-4 tw-border-b tw-border-gray-200 tw-bg-white\">\n <div class=\"tw-flex tw-items-center tw-justify-between tw-mb-0\">\n <div class=\"tw-flex tw-items-center tw-space-x-3 tw-mb-3\">\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-5 tw-h-5\">{{ isEditMode() ? 'edit' : 'add' }}</cide-ele-icon>\n <h6 class=\"tw-text-sm tw-font-medium tw-text-gray-900 tw-m-0\">{{ isEditMode() ? 'Edit Designation' : 'Quick Add Designation' }}</h6>\n </div>\n @if (selectedParentDesignation()) {\n <div class=\"tw-flex tw-items-center tw-space-x-3 tw-bg-blue-50 tw-border tw-border-blue-200 tw-px-4 tw-py-1 tw-rounded-lg\">\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-4 tw-h-4\">account_tree</cide-ele-icon>\n <div class=\"tw-flex tw-items-center tw-space-x-2\">\n <span class=\"tw-text-sm tw-text-blue-600 tw-font-medium\">{{ isEditMode() ? 'Parent:' : 'Creating child under:' }}</span>\n <span class=\"tw-text-sm tw-text-blue-800 tw-font-semibold\">{{ selectedParentDesignation()?.sydsg_name }}</span>\n </div>\n <button \n cideEleButton \n variant=\"ghost\" \n size=\"xs\" \n type=\"button\" \n (click)=\"clearSelectedParent()\" \n class=\"tw-text-blue-400 hover:tw-text-blue-600\">\n <svg class=\"tw-w-4 tw-h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M6 18L18 6M6 6l12 12\"/>\n </svg>\n </button>\n </div>\n }\n @if (selectedParentDepartment()) {\n <div class=\"tw-flex tw-items-center tw-space-x-3 tw-bg-green-50 tw-border tw-border-green-200 tw-px-4 tw-py-1 tw-rounded-lg\">\n <cide-ele-icon class=\"tw-text-green-600 tw-w-4 tw-h-4\">business</cide-ele-icon>\n <div class=\"tw-flex tw-items-center tw-space-x-2\">\n <span class=\"tw-text-sm tw-text-green-600 tw-font-medium\">{{ isEditMode() ? 'Department:' : 'Department:' }}</span>\n <span class=\"tw-text-sm tw-text-green-800 tw-font-semibold\">{{ selectedParentDepartment()?.sydept_name }}</span>\n </div>\n <button \n cideEleButton \n variant=\"ghost\" \n size=\"xs\" \n type=\"button\" \n (click)=\"clearSelectedParentDepartment()\" \n class=\"tw-text-green-400 hover:tw-text-green-600\">\n <svg class=\"tw-w-4 tw-h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M6 18L18 6M6 6l12 12\"/>\n </svg>\n </button>\n </div>\n }\n </div>\n \n <form [formGroup]=\"quickAddForm\" (ngSubmit)=\"quickAddDesignation()\">\n <!-- First Row -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 lg:tw-grid-cols-5 tw-gap-3 tw-mb-3\">\n <!-- Designation Name -->\n <div>\n <cide-ele-input \n id=\"sydsg_name\" \n label=\"Name*\" \n formControlName=\"sydsg_name\"\n placeholder=\"Designation name\"\n size=\"sm\">\n </cide-ele-input>\n </div>\n \n <!-- Designation Code -->\n <div>\n <cide-ele-input \n id=\"sydsg_code\" \n label=\"Code*\" \n formControlName=\"sydsg_code\"\n placeholder=\"DESG001\"\n size=\"sm\">\n </cide-ele-input>\n </div>\n \n <!-- Grade Level -->\n <div>\n <cide-ele-select \n id=\"sydsg_grade_level_id_sydsgl\"\n label=\"Grade Level*\" \n [options]=\"gradeLevelOptions()\" \n formControlName=\"sydsg_grade_level_id_sydsgl\"\n placeholder=\"Select grade level\"\n size=\"sm\">\n </cide-ele-select>\n </div>\n \n <!-- Department -->\n <div>\n <cide-ele-select \n id=\"sydsg_department_id_sydpt\"\n label=\"Department*\" \n [options]=\"departmentOptions()\" \n formControlName=\"sydsg_department_id_sydpt\"\n placeholder=\"Select department\"\n size=\"sm\">\n </cide-ele-select>\n </div>\n \n <!-- Active Status -->\n <div class=\"tw-flex tw-flex-col tw-justify-end\">\n <cide-ele-input \n id=\"sydsg_isactive\"\n type=\"checkbox\"\n label=\"Active\"\n formControlName=\"sydsg_isactive\"\n size=\"sm\">\n </cide-ele-input>\n </div>\n </div>\n \n <!-- Second Row -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 lg:tw-grid-cols-4 tw-gap-3 tw-items-end\">\n <!-- Description -->\n <div>\n <cide-ele-textarea \n id=\"sydsg_description\" \n label=\"Description\" \n formControlName=\"sydsg_description\"\n placeholder=\"Designation description\"\n rows=\"2\"\n size=\"sm\">\n </cide-ele-textarea>\n </div>\n \n <!-- Entity ID (Hidden) -->\n <div class=\"tw-hidden\">\n <cide-ele-input \n id=\"desg_entity_id_syen\" \n label=\"Entity ID*\" \n formControlName=\"desg_entity_id_syen\"\n placeholder=\"Entity ID\"\n size=\"sm\">\n </cide-ele-input>\n </div>\n \n <!-- Action Buttons -->\n <div class=\"tw-flex tw-flex-col tw-justify-end\">\n <div class=\"tw-flex tw-space-x-2\">\n <button \n cideEleButton \n variant=\"primary\" \n size=\"sm\" \n type=\"submit\"\n [disabled]=\"quickAddForm.invalid\"\n class=\"tw-px-2 tw-py-1 tw-w-20\">\n <cide-ele-icon size=\"xs\" class=\"tw-w-4 tw-h-4 tw-mr-1\">{{ isEditMode() ? 'edit' : 'add' }}</cide-ele-icon>\n {{ isEditMode() ? 'Update' : 'Add' }}\n </button>\n <button \n cideEleButton \n variant=\"outline\" \n size=\"sm\" \n type=\"button\"\n (click)=\"resetQuickAddForm()\"\n class=\"tw-px-2 tw-py-1 tw-w-16\">\n <cide-ele-icon size=\"xs\" class=\"tw-w-4 tw-h-4 tw-mr-1\">refresh</cide-ele-icon>\n Reset\n </button>\n </div>\n </div>\n </div>\n </form>\n </div>\n </div>\n\n\n\n <!-- Header Section with Filters -->\n <div class=\"tw-table-row tw-h-0\">\n <div class=\"tw-table-cell tw-px-6 tw-py-3 tw-border-b tw-border-gray-200 tw-bg-gray-50\">\n <div\n class=\"tw-flex tw-flex-col sm:tw-flex-row tw-justify-between tw-items-start sm:tw-items-center tw-space-y-3 sm:tw-space-y-0\">\n\n <!-- Title -->\n <div class=\"tw-flex tw-items-center tw-space-x-2\">\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-5 tw-h-5\">work</cide-ele-icon>\n <h5 class=\"tw-text-base tw-font-medium tw-text-gray-900 tw-m-0\">Designation Management</h5>\n </div>\n\n <!-- Actions -->\n <div\n class=\"tw-flex tw-flex-col sm:tw-flex-row tw-items-start sm:tw-items-center tw-space-y-3 sm:tw-space-y-0 sm:tw-space-x-3\">\n <!-- Search functionality is handled by the data grid -->\n </div>\n </div>\n\n <!-- Error Message -->\n @if (error()) {\n <div class=\"tw-mt-4 tw-p-4 tw-bg-red-50 tw-border tw-border-red-200 tw-rounded-md\">\n <div class=\"tw-flex tw-items-start\">\n <cide-ele-icon name=\"error\" class=\"tw-text-red-400 tw-w-5 tw-h-5 tw-mt-0.5 tw-flex-shrink-0\"></cide-ele-icon>\n <div class=\"tw-ml-3\">\n <h3 class=\"tw-text-sm tw-font-medium tw-text-red-800 tw-m-0\">Error</h3>\n <p class=\"tw-text-sm tw-text-red-700 tw-mt-1 tw-m-0\">{{ error() }}</p>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n\n <!-- Main Content Area -->\n <div class=\"tw-table-row\">\n <div class=\"tw-table-cell tw-h-full tw-relative\">\n \n <!-- Data Grid Component -->\n <div class=\"tw-h-full tw-overflow-auto\">\n \n <cide-ele-data-grid \n [config]=\"gridConfig()\" \n [templateRenderers]=\"getTemplateRenderers()\"\n [actionHandlers]=\"actionHandlers\"\n [serverSidePagination]=\"true\" \n [totalServerItems]=\"totalItems()\" \n [currentServerPage]=\"currentPage()\"\n [currentServerPageSize]=\"pageSize()\" \n (gridEvent)=\"onGridEvent($event)\">\n </cide-ele-data-grid>\n </div>\n\n </div>\n </div>\n\n</div>\n\n<!-- Designation Details Renderer Template -->\n<ng-template #designationDetailsRendererTemplate let-row=\"row\" let-value=\"value\">\n <div class=\"tw-flex tw-items-center tw-min-w-0\">\n <!-- Dynamic Icon based on type -->\n <div class=\"tw-flex-shrink-0\">\n <cide-ele-icon \n [class]=\"row.type === 'department' ? 'tw-text-green-500' : 'tw-text-blue-500'\" \n size=\"xs\">\n {{ row.type === 'department' ? 'business' : 'work' }}\n </cide-ele-icon>\n </div>\n \n <!-- Details -->\n <div class=\"tw-ml-3 tw-min-w-0 tw-flex-1\">\n <div class=\"tw-flex tw-items-center tw-space-x-2\">\n <div class=\"tw-text-sm tw-font-medium tw-text-gray-900 tw-truncate\" \n [title]=\"row.name\">\n {{ row.name || 'Untitled' }}\n </div>\n @if (row.type === 'department') {\n <span class=\"tw-inline-flex tw-items-center tw-px-2 tw-py-0.5 tw-rounded-full tw-text-xs tw-font-medium tw-bg-green-100 tw-text-green-800\">\n Department\n </span>\n }\n </div>\n @if (row.description) {\n <div class=\"tw-text-xs tw-text-gray-500 tw-truncate\" \n [title]=\"row.description\">\n {{ row.description }}\n </div>\n }\n </div>\n </div>\n</ng-template>\n\n<!-- Designation Status Renderer Template -->\n<ng-template #designationStatusRendererTemplate let-row=\"row\" let-value=\"value\">\n <span class=\"tw-inline-flex tw-items-center tw-px-2.5 tw-py-0.5 tw-rounded-full tw-text-xs tw-font-medium tw-whitespace-nowrap\"\n [ngClass]=\"getStatusClass(row.status)\">\n {{ getStatusDisplay(row.status) }}\n </span>\n</ng-template>\n\n<!-- Actions Dropdown Renderer Template -->\n<ng-template #actionsDropdownRendererTemplate let-row=\"row\" let-value=\"value\">\n <cide-ele-dropdown \n [items]=\"getDropdownItems(row)\"\n [config]=\"{ triggerIcon: 'more_vert', triggerSize: 'sm' }\"\n (itemClick)=\"onDropdownItemClick($event, row)\">\n </cide-ele-dropdown>\n</ng-template> ", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: FormsModule }, { kind: "component", type: CideEleDataGridComponent, selector: "cide-ele-data-grid", inputs: ["config", "customRenderers", "templateRenderers", "customFormatters", "actionHandlers", "serverSidePagination", "totalServerItems", "currentServerPage", "currentServerPageSize", "dragDropEnabled"], outputs: ["gridEvent"] }, { kind: "component", type: CideEleButtonComponent, selector: "button[cideEleButton], a[cideEleButton]", inputs: ["label", "variant", "size", "type", "shape", "elevation", "disabled", "id", "loading", "fullWidth", "leftIcon", "rightIcon", "customClass", "tooltip", "ariaLabel", "testId", "routerLink", "routerExtras", "preventDoubleClick", "animated"], outputs: ["btnClick", "doubleClick"] }, { kind: "component", type: CideInputComponent, selector: "cide-ele-input", inputs: ["fill", "label", "labelHide", "disabled", "clearInput", "labelPlacement", "labelDir", "placeholder", "leadingIcon", "trailingIcon", "helperText", "helperTextCollapse", "hideHelperAndErrorText", "errorText", "maxlength", "minlength", "required", "autocapitalize", "autocomplete", "type", "width", "id", "ngModel", "option", "min", "max", "size"], outputs: ["ngModelChange"] }, { kind: "component", type: CideSelectComponent, selector: "cide-ele-select", inputs: ["label", "labelHide", "placeholder", "helperText", "errorText", "required", "disabled", "id", "ngModel", "size", "fill", "labelPlacement", "labelDir", "leadingIcon", "trailingIcon", "clearInput", "options", "multiple", "searchable", "showSearchInput", "loading"], outputs: ["ngModelChange", "change", "searchChange"] }, { kind: "component", type: CideTextareaComponent, selector: "cide-ele-textarea", inputs: ["label", "labelHide", "placeholder", "helperText", "errorText", "required", "disabled", "minlength", "maxlength", "rows", "id", "ngModel", "size", "fill", "labelPlacement", "labelDir", "leadingIcon", "trailingIcon", "clearInput"], outputs: ["ngModelChange"] }, { kind: "component", type: CideIconComponent, selector: "cide-ele-icon", inputs: ["size", "type", "toolTip"] }, { kind: "component", type: CideEleDropdownComponent, selector: "cide-ele-dropdown", inputs: ["items", "config", "triggerTemplate", "menuTemplate"], outputs: ["itemClick", "dropdownToggle"] }] });
4258
4262
  }
4259
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: DesignationListComponent, decorators: [{
4263
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: DesignationListComponent, decorators: [{
4260
4264
  type: Component,
4261
4265
  args: [{ selector: 'cide-core-app-designation-list', standalone: true, imports: [
4262
4266
  CommonModule,
@@ -4280,182 +4284,182 @@ var designationList_component = /*#__PURE__*/Object.freeze({
4280
4284
  // Designation Management Components
4281
4285
 
4282
4286
  class GradeLevelListComponent {
4287
+ // Dependency injection
4288
+ destroyRef = inject(DestroyRef);
4289
+ gradeLevelService = inject(GradeLevelManagementService);
4290
+ appState = inject(AppStateHelperService);
4291
+ fb = inject(NonNullableFormBuilder);
4292
+ router = inject(Router);
4293
+ // Modern ViewChild signals for template renderers (Angular 20 approach)
4294
+ dragHandleRendererTemplate = viewChild.required('dragHandleRendererTemplate');
4295
+ gradeLevelDetailsRendererTemplate = viewChild.required('gradeLevelDetailsRendererTemplate');
4296
+ gradeLevelStatusRendererTemplate = viewChild.required('gradeLevelStatusRendererTemplate');
4297
+ actionsDropdownRendererTemplate = viewChild.required('actionsDropdownRendererTemplate');
4298
+ // Make Math available in template
4299
+ Math = Math;
4300
+ // Signals for reactive state management
4301
+ gradeLevels = signal([], ...(ngDevMode ? [{ debugName: "gradeLevels" }] : []));
4302
+ loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
4303
+ error = signal(null, ...(ngDevMode ? [{ debugName: "error" }] : []));
4304
+ selectedItems = signal([], ...(ngDevMode ? [{ debugName: "selectedItems" }] : []));
4305
+ searchTerm = signal('', ...(ngDevMode ? [{ debugName: "searchTerm" }] : []));
4306
+ // Retrieved grade level data
4307
+ retrievedGradeLevel = signal(null, ...(ngDevMode ? [{ debugName: "retrievedGradeLevel" }] : []));
4308
+ // Edit mode flag
4309
+ isEditMode = signal(false, ...(ngDevMode ? [{ debugName: "isEditMode" }] : []));
4310
+ // Drag order management
4311
+ originalOrder = signal([], ...(ngDevMode ? [{ debugName: "originalOrder" }] : []));
4312
+ hasOrderChanged = signal(false, ...(ngDevMode ? [{ debugName: "hasOrderChanged" }] : []));
4313
+ // Server-side pagination state
4314
+ currentPage = signal(1, ...(ngDevMode ? [{ debugName: "currentPage" }] : []));
4315
+ pageSize = signal(10, ...(ngDevMode ? [{ debugName: "pageSize" }] : []));
4316
+ totalItems = signal(0, ...(ngDevMode ? [{ debugName: "totalItems" }] : []));
4317
+ // Modern reactive form with typed controls
4318
+ quickAddForm = this.fb.group({
4319
+ sydsgl_name: this.fb.control('', [Validators.required, Validators.minLength(1), Validators.maxLength(20)]),
4320
+ sydsgl_description: this.fb.control('', [Validators.maxLength(400)]),
4321
+ sydsgl_order: this.fb.control(1, [Validators.required, Validators.min(1), Validators.max(100)]),
4322
+ sydsgl_isactive: this.fb.control(true, [Validators.required]),
4323
+ sydsgl_entity_id_syen: this.fb.control(this.appState.getActiveEntityId() || '', [Validators.required])
4324
+ });
4325
+ // Grid configuration signal
4326
+ gridConfig = signal({
4327
+ id: 'grade-level-list-grid',
4328
+ title: '',
4329
+ subtitle: '',
4330
+ columns: [
4331
+ {
4332
+ key: 'dragHandle',
4333
+ header: '',
4334
+ type: 'custom',
4335
+ width: '40px',
4336
+ truncate: false,
4337
+ align: 'center',
4338
+ renderer: 'dragHandleRenderer'
4339
+ },
4340
+ {
4341
+ key: 'details',
4342
+ header: 'Grade Level',
4343
+ type: 'custom',
4344
+ width: 'auto',
4345
+ truncate: true,
4346
+ align: 'left',
4347
+ renderer: 'gradeLevelDetailsRenderer'
4348
+ },
4349
+ {
4350
+ key: 'sydsgl_isactive',
4351
+ header: 'Status',
4352
+ type: 'custom',
4353
+ width: '100px',
4354
+ truncate: false,
4355
+ align: 'center',
4356
+ renderer: 'gradeLevelStatusRenderer'
4357
+ },
4358
+ {
4359
+ key: 'actions',
4360
+ header: '',
4361
+ type: 'custom',
4362
+ width: '60px',
4363
+ truncate: false,
4364
+ align: 'center',
4365
+ renderer: 'actionsDropdownRenderer'
4366
+ }
4367
+ ],
4368
+ data: [],
4369
+ trackBy: '_id',
4370
+ dragDrop: {
4371
+ enabled: true,
4372
+ orderField: 'sydsgl_order',
4373
+ dragClass: 'tw-opacity-50 tw-bg-blue-50',
4374
+ dropClass: 'tw-bg-green-50'
4375
+ },
4376
+ pagination: {
4377
+ enabled: true,
4378
+ pageSize: 10,
4379
+ pageSizeOptions: [10, 25, 50, 100],
4380
+ showQuickJump: true,
4381
+ showPageInfo: true,
4382
+ showRefresh: true
4383
+ },
4384
+ search: {
4385
+ enabled: true,
4386
+ placeholder: 'Search grade levels...',
4387
+ searchableColumns: ['sydsgl_name', 'sydsgl_description'],
4388
+ debounceMs: 300
4389
+ },
4390
+ loading: {
4391
+ useDefer: true,
4392
+ skeletonRows: 5,
4393
+ showOverlay: false
4394
+ },
4395
+ scroll: {
4396
+ enabled: true,
4397
+ maxHeight: '',
4398
+ minHeight: '',
4399
+ stickyHeader: true,
4400
+ virtualScroll: false,
4401
+ rowHeight: 50
4402
+ },
4403
+ responsive: true,
4404
+ striped: false,
4405
+ bordered: true,
4406
+ compact: false,
4407
+ tableClass: 'tw-table-fixed tw-w-full tw-rounded-none',
4408
+ onRefresh: 'onGradeLevelRefresh'
4409
+ }, ...(ngDevMode ? [{ debugName: "gridConfig" }] : []));
4410
+ // Template renderers using Angular best practices
4411
+ templateRenderers = computed(() => ({
4412
+ dragHandleRenderer: this.dragHandleRendererTemplate(),
4413
+ gradeLevelDetailsRenderer: this.gradeLevelDetailsRendererTemplate(),
4414
+ gradeLevelStatusRenderer: this.gradeLevelStatusRendererTemplate(),
4415
+ actionsDropdownRenderer: this.actionsDropdownRendererTemplate()
4416
+ }), ...(ngDevMode ? [{ debugName: "templateRenderers" }] : []));
4283
4417
  /**
4284
4418
  * Get template renderers for data grid
4285
4419
  */
4286
4420
  getTemplateRenderers() {
4287
4421
  return this.templateRenderers();
4288
4422
  }
4423
+ // Mixed renderers (templates + string functions)
4424
+ customRenderers = computed(() => ({
4425
+ ...this.templateRenderers()
4426
+ }), ...(ngDevMode ? [{ debugName: "customRenderers" }] : []));
4289
4427
  /**
4290
4428
  * Get custom renderers adapted for current data grid compatibility
4291
4429
  */
4292
4430
  getCustomRenderers() {
4293
4431
  return {};
4294
4432
  }
4433
+ // Action handlers for grid actions
4434
+ actionHandlers = {
4435
+ onEditGradeLevel: (row) => this.editGradeLevel(row._id || ''),
4436
+ onToggleGradeLevel: (row) => this.toggleGradeLevelStatus(row._id || ''),
4437
+ onDeleteGradeLevel: (row) => this.deleteGradeLevel(row._id || ''),
4438
+ onGradeLevelRowClick: (row) => this.onGradeLevelRowClick(row),
4439
+ onGradeLevelRefresh: () => this.onGradeLevelRefresh(),
4440
+ resetOrder: () => this.resetDragOrder(),
4441
+ saveOrder: () => this.saveGradeLevelOrder()
4442
+ };
4443
+ // Computed properties
4444
+ filteredItems = computed(() => {
4445
+ const items = this.gradeLevels();
4446
+ const search = this.searchTerm()?.toLowerCase();
4447
+ if (!search)
4448
+ return items;
4449
+ return items.filter(item => {
4450
+ return item.sydsgl_name?.toLowerCase().includes(search) ||
4451
+ item.sydsgl_description?.toLowerCase().includes(search);
4452
+ });
4453
+ }, ...(ngDevMode ? [{ debugName: "filteredItems" }] : []));
4454
+ hasSelection = computed(() => this.selectedItems().length > 0, ...(ngDevMode ? [{ debugName: "hasSelection" }] : []));
4455
+ // Pagination computed properties
4456
+ totalPages = computed(() => Math.ceil(this.totalItems() / this.pageSize()), ...(ngDevMode ? [{ debugName: "totalPages" }] : []));
4457
+ hasNextPage = computed(() => this.currentPage() < this.totalPages(), ...(ngDevMode ? [{ debugName: "hasNextPage" }] : []));
4458
+ hasPreviousPage = computed(() => this.currentPage() > 1, ...(ngDevMode ? [{ debugName: "hasPreviousPage" }] : []));
4459
+ // Computed property for next order
4460
+ nextOrder = computed(() => this.calculateNextOrder(), ...(ngDevMode ? [{ debugName: "nextOrder" }] : []));
4295
4461
  // Modern constructor with effects for initialization
4296
4462
  constructor() {
4297
- // Dependency injection
4298
- this.destroyRef = inject(DestroyRef);
4299
- this.gradeLevelService = inject(GradeLevelManagementService);
4300
- this.appState = inject(AppStateHelperService);
4301
- this.fb = inject(NonNullableFormBuilder);
4302
- this.router = inject(Router);
4303
- // Modern ViewChild signals for template renderers (Angular 20 approach)
4304
- this.dragHandleRendererTemplate = viewChild.required('dragHandleRendererTemplate');
4305
- this.gradeLevelDetailsRendererTemplate = viewChild.required('gradeLevelDetailsRendererTemplate');
4306
- this.gradeLevelStatusRendererTemplate = viewChild.required('gradeLevelStatusRendererTemplate');
4307
- this.actionsDropdownRendererTemplate = viewChild.required('actionsDropdownRendererTemplate');
4308
- // Make Math available in template
4309
- this.Math = Math;
4310
- // Signals for reactive state management
4311
- this.gradeLevels = signal([]);
4312
- this.loading = signal(false);
4313
- this.error = signal(null);
4314
- this.selectedItems = signal([]);
4315
- this.searchTerm = signal('');
4316
- // Retrieved grade level data
4317
- this.retrievedGradeLevel = signal(null);
4318
- // Edit mode flag
4319
- this.isEditMode = signal(false);
4320
- // Drag order management
4321
- this.originalOrder = signal([]);
4322
- this.hasOrderChanged = signal(false);
4323
- // Server-side pagination state
4324
- this.currentPage = signal(1);
4325
- this.pageSize = signal(10);
4326
- this.totalItems = signal(0);
4327
- // Modern reactive form with typed controls
4328
- this.quickAddForm = this.fb.group({
4329
- sydsgl_name: this.fb.control('', [Validators.required, Validators.minLength(1), Validators.maxLength(20)]),
4330
- sydsgl_description: this.fb.control('', [Validators.maxLength(400)]),
4331
- sydsgl_order: this.fb.control(1, [Validators.required, Validators.min(1), Validators.max(100)]),
4332
- sydsgl_isactive: this.fb.control(true, [Validators.required]),
4333
- sydsgl_entity_id_syen: this.fb.control(this.appState.getActiveEntityId() || '', [Validators.required])
4334
- });
4335
- // Grid configuration signal
4336
- this.gridConfig = signal({
4337
- id: 'grade-level-list-grid',
4338
- title: '',
4339
- subtitle: '',
4340
- columns: [
4341
- {
4342
- key: 'dragHandle',
4343
- header: '',
4344
- type: 'custom',
4345
- width: '40px',
4346
- truncate: false,
4347
- align: 'center',
4348
- renderer: 'dragHandleRenderer'
4349
- },
4350
- {
4351
- key: 'details',
4352
- header: 'Grade Level',
4353
- type: 'custom',
4354
- width: 'auto',
4355
- truncate: true,
4356
- align: 'left',
4357
- renderer: 'gradeLevelDetailsRenderer'
4358
- },
4359
- {
4360
- key: 'sydsgl_isactive',
4361
- header: 'Status',
4362
- type: 'custom',
4363
- width: '100px',
4364
- truncate: false,
4365
- align: 'center',
4366
- renderer: 'gradeLevelStatusRenderer'
4367
- },
4368
- {
4369
- key: 'actions',
4370
- header: '',
4371
- type: 'custom',
4372
- width: '60px',
4373
- truncate: false,
4374
- align: 'center',
4375
- renderer: 'actionsDropdownRenderer'
4376
- }
4377
- ],
4378
- data: [],
4379
- trackBy: '_id',
4380
- dragDrop: {
4381
- enabled: true,
4382
- orderField: 'sydsgl_order',
4383
- dragClass: 'tw-opacity-50 tw-bg-blue-50',
4384
- dropClass: 'tw-bg-green-50'
4385
- },
4386
- pagination: {
4387
- enabled: true,
4388
- pageSize: 10,
4389
- pageSizeOptions: [10, 25, 50, 100],
4390
- showQuickJump: true,
4391
- showPageInfo: true,
4392
- showRefresh: true
4393
- },
4394
- search: {
4395
- enabled: true,
4396
- placeholder: 'Search grade levels...',
4397
- searchableColumns: ['sydsgl_name', 'sydsgl_description'],
4398
- debounceMs: 300
4399
- },
4400
- loading: {
4401
- useDefer: true,
4402
- skeletonRows: 5,
4403
- showOverlay: false
4404
- },
4405
- scroll: {
4406
- enabled: true,
4407
- maxHeight: '',
4408
- minHeight: '',
4409
- stickyHeader: true,
4410
- virtualScroll: false,
4411
- rowHeight: 50
4412
- },
4413
- responsive: true,
4414
- striped: false,
4415
- bordered: true,
4416
- compact: false,
4417
- tableClass: 'tw-table-fixed tw-w-full tw-rounded-none',
4418
- onRefresh: 'onGradeLevelRefresh'
4419
- });
4420
- // Template renderers using Angular best practices
4421
- this.templateRenderers = computed(() => ({
4422
- dragHandleRenderer: this.dragHandleRendererTemplate(),
4423
- gradeLevelDetailsRenderer: this.gradeLevelDetailsRendererTemplate(),
4424
- gradeLevelStatusRenderer: this.gradeLevelStatusRendererTemplate(),
4425
- actionsDropdownRenderer: this.actionsDropdownRendererTemplate()
4426
- }));
4427
- // Mixed renderers (templates + string functions)
4428
- this.customRenderers = computed(() => ({
4429
- ...this.templateRenderers()
4430
- }));
4431
- // Action handlers for grid actions
4432
- this.actionHandlers = {
4433
- onEditGradeLevel: (row) => this.editGradeLevel(row._id || ''),
4434
- onToggleGradeLevel: (row) => this.toggleGradeLevelStatus(row._id || ''),
4435
- onDeleteGradeLevel: (row) => this.deleteGradeLevel(row._id || ''),
4436
- onGradeLevelRowClick: (row) => this.onGradeLevelRowClick(row),
4437
- onGradeLevelRefresh: () => this.onGradeLevelRefresh(),
4438
- resetOrder: () => this.resetDragOrder(),
4439
- saveOrder: () => this.saveGradeLevelOrder()
4440
- };
4441
- // Computed properties
4442
- this.filteredItems = computed(() => {
4443
- const items = this.gradeLevels();
4444
- const search = this.searchTerm()?.toLowerCase();
4445
- if (!search)
4446
- return items;
4447
- return items.filter(item => {
4448
- return item.sydsgl_name?.toLowerCase().includes(search) ||
4449
- item.sydsgl_description?.toLowerCase().includes(search);
4450
- });
4451
- });
4452
- this.hasSelection = computed(() => this.selectedItems().length > 0);
4453
- // Pagination computed properties
4454
- this.totalPages = computed(() => Math.ceil(this.totalItems() / this.pageSize()));
4455
- this.hasNextPage = computed(() => this.currentPage() < this.totalPages());
4456
- this.hasPreviousPage = computed(() => this.currentPage() > 1);
4457
- // Computed property for next order
4458
- this.nextOrder = computed(() => this.calculateNextOrder());
4459
4463
  this.initializeComponent();
4460
4464
  this.destroyRef.onDestroy(() => {
4461
4465
  this.cleanupEventListeners();
@@ -5043,10 +5047,10 @@ class GradeLevelListComponent {
5043
5047
  trackByItemId(index, item) {
5044
5048
  return item._id || '';
5045
5049
  }
5046
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: GradeLevelListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
5047
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.7", type: GradeLevelListComponent, isStandalone: true, selector: "cide-core-app-grade-level-list", viewQueries: [{ propertyName: "dragHandleRendererTemplate", first: true, predicate: ["dragHandleRendererTemplate"], descendants: true, isSignal: true }, { propertyName: "gradeLevelDetailsRendererTemplate", first: true, predicate: ["gradeLevelDetailsRendererTemplate"], descendants: true, isSignal: true }, { propertyName: "gradeLevelStatusRendererTemplate", first: true, predicate: ["gradeLevelStatusRendererTemplate"], descendants: true, isSignal: true }, { propertyName: "actionsDropdownRendererTemplate", first: true, predicate: ["actionsDropdownRendererTemplate"], descendants: true, isSignal: true }], ngImport: i0, template: "<!-- Grade Level List Container -->\n<div class=\"tw-table tw-w-full tw-h-full\">\n\n <!-- Quick Add Form Section -->\n <div class=\"tw-table-row tw-h-0\">\n <div class=\"tw-table-cell tw-px-6 tw-py-4 tw-border-b tw-border-gray-200 tw-bg-white\">\n <div class=\"tw-flex tw-items-center tw-justify-between tw-mb-3\">\n <div class=\"tw-flex tw-items-center tw-space-x-3\">\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-5 tw-h-5\">{{ isEditMode() ? 'edit' : 'add' }}</cide-ele-icon>\n <h6 class=\"tw-text-sm tw-font-medium tw-text-gray-900 tw-m-0\">{{ isEditMode() ? 'Edit Grade Level' : 'Quick Add Grade Level' }}</h6>\n </div>\n </div>\n \n <form [formGroup]=\"quickAddForm\" (ngSubmit)=\"quickAddGradeLevel()\">\n <!-- First Row -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 lg:tw-grid-cols-4 tw-gap-3 tw-mb-3\">\n <!-- Grade Level Name -->\n <div>\n <cide-ele-input \n id=\"sydsgl_name\" \n label=\"Name*\" \n formControlName=\"sydsgl_name\"\n placeholder=\"Grade level name\"\n size=\"sm\">\n </cide-ele-input>\n </div>\n \n <!-- Active Status -->\n <div class=\"tw-flex tw-flex-col tw-justify-end\">\n <cide-ele-input \n id=\"sydsgl_isactive\"\n type=\"checkbox\"\n label=\"Active\"\n formControlName=\"sydsgl_isactive\"\n size=\"sm\">\n </cide-ele-input>\n </div>\n </div>\n \n <!-- Second Row -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 lg:tw-grid-cols-4 tw-gap-3 tw-items-end\">\n <!-- Description -->\n <div>\n <cide-ele-textarea \n id=\"sydsgl_description\" \n label=\"Description\" \n formControlName=\"sydsgl_description\"\n placeholder=\"Grade level description\"\n rows=\"2\"\n size=\"sm\">\n </cide-ele-textarea>\n </div>\n \n <!-- Entity ID (Hidden) -->\n <div class=\"tw-hidden\">\n <cide-ele-input \n id=\"sydsgl_entity_id_syen\" \n label=\"Entity ID*\" \n formControlName=\"sydsgl_entity_id_syen\"\n placeholder=\"Entity ID\"\n size=\"sm\">\n </cide-ele-input>\n </div>\n \n <!-- Action Buttons -->\n <div class=\"tw-flex tw-flex-col tw-justify-end\">\n <div class=\"tw-flex tw-space-x-2\">\n <button \n cideEleButton \n variant=\"primary\" \n size=\"sm\" \n type=\"submit\"\n [disabled]=\"quickAddForm.invalid\"\n class=\"tw-px-2 tw-py-1 tw-w-20\">\n <cide-ele-icon size=\"xs\" class=\"tw-w-4 tw-h-4 tw-mr-1\">{{ isEditMode() ? 'edit' : 'add' }}</cide-ele-icon>\n {{ isEditMode() ? 'Update' : 'Add' }}\n </button>\n <button \n cideEleButton \n variant=\"outline\" \n size=\"sm\" \n type=\"button\"\n (click)=\"resetQuickAddForm()\"\n class=\"tw-px-2 tw-py-1 tw-w-16\">\n <cide-ele-icon size=\"xs\" class=\"tw-w-4 tw-h-4 tw-mr-1\">refresh</cide-ele-icon>\n Reset\n </button>\n </div>\n </div>\n </div>\n </form>\n </div>\n </div>\n\n <!-- Header Section with Filters -->\n <div class=\"tw-table-row tw-h-0\">\n <div class=\"tw-table-cell tw-px-6 tw-py-3 tw-border-b tw-border-gray-200 tw-bg-gray-50\">\n <div\n class=\"tw-flex tw-flex-col sm:tw-flex-row tw-justify-between tw-items-start sm:tw-items-center tw-space-y-3 sm:tw-space-y-0\">\n\n <!-- Title -->\n <div class=\"tw-flex tw-items-center tw-space-x-2\">\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-5 tw-h-5\">school</cide-ele-icon>\n <h5 class=\"tw-text-base tw-font-medium tw-text-gray-900 tw-m-0\">Grade Level Management</h5>\n </div>\n\n <!-- Actions -->\n <div\n class=\"tw-flex tw-flex-col sm:tw-flex-row tw-items-start sm:tw-items-center tw-space-y-3 sm:tw-space-y-0 sm:tw-space-x-3\">\n <!-- Search functionality is handled by the data grid -->\n </div>\n </div>\n\n <!-- Error Message -->\n @if (error()) {\n <div class=\"tw-mt-4 tw-p-4 tw-bg-red-50 tw-border tw-border-red-200 tw-rounded-md\">\n <div class=\"tw-flex tw-items-start\">\n <cide-ele-icon name=\"error\" class=\"tw-text-red-400 tw-w-5 tw-h-5 tw-mt-0.5 tw-flex-shrink-0\"></cide-ele-icon>\n <div class=\"tw-ml-3\">\n <h3 class=\"tw-text-sm tw-font-medium tw-text-red-800 tw-m-0\">Error</h3>\n <p class=\"tw-text-sm tw-text-red-700 tw-mt-1 tw-m-0\">{{ error() }}</p>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n\n <!-- Main Content Area -->\n <div class=\"tw-table-row\">\n <div class=\"tw-table-cell tw-h-full tw-relative\">\n \n <!-- Data Grid Component -->\n <div class=\"tw-h-full tw-overflow-auto\">\n \n <cide-ele-data-grid \n [config]=\"gridConfig()\" \n [templateRenderers]=\"getTemplateRenderers()\"\n [actionHandlers]=\"actionHandlers\"\n [serverSidePagination]=\"true\" \n [totalServerItems]=\"totalItems()\" \n [currentServerPage]=\"currentPage()\"\n [currentServerPageSize]=\"pageSize()\" \n [dragDropEnabled]=\"true\"\n (gridEvent)=\"onGridEvent($event)\">\n </cide-ele-data-grid>\n </div>\n\n </div>\n </div>\n\n</div>\n\n<!-- Drag Handle Renderer Template -->\n<ng-template #dragHandleRendererTemplate let-row=\"row\" let-value=\"value\">\n <div class=\"tw-flex tw-items-center tw-justify-center tw-w-full tw-h-full tw-cursor-move drag-handle\">\n <cide-ele-icon \n class=\"tw-text-gray-400 hover:tw-text-gray-600 tw-transition-colors\" \n size=\"xs\">\n drag_indicator\n </cide-ele-icon>\n </div>\n</ng-template>\n\n<!-- Grade Level Details Renderer Template -->\n<ng-template #gradeLevelDetailsRendererTemplate let-row=\"row\" let-value=\"value\">\n <div class=\"tw-flex tw-items-center tw-min-w-0\">\n <!-- Grade Level Icon -->\n <div class=\"tw-flex-shrink-0\">\n <cide-ele-icon \n class=\"tw-text-gray-400\" \n size=\"xs\">\n school\n </cide-ele-icon>\n </div>\n \n <!-- Grade Level Details -->\n <div class=\"tw-ml-3 tw-min-w-0 tw-flex-1\">\n <div class=\"tw-text-sm tw-font-medium tw-text-gray-900 tw-truncate\" \n [title]=\"row.sydsgl_name\">\n {{ row.sydsgl_name || 'Untitled' }}\n </div>\n @if (row.sydsgl_description) {\n <div class=\"tw-text-xs tw-text-gray-500 tw-truncate\" \n [title]=\"row.sydsgl_description\">\n {{ row.sydsgl_description }}\n </div>\n }\n </div>\n </div>\n</ng-template>\n\n<!-- Grade Level Status Renderer Template -->\n<ng-template #gradeLevelStatusRendererTemplate let-row=\"row\" let-value=\"value\">\n <span class=\"tw-inline-flex tw-items-center tw-px-2.5 tw-py-0.5 tw-rounded-full tw-text-xs tw-font-medium tw-whitespace-nowrap\"\n [ngClass]=\"getStatusClass(row.sydsgl_isactive)\">\n {{ getStatusDisplay(row.sydsgl_isactive) }}\n </span>\n</ng-template>\n\n<!-- Actions Dropdown Renderer Template -->\n<ng-template #actionsDropdownRendererTemplate let-row=\"row\" let-value=\"value\">\n <cide-ele-dropdown \n [items]=\"getDropdownItems(row)\"\n [config]=\"{ triggerIcon: 'more_vert', triggerSize: 'sm' }\"\n (itemClick)=\"onDropdownItemClick($event, row)\">\n </cide-ele-dropdown>\n</ng-template> ", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: FormsModule }, { kind: "component", type: CideEleDataGridComponent, selector: "cide-ele-data-grid", inputs: ["config", "customRenderers", "templateRenderers", "customFormatters", "actionHandlers", "serverSidePagination", "totalServerItems", "currentServerPage", "currentServerPageSize", "dragDropEnabled"], outputs: ["gridEvent"] }, { kind: "component", type: CideEleButtonComponent, selector: "button[cideEleButton], a[cideEleButton]", inputs: ["label", "variant", "size", "type", "shape", "elevation", "disabled", "id", "loading", "fullWidth", "leftIcon", "rightIcon", "customClass", "tooltip", "ariaLabel", "testId", "routerLink", "routerExtras", "preventDoubleClick", "animated"], outputs: ["btnClick", "doubleClick"] }, { kind: "component", type: CideInputComponent, selector: "cide-ele-input", inputs: ["fill", "label", "labelHide", "disabled", "clearInput", "labelPlacement", "labelDir", "placeholder", "leadingIcon", "trailingIcon", "helperText", "helperTextCollapse", "hideHelperAndErrorText", "errorText", "maxlength", "minlength", "required", "autocapitalize", "autocomplete", "type", "width", "id", "ngModel", "option", "min", "max", "size"], outputs: ["ngModelChange"] }, { kind: "component", type: CideTextareaComponent, selector: "cide-ele-textarea", inputs: ["label", "labelHide", "placeholder", "helperText", "errorText", "required", "disabled", "minlength", "maxlength", "rows", "id", "ngModel", "size", "fill", "labelPlacement", "labelDir", "leadingIcon", "trailingIcon", "clearInput"], outputs: ["ngModelChange"] }, { kind: "component", type: CideIconComponent, selector: "cide-ele-icon", inputs: ["size", "type", "toolTip"] }, { kind: "component", type: CideEleDropdownComponent, selector: "cide-ele-dropdown", inputs: ["items", "config", "triggerTemplate", "menuTemplate"], outputs: ["itemClick", "dropdownToggle"] }] }); }
5050
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: GradeLevelListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
5051
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.7", type: GradeLevelListComponent, isStandalone: true, selector: "cide-core-app-grade-level-list", viewQueries: [{ propertyName: "dragHandleRendererTemplate", first: true, predicate: ["dragHandleRendererTemplate"], descendants: true, isSignal: true }, { propertyName: "gradeLevelDetailsRendererTemplate", first: true, predicate: ["gradeLevelDetailsRendererTemplate"], descendants: true, isSignal: true }, { propertyName: "gradeLevelStatusRendererTemplate", first: true, predicate: ["gradeLevelStatusRendererTemplate"], descendants: true, isSignal: true }, { propertyName: "actionsDropdownRendererTemplate", first: true, predicate: ["actionsDropdownRendererTemplate"], descendants: true, isSignal: true }], ngImport: i0, template: "<!-- Grade Level List Container -->\n<div class=\"tw-table tw-w-full tw-h-full\">\n\n <!-- Quick Add Form Section -->\n <div class=\"tw-table-row tw-h-0\">\n <div class=\"tw-table-cell tw-px-6 tw-py-4 tw-border-b tw-border-gray-200 tw-bg-white\">\n <div class=\"tw-flex tw-items-center tw-justify-between tw-mb-3\">\n <div class=\"tw-flex tw-items-center tw-space-x-3\">\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-5 tw-h-5\">{{ isEditMode() ? 'edit' : 'add' }}</cide-ele-icon>\n <h6 class=\"tw-text-sm tw-font-medium tw-text-gray-900 tw-m-0\">{{ isEditMode() ? 'Edit Grade Level' : 'Quick Add Grade Level' }}</h6>\n </div>\n </div>\n \n <form [formGroup]=\"quickAddForm\" (ngSubmit)=\"quickAddGradeLevel()\">\n <!-- First Row -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 lg:tw-grid-cols-4 tw-gap-3 tw-mb-3\">\n <!-- Grade Level Name -->\n <div>\n <cide-ele-input \n id=\"sydsgl_name\" \n label=\"Name*\" \n formControlName=\"sydsgl_name\"\n placeholder=\"Grade level name\"\n size=\"sm\">\n </cide-ele-input>\n </div>\n \n <!-- Active Status -->\n <div class=\"tw-flex tw-flex-col tw-justify-end\">\n <cide-ele-input \n id=\"sydsgl_isactive\"\n type=\"checkbox\"\n label=\"Active\"\n formControlName=\"sydsgl_isactive\"\n size=\"sm\">\n </cide-ele-input>\n </div>\n </div>\n \n <!-- Second Row -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 lg:tw-grid-cols-4 tw-gap-3 tw-items-end\">\n <!-- Description -->\n <div>\n <cide-ele-textarea \n id=\"sydsgl_description\" \n label=\"Description\" \n formControlName=\"sydsgl_description\"\n placeholder=\"Grade level description\"\n rows=\"2\"\n size=\"sm\">\n </cide-ele-textarea>\n </div>\n \n <!-- Entity ID (Hidden) -->\n <div class=\"tw-hidden\">\n <cide-ele-input \n id=\"sydsgl_entity_id_syen\" \n label=\"Entity ID*\" \n formControlName=\"sydsgl_entity_id_syen\"\n placeholder=\"Entity ID\"\n size=\"sm\">\n </cide-ele-input>\n </div>\n \n <!-- Action Buttons -->\n <div class=\"tw-flex tw-flex-col tw-justify-end\">\n <div class=\"tw-flex tw-space-x-2\">\n <button \n cideEleButton \n variant=\"primary\" \n size=\"sm\" \n type=\"submit\"\n [disabled]=\"quickAddForm.invalid\"\n class=\"tw-px-2 tw-py-1 tw-w-20\">\n <cide-ele-icon size=\"xs\" class=\"tw-w-4 tw-h-4 tw-mr-1\">{{ isEditMode() ? 'edit' : 'add' }}</cide-ele-icon>\n {{ isEditMode() ? 'Update' : 'Add' }}\n </button>\n <button \n cideEleButton \n variant=\"outline\" \n size=\"sm\" \n type=\"button\"\n (click)=\"resetQuickAddForm()\"\n class=\"tw-px-2 tw-py-1 tw-w-16\">\n <cide-ele-icon size=\"xs\" class=\"tw-w-4 tw-h-4 tw-mr-1\">refresh</cide-ele-icon>\n Reset\n </button>\n </div>\n </div>\n </div>\n </form>\n </div>\n </div>\n\n <!-- Header Section with Filters -->\n <div class=\"tw-table-row tw-h-0\">\n <div class=\"tw-table-cell tw-px-6 tw-py-3 tw-border-b tw-border-gray-200 tw-bg-gray-50\">\n <div\n class=\"tw-flex tw-flex-col sm:tw-flex-row tw-justify-between tw-items-start sm:tw-items-center tw-space-y-3 sm:tw-space-y-0\">\n\n <!-- Title -->\n <div class=\"tw-flex tw-items-center tw-space-x-2\">\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-5 tw-h-5\">school</cide-ele-icon>\n <h5 class=\"tw-text-base tw-font-medium tw-text-gray-900 tw-m-0\">Grade Level Management</h5>\n </div>\n\n <!-- Actions -->\n <div\n class=\"tw-flex tw-flex-col sm:tw-flex-row tw-items-start sm:tw-items-center tw-space-y-3 sm:tw-space-y-0 sm:tw-space-x-3\">\n <!-- Search functionality is handled by the data grid -->\n </div>\n </div>\n\n <!-- Error Message -->\n @if (error()) {\n <div class=\"tw-mt-4 tw-p-4 tw-bg-red-50 tw-border tw-border-red-200 tw-rounded-md\">\n <div class=\"tw-flex tw-items-start\">\n <cide-ele-icon name=\"error\" class=\"tw-text-red-400 tw-w-5 tw-h-5 tw-mt-0.5 tw-flex-shrink-0\"></cide-ele-icon>\n <div class=\"tw-ml-3\">\n <h3 class=\"tw-text-sm tw-font-medium tw-text-red-800 tw-m-0\">Error</h3>\n <p class=\"tw-text-sm tw-text-red-700 tw-mt-1 tw-m-0\">{{ error() }}</p>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n\n <!-- Main Content Area -->\n <div class=\"tw-table-row\">\n <div class=\"tw-table-cell tw-h-full tw-relative\">\n \n <!-- Data Grid Component -->\n <div class=\"tw-h-full tw-overflow-auto\">\n \n <cide-ele-data-grid \n [config]=\"gridConfig()\" \n [templateRenderers]=\"getTemplateRenderers()\"\n [actionHandlers]=\"actionHandlers\"\n [serverSidePagination]=\"true\" \n [totalServerItems]=\"totalItems()\" \n [currentServerPage]=\"currentPage()\"\n [currentServerPageSize]=\"pageSize()\" \n [dragDropEnabled]=\"true\"\n (gridEvent)=\"onGridEvent($event)\">\n </cide-ele-data-grid>\n </div>\n\n </div>\n </div>\n\n</div>\n\n<!-- Drag Handle Renderer Template -->\n<ng-template #dragHandleRendererTemplate let-row=\"row\" let-value=\"value\">\n <div class=\"tw-flex tw-items-center tw-justify-center tw-w-full tw-h-full tw-cursor-move drag-handle\">\n <cide-ele-icon \n class=\"tw-text-gray-400 hover:tw-text-gray-600 tw-transition-colors\" \n size=\"xs\">\n drag_indicator\n </cide-ele-icon>\n </div>\n</ng-template>\n\n<!-- Grade Level Details Renderer Template -->\n<ng-template #gradeLevelDetailsRendererTemplate let-row=\"row\" let-value=\"value\">\n <div class=\"tw-flex tw-items-center tw-min-w-0\">\n <!-- Grade Level Icon -->\n <div class=\"tw-flex-shrink-0\">\n <cide-ele-icon \n class=\"tw-text-gray-400\" \n size=\"xs\">\n school\n </cide-ele-icon>\n </div>\n \n <!-- Grade Level Details -->\n <div class=\"tw-ml-3 tw-min-w-0 tw-flex-1\">\n <div class=\"tw-text-sm tw-font-medium tw-text-gray-900 tw-truncate\" \n [title]=\"row.sydsgl_name\">\n {{ row.sydsgl_name || 'Untitled' }}\n </div>\n @if (row.sydsgl_description) {\n <div class=\"tw-text-xs tw-text-gray-500 tw-truncate\" \n [title]=\"row.sydsgl_description\">\n {{ row.sydsgl_description }}\n </div>\n }\n </div>\n </div>\n</ng-template>\n\n<!-- Grade Level Status Renderer Template -->\n<ng-template #gradeLevelStatusRendererTemplate let-row=\"row\" let-value=\"value\">\n <span class=\"tw-inline-flex tw-items-center tw-px-2.5 tw-py-0.5 tw-rounded-full tw-text-xs tw-font-medium tw-whitespace-nowrap\"\n [ngClass]=\"getStatusClass(row.sydsgl_isactive)\">\n {{ getStatusDisplay(row.sydsgl_isactive) }}\n </span>\n</ng-template>\n\n<!-- Actions Dropdown Renderer Template -->\n<ng-template #actionsDropdownRendererTemplate let-row=\"row\" let-value=\"value\">\n <cide-ele-dropdown \n [items]=\"getDropdownItems(row)\"\n [config]=\"{ triggerIcon: 'more_vert', triggerSize: 'sm' }\"\n (itemClick)=\"onDropdownItemClick($event, row)\">\n </cide-ele-dropdown>\n</ng-template> ", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: FormsModule }, { kind: "component", type: CideEleDataGridComponent, selector: "cide-ele-data-grid", inputs: ["config", "customRenderers", "templateRenderers", "customFormatters", "actionHandlers", "serverSidePagination", "totalServerItems", "currentServerPage", "currentServerPageSize", "dragDropEnabled"], outputs: ["gridEvent"] }, { kind: "component", type: CideEleButtonComponent, selector: "button[cideEleButton], a[cideEleButton]", inputs: ["label", "variant", "size", "type", "shape", "elevation", "disabled", "id", "loading", "fullWidth", "leftIcon", "rightIcon", "customClass", "tooltip", "ariaLabel", "testId", "routerLink", "routerExtras", "preventDoubleClick", "animated"], outputs: ["btnClick", "doubleClick"] }, { kind: "component", type: CideInputComponent, selector: "cide-ele-input", inputs: ["fill", "label", "labelHide", "disabled", "clearInput", "labelPlacement", "labelDir", "placeholder", "leadingIcon", "trailingIcon", "helperText", "helperTextCollapse", "hideHelperAndErrorText", "errorText", "maxlength", "minlength", "required", "autocapitalize", "autocomplete", "type", "width", "id", "ngModel", "option", "min", "max", "size"], outputs: ["ngModelChange"] }, { kind: "component", type: CideTextareaComponent, selector: "cide-ele-textarea", inputs: ["label", "labelHide", "placeholder", "helperText", "errorText", "required", "disabled", "minlength", "maxlength", "rows", "id", "ngModel", "size", "fill", "labelPlacement", "labelDir", "leadingIcon", "trailingIcon", "clearInput"], outputs: ["ngModelChange"] }, { kind: "component", type: CideIconComponent, selector: "cide-ele-icon", inputs: ["size", "type", "toolTip"] }, { kind: "component", type: CideEleDropdownComponent, selector: "cide-ele-dropdown", inputs: ["items", "config", "triggerTemplate", "menuTemplate"], outputs: ["itemClick", "dropdownToggle"] }] });
5048
5052
  }
5049
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: GradeLevelListComponent, decorators: [{
5053
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: GradeLevelListComponent, decorators: [{
5050
5054
  type: Component,
5051
5055
  args: [{ selector: 'cide-core-app-grade-level-list', standalone: true, imports: [
5052
5056
  CommonModule,
@@ -5070,6 +5074,7 @@ var gradeLevelList_component = /*#__PURE__*/Object.freeze({
5070
5074
  // Grade Level Management Components
5071
5075
 
5072
5076
  class PageManagementService {
5077
+ http;
5073
5078
  constructor(http) {
5074
5079
  this.http = http;
5075
5080
  }
@@ -5151,10 +5156,10 @@ class PageManagementService {
5151
5156
  console.error('Page Management Service Error:', errorMessage);
5152
5157
  return throwError(() => new Error(errorMessage));
5153
5158
  }
5154
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: PageManagementService, deps: [{ token: i1.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable }); }
5155
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: PageManagementService, providedIn: 'root' }); }
5159
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: PageManagementService, deps: [{ token: i1.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable });
5160
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: PageManagementService, providedIn: 'root' });
5156
5161
  }
5157
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: PageManagementService, decorators: [{
5162
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: PageManagementService, decorators: [{
5158
5163
  type: Injectable,
5159
5164
  args: [{
5160
5165
  providedIn: 'root'
@@ -5162,110 +5167,110 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImpor
5162
5167
  }], ctorParameters: () => [{ type: i1.HttpClient }] });
5163
5168
 
5164
5169
  class PageListComponent {
5165
- constructor() {
5166
- // Dependency injection
5167
- this.destroyRef = inject(DestroyRef);
5168
- this.pageService = inject(PageManagementService);
5169
- this.appState = inject(AppStateHelperService);
5170
- this.router = inject(Router);
5171
- // Modern ViewChild signals for template renderers (Angular 20 approach)
5172
- this.pageDetailsRendererTemplate = viewChild.required('pageDetailsRendererTemplate');
5173
- this.pageStatusRendererTemplate = viewChild.required('pageStatusRendererTemplate');
5174
- this.actionsDropdownRendererTemplate = viewChild.required('actionsDropdownRendererTemplate');
5175
- // Make Math available in template
5176
- this.Math = Math;
5177
- // Signals for reactive state management
5178
- this.pages = signal([]);
5179
- this.loading = signal(false);
5180
- this.error = signal(null);
5181
- this.selectedItems = signal([]);
5182
- this.searchTerm = signal('');
5183
- // Pagination signals
5184
- this.currentPage = signal(1);
5185
- this.pageSize = signal(10);
5186
- this.totalItems = signal(0);
5187
- // Grid configuration signal
5188
- this.gridConfig = signal({
5189
- id: 'page-list-grid',
5190
- columns: [
5191
- {
5192
- key: 'details',
5193
- header: 'Page Details',
5194
- type: 'custom',
5195
- width: 'auto',
5196
- truncate: true,
5197
- align: 'left',
5198
- renderer: 'pageDetailsRenderer'
5199
- },
5200
- {
5201
- key: 'sypg_page_code',
5202
- header: 'Page Code',
5203
- type: 'text',
5204
- width: '150px',
5205
- truncate: true,
5206
- align: 'left'
5207
- },
5208
- {
5209
- key: 'sypg_isactive',
5210
- header: 'Status',
5211
- type: 'custom',
5212
- width: '100px',
5213
- truncate: false,
5214
- align: 'center',
5215
- renderer: 'pageStatusRenderer'
5216
- },
5217
- {
5218
- key: 'actions',
5219
- header: '',
5220
- type: 'custom',
5221
- width: '120px',
5222
- truncate: false,
5223
- align: 'center',
5224
- renderer: 'actionsDropdownRenderer'
5225
- }
5226
- ],
5227
- data: [],
5228
- trackBy: '_id',
5229
- pagination: {
5230
- enabled: true,
5231
- pageSize: 10,
5232
- pageSizeOptions: [10, 25, 50, 100],
5233
- showQuickJump: true,
5234
- showPageInfo: true,
5235
- showRefresh: true
5236
- },
5237
- search: {
5238
- enabled: true,
5239
- placeholder: 'Search pages...',
5240
- searchableColumns: ['sypg_title', 'sypg_desc', 'sypg_page_code'],
5241
- debounceMs: 300
5170
+ // Dependency injection
5171
+ destroyRef = inject(DestroyRef);
5172
+ pageService = inject(PageManagementService);
5173
+ appState = inject(AppStateHelperService);
5174
+ router = inject(Router);
5175
+ // Modern ViewChild signals for template renderers (Angular 20 approach)
5176
+ pageDetailsRendererTemplate = viewChild.required('pageDetailsRendererTemplate');
5177
+ pageStatusRendererTemplate = viewChild.required('pageStatusRendererTemplate');
5178
+ actionsDropdownRendererTemplate = viewChild.required('actionsDropdownRendererTemplate');
5179
+ // Make Math available in template
5180
+ Math = Math;
5181
+ // Signals for reactive state management
5182
+ pages = signal([], ...(ngDevMode ? [{ debugName: "pages" }] : []));
5183
+ loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
5184
+ error = signal(null, ...(ngDevMode ? [{ debugName: "error" }] : []));
5185
+ selectedItems = signal([], ...(ngDevMode ? [{ debugName: "selectedItems" }] : []));
5186
+ searchTerm = signal('', ...(ngDevMode ? [{ debugName: "searchTerm" }] : []));
5187
+ // Pagination signals
5188
+ currentPage = signal(1, ...(ngDevMode ? [{ debugName: "currentPage" }] : []));
5189
+ pageSize = signal(10, ...(ngDevMode ? [{ debugName: "pageSize" }] : []));
5190
+ totalItems = signal(0, ...(ngDevMode ? [{ debugName: "totalItems" }] : []));
5191
+ // Grid configuration signal
5192
+ gridConfig = signal({
5193
+ id: 'page-list-grid',
5194
+ columns: [
5195
+ {
5196
+ key: 'details',
5197
+ header: 'Page Details',
5198
+ type: 'custom',
5199
+ width: 'auto',
5200
+ truncate: true,
5201
+ align: 'left',
5202
+ renderer: 'pageDetailsRenderer'
5242
5203
  },
5243
- loading: {
5244
- useDefer: true,
5245
- skeletonRows: 5,
5246
- showOverlay: false
5204
+ {
5205
+ key: 'sypg_page_code',
5206
+ header: 'Page Code',
5207
+ type: 'text',
5208
+ width: '150px',
5209
+ truncate: true,
5210
+ align: 'left'
5247
5211
  },
5248
- scroll: {
5249
- enabled: true,
5250
- maxHeight: '',
5251
- minHeight: '',
5252
- stickyHeader: true,
5253
- virtualScroll: false,
5254
- rowHeight: 50
5212
+ {
5213
+ key: 'sypg_isactive',
5214
+ header: 'Status',
5215
+ type: 'custom',
5216
+ width: '100px',
5217
+ truncate: false,
5218
+ align: 'center',
5219
+ renderer: 'pageStatusRenderer'
5255
5220
  },
5256
- responsive: true,
5257
- striped: false,
5258
- bordered: true,
5259
- compact: false
5260
- });
5261
- // Action handlers for grid
5262
- this.actionHandlers = {
5263
- onEdit: (item) => this.editPage(item),
5264
- onDelete: (item) => this.deletePage(item),
5265
- onToggleStatus: (item) => this.togglePageStatus(item),
5266
- onManageThemes: (item) => this.manageThemes(item),
5267
- onManageControls: (item) => this.manageControls(item)
5268
- };
5221
+ {
5222
+ key: 'actions',
5223
+ header: '',
5224
+ type: 'custom',
5225
+ width: '120px',
5226
+ truncate: false,
5227
+ align: 'center',
5228
+ renderer: 'actionsDropdownRenderer'
5229
+ }
5230
+ ],
5231
+ data: [],
5232
+ trackBy: '_id',
5233
+ pagination: {
5234
+ enabled: true,
5235
+ pageSize: 10,
5236
+ pageSizeOptions: [10, 25, 50, 100],
5237
+ showQuickJump: true,
5238
+ showPageInfo: true,
5239
+ showRefresh: true
5240
+ },
5241
+ search: {
5242
+ enabled: true,
5243
+ placeholder: 'Search pages...',
5244
+ searchableColumns: ['sypg_title', 'sypg_desc', 'sypg_page_code'],
5245
+ debounceMs: 300
5246
+ },
5247
+ loading: {
5248
+ useDefer: true,
5249
+ skeletonRows: 5,
5250
+ showOverlay: false
5251
+ },
5252
+ scroll: {
5253
+ enabled: true,
5254
+ maxHeight: '',
5255
+ minHeight: '',
5256
+ stickyHeader: true,
5257
+ virtualScroll: false,
5258
+ rowHeight: 50
5259
+ },
5260
+ responsive: true,
5261
+ striped: false,
5262
+ bordered: true,
5263
+ compact: false
5264
+ }, ...(ngDevMode ? [{ debugName: "gridConfig" }] : []));
5265
+ // Action handlers for grid
5266
+ actionHandlers = {
5267
+ onEdit: (item) => this.editPage(item),
5268
+ onDelete: (item) => this.deletePage(item),
5269
+ onToggleStatus: (item) => this.togglePageStatus(item),
5270
+ onManageThemes: (item) => this.manageThemes(item),
5271
+ onManageControls: (item) => this.manageControls(item)
5272
+ };
5273
+ constructor() {
5269
5274
  this.initializeComponent();
5270
5275
  }
5271
5276
  /**
@@ -5530,10 +5535,10 @@ class PageListComponent {
5530
5535
  const event = new MouseEvent('click', { bubbles: true });
5531
5536
  document.dispatchEvent(event);
5532
5537
  }
5533
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: PageListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
5534
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.7", type: PageListComponent, isStandalone: true, selector: "cide-core-app-page-list", viewQueries: [{ propertyName: "pageDetailsRendererTemplate", first: true, predicate: ["pageDetailsRendererTemplate"], descendants: true, isSignal: true }, { propertyName: "pageStatusRendererTemplate", first: true, predicate: ["pageStatusRendererTemplate"], descendants: true, isSignal: true }, { propertyName: "actionsDropdownRendererTemplate", first: true, predicate: ["actionsDropdownRendererTemplate"], descendants: true, isSignal: true }], ngImport: i0, template: "<!-- Page List Container -->\n<div class=\"tw-table tw-w-full tw-h-full\">\n\n <!-- Header Section with Filters -->\n <div class=\"tw-table-row tw-h-0\">\n <div class=\"tw-table-cell tw-px-6 tw-py-3 tw-border-b tw-border-gray-200 tw-bg-gray-50\">\n <div class=\"tw-flex tw-flex-col sm:tw-flex-row tw-justify-between tw-items-start sm:tw-items-center tw-space-y-3 sm:tw-space-y-0\">\n\n <!-- Title -->\n <div class=\"tw-flex tw-items-center tw-space-x-2\">\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-5 tw-h-5\">web</cide-ele-icon>\n <h5 class=\"tw-text-base tw-font-medium tw-text-gray-900 tw-m-0\">Page Management</h5>\n </div>\n\n <!-- Actions -->\n <div class=\"tw-flex tw-flex-col sm:tw-flex-row tw-items-start sm:tw-items-center tw-space-y-3 sm:tw-space-y-0 sm:tw-space-x-3\">\n <!-- Add Page Button -->\n <button\n cideEleButton\n variant=\"primary\"\n size=\"sm\"\n (click)=\"createPage()\"\n leftIcon=\"add\"\n class=\"tw-whitespace-nowrap tw-flex tw-items-center tw-gap-2\">\n Create New Page\n </button>\n </div>\n </div>\n\n <!-- Error Message -->\n @if (error()) {\n <div class=\"tw-mt-4 tw-p-4 tw-bg-red-50 tw-border tw-border-red-200 tw-rounded-md\">\n <div class=\"tw-flex tw-items-start\">\n <cide-ele-icon class=\"tw-text-red-400 tw-w-5 tw-h-5 tw-mt-0.5 tw-flex-shrink-0\">error</cide-ele-icon>\n <div class=\"tw-ml-3\">\n <h3 class=\"tw-text-sm tw-font-medium tw-text-red-800 tw-m-0\">Error</h3>\n <p class=\"tw-text-sm tw-text-red-700 tw-mt-1 tw-m-0\">{{ error() }}</p>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n\n <!-- Main Content Area -->\n <div class=\"tw-table-row\">\n <div class=\"tw-table-cell tw-h-full tw-relative\">\n \n <!-- Data Grid Component -->\n <div class=\"tw-h-full tw-overflow-auto\">\n <cide-ele-data-grid\n [config]=\"gridConfig()\"\n [templateRenderers]=\"getTemplateRenderers()\"\n [actionHandlers]=\"actionHandlers\"\n [serverSidePagination]=\"true\"\n [totalServerItems]=\"totalItems()\"\n [currentServerPage]=\"currentPage()\"\n [currentServerPageSize]=\"pageSize()\"\n (gridEvent)=\"onGridEvent($event)\">\n </cide-ele-data-grid>\n </div>\n\n </div>\n </div>\n\n</div>\n\n<!-- Page Details Renderer Template -->\n<ng-template #pageDetailsRendererTemplate let-row=\"row\" let-value=\"value\">\n <div class=\"tw-flex tw-items-center tw-min-w-0\">\n <!-- Page Icon -->\n <div class=\"tw-flex-shrink-0\">\n <cide-ele-icon class=\"tw-text-gray-400 tw-w-4 tw-h-4\">web</cide-ele-icon>\n </div>\n \n <!-- Page Details -->\n <div class=\"tw-ml-3 tw-min-w-0 tw-flex-1\">\n <div class=\"tw-text-sm tw-font-medium tw-text-gray-900 tw-truncate\" \n [title]=\"row.sypg_title\">\n {{ row.sypg_title || 'Untitled' }}\n </div>\n @if (row.sypg_desc) {\n <div class=\"tw-text-xs tw-text-gray-500 tw-truncate\" \n [title]=\"row.sypg_desc\">\n {{ row.sypg_desc }}\n </div>\n }\n </div>\n </div>\n</ng-template>\n\n<!-- Page Status Renderer Template -->\n<ng-template #pageStatusRendererTemplate let-row=\"row\" let-value=\"value\">\n <span class=\"tw-inline-flex tw-items-center tw-px-2.5 tw-py-0.5 tw-rounded-full tw-text-xs tw-font-medium tw-whitespace-nowrap\"\n [ngClass]=\"row.sypg_isactive ? 'tw-bg-green-100 tw-text-green-800' : 'tw-bg-red-100 tw-text-red-800'\">\n {{ row.sypg_isactive ? 'Active' : 'Inactive' }}\n </span>\n</ng-template>\n\n<!-- Actions Dropdown Renderer Template -->\n<ng-template #actionsDropdownRendererTemplate let-row=\"row\" let-value=\"value\">\n <cide-ele-dropdown\n [items]=\"getActionDropdownItems(row)\"\n [config]=\"{ triggerIcon: 'more_vert', triggerSize: 'sm' }\"\n (itemClick)=\"onDropdownItemClick($event, row)\">\n </cide-ele-dropdown>\n</ng-template> ", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: CideEleDataGridComponent, selector: "cide-ele-data-grid", inputs: ["config", "customRenderers", "templateRenderers", "customFormatters", "actionHandlers", "serverSidePagination", "totalServerItems", "currentServerPage", "currentServerPageSize", "dragDropEnabled"], outputs: ["gridEvent"] }, { kind: "component", type: CideEleButtonComponent, selector: "button[cideEleButton], a[cideEleButton]", inputs: ["label", "variant", "size", "type", "shape", "elevation", "disabled", "id", "loading", "fullWidth", "leftIcon", "rightIcon", "customClass", "tooltip", "ariaLabel", "testId", "routerLink", "routerExtras", "preventDoubleClick", "animated"], outputs: ["btnClick", "doubleClick"] }, { kind: "component", type: CideIconComponent, selector: "cide-ele-icon", inputs: ["size", "type", "toolTip"] }, { kind: "component", type: CideEleDropdownComponent, selector: "cide-ele-dropdown", inputs: ["items", "config", "triggerTemplate", "menuTemplate"], outputs: ["itemClick", "dropdownToggle"] }] }); }
5538
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: PageListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
5539
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.7", type: PageListComponent, isStandalone: true, selector: "cide-core-app-page-list", viewQueries: [{ propertyName: "pageDetailsRendererTemplate", first: true, predicate: ["pageDetailsRendererTemplate"], descendants: true, isSignal: true }, { propertyName: "pageStatusRendererTemplate", first: true, predicate: ["pageStatusRendererTemplate"], descendants: true, isSignal: true }, { propertyName: "actionsDropdownRendererTemplate", first: true, predicate: ["actionsDropdownRendererTemplate"], descendants: true, isSignal: true }], ngImport: i0, template: "<!-- Page List Container -->\n<div class=\"tw-table tw-w-full tw-h-full\">\n\n <!-- Header Section with Filters -->\n <div class=\"tw-table-row tw-h-0\">\n <div class=\"tw-table-cell tw-px-6 tw-py-3 tw-border-b tw-border-gray-200 tw-bg-gray-50\">\n <div class=\"tw-flex tw-flex-col sm:tw-flex-row tw-justify-between tw-items-start sm:tw-items-center tw-space-y-3 sm:tw-space-y-0\">\n\n <!-- Title -->\n <div class=\"tw-flex tw-items-center tw-space-x-2\">\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-5 tw-h-5\">web</cide-ele-icon>\n <h5 class=\"tw-text-base tw-font-medium tw-text-gray-900 tw-m-0\">Page Management</h5>\n </div>\n\n <!-- Actions -->\n <div class=\"tw-flex tw-flex-col sm:tw-flex-row tw-items-start sm:tw-items-center tw-space-y-3 sm:tw-space-y-0 sm:tw-space-x-3\">\n <!-- Add Page Button -->\n <button\n cideEleButton\n variant=\"primary\"\n size=\"sm\"\n (click)=\"createPage()\"\n leftIcon=\"add\"\n class=\"tw-whitespace-nowrap tw-flex tw-items-center tw-gap-2\">\n Create New Page\n </button>\n </div>\n </div>\n\n <!-- Error Message -->\n @if (error()) {\n <div class=\"tw-mt-4 tw-p-4 tw-bg-red-50 tw-border tw-border-red-200 tw-rounded-md\">\n <div class=\"tw-flex tw-items-start\">\n <cide-ele-icon class=\"tw-text-red-400 tw-w-5 tw-h-5 tw-mt-0.5 tw-flex-shrink-0\">error</cide-ele-icon>\n <div class=\"tw-ml-3\">\n <h3 class=\"tw-text-sm tw-font-medium tw-text-red-800 tw-m-0\">Error</h3>\n <p class=\"tw-text-sm tw-text-red-700 tw-mt-1 tw-m-0\">{{ error() }}</p>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n\n <!-- Main Content Area -->\n <div class=\"tw-table-row\">\n <div class=\"tw-table-cell tw-h-full tw-relative\">\n \n <!-- Data Grid Component -->\n <div class=\"tw-h-full tw-overflow-auto\">\n <cide-ele-data-grid\n [config]=\"gridConfig()\"\n [templateRenderers]=\"getTemplateRenderers()\"\n [actionHandlers]=\"actionHandlers\"\n [serverSidePagination]=\"true\"\n [totalServerItems]=\"totalItems()\"\n [currentServerPage]=\"currentPage()\"\n [currentServerPageSize]=\"pageSize()\"\n (gridEvent)=\"onGridEvent($event)\">\n </cide-ele-data-grid>\n </div>\n\n </div>\n </div>\n\n</div>\n\n<!-- Page Details Renderer Template -->\n<ng-template #pageDetailsRendererTemplate let-row=\"row\" let-value=\"value\">\n <div class=\"tw-flex tw-items-center tw-min-w-0\">\n <!-- Page Icon -->\n <div class=\"tw-flex-shrink-0\">\n <cide-ele-icon class=\"tw-text-gray-400 tw-w-4 tw-h-4\">web</cide-ele-icon>\n </div>\n \n <!-- Page Details -->\n <div class=\"tw-ml-3 tw-min-w-0 tw-flex-1\">\n <div class=\"tw-text-sm tw-font-medium tw-text-gray-900 tw-truncate\" \n [title]=\"row.sypg_title\">\n {{ row.sypg_title || 'Untitled' }}\n </div>\n @if (row.sypg_desc) {\n <div class=\"tw-text-xs tw-text-gray-500 tw-truncate\" \n [title]=\"row.sypg_desc\">\n {{ row.sypg_desc }}\n </div>\n }\n </div>\n </div>\n</ng-template>\n\n<!-- Page Status Renderer Template -->\n<ng-template #pageStatusRendererTemplate let-row=\"row\" let-value=\"value\">\n <span class=\"tw-inline-flex tw-items-center tw-px-2.5 tw-py-0.5 tw-rounded-full tw-text-xs tw-font-medium tw-whitespace-nowrap\"\n [ngClass]=\"row.sypg_isactive ? 'tw-bg-green-100 tw-text-green-800' : 'tw-bg-red-100 tw-text-red-800'\">\n {{ row.sypg_isactive ? 'Active' : 'Inactive' }}\n </span>\n</ng-template>\n\n<!-- Actions Dropdown Renderer Template -->\n<ng-template #actionsDropdownRendererTemplate let-row=\"row\" let-value=\"value\">\n <cide-ele-dropdown\n [items]=\"getActionDropdownItems(row)\"\n [config]=\"{ triggerIcon: 'more_vert', triggerSize: 'sm' }\"\n (itemClick)=\"onDropdownItemClick($event, row)\">\n </cide-ele-dropdown>\n</ng-template> ", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: CideEleDataGridComponent, selector: "cide-ele-data-grid", inputs: ["config", "customRenderers", "templateRenderers", "customFormatters", "actionHandlers", "serverSidePagination", "totalServerItems", "currentServerPage", "currentServerPageSize", "dragDropEnabled"], outputs: ["gridEvent"] }, { kind: "component", type: CideEleButtonComponent, selector: "button[cideEleButton], a[cideEleButton]", inputs: ["label", "variant", "size", "type", "shape", "elevation", "disabled", "id", "loading", "fullWidth", "leftIcon", "rightIcon", "customClass", "tooltip", "ariaLabel", "testId", "routerLink", "routerExtras", "preventDoubleClick", "animated"], outputs: ["btnClick", "doubleClick"] }, { kind: "component", type: CideIconComponent, selector: "cide-ele-icon", inputs: ["size", "type", "toolTip"] }, { kind: "component", type: CideEleDropdownComponent, selector: "cide-ele-dropdown", inputs: ["items", "config", "triggerTemplate", "menuTemplate"], outputs: ["itemClick", "dropdownToggle"] }] });
5535
5540
  }
5536
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: PageListComponent, decorators: [{
5541
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: PageListComponent, decorators: [{
5537
5542
  type: Component,
5538
5543
  args: [{ selector: 'cide-core-app-page-list', standalone: true, imports: [
5539
5544
  CommonModule,
@@ -5550,9 +5555,10 @@ var pageList_component = /*#__PURE__*/Object.freeze({
5550
5555
  });
5551
5556
 
5552
5557
  class PageThemeService {
5558
+ http;
5559
+ apiUrl = `${coreRoutesUrl?.pageTheme}`;
5553
5560
  constructor(http) {
5554
5561
  this.http = http;
5555
- this.apiUrl = `${coreRoutesUrl?.pageTheme}`;
5556
5562
  console.log('PageThemeService initialized - using real API');
5557
5563
  }
5558
5564
  /**
@@ -5640,10 +5646,10 @@ class PageThemeService {
5640
5646
  console.error('Page Theme Service Error:', errorMessage);
5641
5647
  return throwError(() => new Error(errorMessage));
5642
5648
  }
5643
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: PageThemeService, deps: [{ token: i1.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable }); }
5644
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: PageThemeService, providedIn: 'root' }); }
5649
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: PageThemeService, deps: [{ token: i1.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable });
5650
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: PageThemeService, providedIn: 'root' });
5645
5651
  }
5646
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: PageThemeService, decorators: [{
5652
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: PageThemeService, decorators: [{
5647
5653
  type: Injectable,
5648
5654
  args: [{
5649
5655
  providedIn: 'root'
@@ -5651,171 +5657,38 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImpor
5651
5657
  }], ctorParameters: () => [{ type: i1.HttpClient }] });
5652
5658
 
5653
5659
  class PageThemeComponent {
5654
- constructor() {
5655
- // Dependency injection
5656
- this.destroyRef = inject(DestroyRef);
5657
- this.themeService = inject(PageThemeService);
5658
- this.appState = inject(AppStateHelperService);
5659
- this.fb = inject(NonNullableFormBuilder);
5660
- this.router = inject(Router);
5661
- this.route = inject(ActivatedRoute);
5662
- // Modern ViewChild signals for template renderers (Angular 20 approach)
5663
- this.themeDetailsRendererTemplate = viewChild.required('themeDetailsRendererTemplate');
5664
- this.themeStatusRendererTemplate = viewChild.required('themeStatusRendererTemplate');
5665
- this.actionsDropdownRendererTemplate = viewChild.required('actionsDropdownRendererTemplate');
5666
- // Make Math available in template
5667
- this.Math = Math;
5668
- // Signals for reactive state management
5669
- this.themes = signal([]);
5670
- this.loading = signal(false);
5671
- this.error = signal(null);
5672
- this.selectedItems = signal([]);
5673
- this.searchTerm = signal('');
5674
- // Derived list filtered by searchTerm
5675
- this.filteredThemes = computed(() => {
5676
- const q = (this.searchTerm() || '').toLowerCase().trim();
5677
- const items = this.themes() || [];
5678
- if (!q)
5679
- return items;
5680
- return items.filter(t => {
5681
- const title = (t.sytm_title || '').toLowerCase();
5682
- const code = (t.sytm_theme_code || '').toLowerCase();
5683
- const desc = (t.sytm_desc || '').toLowerCase();
5684
- return title.includes(q) || code.includes(q) || desc.includes(q);
5685
- });
5686
- });
5687
- // Page information
5688
- this.pageId = signal('');
5689
- this.pageTitle = signal('');
5690
- // Form state
5691
- this.isEditMode = signal(false);
5692
- this.editingThemeId = signal(null);
5693
- this.retrievedTheme = signal(null);
5694
- // Pagination signals
5695
- this.currentPage = signal(1);
5696
- this.pageSize = signal(10);
5697
- this.totalItems = signal(0);
5698
- // Modern reactive forms with signals
5699
- this.themeForm = this.fb.group({
5700
- sytm_title: ['', [Validators.required]],
5701
- sytm_desc: [''],
5702
- sytm_theme_code: ['', [Validators.required]],
5703
- sytm_preview_id_fm: [''],
5704
- sytm_sub_title: [''],
5705
- sytm_configuration: ['{}'],
5706
- sytm_entity_id_syen: [''],
5707
- sytm_isselected: [false],
5708
- sytm_layout: this.fb.group({
5709
- sytm_layout_sidebar: this.fb.group({ status: [true] }),
5710
- sytm_layout_header: this.fb.group({ status: [true] }),
5711
- sytm_layout_footer: this.fb.group({ status: [false] }),
5712
- sytm_layout_breadcrumb: this.fb.group({ status: [true] }),
5713
- sytm_layout_console: this.fb.group({ status: [false] }),
5714
- sytm_layout_request: this.fb.group({ status: [false] }),
5715
- sytm_layout_drawer: this.fb.array([])
5716
- }),
5717
- sytm_isactive: [true]
5718
- });
5719
- // Computed values
5720
- this.isFormDirty = computed(() => this.themeForm.dirty);
5721
- // Multi-select options for layout sections
5722
- this.layoutOptions = [
5723
- { value: 'sidebar', label: 'Sidebar' },
5724
- { value: 'header', label: 'Header' },
5725
- { value: 'footer', label: 'Footer' },
5726
- { value: 'breadcrumb', label: 'Breadcrumb' },
5727
- { value: 'console', label: 'Console' },
5728
- { value: 'request', label: 'Request' }
5729
- ];
5730
- // Grid configuration signal
5731
- this.gridConfig = signal({
5732
- id: 'theme-list-grid',
5733
- title: '',
5734
- subtitle: '',
5735
- columns: [
5736
- {
5737
- key: 'details',
5738
- header: 'Theme Details',
5739
- type: 'custom',
5740
- width: 'auto',
5741
- truncate: true,
5742
- align: 'left',
5743
- renderer: 'themeDetailsRenderer'
5744
- },
5745
- {
5746
- key: 'sytm_theme_code',
5747
- header: 'Theme Code',
5748
- type: 'text',
5749
- width: '150px',
5750
- truncate: true,
5751
- align: 'left'
5752
- },
5753
- {
5754
- key: 'sytm_isactive',
5755
- header: 'Status',
5756
- type: 'custom',
5757
- width: '100px',
5758
- truncate: false,
5759
- align: 'center',
5760
- renderer: 'themeStatusRenderer'
5761
- },
5762
- {
5763
- key: 'actions',
5764
- header: '',
5765
- type: 'custom',
5766
- width: '120px',
5767
- truncate: false,
5768
- align: 'center',
5769
- renderer: 'actionsDropdownRenderer'
5770
- }
5771
- ],
5772
- data: [],
5773
- trackBy: '_id',
5774
- pagination: {
5775
- enabled: true,
5776
- pageSize: 10,
5777
- pageSizeOptions: [10, 25, 50, 100],
5778
- showQuickJump: true,
5779
- showPageInfo: true,
5780
- showRefresh: true
5781
- },
5782
- search: {
5783
- enabled: true,
5784
- placeholder: 'Search themes...',
5785
- searchableColumns: ['sytm_title', 'sytm_desc', 'sytm_theme_code'],
5786
- debounceMs: 300
5787
- },
5788
- loading: {
5789
- useDefer: true,
5790
- skeletonRows: 5,
5791
- showOverlay: false
5792
- },
5793
- scroll: {
5794
- enabled: true,
5795
- maxHeight: '',
5796
- minHeight: '',
5797
- stickyHeader: true,
5798
- virtualScroll: false,
5799
- rowHeight: 50
5800
- },
5801
- responsive: true,
5802
- striped: false,
5803
- bordered: true,
5804
- compact: false,
5805
- tableClass: 'tw-table-fixed tw-w-full tw-rounded-none'
5660
+ // Dependency injection
5661
+ destroyRef = inject(DestroyRef);
5662
+ themeService = inject(PageThemeService);
5663
+ appState = inject(AppStateHelperService);
5664
+ fb = inject(NonNullableFormBuilder);
5665
+ router = inject(Router);
5666
+ route = inject(ActivatedRoute);
5667
+ // Modern ViewChild signals for template renderers (Angular 20 approach)
5668
+ themeDetailsRendererTemplate = viewChild.required('themeDetailsRendererTemplate');
5669
+ themeStatusRendererTemplate = viewChild.required('themeStatusRendererTemplate');
5670
+ actionsDropdownRendererTemplate = viewChild.required('actionsDropdownRendererTemplate');
5671
+ // Make Math available in template
5672
+ Math = Math;
5673
+ // Signals for reactive state management
5674
+ themes = signal([], ...(ngDevMode ? [{ debugName: "themes" }] : []));
5675
+ loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
5676
+ error = signal(null, ...(ngDevMode ? [{ debugName: "error" }] : []));
5677
+ selectedItems = signal([], ...(ngDevMode ? [{ debugName: "selectedItems" }] : []));
5678
+ searchTerm = signal('', ...(ngDevMode ? [{ debugName: "searchTerm" }] : []));
5679
+ // Derived list filtered by searchTerm
5680
+ filteredThemes = computed(() => {
5681
+ const q = (this.searchTerm() || '').toLowerCase().trim();
5682
+ const items = this.themes() || [];
5683
+ if (!q)
5684
+ return items;
5685
+ return items.filter(t => {
5686
+ const title = (t.sytm_title || '').toLowerCase();
5687
+ const code = (t.sytm_theme_code || '').toLowerCase();
5688
+ const desc = (t.sytm_desc || '').toLowerCase();
5689
+ return title.includes(q) || code.includes(q) || desc.includes(q);
5806
5690
  });
5807
- // Action handlers for grid
5808
- this.actionHandlers = {
5809
- onEdit: (item) => this.editTheme(item),
5810
- onDelete: (item) => this.deleteTheme(item),
5811
- onToggleStatus: (item) => this.toggleThemeStatus(item)
5812
- };
5813
- // ===== Drawer (sytm_layout_drawer) helpers =====
5814
- this.drawerConfigOptions = [
5815
- { value: 'drawer_notes', label: 'Drawer Notes' },
5816
- { value: 'drawer_theme', label: 'Drawer Theme' }
5817
- ];
5818
- }
5691
+ }, ...(ngDevMode ? [{ debugName: "filteredThemes" }] : []));
5819
5692
  // Helper to resolve preview image URL safely
5820
5693
  getPreviewUrl(theme) {
5821
5694
  const id = theme?.sytm_preview_id_fm || '';
@@ -5835,6 +5708,49 @@ class PageThemeComponent {
5835
5708
  const target = event.target;
5836
5709
  this.searchTerm.set(target?.value ?? '');
5837
5710
  }
5711
+ // Page information
5712
+ pageId = signal('', ...(ngDevMode ? [{ debugName: "pageId" }] : []));
5713
+ pageTitle = signal('', ...(ngDevMode ? [{ debugName: "pageTitle" }] : []));
5714
+ // Form state
5715
+ isEditMode = signal(false, ...(ngDevMode ? [{ debugName: "isEditMode" }] : []));
5716
+ editingThemeId = signal(null, ...(ngDevMode ? [{ debugName: "editingThemeId" }] : []));
5717
+ retrievedTheme = signal(null, ...(ngDevMode ? [{ debugName: "retrievedTheme" }] : []));
5718
+ // Pagination signals
5719
+ currentPage = signal(1, ...(ngDevMode ? [{ debugName: "currentPage" }] : []));
5720
+ pageSize = signal(10, ...(ngDevMode ? [{ debugName: "pageSize" }] : []));
5721
+ totalItems = signal(0, ...(ngDevMode ? [{ debugName: "totalItems" }] : []));
5722
+ // Modern reactive forms with signals
5723
+ themeForm = this.fb.group({
5724
+ sytm_title: ['', [Validators.required]],
5725
+ sytm_desc: [''],
5726
+ sytm_theme_code: ['', [Validators.required]],
5727
+ sytm_preview_id_fm: [''],
5728
+ sytm_sub_title: [''],
5729
+ sytm_configuration: ['{}'],
5730
+ sytm_entity_id_syen: [''],
5731
+ sytm_isselected: [false],
5732
+ sytm_layout: this.fb.group({
5733
+ sytm_layout_sidebar: this.fb.group({ status: [true] }),
5734
+ sytm_layout_header: this.fb.group({ status: [true] }),
5735
+ sytm_layout_footer: this.fb.group({ status: [false] }),
5736
+ sytm_layout_breadcrumb: this.fb.group({ status: [true] }),
5737
+ sytm_layout_console: this.fb.group({ status: [false] }),
5738
+ sytm_layout_request: this.fb.group({ status: [false] }),
5739
+ sytm_layout_drawer: this.fb.array([])
5740
+ }),
5741
+ sytm_isactive: [true]
5742
+ });
5743
+ // Computed values
5744
+ isFormDirty = computed(() => this.themeForm.dirty, ...(ngDevMode ? [{ debugName: "isFormDirty" }] : []));
5745
+ // Multi-select options for layout sections
5746
+ layoutOptions = [
5747
+ { value: 'sidebar', label: 'Sidebar' },
5748
+ { value: 'header', label: 'Header' },
5749
+ { value: 'footer', label: 'Footer' },
5750
+ { value: 'breadcrumb', label: 'Breadcrumb' },
5751
+ { value: 'console', label: 'Console' },
5752
+ { value: 'request', label: 'Request' }
5753
+ ];
5838
5754
  // Read enabled selections from form values
5839
5755
  enabledLayoutSelections() {
5840
5756
  const layout = this.themeForm.get('sytm_layout');
@@ -5867,6 +5783,89 @@ class PageThemeComponent {
5867
5783
  setBool('sytm_layout.sytm_layout_console.status', selected.has('console'));
5868
5784
  setBool('sytm_layout.sytm_layout_request.status', selected.has('request'));
5869
5785
  }
5786
+ // Grid configuration signal
5787
+ gridConfig = signal({
5788
+ id: 'theme-list-grid',
5789
+ title: '',
5790
+ subtitle: '',
5791
+ columns: [
5792
+ {
5793
+ key: 'details',
5794
+ header: 'Theme Details',
5795
+ type: 'custom',
5796
+ width: 'auto',
5797
+ truncate: true,
5798
+ align: 'left',
5799
+ renderer: 'themeDetailsRenderer'
5800
+ },
5801
+ {
5802
+ key: 'sytm_theme_code',
5803
+ header: 'Theme Code',
5804
+ type: 'text',
5805
+ width: '150px',
5806
+ truncate: true,
5807
+ align: 'left'
5808
+ },
5809
+ {
5810
+ key: 'sytm_isactive',
5811
+ header: 'Status',
5812
+ type: 'custom',
5813
+ width: '100px',
5814
+ truncate: false,
5815
+ align: 'center',
5816
+ renderer: 'themeStatusRenderer'
5817
+ },
5818
+ {
5819
+ key: 'actions',
5820
+ header: '',
5821
+ type: 'custom',
5822
+ width: '120px',
5823
+ truncate: false,
5824
+ align: 'center',
5825
+ renderer: 'actionsDropdownRenderer'
5826
+ }
5827
+ ],
5828
+ data: [],
5829
+ trackBy: '_id',
5830
+ pagination: {
5831
+ enabled: true,
5832
+ pageSize: 10,
5833
+ pageSizeOptions: [10, 25, 50, 100],
5834
+ showQuickJump: true,
5835
+ showPageInfo: true,
5836
+ showRefresh: true
5837
+ },
5838
+ search: {
5839
+ enabled: true,
5840
+ placeholder: 'Search themes...',
5841
+ searchableColumns: ['sytm_title', 'sytm_desc', 'sytm_theme_code'],
5842
+ debounceMs: 300
5843
+ },
5844
+ loading: {
5845
+ useDefer: true,
5846
+ skeletonRows: 5,
5847
+ showOverlay: false
5848
+ },
5849
+ scroll: {
5850
+ enabled: true,
5851
+ maxHeight: '',
5852
+ minHeight: '',
5853
+ stickyHeader: true,
5854
+ virtualScroll: false,
5855
+ rowHeight: 50
5856
+ },
5857
+ responsive: true,
5858
+ striped: false,
5859
+ bordered: true,
5860
+ compact: false,
5861
+ tableClass: 'tw-table-fixed tw-w-full tw-rounded-none'
5862
+ }, ...(ngDevMode ? [{ debugName: "gridConfig" }] : []));
5863
+ // Action handlers for grid
5864
+ actionHandlers = {
5865
+ onEdit: (item) => this.editTheme(item),
5866
+ onDelete: (item) => this.deleteTheme(item),
5867
+ onToggleStatus: (item) => this.toggleThemeStatus(item)
5868
+ };
5870
5869
  ngOnInit() {
5871
5870
  this.initializeComponent();
5872
5871
  }
@@ -6317,6 +6316,11 @@ class PageThemeComponent {
6317
6316
  const event = new MouseEvent('click', { bubbles: true });
6318
6317
  document.dispatchEvent(event);
6319
6318
  }
6319
+ // ===== Drawer (sytm_layout_drawer) helpers =====
6320
+ drawerConfigOptions = [
6321
+ { value: 'drawer_notes', label: 'Drawer Notes' },
6322
+ { value: 'drawer_theme', label: 'Drawer Theme' }
6323
+ ];
6320
6324
  get drawerArray() {
6321
6325
  return this.themeForm.get('sytm_layout.sytm_layout_drawer');
6322
6326
  }
@@ -6384,10 +6388,10 @@ class PageThemeComponent {
6384
6388
  error: () => { this.loading.set(false); }
6385
6389
  });
6386
6390
  }
6387
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: PageThemeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
6388
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.7", type: PageThemeComponent, isStandalone: true, selector: "cide-core-app-page-theme", viewQueries: [{ propertyName: "themeDetailsRendererTemplate", first: true, predicate: ["themeDetailsRendererTemplate"], descendants: true, isSignal: true }, { propertyName: "themeStatusRendererTemplate", first: true, predicate: ["themeStatusRendererTemplate"], descendants: true, isSignal: true }, { propertyName: "actionsDropdownRendererTemplate", first: true, predicate: ["actionsDropdownRendererTemplate"], descendants: true, isSignal: true }], ngImport: i0, template: "<!-- Page Theme Container -->\r\n<div class=\"tw-flex tw-h-full tw-w-full\">\r\n \r\n <!-- Left: Form and header (60%) -->\r\n <div class=\"tw-w-full lg:tw-w-3/5 tw-flex tw-flex-col tw-border-r tw-border-gray-200\">\r\n\r\n <!-- Header Section -->\r\n <div class=\"tw-px-6 tw-py-3 tw-border-b tw-border-gray-200 tw-bg-gray-50\">\r\n <div class=\"tw-flex tw-flex-col sm:tw-flex-row tw-justify-between tw-items-start sm:tw-items-center tw-space-y-3 sm:tw-space-y-0\">\r\n\r\n <!-- Title and Back Button -->\r\n <div class=\"tw-flex tw-items-center tw-space-x-4\">\r\n <button cideEleButton variant=\"ghost\" size=\"sm\" (click)=\"goBack()\" class=\"tw-text-gray-600 hover:tw-text-gray-900\">\r\n <cide-ele-icon class=\"tw-w-4 tw-h-4\">arrow_back</cide-ele-icon>\r\n </button>\r\n <div class=\"tw-flex tw-items-center tw-space-x-2\">\r\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-5 tw-h-5\">palette</cide-ele-icon>\r\n <div>\r\n <h5 class=\"tw-text-base tw-font-medium tw-text-gray-900 tw-m-0\">Theme Management</h5>\r\n <p class=\"tw-text-sm tw-text-gray-500 tw-m-0\">Page: {{ pageTitle() }}</p>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Error Message -->\r\n @if (error()) {\r\n <div class=\"tw-mt-4 tw-p-4 tw-bg-red-50 tw-border tw-border-red-200 tw-rounded-md\">\r\n <div class=\"tw-flex tw-items-start\">\r\n <cide-ele-icon name=\"error\" class=\"tw-text-red-400 tw-w-5 tw-h-5 tw-mt-0.5 tw-flex-shrink-0\"></cide-ele-icon>\r\n <div class=\"tw-ml-3\">\r\n <h3 class=\"tw-text-sm tw-font-medium tw-text-red-800 tw-m-0\">Error</h3>\r\n <p class=\"tw-text-sm tw-text-red-700 tw-mt-1 tw-m-0\">{{ error() }}</p>\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- Quick Add/Edit Form Section -->\r\n <div class=\"tw-px-6 tw-py-4 tw-bg-white tw-overflow-auto\">\r\n <div class=\"tw-flex tw-items-center tw-justify-between tw-mb-3\">\r\n <div class=\"tw-flex tw-items-center tw-space-x-3\">\r\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-5 tw-h-5\">{{ isEditMode() ? 'edit' : 'add' }}</cide-ele-icon>\r\n <h6 class=\"tw-text-sm tw-font-medium tw-text-gray-900 tw-m-0\">{{ isEditMode() ? 'Edit Theme' : 'Quick Add Theme' }}</h6>\r\n </div>\r\n </div>\r\n\r\n <!-- Form (kept as-is) -->\r\n <form [formGroup]=\"themeForm\" (ngSubmit)=\"saveTheme()\" class=\"tw-space-y-4\">\r\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 lg:tw-grid-cols-3 tw-gap-4\">\r\n <!-- Theme Title -->\r\n <div class=\"tw-space-y-2\">\r\n <cide-ele-input id=\"sytm_title\" formControlName=\"sytm_title\" placeholder=\"Enter theme title\" label=\"Theme Title*\" size=\"sm\"></cide-ele-input>\r\n </div>\r\n <!-- Theme Code -->\r\n <div class=\"tw-space-y-2\">\r\n <cide-ele-input id=\"sytm_theme_code\" formControlName=\"sytm_theme_code\" placeholder=\"Enter theme code\" label=\"Theme Code*\" size=\"sm\"></cide-ele-input>\r\n </div>\r\n <!-- Status -->\r\n <div class=\"tw-space-y-2\">\r\n <cide-ele-input\r\n id=\"sytm_isactive_cb\"\r\n type=\"checkbox\"\r\n label=\"Active\"\r\n size=\"sm\"\r\n formControlName=\"sytm_isactive\">\r\n </cide-ele-input>\r\n </div>\r\n <!-- Sub Title -->\r\n <div class=\"tw-space-y-2\">\r\n <cide-ele-input id=\"sytm_sub_title\" formControlName=\"sytm_sub_title\" placeholder=\"Enter sub title\" label=\"Sub Title\" size=\"sm\"></cide-ele-input>\r\n </div>\r\n <!-- Preview ID -->\r\n <div class=\"tw-space-y-2\">\r\n <cide-ele-input id=\"sytm_preview_id_fm\" formControlName=\"sytm_preview_id_fm\" placeholder=\"Enter preview image ID\" label=\"Preview Image ID\" size=\"sm\"></cide-ele-input>\r\n </div>\r\n <!-- Description -->\r\n <div class=\"tw-space-y-2 md:tw-col-span-2\">\r\n <cide-ele-textarea id=\"sytm_desc\" formControlName=\"sytm_desc\" placeholder=\"Enter theme description\" rows=\"2\" label=\"Description\" size=\"sm\"></cide-ele-textarea>\r\n </div>\r\n <!-- Configuration JSON -->\r\n <div class=\"tw-space-y-2 md:tw-col-span-3\">\r\n <cide-ele-json-editor label=\"Configuration JSON\" formControlName=\"sytm_configuration\" [required]=\"true\" [config]=\"{\r\n showLineNumbers: true,\r\n autoFormat: true,\r\n validateOnChange: true,\r\n minHeight: 150,\r\n maxHeight: 300,\r\n placeholder: 'Enter theme configuration JSON...'\r\n }\" helperText=\"Enter valid JSON configuration for the theme\"></cide-ele-json-editor>\r\n </div>\r\n <!-- Layout Configuration + Selection: right-side checkbox list -->\r\n <div class=\"lg:tw-col-span-1 tw-space-y-2\">\r\n <div class=\"tw-text-sm tw-font-medium tw-text-gray-700\">Layout & Selection</div>\r\n <!-- Selected toggle -->\r\n <div class=\"tw-bg-white tw-border tw-border-gray-200 tw-rounded-md tw-px-3 tw-py-2\">\r\n <cide-ele-input\r\n id=\"sytm_isselected\"\r\n type=\"checkbox\"\r\n label=\"Selected (Default)\"\r\n size=\"sm\"\r\n formControlName=\"sytm_isselected\">\r\n </cide-ele-input>\r\n </div>\r\n <div formGroupName=\"sytm_layout\" class=\"tw-bg-white tw-border tw-border-gray-200 tw-rounded-md tw-divide-y tw-overflow-hidden\">\r\n <!-- Sidebar -->\r\n <div class=\"tw-px-3 tw-py-2\" formGroupName=\"sytm_layout_sidebar\">\r\n <cide-ele-input id=\"layout_sidebar_status\" type=\"checkbox\" label=\"Sidebar\" size=\"sm\" formControlName=\"status\"></cide-ele-input>\r\n </div>\r\n <!-- Header -->\r\n <div class=\"tw-px-3 tw-py-2\" formGroupName=\"sytm_layout_header\">\r\n <cide-ele-input id=\"layout_header_status\" type=\"checkbox\" label=\"Header\" size=\"sm\" formControlName=\"status\"></cide-ele-input>\r\n </div>\r\n <!-- Footer -->\r\n <div class=\"tw-px-3 tw-py-2\" formGroupName=\"sytm_layout_footer\">\r\n <cide-ele-input id=\"layout_footer_status\" type=\"checkbox\" label=\"Footer\" size=\"sm\" formControlName=\"status\"></cide-ele-input>\r\n </div>\r\n <!-- Breadcrumb -->\r\n <div class=\"tw-px-3 tw-py-2\" formGroupName=\"sytm_layout_breadcrumb\">\r\n <cide-ele-input id=\"layout_breadcrumb_status\" type=\"checkbox\" label=\"Breadcrumb\" size=\"sm\" formControlName=\"status\"></cide-ele-input>\r\n </div>\r\n <!-- Console -->\r\n <div class=\"tw-px-3 tw-py-2\" formGroupName=\"sytm_layout_console\">\r\n <cide-ele-input id=\"layout_console_status\" type=\"checkbox\" label=\"Console\" size=\"sm\" formControlName=\"status\"></cide-ele-input>\r\n </div>\r\n <!-- Request -->\r\n <div class=\"tw-px-3 tw-py-2\" formGroupName=\"sytm_layout_request\">\r\n <cide-ele-input id=\"layout_request_status\" type=\"checkbox\" label=\"Request\" size=\"sm\" formControlName=\"status\"></cide-ele-input>\r\n </div>\r\n </div>\r\n <p class=\"tw-text-xs tw-text-gray-500 tw-pt-1\">Toggle active sections. Only one theme can be selected as default. More options can be added here later.</p>\r\n </div>\r\n <!-- Drawer Configuration -->\r\n <div class=\"tw-space-y-2 md:tw-col-span-3\">\r\n <div class=\"tw-flex tw-items-center tw-justify-between\">\r\n <div class=\"tw-text-sm tw-font-medium tw-text-gray-700\">Drawers</div>\r\n <button cideEleButton type=\"button\" size=\"xs\" variant=\"outline\" (click)=\"addDrawer()\">\r\n Add Drawer\r\n </button>\r\n </div>\r\n\r\n <div formGroupName=\"sytm_layout\">\r\n <div class=\"tw-space-y-2\" formArrayName=\"sytm_layout_drawer\">\r\n <div *ngFor=\"let drawerGrp of drawerArray.controls; let i = index\" [formGroupName]=\"i\" class=\"tw-border tw-border-gray-200 tw-rounded-md tw-p-3 tw-flex tw-items-center tw-gap-3\">\r\n <cide-ele-input id=\"drawer_active_{{i}}\" type=\"checkbox\" label=\"Active\" size=\"sm\" formControlName=\"syth_status\"></cide-ele-input>\r\n <div class=\"tw-flex-1\">\r\n <cide-ele-select\r\n id=\"drawer_config_{{i}}\"\r\n label=\"Drawer For\"\r\n size=\"sm\"\r\n [options]=\"drawerConfigOptions\"\r\n formControlName=\"syth_config_syco_for\">\r\n </cide-ele-select>\r\n </div>\r\n <button cideEleButton type=\"button\" size=\"xs\" variant=\"ghost\" (click)=\"removeDrawer(i)\">\r\n <cide-ele-icon class=\"tw-w-4 tw-h-4\">delete</cide-ele-icon>\r\n </button>\r\n </div>\r\n <p class=\"tw-text-xs tw-text-gray-500\">Configure multiple drawers as needed.</p>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Form Actions -->\r\n <div class=\"tw-flex tw-flex-col tw-gap-2 tw-pt-4 tw-border-t tw-border-gray-200\">\r\n <div class=\"tw-flex tw-items-center tw-justify-end tw-space-x-3\">\r\n <button cideEleButton type=\"button\" variant=\"outline\" (click)=\"cancelForm()\" [disabled]=\"loading()\">Cancel</button>\r\n <button cideEleButton type=\"submit\" variant=\"primary\" leftIcon=\"add\" [disabled]=\"!themeForm.valid || loading()\" [loading]=\"loading()\">\r\n {{ isEditMode() ? 'Update Theme' : 'Create Theme' }}\r\n </button>\r\n </div>\r\n </div>\r\n </form>\r\n </div>\r\n </div>\r\n\r\n <!-- Right: Theme gallery (40%) -->\r\n <div class=\"tw-hidden lg:tw-flex tw-w-2/5 tw-flex-col\">\r\n <!-- (Header consolidated above) -->\r\n\r\n <!-- Gallery list -->\r\n <div class=\"tw-flex-1 tw-overflow-auto tw-bg-gray-50\">\r\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-3 tw-p-4\">\r\n @for (theme of filteredThemes(); track theme._id) {\r\n <div class=\"tw-rounded-md tw-transition tw-cursor-pointer tw-relative\"\r\n [ngClass]=\"theme.sytm_isselected\r\n ? 'tw-border tw-border-blue-500 tw-ring-2 tw-ring-blue-200 tw-bg-blue-50/50'\r\n : 'tw-bg-white tw-border tw-border-gray-200 hover:tw-shadow-sm'\"\r\n (click)=\"editTheme(theme)\"\r\n role=\"button\"\r\n tabindex=\"0\"\r\n [attr.aria-selected]=\"theme.sytm_isselected ? 'true' : 'false'\"\r\n [attr.aria-label]=\"'Edit theme ' + (theme.sytm_title || theme.sytm_theme_code)\"\r\n (keydown.enter)=\"editTheme(theme)\"\r\n (keydown.space)=\"$event.preventDefault(); editTheme(theme)\">\r\n\r\n <!-- Selected badge -->\r\n <div *ngIf=\"theme.sytm_isselected\"\r\n class=\"tw-absolute tw-top-2 tw-right-2 tw-flex tw-items-center tw-justify-center tw-w-6 tw-h-6 tw-rounded-full tw-bg-blue-600 tw-text-white\">\r\n <cide-ele-icon class=\"tw-w-4 tw-h-4\">check</cide-ele-icon>\r\n </div>\r\n \r\n <div class=\"tw-aspect-[16/9] tw-bg-gray-100 tw-rounded-t-md tw-overflow-hidden tw-flex tw-items-center tw-justify-center\">\r\n @if (getPreviewUrl(theme)) {\r\n <img [src]=\"getPreviewUrl(theme)\" class=\"tw-w-full tw-h-full tw-object-cover\" alt=\"Preview\" />\r\n } @else {\r\n <div class=\"tw-text-gray-400 tw-text-xs\">No preview</div>\r\n }\r\n </div>\r\n <div class=\"tw-p-3 tw-space-y-1\">\r\n <div class=\"tw-text-sm tw-font-medium tw-text-gray-900 tw-truncate\" [title]=\"theme.sytm_title\">{{ theme.sytm_title || 'Untitled Theme' }}</div>\r\n <div class=\"tw-text-xs tw-text-gray-500 tw-truncate\" [title]=\"theme.sytm_theme_code\">{{ theme.sytm_theme_code }}</div>\r\n <div class=\"tw-flex tw-items-center tw-justify-between tw-pt-1\">\r\n <span class=\"tw-inline-flex tw-items-center tw-gap-1 tw-text-xs\" [ngClass]=\"theme.sytm_isactive ? 'tw-text-green-700' : 'tw-text-red-700'\">\r\n <span class=\"tw-w-1.5 tw-h-1.5 tw-rounded-full\" [ngClass]=\"theme.sytm_isactive ? 'tw-bg-green-500' : 'tw-bg-red-500'\"></span>\r\n {{ theme.sytm_isactive ? 'Active' : 'Inactive' }}\r\n </span>\r\n <div class=\"tw-flex tw-items-center tw-gap-1\">\r\n <!-- Set Selected Button - Clear and Simple -->\r\n @if (theme.sytm_isselected) {\r\n <span class=\"tw-inline-flex tw-items-center tw-gap-1 tw-px-2 tw-py-1 tw-bg-green-100 tw-text-green-800 tw-rounded-md tw-text-xs tw-font-medium\">\r\n <cide-ele-icon class=\"tw-w-3 tw-h-3\">check</cide-ele-icon>\r\n Selected\r\n </span>\r\n } @else {\r\n <button cideEleButton \r\n variant=\"outline\" \r\n size=\"xs\"\r\n (click)=\"$event.stopPropagation(); setSelectedTheme(theme)\"\r\n [attr.aria-label]=\"'Select ' + (theme.sytm_title || theme.sytm_theme_code) + ' theme'\"\r\n class=\"tw-text-xs\">\r\n Select\r\n </button>\r\n }\r\n <button cideEleButton variant=\"ghost\" size=\"xs\" (click)=\"$event.stopPropagation(); editTheme(theme)\"\r\n [attr.aria-label]=\"'Edit theme ' + (theme.sytm_title || theme.sytm_theme_code)\">\r\n <cide-ele-icon class=\"tw-w-4 tw-h-4\">edit</cide-ele-icon>\r\n </button>\r\n <button cideEleButton variant=\"ghost\" size=\"xs\" (click)=\"$event.stopPropagation(); deleteTheme(theme)\"\r\n [attr.aria-label]=\"'Delete theme ' + (theme.sytm_title || theme.sytm_theme_code)\">\r\n <cide-ele-icon class=\"tw-w-4 tw-h-4\">delete</cide-ele-icon>\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n\r\n @if (!loading() && filteredThemes().length === 0) {\r\n <div class=\"tw-col-span-full tw-text-center tw-text-xs tw-text-gray-500 tw-py-8\">No themes found</div>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<!-- \r\n Angular Template References for Grid Renderers (Best Practice)\r\n \r\n These ng-template elements represent the Angular best practice for custom rendering.\r\n They provide:\r\n - Type safety with template context\r\n - Component lifecycle integration\r\n - Change detection optimization\r\n - Proper event handling\r\n - Accessibility features\r\n \r\n Note: Current data grid uses string renderers for compatibility.\r\n Templates are maintained for future component enhancement.\r\n-->\r\n\r\n<!-- Theme Details Renderer Template -->\r\n<ng-template #themeDetailsRendererTemplate let-row=\"row\" let-value=\"value\">\r\n <div class=\"tw-flex tw-items-center tw-min-w-0\">\r\n <!-- Theme Icon -->\r\n <div class=\"tw-flex-shrink-0\">\r\n <cide-ele-icon \r\n class=\"tw-text-purple-600\" \r\n size=\"xs\">\r\n palette\r\n </cide-ele-icon>\r\n </div>\r\n \r\n <!-- Theme Details -->\r\n <div class=\"tw-ml-3 tw-min-w-0 tw-flex-1\">\r\n <div class=\"tw-text-sm tw-font-medium tw-text-gray-900 tw-truncate\" \r\n [title]=\"row.sytm_title\">\r\n {{ row.sytm_title || 'Untitled' }}\r\n </div>\r\n @if (row.sytm_desc) {\r\n <div class=\"tw-text-xs tw-text-gray-500 tw-truncate\" \r\n [title]=\"row.sytm_desc\">\r\n {{ row.sytm_desc }}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n</ng-template>\r\n\r\n<!-- Theme Status Renderer Template -->\r\n<ng-template #themeStatusRendererTemplate let-row=\"row\" let-value=\"value\">\r\n <span class=\"tw-inline-flex tw-items-center tw-px-2.5 tw-py-0.5 tw-rounded-full tw-text-xs tw-font-medium tw-whitespace-nowrap\"\r\n [ngClass]=\"row.sytm_isactive ? 'tw-bg-green-100 tw-text-green-800' : 'tw-bg-red-100 tw-text-red-800'\">\r\n {{ row.sytm_isactive ? 'Active' : 'Inactive' }}\r\n </span>\r\n</ng-template>\r\n\r\n<!-- Actions Dropdown Renderer Template -->\r\n<ng-template #actionsDropdownRendererTemplate let-row=\"row\" let-value=\"value\">\r\n <cide-ele-dropdown \r\n [items]=\"getActionDropdownItems(row)\"\r\n [config]=\"{ triggerIcon: 'more_vert', triggerSize: 'sm' }\"\r\n (itemClick)=\"onDropdownItemClick($event, row)\">\r\n </cide-ele-dropdown>\r\n</ng-template> ", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i2.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "directive", type: i2.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { kind: "ngmodule", type: FormsModule }, { kind: "component", type: CideEleButtonComponent, selector: "button[cideEleButton], a[cideEleButton]", inputs: ["label", "variant", "size", "type", "shape", "elevation", "disabled", "id", "loading", "fullWidth", "leftIcon", "rightIcon", "customClass", "tooltip", "ariaLabel", "testId", "routerLink", "routerExtras", "preventDoubleClick", "animated"], outputs: ["btnClick", "doubleClick"] }, { kind: "component", type: CideInputComponent, selector: "cide-ele-input", inputs: ["fill", "label", "labelHide", "disabled", "clearInput", "labelPlacement", "labelDir", "placeholder", "leadingIcon", "trailingIcon", "helperText", "helperTextCollapse", "hideHelperAndErrorText", "errorText", "maxlength", "minlength", "required", "autocapitalize", "autocomplete", "type", "width", "id", "ngModel", "option", "min", "max", "size"], outputs: ["ngModelChange"] }, { kind: "component", type: CideSelectComponent, selector: "cide-ele-select", inputs: ["label", "labelHide", "placeholder", "helperText", "errorText", "required", "disabled", "id", "ngModel", "size", "fill", "labelPlacement", "labelDir", "leadingIcon", "trailingIcon", "clearInput", "options", "multiple", "searchable", "showSearchInput", "loading"], outputs: ["ngModelChange", "change", "searchChange"] }, { kind: "component", type: CideTextareaComponent, selector: "cide-ele-textarea", inputs: ["label", "labelHide", "placeholder", "helperText", "errorText", "required", "disabled", "minlength", "maxlength", "rows", "id", "ngModel", "size", "fill", "labelPlacement", "labelDir", "leadingIcon", "trailingIcon", "clearInput"], outputs: ["ngModelChange"] }, { kind: "component", type: CideIconComponent, selector: "cide-ele-icon", inputs: ["size", "type", "toolTip"] }, { kind: "component", type: CideEleDropdownComponent, selector: "cide-ele-dropdown", inputs: ["items", "config", "triggerTemplate", "menuTemplate"], outputs: ["itemClick", "dropdownToggle"] }, { kind: "component", type: CideEleJsonEditorComponent, selector: "cide-ele-json-editor", inputs: ["label", "helperText", "required", "disabled", "showCharacterCount", "config"], outputs: ["valueChange", "objectChange", "errorsChange", "validChange"] }] }); }
6391
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: PageThemeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
6392
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.7", type: PageThemeComponent, isStandalone: true, selector: "cide-core-app-page-theme", viewQueries: [{ propertyName: "themeDetailsRendererTemplate", first: true, predicate: ["themeDetailsRendererTemplate"], descendants: true, isSignal: true }, { propertyName: "themeStatusRendererTemplate", first: true, predicate: ["themeStatusRendererTemplate"], descendants: true, isSignal: true }, { propertyName: "actionsDropdownRendererTemplate", first: true, predicate: ["actionsDropdownRendererTemplate"], descendants: true, isSignal: true }], ngImport: i0, template: "<!-- Page Theme Container -->\r\n<div class=\"tw-flex tw-h-full tw-w-full\">\r\n \r\n <!-- Left: Form and header (60%) -->\r\n <div class=\"tw-w-full lg:tw-w-3/5 tw-flex tw-flex-col tw-border-r tw-border-gray-200\">\r\n\r\n <!-- Header Section -->\r\n <div class=\"tw-px-6 tw-py-3 tw-border-b tw-border-gray-200 tw-bg-gray-50\">\r\n <div class=\"tw-flex tw-flex-col sm:tw-flex-row tw-justify-between tw-items-start sm:tw-items-center tw-space-y-3 sm:tw-space-y-0\">\r\n\r\n <!-- Title and Back Button -->\r\n <div class=\"tw-flex tw-items-center tw-space-x-4\">\r\n <button cideEleButton variant=\"ghost\" size=\"sm\" (click)=\"goBack()\" class=\"tw-text-gray-600 hover:tw-text-gray-900\">\r\n <cide-ele-icon class=\"tw-w-4 tw-h-4\">arrow_back</cide-ele-icon>\r\n </button>\r\n <div class=\"tw-flex tw-items-center tw-space-x-2\">\r\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-5 tw-h-5\">palette</cide-ele-icon>\r\n <div>\r\n <h5 class=\"tw-text-base tw-font-medium tw-text-gray-900 tw-m-0\">Theme Management</h5>\r\n <p class=\"tw-text-sm tw-text-gray-500 tw-m-0\">Page: {{ pageTitle() }}</p>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Error Message -->\r\n @if (error()) {\r\n <div class=\"tw-mt-4 tw-p-4 tw-bg-red-50 tw-border tw-border-red-200 tw-rounded-md\">\r\n <div class=\"tw-flex tw-items-start\">\r\n <cide-ele-icon name=\"error\" class=\"tw-text-red-400 tw-w-5 tw-h-5 tw-mt-0.5 tw-flex-shrink-0\"></cide-ele-icon>\r\n <div class=\"tw-ml-3\">\r\n <h3 class=\"tw-text-sm tw-font-medium tw-text-red-800 tw-m-0\">Error</h3>\r\n <p class=\"tw-text-sm tw-text-red-700 tw-mt-1 tw-m-0\">{{ error() }}</p>\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- Quick Add/Edit Form Section -->\r\n <div class=\"tw-px-6 tw-py-4 tw-bg-white tw-overflow-auto\">\r\n <div class=\"tw-flex tw-items-center tw-justify-between tw-mb-3\">\r\n <div class=\"tw-flex tw-items-center tw-space-x-3\">\r\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-5 tw-h-5\">{{ isEditMode() ? 'edit' : 'add' }}</cide-ele-icon>\r\n <h6 class=\"tw-text-sm tw-font-medium tw-text-gray-900 tw-m-0\">{{ isEditMode() ? 'Edit Theme' : 'Quick Add Theme' }}</h6>\r\n </div>\r\n </div>\r\n\r\n <!-- Form (kept as-is) -->\r\n <form [formGroup]=\"themeForm\" (ngSubmit)=\"saveTheme()\" class=\"tw-space-y-4\">\r\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 lg:tw-grid-cols-3 tw-gap-4\">\r\n <!-- Theme Title -->\r\n <div class=\"tw-space-y-2\">\r\n <cide-ele-input id=\"sytm_title\" formControlName=\"sytm_title\" placeholder=\"Enter theme title\" label=\"Theme Title*\" size=\"sm\"></cide-ele-input>\r\n </div>\r\n <!-- Theme Code -->\r\n <div class=\"tw-space-y-2\">\r\n <cide-ele-input id=\"sytm_theme_code\" formControlName=\"sytm_theme_code\" placeholder=\"Enter theme code\" label=\"Theme Code*\" size=\"sm\"></cide-ele-input>\r\n </div>\r\n <!-- Status -->\r\n <div class=\"tw-space-y-2\">\r\n <cide-ele-input\r\n id=\"sytm_isactive_cb\"\r\n type=\"checkbox\"\r\n label=\"Active\"\r\n size=\"sm\"\r\n formControlName=\"sytm_isactive\">\r\n </cide-ele-input>\r\n </div>\r\n <!-- Sub Title -->\r\n <div class=\"tw-space-y-2\">\r\n <cide-ele-input id=\"sytm_sub_title\" formControlName=\"sytm_sub_title\" placeholder=\"Enter sub title\" label=\"Sub Title\" size=\"sm\"></cide-ele-input>\r\n </div>\r\n <!-- Preview ID -->\r\n <div class=\"tw-space-y-2\">\r\n <cide-ele-input id=\"sytm_preview_id_fm\" formControlName=\"sytm_preview_id_fm\" placeholder=\"Enter preview image ID\" label=\"Preview Image ID\" size=\"sm\"></cide-ele-input>\r\n </div>\r\n <!-- Description -->\r\n <div class=\"tw-space-y-2 md:tw-col-span-2\">\r\n <cide-ele-textarea id=\"sytm_desc\" formControlName=\"sytm_desc\" placeholder=\"Enter theme description\" rows=\"2\" label=\"Description\" size=\"sm\"></cide-ele-textarea>\r\n </div>\r\n <!-- Configuration JSON -->\r\n <div class=\"tw-space-y-2 md:tw-col-span-3\">\r\n <cide-ele-json-editor label=\"Configuration JSON\" formControlName=\"sytm_configuration\" [required]=\"true\" [config]=\"{\r\n showLineNumbers: true,\r\n autoFormat: true,\r\n validateOnChange: true,\r\n minHeight: 150,\r\n maxHeight: 300,\r\n placeholder: 'Enter theme configuration JSON...'\r\n }\" helperText=\"Enter valid JSON configuration for the theme\"></cide-ele-json-editor>\r\n </div>\r\n <!-- Layout Configuration + Selection: right-side checkbox list -->\r\n <div class=\"lg:tw-col-span-1 tw-space-y-2\">\r\n <div class=\"tw-text-sm tw-font-medium tw-text-gray-700\">Layout & Selection</div>\r\n <!-- Selected toggle -->\r\n <div class=\"tw-bg-white tw-border tw-border-gray-200 tw-rounded-md tw-px-3 tw-py-2\">\r\n <cide-ele-input\r\n id=\"sytm_isselected\"\r\n type=\"checkbox\"\r\n label=\"Selected (Default)\"\r\n size=\"sm\"\r\n formControlName=\"sytm_isselected\">\r\n </cide-ele-input>\r\n </div>\r\n <div formGroupName=\"sytm_layout\" class=\"tw-bg-white tw-border tw-border-gray-200 tw-rounded-md tw-divide-y tw-overflow-hidden\">\r\n <!-- Sidebar -->\r\n <div class=\"tw-px-3 tw-py-2\" formGroupName=\"sytm_layout_sidebar\">\r\n <cide-ele-input id=\"layout_sidebar_status\" type=\"checkbox\" label=\"Sidebar\" size=\"sm\" formControlName=\"status\"></cide-ele-input>\r\n </div>\r\n <!-- Header -->\r\n <div class=\"tw-px-3 tw-py-2\" formGroupName=\"sytm_layout_header\">\r\n <cide-ele-input id=\"layout_header_status\" type=\"checkbox\" label=\"Header\" size=\"sm\" formControlName=\"status\"></cide-ele-input>\r\n </div>\r\n <!-- Footer -->\r\n <div class=\"tw-px-3 tw-py-2\" formGroupName=\"sytm_layout_footer\">\r\n <cide-ele-input id=\"layout_footer_status\" type=\"checkbox\" label=\"Footer\" size=\"sm\" formControlName=\"status\"></cide-ele-input>\r\n </div>\r\n <!-- Breadcrumb -->\r\n <div class=\"tw-px-3 tw-py-2\" formGroupName=\"sytm_layout_breadcrumb\">\r\n <cide-ele-input id=\"layout_breadcrumb_status\" type=\"checkbox\" label=\"Breadcrumb\" size=\"sm\" formControlName=\"status\"></cide-ele-input>\r\n </div>\r\n <!-- Console -->\r\n <div class=\"tw-px-3 tw-py-2\" formGroupName=\"sytm_layout_console\">\r\n <cide-ele-input id=\"layout_console_status\" type=\"checkbox\" label=\"Console\" size=\"sm\" formControlName=\"status\"></cide-ele-input>\r\n </div>\r\n <!-- Request -->\r\n <div class=\"tw-px-3 tw-py-2\" formGroupName=\"sytm_layout_request\">\r\n <cide-ele-input id=\"layout_request_status\" type=\"checkbox\" label=\"Request\" size=\"sm\" formControlName=\"status\"></cide-ele-input>\r\n </div>\r\n </div>\r\n <p class=\"tw-text-xs tw-text-gray-500 tw-pt-1\">Toggle active sections. Only one theme can be selected as default. More options can be added here later.</p>\r\n </div>\r\n <!-- Drawer Configuration -->\r\n <div class=\"tw-space-y-2 md:tw-col-span-3\">\r\n <div class=\"tw-flex tw-items-center tw-justify-between\">\r\n <div class=\"tw-text-sm tw-font-medium tw-text-gray-700\">Drawers</div>\r\n <button cideEleButton type=\"button\" size=\"xs\" variant=\"outline\" (click)=\"addDrawer()\">\r\n Add Drawer\r\n </button>\r\n </div>\r\n\r\n <div formGroupName=\"sytm_layout\">\r\n <div class=\"tw-space-y-2\" formArrayName=\"sytm_layout_drawer\">\r\n <div *ngFor=\"let drawerGrp of drawerArray.controls; let i = index\" [formGroupName]=\"i\" class=\"tw-border tw-border-gray-200 tw-rounded-md tw-p-3 tw-flex tw-items-center tw-gap-3\">\r\n <cide-ele-input id=\"drawer_active_{{i}}\" type=\"checkbox\" label=\"Active\" size=\"sm\" formControlName=\"syth_status\"></cide-ele-input>\r\n <div class=\"tw-flex-1\">\r\n <cide-ele-select\r\n id=\"drawer_config_{{i}}\"\r\n label=\"Drawer For\"\r\n size=\"sm\"\r\n [options]=\"drawerConfigOptions\"\r\n formControlName=\"syth_config_syco_for\">\r\n </cide-ele-select>\r\n </div>\r\n <button cideEleButton type=\"button\" size=\"xs\" variant=\"ghost\" (click)=\"removeDrawer(i)\">\r\n <cide-ele-icon class=\"tw-w-4 tw-h-4\">delete</cide-ele-icon>\r\n </button>\r\n </div>\r\n <p class=\"tw-text-xs tw-text-gray-500\">Configure multiple drawers as needed.</p>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Form Actions -->\r\n <div class=\"tw-flex tw-flex-col tw-gap-2 tw-pt-4 tw-border-t tw-border-gray-200\">\r\n <div class=\"tw-flex tw-items-center tw-justify-end tw-space-x-3\">\r\n <button cideEleButton type=\"button\" variant=\"outline\" (click)=\"cancelForm()\" [disabled]=\"loading()\">Cancel</button>\r\n <button cideEleButton type=\"submit\" variant=\"primary\" leftIcon=\"add\" [disabled]=\"!themeForm.valid || loading()\" [loading]=\"loading()\">\r\n {{ isEditMode() ? 'Update Theme' : 'Create Theme' }}\r\n </button>\r\n </div>\r\n </div>\r\n </form>\r\n </div>\r\n </div>\r\n\r\n <!-- Right: Theme gallery (40%) -->\r\n <div class=\"tw-hidden lg:tw-flex tw-w-2/5 tw-flex-col\">\r\n <!-- (Header consolidated above) -->\r\n\r\n <!-- Gallery list -->\r\n <div class=\"tw-flex-1 tw-overflow-auto tw-bg-gray-50\">\r\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-3 tw-p-4\">\r\n @for (theme of filteredThemes(); track theme._id) {\r\n <div class=\"tw-rounded-md tw-transition tw-cursor-pointer tw-relative\"\r\n [ngClass]=\"theme.sytm_isselected\r\n ? 'tw-border tw-border-blue-500 tw-ring-2 tw-ring-blue-200 tw-bg-blue-50/50'\r\n : 'tw-bg-white tw-border tw-border-gray-200 hover:tw-shadow-sm'\"\r\n (click)=\"editTheme(theme)\"\r\n role=\"button\"\r\n tabindex=\"0\"\r\n [attr.aria-selected]=\"theme.sytm_isselected ? 'true' : 'false'\"\r\n [attr.aria-label]=\"'Edit theme ' + (theme.sytm_title || theme.sytm_theme_code)\"\r\n (keydown.enter)=\"editTheme(theme)\"\r\n (keydown.space)=\"$event.preventDefault(); editTheme(theme)\">\r\n\r\n <!-- Selected badge -->\r\n <div *ngIf=\"theme.sytm_isselected\"\r\n class=\"tw-absolute tw-top-2 tw-right-2 tw-flex tw-items-center tw-justify-center tw-w-6 tw-h-6 tw-rounded-full tw-bg-blue-600 tw-text-white\">\r\n <cide-ele-icon class=\"tw-w-4 tw-h-4\">check</cide-ele-icon>\r\n </div>\r\n \r\n <div class=\"tw-aspect-[16/9] tw-bg-gray-100 tw-rounded-t-md tw-overflow-hidden tw-flex tw-items-center tw-justify-center\">\r\n @if (getPreviewUrl(theme)) {\r\n <img [src]=\"getPreviewUrl(theme)\" class=\"tw-w-full tw-h-full tw-object-cover\" alt=\"Preview\" />\r\n } @else {\r\n <div class=\"tw-text-gray-400 tw-text-xs\">No preview</div>\r\n }\r\n </div>\r\n <div class=\"tw-p-3 tw-space-y-1\">\r\n <div class=\"tw-text-sm tw-font-medium tw-text-gray-900 tw-truncate\" [title]=\"theme.sytm_title\">{{ theme.sytm_title || 'Untitled Theme' }}</div>\r\n <div class=\"tw-text-xs tw-text-gray-500 tw-truncate\" [title]=\"theme.sytm_theme_code\">{{ theme.sytm_theme_code }}</div>\r\n <div class=\"tw-flex tw-items-center tw-justify-between tw-pt-1\">\r\n <span class=\"tw-inline-flex tw-items-center tw-gap-1 tw-text-xs\" [ngClass]=\"theme.sytm_isactive ? 'tw-text-green-700' : 'tw-text-red-700'\">\r\n <span class=\"tw-w-1.5 tw-h-1.5 tw-rounded-full\" [ngClass]=\"theme.sytm_isactive ? 'tw-bg-green-500' : 'tw-bg-red-500'\"></span>\r\n {{ theme.sytm_isactive ? 'Active' : 'Inactive' }}\r\n </span>\r\n <div class=\"tw-flex tw-items-center tw-gap-1\">\r\n <!-- Set Selected Button - Clear and Simple -->\r\n @if (theme.sytm_isselected) {\r\n <span class=\"tw-inline-flex tw-items-center tw-gap-1 tw-px-2 tw-py-1 tw-bg-green-100 tw-text-green-800 tw-rounded-md tw-text-xs tw-font-medium\">\r\n <cide-ele-icon class=\"tw-w-3 tw-h-3\">check</cide-ele-icon>\r\n Selected\r\n </span>\r\n } @else {\r\n <button cideEleButton \r\n variant=\"outline\" \r\n size=\"xs\"\r\n (click)=\"$event.stopPropagation(); setSelectedTheme(theme)\"\r\n [attr.aria-label]=\"'Select ' + (theme.sytm_title || theme.sytm_theme_code) + ' theme'\"\r\n class=\"tw-text-xs\">\r\n Select\r\n </button>\r\n }\r\n <button cideEleButton variant=\"ghost\" size=\"xs\" (click)=\"$event.stopPropagation(); editTheme(theme)\"\r\n [attr.aria-label]=\"'Edit theme ' + (theme.sytm_title || theme.sytm_theme_code)\">\r\n <cide-ele-icon class=\"tw-w-4 tw-h-4\">edit</cide-ele-icon>\r\n </button>\r\n <button cideEleButton variant=\"ghost\" size=\"xs\" (click)=\"$event.stopPropagation(); deleteTheme(theme)\"\r\n [attr.aria-label]=\"'Delete theme ' + (theme.sytm_title || theme.sytm_theme_code)\">\r\n <cide-ele-icon class=\"tw-w-4 tw-h-4\">delete</cide-ele-icon>\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n\r\n @if (!loading() && filteredThemes().length === 0) {\r\n <div class=\"tw-col-span-full tw-text-center tw-text-xs tw-text-gray-500 tw-py-8\">No themes found</div>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<!-- \r\n Angular Template References for Grid Renderers (Best Practice)\r\n \r\n These ng-template elements represent the Angular best practice for custom rendering.\r\n They provide:\r\n - Type safety with template context\r\n - Component lifecycle integration\r\n - Change detection optimization\r\n - Proper event handling\r\n - Accessibility features\r\n \r\n Note: Current data grid uses string renderers for compatibility.\r\n Templates are maintained for future component enhancement.\r\n-->\r\n\r\n<!-- Theme Details Renderer Template -->\r\n<ng-template #themeDetailsRendererTemplate let-row=\"row\" let-value=\"value\">\r\n <div class=\"tw-flex tw-items-center tw-min-w-0\">\r\n <!-- Theme Icon -->\r\n <div class=\"tw-flex-shrink-0\">\r\n <cide-ele-icon \r\n class=\"tw-text-purple-600\" \r\n size=\"xs\">\r\n palette\r\n </cide-ele-icon>\r\n </div>\r\n \r\n <!-- Theme Details -->\r\n <div class=\"tw-ml-3 tw-min-w-0 tw-flex-1\">\r\n <div class=\"tw-text-sm tw-font-medium tw-text-gray-900 tw-truncate\" \r\n [title]=\"row.sytm_title\">\r\n {{ row.sytm_title || 'Untitled' }}\r\n </div>\r\n @if (row.sytm_desc) {\r\n <div class=\"tw-text-xs tw-text-gray-500 tw-truncate\" \r\n [title]=\"row.sytm_desc\">\r\n {{ row.sytm_desc }}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n</ng-template>\r\n\r\n<!-- Theme Status Renderer Template -->\r\n<ng-template #themeStatusRendererTemplate let-row=\"row\" let-value=\"value\">\r\n <span class=\"tw-inline-flex tw-items-center tw-px-2.5 tw-py-0.5 tw-rounded-full tw-text-xs tw-font-medium tw-whitespace-nowrap\"\r\n [ngClass]=\"row.sytm_isactive ? 'tw-bg-green-100 tw-text-green-800' : 'tw-bg-red-100 tw-text-red-800'\">\r\n {{ row.sytm_isactive ? 'Active' : 'Inactive' }}\r\n </span>\r\n</ng-template>\r\n\r\n<!-- Actions Dropdown Renderer Template -->\r\n<ng-template #actionsDropdownRendererTemplate let-row=\"row\" let-value=\"value\">\r\n <cide-ele-dropdown \r\n [items]=\"getActionDropdownItems(row)\"\r\n [config]=\"{ triggerIcon: 'more_vert', triggerSize: 'sm' }\"\r\n (itemClick)=\"onDropdownItemClick($event, row)\">\r\n </cide-ele-dropdown>\r\n</ng-template> ", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i2.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "directive", type: i2.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { kind: "ngmodule", type: FormsModule }, { kind: "component", type: CideEleButtonComponent, selector: "button[cideEleButton], a[cideEleButton]", inputs: ["label", "variant", "size", "type", "shape", "elevation", "disabled", "id", "loading", "fullWidth", "leftIcon", "rightIcon", "customClass", "tooltip", "ariaLabel", "testId", "routerLink", "routerExtras", "preventDoubleClick", "animated"], outputs: ["btnClick", "doubleClick"] }, { kind: "component", type: CideInputComponent, selector: "cide-ele-input", inputs: ["fill", "label", "labelHide", "disabled", "clearInput", "labelPlacement", "labelDir", "placeholder", "leadingIcon", "trailingIcon", "helperText", "helperTextCollapse", "hideHelperAndErrorText", "errorText", "maxlength", "minlength", "required", "autocapitalize", "autocomplete", "type", "width", "id", "ngModel", "option", "min", "max", "size"], outputs: ["ngModelChange"] }, { kind: "component", type: CideSelectComponent, selector: "cide-ele-select", inputs: ["label", "labelHide", "placeholder", "helperText", "errorText", "required", "disabled", "id", "ngModel", "size", "fill", "labelPlacement", "labelDir", "leadingIcon", "trailingIcon", "clearInput", "options", "multiple", "searchable", "showSearchInput", "loading"], outputs: ["ngModelChange", "change", "searchChange"] }, { kind: "component", type: CideTextareaComponent, selector: "cide-ele-textarea", inputs: ["label", "labelHide", "placeholder", "helperText", "errorText", "required", "disabled", "minlength", "maxlength", "rows", "id", "ngModel", "size", "fill", "labelPlacement", "labelDir", "leadingIcon", "trailingIcon", "clearInput"], outputs: ["ngModelChange"] }, { kind: "component", type: CideIconComponent, selector: "cide-ele-icon", inputs: ["size", "type", "toolTip"] }, { kind: "component", type: CideEleDropdownComponent, selector: "cide-ele-dropdown", inputs: ["items", "config", "triggerTemplate", "menuTemplate"], outputs: ["itemClick", "dropdownToggle"] }, { kind: "component", type: CideEleJsonEditorComponent, selector: "cide-ele-json-editor", inputs: ["label", "helperText", "required", "disabled", "showCharacterCount", "config"], outputs: ["valueChange", "objectChange", "errorsChange", "validChange"] }] });
6389
6393
  }
6390
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: PageThemeComponent, decorators: [{
6394
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: PageThemeComponent, decorators: [{
6391
6395
  type: Component,
6392
6396
  args: [{ selector: 'cide-core-app-page-theme', standalone: true, imports: [
6393
6397
  CommonModule,
@@ -6411,6 +6415,7 @@ var pageTheme_component = /*#__PURE__*/Object.freeze({
6411
6415
  });
6412
6416
 
6413
6417
  class PageControlsService {
6418
+ http;
6414
6419
  constructor(http) {
6415
6420
  this.http = http;
6416
6421
  console.log('PageControlsService initialized - using real API');
@@ -6530,10 +6535,10 @@ class PageControlsService {
6530
6535
  console.error('Page Controls Service Error:', errorMessage);
6531
6536
  return throwError(() => new Error(errorMessage));
6532
6537
  }
6533
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: PageControlsService, deps: [{ token: i1.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable }); }
6534
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: PageControlsService, providedIn: 'root' }); }
6538
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: PageControlsService, deps: [{ token: i1.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable });
6539
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: PageControlsService, providedIn: 'root' });
6535
6540
  }
6536
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: PageControlsService, decorators: [{
6541
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: PageControlsService, decorators: [{
6537
6542
  type: Injectable,
6538
6543
  args: [{
6539
6544
  providedIn: 'root'
@@ -6541,64 +6546,62 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImpor
6541
6546
  }], ctorParameters: () => [{ type: i1.HttpClient }] });
6542
6547
 
6543
6548
  class PageControlsComponent {
6544
- constructor() {
6545
- // Dependency injection
6546
- this.destroyRef = inject(DestroyRef);
6547
- this.controlsService = inject(PageControlsService);
6548
- this.appState = inject(AppStateHelperService);
6549
- this.fb = inject(NonNullableFormBuilder);
6550
- this.router = inject(Router);
6551
- this.route = inject(ActivatedRoute);
6552
- // Make Math available in template
6553
- this.Math = Math;
6554
- // Signals for reactive state management
6555
- this.controls = signal([]);
6556
- this.loading = signal(false);
6557
- this.error = signal(null);
6558
- this.selectedItems = signal([]);
6559
- this.searchTerm = signal('');
6560
- // Page information
6561
- this.pageId = signal('');
6562
- this.pageTitle = signal('');
6563
- // Form state
6564
- this.isEditMode = signal(false);
6565
- this.editingControlId = signal(null);
6566
- this.retrievedControl = signal(null);
6567
- // Control selection for new layout
6568
- this.selectedControlId = signal(null);
6569
- // Pagination signals
6570
- this.currentPage = signal(1);
6571
- this.pageSize = signal(10);
6572
- this.totalItems = signal(0);
6573
- // Modern reactive forms with signals - No validators for simplicity
6574
- this.controlForm = this.fb.group({
6575
- sype_key: [''],
6576
- sype_label: [''],
6577
- sype_label_hide: [false],
6578
- sype_auto_complete: [false], // Changed to boolean for checkbox
6579
- sype_hide_helper_and_error_text: [false],
6580
- sype_type: [''], // controlType
6581
- sype_option_key: [''],
6582
- sype_placeholder: [''],
6583
- sype_min_length: [0],
6584
- sype_max_length: [20],
6585
- sype_regex: [''],
6586
- sype_required: [false],
6587
- sype_disabled: [false],
6588
- sype_width: [''], // Changed to string for px values like "20px"
6589
- sype_height: [''], // Changed to string for px values like "20px"
6590
- sype_label_placement: ['left'],
6591
- sype_helper_text_collapse: [false],
6592
- sype_default: [''],
6593
- sype_tooltip: [''],
6594
- sype_size: ['sm'], // Changed default to small
6595
- sype_leading_icon: [''],
6596
- sype_isactive: [true],
6597
- sype_entity_id_syen: ['']
6598
- });
6599
- // Computed values
6600
- this.isFormDirty = computed(() => this.controlForm.dirty);
6601
- }
6549
+ // Dependency injection
6550
+ destroyRef = inject(DestroyRef);
6551
+ controlsService = inject(PageControlsService);
6552
+ appState = inject(AppStateHelperService);
6553
+ fb = inject(NonNullableFormBuilder);
6554
+ router = inject(Router);
6555
+ route = inject(ActivatedRoute);
6556
+ // Make Math available in template
6557
+ Math = Math;
6558
+ // Signals for reactive state management
6559
+ controls = signal([], ...(ngDevMode ? [{ debugName: "controls" }] : []));
6560
+ loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
6561
+ error = signal(null, ...(ngDevMode ? [{ debugName: "error" }] : []));
6562
+ selectedItems = signal([], ...(ngDevMode ? [{ debugName: "selectedItems" }] : []));
6563
+ searchTerm = signal('', ...(ngDevMode ? [{ debugName: "searchTerm" }] : []));
6564
+ // Page information
6565
+ pageId = signal('', ...(ngDevMode ? [{ debugName: "pageId" }] : []));
6566
+ pageTitle = signal('', ...(ngDevMode ? [{ debugName: "pageTitle" }] : []));
6567
+ // Form state
6568
+ isEditMode = signal(false, ...(ngDevMode ? [{ debugName: "isEditMode" }] : []));
6569
+ editingControlId = signal(null, ...(ngDevMode ? [{ debugName: "editingControlId" }] : []));
6570
+ retrievedControl = signal(null, ...(ngDevMode ? [{ debugName: "retrievedControl" }] : []));
6571
+ // Control selection for new layout
6572
+ selectedControlId = signal(null, ...(ngDevMode ? [{ debugName: "selectedControlId" }] : []));
6573
+ // Pagination signals
6574
+ currentPage = signal(1, ...(ngDevMode ? [{ debugName: "currentPage" }] : []));
6575
+ pageSize = signal(10, ...(ngDevMode ? [{ debugName: "pageSize" }] : []));
6576
+ totalItems = signal(0, ...(ngDevMode ? [{ debugName: "totalItems" }] : []));
6577
+ // Modern reactive forms with signals - No validators for simplicity
6578
+ controlForm = this.fb.group({
6579
+ sype_key: [''],
6580
+ sype_label: [''],
6581
+ sype_label_hide: [false],
6582
+ sype_auto_complete: [false], // Changed to boolean for checkbox
6583
+ sype_hide_helper_and_error_text: [false],
6584
+ sype_type: [''], // controlType
6585
+ sype_option_key: [''],
6586
+ sype_placeholder: [''],
6587
+ sype_min_length: [0],
6588
+ sype_max_length: [20],
6589
+ sype_regex: [''],
6590
+ sype_required: [false],
6591
+ sype_disabled: [false],
6592
+ sype_width: [''], // Changed to string for px values like "20px"
6593
+ sype_height: [''], // Changed to string for px values like "20px"
6594
+ sype_label_placement: ['left'],
6595
+ sype_helper_text_collapse: [false],
6596
+ sype_default: [''],
6597
+ sype_tooltip: [''],
6598
+ sype_size: ['sm'], // Changed default to small
6599
+ sype_leading_icon: [''],
6600
+ sype_isactive: [true],
6601
+ sype_entity_id_syen: ['']
6602
+ });
6603
+ // Computed values
6604
+ isFormDirty = computed(() => this.controlForm.dirty, ...(ngDevMode ? [{ debugName: "isFormDirty" }] : []));
6602
6605
  ngOnInit() {
6603
6606
  this.initializeComponent();
6604
6607
  }
@@ -6994,10 +6997,10 @@ class PageControlsComponent {
6994
6997
  trackByControlId(index, control) {
6995
6998
  return control._id || '';
6996
6999
  }
6997
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: PageControlsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
6998
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.7", type: PageControlsComponent, isStandalone: true, selector: "cide-core-app-page-controls", ngImport: i0, template: "<!-- Page Controls Container -->\n<div class=\"page-controls-container\">\n <!-- Header Section -->\n <div class=\"header\">\n <div class=\"header-content\">\n <div class=\"header-left\">\n <button \n cideEleButton\n variant=\"ghost\"\n size=\"sm\"\n (click)=\"goBack()\"\n class=\"back-button\">\n <cide-ele-icon>arrow_back</cide-ele-icon>\n </button>\n <div class=\"title-section\">\n <cide-ele-icon class=\"title-icon\">settings</cide-ele-icon>\n <div>\n <h1 class=\"title\">Control Management</h1>\n <p class=\"subtitle\">Page: {{ pageTitle() }}</p>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Error Message -->\n <div class=\"error-message\" *ngIf=\"error()\">\n <cide-ele-icon>error</cide-ele-icon>\n <div>\n <h3>Error</h3>\n <p>{{ error() }}</p>\n </div>\n </div>\n\n <!-- Main Content Area -->\n <div class=\"main-content\">\n <!-- Form Section -->\n <div class=\"form-section\">\n <div class=\"form-header\">\n <cide-ele-icon>{{ isEditMode() ? 'edit' : 'add' }}</cide-ele-icon>\n <h3>{{ isEditMode() ? 'Edit Control' : 'Quick Add Control' }}</h3>\n </div>\n\n <!-- Form -->\n <form [formGroup]=\"controlForm\" (ngSubmit)=\"saveControl()\" class=\"control-form tw-overflow-y-auto\">\n <div class=\"form-grid\">\n \n <!-- Basic Information Section -->\n <!-- Control Key -->\n <div class=\"form-group\">\n <cide-ele-input\n id=\"sype_key\"\n formControlName=\"sype_key\"\n placeholder=\"Enter control key\"\n label=\"Control Key\"\n size=\"sm\">\n </cide-ele-input>\n </div>\n\n <!-- Control Label -->\n <div class=\"form-group\">\n <cide-ele-input\n id=\"sype_label\"\n formControlName=\"sype_label\"\n placeholder=\"Enter control label\"\n label=\"Control Label\"\n size=\"sm\">\n </cide-ele-input>\n </div>\n\n <!-- Control Type -->\n <div class=\"form-group\">\n <cide-ele-select\n id=\"sype_type\"\n formControlName=\"sype_type\"\n [options]=\"[\n { value: 'text', label: 'Text Input' },\n { value: 'textarea', label: 'Text Area' },\n { value: 'select', label: 'Select' },\n { value: 'checkbox', label: 'Checkbox' },\n { value: 'radio', label: 'Radio' },\n { value: 'date', label: 'Date' },\n { value: 'number', label: 'Number' },\n { value: 'email', label: 'Email' },\n { value: 'password', label: 'Password' },\n { value: 'file', label: 'File Upload' }\n ]\"\n label=\"Control Type\"\n size=\"sm\">\n </cide-ele-select>\n </div>\n\n <!-- Status - Checkbox aligned properly -->\n <div class=\"form-group\">\n <cide-ele-input\n id=\"sype_isactive\"\n type=\"checkbox\"\n formControlName=\"sype_isactive\"\n label=\"Active Status\"\n size=\"sm\">\n </cide-ele-input>\n </div>\n\n <!-- Placeholder -->\n <div class=\"form-group\">\n <cide-ele-input\n id=\"sype_placeholder\"\n formControlName=\"sype_placeholder\"\n placeholder=\"Enter placeholder text\"\n label=\"Placeholder\"\n size=\"sm\">\n </cide-ele-input>\n </div>\n\n <!-- Auto Complete - Checkbox aligned properly -->\n <div class=\"form-group\">\n <cide-ele-input\n id=\"sype_auto_complete\"\n type=\"checkbox\"\n formControlName=\"sype_auto_complete\"\n label=\"Auto Complete\"\n size=\"sm\">\n </cide-ele-input>\n </div>\n\n <!-- Tooltip -->\n <div class=\"form-group\">\n <cide-ele-input\n id=\"sype_tooltip\"\n formControlName=\"sype_tooltip\"\n placeholder=\"Enter tooltip text\"\n label=\"Tooltip\"\n size=\"sm\">\n </cide-ele-input>\n </div>\n\n <!-- Validation & Sizing Section -->\n <!-- Min/Max Length - Side by side -->\n <div class=\"form-group form-group-row\">\n <div class=\"form-group-half\">\n <cide-ele-input\n id=\"sype_min_length\"\n type=\"number\"\n formControlName=\"sype_min_length\"\n placeholder=\"0\"\n label=\"Min Length\"\n size=\"xs\">\n </cide-ele-input>\n </div>\n <div class=\"form-group-half\">\n <cide-ele-input\n id=\"sype_max_length\"\n type=\"number\"\n formControlName=\"sype_max_length\"\n placeholder=\"20\"\n label=\"Max Length\"\n size=\"xs\">\n </cide-ele-input>\n </div>\n </div>\n\n <!-- Size & Label Placement - Side by side -->\n <div class=\"form-group form-group-row\">\n <div class=\"form-group-half\">\n <cide-ele-select\n id=\"sype_size\"\n formControlName=\"sype_size\"\n label=\"Size\"\n size=\"xs\"\n [options]=\"[\n { value: 'xs', label: 'XS' },\n { value: 'sm', label: 'SM' },\n { value: 'md', label: 'MD' },\n { value: 'lg', label: 'LG' },\n { value: 'xl', label: 'XL' },\n { value: 'xxl', label: 'XXL' }\n ]\">\n </cide-ele-select>\n </div>\n <div class=\"form-group-half\">\n <cide-ele-select\n id=\"sype_label_placement\"\n formControlName=\"sype_label_placement\"\n label=\"Label Placement\"\n size=\"xs\"\n [options]=\"[\n { value: 'left', label: 'Left' },\n { value: 'floating', label: 'Floating' },\n { value: 'fixed', label: 'Fixed' }\n ]\">\n </cide-ele-select>\n </div>\n </div>\n\n <!-- Width & Height - Side by side -->\n <div class=\"form-group form-group-row\">\n <div class=\"form-group-half\">\n <cide-ele-input\n id=\"sype_width\"\n type=\"text\"\n formControlName=\"sype_width\"\n placeholder=\"20px\"\n label=\"Width\"\n size=\"xs\">\n </cide-ele-input>\n </div>\n <div class=\"form-group-half\">\n <cide-ele-input\n id=\"sype_height\"\n type=\"text\"\n formControlName=\"sype_height\"\n placeholder=\"20px\"\n label=\"Height\"\n size=\"xs\">\n </cide-ele-input>\n </div>\n </div>\n\n <!-- Leading Icon -->\n <div class=\"form-group\">\n <cide-ele-input\n id=\"sype_leading_icon\"\n formControlName=\"sype_leading_icon\"\n placeholder=\"Enter icon name\"\n label=\"Leading Icon\"\n size=\"sm\">\n </cide-ele-input>\n </div>\n\n <!-- Default Value -->\n <div class=\"form-group\">\n <cide-ele-input\n id=\"sype_default\"\n formControlName=\"sype_default\"\n placeholder=\"Enter default value\"\n label=\"Default Value\"\n size=\"sm\">\n </cide-ele-input>\n </div>\n\n <!-- Regex Pattern -->\n <div class=\"form-group\">\n <cide-ele-input\n id=\"sype_regex\"\n formControlName=\"sype_regex\"\n placeholder=\"Enter regex pattern\"\n label=\"Regex Pattern\"\n size=\"sm\">\n </cide-ele-input>\n </div>\n\n <!-- Option Key -->\n <div class=\"form-group\">\n <cide-ele-input\n id=\"sype_option_key\"\n formControlName=\"sype_option_key\"\n placeholder=\"Enter option key\"\n label=\"Option Key\"\n size=\"sm\">\n </cide-ele-input>\n </div>\n\n <!-- Entity ID (Auto-assigned from AppState) - Hidden -->\n <div class=\"form-group\" style=\"display: none;\">\n <cide-ele-input\n id=\"sype_entity_id_syen\"\n formControlName=\"sype_entity_id_syen\"\n placeholder=\"Auto-assigned from system\"\n label=\"Entity ID (Auto-assigned)\"\n size=\"sm\"\n readonly>\n </cide-ele-input>\n </div>\n\n <!-- Control Options -->\n <div class=\"form-group full-width\">\n <h6 class=\"options-title\">Control Options</h6>\n <div class=\"options-grid\">\n \n <!-- Required -->\n <div class=\"option-item\">\n <cide-ele-input\n id=\"sype_required\"\n type=\"checkbox\"\n formControlName=\"sype_required\"\n label=\"Required\"\n size=\"xs\">\n </cide-ele-input>\n </div>\n\n <!-- Disabled -->\n <div class=\"option-item\">\n <cide-ele-input\n id=\"sype_disabled\"\n type=\"checkbox\"\n formControlName=\"sype_disabled\"\n label=\"Disabled\"\n size=\"xs\">\n </cide-ele-input>\n </div>\n\n <!-- Hide Label -->\n <div class=\"option-item\">\n <cide-ele-input\n id=\"sype_label_hide\"\n type=\"checkbox\"\n formControlName=\"sype_label_hide\"\n label=\"Hide Label\"\n size=\"xs\">\n </cide-ele-input>\n </div>\n\n <!-- Hide Helper Text -->\n <div class=\"option-item\">\n <cide-ele-input\n id=\"sype_hide_helper_and_error_text\"\n type=\"checkbox\"\n formControlName=\"sype_hide_helper_and_error_text\"\n label=\"Hide Helper Text\"\n size=\"xs\">\n </cide-ele-input>\n </div>\n\n <!-- Helper Text Collapse -->\n <div class=\"option-item\">\n <cide-ele-input\n id=\"sype_helper_text_collapse\"\n type=\"checkbox\"\n formControlName=\"sype_helper_text_collapse\"\n label=\"Collapse Helper\"\n size=\"xs\">\n </cide-ele-input>\n </div>\n\n </div>\n </div>\n\n </div>\n\n <!-- Form Actions -->\n <div class=\"form-actions\">\n <button \n cideEleButton\n type=\"button\"\n variant=\"outline\"\n (click)=\"cancelForm()\"\n [disabled]=\"loading()\">\n Cancel\n </button>\n <button \n cideEleButton\n type=\"submit\"\n variant=\"primary\"\n [disabled]=\"loading()\">\n {{ isEditMode() ? 'Update Control' : 'Create Control' }}\n </button>\n </div>\n </form>\n </div>\n\n <!-- Controls List Section -->\n <div class=\"controls-list-section\">\n <div class=\"controls-header\">\n <h3>Page Controls</h3>\n <p>Controls connected to this page</p>\n </div>\n \n <div class=\"controls-list\" *ngIf=\"!loading() && controls().length > 0\">\n <div \n class=\"control-item\" \n *ngFor=\"let control of controls(); trackBy: trackByControlId\"\n [class.selected]=\"selectedControlId() === control._id\"\n (click)=\"selectControl(control)\"\n (keyup.enter)=\"selectControl(control)\"\n (keyup.space)=\"selectControl(control)\"\n tabindex=\"0\"\n role=\"button\"\n [attr.aria-label]=\"'Select control ' + (control.sype_label || control.sype_key)\">\n <div class=\"control-header\">\n <div class=\"control-icon\">\n <cide-ele-icon>settings_input_component</cide-ele-icon>\n </div>\n <div class=\"control-info\">\n <h4>{{ control.sype_label || control.sype_key }}</h4>\n <p>{{ control.sype_tooltip || 'No tooltip' }}</p>\n <div class=\"control-meta\">\n <span class=\"control-type\">{{ control.sype_type }}</span>\n <span class=\"control-status\" [class.active]=\"control.sype_isactive\">\n {{ control.sype_isactive ? 'Active' : 'Inactive' }}\n </span>\n </div>\n </div>\n <div class=\"control-actions\">\n <button \n cideEleButton\n variant=\"ghost\"\n size=\"sm\"\n (click)=\"editControl(control); $event.stopPropagation()\">\n <cide-ele-icon>edit</cide-ele-icon>\n </button>\n <button \n cideEleButton\n variant=\"ghost\"\n size=\"sm\"\n (click)=\"deleteControl(control); $event.stopPropagation()\">\n <cide-ele-icon>delete</cide-ele-icon>\n </button>\n </div>\n </div>\n \n \n </div>\n </div>\n\n <div class=\"controls-list-empty\" *ngIf=\"!loading() && controls().length === 0\">\n <cide-ele-icon>settings_input_component</cide-ele-icon>\n <p>No controls available</p>\n <small>Create controls using the form on the left</small>\n </div>\n\n <div class=\"controls-list-loading\" *ngIf=\"loading()\">\n <cide-ele-icon class=\"spinning\">refresh</cide-ele-icon>\n <p>Loading controls...</p>\n </div>\n </div>\n </div>\n</div>\n\n ", styles: [".page-controls-container{@apply tw-flex tw-flex-col tw-h-full tw-bg-gray-50;}.header{@apply tw-bg-white tw-border-b tw-border-gray-200 tw-px-6 tw-py-4;}.header-content{@apply tw-flex tw-items-center tw-justify-between;}.header-left{@apply tw-flex tw-items-center tw-space-x-4;}.back-button{@apply tw-flex tw-items-center tw-justify-center tw-w-8 tw-h-8 tw-text-gray-600 hover:tw-text-gray-900 hover:tw-bg-gray-100 tw-rounded-md tw-transition-colors;}.title-section{@apply tw-flex tw-items-center tw-space-x-3;}.title-icon{@apply tw-text-blue-600 tw-text-xl;}.title{@apply tw-text-xl tw-font-semibold tw-text-gray-900 tw-mb-0;}.subtitle{@apply tw-text-sm tw-text-gray-500 tw-mb-0;}.error-message{@apply tw-bg-red-50 tw-border tw-border-red-200 tw-rounded-md tw-p-4 tw-mx-6 tw-mt-4 tw-flex tw-items-start tw-space-x-3;}.error-message cide-ele-icon{@apply tw-text-red-500 tw-flex-shrink-0 tw-mt-0.5;}.error-message h3{@apply tw-text-red-800 tw-font-medium tw-mb-1;}.error-message p{@apply tw-text-red-700 tw-text-sm tw-mb-0;}.main-content{@apply tw-flex tw-flex-1 tw-gap-6 tw-p-6 tw-overflow-hidden;}.form-section{@apply tw-w-3/5 tw-bg-white tw-rounded-lg tw-border tw-border-gray-200 tw-shadow-sm tw-flex tw-flex-col;}.form-header{@apply tw-flex tw-items-center tw-space-x-3 tw-p-6 tw-border-b tw-border-gray-200;}.form-header cide-ele-icon{@apply tw-text-blue-600;}.form-header h3{@apply tw-text-lg tw-font-medium tw-text-gray-900 tw-mb-0;}.control-form{@apply tw-flex tw-flex-col tw-flex-1 tw-p-6;}.form-grid{@apply tw-grid tw-grid-cols-2 tw-gap-4 tw-mb-6;}.form-group{@apply tw-space-y-1;}.form-group.full-width{@apply tw-col-span-2;}.form-group.compact-number,.form-group.compact-select,.form-group.compact-dimension{@apply tw-max-w-32;}.form-group.compact-number{@apply tw-min-w-20;}.form-group.compact-dimension{@apply tw-min-w-24;}.form-group.compact-select{@apply tw-min-w-28;}.form-group.form-group-row{@apply tw-col-span-2 tw-flex tw-gap-4;}.form-group-half{@apply tw-flex-1 tw-space-y-1;}.checkbox-field{margin:.25rem 0}.checkbox-label{display:flex;flex-direction:column;gap:.25rem;cursor:pointer;padding:.75rem 0;background:transparent;border:none;border-radius:0;transition:all .2s ease}.checkbox-label:hover{background:#667eea05}.checkbox-label .checkbox-input{width:1rem;height:1rem;accent-color:#667eea;border-radius:3px;margin-bottom:.125rem}.checkbox-label .checkbox-text{font-weight:600;color:#374151;font-size:.875rem}.checkbox-label .checkbox-description{font-size:.75rem;color:#6b7280;margin-top:.125rem}.options-title{@apply tw-text-sm tw-font-medium tw-text-gray-900 tw-mb-3;}.options-grid{@apply tw-grid tw-grid-cols-3 tw-gap-3;}.option-item{@apply tw-flex tw-items-center tw-space-x-2;}.option-checkbox{@apply tw-rounded tw-border-gray-300 tw-text-blue-600 focus:tw-ring-blue-500 focus:tw-border-blue-500;}.option-item label{@apply tw-text-sm tw-text-gray-700 tw-cursor-pointer;}.form-actions{@apply tw-flex tw-justify-end tw-space-x-3 tw-pt-4 tw-border-t tw-border-gray-200 tw-mt-auto;}.controls-list-section{@apply tw-w-2/5 tw-bg-white tw-rounded-lg tw-border tw-border-gray-200 tw-shadow-sm tw-flex tw-flex-col;}.controls-header{@apply tw-p-6 tw-border-b tw-border-gray-200;}.controls-header h3{@apply tw-text-lg tw-font-medium tw-text-gray-900 tw-mb-1;}.controls-header p{@apply tw-text-sm tw-text-gray-500 tw-mb-0;}.controls-list{@apply tw-flex-1 tw-overflow-y-auto tw-p-4;}.control-item{@apply tw-bg-gray-50 tw-border tw-border-gray-200 tw-rounded-lg tw-p-4 tw-mb-3 tw-cursor-pointer tw-transition-all tw-duration-200;}.control-item:hover{@apply tw-shadow-md tw-border-gray-300;}.control-item.selected{@apply tw-bg-blue-50 tw-border-blue-300 tw-shadow-md;}.control-item:focus{@apply tw-outline-none tw-ring-2 tw-ring-blue-500 tw-ring-offset-2;}.control-item:last-child{@apply tw-mb-0;}.control-header{@apply tw-flex tw-items-start tw-space-x-3;}.control-icon{@apply tw-flex-shrink-0 tw-w-10 tw-h-10 tw-bg-blue-100 tw-rounded-lg tw-flex tw-items-center tw-justify-center;}.control-icon cide-ele-icon{@apply tw-text-blue-600;}.control-info{@apply tw-flex-1 tw-min-w-0;}.control-info h4{@apply tw-text-sm tw-font-medium tw-text-gray-900 tw-mb-1 tw-truncate;}.control-info p{@apply tw-text-xs tw-text-gray-500 tw-mb-2 tw-truncate;}.control-meta{@apply tw-flex tw-items-center tw-space-x-2;}.control-type{@apply tw-inline-flex tw-items-center tw-px-2 tw-py-0.5 tw-rounded-full tw-text-xs tw-font-medium tw-bg-gray-100 tw-text-gray-800;}.control-status{@apply tw-inline-flex tw-items-center tw-px-2 tw-py-0.5 tw-rounded-full tw-text-xs tw-font-medium tw-bg-red-100 tw-text-red-800;}.control-status.active{@apply tw-bg-green-100 tw-text-green-800;}.control-actions{@apply tw-flex tw-items-center tw-space-x-1 tw-opacity-0 tw-transition-opacity tw-duration-200;}.control-item:hover .control-actions,.control-item.selected .control-actions{@apply tw-opacity-100;}.controls-list-empty{@apply tw-flex tw-flex-col tw-items-center tw-justify-center tw-py-12 tw-text-center;}.controls-list-empty cide-ele-icon{@apply tw-text-4xl tw-text-gray-300 tw-mb-4;}.controls-list-empty p{@apply tw-text-gray-500 tw-font-medium tw-mb-1;}.controls-list-empty small{@apply tw-text-gray-400;}.controls-list-loading{@apply tw-flex tw-flex-col tw-items-center tw-justify-center tw-py-12 tw-text-center;}.controls-list-loading cide-ele-icon{@apply tw-text-2xl tw-text-blue-500 tw-mb-4;}.controls-list-loading p{@apply tw-text-gray-500;}.spinning{animation:spin 1s linear infinite}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@media (max-width: 1024px){.main-content{@apply tw-flex-col;}.form-section{@apply tw-w-full;}.controls-list-section{@apply tw-w-full tw-max-h-96;}.form-grid{@apply tw-grid-cols-1;}.options-grid{@apply tw-grid-cols-2;}}@media (max-width: 640px){.main-content{@apply tw-p-4 tw-gap-4;}.form-grid{@apply tw-gap-3;}.form-actions{@apply tw-flex-col tw-space-x-0 tw-space-y-2;}.options-grid{@apply tw-grid-cols-1;}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: FormsModule }, { kind: "component", type: CideEleButtonComponent, selector: "button[cideEleButton], a[cideEleButton]", inputs: ["label", "variant", "size", "type", "shape", "elevation", "disabled", "id", "loading", "fullWidth", "leftIcon", "rightIcon", "customClass", "tooltip", "ariaLabel", "testId", "routerLink", "routerExtras", "preventDoubleClick", "animated"], outputs: ["btnClick", "doubleClick"] }, { kind: "component", type: CideInputComponent, selector: "cide-ele-input", inputs: ["fill", "label", "labelHide", "disabled", "clearInput", "labelPlacement", "labelDir", "placeholder", "leadingIcon", "trailingIcon", "helperText", "helperTextCollapse", "hideHelperAndErrorText", "errorText", "maxlength", "minlength", "required", "autocapitalize", "autocomplete", "type", "width", "id", "ngModel", "option", "min", "max", "size"], outputs: ["ngModelChange"] }, { kind: "component", type: CideSelectComponent, selector: "cide-ele-select", inputs: ["label", "labelHide", "placeholder", "helperText", "errorText", "required", "disabled", "id", "ngModel", "size", "fill", "labelPlacement", "labelDir", "leadingIcon", "trailingIcon", "clearInput", "options", "multiple", "searchable", "showSearchInput", "loading"], outputs: ["ngModelChange", "change", "searchChange"] }, { kind: "component", type: CideIconComponent, selector: "cide-ele-icon", inputs: ["size", "type", "toolTip"] }] }); }
7000
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: PageControlsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
7001
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.7", type: PageControlsComponent, isStandalone: true, selector: "cide-core-app-page-controls", ngImport: i0, template: "<!-- Page Controls Container -->\n<div class=\"page-controls-container\">\n <!-- Header Section -->\n <div class=\"header\">\n <div class=\"header-content\">\n <div class=\"header-left\">\n <button \n cideEleButton\n variant=\"ghost\"\n size=\"sm\"\n (click)=\"goBack()\"\n class=\"back-button\">\n <cide-ele-icon>arrow_back</cide-ele-icon>\n </button>\n <div class=\"title-section\">\n <cide-ele-icon class=\"title-icon\">settings</cide-ele-icon>\n <div>\n <h1 class=\"title\">Control Management</h1>\n <p class=\"subtitle\">Page: {{ pageTitle() }}</p>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Error Message -->\n <div class=\"error-message\" *ngIf=\"error()\">\n <cide-ele-icon>error</cide-ele-icon>\n <div>\n <h3>Error</h3>\n <p>{{ error() }}</p>\n </div>\n </div>\n\n <!-- Main Content Area -->\n <div class=\"main-content\">\n <!-- Form Section -->\n <div class=\"form-section\">\n <div class=\"form-header\">\n <cide-ele-icon>{{ isEditMode() ? 'edit' : 'add' }}</cide-ele-icon>\n <h3>{{ isEditMode() ? 'Edit Control' : 'Quick Add Control' }}</h3>\n </div>\n\n <!-- Form -->\n <form [formGroup]=\"controlForm\" (ngSubmit)=\"saveControl()\" class=\"control-form tw-overflow-y-auto\">\n <div class=\"form-grid\">\n \n <!-- Basic Information Section -->\n <!-- Control Key -->\n <div class=\"form-group\">\n <cide-ele-input\n id=\"sype_key\"\n formControlName=\"sype_key\"\n placeholder=\"Enter control key\"\n label=\"Control Key\"\n size=\"sm\">\n </cide-ele-input>\n </div>\n\n <!-- Control Label -->\n <div class=\"form-group\">\n <cide-ele-input\n id=\"sype_label\"\n formControlName=\"sype_label\"\n placeholder=\"Enter control label\"\n label=\"Control Label\"\n size=\"sm\">\n </cide-ele-input>\n </div>\n\n <!-- Control Type -->\n <div class=\"form-group\">\n <cide-ele-select\n id=\"sype_type\"\n formControlName=\"sype_type\"\n [options]=\"[\n { value: 'text', label: 'Text Input' },\n { value: 'textarea', label: 'Text Area' },\n { value: 'select', label: 'Select' },\n { value: 'checkbox', label: 'Checkbox' },\n { value: 'radio', label: 'Radio' },\n { value: 'date', label: 'Date' },\n { value: 'number', label: 'Number' },\n { value: 'email', label: 'Email' },\n { value: 'password', label: 'Password' },\n { value: 'file', label: 'File Upload' }\n ]\"\n label=\"Control Type\"\n size=\"sm\">\n </cide-ele-select>\n </div>\n\n <!-- Status - Checkbox aligned properly -->\n <div class=\"form-group\">\n <cide-ele-input\n id=\"sype_isactive\"\n type=\"checkbox\"\n formControlName=\"sype_isactive\"\n label=\"Active Status\"\n size=\"sm\">\n </cide-ele-input>\n </div>\n\n <!-- Placeholder -->\n <div class=\"form-group\">\n <cide-ele-input\n id=\"sype_placeholder\"\n formControlName=\"sype_placeholder\"\n placeholder=\"Enter placeholder text\"\n label=\"Placeholder\"\n size=\"sm\">\n </cide-ele-input>\n </div>\n\n <!-- Auto Complete - Checkbox aligned properly -->\n <div class=\"form-group\">\n <cide-ele-input\n id=\"sype_auto_complete\"\n type=\"checkbox\"\n formControlName=\"sype_auto_complete\"\n label=\"Auto Complete\"\n size=\"sm\">\n </cide-ele-input>\n </div>\n\n <!-- Tooltip -->\n <div class=\"form-group\">\n <cide-ele-input\n id=\"sype_tooltip\"\n formControlName=\"sype_tooltip\"\n placeholder=\"Enter tooltip text\"\n label=\"Tooltip\"\n size=\"sm\">\n </cide-ele-input>\n </div>\n\n <!-- Validation & Sizing Section -->\n <!-- Min/Max Length - Side by side -->\n <div class=\"form-group form-group-row\">\n <div class=\"form-group-half\">\n <cide-ele-input\n id=\"sype_min_length\"\n type=\"number\"\n formControlName=\"sype_min_length\"\n placeholder=\"0\"\n label=\"Min Length\"\n size=\"xs\">\n </cide-ele-input>\n </div>\n <div class=\"form-group-half\">\n <cide-ele-input\n id=\"sype_max_length\"\n type=\"number\"\n formControlName=\"sype_max_length\"\n placeholder=\"20\"\n label=\"Max Length\"\n size=\"xs\">\n </cide-ele-input>\n </div>\n </div>\n\n <!-- Size & Label Placement - Side by side -->\n <div class=\"form-group form-group-row\">\n <div class=\"form-group-half\">\n <cide-ele-select\n id=\"sype_size\"\n formControlName=\"sype_size\"\n label=\"Size\"\n size=\"xs\"\n [options]=\"[\n { value: 'xs', label: 'XS' },\n { value: 'sm', label: 'SM' },\n { value: 'md', label: 'MD' },\n { value: 'lg', label: 'LG' },\n { value: 'xl', label: 'XL' },\n { value: 'xxl', label: 'XXL' }\n ]\">\n </cide-ele-select>\n </div>\n <div class=\"form-group-half\">\n <cide-ele-select\n id=\"sype_label_placement\"\n formControlName=\"sype_label_placement\"\n label=\"Label Placement\"\n size=\"xs\"\n [options]=\"[\n { value: 'left', label: 'Left' },\n { value: 'floating', label: 'Floating' },\n { value: 'fixed', label: 'Fixed' }\n ]\">\n </cide-ele-select>\n </div>\n </div>\n\n <!-- Width & Height - Side by side -->\n <div class=\"form-group form-group-row\">\n <div class=\"form-group-half\">\n <cide-ele-input\n id=\"sype_width\"\n type=\"text\"\n formControlName=\"sype_width\"\n placeholder=\"20px\"\n label=\"Width\"\n size=\"xs\">\n </cide-ele-input>\n </div>\n <div class=\"form-group-half\">\n <cide-ele-input\n id=\"sype_height\"\n type=\"text\"\n formControlName=\"sype_height\"\n placeholder=\"20px\"\n label=\"Height\"\n size=\"xs\">\n </cide-ele-input>\n </div>\n </div>\n\n <!-- Leading Icon -->\n <div class=\"form-group\">\n <cide-ele-input\n id=\"sype_leading_icon\"\n formControlName=\"sype_leading_icon\"\n placeholder=\"Enter icon name\"\n label=\"Leading Icon\"\n size=\"sm\">\n </cide-ele-input>\n </div>\n\n <!-- Default Value -->\n <div class=\"form-group\">\n <cide-ele-input\n id=\"sype_default\"\n formControlName=\"sype_default\"\n placeholder=\"Enter default value\"\n label=\"Default Value\"\n size=\"sm\">\n </cide-ele-input>\n </div>\n\n <!-- Regex Pattern -->\n <div class=\"form-group\">\n <cide-ele-input\n id=\"sype_regex\"\n formControlName=\"sype_regex\"\n placeholder=\"Enter regex pattern\"\n label=\"Regex Pattern\"\n size=\"sm\">\n </cide-ele-input>\n </div>\n\n <!-- Option Key -->\n <div class=\"form-group\">\n <cide-ele-input\n id=\"sype_option_key\"\n formControlName=\"sype_option_key\"\n placeholder=\"Enter option key\"\n label=\"Option Key\"\n size=\"sm\">\n </cide-ele-input>\n </div>\n\n <!-- Entity ID (Auto-assigned from AppState) - Hidden -->\n <div class=\"form-group\" style=\"display: none;\">\n <cide-ele-input\n id=\"sype_entity_id_syen\"\n formControlName=\"sype_entity_id_syen\"\n placeholder=\"Auto-assigned from system\"\n label=\"Entity ID (Auto-assigned)\"\n size=\"sm\"\n readonly>\n </cide-ele-input>\n </div>\n\n <!-- Control Options -->\n <div class=\"form-group full-width\">\n <h6 class=\"options-title\">Control Options</h6>\n <div class=\"options-grid\">\n \n <!-- Required -->\n <div class=\"option-item\">\n <cide-ele-input\n id=\"sype_required\"\n type=\"checkbox\"\n formControlName=\"sype_required\"\n label=\"Required\"\n size=\"xs\">\n </cide-ele-input>\n </div>\n\n <!-- Disabled -->\n <div class=\"option-item\">\n <cide-ele-input\n id=\"sype_disabled\"\n type=\"checkbox\"\n formControlName=\"sype_disabled\"\n label=\"Disabled\"\n size=\"xs\">\n </cide-ele-input>\n </div>\n\n <!-- Hide Label -->\n <div class=\"option-item\">\n <cide-ele-input\n id=\"sype_label_hide\"\n type=\"checkbox\"\n formControlName=\"sype_label_hide\"\n label=\"Hide Label\"\n size=\"xs\">\n </cide-ele-input>\n </div>\n\n <!-- Hide Helper Text -->\n <div class=\"option-item\">\n <cide-ele-input\n id=\"sype_hide_helper_and_error_text\"\n type=\"checkbox\"\n formControlName=\"sype_hide_helper_and_error_text\"\n label=\"Hide Helper Text\"\n size=\"xs\">\n </cide-ele-input>\n </div>\n\n <!-- Helper Text Collapse -->\n <div class=\"option-item\">\n <cide-ele-input\n id=\"sype_helper_text_collapse\"\n type=\"checkbox\"\n formControlName=\"sype_helper_text_collapse\"\n label=\"Collapse Helper\"\n size=\"xs\">\n </cide-ele-input>\n </div>\n\n </div>\n </div>\n\n </div>\n\n <!-- Form Actions -->\n <div class=\"form-actions\">\n <button \n cideEleButton\n type=\"button\"\n variant=\"outline\"\n (click)=\"cancelForm()\"\n [disabled]=\"loading()\">\n Cancel\n </button>\n <button \n cideEleButton\n type=\"submit\"\n variant=\"primary\"\n [disabled]=\"loading()\">\n {{ isEditMode() ? 'Update Control' : 'Create Control' }}\n </button>\n </div>\n </form>\n </div>\n\n <!-- Controls List Section -->\n <div class=\"controls-list-section\">\n <div class=\"controls-header\">\n <h3>Page Controls</h3>\n <p>Controls connected to this page</p>\n </div>\n \n <div class=\"controls-list\" *ngIf=\"!loading() && controls().length > 0\">\n <div \n class=\"control-item\" \n *ngFor=\"let control of controls(); trackBy: trackByControlId\"\n [class.selected]=\"selectedControlId() === control._id\"\n (click)=\"selectControl(control)\"\n (keyup.enter)=\"selectControl(control)\"\n (keyup.space)=\"selectControl(control)\"\n tabindex=\"0\"\n role=\"button\"\n [attr.aria-label]=\"'Select control ' + (control.sype_label || control.sype_key)\">\n <div class=\"control-header\">\n <div class=\"control-icon\">\n <cide-ele-icon>settings_input_component</cide-ele-icon>\n </div>\n <div class=\"control-info\">\n <h4>{{ control.sype_label || control.sype_key }}</h4>\n <p>{{ control.sype_tooltip || 'No tooltip' }}</p>\n <div class=\"control-meta\">\n <span class=\"control-type\">{{ control.sype_type }}</span>\n <span class=\"control-status\" [class.active]=\"control.sype_isactive\">\n {{ control.sype_isactive ? 'Active' : 'Inactive' }}\n </span>\n </div>\n </div>\n <div class=\"control-actions\">\n <button \n cideEleButton\n variant=\"ghost\"\n size=\"sm\"\n (click)=\"editControl(control); $event.stopPropagation()\">\n <cide-ele-icon>edit</cide-ele-icon>\n </button>\n <button \n cideEleButton\n variant=\"ghost\"\n size=\"sm\"\n (click)=\"deleteControl(control); $event.stopPropagation()\">\n <cide-ele-icon>delete</cide-ele-icon>\n </button>\n </div>\n </div>\n \n \n </div>\n </div>\n\n <div class=\"controls-list-empty\" *ngIf=\"!loading() && controls().length === 0\">\n <cide-ele-icon>settings_input_component</cide-ele-icon>\n <p>No controls available</p>\n <small>Create controls using the form on the left</small>\n </div>\n\n <div class=\"controls-list-loading\" *ngIf=\"loading()\">\n <cide-ele-icon class=\"spinning\">refresh</cide-ele-icon>\n <p>Loading controls...</p>\n </div>\n </div>\n </div>\n</div>\n\n ", styles: [".page-controls-container{@apply tw-flex tw-flex-col tw-h-full tw-bg-gray-50;}.header{@apply tw-bg-white tw-border-b tw-border-gray-200 tw-px-6 tw-py-4;}.header-content{@apply tw-flex tw-items-center tw-justify-between;}.header-left{@apply tw-flex tw-items-center tw-space-x-4;}.back-button{@apply tw-flex tw-items-center tw-justify-center tw-w-8 tw-h-8 tw-text-gray-600 hover:tw-text-gray-900 hover:tw-bg-gray-100 tw-rounded-md tw-transition-colors;}.title-section{@apply tw-flex tw-items-center tw-space-x-3;}.title-icon{@apply tw-text-blue-600 tw-text-xl;}.title{@apply tw-text-xl tw-font-semibold tw-text-gray-900 tw-mb-0;}.subtitle{@apply tw-text-sm tw-text-gray-500 tw-mb-0;}.error-message{@apply tw-bg-red-50 tw-border tw-border-red-200 tw-rounded-md tw-p-4 tw-mx-6 tw-mt-4 tw-flex tw-items-start tw-space-x-3;}.error-message cide-ele-icon{@apply tw-text-red-500 tw-flex-shrink-0 tw-mt-0.5;}.error-message h3{@apply tw-text-red-800 tw-font-medium tw-mb-1;}.error-message p{@apply tw-text-red-700 tw-text-sm tw-mb-0;}.main-content{@apply tw-flex tw-flex-1 tw-gap-6 tw-p-6 tw-overflow-hidden;}.form-section{@apply tw-w-3/5 tw-bg-white tw-rounded-lg tw-border tw-border-gray-200 tw-shadow-sm tw-flex tw-flex-col;}.form-header{@apply tw-flex tw-items-center tw-space-x-3 tw-p-6 tw-border-b tw-border-gray-200;}.form-header cide-ele-icon{@apply tw-text-blue-600;}.form-header h3{@apply tw-text-lg tw-font-medium tw-text-gray-900 tw-mb-0;}.control-form{@apply tw-flex tw-flex-col tw-flex-1 tw-p-6;}.form-grid{@apply tw-grid tw-grid-cols-2 tw-gap-4 tw-mb-6;}.form-group{@apply tw-space-y-1;}.form-group.full-width{@apply tw-col-span-2;}.form-group.compact-number,.form-group.compact-select,.form-group.compact-dimension{@apply tw-max-w-32;}.form-group.compact-number{@apply tw-min-w-20;}.form-group.compact-dimension{@apply tw-min-w-24;}.form-group.compact-select{@apply tw-min-w-28;}.form-group.form-group-row{@apply tw-col-span-2 tw-flex tw-gap-4;}.form-group-half{@apply tw-flex-1 tw-space-y-1;}.checkbox-field{margin:.25rem 0}.checkbox-label{display:flex;flex-direction:column;gap:.25rem;cursor:pointer;padding:.75rem 0;background:transparent;border:none;border-radius:0;transition:all .2s ease}.checkbox-label:hover{background:#667eea05}.checkbox-label .checkbox-input{width:1rem;height:1rem;accent-color:#667eea;border-radius:3px;margin-bottom:.125rem}.checkbox-label .checkbox-text{font-weight:600;color:#374151;font-size:.875rem}.checkbox-label .checkbox-description{font-size:.75rem;color:#6b7280;margin-top:.125rem}.options-title{@apply tw-text-sm tw-font-medium tw-text-gray-900 tw-mb-3;}.options-grid{@apply tw-grid tw-grid-cols-3 tw-gap-3;}.option-item{@apply tw-flex tw-items-center tw-space-x-2;}.option-checkbox{@apply tw-rounded tw-border-gray-300 tw-text-blue-600 focus:tw-ring-blue-500 focus:tw-border-blue-500;}.option-item label{@apply tw-text-sm tw-text-gray-700 tw-cursor-pointer;}.form-actions{@apply tw-flex tw-justify-end tw-space-x-3 tw-pt-4 tw-border-t tw-border-gray-200 tw-mt-auto;}.controls-list-section{@apply tw-w-2/5 tw-bg-white tw-rounded-lg tw-border tw-border-gray-200 tw-shadow-sm tw-flex tw-flex-col;}.controls-header{@apply tw-p-6 tw-border-b tw-border-gray-200;}.controls-header h3{@apply tw-text-lg tw-font-medium tw-text-gray-900 tw-mb-1;}.controls-header p{@apply tw-text-sm tw-text-gray-500 tw-mb-0;}.controls-list{@apply tw-flex-1 tw-overflow-y-auto tw-p-4;}.control-item{@apply tw-bg-gray-50 tw-border tw-border-gray-200 tw-rounded-lg tw-p-4 tw-mb-3 tw-cursor-pointer tw-transition-all tw-duration-200;}.control-item:hover{@apply tw-shadow-md tw-border-gray-300;}.control-item.selected{@apply tw-bg-blue-50 tw-border-blue-300 tw-shadow-md;}.control-item:focus{@apply tw-outline-none tw-ring-2 tw-ring-blue-500 tw-ring-offset-2;}.control-item:last-child{@apply tw-mb-0;}.control-header{@apply tw-flex tw-items-start tw-space-x-3;}.control-icon{@apply tw-flex-shrink-0 tw-w-10 tw-h-10 tw-bg-blue-100 tw-rounded-lg tw-flex tw-items-center tw-justify-center;}.control-icon cide-ele-icon{@apply tw-text-blue-600;}.control-info{@apply tw-flex-1 tw-min-w-0;}.control-info h4{@apply tw-text-sm tw-font-medium tw-text-gray-900 tw-mb-1 tw-truncate;}.control-info p{@apply tw-text-xs tw-text-gray-500 tw-mb-2 tw-truncate;}.control-meta{@apply tw-flex tw-items-center tw-space-x-2;}.control-type{@apply tw-inline-flex tw-items-center tw-px-2 tw-py-0.5 tw-rounded-full tw-text-xs tw-font-medium tw-bg-gray-100 tw-text-gray-800;}.control-status{@apply tw-inline-flex tw-items-center tw-px-2 tw-py-0.5 tw-rounded-full tw-text-xs tw-font-medium tw-bg-red-100 tw-text-red-800;}.control-status.active{@apply tw-bg-green-100 tw-text-green-800;}.control-actions{@apply tw-flex tw-items-center tw-space-x-1 tw-opacity-0 tw-transition-opacity tw-duration-200;}.control-item:hover .control-actions,.control-item.selected .control-actions{@apply tw-opacity-100;}.controls-list-empty{@apply tw-flex tw-flex-col tw-items-center tw-justify-center tw-py-12 tw-text-center;}.controls-list-empty cide-ele-icon{@apply tw-text-4xl tw-text-gray-300 tw-mb-4;}.controls-list-empty p{@apply tw-text-gray-500 tw-font-medium tw-mb-1;}.controls-list-empty small{@apply tw-text-gray-400;}.controls-list-loading{@apply tw-flex tw-flex-col tw-items-center tw-justify-center tw-py-12 tw-text-center;}.controls-list-loading cide-ele-icon{@apply tw-text-2xl tw-text-blue-500 tw-mb-4;}.controls-list-loading p{@apply tw-text-gray-500;}.spinning{animation:spin 1s linear infinite}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@media (max-width: 1024px){.main-content{@apply tw-flex-col;}.form-section{@apply tw-w-full;}.controls-list-section{@apply tw-w-full tw-max-h-96;}.form-grid{@apply tw-grid-cols-1;}.options-grid{@apply tw-grid-cols-2;}}@media (max-width: 640px){.main-content{@apply tw-p-4 tw-gap-4;}.form-grid{@apply tw-gap-3;}.form-actions{@apply tw-flex-col tw-space-x-0 tw-space-y-2;}.options-grid{@apply tw-grid-cols-1;}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: FormsModule }, { kind: "component", type: CideEleButtonComponent, selector: "button[cideEleButton], a[cideEleButton]", inputs: ["label", "variant", "size", "type", "shape", "elevation", "disabled", "id", "loading", "fullWidth", "leftIcon", "rightIcon", "customClass", "tooltip", "ariaLabel", "testId", "routerLink", "routerExtras", "preventDoubleClick", "animated"], outputs: ["btnClick", "doubleClick"] }, { kind: "component", type: CideInputComponent, selector: "cide-ele-input", inputs: ["fill", "label", "labelHide", "disabled", "clearInput", "labelPlacement", "labelDir", "placeholder", "leadingIcon", "trailingIcon", "helperText", "helperTextCollapse", "hideHelperAndErrorText", "errorText", "maxlength", "minlength", "required", "autocapitalize", "autocomplete", "type", "width", "id", "ngModel", "option", "min", "max", "size"], outputs: ["ngModelChange"] }, { kind: "component", type: CideSelectComponent, selector: "cide-ele-select", inputs: ["label", "labelHide", "placeholder", "helperText", "errorText", "required", "disabled", "id", "ngModel", "size", "fill", "labelPlacement", "labelDir", "leadingIcon", "trailingIcon", "clearInput", "options", "multiple", "searchable", "showSearchInput", "loading"], outputs: ["ngModelChange", "change", "searchChange"] }, { kind: "component", type: CideIconComponent, selector: "cide-ele-icon", inputs: ["size", "type", "toolTip"] }] });
6999
7002
  }
7000
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: PageControlsComponent, decorators: [{
7003
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: PageControlsComponent, decorators: [{
7001
7004
  type: Component,
7002
7005
  args: [{ selector: 'cide-core-app-page-controls', standalone: true, imports: [
7003
7006
  CommonModule,