underpost 2.8.867 → 2.8.872
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 +3 -1
- package/README.md +26 -2
- package/bin/build.js +1 -0
- package/bin/deploy.js +4 -0
- package/bin/util.js +1 -56
- package/cli.md +3 -1
- package/conf.js +3 -2
- package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
- package/manifests/deployment/mongo-express/deployment.yaml +12 -12
- package/manifests/maas/nvim.sh +91 -0
- package/package.json +2 -12
- package/src/api/file/file.service.js +28 -8
- package/src/api/user/user.router.js +24 -0
- package/src/api/user/user.service.js +3 -4
- package/src/cli/cluster.js +2 -13
- package/src/cli/cron.js +0 -1
- package/src/cli/db.js +0 -19
- package/src/cli/deploy.js +17 -26
- package/src/cli/fs.js +1 -0
- package/src/cli/index.js +1 -0
- package/src/cli/repository.js +1 -0
- package/src/cli/run.js +10 -2
- package/src/client/components/core/Account.js +2 -1
- package/src/client/components/core/AgGrid.js +2 -2
- package/src/client/components/core/CalendarCore.js +2 -3
- package/src/client/components/core/CommonJs.js +1 -2
- package/src/client/components/core/Content.js +2 -1
- package/src/client/components/core/Css.js +2 -1
- package/src/client/components/core/CssCore.js +14 -1
- package/src/client/components/core/Docs.js +5 -5
- package/src/client/components/core/FileExplorer.js +3 -3
- package/src/client/components/core/FullScreen.js +19 -28
- package/src/client/components/core/Input.js +1 -0
- package/src/client/components/core/JoyStick.js +2 -2
- package/src/client/components/core/LoadingAnimation.js +2 -2
- package/src/client/components/core/Logger.js +4 -1
- package/src/client/components/core/Modal.js +54 -47
- package/src/client/components/core/ObjectLayerEngine.js +229 -4
- package/src/client/components/core/ObjectLayerEngineModal.js +442 -0
- package/src/client/components/core/Pagination.js +14 -0
- package/src/client/components/core/Panel.js +3 -8
- package/src/client/components/core/PanelForm.js +5 -14
- package/src/client/components/core/Recover.js +2 -2
- package/src/client/components/core/Router.js +183 -34
- package/src/client/components/core/Stream.js +1 -1
- package/src/client/components/core/ToggleSwitch.js +15 -1
- package/src/client/components/core/VanillaJs.js +0 -84
- package/src/client/components/core/Worker.js +2 -2
- package/src/client/components/default/MenuDefault.js +4 -3
- package/src/client/components/default/RoutesDefault.js +3 -2
- package/src/client/public/default/assets/mailer/api-user-default-avatar.png +0 -0
- package/src/client/services/core/core.service.js +1 -1
- package/src/client/ssr/head/DefaultScripts.js +1 -0
- package/src/index.js +1 -1
- package/src/server/client-build.js +3 -11
- package/src/server/client-icons.js +6 -78
- package/src/server/conf.js +4 -56
- package/src/server/process.js +2 -1
- package/src/server/runtime.js +7 -0
- package/src/server/ssl.js +1 -2
|
@@ -1,21 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vanilla JavaScript module for manipulating the DOM.
|
|
3
|
+
* @module src/client/components/core/Router.js
|
|
4
|
+
* @namespace PwaRouter
|
|
5
|
+
*/
|
|
6
|
+
|
|
1
7
|
import { titleFormatted } from './CommonJs.js';
|
|
2
8
|
import { loggerFactory } from './Logger.js';
|
|
3
|
-
import {
|
|
9
|
+
import { htmls, s } from './VanillaJs.js';
|
|
4
10
|
import { Modal } from './Modal.js';
|
|
5
11
|
import { Worker } from './Worker.js';
|
|
6
12
|
|
|
7
|
-
|
|
13
|
+
const logger = loggerFactory(import.meta, { trace: true });
|
|
8
14
|
|
|
15
|
+
/**
|
|
16
|
+
* @type {Object.<string, function>}
|
|
17
|
+
* @description Holds event listeners for router changes.
|
|
18
|
+
* @memberof PwaRouter
|
|
19
|
+
*/
|
|
9
20
|
const RouterEvents = {};
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @type {string[]}
|
|
24
|
+
* @description Array of core UI component IDs that should not trigger modal close route changes.
|
|
25
|
+
* @memberof PwaRouter
|
|
26
|
+
*/
|
|
27
|
+
const coreUI = ['modal-menu', 'main-body', 'main-body-top', 'bottom-bar', 'board-notification'];
|
|
28
|
+
/**
|
|
29
|
+
* @type {Object.<string, function>}
|
|
30
|
+
* @description Holds event listeners for route changes that should close a modal.
|
|
31
|
+
* @memberof PwaRouter
|
|
32
|
+
*/
|
|
10
33
|
const closeModalRouteChangeEvents = {};
|
|
11
34
|
|
|
12
|
-
|
|
35
|
+
/**
|
|
36
|
+
* Determines the base path for the application, often used for routing within a sub-directory.
|
|
37
|
+
* It checks the current URL's pathname and `window.Routes` to return the appropriate proxy path.
|
|
38
|
+
*
|
|
39
|
+
* @returns {string} The calculated proxy path. Returns `/<first-segment>/` if a segment exists,
|
|
40
|
+
* otherwise `/`. If `window.Routes` indicates the path is a root route, it returns `/`.
|
|
41
|
+
* @memberof PwaRouter
|
|
42
|
+
*/
|
|
43
|
+
const getProxyPath = () => {
|
|
44
|
+
let path = location.pathname.split('/')[1] ? `/${location.pathname.split('/')[1]}/` : '/';
|
|
45
|
+
if (window.Routes && path !== '/' && path.slice(0, -1) in window.Routes()) path = '/';
|
|
46
|
+
return path;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Sets the browser's path using the History API. It sanitizes the path, handles query strings and hashes,
|
|
51
|
+
* and prevents pushing the same state twice.
|
|
52
|
+
* @param {string} [path='/'] - The new path to set. Can include query strings and hashes.
|
|
53
|
+
* @param {object} [options={ removeSearch: false, removeHash: false }] - Options for path manipulation.
|
|
54
|
+
* @param {boolean} [options.removeSearch=false] - If true, removes the search part of the URL.
|
|
55
|
+
* @param {boolean} [options.removeHash=false] - If true, removes the hash part of the URL. Defaults to `false`.
|
|
56
|
+
* @param {object} [stateStorage={}] - State object to associate with the history entry.
|
|
57
|
+
* @param {string} [title=''] - The title for the new history entry.
|
|
58
|
+
* @memberof PwaRouter
|
|
59
|
+
* @returns {void | undefined} Returns `undefined` if the new path is the same as the current path, otherwise `void` (result of `history.pushState`).
|
|
60
|
+
*/
|
|
61
|
+
const setPath = (path = '/', options = { removeSearch: false, removeHash: false }, stateStorage = {}, title = '') => {
|
|
62
|
+
logger.warn(`Set path input`, `${path}`);
|
|
63
|
+
if (!path) path = '/';
|
|
13
64
|
|
|
65
|
+
let [inputPath, inputSearchHash] = `${path}`.split('?');
|
|
66
|
+
let [inputSearch, inputHash] = inputSearchHash ? inputSearchHash.split('#') : [];
|
|
67
|
+
|
|
68
|
+
let sanitizedPath = (inputPath[0] !== '/' ? `/${inputPath}` : inputPath)
|
|
69
|
+
.trim()
|
|
70
|
+
.replaceAll('//', '/')
|
|
71
|
+
.replaceAll(`\\`, '/');
|
|
72
|
+
|
|
73
|
+
if (sanitizedPath.length > 1 && sanitizedPath[sanitizedPath.length - 1] === '/')
|
|
74
|
+
sanitizedPath = sanitizedPath.slice(0, -1);
|
|
75
|
+
|
|
76
|
+
const newFullPath = `${sanitizedPath}${inputSearch && !options.removeSearch ? `?${inputSearch}` : ''}${
|
|
77
|
+
inputHash && !options.removeHash ? `#${inputHash}` : ''
|
|
78
|
+
}`;
|
|
79
|
+
const currentFullPath = `${window.location.pathname}${location.search}${location.hash}`;
|
|
80
|
+
logger.warn(`Set path output`, {
|
|
81
|
+
inputPath: inputPath,
|
|
82
|
+
inputSearch: inputSearch,
|
|
83
|
+
inputHash: inputHash,
|
|
84
|
+
sanitizedPath: sanitizedPath,
|
|
85
|
+
currentLocationSearch: location.search,
|
|
86
|
+
currentLocationHash: location.hash,
|
|
87
|
+
currentFullPath,
|
|
88
|
+
newFullPath,
|
|
89
|
+
});
|
|
90
|
+
if (currentFullPath === newFullPath) {
|
|
91
|
+
logger.warn('Prevent overwriting same path', { currentFullPath, newFullPath });
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
return history.pushState.call(history, stateStorage, title, newFullPath);
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Extracts query parameters from the current URL's search string and returns them as an object.
|
|
99
|
+
* @returns An object containing the query parameters from the current URL is being returned.
|
|
100
|
+
* @memberof PwaRouter
|
|
101
|
+
*/
|
|
102
|
+
const getQueryParams = () => {
|
|
103
|
+
const params = new URLSearchParams(window.location.search);
|
|
104
|
+
let queries = {};
|
|
105
|
+
for (const param of params) {
|
|
106
|
+
queries[param[0]] = param[1];
|
|
107
|
+
}
|
|
108
|
+
return queries;
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Sanitizes a route string for use in CSS classes or other identifiers.
|
|
113
|
+
* Defaults to 'home' for empty, '/', or '\' routes.
|
|
114
|
+
* @param {string} route - The route string to sanitize.
|
|
115
|
+
* @returns {string} The sanitized route string.
|
|
116
|
+
* @memberof PwaRouter
|
|
117
|
+
*/
|
|
14
118
|
const sanitizeRoute = (route) =>
|
|
15
119
|
!route || route === '/' || route === `\\`
|
|
16
120
|
? 'home'
|
|
17
121
|
: route.toLowerCase().replaceAll('/', '').replaceAll(`\\`, '').replaceAll(' ', '-');
|
|
18
122
|
|
|
123
|
+
/**
|
|
124
|
+
* Sets the document title and updates the active state of the main menu button corresponding to the route.
|
|
125
|
+
* The title is formatted and appended with the main application title from `Worker.title` if it's not already present.
|
|
126
|
+
* @param {string} route - The current route string.
|
|
127
|
+
* @memberof PwaRouter
|
|
128
|
+
*/
|
|
19
129
|
const setDocTitle = (route) => {
|
|
20
130
|
const _route = sanitizeRoute(route);
|
|
21
131
|
// logger.warn('setDocTitle', _route);
|
|
@@ -27,6 +137,14 @@ const setDocTitle = (route) => {
|
|
|
27
137
|
}
|
|
28
138
|
};
|
|
29
139
|
|
|
140
|
+
/**
|
|
141
|
+
* Main router function. It matches the current URL path against the provided routes configuration
|
|
142
|
+
* and renders the corresponding component. It also fires registered router events.
|
|
143
|
+
* @param {object} [options={ Routes: () => {}, e: new PopStateEvent() }] - The router options.
|
|
144
|
+
* @param {function} options.Routes - A function that returns the routes object.
|
|
145
|
+
* @param {PopStateEvent} options.e - The popstate event object.
|
|
146
|
+
* @memberof PwaRouter
|
|
147
|
+
*/
|
|
30
148
|
const Router = function (options = { Routes: () => {}, e: new PopStateEvent() }) {
|
|
31
149
|
const { e, Routes } = options;
|
|
32
150
|
const proxyPath = getProxyPath();
|
|
@@ -50,20 +168,43 @@ const Router = function (options = { Routes: () => {}, e: new PopStateEvent() })
|
|
|
50
168
|
}
|
|
51
169
|
};
|
|
52
170
|
|
|
171
|
+
/**
|
|
172
|
+
* Initializes the router and sets up the `onpopstate` event listener to handle browser
|
|
173
|
+
* back/forward navigation.
|
|
174
|
+
* @param {object} RouterInstance - The router instance configuration, including the `Routes` function.
|
|
175
|
+
* @memberof PwaRouter
|
|
176
|
+
*/
|
|
53
177
|
const LoadRouter = function (RouterInstance) {
|
|
54
178
|
Router(RouterInstance);
|
|
55
179
|
window.onpopstate = (e) => Router({ ...RouterInstance, e });
|
|
56
180
|
};
|
|
57
181
|
|
|
182
|
+
/**
|
|
183
|
+
* Sets the URL path with a specific query parameter, commonly used for content IDs.
|
|
184
|
+
* This function constructs a new URI based on the proxy path, a given path, and an optional query parameter.
|
|
185
|
+
* @param {object} [options={ path: '', queryPath: '' }] - The path options.
|
|
186
|
+
* @param {string} [options.path=''] - The base path segment.
|
|
187
|
+
* @memberof PwaRouter
|
|
188
|
+
*/
|
|
58
189
|
const setQueryPath = (options = { path: '', queryPath: '' }, queryKey = 'cid') => {
|
|
59
190
|
const { queryPath, path } = options;
|
|
60
191
|
const newUri = `${getProxyPath()}${path === 'home' ? '' : `${path}/`}${
|
|
61
|
-
typeof queryPath === 'string' ? `?${queryKey}=${queryPath}` : ''
|
|
192
|
+
typeof queryPath === 'string' && queryPath ? `?${queryKey}=${queryPath}` : ''
|
|
62
193
|
}`;
|
|
63
194
|
const currentUri = `${window.location.pathname}${location.search}`;
|
|
64
|
-
if (currentUri !== newUri && currentUri !== `${newUri}/`) setPath(newUri);
|
|
195
|
+
if (currentUri !== newUri && currentUri !== `${newUri}/`) setPath(newUri, {}, '');
|
|
65
196
|
};
|
|
66
197
|
|
|
198
|
+
/**
|
|
199
|
+
* Registers a listener for route changes that specifically watches for a `queryKey` parameter
|
|
200
|
+
* on a matching `routeId`. The provided event callback is triggered with the query parameter's value.
|
|
201
|
+
* @param {object} options - The listener options.
|
|
202
|
+
* @param {string} options.id - A unique ID for the listener.
|
|
203
|
+
* @param {string} options.routeId - The route ID to listen for.
|
|
204
|
+
* @param {function(string): void} options.event - The callback function to execute with the query path value (or an empty string if not found).
|
|
205
|
+
* @param {string} [queryKey='cid'] - The query parameter key to look for.
|
|
206
|
+
* @memberof PwaRouter
|
|
207
|
+
*/
|
|
67
208
|
const listenQueryPathInstance = ({ id, routeId, event }, queryKey = 'cid') => {
|
|
68
209
|
RouterEvents[id] = ({ path, pushPath, proxyPath, route }) => {
|
|
69
210
|
if ((route === '' && routeId === 'home') || (route && routeId && route === routeId)) {
|
|
@@ -80,38 +221,42 @@ const listenQueryPathInstance = ({ id, routeId, event }, queryKey = 'cid') => {
|
|
|
80
221
|
});
|
|
81
222
|
};
|
|
82
223
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
}
|
|
87
|
-
|
|
224
|
+
/**
|
|
225
|
+
* Handles the logic for changing the route when a modal is closed. It determines the next URL
|
|
226
|
+
* based on the remaining open modals or falls back to a home URL.
|
|
227
|
+
* @param {object} [options={}] - Options for the modal close event.
|
|
228
|
+
* @param {string} options.closedId - The ID of the modal that was just closed.
|
|
229
|
+
* @memberof PwaRouter
|
|
230
|
+
*/
|
|
88
231
|
const closeModalRouteChangeEvent = (options = {}) => {
|
|
89
|
-
|
|
90
|
-
|
|
232
|
+
logger.warn('closeModalRouteChangeEvent', options);
|
|
233
|
+
const { closedId } = options;
|
|
234
|
+
if (!closedId) return;
|
|
235
|
+
if (coreUI.find((id) => closedId.startsWith(id))) {
|
|
236
|
+
logger.warn('prevent core ui component close');
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
91
239
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
240
|
+
const remainingModals = Object.keys(Modal.Data).filter(
|
|
241
|
+
(id) => id !== closedId && (Modal.Data[id]?.options?.route || Modal.Data[id]?.options?.query),
|
|
242
|
+
);
|
|
95
243
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
setPath(newPath);
|
|
102
|
-
setDocTitle(newPath);
|
|
103
|
-
Modal.setTopModalCallback(subIdModal);
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
newPath = `${newPath}${homeCid ? `?cid=${homeCid}` : ''}`;
|
|
107
|
-
triggerCloseModalRouteChangeEvents(newPath);
|
|
108
|
-
setPath(newPath);
|
|
109
|
-
setDocTitle(newPath);
|
|
110
|
-
}
|
|
244
|
+
const topModalId = remainingModals.reverse().find((id) => Modal.Data[id]);
|
|
245
|
+
|
|
246
|
+
for (const event of Object.keys(closeModalRouteChangeEvents)) closeModalRouteChangeEvents[event]();
|
|
247
|
+
if (topModalId) Modal.setTopModalCallback(topModalId);
|
|
248
|
+
setPath(`${getProxyPath()}${Modal.Data[topModalId]?.options?.route || 'home'}`);
|
|
111
249
|
};
|
|
112
250
|
|
|
113
|
-
|
|
114
|
-
|
|
251
|
+
/**
|
|
252
|
+
* Handles routing for modals that are meant to be displayed as a "view" (e.g., a full-page modal).
|
|
253
|
+
* It updates the URL to reflect the modal's route.
|
|
254
|
+
* @param {object} [options={ route: 'home' }] - The options for handling the modal view route.
|
|
255
|
+
* @param {string} options.route - The route associated with the modal view.
|
|
256
|
+
* @memberof PwaRouter
|
|
257
|
+
*/
|
|
258
|
+
const handleModalViewRoute = (options = { route: 'home' }) => {
|
|
259
|
+
const { route } = options;
|
|
115
260
|
if (!route) return;
|
|
116
261
|
|
|
117
262
|
let path = window.location.pathname;
|
|
@@ -126,13 +271,17 @@ const handleModalViewRoute = (options = {}) => {
|
|
|
126
271
|
};
|
|
127
272
|
|
|
128
273
|
export {
|
|
274
|
+
RouterEvents,
|
|
275
|
+
closeModalRouteChangeEvents,
|
|
276
|
+
coreUI,
|
|
129
277
|
Router,
|
|
130
278
|
setDocTitle,
|
|
131
279
|
LoadRouter,
|
|
132
|
-
RouterEvents,
|
|
133
280
|
setQueryPath,
|
|
134
281
|
listenQueryPathInstance,
|
|
135
282
|
closeModalRouteChangeEvent,
|
|
136
283
|
handleModalViewRoute,
|
|
137
|
-
|
|
284
|
+
getQueryParams,
|
|
285
|
+
getProxyPath,
|
|
286
|
+
setPath,
|
|
138
287
|
};
|
|
@@ -67,7 +67,7 @@ const ToggleSwitch = {
|
|
|
67
67
|
|
|
68
68
|
if (options.type === 'checkbox') {
|
|
69
69
|
}
|
|
70
|
-
|
|
70
|
+
const htmlRender = html`
|
|
71
71
|
${options?.displayMode === 'checkbox'
|
|
72
72
|
? html`<div class="${options?.containerClass ? options.containerClass : 'inl box-content-border'} ${id}">
|
|
73
73
|
<div class="in ${id}-content toggle-switch-content-checkbox">
|
|
@@ -81,6 +81,20 @@ const ToggleSwitch = {
|
|
|
81
81
|
</div>`}
|
|
82
82
|
<input type="checkbox" class="${id}-checkbox" style="display: none" />
|
|
83
83
|
`;
|
|
84
|
+
if (options.wrapper) {
|
|
85
|
+
setTimeout(() => (s(`.toggle-form-container-${id}`).onclick = () => ToggleSwitch.Tokens[`${id}`].click()));
|
|
86
|
+
return html`
|
|
87
|
+
<div class="in toggle-form-container toggle-form-container-${id} hover">
|
|
88
|
+
<div class="fl ">
|
|
89
|
+
<div class="in fll" style="width: 70%">
|
|
90
|
+
<div class="in">${options.wrapperLabel}</div>
|
|
91
|
+
</div>
|
|
92
|
+
<div class="in fll" style="width: 30%">${htmlRender}</div>
|
|
93
|
+
</div>
|
|
94
|
+
</div>
|
|
95
|
+
`;
|
|
96
|
+
}
|
|
97
|
+
return htmlRender;
|
|
84
98
|
},
|
|
85
99
|
};
|
|
86
100
|
|
|
@@ -132,72 +132,6 @@ const copyData = (data) =>
|
|
|
132
132
|
*/
|
|
133
133
|
const pasteData = () => new Promise((resolve) => navigator.clipboard.readText().then((clipText) => resolve(clipText)));
|
|
134
134
|
|
|
135
|
-
/**
|
|
136
|
-
* The setPath function in JavaScript updates the browser's history with a new path, state, and title.
|
|
137
|
-
* @param path - The `path` parameter is a string that represents the URL path where you want to
|
|
138
|
-
* navigate or update in the browser history. It is the first parameter in the `setPath` function and
|
|
139
|
-
* has a default value of `'/'`.
|
|
140
|
-
* @param stateStorage - The `stateStorage` parameter in the `setPath` function is an object that
|
|
141
|
-
* represents the state object associated with the new history entry. It is used to store data related
|
|
142
|
-
* to the state of the application when navigating to a new path using `history.pushState()`. This data
|
|
143
|
-
* can be accessed later
|
|
144
|
-
* @param title - The `title` parameter in the `setPath` function is a string that represents the
|
|
145
|
-
* title of the new history entry. It is used as the title of the new history entry in the browser's
|
|
146
|
-
* history.
|
|
147
|
-
* @memberof VanillaJS
|
|
148
|
-
*/
|
|
149
|
-
const setPath = (path = '/', stateStorage = {}, title = '') => {
|
|
150
|
-
if (!path) path = '/';
|
|
151
|
-
|
|
152
|
-
const [inputPath, inputSearch] = `${path}`.split('?');
|
|
153
|
-
|
|
154
|
-
let sanitizedPath = (inputPath[0] !== '/' ? `/${inputPath}` : inputPath)
|
|
155
|
-
.trim()
|
|
156
|
-
.replaceAll('//', '/')
|
|
157
|
-
.replaceAll(`\\`, '/');
|
|
158
|
-
|
|
159
|
-
if (sanitizedPath.length > 1 && sanitizedPath[sanitizedPath.length - 1] === '/')
|
|
160
|
-
sanitizedPath = sanitizedPath.slice(0, -1);
|
|
161
|
-
|
|
162
|
-
if (window.location.pathname === sanitizedPath && (!inputSearch || inputSearch === location.search)) {
|
|
163
|
-
console.warn('Prevent overwriting same path', {
|
|
164
|
-
inputPath: inputPath,
|
|
165
|
-
inputSearch: inputSearch,
|
|
166
|
-
sanitizedPath: sanitizedPath,
|
|
167
|
-
currentLocationSearch: location.search,
|
|
168
|
-
currentLocationHash: location.hash,
|
|
169
|
-
});
|
|
170
|
-
return;
|
|
171
|
-
}
|
|
172
|
-
console.warn('Set path', {
|
|
173
|
-
inputPath: inputPath,
|
|
174
|
-
inputSearch: inputSearch,
|
|
175
|
-
sanitizedPath: sanitizedPath,
|
|
176
|
-
currentLocationSearch: location.search,
|
|
177
|
-
currentLocationHash: location.hash,
|
|
178
|
-
});
|
|
179
|
-
return history.pushState(
|
|
180
|
-
stateStorage,
|
|
181
|
-
title,
|
|
182
|
-
`${sanitizedPath}${inputSearch ? `?${inputSearch}` : ''}${location.hash ?? ''}`,
|
|
183
|
-
);
|
|
184
|
-
};
|
|
185
|
-
|
|
186
|
-
/**
|
|
187
|
-
* The function `getQueryParams` extracts query parameters from the current URL and returns them as an
|
|
188
|
-
* object.
|
|
189
|
-
* @returns An object containing the query parameters from the current URL is being returned.
|
|
190
|
-
* @memberof VanillaJS
|
|
191
|
-
*/
|
|
192
|
-
const getQueryParams = () => {
|
|
193
|
-
const params = new URLSearchParams(window.location.search);
|
|
194
|
-
let queries = {};
|
|
195
|
-
for (const param of params) {
|
|
196
|
-
queries[param[0]] = param[1];
|
|
197
|
-
}
|
|
198
|
-
return queries;
|
|
199
|
-
};
|
|
200
|
-
|
|
201
135
|
/**
|
|
202
136
|
* The `preHTML` function in JavaScript replaces special characters like &, <, and > with their
|
|
203
137
|
* corresponding HTML entities.
|
|
@@ -375,21 +309,6 @@ const getBlobFromUint8ArrayFile = (data = [[]], mimetype = 'application/octet-st
|
|
|
375
309
|
return new Blob([new Uint8Array(data)], { type: mimetype });
|
|
376
310
|
};
|
|
377
311
|
|
|
378
|
-
// Router
|
|
379
|
-
/**
|
|
380
|
-
* The function `getProxyPath` returns a proxy path based on the current location pathname.
|
|
381
|
-
* @returns The `getProxyPath` function returns the path based on the current location. If the first
|
|
382
|
-
* segment of the pathname is not empty, it returns `/<first-segment>/`, otherwise it returns `/`. If
|
|
383
|
-
* the `window.Routes` object exists and the path is not `/` and the path without the trailing slash is
|
|
384
|
-
* a key in the `window.Routes` object, it returns `/`.
|
|
385
|
-
* @memberof VanillaJS
|
|
386
|
-
*/
|
|
387
|
-
const getProxyPath = () => {
|
|
388
|
-
let path = location.pathname.split('/')[1] ? `/${location.pathname.split('/')[1]}/` : '/';
|
|
389
|
-
if (window.Routes && path !== '/' && path.slice(0, -1) in window.Routes()) path = '/';
|
|
390
|
-
return path;
|
|
391
|
-
};
|
|
392
|
-
|
|
393
312
|
/**
|
|
394
313
|
* The function `isNavigator` checks if the user agent string contains a specified name.
|
|
395
314
|
* @param name - The `name` parameter is a string that represents the name of a browser or device to
|
|
@@ -478,8 +397,6 @@ export {
|
|
|
478
397
|
sa,
|
|
479
398
|
copyData,
|
|
480
399
|
pasteData,
|
|
481
|
-
setPath,
|
|
482
|
-
getQueryParams,
|
|
483
400
|
preHTML,
|
|
484
401
|
disableOptionsClick,
|
|
485
402
|
checkFullScreen,
|
|
@@ -488,7 +405,6 @@ export {
|
|
|
488
405
|
getResponsiveData,
|
|
489
406
|
isElement,
|
|
490
407
|
downloadFile,
|
|
491
|
-
getProxyPath,
|
|
492
408
|
getRawContentFile,
|
|
493
409
|
getBlobFromUint8ArrayFile,
|
|
494
410
|
isNavigator,
|
|
@@ -5,8 +5,8 @@ import { LoadingAnimation } from './LoadingAnimation.js';
|
|
|
5
5
|
import { loggerFactory } from './Logger.js';
|
|
6
6
|
import { LoadRouter } from './Router.js';
|
|
7
7
|
import { Translate } from './Translate.js';
|
|
8
|
-
import {
|
|
9
|
-
|
|
8
|
+
import { s } from './VanillaJs.js';
|
|
9
|
+
import { getProxyPath } from './Router.js';
|
|
10
10
|
const logger = loggerFactory(import.meta);
|
|
11
11
|
|
|
12
12
|
const Worker = {
|
|
@@ -17,10 +17,11 @@ import { LogOut } from '../core/LogOut.js';
|
|
|
17
17
|
import { buildBadgeToolTipMenuOption, Modal, renderMenuLabel, renderViewTitle } from '../core/Modal.js';
|
|
18
18
|
import { SignUp } from '../core/SignUp.js';
|
|
19
19
|
import { Translate } from '../core/Translate.js';
|
|
20
|
-
import {
|
|
20
|
+
import { htmls, s } from '../core/VanillaJs.js';
|
|
21
|
+
import { getProxyPath } from '../core/Router.js';
|
|
21
22
|
import { ElementsDefault } from './ElementsDefault.js';
|
|
22
23
|
import Sortable from 'sortablejs';
|
|
23
|
-
import { RouterDefault } from './RoutesDefault.js';
|
|
24
|
+
import { RouterDefault, BannerAppTemplate } from './RoutesDefault.js';
|
|
24
25
|
import { SettingsDefault } from './SettingsDefault.js';
|
|
25
26
|
import { Badge } from '../core/Badge.js';
|
|
26
27
|
import { Docs } from '../core/Docs.js';
|
|
@@ -35,7 +36,7 @@ const MenuDefault = {
|
|
|
35
36
|
const id = getId(this.Data, 'menu-');
|
|
36
37
|
this.Data[id] = {};
|
|
37
38
|
const RouterInstance = RouterDefault();
|
|
38
|
-
|
|
39
|
+
|
|
39
40
|
const { barConfig } = await Themes[Css.currentTheme]();
|
|
40
41
|
const heightTopBar = 50;
|
|
41
42
|
const heightBottomBar = 50;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { loggerFactory } from '../core/Logger.js';
|
|
2
2
|
import { Modal } from '../core/Modal.js';
|
|
3
|
-
import {
|
|
3
|
+
import { s } from '../core/VanillaJs.js';
|
|
4
|
+
import { getProxyPath } from '../core/Router.js';
|
|
4
5
|
|
|
5
6
|
const logger = loggerFactory(import.meta);
|
|
6
7
|
|
|
@@ -39,7 +40,7 @@ const RoutesDefault = () => {
|
|
|
39
40
|
window.Routes = RoutesDefault;
|
|
40
41
|
|
|
41
42
|
const RouterDefault = () => {
|
|
42
|
-
return { Routes: RoutesDefault
|
|
43
|
+
return { Routes: RoutesDefault };
|
|
43
44
|
};
|
|
44
45
|
|
|
45
46
|
export { RoutesDefault, RouterDefault, BannerAppTemplate };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Auth } from '../../components/core/Auth.js';
|
|
2
2
|
import { loggerFactory } from '../../components/core/Logger.js';
|
|
3
|
-
import { getProxyPath } from '../../components/core/
|
|
3
|
+
import { getProxyPath } from '../../components/core/Router.js';
|
|
4
4
|
|
|
5
5
|
const logger = loggerFactory(import.meta);
|
|
6
6
|
|
package/src/index.js
CHANGED
|
@@ -19,7 +19,7 @@ import * as dir from 'path';
|
|
|
19
19
|
import { shellExec } from './process.js';
|
|
20
20
|
import { SitemapStream, streamToPromise } from 'sitemap';
|
|
21
21
|
import { Readable } from 'stream';
|
|
22
|
-
import { buildIcons
|
|
22
|
+
import { buildIcons } from './client-icons.js';
|
|
23
23
|
import Underpost from '../index.js';
|
|
24
24
|
import { buildDocs } from './client-build-docs.js';
|
|
25
25
|
|
|
@@ -65,16 +65,8 @@ const fullBuild = async ({
|
|
|
65
65
|
fs.removeSync(rootClientPath);
|
|
66
66
|
|
|
67
67
|
if (fs.existsSync(`./src/client/public/${publicClientId}`)) {
|
|
68
|
-
if (iconsBuild) {
|
|
69
|
-
|
|
70
|
-
if (!fs.existsSync(defaultBaseIconFolderPath)) fs.mkdirSync(defaultBaseIconFolderPath, { recursive: true });
|
|
71
|
-
const defaultBaseIconPath = `${defaultBaseIconFolderPath}/base-icon.png`;
|
|
72
|
-
if (!fs.existsSync(defaultBaseIconPath))
|
|
73
|
-
await buildTextImg(metadata.title, { debugFilename: defaultBaseIconPath });
|
|
74
|
-
|
|
75
|
-
if (!fs.existsSync(`./src/client/public/${publicClientId}/site.webmanifest`))
|
|
76
|
-
await buildIcons({ publicClientId, metadata });
|
|
77
|
-
}
|
|
68
|
+
if (iconsBuild === true) await buildIcons({ publicClientId, metadata });
|
|
69
|
+
|
|
78
70
|
fs.copySync(
|
|
79
71
|
`./src/client/public/${publicClientId}`,
|
|
80
72
|
rootClientPath /* {
|
|
@@ -1,80 +1,17 @@
|
|
|
1
1
|
import { favicons } from 'favicons';
|
|
2
|
-
// TODO: search alternatives
|
|
3
|
-
// import textToImage from 'text-to-image';
|
|
4
2
|
import { loggerFactory } from './logger.js';
|
|
5
3
|
import fs from 'fs-extra';
|
|
6
|
-
import { getCapVariableName
|
|
7
|
-
import { FileFactory } from '../api/file/file.service.js';
|
|
8
|
-
import { svg, png, png3x } from 'font-awesome-assets';
|
|
4
|
+
import { getCapVariableName } from '../client/components/core/CommonJs.js';
|
|
9
5
|
|
|
10
6
|
const logger = loggerFactory(import.meta);
|
|
11
7
|
|
|
12
|
-
const faBase64Png = (faId = 'check', width = 100, height = 100, color = '#209e00') => {
|
|
13
|
-
const b64Src = png3x(faId, color, width, height);
|
|
14
|
-
return b64Src.split('src="data:image/png;base64,')[1].split('"')[0];
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
const defaultBaseTextImgOptions = {
|
|
18
|
-
debug: true,
|
|
19
|
-
fontFamily: 'Arial',
|
|
20
|
-
fontWeight: 'bold',
|
|
21
|
-
bgColor: 'black',
|
|
22
|
-
textColor: 'white',
|
|
23
|
-
debugFilename: 'src/client/public/text-image.png',
|
|
24
|
-
verticalAlign: 'center',
|
|
25
|
-
textAlign: 'center',
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
const defaultBaseTextImgOptionsSizes = {
|
|
29
|
-
'70x70': {
|
|
30
|
-
maxWidth: 70,
|
|
31
|
-
customHeight: 70,
|
|
32
|
-
fontSize: 25,
|
|
33
|
-
margin: 10,
|
|
34
|
-
},
|
|
35
|
-
'100x100': {
|
|
36
|
-
maxWidth: 100,
|
|
37
|
-
customHeight: 100,
|
|
38
|
-
fontSize: 30,
|
|
39
|
-
margin: 12,
|
|
40
|
-
},
|
|
41
|
-
'100x300': {
|
|
42
|
-
maxWidth: 300,
|
|
43
|
-
customHeight: 100,
|
|
44
|
-
fontSize: 30,
|
|
45
|
-
margin: 12,
|
|
46
|
-
},
|
|
47
|
-
'1200x1200': {
|
|
48
|
-
maxWidth: 1200,
|
|
49
|
-
customHeight: 1200,
|
|
50
|
-
fontSize: 500,
|
|
51
|
-
margin: 50,
|
|
52
|
-
},
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
const buildTextImg = async (text = 'APP', options, size = '1200x1200') => {
|
|
56
|
-
options = { ...defaultBaseTextImgOptions, ...defaultBaseTextImgOptionsSizes[size], ...options };
|
|
57
|
-
// await textToImage.generate(text, options);
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
const getBufferPngText = async ({ text, textColor, bgColor, size, debugFilename }) => {
|
|
61
|
-
if (!text) text = 'Hello World!';
|
|
62
|
-
if (!textColor) textColor = '#000000';
|
|
63
|
-
if (!bgColor) bgColor = '#ffffff';
|
|
64
|
-
if (!size) size = '100x300';
|
|
65
|
-
if (!debugFilename) debugFilename = `./${s4()}${s4()}${s4()}.png`;
|
|
66
|
-
await buildTextImg(text, { textColor, bgColor, size, debugFilename }, size);
|
|
67
|
-
if (!fs.existsSync(debugFilename)) return Buffer.alloc(0); // Return empty buffer if file not found
|
|
68
|
-
const bufferImage = fs.readFileSync(debugFilename);
|
|
69
|
-
fs.removeSync(debugFilename);
|
|
70
|
-
return bufferImage;
|
|
71
|
-
};
|
|
72
|
-
|
|
73
8
|
const buildIcons = async ({
|
|
74
9
|
publicClientId,
|
|
75
|
-
metadata: { title, description, keywords, author, thumbnail, themeColor },
|
|
10
|
+
metadata: { title, description, keywords, author, thumbnail, themeColor, baseBuildIconReference },
|
|
76
11
|
}) => {
|
|
77
|
-
const source =
|
|
12
|
+
const source = baseBuildIconReference
|
|
13
|
+
? baseBuildIconReference
|
|
14
|
+
: `src/client/public/${publicClientId}/assets/logo/base-icon.png`; // Source image(s). `string`, `buffer` or array of `string`
|
|
78
15
|
|
|
79
16
|
const configuration = {
|
|
80
17
|
path: '/', // Path for overriding default icons path. `string`
|
|
@@ -149,13 +86,4 @@ const buildIcons = async ({
|
|
|
149
86
|
}
|
|
150
87
|
};
|
|
151
88
|
|
|
152
|
-
|
|
153
|
-
const faId = 'user';
|
|
154
|
-
const tmpFilePath = `./tmp/${faId}-${s4() + s4()}.svg`;
|
|
155
|
-
fs.writeFileSync(tmpFilePath, svg(faId, '#f5f5f5d1'), 'utf8');
|
|
156
|
-
const file = await new File(FileFactory.svg(fs.readFileSync(tmpFilePath), `${faId}.svg`)).save();
|
|
157
|
-
fs.removeSync(tmpFilePath);
|
|
158
|
-
return file._id;
|
|
159
|
-
};
|
|
160
|
-
|
|
161
|
-
export { buildIcons, buildTextImg, defaultBaseTextImgOptions, faBase64Png, getBufferPngText, getDefaultProfileImageId };
|
|
89
|
+
export { buildIcons };
|