underpost 3.2.5 → 3.2.8

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 (138) hide show
  1. package/.github/workflows/release.cd.yml +1 -2
  2. package/CHANGELOG.md +251 -1
  3. package/CLI-HELP.md +26 -13
  4. package/Dockerfile +0 -4
  5. package/README.md +3 -3
  6. package/bin/build.js +13 -3
  7. package/bin/deploy.js +570 -1
  8. package/bin/file.js +5 -0
  9. package/conf.js +11 -2
  10. package/jsconfig.json +1 -1
  11. package/manifests/cronjobs/dd-cron/dd-cron-backup.yaml +1 -1
  12. package/manifests/cronjobs/dd-cron/dd-cron-dns.yaml +1 -1
  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 +20 -11
  17. package/src/api/core/core.controller.js +10 -10
  18. package/src/api/core/core.service.js +10 -10
  19. package/src/api/default/default.controller.js +10 -10
  20. package/src/api/default/default.service.js +10 -10
  21. package/src/api/document/document.controller.js +12 -12
  22. package/src/api/document/document.model.js +10 -16
  23. package/src/api/file/file.controller.js +8 -8
  24. package/src/api/file/file.model.js +10 -10
  25. package/src/api/file/file.service.js +36 -36
  26. package/src/api/test/test.controller.js +8 -8
  27. package/src/api/test/test.service.js +8 -8
  28. package/src/api/user/guest.service.js +99 -0
  29. package/src/api/user/user.controller.js +6 -6
  30. package/src/api/user/user.model.js +8 -13
  31. package/src/api/user/user.service.js +3 -20
  32. package/src/cli/deploy.js +33 -30
  33. package/src/cli/fs.js +62 -5
  34. package/src/cli/image.js +43 -1
  35. package/src/cli/index.js +5 -1
  36. package/src/cli/release.js +57 -1
  37. package/src/cli/repository.js +35 -3
  38. package/src/cli/run.js +300 -35
  39. package/src/cli/ssh.js +1 -1
  40. package/src/cli/static.js +43 -115
  41. package/src/client/Default.index.js +21 -33
  42. package/src/client/components/core/404.js +4 -4
  43. package/src/client/components/core/500.js +4 -4
  44. package/src/client/components/core/Account.js +73 -60
  45. package/src/client/components/core/AgGrid.js +23 -33
  46. package/src/client/components/core/Alert.js +12 -13
  47. package/src/client/components/core/AppStore.js +1 -1
  48. package/src/client/components/core/Auth.js +20 -32
  49. package/src/client/components/core/Badge.js +7 -13
  50. package/src/client/components/core/BtnIcon.js +15 -17
  51. package/src/client/components/core/CalendarCore.js +42 -63
  52. package/src/client/components/core/Chat.js +13 -15
  53. package/src/client/components/core/ClientEvents.js +87 -0
  54. package/src/client/components/core/ColorPaletteElement.js +309 -0
  55. package/src/client/components/core/Content.js +17 -14
  56. package/src/client/components/core/Css.js +15 -71
  57. package/src/client/components/core/CssCore.js +12 -16
  58. package/src/client/components/core/D3Chart.js +4 -4
  59. package/src/client/components/core/Docs.js +60 -59
  60. package/src/client/components/core/DropDown.js +69 -91
  61. package/src/client/components/core/EventBus.js +92 -0
  62. package/src/client/components/core/EventsUI.js +14 -17
  63. package/src/client/components/core/FileExplorer.js +102 -234
  64. package/src/client/components/core/FullScreen.js +47 -75
  65. package/src/client/components/core/Input.js +24 -69
  66. package/src/client/components/core/Keyboard.js +25 -18
  67. package/src/client/components/core/KeyboardAvoidance.js +145 -0
  68. package/src/client/components/core/LoadingAnimation.js +25 -31
  69. package/src/client/components/core/LogIn.js +41 -41
  70. package/src/client/components/core/LogOut.js +23 -14
  71. package/src/client/components/core/Modal.js +397 -176
  72. package/src/client/components/core/NotificationManager.js +14 -18
  73. package/src/client/components/core/Panel.js +54 -50
  74. package/src/client/components/core/PanelForm.js +25 -125
  75. package/src/client/components/core/Polyhedron.js +110 -214
  76. package/src/client/components/core/PublicProfile.js +39 -32
  77. package/src/client/components/core/Recover.js +52 -48
  78. package/src/client/components/core/Responsive.js +88 -32
  79. package/src/client/components/core/RichText.js +9 -18
  80. package/src/client/components/core/Router.js +24 -3
  81. package/src/client/components/core/SearchBox.js +37 -37
  82. package/src/client/components/core/SignUp.js +39 -30
  83. package/src/client/components/core/SocketIo.js +31 -2
  84. package/src/client/components/core/SocketIoHandler.js +6 -6
  85. package/src/client/components/core/ToggleSwitch.js +8 -20
  86. package/src/client/components/core/ToolTip.js +5 -17
  87. package/src/client/components/core/Translate.js +56 -59
  88. package/src/client/components/core/Validator.js +26 -16
  89. package/src/client/components/core/Wallet.js +15 -26
  90. package/src/client/components/core/Worker.js +140 -25
  91. package/src/client/components/core/windowGetDimensions.js +7 -7
  92. package/src/client/components/default/{MenuDefault.js → AppShellDefault.js} +87 -87
  93. package/src/client/components/default/CssDefault.js +12 -12
  94. package/src/client/components/default/LogInDefault.js +6 -4
  95. package/src/client/components/default/LogOutDefault.js +6 -4
  96. package/src/client/components/default/RouterDefault.js +47 -0
  97. package/src/client/components/default/SettingsDefault.js +4 -4
  98. package/src/client/components/default/SignUpDefault.js +6 -4
  99. package/src/client/components/default/TranslateDefault.js +3 -3
  100. package/src/client/services/core/core.service.js +17 -49
  101. package/src/client/services/default/default.management.js +139 -242
  102. package/src/client/services/default/default.service.js +10 -16
  103. package/src/client/services/document/document.service.js +14 -19
  104. package/src/client/services/file/file.service.js +8 -13
  105. package/src/client/services/test/test.service.js +8 -13
  106. package/src/client/services/user/guest.service.js +79 -0
  107. package/src/client/services/user/user.management.js +5 -5
  108. package/src/client/services/user/user.service.js +14 -20
  109. package/src/client/ssr/body/404.js +3 -3
  110. package/src/client/ssr/body/500.js +3 -3
  111. package/src/client/ssr/body/CacheControl.js +5 -2
  112. package/src/client/ssr/body/DefaultSplashScreen.js +19 -12
  113. package/src/client/ssr/mailer/DefaultRecoverEmail.js +19 -20
  114. package/src/client/ssr/mailer/DefaultVerifyEmail.js +15 -16
  115. package/src/client/ssr/offline/Maintenance.js +12 -11
  116. package/src/client/ssr/offline/NoNetworkConnection.js +3 -3
  117. package/src/client/ssr/pages/Test.js +2 -2
  118. package/src/client/sw/core.sw.js +212 -0
  119. package/src/index.js +1 -1
  120. package/src/runtime/express/Dockerfile +4 -4
  121. package/src/runtime/lampp/Dockerfile +8 -7
  122. package/src/runtime/wp/Dockerfile +11 -17
  123. package/src/server/client-build-docs.js +45 -46
  124. package/src/server/client-build.js +334 -60
  125. package/src/server/client-formatted.js +47 -16
  126. package/src/server/conf.js +5 -4
  127. package/src/server/ipfs-client.js +232 -91
  128. package/src/server/process.js +13 -27
  129. package/src/server/start.js +6 -3
  130. package/src/server/valkey.js +134 -235
  131. package/tsconfig.docs.json +15 -0
  132. package/typedoc.json +20 -0
  133. package/jsdoc.json +0 -52
  134. package/src/client/components/core/ColorPalette.js +0 -5267
  135. package/src/client/components/core/JoyStick.js +0 -80
  136. package/src/client/components/default/RoutesDefault.js +0 -49
  137. package/src/client/sw/default.sw.js +0 -127
  138. package/src/client/sw/template.sw.js +0 -84
@@ -16,75 +16,58 @@ import { Translate } from './Translate.js';
16
16
  import { Validator } from './Validator.js';
17
17
  import { copyData, downloadFile, s } from './VanillaJs.js';
18
18
  import { getProxyPath, getQueryParams, setPath, setQueryParams, listenQueryParamsChange } from './Router.js';
