underpost 3.2.5 → 3.2.9

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 (144) hide show
  1. package/.github/workflows/release.cd.yml +1 -2
  2. package/CHANGELOG.md +351 -1
  3. package/CLI-HELP.md +40 -13
  4. package/Dockerfile +0 -4
  5. package/README.md +4 -4
  6. package/bin/build.js +14 -5
  7. package/bin/deploy.js +570 -1
  8. package/bin/file.js +6 -0
  9. package/conf.js +11 -2
  10. package/jsconfig.json +1 -1
  11. package/manifests/cronjobs/dd-cron/dd-cron-backup.yaml +2 -2
  12. package/manifests/cronjobs/dd-cron/dd-cron-dns.yaml +2 -2
  13. package/manifests/deployment/dd-default-development/deployment.yaml +2 -6
  14. package/manifests/deployment/dd-test-development/deployment.yaml +136 -66
  15. package/manifests/deployment/dd-test-development/proxy.yaml +41 -5
  16. package/package.json +24 -15
  17. package/scripts/k3s-node-setup.sh +2 -2
  18. package/scripts/nat-iptables.sh +103 -18
  19. package/src/api/core/core.controller.js +10 -10
  20. package/src/api/core/core.service.js +10 -10
  21. package/src/api/default/default.controller.js +10 -10
  22. package/src/api/default/default.service.js +10 -10
  23. package/src/api/document/document.controller.js +12 -12
  24. package/src/api/document/document.model.js +10 -16
  25. package/src/api/file/file.controller.js +8 -8
  26. package/src/api/file/file.model.js +10 -10
  27. package/src/api/file/file.service.js +36 -36
  28. package/src/api/test/test.controller.js +8 -8
  29. package/src/api/test/test.service.js +8 -8
  30. package/src/api/user/guest.service.js +99 -0
  31. package/src/api/user/user.controller.js +6 -6
  32. package/src/api/user/user.model.js +8 -13
  33. package/src/api/user/user.service.js +3 -20
  34. package/src/cli/cluster.js +61 -14
  35. package/src/cli/db.js +47 -2
  36. package/src/cli/deploy.js +67 -35
  37. package/src/cli/fs.js +79 -8
  38. package/src/cli/image.js +43 -1
  39. package/src/cli/index.js +26 -1
  40. package/src/cli/release.js +57 -1
  41. package/src/cli/repository.js +69 -31
  42. package/src/cli/run.js +415 -36
  43. package/src/cli/ssh.js +1 -1
  44. package/src/cli/static.js +43 -115
  45. package/src/client/Default.index.js +21 -33
  46. package/src/client/components/core/404.js +4 -4
  47. package/src/client/components/core/500.js +4 -4
  48. package/src/client/components/core/Account.js +73 -60
  49. package/src/client/components/core/AgGrid.js +23 -33
  50. package/src/client/components/core/Alert.js +12 -13
  51. package/src/client/components/core/AppStore.js +1 -1
  52. package/src/client/components/core/Auth.js +35 -37
  53. package/src/client/components/core/Badge.js +7 -13
  54. package/src/client/components/core/BtnIcon.js +15 -17
  55. package/src/client/components/core/CalendarCore.js +42 -63
  56. package/src/client/components/core/Chat.js +13 -15
  57. package/src/client/components/core/ClientEvents.js +87 -0
  58. package/src/client/components/core/ColorPaletteElement.js +309 -0
  59. package/src/client/components/core/Content.js +17 -14
  60. package/src/client/components/core/Css.js +15 -71
  61. package/src/client/components/core/CssCore.js +12 -16
  62. package/src/client/components/core/D3Chart.js +4 -4
  63. package/src/client/components/core/Docs.js +64 -91
  64. package/src/client/components/core/DropDown.js +69 -91
  65. package/src/client/components/core/EventBus.js +92 -0
  66. package/src/client/components/core/EventsUI.js +14 -17
  67. package/src/client/components/core/FileExplorer.js +96 -228
  68. package/src/client/components/core/FullScreen.js +47 -75
  69. package/src/client/components/core/Input.js +24 -69
  70. package/src/client/components/core/Keyboard.js +25 -18
  71. package/src/client/components/core/KeyboardAvoidance.js +145 -0
  72. package/src/client/components/core/LoadingAnimation.js +25 -31
  73. package/src/client/components/core/LogIn.js +41 -41
  74. package/src/client/components/core/LogOut.js +23 -14
  75. package/src/client/components/core/Modal.js +462 -178
  76. package/src/client/components/core/NotificationManager.js +14 -18
  77. package/src/client/components/core/Panel.js +54 -50
  78. package/src/client/components/core/PanelForm.js +25 -125
  79. package/src/client/components/core/Polyhedron.js +110 -214
  80. package/src/client/components/core/PublicProfile.js +39 -32
  81. package/src/client/components/core/Recover.js +48 -44
  82. package/src/client/components/core/Responsive.js +88 -32
  83. package/src/client/components/core/RichText.js +9 -18
  84. package/src/client/components/core/Router.js +24 -3
  85. package/src/client/components/core/SearchBox.js +37 -37
  86. package/src/client/components/core/SignUp.js +39 -30
  87. package/src/client/components/core/SocketIo.js +31 -2
  88. package/src/client/components/core/SocketIoHandler.js +6 -6
  89. package/src/client/components/core/ToggleSwitch.js +8 -20
  90. package/src/client/components/core/ToolTip.js +5 -17
  91. package/src/client/components/core/Translate.js +56 -59
  92. package/src/client/components/core/Validator.js +26 -16
  93. package/src/client/components/core/Wallet.js +15 -26
  94. package/src/client/components/core/Worker.js +163 -27
  95. package/src/client/components/core/windowGetDimensions.js +7 -7
  96. package/src/client/components/default/{MenuDefault.js → AppShellDefault.js} +87 -87
  97. package/src/client/components/default/CssDefault.js +12 -12
  98. package/src/client/components/default/LogInDefault.js +6 -4
  99. package/src/client/components/default/LogOutDefault.js +6 -4
  100. package/src/client/components/default/RouterDefault.js +47 -0
  101. package/src/client/components/default/SettingsDefault.js +4 -4
  102. package/src/client/components/default/SignUpDefault.js +6 -4
  103. package/src/client/components/default/TranslateDefault.js +3 -3
  104. package/src/client/services/core/core.service.js +17 -49
  105. package/src/client/services/default/default.management.js +159 -267
  106. package/src/client/services/default/default.service.js +10 -16
  107. package/src/client/services/document/document.service.js +14 -19
  108. package/src/client/services/file/file.service.js +8 -13
  109. package/src/client/services/test/test.service.js +8 -13
  110. package/src/client/services/user/guest.service.js +86 -0
  111. package/src/client/services/user/user.management.js +5 -5
  112. package/src/client/services/user/user.service.js +14 -20
  113. package/src/client/ssr/body/404.js +3 -3
  114. package/src/client/ssr/body/500.js +3 -3
  115. package/src/client/ssr/body/CacheControl.js +5 -2
  116. package/src/client/ssr/body/DefaultSplashScreen.js +19 -12
  117. package/src/client/ssr/mailer/DefaultRecoverEmail.js +19 -20
  118. package/src/client/ssr/mailer/DefaultVerifyEmail.js +15 -16
  119. package/src/client/ssr/offline/Maintenance.js +12 -11
  120. package/src/client/ssr/offline/NoNetworkConnection.js +3 -3
  121. package/src/client/ssr/pages/Test.js +2 -2
  122. package/src/client/sw/core.sw.js +212 -0
  123. package/src/index.js +1 -1
  124. package/src/runtime/express/Dockerfile +4 -4
  125. package/src/runtime/lampp/Dockerfile +8 -7
  126. package/src/runtime/wp/Dockerfile +11 -17
  127. package/src/server/client-build-docs.js +45 -46
  128. package/src/server/client-build.js +334 -60
  129. package/src/server/client-formatted.js +47 -16
  130. package/src/server/conf.js +5 -4
  131. package/src/server/data-query.js +32 -20
  132. package/src/server/dns.js +22 -0
  133. package/src/server/ipfs-client.js +232 -91
  134. package/src/server/process.js +13 -27
  135. package/src/server/start.js +17 -3
  136. package/src/server/valkey.js +141 -235
  137. package/tsconfig.docs.json +15 -0
  138. package/typedoc.json +29 -0
  139. package/jsdoc.json +0 -52
  140. package/src/client/components/core/ColorPalette.js +0 -5267
  141. package/src/client/components/core/JoyStick.js +0 -80
  142. package/src/client/components/default/RoutesDefault.js +0 -49
  143. package/src/client/sw/default.sw.js +0 -127
  144. package/src/client/sw/template.sw.js +0 -84
