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.
- package/.github/workflows/release.cd.yml +1 -2
- package/CHANGELOG.md +251 -1
- package/CLI-HELP.md +26 -13
- package/Dockerfile +0 -4
- package/README.md +3 -3
- package/bin/build.js +13 -3
- package/bin/deploy.js +570 -1
- package/bin/file.js +5 -0
- package/conf.js +11 -2
- package/jsconfig.json +1 -1
- package/manifests/cronjobs/dd-cron/dd-cron-backup.yaml +1 -1
- package/manifests/cronjobs/dd-cron/dd-cron-dns.yaml +1 -1
- package/manifests/deployment/dd-default-development/deployment.yaml +2 -6
- package/manifests/deployment/dd-test-development/deployment.yaml +136 -66
- package/manifests/deployment/dd-test-development/proxy.yaml +41 -5
- package/package.json +20 -11
- package/src/api/core/core.controller.js +10 -10
- package/src/api/core/core.service.js +10 -10
- package/src/api/default/default.controller.js +10 -10
- package/src/api/default/default.service.js +10 -10
- package/src/api/document/document.controller.js +12 -12
- package/src/api/document/document.model.js +10 -16
- package/src/api/file/file.controller.js +8 -8
- package/src/api/file/file.model.js +10 -10
- package/src/api/file/file.service.js +36 -36
- package/src/api/test/test.controller.js +8 -8
- package/src/api/test/test.service.js +8 -8
- package/src/api/user/guest.service.js +99 -0
- package/src/api/user/user.controller.js +6 -6
- package/src/api/user/user.model.js +8 -13
- package/src/api/user/user.service.js +3 -20
- package/src/cli/deploy.js +33 -30
- package/src/cli/fs.js +62 -5
- package/src/cli/image.js +43 -1
- package/src/cli/index.js +5 -1
- package/src/cli/release.js +57 -1
- package/src/cli/repository.js +35 -3
- package/src/cli/run.js +300 -35
- package/src/cli/ssh.js +1 -1
- package/src/cli/static.js +43 -115
- package/src/client/Default.index.js +21 -33
- package/src/client/components/core/404.js +4 -4
- package/src/client/components/core/500.js +4 -4
- package/src/client/components/core/Account.js +73 -60
- package/src/client/components/core/AgGrid.js +23 -33
- package/src/client/components/core/Alert.js +12 -13
- package/src/client/components/core/AppStore.js +1 -1
- package/src/client/components/core/Auth.js +20 -32
- package/src/client/components/core/Badge.js +7 -13
- package/src/client/components/core/BtnIcon.js +15 -17
- package/src/client/components/core/CalendarCore.js +42 -63
- package/src/client/components/core/Chat.js +13 -15
- package/src/client/components/core/ClientEvents.js +87 -0
- package/src/client/components/core/ColorPaletteElement.js +309 -0
- package/src/client/components/core/Content.js +17 -14
- package/src/client/components/core/Css.js +15 -71
- package/src/client/components/core/CssCore.js +12 -16
- package/src/client/components/core/D3Chart.js +4 -4
- package/src/client/components/core/Docs.js +60 -59
- package/src/client/components/core/DropDown.js +69 -91
- package/src/client/components/core/EventBus.js +92 -0
- package/src/client/components/core/EventsUI.js +14 -17
- package/src/client/components/core/FileExplorer.js +102 -234
- package/src/client/components/core/FullScreen.js +47 -75
- package/src/client/components/core/Input.js +24 -69
- package/src/client/components/core/Keyboard.js +25 -18
- package/src/client/components/core/KeyboardAvoidance.js +145 -0
- package/src/client/components/core/LoadingAnimation.js +25 -31
- package/src/client/components/core/LogIn.js +41 -41
- package/src/client/components/core/LogOut.js +23 -14
- package/src/client/components/core/Modal.js +397 -176
- package/src/client/components/core/NotificationManager.js +14 -18
- package/src/client/components/core/Panel.js +54 -50
- package/src/client/components/core/PanelForm.js +25 -125
- package/src/client/components/core/Polyhedron.js +110 -214
- package/src/client/components/core/PublicProfile.js +39 -32
- package/src/client/components/core/Recover.js +52 -48
- package/src/client/components/core/Responsive.js +88 -32
- package/src/client/components/core/RichText.js +9 -18
- package/src/client/components/core/Router.js +24 -3
- package/src/client/components/core/SearchBox.js +37 -37
- package/src/client/components/core/SignUp.js +39 -30
- package/src/client/components/core/SocketIo.js +31 -2
- package/src/client/components/core/SocketIoHandler.js +6 -6
- package/src/client/components/core/ToggleSwitch.js +8 -20
- package/src/client/components/core/ToolTip.js +5 -17
- package/src/client/components/core/Translate.js +56 -59
- package/src/client/components/core/Validator.js +26 -16
- package/src/client/components/core/Wallet.js +15 -26
- package/src/client/components/core/Worker.js +140 -25
- package/src/client/components/core/windowGetDimensions.js +7 -7
- package/src/client/components/default/{MenuDefault.js → AppShellDefault.js} +87 -87
- package/src/client/components/default/CssDefault.js +12 -12
- package/src/client/components/default/LogInDefault.js +6 -4
- package/src/client/components/default/LogOutDefault.js +6 -4
- package/src/client/components/default/RouterDefault.js +47 -0
- package/src/client/components/default/SettingsDefault.js +4 -4
- package/src/client/components/default/SignUpDefault.js +6 -4
- package/src/client/components/default/TranslateDefault.js +3 -3
- package/src/client/services/core/core.service.js +17 -49
- package/src/client/services/default/default.management.js +139 -242
- package/src/client/services/default/default.service.js +10 -16
- package/src/client/services/document/document.service.js +14 -19
- package/src/client/services/file/file.service.js +8 -13
- package/src/client/services/test/test.service.js +8 -13
- package/src/client/services/user/guest.service.js +79 -0
- package/src/client/services/user/user.management.js +5 -5
- package/src/client/services/user/user.service.js +14 -20
- package/src/client/ssr/body/404.js +3 -3
- package/src/client/ssr/body/500.js +3 -3
- package/src/client/ssr/body/CacheControl.js +5 -2
- package/src/client/ssr/body/DefaultSplashScreen.js +19 -12
- package/src/client/ssr/mailer/DefaultRecoverEmail.js +19 -20
- package/src/client/ssr/mailer/DefaultVerifyEmail.js +15 -16
- package/src/client/ssr/offline/Maintenance.js +12 -11
- package/src/client/ssr/offline/NoNetworkConnection.js +3 -3
- package/src/client/ssr/pages/Test.js +2 -2
- package/src/client/sw/core.sw.js +212 -0
- package/src/index.js +1 -1
- package/src/runtime/express/Dockerfile +4 -4
- package/src/runtime/lampp/Dockerfile +8 -7
- package/src/runtime/wp/Dockerfile +11 -17
- package/src/server/client-build-docs.js +45 -46
- package/src/server/client-build.js +334 -60
- package/src/server/client-formatted.js +47 -16
- package/src/server/conf.js +5 -4
- package/src/server/ipfs-client.js +232 -91
- package/src/server/process.js +13 -27
- package/src/server/start.js +6 -3
- package/src/server/valkey.js +134 -235
- package/tsconfig.docs.json +15 -0
- package/typedoc.json +20 -0
- package/jsdoc.json +0 -52
- package/src/client/components/core/ColorPalette.js +0 -5267
- package/src/client/components/core/JoyStick.js +0 -80
- package/src/client/components/default/RoutesDefault.js +0 -49
- package/src/client/sw/default.sw.js +0 -127
- 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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
75
|
-
if (
|
|
76
|
-
|
|
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 (
|
|
82
|
-
|
|
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
|
-
|
|
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
|
|
107
|
-
|
|
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
|
|
122
|
-
if (
|
|
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, () =>
|
|
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(() =>
|
|
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(() =>
|
|
128
|
+
setTimeout(() => FullScreen._syncToggleState(), 100);
|
|
145
129
|
}
|
|
146
130
|
},
|
|
147
131
|
false,
|
|
148
132
|
);
|
|
149
|
-
|
|
150
|
-
|
|
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
|
|
162
|
-
if (
|
|
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(() =>
|
|
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
|
|
180
|
-
if (!
|
|
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(() =>
|
|
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
|
-
|
|
173
|
+
static async RenderSetting() {
|
|
198
174
|
// Initialize state from actual fullscreen status
|
|
199
|
-
|
|
200
|
-
|
|
175
|
+
FullScreen._fullScreenSwitch = FullScreen._isFullScreen();
|
|
201
176
|
// Setup event listeners once
|
|
202
|
-
|
|
203
|
-
|
|
177
|
+
FullScreen._addEventListeners();
|
|
204
178
|
// Update responsive event
|
|
205
|
-
Responsive.
|
|
206
|
-
|
|
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.
|
|
183
|
+
${await ToggleSwitch.instance({
|
|
211
184
|
wrapper: true,
|
|
212
|
-
wrapperLabel: html`<i class="fa-solid fa-expand"></i> ${Translate.
|
|
185
|
+
wrapperLabel: html`<i class="fa-solid fa-expand"></i> ${Translate.instance('fullscreen')}`,
|
|
213
186
|
id: 'fullscreen',
|
|
214
187
|
disabledOnClick: true,
|
|
215
|
-
checked:
|
|
188
|
+
checked: FullScreen._fullScreenSwitch,
|
|
216
189
|
on: {
|
|
217
190
|
unchecked: () => {
|
|
218
|
-
|
|
191
|
+
FullScreen._exitFullScreen();
|
|
219
192
|
},
|
|
220
193
|
checked: () => {
|
|
221
|
-
|
|
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
|
-
|
|
172
|
+
class Input {
|
|
188
173
|
/**
|
|
189
174
|
* Renders an input element based on the provided options.
|
|
190
175
|
* @async
|
|
191
|
-
* @function
|
|
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
|
-
|
|
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}"> </div>
|
|
275
256
|
</div>
|
|
276
257
|
</div>`;
|
|
277
|
-
}
|
|
278
|
-
parseJson
|
|
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
|
|
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
|
|
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` `);
|
|
351
326
|
}
|
|
352
327
|
return obj;
|
|
353
|
-
}
|
|
354
|
-
|
|
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` `);
|
|
437
401
|
}
|
|
438
402
|
});
|
|
439
|
-
}
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
490
|
+
${await BtnIcon.instance({
|
|
534
491
|
class: `wfa btn-clear-input-file-${id}`,
|
|
535
|
-
label: `<i class="fa-solid fa-broom"></i> ${Translate.
|
|
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.
|
|
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.
|
|
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,
|