19
-
20
19
  const logger = loggerFactory(import.meta);
21
-
22
20
  class LoadFolderRenderer {
23
21
  eGui;
24
-
25
22
  async init(params) {
26
23
  console.log('LoadFolderRenderer created', params);
27
24
  // params.data._id
28
-
29
25
  this.eGui = document.createElement('div');
30
26
  this.eGui.innerHTML = html`<i class="fas fa-folder"></i> ${params.data.location}`;
31
27
  }
32
-
33
28
  getGui() {
34
29
  return this.eGui;
35
30
  }
36
-
37
31
  refresh(params) {
38
32
  console.log('LoadFolderRenderer refreshed', params);
39
33
  return true;
40
34
  }
41
35
  }
42
-
43
36
  class LoadFileNameRenderer {
44
37
  eGui;
45
-
46
38
  async init(params) {
47
39
  console.log('LoadFileNameRenderer created', params);
48
40
  // params.data._id
49
-
50
41
  this.eGui = document.createElement('div');
51
42
  this.eGui.innerHTML = html`<i class="fas fa-file"></i> ${params.data.name}`;
52
43
  }
53
-
54
44
  getGui() {
55
45
  return this.eGui;
56
46
  }
57
-
58
47
  refresh(params) {
59
48
  console.log('LoadFileNameRenderer refreshed', params);
60
49
  return true;
61
50
  }
62
51
  }
63
-
64
52
  class FolderHeaderComp {
65
53
  eGui;
66
-
67
54
  async init(params) {
68
55
  console.log('FolderHeaderComp created', params);
69
56
  // params.data._id
70
-
71
57
  this.eGui = document.createElement('div');
72
58
  this.eGui.innerHTML = html`<i class="fas fa-file"></i>`;
73
59
  }
74
-
75
60
  getGui() {
76
61
  return this.eGui;
77
62
  }
78
-
79
63
  refresh(params) {
80
64
  console.log('FolderHeaderComp refreshed', params);
81
65
  return true;
82
66
  }
83
67
  }
