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
@@ -4,42 +4,37 @@
4
4
  * @module src/client/components/core/FullScreen.js
5
5
  * @namespace FullScreenClient
6
6
  */
7
-
8
7
  import { Responsive } from './Responsive.js';
9
8
  import { ToggleSwitch } from './ToggleSwitch.js';
10
9
  import { Translate } from './Translate.js';
11
10
  import { checkFullScreen, fullScreenIn, fullScreenOut, s } from './VanillaJs.js';
12
-
13
11
  /**
14
12
  * Manages fullscreen mode state, event handling, and UI synchronization.
15
13
  * Supports all major browsers and PWA/Nativefier environments with comprehensive
16
14
  * vendor-prefixed API detection.
17
15
  * @memberof FullScreenClient
18
16
  */
19
- const FullScreen = {
17
+ class FullScreen {
20
18
  /**
21
19
  * Internal state flag tracking the intended fullscreen mode.
22
20
  * @type {boolean}
23
21
  * @private
24
22
  */
25
- _fullScreenSwitch: false,
26
-
23
+ static _fullScreenSwitch = false;
27
24
  /**
28
25
  * Flag indicating whether event listeners have been attached.
29
26
  * Prevents duplicate event listener registration.
30
27
  * @type {boolean}
31
28
  * @private
32
29
  */
33
- _eventListenersAdded: false,
34
-
30
+ static _eventListenersAdded = false;
35
31
  /**
36
32
  * Flag preventing concurrent sync operations.
37
33
  * Ensures state synchronization happens sequentially.
38
34
  * @type {boolean}
39
35
  * @private
40
36
  */
41
- _syncInProgress: false,
42
-
37
+ static _syncInProgress = false;
43
38
  /**
44
39
  * Checks if the browser is currently in fullscreen mode.
45
40
  * Supports all vendor-prefixed fullscreen APIs for maximum compatibility:
@@ -51,7 +46,7 @@ const FullScreen = {
51
46
  * @memberof FullScreenClient.FullScreen
52
47
  * @returns {boolean} True if currently in fullscreen mode, false otherwise.
53
48
  */
54
- _isFullScreen: function () {
49
+ static _isFullScreen() {
55
50
  return !!(
56
51
  document.fullscreenElement ||
57
52
  document.webkitFullscreenElement ||
@@ -61,8 +56,7 @@ const FullScreen = {
61
56
  document.webkitIsFullScreen ||
62
57
  document.mozFullScreen
63
58
  );
64
- },
65
-
59
+ }
66
60
  /**
67
61
  * Synchronizes the toggle switch UI state with the actual fullscreen state.
68
62
  * Prevents race conditions using the _syncInProgress flag.
@@ -71,16 +65,13 @@ const FullScreen = {
71
65
  * @memberof FullScreenClient.FullScreen
72
66
  * @returns {void}
73
67
  */
74
- _syncToggleState: function () {
75
- if (this._syncInProgress) return;
76
- this._syncInProgress = true;
77
-
78
- const actualFullScreen = this._isFullScreen();
79
-
68
+ static _syncToggleState() {
69
+ if (FullScreen._syncInProgress) return;
70
+ FullScreen._syncInProgress = true;
71
+ const actualFullScreen = FullScreen._isFullScreen();
80
72
  // Only update if there's a mismatch
81
- if (this._fullScreenSwitch !== actualFullScreen) {
82
- this._fullScreenSwitch = actualFullScreen;
83
-
73
+ if (FullScreen._fullScreenSwitch !== actualFullScreen) {
74
+ FullScreen._fullScreenSwitch = actualFullScreen;
84
75
  // Update toggle switch UI if it exists
85
76
  const toggle = s('.fullscreen');
86
77
  if (toggle && ToggleSwitch.Tokens[`fullscreen`]) {
@@ -90,12 +81,10 @@ const FullScreen = {
90
81
  }
91
82
  }
92
83
  }
93
-
94
84
  setTimeout(() => {
95
- this._syncInProgress = false;
85
+ FullScreen._syncInProgress = false;
96
86
  }, 100);
97
- },
98
-
87
+ }
99
88
  /**
100
89
  * Event handler for fullscreen change events.
101
90
  * Triggers UI state synchronization when fullscreen mode changes.
@@ -103,10 +92,9 @@ const FullScreen = {
103
92
  * @memberof FullScreenClient.FullScreen
104
93
  * @returns {void}
105
94
  */
106
- _handleFullScreenChange: function () {
107
- this._syncToggleState();
108
- },
109
-
95
+ static _handleFullScreenChange() {
96
+ FullScreen._syncToggleState();
97
+ }
110
98
  /**
111
99
  * Attaches all necessary event listeners for fullscreen mode detection.
112
100
  * Handles multiple scenarios:
@@ -118,38 +106,32 @@ const FullScreen = {
118
106
  * @memberof FullScreenClient.FullScreen
119
107
  * @returns {void}
120
108
  */
121
- _addEventListeners: function () {
122
- if (this._eventListenersAdded) return;
123
-
109
+ static _addEventListeners() {
110
+ if (FullScreen._eventListenersAdded) return;
124
111
  const events = ['fullscreenchange', 'webkitfullscreenchange', 'mozfullscreenchange', 'MSFullscreenChange'];
125
-
126
112
  events.forEach((eventName) => {
127
- document.addEventListener(eventName, () => this._handleFullScreenChange(), false);
113
+ document.addEventListener(eventName, () => FullScreen._handleFullScreenChange(), false);
128
114
  });
129
-
130
115
  // Additional check for PWA/Nativefier window resize events
131
116
  window.addEventListener(
132
117
  'resize',
133
118
  () => {
134
- setTimeout(() => this._syncToggleState(), 150);
119
+ setTimeout(() => FullScreen._syncToggleState(), 150);
135
120
  },
136
121
  false,
137
122
  );
138
-
139
123
  // ESC key detection fallback
140
124
  document.addEventListener(
141
125
  'keydown',
142
126
  (e) => {
143
127
  if (e.key === 'Escape' || e.keyCode === 27) {
144
- setTimeout(() => this._syncToggleState(), 100);
128
+ setTimeout(() => FullScreen._syncToggleState(), 100);
145
129
  }
146
130
  },
147
131
  false,
148
132
  );
149
-
150
- this._eventListenersAdded = true;
151
- },
152
-
133
+ FullScreen._eventListenersAdded = true;
134
+ }
153
135
  /**
154
136
  * Enters fullscreen mode if not already in fullscreen.
155
137
  * Updates internal state and triggers fullscreen API.
@@ -158,16 +140,13 @@ const FullScreen = {
158
140
  * @memberof FullScreenClient.FullScreen
159
141
  * @returns {void}
160
142
  */
161
- _enterFullScreen: function () {
162
- if (this._isFullScreen()) return;
163
-
164
- this._fullScreenSwitch = true;
143
+ static _enterFullScreen() {
144
+ if (FullScreen._isFullScreen()) return;
145
+ FullScreen._fullScreenSwitch = true;
165
146
  fullScreenIn();
166
-
167
147
  // Verify after attempt
168
- setTimeout(() => this._syncToggleState(), 300);
169
- },
170
-
148
+ setTimeout(() => FullScreen._syncToggleState(), 300);
149
+ }
171
150
  /**
172
151
  * Exits fullscreen mode if currently in fullscreen.
173
152
  * Updates internal state and triggers fullscreen exit API.
@@ -176,16 +155,13 @@ const FullScreen = {
176
155
  * @memberof FullScreenClient.FullScreen
177
156
  * @returns {void}
178
157
  */
179
- _exitFullScreen: function () {
180
- if (!this._isFullScreen()) return;
181
-
182
- this._fullScreenSwitch = false;
158
+ static _exitFullScreen() {
159
+ if (!FullScreen._isFullScreen()) return;
160
+ FullScreen._fullScreenSwitch = false;
183
161
  fullScreenOut();
184
-
185
162
  // Verify after attempt
186
- setTimeout(() => this._syncToggleState(), 300);
187
- },
188
-
163
+ setTimeout(() => FullScreen._syncToggleState(), 300);
164
+ }
189
165
  /**
190
166
  * Renders the fullscreen toggle setting UI component.
191
167
  * Initializes fullscreen state detection, sets up event listeners,
@@ -194,36 +170,32 @@ const FullScreen = {
194
170
  * @memberof FullScreenClient.FullScreen
195
171
  * @returns {Promise<string>} A promise resolving to the HTML string for the fullscreen setting component.
196
172
  */
197
- RenderSetting: async function () {
173
+ static async RenderSetting() {
198
174
  // Initialize state from actual fullscreen status
199
- this._fullScreenSwitch = this._isFullScreen();
200
-
175
+ FullScreen._fullScreenSwitch = FullScreen._isFullScreen();
201
176
  // Setup event listeners once
202
- this._addEventListeners();
203
-
177
+ FullScreen._addEventListeners();
204
178
  // Update responsive event
205
- Responsive.Event['full-screen-settings'] = () => {
206
- this._syncToggleState();
207
- };
208
-
179
+ Responsive.onChanged(() => {
180
+ FullScreen._syncToggleState();
181
+ }, { key: 'full-screen-settings' });
209
182
  return html`<div class="in section-mp">
210
- ${await ToggleSwitch.Render({
183
+ ${await ToggleSwitch.instance({
211
184
  wrapper: true,
212
- wrapperLabel: html`<i class="fa-solid fa-expand"></i> ${Translate.Render('fullscreen')}`,
185
+ wrapperLabel: html`<i class="fa-solid fa-expand"></i> ${Translate.instance('fullscreen')}`,
213
186
  id: 'fullscreen',
214
187
  disabledOnClick: true,
215
- checked: this._fullScreenSwitch,
188
+ checked: FullScreen._fullScreenSwitch,
216
189
  on: {
217
190
  unchecked: () => {
218
- this._exitFullScreen();
191
+ FullScreen._exitFullScreen();
219
192
  },
220
193
  checked: () => {
221
- this._enterFullScreen();
194
+ FullScreen._enterFullScreen();
222
195
  },
223
196
  },
224
197
  })}
225
198
  </div>`;
226
- },
227
- };
228
-
199
+ }
200
+ }
229
201
  export { FullScreen };
@@ -5,7 +5,6 @@
5
5
  * @module src/client/components/core/Input.js
6
6
  * @namespace InputClient
7
7
  */
8
-
9
8
  import { AgGrid } from './AgGrid.js';
10
9
  import { BtnIcon } from './BtnIcon.js';
11
10
  import { isValidDate } from './CommonJs.js';
@@ -18,7 +17,6 @@ import { Translate } from './Translate.js';
18
17
  import { htmls, htmlStrSanitize, s } from './VanillaJs.js';
19
18
  import { getApiBaseUrl } from '../../services/core/core.service.js';
20
19
  import { FileService } from '../../services/file/file.service.js';
21
-
22
20
  /**
23
21
  * Logger instance for this module.
24
22
  * @type {Function}
@@ -26,7 +24,6 @@ import { FileService } from '../../services/file/file.service.js';
26
24
  * @private
27
25
  */
28
26
  const logger = loggerFactory(import.meta);
29
-
30
27
  /**
31
28
  * Creates a FormData object from file input event.
32
29
  * Filters files by extension if provided.
@@ -49,7 +46,6 @@ const fileFormDataFactory = (e, extensions) => {
49
46
  }
50
47
  return form;
51
48
  };
52
-
53
49
  /**
54
50
  * Convert file data to File object.
55
51
  * Supports both legacy format (with buffer data) and new format (metadata only).
@@ -72,7 +68,6 @@ const getFileFromFileData = (fileData) => {
72
68
  logger.error('getFileFromFileData: fileData is undefined');
73
69
  return null;
74
70
  }
75
-
76
71
  // Check if this is legacy format with buffer data
77
72
  if (fileData.data?.data) {
78
73
  try {
@@ -83,7 +78,6 @@ const getFileFromFileData = (fileData) => {
83
78
  return null;
84
79
  }
85
80
  }
86
-
87
81
  // New format - metadata only, cannot create File without content
88
82
  // Return null and let caller fetch from blob endpoint if needed
89
83
  if (fileData._id && !fileData.data?.data) {
@@ -93,11 +87,9 @@ const getFileFromFileData = (fileData) => {
93
87
  );
94
88
  return null;
95
89
  }
96
-
97
90
  logger.error('getFileFromFileData: Invalid file data structure', fileData);
98
91
  return null;
99
92
  };
100
-
101
93
  /**
102
94
  * Fetch file content from blob endpoint and create File object.
103
95
  * Used for metadata-only format files during edit mode.
@@ -116,14 +108,12 @@ const getFileFromBlobEndpoint = async (fileData) => {
116
108
  if (!fileData || !fileData._id) {
117
109
  return null;
118
110
  }
119
-
120
111
  try {
121
112
  const { data: blobArray, status } = await FileService.get({ id: `blob/${fileData._id}` });
122
113
  if (status !== 'success' || !blobArray || !blobArray[0]) {
123
114
  logger.error('Failed to fetch file from blob endpoint');
124
115
  return null;
125
116
  }
126
-
127
117
  const blob = blobArray[0];
128
118
  return new File([blob], fileData.name || 'file', { type: fileData.mimetype || blob.type });
129
119
  } catch (error) {
@@ -131,7 +121,6 @@ const getFileFromBlobEndpoint = async (fileData) => {
131
121
  return null;
132
122
  }
133
123
  };
134
-
135
124
  /**
136
125
  * Get image/file source URL from file data.
137
126
  * Supports both legacy format (with buffer) and new format (metadata only).
@@ -151,7 +140,6 @@ const getSrcFromFileData = (fileData) => {
151
140
  logger.error('getSrcFromFileData: fileData is undefined');
152
141
  return null;
153
142
  }
154
-
155
143
  // Legacy format with buffer data - create object URL
156
144
  if (fileData.data?.data) {
157
145
  try {
@@ -163,7 +151,6 @@ const getSrcFromFileData = (fileData) => {
163
151
  logger.error('Error getting src from legacy buffer data:', error);
164
152
  }
165
153
  }
166
-
167
154
  // New format - use blob endpoint
168
155
  if (fileData._id) {
169
156
  try {
@@ -173,22 +160,20 @@ const getSrcFromFileData = (fileData) => {
173
160
  return null;
174
161
  }
175
162
  }
176
-
177
163
  logger.error('getSrcFromFileData: Cannot generate src, invalid file data:', fileData);
178
164
  return null;
179
165
  };
180
-
181
166
  /**
182
167
  * Input component for rendering various form input types.
183
168
  * Supports text, password, file, color, date, dropdown, toggle, rich text, and grid inputs.
184
169
  * @namespace InputClient.Input
185
170
  * @memberof InputClient
186
171
  */
187
- const Input = {
172
+ class Input {
188
173
  /**
189
174
  * Renders an input element based on the provided options.
190
175
  * @async
191
- * @function Render
176
+ * @function instance
192
177
  * @memberof InputClient.Input
193
178
  * @param {Object} options - Input configuration options.
194
179
  * @param {string} options.id - Unique identifier for the input.
@@ -200,7 +185,7 @@ const Input = {
200
185
  * @param {boolean} [options.disabled] - Whether the input is disabled.
201
186
  * @returns {Promise<string>} HTML string for the input component.
202
187
  */
203
- Render: async function (options) {
188
+ static async instance(options) {
204
189
  const { id } = options;
205
190
  options?.placeholder
206
191
  ? options.placeholder === true
@@ -213,7 +198,6 @@ const Input = {
213
198
  ['color', 'file'].includes(options.type) ? s(`.${id}`).click() : s(`.${id}`).focus();
214
199
  ['datetime-local'].includes(options.type) ? s(`.${id}`).showPicker() : s(`.${id}`).focus();
215
200
  };
216
-
217
201
  if (s(`.btn-eye-${id}`))
218
202
  s(`.btn-eye-${id}`).onclick = () => {
219
203
  if (s(`.fa-eye-slash-${id}`).style.display === 'none') {
@@ -227,9 +211,7 @@ const Input = {
227
211
  s(`.${id}`).type = 'password';
228
212
  };
229
213
  });
230
-
231
214
  const labelValue = htmlStrSanitize(options.label) ? htmlStrSanitize(options.label) : id;
232
-
233
215
  const inputElement = html` <label for="${id}-name">
234
216
  <span class="hide">${labelValue}</span>
235
217
  <input
@@ -252,7 +234,6 @@ const Input = {
252
234
  <div class="${id}-input-extension input-info input-extension ${options?.extension ? '' : 'hide'}">
253
235
  ${options?.extension ? await options.extension() : ''}
254
236
  </div>`;
255
-
256
237
  return html` <div class="${options?.containerClass ? options.containerClass + ' ' : ''} input-container-${id}">
257
238
  <div class="in">
258
239
  ${options?.label ? html`<div class="in input-label input-label-${id}">${options.label}</div>` : ''}
@@ -274,15 +255,15 @@ const Input = {
274
255
  <div class="in input-info input-info-${id}">&nbsp</div>
275
256
  </div>
276
257
  </div>`;
277
- },
278
- parseJson: (selector) => {
258
+ }
259
+ static parseJson = (selector) => {
279
260
  try {
280
261
  return JSON.parse(s(selector).value);
281
262
  } catch (error) {
282
263
  return s(selector).value;
283
264
  }
284
- },
285
- getValues: function (formData) {
265
+ };
266
+ static getValues(formData) {
286
267
  const obj = {};
287
268
  for (const inputData of formData) {
288
269
  if (inputData.disableRender) continue;
@@ -297,11 +278,9 @@ const Input = {
297
278
  case 'checkbox-on-off':
298
279
  obj[inputData.model] = s(`.${inputData.id}-checkbox`).checked;
299
280
  continue;
300
-
301
281
  default:
302
282
  break;
303
283
  }
304
-
305
284
  if (!s(`.${inputData.id}`) || !s(`.${inputData.id}`).value || s(`.${inputData.id}`).value === 'undefined')
306
285
  continue;
307
286
  if ('model' in inputData) {
@@ -309,17 +288,15 @@ const Input = {
309
288
  }
310
289
  }
311
290
  return obj;
312
- },
313
- cleanValues: function (formData) {
291
+ }
292
+ static cleanValues(formData) {
314
293
  const obj = {};
315
294
  for (const inputData of formData) {
316
295
  if (!s(`.${inputData.id}`)) continue;
317
-
318
296
  switch (inputData.inputType) {
319
297
  case 'file':
320
298
  s(`.${inputData.id}`).inputFiles = undefined;
321
299
  s(`.${inputData.id}`).value = null;
322
-
323
300
  if (s(`.file-name-render-${inputData.id}`) && s(`.${inputData.id}`).fileNameInputExtDefaultContent)
324
301
  htmls(`.file-name-render-${inputData.id}`, `${s(`.${inputData.id}`).fileNameInputExtDefaultContent}`);
325
302
  continue;
@@ -339,60 +316,49 @@ const Input = {
339
316
  if (s(`.${inputData.id}-checkbox`).checked) ToggleSwitch.Tokens[inputData.id].click();
340
317
  continue;
341
318
  break;
342
-
343
319
  default:
344
320
  break;
345
321
  }
346
-
347
322
  if ('model' in inputData) {
348
323
  if (!['dropdown'].includes(inputData.inputType)) s(`.${inputData.id}`).value = '';
349
324
  }
350
325
  if (s(`.input-info-${inputData.id}`)) htmls(`.input-info-${inputData.id}`, html`&nbsp`);
351
326
  }
352
327
  return obj;
353
- },
354
- setValues: async function (formData, obj, originObj, fileObj) {
328
+ }
329
+ static async setValues(formData, obj, originObj, fileObj) {
355
330
  setTimeout(async () => {
356
331
  for (const inputData of formData) {
357
332
  if (!s(`.${inputData.id}`)) continue;
358
-
359
333
  switch (inputData.inputType) {
360
334
  case 'file':
361
335
  if (fileObj && fileObj[inputData.model] && s(`.${inputData.id}`)) {
362
336
  const dataTransfer = new DataTransfer();
363
-
364
337
  if (fileObj[inputData.model].fileBlob) {
365
338
  let fileBlobData = getFileFromFileData(fileObj[inputData.model].fileBlob);
366
-
367
339
  // If fileBlob is metadata-only, try to fetch from blob endpoint
368
340
  if (!fileBlobData && fileObj[inputData.model].fileBlob?._id) {
369
341
  fileBlobData = await getFileFromBlobEndpoint(fileObj[inputData.model].fileBlob);
370
342
  }
371
-
372
343
  if (fileBlobData) {
373
344
  dataTransfer.items.add(fileBlobData);
374
345
  }
375
346
  }
376
-
377
347
  if (fileObj[inputData.model].mdBlob) {
378
348
  let mdBlobData = getFileFromFileData(fileObj[inputData.model].mdBlob);
379
-
380
349
  // If mdBlob is metadata-only, try to fetch from blob endpoint
381
350
  if (!mdBlobData && fileObj[inputData.model].mdBlob?._id) {
382
351
  mdBlobData = await getFileFromBlobEndpoint(fileObj[inputData.model].mdBlob);
383
352
  }
384
-
385
353
  if (mdBlobData) {
386
354
  dataTransfer.items.add(mdBlobData);
387
355
  }
388
356
  }
389
-
390
357
  if (dataTransfer.files.length) {
391
358
  s(`.${inputData.id}`).files = dataTransfer.files;
392
359
  s(`.${inputData.id}`).onchange({ target: s(`.${inputData.id}`) });
393
360
  }
394
361
  }
395
-
396
362
  continue;
397
363
  break;
398
364
  case 'md':
@@ -401,7 +367,6 @@ const Input = {
401
367
  }
402
368
  continue;
403
369
  break;
404
-
405
370
  case 'dropdown-checkbox': {
406
371
  s(`.dropdown-option-${inputData.id}-reset`).click();
407
372
  for (const opt of originObj[inputData.model]) s(`.dropdown-option-${inputData.id}-${opt}`).click();
@@ -429,18 +394,16 @@ const Input = {
429
394
  default:
430
395
  break;
431
396
  }
432
-
433
397
  if ('model' in inputData) {
434
398
  if (!['dropdown'].includes(inputData.inputType)) s(`.${inputData.id}`).value = obj[inputData.model];
435
399
  }
436
400
  if (s(`.input-info-${inputData.id}`)) htmls(`.input-info-${inputData.id}`, html`&nbsp`);
437
401
  }
438
402
  });
439
- },
440
- };
441
-
442
- const InputFile = {
443
- Render: async function (
403
+ }
404
+ }
405
+ class InputFile {
406
+ static async instance(
444
407
  options = { id: '', multiple: false, extensionsAccept: [] },
445
408
  on = { change: () => {}, clear: () => {} },
446
409
  ) {
@@ -455,7 +418,6 @@ const InputFile = {
455
418
  AgGrid.grids[gridId].setGridOption('rowData', []);
456
419
  if (on && typeof on.clear === 'function') on.clear();
457
420
  };
458
-
459
421
  ['drag', 'dragstart', 'dragend', 'dragover', 'dragenter', 'dragleave', 'drop'].forEach(function (event) {
460
422
  s(`.drop-zone-${id}`).addEventListener(event, function (e) {
461
423
  e.preventDefault();
@@ -465,25 +427,23 @@ const InputFile = {
465
427
  s(`.drop-zone-${id}`).addEventListener(
466
428
  'dragover',
467
429
  function (e) {
468
- this.classList.add('drop-hover-container');
430
+ InputFile.classList.add('drop-hover-container');
469
431
  },
470
432
  false,
471
433
  );
472
-
473
434
  s(`.drop-zone-${id}`).addEventListener(
474
435
  'dragleave',
475
436
  function (e) {
476
- this.classList.remove('drop-hover-container');
437
+ InputFile.classList.remove('drop-hover-container');
477
438
  },
478
439
  false,
479
440
  );
480
441
  s(`.drop-zone-${id}`).addEventListener(
481
442
  'drop',
482
443
  function (e) {
483
- this.classList.remove('drop-hover-container');
444
+ InputFile.classList.remove('drop-hover-container');
484
445
  const files = e.dataTransfer.files;
485
446
  const dataTransfer = new DataTransfer();
486
-
487
447
  let countFiles = 0;
488
448
  Array.prototype.forEach.call(files, (file) => {
489
449
  // logger.info(file);
@@ -491,17 +451,14 @@ const InputFile = {
491
451
  dataTransfer.items.add(file);
492
452
  countFiles++;
493
453
  });
494
-
495
454
  s(`.${id}`).files = dataTransfer.files;
496
455
  s(`.${id}`).onchange({ target: s(`.${id}`) });
497
456
  },
498
457
  false,
499
458
  );
500
-
501
459
  s(`.drop-zone-${id}`).addEventListener('click', function (e) {
502
460
  s(`.${id}`).click();
503
461
  });
504
-
505
462
  s(`.${id}`).onchange = (e) => {
506
463
  // logger.info('e', e);
507
464
  const fileGridData = [];
@@ -530,13 +487,13 @@ const InputFile = {
530
487
  ${extensionsAccept.length > 0 ? `accept="${extensionsAccept.join(', ')}"` : ''}
531
488
  />
532
489
  <div class="in">
533
- ${await BtnIcon.Render({
490
+ ${await BtnIcon.instance({
534
491
  class: `wfa btn-clear-input-file-${id}`,
535
- label: `<i class="fa-solid fa-broom"></i> ${Translate.Render('clear')}`,
492
+ label: `<i class="fa-solid fa-broom"></i> ${Translate.instance('clear')}`,
536
493
  })}
537
494
  </div>
538
495
  <div class="in">
539
- ${await AgGrid.Render({
496
+ ${await AgGrid.instance({
540
497
  id: gridId,
541
498
  darkTheme,
542
499
  style: {
@@ -558,19 +515,17 @@ const InputFile = {
558
515
  <div class="in section-mp input-file-sub-col drop-zone-${id}">
559
516
  <div class="abs center">
560
517
  <i class="fas fa-cloud" style="font-size: 30px"></i><br />
561
- ${Translate.Render('drop-file')}
518
+ ${Translate.instance('drop-file')}
562
519
  </div>
563
520
  </div>
564
521
  </div>
565
522
  </div>`;
566
- },
567
- };
568
-
523
+ }
524
+ }
569
525
  function isTextInputFocused() {
570
526
  const active = document.activeElement;
571
527
  return active && (active.tagName === 'INPUT' || active.tagName === 'TEXTAREA');
572
528
  }
573
-
574
529
  export {
575
530
  Input,
576
531
  InputFile,