@@ -10,44 +10,39 @@ import { Translate } from '../../components/core/Translate.js';
10
10
  import { getQueryParams, listenQueryParamsChange, RouterEvents, setQueryParams } from '../../components/core/Router.js';
11
11
  import { s } from '../../components/core/VanillaJs.js';
12
12
  import { DefaultService } from './default.service.js';
13
-
14
13
  const logger = loggerFactory(import.meta);
15
-
16
- const DefaultOptions = {
17
- idModal: 'modal-default-management',
18
- serviceId: 'default-management',
19
- entity: 'default',
20
- columnDefs: [
14
+ class DefaultOptions {
15
+ static idModal = 'modal-default-management';
16
+ static serviceId = 'default-management';
17
+ static entity = 'default';
18
+ static columnDefs = [
21
19
  { field: '0', headerName: '0', cellClassRules: { 'row-new-highlight': (params) => true } },
22
20
  { field: '1', headerName: '1' },
23
21
  { field: '2', headerName: '2' },
24
22
  { field: 'createdAt', headerName: 'createdAt', cellDataType: 'date', editable: false },
25
23
  { field: 'updatedAt', headerName: 'updatedAt', cellDataType: 'date', editable: false },
26
- ],
27
- defaultColKeyFocus: '0',
28
- ServiceProvider: DefaultService,
29
- permissions: {
24
+ ];
25
+ static defaultColKeyFocus = '0';
26
+ static ServiceProvider = DefaultService;
27
+ static permissions = {
30
28
  add: true,
31
29
  remove: true,
32
30
  reload: true,
33
- },
34
- paginationOptions: {
31
+ };
32
+ static paginationOptions = {
35
33
  limitOptions: [10, 20, 50, 100],
36
- },
37
- };
38
-
34
+ };
35
+ }
39
36
  const columnDefFormatter = (obj, columnDefs, customFormat) => {
40
37
  for (const colDef of columnDefs)
41
38
  switch (colDef.cellDataType) {
42
39
  case 'date': {
43
40
  const value = obj[colDef.field];
44
-
45
41
  // Do NOT default missing/blank dates to "now" — render as empty instead.
46
42
  if (value === null || value === undefined || value === '') {
47
43
  obj[colDef.field] = null;
48
44
  break;
49
45
  }
50
-
51
46
  const date = new Date(value);
52
47
  obj[colDef.field] = isNaN(date.getTime()) ? null : date;
53
48
  break;
@@ -59,69 +54,64 @@ const columnDefFormatter = (obj, columnDefs, customFormat) => {
59
54
  }
60
55
  return customFormat ? customFormat(obj) : obj;
61
56
  };
62
-
63
- const DefaultManagement = {
64
- Tokens: {},
57
+ class DefaultManagement {
58
+ static Tokens = {};
65
59
  // Helper functions for managing serviceOptions ID filter
66
- setIdFilter: function (id, itemId) {
67
- if (!this.Tokens[id]) {
68
- this.Tokens[id] = {};
60
+ static setIdFilter(id, itemId) {
61
+ if (!DefaultManagement.Tokens[id]) {
62
+ DefaultManagement.Tokens[id] = {};
69
63
  }
70
- if (!this.Tokens[id].serviceOptions) {
71
- this.Tokens[id].serviceOptions = {};
64
+ if (!DefaultManagement.Tokens[id].serviceOptions) {
65
+ DefaultManagement.Tokens[id].serviceOptions = {};
72
66
  }
73
- if (!this.Tokens[id].serviceOptions.get) {
74
- this.Tokens[id].serviceOptions.get = {};
67
+ if (!DefaultManagement.Tokens[id].serviceOptions.get) {
68
+ DefaultManagement.Tokens[id].serviceOptions.get = {};
75
69
  }
76
- this.Tokens[id].serviceOptions.get.id = itemId;
77
- },
78
- clearIdFilter: function (id) {
79
- if (this.Tokens[id]?.serviceOptions?.get?.id) {
80
- delete this.Tokens[id].serviceOptions.get.id;
70
+ DefaultManagement.Tokens[id].serviceOptions.get.id = itemId;
71
+ }
72
+ static clearIdFilter(id) {
73
+ if (DefaultManagement.Tokens[id]?.serviceOptions?.get?.id) {
74
+ delete DefaultManagement.Tokens[id].serviceOptions.get.id;
81
75
  }
82
- },
83
- getIdFilter: function (id) {
84
- return this.Tokens[id]?.serviceOptions?.get?.id ?? undefined;
85
- },
86
- waitGridReady: function (id) {
76
+ }
77
+ static getIdFilter(id) {
78
+ return DefaultManagement.Tokens[id]?.serviceOptions?.get?.id ?? undefined;
79
+ }
80
+ static waitGridReady(id) {
87
81
  return new Promise((resolve) => {
88
- if (this.Tokens[id]?.gridApi) {
89
- return resolve(this.Tokens[id].gridApi);
82
+ if (DefaultManagement.Tokens[id]?.gridApi) {
83
+ return resolve(DefaultManagement.Tokens[id].gridApi);
90
84
  }
91
- if (!this.Tokens[id].readyGridEvent) this.Tokens[id].readyGridEvent = {};
92
- this.Tokens[id].readyGridEvent['waitGridReady'] = (params) => {
93
- delete this.Tokens[id].readyGridEvent['waitGridReady'];
85
+ if (!DefaultManagement.Tokens[id].readyGridEvent) DefaultManagement.Tokens[id].readyGridEvent = {};
86
+ DefaultManagement.Tokens[id].readyGridEvent['waitGridReady'] = (params) => {
87
+ delete DefaultManagement.Tokens[id].readyGridEvent['waitGridReady'];
94
88
  resolve(params.api);
95
89
  };
96
90
  });
97
- },
98
- runIsolated: async function (id, callback) {
99
- if (!this.Tokens[id]) return await callback();
100
- this.Tokens[id].isProcessingQueryChange = true;
91
+ }
92
+ static async runIsolated(id, callback) {
93
+ if (!DefaultManagement.Tokens[id]) return await callback();
94
+ DefaultManagement.Tokens[id].isProcessingQueryChange = true;
101
95
  try {
102
96
  return await callback();
103
97
  } finally {
104
- this.Tokens[id].isProcessingQueryChange = false;
98
+ DefaultManagement.Tokens[id].isProcessingQueryChange = false;
105
99
  }
106
- },
107
- loadTable: async function (id, options = {}) {
100
+ }
101
+ static async loadTable(id, options = {}) {
108
102
  options = { reload: true, force: true, createHistory: false, skipUrlUpdate: false, ...options };
109
103
  try {
110
- if (!this.Tokens[id]) {
104
+ if (!DefaultManagement.Tokens[id]) {
111
105
  logger.warn(`DefaultManagement loadTable - Token not found for id: ${id}`);
112
106
  return;
113
107
  }
114
- const { serviceId, columnDefs, customFormat, gridId } = this.Tokens[id];
115
-
116
- let _page = this.Tokens[id].page;
117
- let _limit = this.Tokens[id].limit;
118
- let _id = this.getIdFilter(id);
119
-
120
- let filterModel = this.Tokens[id].filterModel || {};
121
- let sortModel = this.Tokens[id].sortModel || [];
122
-
123
- const gridApi = this.Tokens[id].gridApi || AgGrid.grids[gridId];
124
-
108
+ const { serviceId, columnDefs, customFormat, gridId } = DefaultManagement.Tokens[id];
109
+ let _page = DefaultManagement.Tokens[id].page;
110
+ let _limit = DefaultManagement.Tokens[id].limit;
111
+ let _id = DefaultManagement.getIdFilter(id);
112
+ let filterModel = DefaultManagement.Tokens[id].filterModel || {};
113
+ let sortModel = DefaultManagement.Tokens[id].sortModel || [];
114
+ const gridApi = DefaultManagement.Tokens[id].gridApi || AgGrid.grids[gridId];
125
115
  if (gridApi) {
126
116
  filterModel = gridApi.getFilterModel() || {};
127
117
  const columnState = gridApi.getColumnState();
@@ -132,11 +122,9 @@ const DefaultManagement = {
132
122
  .sort((a, b) => (a.sortIndex || 0) - (b.sortIndex || 0));
133
123
  }
134
124
  }
135
-
136
125
  // Clean up filterModel and sortModel for URL params
137
126
  const filterModelStr = Object.keys(filterModel).length > 0 ? JSON.stringify(filterModel) : null;
138
127
  const sortModelStr = sortModel.length > 0 ? JSON.stringify(sortModel) : null;
139
-
140
128
  // Update URL parameters to reflect current grid state
141
129
  // Use pushState (createHistory) for filter/sort changes to enable browser back/forward
142
130
  // Skip URL update when handling browser navigation to avoid interfering with history
@@ -150,9 +138,8 @@ const DefaultManagement = {
150
138
  };
151
139
  setQueryParams(urlParams, { replace: !options.createHistory });
152
140
  }
153
-
154
- if (!options.force && this.Tokens[id].lastOptions) {
155
- const last = this.Tokens[id].lastOptions;
141
+ if (!options.force && DefaultManagement.Tokens[id].lastOptions) {
142
+ const last = DefaultManagement.Tokens[id].lastOptions;
156
143
  if (
157
144
  _page === last.page &&
158
145
  _limit === last.limit &&
@@ -164,31 +151,26 @@ const DefaultManagement = {
164
151
  return;
165
152
  }
166
153
  }
167
- this.Tokens[id].lastOptions = {
154
+ DefaultManagement.Tokens[id].lastOptions = {
168
155
  page: _page,
169
156
  limit: _limit,
170
157
  id: _id,
171
158
  filterModel,
172
159
  sortModel,
173
160
  };
174
-
175
161
  // Update tokens with current state
176
- this.Tokens[id].filterModel = filterModel;
177
- this.Tokens[id].sortModel = sortModel;
178
-
162
+ DefaultManagement.Tokens[id].filterModel = filterModel;
163
+ DefaultManagement.Tokens[id].sortModel = sortModel;
179
164
  const queryOptions = {
180
165
  page: _page,
181
166
  limit: _limit,
182
167
  };
183
-
184
168
  if (_id) {
185
169
  queryOptions.id = _id;
186
170
  }
187
-
188
171
  if (filterModel && Object.keys(filterModel).length > 0) {
189
172
  queryOptions.filterModel = filterModel;
190
173
  }
191
-
192
174
  if (sortModel && sortModel.length > 0) {
193
175
  queryOptions.sortModel = sortModel;
194
176
  // Legacy simple sort support
@@ -197,7 +179,6 @@ const DefaultManagement = {
197
179
  queryOptions.asc = sortModel[0].sort === 'asc' ? '1' : '0';
198
180
  }
199
181
  }
200
-
201
182
  logger.info(`Loading table ${serviceId}`, {
202
183
  id,
203
184
  idFilter: _id,
@@ -205,16 +186,13 @@ const DefaultManagement = {
205
186
  limit: _limit,
206
187
  hasFilters: Object.keys(filterModel).length > 0,
207
188
  });
208
-
209
- if (!this.Tokens[id] || !this.Tokens[id].ServiceProvider) {
189
+ if (!DefaultManagement.Tokens[id] || !DefaultManagement.Tokens[id].ServiceProvider) {
210
190
  logger.warn(`DefaultManagement loadTable ${serviceId} - ServiceProvider not found for token ${id}`);
211
191
  return;
212
192
  }
213
-
214
- const result = await this.Tokens[id].ServiceProvider.get(queryOptions);
193
+ const result = await DefaultManagement.Tokens[id].ServiceProvider.get(queryOptions);
215
194
  if (result.status === 'success') {
216
195
  let data, total, page, totalPages;
217
-
218
196
  // Handle both single object (when querying by ID) and paginated array responses
219
197
  if (queryOptions.id && result.data && !Array.isArray(result.data.data)) {
220
198
  // Single object response when filtering by ID
@@ -226,24 +204,23 @@ const DefaultManagement = {
226
204
  // Paginated array response
227
205
  ({ data = [], total = 0, page = 1, totalPages = 1 } = result.data || {});
228
206
  }
229
-
230
- this.Tokens[id].total = total;
231
- this.Tokens[id].page = page;
232
- this.Tokens[id].totalPages = totalPages;
207
+ DefaultManagement.Tokens[id].total = total;
208
+ DefaultManagement.Tokens[id].page = page;
209
+ DefaultManagement.Tokens[id].totalPages = totalPages;
233
210
  const rowDataScope = data.map((row) => columnDefFormatter(row, columnDefs, customFormat));
234
211
  if (options.reload) {
235
- const grid = AgGrid.grids[this.Tokens[id].gridId];
212
+ const grid = AgGrid.grids[DefaultManagement.Tokens[id].gridId];
236
213
  if (grid && grid.setGridOption) {
237
214
  grid.setGridOption('rowData', rowDataScope);
238
215
  } else {
239
216
  logger.warn(`Grid ${gridId} not found or not ready for setGridOption`);
240
217
  }
241
218
  }
242
- const paginationComp = s(`#ag-pagination-${this.Tokens[id].gridId}`);
219
+ const paginationComp = s(`#ag-pagination-${DefaultManagement.Tokens[id].gridId}`);
243
220
  if (paginationComp) {
244
- paginationComp.setAttribute('current-page', this.Tokens[id].page);
245
- paginationComp.setAttribute('total-pages', this.Tokens[id].totalPages);
246
- paginationComp.setAttribute('total-items', this.Tokens[id].total);
221
+ paginationComp.setAttribute('current-page', DefaultManagement.Tokens[id].page);
222
+ paginationComp.setAttribute('total-pages', DefaultManagement.Tokens[id].totalPages);
223
+ paginationComp.setAttribute('total-items', DefaultManagement.Tokens[id].total);
247
224
  } else {
248
225
  logger.warn(`Pagination component not found for grid ${gridId}`);
249
226
  }
@@ -253,7 +230,7 @@ const DefaultManagement = {
253
230
  await DefaultManagement.Tokens[id].readyRowDataEvent[event](rowDataScope);
254
231
  }, 1);
255
232
  // Update clear filter button visibility
256
- this.updateClearFilterButtonVisibility(id);
233
+ DefaultManagement.updateClearFilterButtonVisibility(id);
257
234
  } else {
258
235
  logger.error(`Failed to load table ${serviceId}:`, result);
259
236
  }
@@ -261,30 +238,27 @@ const DefaultManagement = {
261
238
  logger.error(`Error in loadTable for ${id}:`, error);
262
239
  throw error;
263
240
  }
264
- },
265
- hasActiveFilters: function (id) {
266
- const gridId = this.Tokens[id]?.gridId;
241
+ }
242
+ static hasActiveFilters(id) {
243
+ const gridId = DefaultManagement.Tokens[id]?.gridId;
267
244
  if (!gridId) return false;
268
-
269
245
  const gridApi = AgGrid.grids[gridId];
270
246
  const filterModel = gridApi ? gridApi.getFilterModel() : {};
271
- const idFilter = this.getIdFilter(id);
272
- const sortModel = this.Tokens[id]?.sortModel || [];
273
-
247
+ const idFilter = DefaultManagement.getIdFilter(id);
248
+ const sortModel = DefaultManagement.Tokens[id]?.sortModel || [];
274
249
  return Object.keys(filterModel).length > 0 || !!idFilter || sortModel.length > 0;
275
- },
276
- updateClearFilterButtonVisibility: function (id) {
250
+ }
251
+ static updateClearFilterButtonVisibility(id) {
277
252
  const clearFilterBtn = s(`.management-table-btn-clear-filter-${id}`);
278
253
  if (!clearFilterBtn) return;
279
-
280
- if (this.hasActiveFilters(id)) {
254
+ if (DefaultManagement.hasActiveFilters(id)) {
281
255
  clearFilterBtn.classList.remove('hide');
282
256
  } else {
283
257
  clearFilterBtn.classList.add('hide');
284
258
  }
285
- },
286
- refreshTable: async function (id) {
287
- const gridApi = AgGrid.grids[this.Tokens[id].gridId];
259
+ }
260
+ static async refreshTable(id) {
261
+ const gridApi = AgGrid.grids[DefaultManagement.Tokens[id].gridId];
288
262
  if (gridApi) {
289
263
  // Use refreshCells with change detection for optimal performance
290
264
  // This is preferred over redrawRows() as it only updates changed cells
@@ -293,13 +267,13 @@ const DefaultManagement = {
293
267
  suppressFlash: false, // Show flash animation for changed cells (requires enableCellChangeFlash)
294
268
  });
295
269
  }
296
- },
297
- RenderTable: async function (options = DefaultOptions) {
270
+ }
271
+ static async instance(options = DefaultOptions) {
298
272
  if (!options) options = DefaultOptions;
299
273
  const { serviceId, columnDefs, entity, defaultColKeyFocus, ServiceProvider, permissions, paginationOptions } =
300
274
  options;
301
- logger.info('DefaultManagement RenderTable', options);
302
- const id = options?.idModal ? options.idModal : getId(this.Tokens, `${serviceId}-`);
275
+ logger.info('DefaultManagement instance', options);
276
+ const id = options?.idModal ? options.idModal : getId(DefaultManagement.Tokens, `${serviceId}-`);
303
277
  const gridId = `${serviceId}-grid-${id}`;
304
278
  const queryParamsListenerId = `default-management-${id}`;
305
279
  const queryParams = getQueryParams();
@@ -307,7 +281,6 @@ const DefaultManagement = {
307
281
  const defaultLimit = paginationOptions?.limitOptions?.[0] || 10;
308
282
  const limit = parseInt(queryParams.limit) || defaultLimit;
309
283
  const urlId = queryParams.id || undefined;
310
-
311
284
  let filterModel = {};
312
285
  let sortModel = [];
313
286
  try {
@@ -316,17 +289,14 @@ const DefaultManagement = {
316
289
  } catch (e) {
317
290
  logger.warn('Error parsing filter/sort model from URL', e);
318
291
  }
319
-
320
292
  // Enhance column definitions for Date filtering and ensure colId
321
293
  const enhancedColumnDefs = columnDefs.map((col) => {
322
294
  const enhancedCol = {
323
295
  ...col,
324
296
  colId: col.field, // Ensure colId matches field
325
297
  };
326
-
327
298
  if (enhancedCol.cellDataType === 'date' || enhancedCol.filter === 'agDateColumnFilter') {
328
299
  enhancedCol.filter = 'agDateColumnFilter';
329
-
330
300
  // Value getter to ensure date is properly parsed
331
301
  if (!enhancedCol.valueGetter) {
332
302
  enhancedCol.valueGetter = (params) => {
@@ -336,7 +306,6 @@ const DefaultManagement = {
336
306
  return isNaN(date.getTime()) ? null : date;
337
307
  };
338
308
  }
339
-
340
309
  // Value formatter for display
341
310
  if (!enhancedCol.valueFormatter) {
342
311
  enhancedCol.valueFormatter = (params) => {
@@ -350,7 +319,6 @@ const DefaultManagement = {
350
319
  });
351
320
  };
352
321
  }
353
-
354
322
  enhancedCol.filterParams = {
355
323
  comparator: (filterLocalDateAtMidnight, cellValue) => {
356
324
  if (cellValue == null) return -1;
@@ -374,27 +342,21 @@ const DefaultManagement = {
374
342
  }
375
343
  return enhancedCol;
376
344
  });
377
-
378
345
  class RemoveActionGridRenderer {
379
346
  eGui;
380
347
  tokens;
381
-
382
348
  async init(params) {
383
349
  this.eGui = document.createElement('div');
384
350
  this.tokens = {};
385
351
  const { rowIndex } = params;
386
352
  const { createdAt, updatedAt } = params.data;
387
-
388
353
  const cellRenderId = getId(this.tokens, `${serviceId}-`);
389
354
  this.tokens[cellRenderId] = {};
390
-
391
- this.eGui.innerHTML = html` ${await BtnIcon.Render({
355
+ this.eGui.innerHTML = html` ${await BtnIcon.instance({
392
356
  label: html`<div class="abs center">
393
357
  <i class="fas fa-times"></i>
394
358
  </div> `,
395
- class: `in fll section-mp management-table-btn-mini management-table-btn-remove-${id}-${cellRenderId} ${
396
- !params.data._id ? 'hide' : ''
397
- }`,
359
+ class: `in fll section-mp management-table-btn-mini management-table-btn-remove-${id}-${cellRenderId} ${!params.data._id ? 'hide' : ''}`,
398
360
  })}`;
399
361
  setTimeout(() => {
400
362
  EventsUI.onClick(
@@ -404,7 +366,7 @@ const DefaultManagement = {
404
366
  html: async () => {
405
367
  return html`
406
368
  <div class="in section-mp" style="text-align: center">
407
- ${Translate.Render('confirm-delete-item')}
369
+ ${Translate.instance('confirm-delete-item')}
408
370
  ${Object.keys(params.data).length > 0
409
371
  ? html`<br />
410
372
  "${options.defaultColKeyFocus
@@ -420,9 +382,8 @@ const DefaultManagement = {
420
382
  let result;
421
383
  if (params.data._id) result = await ServiceProvider.delete({ id: params.data._id });
422
384
  else result = { status: 'success' };
423
-
424
385
  NotificationManager.Push({
425
- html: result.status === 'error' ? result.message : Translate.Render('item-success-delete'),
386
+ html: result.status === 'error' ? result.message : Translate.instance('item-success-delete'),
426
387
  status: result.status,
427
388
  });
428
389
  if (result.status === 'success') {
@@ -434,7 +395,6 @@ const DefaultManagement = {
434
395
  if (token.page > newTotalPages && newTotalPages > 0) {
435
396
  token.page = newTotalPages;
436
397
  }
437
-
438
398
  // reload the current page
439
399
  await DefaultManagement.loadTable(id, { reload: false });
440
400
  }
@@ -443,16 +403,13 @@ const DefaultManagement = {
443
403
  );
444
404
  });
445
405
  }
446
-
447
406
  getGui() {
448
407
  return this.eGui;
449
408
  }
450
-
451
409
  refresh(params) {
452
410
  return true;
453
411
  }
454
412
  }
455
-
456
413
  const finalColumnDefs = (enhancedColumnDefs || []).concat(
457
414
  permissions.remove
458
415
  ? [
@@ -466,9 +423,8 @@ const DefaultManagement = {
466
423
  ]
467
424
  : [],
468
425
  );
469
-
470
- this.Tokens[id] = {
471
- ...this.Tokens[id],
426
+ DefaultManagement.Tokens[id] = {
427
+ ...DefaultManagement.Tokens[id],
472
428
  ...options,
473
429
  columnDefs: finalColumnDefs, // Use enhanced definitions including actions
474
430
  gridId,
@@ -481,12 +437,10 @@ const DefaultManagement = {
481
437
  isInitializing: true, // Flag to prevent double loading during grid ready
482
438
  isProcessingQueryChange: false, // Flag to prevent listener recursion
483
439
  };
484
-
485
440
  // Initialize ID filter from query params if present
486
441
  if (urlId) {
487
- this.setIdFilter(id, urlId);
442
+ DefaultManagement.setIdFilter(id, urlId);
488
443
  }
489
-
490
444
  setQueryParams({
491
445
  page,
492
446
  limit,
@@ -494,10 +448,8 @@ const DefaultManagement = {
494
448
  filterModel: Object.keys(filterModel).length > 0 ? JSON.stringify(filterModel) : null,
495
449
  sortModel: sortModel.length > 0 ? JSON.stringify(sortModel) : null,
496
450
  });
497
-
498
451
  setTimeout(async () => {
499
452
  // https://www.ag-grid.com/javascript-data-grid/data-update-transactions/
500
-
501
453
  // Initial loadTable is now called in onGridReady after grid is fully initialized
502
454
  // {
503
455
  // const result = await ServiceProvider.get();
@@ -516,7 +468,6 @@ const DefaultManagement = {
516
468
  };
517
469
  EventsUI.onClick(`.management-table-btn-add-${id}`, async () => {
518
470
  if (options.customEvent && options.customEvent.add) return await options.customEvent.add();
519
-
520
471
  const rowObj = {};
521
472
  for (const def of columnDefs) {
522
473
  rowObj[def.field] = '';
@@ -527,7 +478,7 @@ const DefaultManagement = {
527
478
  data: rowObj,
528
479
  };
529
480
  // NotificationManager.Push({
530
- // html: result.status === 'error' ? result.message : `${Translate.Render('success-create-item')}`,
481
+ // html: result.status === 'error' ? result.message : `${Translate.instance('success-create-item')}`,
531
482
  // status: result.status,
532
483
  // });
533
484
  if (result.status === 'success') {
@@ -551,26 +502,20 @@ const DefaultManagement = {
551
502
  // defaultState: { sort: null },
552
503
  // });
553
504
  }
554
-
555
505
  // https://www.ag-grid.com/javascript-data-grid/cell-editing-start-stop/
556
-
557
506
  const pinned = undefined;
558
507
  const key = undefined;
559
-
560
508
  // setFocusedCell = (
561
509
  // rowIndex: number,
562
510
  // colKey: string | Column,
563
511
  // rowPinned?: RowPinnedType
564
512
  // ) => void;
565
-
566
513
  // type RowPinnedType =
567
514
  // 'top'
568
515
  // | 'bottom'
569
516
  // | null
570
517
  // | undefined
571
-
572
518
  AgGrid.grids[gridId].setFocusedCell(0, '0', pinned);
573
-
574
519
  // interface StartEditingCellParams {
575
520
  // // The row index of the row to start editing
576
521
  // rowIndex: number;
@@ -581,7 +526,6 @@ const DefaultManagement = {
581
526
  // // The key to pass to the cell editor
582
527
  // key?: string;
583
528
  // }
584
-
585
529
  setTimeout(() => {
586
530
  s(`.management-table-btn-save-${id}`).classList.remove('hide');
587
531
  // s(`.management-table-btn-stop-${id}`).classList.remove('hide');
@@ -596,7 +540,6 @@ const DefaultManagement = {
596
540
  });
597
541
  });
598
542
  });
599
-
600
543
  EventsUI.onClick(`.management-table-btn-stop-${id}`, async () => {
601
544
  s(`.management-table-btn-save-${id}`).classList.add('hide');
602
545
  // s(`.management-table-btn-stop-${id}`).classList.add('hide');
@@ -611,7 +554,7 @@ const DefaultManagement = {
611
554
  html: async () => {
612
555
  return html`
613
556
  <div class="in section-mp" style="text-align: center;">
614
- <strong>${Translate.Render('confirm-delete-all-data')}</strong>
557
+ <strong>${Translate.instance('confirm-delete-all-data')}</strong>
615
558
  </div>
616
559
  `;
617
560
  },
@@ -622,60 +565,52 @@ const DefaultManagement = {
622
565
  if (confirmResult.status === 'cancelled') return;
623
566
  const result = await ServiceProvider.delete();
624
567
  NotificationManager.Push({
625
- html: result.status === 'error' ? result.message : Translate.Render('success-delete-all-items'),
568
+ html: result.status === 'error' ? result.message : Translate.instance('success-delete-all-items'),
626
569
  status: result.status,
627
570
  });
628
571
  if (result.status === 'success') {
629
572
  DefaultManagement.loadTable(id);
630
573
  }
631
574
  });
632
-
633
575
  // Listen to query parameter changes for browser back/forward navigation
634
576
  listenQueryParamsChange({
635
577
  id: queryParamsListenerId,
636
578
  event: (queryParams) => {
637
579
  // Prevent recursion - if we're already processing a query change, skip
638
- if (this.Tokens[id].isProcessingQueryChange) {
580
+ if (DefaultManagement.Tokens[id].isProcessingQueryChange) {
639
581
  return;
640
582
  }
641
-
642
583
  const newPage = parseInt(queryParams.page, 10) || 1;
643
- const newLimit = parseInt(queryParams.limit, 10) || this.Tokens[id].limit || 10;
584
+ const newLimit = parseInt(queryParams.limit, 10) || DefaultManagement.Tokens[id].limit || 10;
644
585
  const newFilterModel = queryParams.filterModel;
645
586
  const newSortModel = queryParams.sortModel;
646
587
  const newId = queryParams.id || undefined;
647
-
648
588
  let shouldReload = false;
649
-
650
589
  // Check if id parameter changed
651
- const currentId = this.getIdFilter(id);
590
+ const currentId = DefaultManagement.getIdFilter(id);
652
591
  if (newId !== currentId) {
653
592
  if (newId) {
654
- this.setIdFilter(id, newId);
593
+ DefaultManagement.setIdFilter(id, newId);
655
594
  } else {
656
- this.clearIdFilter(id);
595
+ DefaultManagement.clearIdFilter(id);
657
596
  }
658
597
  shouldReload = true;
659
598
  }
660
-
661
599
  // Check if page or limit changed
662
- if (newPage !== this.Tokens[id].page || newLimit !== this.Tokens[id].limit) {
663
- this.Tokens[id].page = newPage;
664
- this.Tokens[id].limit = newLimit;
600
+ if (newPage !== DefaultManagement.Tokens[id].page || newLimit !== DefaultManagement.Tokens[id].limit) {
601
+ DefaultManagement.Tokens[id].page = newPage;
602
+ DefaultManagement.Tokens[id].limit = newLimit;
665
603
  shouldReload = true;
666
604
  }
667
-
668
605
  // Check if filter or sort changed by comparing with actual grid state
669
606
  const gridApi = AgGrid.grids[gridId];
670
607
  let filterChanged = false;
671
608
  let sortChanged = false;
672
-
673
609
  if (gridApi) {
674
610
  // Get current grid filter state
675
611
  const currentGridFilterModel = gridApi.getFilterModel() || {};
676
612
  const currentGridFilterStr = JSON.stringify(currentGridFilterModel);
677
613
  const newFilterStr = newFilterModel || '{}';
678
-
679
614
  // Get current grid sort state
680
615
  const currentColumnState = gridApi.getColumnState() || [];
681
616
  const currentGridSortModel = currentColumnState
@@ -684,36 +619,31 @@ const DefaultManagement = {
684
619
  .sort((a, b) => (a.sortIndex || 0) - (b.sortIndex || 0));
685
620
  const currentGridSortStr = JSON.stringify(currentGridSortModel);
686
621
  const newSortStr = newSortModel || '[]';
687
-
688
622
  filterChanged = currentGridFilterStr !== newFilterStr;
689
623
  sortChanged = currentGridSortStr !== newSortStr;
690
624
  }
691
-
692
625
  if (filterChanged || sortChanged) {
693
626
  // Parse and apply the new filter/sort models
694
627
  try {
695
- this.Tokens[id].filterModel = newFilterModel ? JSON.parse(newFilterModel) : {};
628
+ DefaultManagement.Tokens[id].filterModel = newFilterModel ? JSON.parse(newFilterModel) : {};
696
629
  } catch (e) {
697
- this.Tokens[id].filterModel = {};
630
+ DefaultManagement.Tokens[id].filterModel = {};
698
631
  }
699
632
  try {
700
- this.Tokens[id].sortModel = newSortModel ? JSON.parse(newSortModel) : [];
633
+ DefaultManagement.Tokens[id].sortModel = newSortModel ? JSON.parse(newSortModel) : [];
701
634
  } catch (e) {
702
- this.Tokens[id].sortModel = [];
635
+ DefaultManagement.Tokens[id].sortModel = [];
703
636
  }
704
-
705
637
  // Apply filters and sorts to the grid
706
638
  if (gridApi) {
707
639
  // Temporarily disable filter/sort change handlers to prevent recursion
708
- this.Tokens[id].isProcessingQueryChange = true;
709
-
640
+ DefaultManagement.Tokens[id].isProcessingQueryChange = true;
710
641
  if (filterChanged) {
711
- gridApi.setFilterModel(this.Tokens[id].filterModel);
642
+ gridApi.setFilterModel(DefaultManagement.Tokens[id].filterModel);
712
643
  }
713
-
714
644
  if (sortChanged) {
715
645
  // Apply sort model
716
- const columnState = this.Tokens[id].sortModel.map((sortItem) => ({
646
+ const columnState = DefaultManagement.Tokens[id].sortModel.map((sortItem) => ({
717
647
  colId: sortItem.colId,
718
648
  sort: sortItem.sort,
719
649
  sortIndex: sortItem.sortIndex,
@@ -729,54 +659,45 @@ const DefaultManagement = {
729
659
  });
730
660
  }
731
661
  }
732
-
733
662
  // Re-enable handlers after a short delay
734
663
  setTimeout(() => {
735
- this.Tokens[id].isProcessingQueryChange = false;
664
+ DefaultManagement.Tokens[id].isProcessingQueryChange = false;
736
665
  }, 100);
737
666
  }
738
667
  shouldReload = true;
739
668
  }
740
-
741
669
  if (shouldReload) {
742
670
  // Skip URL update since browser already changed it (back/forward navigation)
743
671
  DefaultManagement.loadTable(id, { reload: true, force: true, createHistory: false, skipUrlUpdate: true });
744
672
  }
745
673
  },
746
674
  });
747
-
748
675
  EventsUI.onClick(`.management-table-btn-clear-filter-${id}`, async () => {
749
676
  try {
750
677
  const gridApi = AgGrid.grids[gridId];
751
-
752
- // Clear all filters
753
- DefaultManagement.clearIdFilter(id);
754
- if (gridApi) {
755
- gridApi.setFilterModel({});
756
- gridApi.applyColumnState({ defaultState: { sort: null } });
757
- }
758
-
759
- // Clear token state
760
- if (DefaultManagement.Tokens[id]) {
761
- DefaultManagement.Tokens[id].filterModel = {};
762
- DefaultManagement.Tokens[id].sortModel = [];
763
- }
764
-
765
- // Update URL - keep only page and limit
766
- const queryParams = getQueryParams();
767
- setQueryParams({
768
- page: queryParams.page || 1,
769
- limit: queryParams.limit || DefaultManagement.Tokens[id]?.limit || 10,
770
- filterModel: null,
771
- sortModel: null,
772
- id: null,
678
+ await DefaultManagement.runIsolated(id, async () => {
679
+ // Clear all filters without letting grid/query listeners trigger their own reloads.
680
+ DefaultManagement.clearIdFilter(id);
681
+ if (gridApi) {
682
+ gridApi.setFilterModel({});
683
+ gridApi.applyColumnState({ defaultState: { sort: null } });
684
+ }
685
+ if (DefaultManagement.Tokens[id]) {
686
+ DefaultManagement.Tokens[id].filterModel = {};
687
+ DefaultManagement.Tokens[id].sortModel = [];
688
+ }
689
+ const queryParams = getQueryParams();
690
+ setQueryParams({
691
+ page: queryParams.page || 1,
692
+ limit: queryParams.limit || DefaultManagement.Tokens[id]?.limit || 10,
693
+ filterModel: null,
694
+ sortModel: null,
695
+ id: null,
696
+ });
697
+ await DefaultManagement.loadTable(id, { force: true, reload: true, skipUrlUpdate: true });
773
698
  });
774
-
775
- // Reload table
776
- await DefaultManagement.loadTable(id, { force: true, reload: true });
777
-
778
699
  NotificationManager.Push({
779
- html: Translate.Render('success-clear-filter') || 'Filters cleared',
700
+ html: Translate.instance('success-clear-filter') || 'Filters cleared',
780
701
  status: 'success',
781
702
  });
782
703
  } catch (error) {
@@ -790,12 +711,10 @@ const DefaultManagement = {
790
711
  try {
791
712
  // Reload data from server
792
713
  await DefaultManagement.loadTable(id, { force: true, reload: true });
793
-
794
714
  // Other option: Refresh cells to update UI
795
715
  // DefaultManagement.refreshTable(id);
796
-
797
716
  NotificationManager.Push({
798
- html: Translate.Render('success-reload-data') || 'Data reloaded successfully',
717
+ html: Translate.instance('success-reload-data') || 'Data reloaded successfully',
799
718
  status: 'success',
800
719
  });
801
720
  } catch (error) {
@@ -809,15 +728,11 @@ const DefaultManagement = {
809
728
  s(`#ag-pagination-${gridId}`).addEventListener('page-change', async (event) => {
810
729
  const token = DefaultManagement.Tokens[id];
811
730
  token.page = event.detail.page;
812
- // Skip URL update since Pagination component already updated it
813
- await DefaultManagement.loadTable(id, { skipUrlUpdate: true });
814
731
  });
815
732
  s(`#ag-pagination-${gridId}`).addEventListener('limit-change', async (event) => {
816
733
  const token = DefaultManagement.Tokens[id];
817
734
  token.limit = event.detail.limit;
818
735
  token.page = 1; // Reset to first page
819
- // Skip URL update since Pagination component already updated it
820
- await DefaultManagement.loadTable(id, { skipUrlUpdate: true });
821
736
  });
822
737
  RouterEvents[id] = async (...args) => {
823
738
  const queryParams = getQueryParams();
@@ -830,21 +745,17 @@ const DefaultManagement = {
830
745
  if (queryParams.filterModel) filterModel = JSON.parse(queryParams.filterModel);
831
746
  if (queryParams.sortModel) sortModel = JSON.parse(queryParams.sortModel);
832
747
  } catch (e) {}
833
-
834
748
  const token = DefaultManagement.Tokens[id];
835
-
836
749
  if (!token) {
837
750
  // Token doesn't exist yet, table hasn't been initialized
838
751
  return;
839
752
  }
840
-
841
753
  // Check if state in URL is different from current state
842
754
  const currentId = DefaultManagement.getIdFilter(id);
843
755
  const isIdChanged = currentId !== urlId;
844
756
  const isPaginationChanged = token.page !== page || token.limit !== limit;
845
757
  const isFilterChanged = JSON.stringify(token.filterModel || {}) !== JSON.stringify(filterModel);
846
758
  const isSortChanged = JSON.stringify(token.sortModel || []) !== JSON.stringify(sortModel);
847
-
848
759
  if (isPaginationChanged || isFilterChanged || isSortChanged || isIdChanged) {
849
760
  // Update ID filter from query params
850
761
  if (urlId) {
@@ -852,12 +763,10 @@ const DefaultManagement = {
852
763
  } else {
853
764
  DefaultManagement.clearIdFilter(id);
854
765
  }
855
-
856
766
  token.page = page;
857
767
  token.limit = limit;
858
768
  token.filterModel = filterModel;
859
769
  token.sortModel = sortModel;
860
-
861
770
  // If grid is active, we should update its state to match URL
862
771
  const gridApi = AgGrid.grids[gridId];
863
772
  if (gridApi && gridApi.setFilterModel && gridApi.applyColumnState) {
@@ -893,49 +802,41 @@ const DefaultManagement = {
893
802
  };
894
803
  }, 1);
895
804
  return html`<div class="fl management-table-toolbar">
896
- ${await BtnIcon.Render({
897
- class: `in fll section-mp management-table-btn-mini management-table-btn-add-${id} ${
898
- permissions.add ? '' : 'hide'
899
- }`,
805
+ ${await BtnIcon.instance({
806
+ class: `in fll section-mp management-table-btn-mini management-table-btn-add-${id} ${permissions.add ? '' : 'hide'}`,
900
807
  label: html`<div class="abs center btn-add-${id}-label"><i class="fa-solid fa-circle-plus"></i></div> `,
901
808
  type: 'button',
902
809
  })}
903
- ${await BtnIcon.Render({
810
+ ${await BtnIcon.instance({
904
811
  class: `in fll section-mp management-table-btn-mini management-table-btn-save-${id} hide`,
905
812
  label: html`<div class="abs center btn-save-${id}-label"><i class="fas fa-save"></i></div> `,
906
813
  type: 'button',
907
814
  })}
908
- ${await BtnIcon.Render({
815
+ ${await BtnIcon.instance({
909
816
  class: `in fll section-mp management-table-btn-mini management-table-btn-stop-${id} hide`,
910
817
  label: html`<div class="abs center btn-save-${id}-label"><i class="fa-solid fa-rectangle-xmark"></i></div> `,
911
818
  type: 'button',
912
819
  })}
913
- ${await BtnIcon.Render({
914
- class: `in fll section-mp management-table-btn-mini management-table-btn-clean-${id} ${
915
- permissions.remove ? '' : 'hide'
916
- }`,
820
+ ${await BtnIcon.instance({
821
+ class: `in fll section-mp management-table-btn-mini management-table-btn-clean-${id} ${permissions.remove ? '' : 'hide'}`,
917
822
  label: html`<div class="abs center btn-clean-${id}-label"><i class="fas fa-broom"></i></div> `,
918
823
  type: 'button',
919
824
  })}
920
- ${await BtnIcon.Render({
921
- class: `in fll section-mp management-table-btn-mini management-table-btn-clear-filter-${id} ${
922
- Object.keys(filterModel).length > 0 || sortModel.length > 0 || urlId ? '' : 'hide'
923
- }`,
825
+ ${await BtnIcon.instance({
826
+ class: `in fll section-mp management-table-btn-mini management-table-btn-clear-filter-${id} ${Object.keys(filterModel).length > 0 || sortModel.length > 0 || urlId ? '' : 'hide'}`,
924
827
  label: html`<div class="abs center btn-clear-filter-${id}-label">
925
828
  <i class="fa-solid fa-filter-circle-xmark"></i>
926
829
  </div> `,
927
830
  type: 'button',
928
831
  })}
929
- ${await BtnIcon.Render({
930
- class: `in fll section-mp management-table-btn-mini management-table-btn-reload-${id} ${
931
- permissions.reload ? '' : 'hide'
932
- }`,
832
+ ${await BtnIcon.instance({
833
+ class: `in fll section-mp management-table-btn-mini management-table-btn-reload-${id} ${permissions.reload ? '' : 'hide'}`,
933
834
  label: html`<div class="abs center btn-reload-${id}-label"><i class="fas fa-sync-alt"></i></div> `,
934
835
  type: 'button',
935
836
  })}
936
837
  </div>
937
838
  <div class="in section-mp">
938
- ${await AgGrid.Render({
839
+ ${await AgGrid.instance({
939
840
  id: gridId,
940
841
  parentModal: options.idModal,
941
842
  usePagination: true,
@@ -964,17 +865,15 @@ const DefaultManagement = {
964
865
  autoHeight: true,
965
866
  },
966
867
  onGridReady: async (params) => {
967
- this.Tokens[id].gridApi = params.api;
968
-
969
- if (this.Tokens[id].readyGridEvent) {
970
- for (const key of Object.keys(this.Tokens[id].readyGridEvent)) {
971
- await this.Tokens[id].readyGridEvent[key](params);
868
+ DefaultManagement.Tokens[id].gridApi = params.api;
869
+ if (DefaultManagement.Tokens[id].readyGridEvent) {
870
+ for (const key of Object.keys(DefaultManagement.Tokens[id].readyGridEvent)) {
871
+ await DefaultManagement.Tokens[id].readyGridEvent[key](params);
972
872
  }
973
873
  }
974
-
975
874
  params.api.setGridOption('columnDefs', finalColumnDefs);
976
875
  // Apply initial state from URL
977
- const { filterModel, sortModel } = this.Tokens[id];
876
+ const { filterModel, sortModel } = DefaultManagement.Tokens[id];
978
877
  if (filterModel && Object.keys(filterModel).length > 0) {
979
878
  params.api.setFilterModel(filterModel);
980
879
  }
@@ -988,28 +887,26 @@ const DefaultManagement = {
988
887
  // Filter/sort state has been applied, this will fetch data from server
989
888
  DefaultManagement.loadTable(id).finally(() => {
990
889
  // Mark initialization complete to allow future filter/sort events
991
- this.Tokens[id].isInitializing = false;
890
+ DefaultManagement.Tokens[id].isInitializing = false;
992
891
  });
993
892
  },
994
893
  onFilterChanged: () => {
995
894
  // Skip if still initializing (state being applied in onGridReady)
996
- if (this.Tokens[id].isInitializing) return;
895
+ if (DefaultManagement.Tokens[id].isInitializing) return;
997
896
  // Skip if we're processing a query change from browser navigation
998
- if (this.Tokens[id].isProcessingQueryChange) return;
897
+ if (DefaultManagement.Tokens[id].isProcessingQueryChange) return;
999
898
  // Reset to page 1 on filter change
1000
- this.Tokens[id].page = 1;
1001
-
899
+ DefaultManagement.Tokens[id].page = 1;
1002
900
  // Update clear filter button visibility
1003
901
  DefaultManagement.updateClearFilterButtonVisibility(id);
1004
-
1005
902
  // Create history entry for filter changes
1006
903
  DefaultManagement.loadTable(id, { reload: true, force: true, createHistory: true });
1007
904
  },
1008
905
  onSortChanged: () => {
1009
906
  // Skip if still initializing (state being applied in onGridReady)
1010
- if (this.Tokens[id].isInitializing) return;
907
+ if (DefaultManagement.Tokens[id].isInitializing) return;
1011
908
  // Skip if we're processing a query change from browser navigation
1012
- if (this.Tokens[id].isProcessingQueryChange) return;
909
+ if (DefaultManagement.Tokens[id].isProcessingQueryChange) return;
1013
910
  // Update clear filter button visibility
1014
911
  DefaultManagement.updateClearFilterButtonVisibility(id);
1015
912
  // Create history entry for sort changes
@@ -1025,7 +922,7 @@ const DefaultManagement = {
1025
922
  const body = event.data ? event.data : {};
1026
923
  const result = await ServiceProvider.put({ id: event.data._id, body });
1027
924
  NotificationManager.Push({
1028
- html: result.status === 'error' ? result.message : `${Translate.Render('success-update-item')}`,
925
+ html: result.status === 'error' ? result.message : `${Translate.instance('success-update-item')}`,
1029
926
  status: result.status,
1030
927
  });
1031
928
  if (result.status === 'success') {
@@ -1083,26 +980,22 @@ const DefaultManagement = {
1083
980
  if (!event.data._id) {
1084
981
  result = await ServiceProvider.post({ body: event.data });
1085
982
  NotificationManager.Push({
1086
- html: result.status === 'error' ? result.message : `${Translate.Render('success-create-item')}`,
983
+ html: result.status === 'error' ? result.message : `${Translate.instance('success-create-item')}`,
1087
984
  status: result.status,
1088
985
  });
1089
986
  if (result.status === 'success') {
1090
987
  // Filter by the newly created row's ID
1091
988
  const newItemId = result.data._id;
1092
-
1093
989
  // Update UI buttons first
1094
990
  s(`.management-table-btn-save-${id}`).classList.add('hide');
1095
991
  if (permissions.add) s(`.management-table-btn-add-${id}`).classList.remove('hide');
1096
992
  if (permissions.remove) s(`.management-table-btn-clean-${id}`).classList.remove('hide');
1097
993
  if (permissions.reload) s(`.management-table-btn-reload-${id}`).classList.remove('hide');
1098
-
1099
994
  // Stop editing to avoid triggering other events
1100
995
  AgGrid.grids[gridId].stopEditing();
1101
-
1102
996
  // Set ID filter and reload
1103
- this.Tokens[id].page = 1;
1104
- this.setIdFilter(id, newItemId);
1105
-
997
+ DefaultManagement.Tokens[id].page = 1;
998
+ DefaultManagement.setIdFilter(id, newItemId);
1106
999
  setTimeout(async () => {
1107
1000
  await DefaultManagement.loadTable(id, { force: true, createHistory: true });
1108
1001
  });
@@ -1117,7 +1010,6 @@ const DefaultManagement = {
1117
1010
  },
1118
1011
  })}
1119
1012
  </div>`;
1120
- },
1121
- };
1122
-
1013
+ }
1014
+ }
1123
1015
  export { DefaultManagement };