84
-
85
- const FileExplorer = {
86
- Api: {},
87
- Render: async function (options = { idModal: '' }) {
68
+ class FileExplorer {
69
+ static Api = {};
70
+ static async instance(options = { idModal: '' }) {
88
71
  const { idModal } = options;
89
72
  FileExplorer.Api[idModal] = options;
90
73
  const gridFolderId = 'folder-explorer-grid';
@@ -92,15 +75,13 @@ const FileExplorer = {
92
75
  const idDropFileInput = 'file-explorer';
93
76
  let formBodyFiles;
94
77
  const query = getQueryParams();
95
- let location = query?.location ? this.locationFormat({ f: query }) : '/';
78
+ let location = query?.location ? FileExplorer.locationFormat({ f: query }) : '/';
96
79
  let files, folders, documentId, documentInstance;
97
-
98
80
  // Simple pagination state
99
81
  const PAGE_SIZE = 5;
100
82
  let currentPage = query?.page ? parseInt(query.page) - 1 : 0;
101
83
  if (currentPage < 0) currentPage = 0;
102
84
  let displayedFiles = [];
103
-
104
85
  // Search filter state - initialize from URL query param
105
86
  let searchFilters = {
106
87
  title: query?.title || '',
@@ -120,7 +101,6 @@ const FileExplorer = {
120
101
  const applySearchFilter = () => {
121
102
  filteredFiles = files;
122
103
  };
123
-
124
104
  const updatePaginationUI = () => {
125
105
  const paginationInfo = s(`.file-explorer-pagination-info`);
126
106
  const prevBtn = s(`.file-explorer-prev-btn`);
@@ -145,31 +125,26 @@ const FileExplorer = {
145
125
  nextBtn.style.cursor = isDisabled ? 'not-allowed' : 'pointer';
146
126
  }
147
127
  };
148
-
149
128
  const getPagedFiles = () => {
150
129
  const start = currentPage * PAGE_SIZE;
151
130
  const end = start + PAGE_SIZE;
152
131
  return filteredFiles.slice(start, end);
153
132
  };
154
-
155
133
  FileExplorer.Api[idModal].displayList = async () => {
156
134
  if (!s(`.${idModal}`)) return;
157
135
  const query = getQueryParams();
158
- location = query?.location ? this.locationFormat({ f: query }) : '/';
136
+ location = query?.location ? FileExplorer.locationFormat({ f: query }) : '/';
159
137
  s(`.file-explorer-query-nav`).value = location;
160
-
161
138
  // Sync search filters from URL
162
139
  searchFilters = {
163
140
  title: query?.title || '',
164
141
  mdFile: query?.mdFile || '',
165
142
  file: query?.file || '',
166
143
  };
167
-
168
144
  if (s(`.file-explorer-search-title`)) s(`.file-explorer-search-title`).value = searchFilters.title;
169
145
  if (s(`.file-explorer-search-md-file`)) s(`.file-explorer-search-md-file`).value = searchFilters.mdFile;
170
146
  if (s(`.file-explorer-search-file`)) s(`.file-explorer-search-file`).value = searchFilters.file;
171
-
172
- const format = this.documentDataFormat({ document: documentInstance, location, searchFilters });
147
+ const format = FileExplorer.documentDataFormat({ document: documentInstance, location, searchFilters });
173
148
  files = format.files;
174
149
  folders = format.folders;
175
150
  applySearchFilter();
@@ -194,7 +169,7 @@ const FileExplorer = {
194
169
  });
195
170
  // Handle both old format (array) and new format with pagination
196
171
  const document = Array.isArray(responseData) ? responseData : responseData.data || [];
197
- const format = this.documentDataFormat({ document, location, searchFilters });
172
+ const format = FileExplorer.documentDataFormat({ document, location, searchFilters });
198
173
  files = format.files;
199
174
  documentId = format.documentId;
200
175
  folders = format.folders;
@@ -212,7 +187,6 @@ const FileExplorer = {
212
187
  if (s(`.${idModal}`) && optionsUpdate && optionsUpdate.display) await FileExplorer.Api[idModal].displayList();
213
188
  });
214
189
  };
215
-
216
190
  RouterEvents['file-explorer'] = ({ path, pushPath, route }) => {
217
191
  if (route === 'cloud')
218
192
  setTimeout(async () => {
@@ -220,14 +194,12 @@ const FileExplorer = {
220
194
  await FileExplorer.Api[idModal].displayList();
221
195
  });
222
196
  };
223
-
224
197
  // Listen for query param changes (browser back/forward navigation)
225
198
  listenQueryParamsChange({
226
199
  id: queryParamsListenerId,
227
200
  event: async (queryParams) => {
228
201
  if (!s(`.${idModal}`)) return;
229
202
  if (isProcessingQueryChange) return;
230
-
231
203
  const tab = queryParams?.tab || '';
232
204
  if (tab === 'upload') {
233
205
  s(`.file-explorer-nav`).style.display = 'none';
@@ -236,7 +208,6 @@ const FileExplorer = {
236
208
  s(`.file-explorer-nav`).style.display = 'block';
237
209
  s(`.file-explorer-uploader`).style.display = 'none';
238
210
  }
239
-
240
211
  const page = queryParams?.page ? parseInt(queryParams.page) - 1 : 0;
241
212
  if (page !== currentPage) {
242
213
  currentPage = page >= 0 ? page : 0;
@@ -246,13 +217,11 @@ const FileExplorer = {
246
217
  }
247
218
  updatePaginationUI();
248
219
  }
249
-
250
220
  const newFilters = {
251
221
  title: queryParams?.title || '',
252
222
  mdFile: queryParams?.mdFile || '',
253
223
  file: queryParams?.file || '',
254
224
  };
255
-
256
225
  if (
257
226
  newFilters.title !== searchFilters.title ||
258
227
  newFilters.mdFile !== searchFilters.mdFile ||
@@ -260,20 +229,16 @@ const FileExplorer = {
260
229
  ) {
261
230
  isProcessingQueryChange = true;
262
231
  searchFilters = newFilters;
263
-
264
232
  if (s(`.file-explorer-search-title`)) s(`.file-explorer-search-title`).value = searchFilters.title;
265
233
  if (s(`.file-explorer-search-md-file`)) s(`.file-explorer-search-md-file`).value = searchFilters.mdFile;
266
234
  if (s(`.file-explorer-search-file`)) s(`.file-explorer-search-file`).value = searchFilters.file;
267
-
268
235
  await FileExplorer.Api[idModal].updateData({ display: true });
269
-
270
236
  setTimeout(() => {
271
237
  isProcessingQueryChange = false;
272
238
  }, 100);
273
239
  }
274
240
  },
275
241
  });
276
-
277
242
  // Pagination button event handlers
278
243
  setTimeout(() => {
279
244
  EventsUI.onClick(`.file-explorer-prev-btn`, (e) => {
@@ -282,17 +247,14 @@ const FileExplorer = {
282
247
  setQueryParams({ page: currentPage }, { replace: false });
283
248
  }
284
249
  });
285
-
286
250
  EventsUI.onClick(`.file-explorer-next-btn`, (e) => {
287
251
  e.preventDefault();
288
252
  if ((currentPage + 1) * PAGE_SIZE < filteredFiles.length) {
289
253
  setQueryParams({ page: currentPage + 2 }, { replace: false });
290
254
  }
291
255
  });
292
-
293
256
  // Search input handlers
294
257
  let searchTimeout;
295
-
296
258
  const setupSearchInput = (selector, key) => {
297
259
  const el = s(selector);
298
260
  if (el) {
@@ -302,24 +264,18 @@ const FileExplorer = {
302
264
  searchTimeout = setTimeout(async () => {
303
265
  const val = e.target.value.trim();
304
266
  if (val === searchFilters[key]) return;
305
-
306
267
  isProcessingQueryChange = true;
307
268
  searchFilters[key] = val;
308
269
  await FileExplorer.Api[idModal].updateData({ display: true });
309
-
310
270
  const queryParams = {};
311
271
  if (searchFilters.title) queryParams.title = searchFilters.title;
312
272
  if (searchFilters.mdFile) queryParams.mdFile = searchFilters.mdFile;
313
273
  if (searchFilters.file) queryParams.file = searchFilters.file;
314
-
315
274
  if (!searchFilters.title) queryParams.title = null;
316
275
  if (!searchFilters.mdFile) queryParams.mdFile = null;
317
276
  if (!searchFilters.file) queryParams.file = null;
318
-
319
277
  queryParams.page = 1;
320
-
321
278
  setQueryParams(queryParams, { replace: false });
322
-
323
279
  setTimeout(() => {
324
280
  isProcessingQueryChange = false;
325
281
  }, 100);
@@ -330,71 +286,52 @@ const FileExplorer = {
330
286
  });
331
287
  }
332
288
  };
333
-
334
289
  setupSearchInput(`.file-explorer-search-title`, 'title');
335
290
  setupSearchInput(`.file-explorer-search-md-file`, 'mdFile');
336
291
  setupSearchInput(`.file-explorer-search-file`, 'file');
337
-
338
292
  // Submit search button
339
293
  EventsUI.onClick(`.file-explorer-search-submit`, async (e) => {
340
294
  e.preventDefault();
341
295
  clearTimeout(searchTimeout);
342
-
343
296
  const titleVal = s(`.file-explorer-search-title`)?.value.trim() || '';
344
297
  const mdFileVal = s(`.file-explorer-search-md-file`)?.value.trim() || '';
345
298
  const fileVal = s(`.file-explorer-search-file`)?.value.trim() || '';
346
-
347
299
  searchFilters = { title: titleVal, mdFile: mdFileVal, file: fileVal };
348
-
349
300
  isProcessingQueryChange = true;
350
-
351
301
  const queryParams = {};
352
302
  if (searchFilters.title) queryParams.title = searchFilters.title;
353
303
  if (searchFilters.mdFile) queryParams.mdFile = searchFilters.mdFile;
354
304
  if (searchFilters.file) queryParams.file = searchFilters.file;
355
-
356
305
  if (!searchFilters.title) queryParams.title = null;
357
306
  if (!searchFilters.mdFile) queryParams.mdFile = null;
358
307
  if (!searchFilters.file) queryParams.file = null;
359
-
360
308
  queryParams.page = 1;
361
-
362
309
  setQueryParams(queryParams, { replace: false });
363
-
364
310
  await FileExplorer.Api[idModal].updateData({ display: true });
365
-
366
311
  setTimeout(() => {
367
312
  isProcessingQueryChange = false;
368
313
  }, 100);
369
314
  });
370
-
371
315
  // Clear search button
372
316
  EventsUI.onClick(`.file-explorer-search-clear`, (e) => {
373
317
  e.preventDefault();
374
-
375
318
  if (!searchFilters.title && !searchFilters.mdFile && !searchFilters.file) return;
376
-
377
319
  isProcessingQueryChange = true;
378
320
  if (s(`.file-explorer-search-title`)) s(`.file-explorer-search-title`).value = '';
379
321
  if (s(`.file-explorer-search-md-file`)) s(`.file-explorer-search-md-file`).value = '';
380
322
  if (s(`.file-explorer-search-file`)) s(`.file-explorer-search-file`).value = '';
381
-
382
323
  searchFilters = { title: '', mdFile: '', file: '' };
383
-
384
324
  applySearchFilter();
385
325
  currentPage = 0;
386
326
  displayedFiles = getPagedFiles();
387
327
  AgGrid.grids[gridFileId].setGridOption('rowData', displayedFiles);
388
328
  updatePaginationUI();
389
-
390
329
  setQueryParams({ title: null, mdFile: null, file: null, page: 1 }, { replace: false });
391
-
392
330
  setTimeout(() => {
393
331
  isProcessingQueryChange = false;
394
332
  }, 100);
395
333
  });
396
334
  });
397
-
398
335
  setTimeout(async () => {
399
336
  FileExplorer.Api[idModal].updateData({ display: true });
400
337
  const formData = [
@@ -405,22 +342,19 @@ const FileExplorer = {
405
342
  },
406
343
  ];
407
344
  const validators = await Validator.instance(formData);
408
-
409
345
  EventsUI.onClick(`.btn-input-file-explorer`, async (e) => {
410
346
  e.preventDefault();
411
-
412
347
  // Check authentication before upload
413
348
  if (!Auth.getToken()) {
414
349
  return NotificationManager.Push({
415
- html: Translate.Render(`error-user-not-authenticated`),
350
+ html: Translate.instance(`error-user-not-authenticated`),
416
351
  status: 'error',
417
352
  });
418
353
  }
419
-
420
354
  const { errorMessage } = await validators();
421
355
  if (!formBodyFiles)
422
356
  return NotificationManager.Push({
423
- html: Translate.Render(`warning-upload-no-selects-file`),
357
+ html: Translate.instance(`warning-upload-no-selects-file`),
424
358
  status: 'warning',
425
359
  });
426
360
  if (errorMessage) return;
@@ -429,7 +363,7 @@ const FileExplorer = {
429
363
  const { status, data } = await FileService.post({ body: formBodyFiles });
430
364
  if (status === 'error' || !data) {
431
365
  return NotificationManager.Push({
432
- html: Translate.Render(`error-upload-file`),
366
+ html: Translate.instance(`error-upload-file`),
433
367
  status: 'error',
434
368
  });
435
369
  }
@@ -440,7 +374,7 @@ const FileExplorer = {
440
374
  // for (const inputData of formData) {
441
375
  // if ('model' in inputData) body[inputData.model] = s(`.${inputData.id}`).value;
442
376
  // }
443
- location = this.locationFormat({ f: { location: s(`.file-explorer-query-nav`).value } });
377
+ location = FileExplorer.locationFormat({ f: { location: s(`.file-explorer-query-nav`).value } });
444
378
  let status = 'success';
445
379
  for (const file of fileData) {
446
380
  const result = await DocumentService.post({
@@ -453,7 +387,7 @@ const FileExplorer = {
453
387
  if (result.status === 'success') documentInstance.push({ ...result.data, fileId: file });
454
388
  else if (status !== 'error') status = 'error';
455
389
  }
456
- const format = this.documentDataFormat({ document: documentInstance, location });
390
+ const format = FileExplorer.documentDataFormat({ document: documentInstance, location });
457
391
  files = format.files;
458
392
  folders = format.folders;
459
393
  applySearchFilter();
@@ -463,7 +397,7 @@ const FileExplorer = {
463
397
  AgGrid.grids[gridFolderId].setGridOption('rowData', folders);
464
398
  updatePaginationUI();
465
399
  NotificationManager.Push({
466
- html: Translate.Render(`${status}-upload-file`),
400
+ html: Translate.instance(`${status}-upload-file`),
467
401
  status,
468
402
  });
469
403
  if (status === 'success') {
@@ -478,10 +412,9 @@ const FileExplorer = {
478
412
  }
479
413
  }
480
414
  });
481
-
482
415
  EventsUI.onClick(`.btn-input-go-explorer`, async (e) => {
483
416
  e.preventDefault();
484
- const newLocation = this.locationFormat({ f: { location: s(`.file-explorer-query-nav`).value } });
417
+ const newLocation = FileExplorer.locationFormat({ f: { location: s(`.file-explorer-query-nav`).value } });
485
418
  if (newLocation === location) return;
486
419
  location = newLocation;
487
420
  setPath(`${window.location.pathname}?location=${location}`);
@@ -491,18 +424,16 @@ const FileExplorer = {
491
424
  });
492
425
  EventsUI.onClick(`.btn-input-home-directory`, async (e) => {
493
426
  e.preventDefault();
494
-
495
427
  if (getQueryParams()?.tab === 'upload') {
496
428
  setQueryParams({ tab: null }, { replace: false });
497
429
  return;
498
430
  }
499
-
500
431
  let newLocation = '/';
501
432
  if (newLocation === location) return;
502
433
  location = newLocation;
503
434
  setPath(`${window.location.pathname}?location=${location}`);
504
435
  s(`.file-explorer-query-nav`).value = location;
505
- const format = this.documentDataFormat({ document: documentInstance, location });
436
+ const format = FileExplorer.documentDataFormat({ document: documentInstance, location });
506
437
  files = format.files;
507
438
  folders = format.folders;
508
439
  applySearchFilter();
@@ -516,7 +447,7 @@ const FileExplorer = {
516
447
  e.preventDefault();
517
448
  await copyData(window.location.href);
518
449
  NotificationManager.Push({
519
- html: Translate.Render('success-copy-data'),
450
+ html: Translate.instance('success-copy-data'),
520
451
  status: 'success',
521
452
  });
522
453
  });
@@ -533,53 +464,49 @@ const FileExplorer = {
533
464
  setQueryParams({ tab: 'upload' }, { replace: false });
534
465
  });
535
466
  });
536
-
537
467
  class LoadFileActionsRenderer {
538
468
  eGui;
539
-
540
469
  async init(params) {
541
470
  console.log('LoadFileActionsRenderer created', params);
542
471
  // params.data._id
543
-
544
- this.eGui = document.createElement('div');
472
+ FileExplorer.eGui = document.createElement('div');
545
473
  const isPublic = params.data.isPublic;
546
474
  const toggleId = `toggle-public-${params.data._id}`;
547
475
  const hasGenericFile = !!params.data.hasGenericFile;
548
476
  const hasMdFile = !!params.data.hasMdFile;
549
-
550
- this.eGui.innerHTML = html`
477
+ FileExplorer.eGui.innerHTML = html`
551
478
  <div class="fl">
552
- ${await BtnIcon.Render({
479
+ ${await BtnIcon.instance({
553
480
  class: `in fll management-table-btn-mini btn-file-download-${params.data._id}${!hasGenericFile ? ' btn-disabled' : ''}`,
554
481
  label: html` <i class="fas fa-download"></i>`,
555
482
  type: 'button',
556
483
  })}
557
- ${await BtnIcon.Render({
484
+ ${await BtnIcon.instance({
558
485
  class: `in fll management-table-btn-mini btn-file-delete-${params.data._id}`,
559
486
  label: html` <i class="fa-solid fa-circle-xmark"></i>`,
560
487
  type: 'button',
561
488
  })}
562
- ${await BtnIcon.Render({
489
+ ${await BtnIcon.instance({
563
490
  class: `in fll management-table-btn-mini btn-file-view-${params.data._id}`,
564
491
  label: html` <i class="fas fa-eye"></i>`,
565
492
  type: 'button',
566
493
  })}
567
- ${await BtnIcon.Render({
494
+ ${await BtnIcon.instance({
568
495
  class: `in fll management-table-btn-mini btn-file-copy-content-link-${params.data._id}${!hasGenericFile ? ' btn-disabled' : ''}`,
569
496
  label: html`<i class="fas fa-copy"></i>`,
570
497
  type: 'button',
571
498
  })}
572
- ${await BtnIcon.Render({
499
+ ${await BtnIcon.instance({
573
500
  class: `in fll management-table-btn-mini btn-file-copy-md-link-${params.data._id}${!hasMdFile ? ' btn-disabled' : ''}`,
574
501
  label: html`<i class="fas fa-file-code"></i>`,
575
502
  type: 'button',
576
503
  })}
577
- ${await BtnIcon.Render({
504
+ ${await BtnIcon.instance({
578
505
  class: `in fll management-table-btn-mini btn-file-edit-${params.data._id}`,
579
506
  label: html`<i class="fas fa-edit"></i>`,
580
507
  type: 'button',
581
508
  })}
582
- ${await BtnIcon.Render({
509
+ ${await BtnIcon.instance({
583
510
  class: `in fll management-table-btn-mini ${toggleId}`,
584
511
  label: isPublic
585
512
  ? html`<i class="fas fa-globe" style="color: #4caf50;"></i>`
@@ -588,27 +515,22 @@ const FileExplorer = {
588
515
  })}
589
516
  </div>
590
517
  `;
591
-
592
518
  setTimeout(() => {
593
519
  const uri = `${getProxyPath()}content/?cid=${params.data._id}`;
594
520
  const url = `${window.location.origin}${uri}`;
595
-
596
521
  const originObj = documentInstance.find((d) => d._id === params.data._id);
597
522
  const blobUri =
598
523
  originObj && originObj.fileId
599
524
  ? getApiBaseUrl({ id: originObj.fileId._id, endpoint: 'file/blob' })
600
525
  : undefined;
601
-
602
526
  const mdBlobUri =
603
527
  originObj && originObj.mdFileId
604
528
  ? getApiBaseUrl({ id: originObj.mdFileId._id, endpoint: 'file/blob' })
605
529
  : undefined;
606
-
607
530
  if (!originObj) {
608
531
  s(`.btn-file-view-${params.data._id}`).classList.add('hide');
609
532
  s(`.btn-file-copy-content-link-${params.data._id}`).classList.add('hide');
610
533
  }
611
-
612
534
  // Disable download button if no generic file
613
535
  if (!hasGenericFile) {
614
536
  const dlBtn = s(`.btn-file-download-${params.data._id}`);
@@ -618,7 +540,6 @@ const FileExplorer = {
618
540
  dlBtn.style.pointerEvents = 'none';
619
541
  }
620
542
  }
621
-
622
543
  // Disable copy generic file link button if no generic file
623
544
  if (!hasGenericFile) {
624
545
  const copyBtn = s(`.btn-file-copy-content-link-${params.data._id}`);
@@ -628,7 +549,6 @@ const FileExplorer = {
628
549
  copyBtn.style.pointerEvents = 'none';
629
550
  }
630
551
  }
631
-
632
552
  // Disable copy md file link button if no md file
633
553
  if (!hasMdFile) {
634
554
  const mdCopyBtn = s(`.btn-file-copy-md-link-${params.data._id}`);
@@ -638,7 +558,6 @@ const FileExplorer = {
638
558
  mdCopyBtn.style.pointerEvents = 'none';
639
559
  }
640
560
  }
641
-
642
561
  EventsUI.onClick(`.btn-file-view-${params.data._id}`, async (e) => {
643
562
  e.preventDefault();
644
563
  if (location.href !== url) {
@@ -646,27 +565,24 @@ const FileExplorer = {
646
565
  s(`.main-btn-content`).click();
647
566
  }
648
567
  });
649
-
650
568
  EventsUI.onClick(`.btn-file-copy-content-link-${params.data._id}`, async (e) => {
651
569
  e.preventDefault();
652
570
  if (!hasGenericFile || !blobUri) return;
653
571
  await copyData(blobUri);
654
572
  NotificationManager.Push({
655
- html: Translate.Render('success-copy-data'),
573
+ html: Translate.instance('success-copy-data'),
656
574
  status: 'success',
657
575
  });
658
576
  });
659
-
660
577
  EventsUI.onClick(`.btn-file-copy-md-link-${params.data._id}`, async (e) => {
661
578
  e.preventDefault();
662
579
  if (!hasMdFile || !mdBlobUri) return;
663
580
  await copyData(mdBlobUri);
664
581
  NotificationManager.Push({
665
- html: Translate.Render('success-copy-data'),
582
+ html: Translate.instance('success-copy-data'),
666
583
  status: 'success',
667
584
  });
668
585
  });
669
-
670
586
  EventsUI.onClick(`.btn-file-download-${params.data._id}`, async (e) => {
671
587
  e.preventDefault();
672
588
  if (!hasGenericFile) return;
@@ -695,7 +611,7 @@ const FileExplorer = {
695
611
  html: async () => {
696
612
  return html`
697
613
  <div class="in section-mp" style="text-align: center">
698
- ${Translate.Render('confirm-delete-item')}
614
+ ${Translate.instance('confirm-delete-item')}
699
615
  <br />
700
616
  "${params.data.title}"
701
617
  </div>
@@ -704,7 +620,6 @@ const FileExplorer = {
704
620
  id: `delete-${params.data._id}`,
705
621
  });
706
622
  if (confirmResult.status !== 'confirm') return;
707
-
708
623
  const { data, status, message } = await FileService.delete({
709
624
  id: params.data.fileId,
710
625
  });
@@ -722,7 +637,6 @@ const FileExplorer = {
722
637
  status,
723
638
  });
724
639
  if (status === 'error') return;
725
-
726
640
  documentInstance = documentInstance.filter((f) => f._id !== params.data._id);
727
641
  const format = FileExplorer.documentDataFormat({ document: documentInstance, location });
728
642
  files = format.files;
@@ -736,20 +650,18 @@ const FileExplorer = {
736
650
  },
737
651
  { context: 'modal' },
738
652
  );
739
-
740
653
  // Toggle public/private status
741
654
  EventsUI.onClick(
742
655
  `.${toggleId}`,
743
656
  async (e) => {
744
657
  e.preventDefault();
745
-
746
658
  // If document is currently private, show confirmation before making public
747
659
  if (!params.data.isPublic) {
748
660
  const confirmResult = await Modal.RenderConfirm({
749
661
  html: async () => {
750
662
  return html`
751
663
  <div class="in section-mp" style="text-align: center">
752
- ${Translate.Render('confirm-make-public')}
664
+ ${Translate.instance('confirm-make-public')}
753
665
  <br />
754
666
  "${params.data.title}"
755
667
  </div>
@@ -759,29 +671,24 @@ const FileExplorer = {
759
671
  });
760
672
  if (confirmResult.status !== 'confirm') return;
761
673
  }
762
-
763
674
  try {
764
675
  const { data, status } = await DocumentService.patch({
765
676
  id: params.data._id,
766
677
  action: 'toggle-public',
767
678
  });
768
-
769
679
  if (status === 'success') {
770
680
  // Update local data
771
681
  params.data.isPublic = data.isPublic;
772
-
773
682
  // Update documentInstance
774
683
  const docIndex = documentInstance.findIndex((d) => d._id === params.data._id);
775
684
  if (docIndex !== -1) {
776
685
  documentInstance[docIndex].isPublic = data.isPublic;
777
686
  }
778
-
779
687
  // Refresh the isPublic column cell in the grid
780
688
  const rowNode = AgGrid.grids[gridFileId].getRowNode(params.node.id);
781
689
  if (rowNode) {
782
690
  rowNode.setDataValue('isPublic', data.isPublic);
783
691
  }
784
-
785
692
  // Update button icon
786
693
  const btnElement = s(`.${toggleId}`);
787
694
  if (btnElement) {
@@ -796,11 +703,10 @@ const FileExplorer = {
796
703
  }
797
704
  }
798
705
  }
799
-
800
706
  NotificationManager.Push({
801
707
  html: data.isPublic
802
- ? Translate.Render('document-now-public')
803
- : Translate.Render('document-now-private'),
708
+ ? Translate.instance('document-now-public')
709
+ : Translate.instance('document-now-private'),
804
710
  status: 'success',
805
711
  });
806
712
  } else {
@@ -809,31 +715,26 @@ const FileExplorer = {
809
715
  } catch (error) {
810
716
  logger.error('Toggle public failed:', error);
811
717
  NotificationManager.Push({
812
- html: Translate.Render('error-toggle-public'),
718
+ html: Translate.instance('error-toggle-public'),
813
719
  status: 'error',
814
720
  });
815
721
  }
816
722
  },
817
723
  { context: 'modal' },
818
724
  );
819
-
820
725
  // Edit document button
821
726
  EventsUI.onClick(
822
727
  `.btn-file-edit-${params.data._id}`,
823
728
  async (e) => {
824
729
  e.preventDefault();
825
-
826
730
  // Get the original document data from documentInstance
827
731
  const originDoc = documentInstance.find((d) => d._id === params.data._id);
828
732
  const editModalId = `edit-doc-${params.data._id}`;
829
-
830
733
  // Check file existence for proper UX
831
734
  const hasMdFile = !!(originDoc && originDoc.mdFileId);
832
735
  const hasGenericFile = !!(originDoc && originDoc.fileId);
833
-
834
736
  const mdFileMimetype = hasMdFile ? originDoc.mdFileId.mimetype : '';
835
737
  const genericFileMimetype = hasGenericFile ? originDoc.fileId.mimetype : '';
836
-
837
738
  const editFormHtml = async () => {
838
739
  return html`
839
740
  <div class="in edit-document-form" style="max-width: 600px; margin: 0 auto; padding: 20px;">
@@ -843,16 +744,16 @@ const FileExplorer = {
843
744
  style="text-align: center; margin-bottom: 25px; padding-bottom: 15px; border-bottom: 1px solid rgba(128,128,128,0.3);"
844
745
  >
845
746
  <p style="color: #888; font-size: 14px; margin: 0;">
846
- ${Translate.Render('editing')}: <strong style="color: inherit;">${params.data.title}</strong>
747
+ ${Translate.instance('editing')}: <strong style="color: inherit;">${params.data.title}</strong>
847
748
  </p>
848
749
  </div>
849
750
 
850
751
  <!-- Document Title -->
851
752
  <div class="in section-mp" style="margin-bottom: 20px;">
852
- ${await Input.Render({
753
+ ${await Input.instance({
853
754
  id: `edit-doc-title-${params.data._id}`,
854
755
  type: 'text',
855
- label: html`<i class="fas fa-heading"></i> ${Translate.Render('doc-title')}`,
756
+ label: html`<i class="fas fa-heading"></i> ${Translate.instance('doc-title')}`,
856
757
  containerClass: 'in section-mp input-container-width',
857
758
  placeholder: true,
858
759
  value: params.data.title || '',
@@ -862,10 +763,10 @@ const FileExplorer = {
862
763
  <!-- MD File Name -->
863
764
  <div class="in section-mp" style="margin-bottom: 20px;">
864
765
  ${hasMdFile
865
- ? await Input.Render({
766
+ ? await Input.instance({
866
767
  id: `edit-doc-md-file-${params.data._id}`,
867
768
  type: 'text',
868
- label: html`<i class="fas fa-file-code"></i> ${Translate.Render('md-file-name')}
769
+ label: html`<i class="fas fa-file-code"></i> ${Translate.instance('md-file-name')}
869
770
  <span style="font-size: 11px; color: #888; margin-left: 8px;">(${mdFileMimetype})</span>`,
870
771
  containerClass: 'in section-mp input-container-width',
871
772
  placeholder: true,
@@ -874,12 +775,12 @@ const FileExplorer = {
874
775
  : html`
875
776
  <div class="in section-mp input-container-width" style="opacity: 0.6;">
876
777
  <label style="display: block; margin-bottom: 5px;">
877
- <i class="fas fa-file-code"></i> ${Translate.Render('md-file-name')}
778
+ <i class="fas fa-file-code"></i> ${Translate.instance('md-file-name')}
878
779
  </label>
879
780
  <div
880
781
  style="padding: 10px 12px; border: 1px dashed rgba(128,128,128,0.5); border-radius: 4px; color: #888; font-style: italic;"
881
782
  >
882
- <i class="fas fa-info-circle"></i> ${Translate.Render('no-md-file-attached')}
783
+ <i class="fas fa-info-circle"></i> ${Translate.instance('no-md-file-attached')}
883
784
  </div>
884
785
  </div>
885
786
  `}
@@ -888,10 +789,10 @@ const FileExplorer = {
888
789
  <!-- Generic File Name -->
889
790
  <div class="in section-mp" style="margin-bottom: 20px;">
890
791
  ${hasGenericFile
891
- ? await Input.Render({
792
+ ? await Input.instance({
892
793
  id: `edit-doc-file-${params.data._id}`,
893
794
  type: 'text',
894
- label: html`<i class="fas fa-file"></i> ${Translate.Render('generic-file-name')}
795
+ label: html`<i class="fas fa-file"></i> ${Translate.instance('generic-file-name')}
895
796
  <span style="font-size: 11px; color: #888; margin-left: 8px;"
896
797
  >(${genericFileMimetype})</span
897
798
  >`,
@@ -902,12 +803,12 @@ const FileExplorer = {
902
803
  : html`
903
804
  <div class="in section-mp input-container-width" style="opacity: 0.6;">
904
805
  <label style="display: block; margin-bottom: 5px;">
905
- <i class="fas fa-file"></i> ${Translate.Render('generic-file-name')}
806
+ <i class="fas fa-file"></i> ${Translate.instance('generic-file-name')}
906
807
  </label>
907
808
  <div
908
809
  style="padding: 10px 12px; border: 1px dashed rgba(128,128,128,0.5); border-radius: 4px; color: #888; font-style: italic;"
909
810
  >
910
- <i class="fas fa-info-circle"></i> ${Translate.Render('no-generic-file-attached')}
811
+ <i class="fas fa-info-circle"></i> ${Translate.instance('no-generic-file-attached')}
911
812
  </div>
912
813
  </div>
913
814
  `}
@@ -915,10 +816,10 @@ const FileExplorer = {
915
816
 
916
817
  <!-- Location -->
917
818
  <div class="in section-mp" style="margin-bottom: 25px;">
918
- ${await Input.Render({
819
+ ${await Input.instance({
919
820
  id: `edit-doc-location-${params.data._id}`,
920
821
  type: 'text',
921
- label: html`<i class="fas fa-folder"></i> ${Translate.Render('location')}`,
822
+ label: html`<i class="fas fa-folder"></i> ${Translate.instance('location')}`,
922
823
  containerClass: 'in section-mp input-container-width',
923
824
  placeholder: true,
924
825
  value: params.data.location || '/',
@@ -931,16 +832,16 @@ const FileExplorer = {
931
832
  style="margin-top: 30px; border-top: 1px solid rgba(128,128,128,0.3); padding-top: 20px;"
932
833
  >
933
834
  <div class="in fll" style="width: 50%; padding: 5px;">
934
- ${await BtnIcon.Render({
835
+ ${await BtnIcon.instance({
935
836
  class: `in wfa btn-edit-doc-cancel-${params.data._id}`,
936
- label: html`<i class="fas fa-times"></i> ${Translate.Render('cancel')}`,
837
+ label: html`<i class="fas fa-times"></i> ${Translate.instance('cancel')}`,
937
838
  type: 'button',
938
839
  })}
939
840
  </div>
940
841
  <div class="in fll" style="width: 50%; padding: 5px;">
941
- ${await BtnIcon.Render({
842
+ ${await BtnIcon.instance({
942
843
  class: `in wfa btn-edit-doc-submit-${params.data._id}`,
943
- label: html`<i class="fas fa-save"></i> ${Translate.Render('save')}`,
844
+ label: html`<i class="fas fa-save"></i> ${Translate.instance('save')}`,
944
845
  type: 'button',
945
846
  })}
946
847
  </div>
@@ -948,15 +849,13 @@ const FileExplorer = {
948
849
  </div>
949
850
  `;
950
851
  };
951
-
952
852
  const { barConfig } = await Themes[Css.currentTheme]();
953
-
954
- await Modal.Render({
853
+ await Modal.instance({
955
854
  id: editModalId,
956
855
  barConfig,
957
856
  title: renderViewTitle({
958
857
  icon: html`<i class="fas fa-edit"></i>`,
959
- text: Translate.Render('edit-document'),
858
+ text: Translate.instance('edit-document'),
960
859
  }),
961
860
  html: editFormHtml,
962
861
  handleType: 'bar',
@@ -966,37 +865,30 @@ const FileExplorer = {
966
865
  RouterInstance: Modal.Data[options.idModal].options.RouterInstance,
967
866
  barMode: Modal.Data[options.idModal].options.barMode,
968
867
  });
969
-
970
868
  // Handle submit button
971
869
  setTimeout(() => {
972
870
  EventsUI.onClick(
973
871
  `.btn-edit-doc-submit-${params.data._id}`,
974
872
  async (ev) => {
975
873
  ev.preventDefault();
976
-
977
874
  const newTitle = s(`.edit-doc-title-${params.data._id}`).value.trim();
978
875
  const newLocation = s(`.edit-doc-location-${params.data._id}`).value.trim();
979
-
980
876
  // Get file names only if files exist
981
877
  const newMdFileName = hasMdFile ? s(`.edit-doc-md-file-${params.data._id}`)?.value.trim() : null;
982
878
  const newFileName = hasGenericFile ? s(`.edit-doc-file-${params.data._id}`)?.value.trim() : null;
983
-
984
879
  if (!newTitle) {
985
880
  NotificationManager.Push({
986
- html: Translate.Render('error-title-required'),
881
+ html: Translate.instance('error-title-required'),
987
882
  status: 'error',
988
883
  });
989
884
  return;
990
885
  }
991
-
992
886
  const formattedLocation = FileExplorer.locationFormat({ f: { location: newLocation || '/' } });
993
-
994
887
  try {
995
888
  const updateBody = {
996
889
  title: newTitle,
997
890
  location: formattedLocation,
998
891
  };
999
-
1000
892
  // Preserve existing fields from the original document
1001
893
  if (originDoc) {
1002
894
  if (originDoc.fileId) updateBody.fileId = originDoc.fileId._id || originDoc.fileId;
@@ -1004,7 +896,6 @@ const FileExplorer = {
1004
896
  if (originDoc.tags) updateBody.tags = originDoc.tags;
1005
897
  if (typeof originDoc.isPublic !== 'undefined') updateBody.isPublic = originDoc.isPublic;
1006
898
  }
1007
-
1008
899
  // Include file name updates if files exist and names changed
1009
900
  if (hasMdFile && newMdFileName && newMdFileName !== params.data.mdFileName) {
1010
901
  updateBody.mdFileName = newMdFileName;
@@ -1012,23 +903,19 @@ const FileExplorer = {
1012
903
  if (hasGenericFile && newFileName && newFileName !== params.data.fileName) {
1013
904
  updateBody.fileName = newFileName;
1014
905
  }
1015
-
1016
906
  const { data, status } = await DocumentService.put({
1017
907
  id: params.data._id,
1018
908
  body: updateBody,
1019
909
  });
1020
-
1021
910
  if (status === 'success') {
1022
911
  // Check if location changed
1023
912
  const locationChanged = formattedLocation !== params.data.location;
1024
-
1025
913
  // Update local data
1026
914
  params.data.title = newTitle;
1027
915
  params.data.name = newTitle;
1028
916
  params.data.location = formattedLocation;
1029
917
  if (hasMdFile && newMdFileName) params.data.mdFileName = newMdFileName;
1030
918
  if (hasGenericFile && newFileName) params.data.fileName = newFileName;
1031
-
1032
919
  // Update documentInstance
1033
920
  const docIndex = documentInstance.findIndex((d) => d._id === params.data._id);
1034
921
  if (docIndex !== -1) {
@@ -1042,7 +929,6 @@ const FileExplorer = {
1042
929
  documentInstance[docIndex].fileId.name = newFileName;
1043
930
  }
1044
931
  }
1045
-
1046
932
  // Refresh the grid with new location
1047
933
  const format = FileExplorer.documentDataFormat({ document: documentInstance, location });
1048
934
  files = format.files;
@@ -1053,22 +939,18 @@ const FileExplorer = {
1053
939
  AgGrid.grids[gridFileId].setGridOption('rowData', displayedFiles);
1054
940
  AgGrid.grids[gridFolderId].setGridOption('rowData', folders);
1055
941
  updatePaginationUI();
1056
-
1057
942
  NotificationManager.Push({
1058
- html: Translate.Render('success-update-document'),
943
+ html: Translate.instance('success-update-document'),
1059
944
  status: 'success',
1060
945
  });
1061
-
1062
946
  // If location changed, navigate to the new location
1063
947
  if (!s(`.file-explorer-query-nav`)) s(`.main-btn-cloud`).click();
1064
-
1065
948
  if (locationChanged)
1066
949
  setTimeout(() => {
1067
950
  location = formattedLocation;
1068
951
  setPath(`${window.location.pathname}?location=${location}`);
1069
952
  s(`.file-explorer-query-nav`).value = location;
1070
953
  });
1071
-
1072
954
  Modal.removeModal(editModalId);
1073
955
  } else {
1074
956
  throw new Error('Failed to update document');
@@ -1076,14 +958,13 @@ const FileExplorer = {
1076
958
  } catch (error) {
1077
959
  logger.error('Update document failed:', error);
1078
960
  NotificationManager.Push({
1079
- html: Translate.Render('error-update-document'),
961
+ html: Translate.instance('error-update-document'),
1080
962
  status: 'error',
1081
963
  });
1082
964
  }
1083
965
  },
1084
966
  { context: 'modal' },
1085
967
  );
1086
-
1087
968
  // Handle cancel button
1088
969
  EventsUI.onClick(
1089
970
  `.btn-edit-doc-cancel-${params.data._id}`,
@@ -1099,36 +980,30 @@ const FileExplorer = {
1099
980
  );
1100
981
  });
1101
982
  }
1102
-
1103
983
  getGui() {
1104
- return this.eGui;
984
+ return FileExplorer.eGui;
1105
985
  }
1106
-
1107
986
  refresh(params) {
1108
987
  console.log('LoadFileActionsRenderer refreshed', params);
1109
988
  return true;
1110
989
  }
1111
990
  }
1112
-
1113
991
  class LoadFolderActionsRenderer {
1114
992
  eGui;
1115
-
1116
993
  async init(params) {
1117
994
  console.log('LoadFolderActionsRenderer created', params);
1118
995
  // params.data._id
1119
996
  const id = params.data.locationId;
1120
-
1121
- this.eGui = document.createElement('div');
1122
- this.eGui.innerHTML = html`
997
+ FileExplorer.eGui = document.createElement('div');
998
+ FileExplorer.eGui.innerHTML = html`
1123
999
  <div class="fl">
1124
- ${await BtnIcon.Render({
1000
+ ${await BtnIcon.instance({
1125
1001
  class: `in fll management-table-btn-mini btn-folder-delete-${id}`,
1126
1002
  label: html` <i class="fa-solid fa-circle-xmark"></i>`,
1127
1003
  type: 'button',
1128
1004
  })}
1129
1005
  </div>
1130
1006
  `;
1131
-
1132
1007
  setTimeout(() => {
1133
1008
  EventsUI.onClick(
1134
1009
  `.btn-folder-delete-${id}`,
@@ -1137,7 +1012,7 @@ const FileExplorer = {
1137
1012
  html: async () => {
1138
1013
  return html`
1139
1014
  <div class="in section-mp" style="text-align: center">
1140
- ${Translate.Render('confirm-delete-item')}
1015
+ ${Translate.instance('confirm-delete-item')}
1141
1016
  <br />
1142
1017
  "${params.data.location}"
1143
1018
  </div>
@@ -1146,11 +1021,10 @@ const FileExplorer = {
1146
1021
  id: `delete-${id}`,
1147
1022
  });
1148
1023
  if (confirmResult.status !== 'confirm') return;
1149
-
1150
1024
  e.preventDefault();
1151
1025
  const idFilesDelete = [];
1152
1026
  for (const file of documentInstance.filter(
1153
- (f) => FileExplorer.locationFormat({ f }) === params.data.location, // .startsWith(params.data.location),
1027
+ (f) => FileExplorer.locationFormat({ f }) === params.data.location,
1154
1028
  )) {
1155
1029
  {
1156
1030
  const { data, status, message } = await FileService.delete({
@@ -1165,7 +1039,7 @@ const FileExplorer = {
1165
1039
  }
1166
1040
  }
1167
1041
  NotificationManager.Push({
1168
- html: Translate.Render('success-delete'),
1042
+ html: Translate.instance('success-delete'),
1169
1043
  status: 'success',
1170
1044
  });
1171
1045
  documentInstance = documentInstance.filter((f) => !idFilesDelete.includes(f._id));
@@ -1183,62 +1057,59 @@ const FileExplorer = {
1183
1057
  );
1184
1058
  });
1185
1059
  }
1186
-
1187
1060
  getGui() {
1188
- return this.eGui;
1061
+ return FileExplorer.eGui;
1189
1062
  }
1190
-
1191
1063
  refresh(params) {
1192
1064
  console.log('LoadFolderActionsRenderer refreshed', params);
1193
1065
  return true;
1194
1066
  }
1195
1067
  }
1196
-
1197
1068
  return html`
1198
1069
  <form>
1199
1070
  <div class="fl">
1200
- ${await BtnIcon.Render({
1071
+ ${await BtnIcon.instance({
1201
1072
  class: 'in fll management-table-btn-mini btn-input-home-directory',
1202
1073
  label: html`<i class="fas fa-home"></i>
1203
- <!-- ${Translate.Render('home-directory')} -->`,
1074
+ <!-- ${Translate.instance('home-directory')} -->`,
1204
1075
  type: 'button',
1205
1076
  })}
1206
- ${await BtnIcon.Render({
1077
+ ${await BtnIcon.instance({
1207
1078
  class: 'in fll management-table-btn-mini btn-input-back-explorer',
1208
1079
  label: html` <i class="fa-solid fa-circle-left"></i>
1209
- <!-- ${Translate.Render('go')} -->`,
1080
+ <!-- ${Translate.instance('go')} -->`,
1210
1081
  type: 'button',
1211
1082
  })}
1212
- ${await BtnIcon.Render({
1083
+ ${await BtnIcon.instance({
1213
1084
  class: 'in fll management-table-btn-mini btn-input-forward-explorer',
1214
1085
  label: html` <i class="fa-solid fa-circle-right"></i>
1215
- <!-- ${Translate.Render('go')} -->`,
1086
+ <!-- ${Translate.instance('go')} -->`,
1216
1087
  type: 'button',
1217
1088
  })}
1218
- ${await BtnIcon.Render({
1089
+ ${await BtnIcon.instance({
1219
1090
  class: 'in fll management-table-btn-mini btn-input-go-explorer',
1220
1091
  label: html`<i class="fas fa-sync-alt"></i>
1221
- <!-- ${Translate.Render('go')} -->`,
1092
+ <!-- ${Translate.instance('go')} -->`,
1222
1093
  type: 'submit',
1223
1094
  })}
1224
- ${await BtnIcon.Render({
1095
+ ${await BtnIcon.instance({
1225
1096
  class: 'in fll management-table-btn-mini btn-input-copy-directory',
1226
1097
  label: html`<i class="fas fa-copy"></i>
1227
- <!-- ${Translate.Render('home-directory')} -->`,
1098
+ <!-- ${Translate.instance('home-directory')} -->`,
1228
1099
  type: 'button',
1229
1100
  })}
1230
- ${await BtnIcon.Render({
1101
+ ${await BtnIcon.instance({
1231
1102
  class: 'in fll management-table-btn-mini btn-input-upload-file',
1232
1103
  label: html`<i class="fa-solid fa-cloud-arrow-up"></i>
1233
- <!-- ${Translate.Render('home-directory')} -->`,
1104
+ <!-- ${Translate.instance('home-directory')} -->`,
1234
1105
  type: 'button',
1235
1106
  })}
1236
1107
  </div>
1237
1108
  <div class="in">
1238
- ${await Input.Render({
1109
+ ${await Input.instance({
1239
1110
  id: `file-explorer-query-nav`,
1240
1111
  type: 'text',
1241
- label: html`<i class="fab fa-wpexplorer"></i> ${Translate.Render('current-path')}`,
1112
+ label: html`<i class="fab fa-wpexplorer"></i> ${Translate.instance('current-path')}`,
1242
1113
  containerClass: 'in section-mp input-container-width',
1243
1114
  placeholder: true,
1244
1115
  value: location,
@@ -1251,28 +1122,28 @@ const FileExplorer = {
1251
1122
  })}
1252
1123
  <div class="fl file-explorer-search-container">
1253
1124
  <div class="in fll file-explorer-search-col-a">
1254
- ${await Input.Render({
1125
+ ${await Input.instance({
1255
1126
  id: `file-explorer-search-title`,
1256
1127
  type: 'text',
1257
- label: html`<i class="fas fa-search"></i> ${Translate.Render('doc-title')}`,
1128
+ label: html`<i class="fas fa-search"></i> ${Translate.instance('doc-title')}`,
1258
1129
  containerClass: 'in section-mp input-container-width',
1259
1130
  placeholder: true,
1260
1131
  })}
1261
1132
  </div>
1262
1133
  <div class="in fll file-explorer-search-col-b">
1263
- ${await Input.Render({
1134
+ ${await Input.instance({
1264
1135
  id: `file-explorer-search-md-file`,
1265
1136
  type: 'text',
1266
- label: html`<i class="fas fa-file-code"></i> ${Translate.Render('md-file-name')}`,
1137
+ label: html`<i class="fas fa-file-code"></i> ${Translate.instance('md-file-name')}`,
1267
1138
  containerClass: 'in section-mp input-container-width',
1268
1139
  placeholder: true,
1269
1140
  })}
1270
1141
  </div>
1271
1142
  <div class="in fll file-explorer-search-col-c">
1272
- ${await Input.Render({
1143
+ ${await Input.instance({
1273
1144
  id: `file-explorer-search-file`,
1274
1145
  type: 'text',
1275
- label: html`<i class="fas fa-file"></i> ${Translate.Render('generic-file-name')}`,
1146
+ label: html`<i class="fas fa-file"></i> ${Translate.instance('generic-file-name')}`,
1276
1147
  containerClass: 'in section-mp input-container-width',
1277
1148
  placeholder: true,
1278
1149
  })}
@@ -1281,13 +1152,13 @@ const FileExplorer = {
1281
1152
  class="in fll file-explorer-search-col-d"
1282
1153
  style="display: flex; align-items: center; justify-content: center; height: 100%;"
1283
1154
  >
1284
- ${await BtnIcon.Render({
1155
+ ${await BtnIcon.instance({
1285
1156
  class: 'in management-table-btn-mini file-explorer-search-submit',
1286
1157
  label: html`<i class="fas fa-search"></i>`,
1287
1158
  type: 'button',
1288
1159
  style: 'top: 10px; margin-right: 5px;',
1289
1160
  })}
1290
- ${await BtnIcon.Render({
1161
+ ${await BtnIcon.instance({
1291
1162
  class: 'in management-table-btn-mini file-explorer-search-clear',
1292
1163
  label: html`<i class="fas fa-broom"></i>`,
1293
1164
  type: 'button',
@@ -1300,7 +1171,7 @@ const FileExplorer = {
1300
1171
  <div class="in fll explorer-file-col">
1301
1172
  <div class="in explorer-file-sub-col section-mp">
1302
1173
  <div class="in">
1303
- ${await AgGrid.Render({
1174
+ ${await AgGrid.instance({
1304
1175
  id: gridFolderId,
1305
1176
  darkTheme,
1306
1177
  // style: {
@@ -1331,7 +1202,7 @@ const FileExplorer = {
1331
1202
  location = newLocation;
1332
1203
  setPath(`${window.location.pathname}?location=${location}`);
1333
1204
  s(`.file-explorer-query-nav`).value = location;
1334
- const format = this.documentDataFormat({ document: documentInstance, location });
1205
+ const format = FileExplorer.documentDataFormat({ document: documentInstance, location });
1335
1206
  files = format.files;
1336
1207
  folders = format.folders;
1337
1208
  applySearchFilter();
@@ -1370,7 +1241,7 @@ const FileExplorer = {
1370
1241
  location = newLocation;
1371
1242
  setPath(`${window.location.pathname}?location=${location}`);
1372
1243
  s(`.file-explorer-query-nav`).value = location;
1373
- const format = this.documentDataFormat({ document: documentInstance, location });
1244
+ const format = FileExplorer.documentDataFormat({ document: documentInstance, location });
1374
1245
  files = format.files;
1375
1246
  folders = format.folders;
1376
1247
  applySearchFilter();
@@ -1389,7 +1260,7 @@ const FileExplorer = {
1389
1260
  <div class="in fll explorer-file-col">
1390
1261
  <div class="in explorer-file-sub-col section-mp">
1391
1262
  <div class="in">
1392
- ${await AgGrid.Render({
1263
+ ${await AgGrid.instance({
1393
1264
  id: gridFileId,
1394
1265
  darkTheme,
1395
1266
  // style: {
@@ -1421,9 +1292,9 @@ const FileExplorer = {
1421
1292
  </div>
1422
1293
  <div class="fl file-explorer-pagination" style="padding: 5px 0;">
1423
1294
  <div class="in fll" style="width: 33.33%;">
1424
- ${await BtnIcon.Render({
1295
+ ${await BtnIcon.instance({
1425
1296
  class: 'in wfa file-explorer-prev-btn',
1426
- label: html`<i class="fa-solid fa-chevron-left"></i> ${Translate.Render('previous')}`,
1297
+ label: html`<i class="fa-solid fa-chevron-left"></i> ${Translate.instance('previous')}`,
1427
1298
  type: 'button',
1428
1299
  })}
1429
1300
  </div>
@@ -1435,9 +1306,9 @@ const FileExplorer = {
1435
1306
  >
1436
1307
  </div>
1437
1308
  <div class="in fll" style="width: 33.33%;">
1438
- ${await BtnIcon.Render({
1309
+ ${await BtnIcon.instance({
1439
1310
  class: 'in wfa file-explorer-next-btn',
1440
- label: html`${Translate.Render('next')} <i class="fa-solid fa-chevron-right"></i>`,
1311
+ label: html`${Translate.instance('next')} <i class="fa-solid fa-chevron-right"></i>`,
1441
1312
  type: 'button',
1442
1313
  })}
1443
1314
  </div>
@@ -1446,7 +1317,7 @@ const FileExplorer = {
1446
1317
  </div>
1447
1318
  </div>
1448
1319
  <form class="file-explorer-uploader" style="display: none">
1449
- ${await InputFile.Render(
1320
+ ${await InputFile.instance(
1450
1321
  {
1451
1322
  id: idDropFileInput,
1452
1323
  multiple: true,
@@ -1463,7 +1334,7 @@ const FileExplorer = {
1463
1334
  },
1464
1335
  )}
1465
1336
  <div class="in">
1466
- ${await BtnIcon.Render({
1337
+ ${await BtnIcon.instance({
1467
1338
  class: 'wfa section-mp btn-input-file-explorer',
1468
1339
  style: renderCssAttr({
1469
1340
  style: {
@@ -1472,22 +1343,22 @@ const FileExplorer = {
1472
1343
  padding: '20px',
1473
1344
  },
1474
1345
  }),
1475
- label: html`<i class="fa-solid fa-cloud-arrow-up"></i> ${Translate.Render('upload')}`,
1346
+ label: html`<i class="fa-solid fa-cloud-arrow-up"></i> ${Translate.instance('upload')}`,
1476
1347
  type: 'submit',
1477
1348
  })}
1478
1349
  </div>
1479
1350
  </form>
1480
1351
  `;
1481
- },
1482
- locationFormat: function ({ f }) {
1352
+ }
1353
+ static locationFormat({ f }) {
1483
1354
  if (f.location[0] !== '/') f.location = `/${f.location}`;
1484
1355
  if (f.location !== '/' && f.location[f.location.length - 1] === '/') f.location = f.location.slice(0, -1);
1485
1356
  return f.location;
1486
- },
1487
- documentDataFormat: function ({ document, location, searchFilters }) {
1357
+ }
1358
+ static documentDataFormat({ document, location, searchFilters }) {
1488
1359
  let files = document.map((f) => {
1489
1360
  return {
1490
- location: this.locationFormat({ f }),
1361
+ location: FileExplorer.locationFormat({ f }),
1491
1362
  name: f.title,
1492
1363
  mdFileName: f.mdFileId?.name || '',
1493
1364
  fileName: f.fileId?.name || '',
@@ -1511,9 +1382,7 @@ const FileExplorer = {
1511
1382
  locationId: `loc-${i}`,
1512
1383
  };
1513
1384
  });
1514
-
1515
1385
  const isSearching = searchFilters && (searchFilters.title || searchFilters.mdFile || searchFilters.file);
1516
-
1517
1386
  if (!isSearching) {
1518
1387
  files = files.filter((f) => f.location === location);
1519
1388
  folders = folders
@@ -1532,7 +1401,6 @@ const FileExplorer = {
1532
1401
  .filter((f) => f.fileCount > 0);
1533
1402
  }
1534
1403
  return { files, documentId, folders };
1535
- },
1536
- };
1537
-
1404
+ }
1405
+ }
1538
1406
  export { FileExplorer };