underpost 2.8.871 → 2.8.873
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/.env.development +2 -1
- package/.env.production +2 -1
- package/.env.test +2 -1
- package/.github/workflows/ghpkg.ci.yml +1 -1
- package/.github/workflows/npmpkg.ci.yml +1 -1
- package/.github/workflows/pwa-microservices-template-page.cd.yml +1 -1
- package/.github/workflows/pwa-microservices-template-test.ci.yml +1 -1
- package/.github/workflows/release.cd.yml +2 -2
- package/README.md +66 -36
- package/bin/build.js +4 -0
- package/bin/deploy.js +4 -0
- package/cli.md +88 -87
- package/conf.js +2 -1
- package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
- package/manifests/deployment/dd-test-development/deployment.yaml +138 -0
- package/manifests/deployment/dd-test-development/proxy.yaml +26 -0
- package/package.json +6 -3
- package/src/api/core/core.router.js +2 -1
- package/src/api/default/default.controller.js +6 -1
- package/src/api/default/default.router.js +6 -2
- package/src/api/default/default.service.js +10 -1
- package/src/api/file/file.router.js +2 -1
- package/src/api/test/test.router.js +1 -1
- package/src/api/user/postman_collection.json +216 -0
- package/src/api/user/user.controller.js +25 -60
- package/src/api/user/user.model.js +29 -7
- package/src/api/user/user.router.js +6 -3
- package/src/api/user/user.service.js +80 -32
- package/src/cli/baremetal.js +33 -3
- package/src/cli/cloud-init.js +11 -0
- package/src/cli/deploy.js +5 -2
- package/src/cli/index.js +1 -0
- package/src/cli/lxd.js +7 -0
- package/src/cli/repository.js +1 -0
- package/src/cli/run.js +18 -5
- package/src/cli/ssh.js +20 -6
- package/src/client/components/core/Account.js +2 -1
- package/src/client/components/core/AgGrid.js +30 -8
- package/src/client/components/core/Auth.js +98 -55
- package/src/client/components/core/CalendarCore.js +3 -4
- 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 +2 -1
- package/src/client/components/core/Docs.js +4 -4
- package/src/client/components/core/FileExplorer.js +3 -3
- package/src/client/components/core/JoyStick.js +2 -2
- package/src/client/components/core/LoadingAnimation.js +2 -2
- package/src/client/components/core/LogIn.js +16 -23
- package/src/client/components/core/LogOut.js +5 -1
- package/src/client/components/core/Logger.js +4 -1
- package/src/client/components/core/Modal.js +17 -27
- package/src/client/components/core/ObjectLayerEngineModal.js +2 -1
- package/src/client/components/core/Pagination.js +207 -0
- package/src/client/components/core/Panel.js +3 -11
- package/src/client/components/core/PanelForm.js +6 -15
- package/src/client/components/core/Recover.js +2 -2
- package/src/client/components/core/Router.js +205 -33
- package/src/client/components/core/SignUp.js +1 -2
- package/src/client/components/core/Stream.js +1 -1
- package/src/client/components/core/VanillaJs.js +0 -83
- package/src/client/components/core/Worker.js +2 -2
- package/src/client/components/default/LogInDefault.js +0 -6
- package/src/client/components/default/LogOutDefault.js +0 -16
- package/src/client/components/default/MenuDefault.js +4 -3
- package/src/client/components/default/RoutesDefault.js +3 -2
- package/src/client/services/core/core.service.js +6 -2
- package/src/client/services/default/default.management.js +115 -18
- package/src/client/services/default/default.service.js +9 -4
- package/src/client/services/user/user.management.js +6 -0
- package/src/client/services/user/user.service.js +11 -4
- package/src/client/ssr/head/DefaultScripts.js +1 -0
- package/src/index.js +24 -2
- package/src/runtime/lampp/Lampp.js +89 -2
- package/src/runtime/xampp/Xampp.js +48 -1
- package/src/server/auth.js +518 -155
- package/src/server/conf.js +19 -1
- package/src/server/runtime.js +62 -221
- package/src/server/ssl.js +1 -2
- package/src/server/ssr.js +85 -0
- package/src/server/valkey.js +2 -1
|
@@ -132,71 +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
|
-
* @param {object} [options={}] - Additional options.
|
|
148
|
-
* @param {boolean} [options.replace=false] - If true, use `history.replaceState` instead of `history.pushState`.
|
|
149
|
-
* @memberof VanillaJS
|
|
150
|
-
*/
|
|
151
|
-
const setPath = (path = '/', stateStorage = {}, title = '', options = {}) => {
|
|
152
|
-
if (!path) path = '/';
|
|
153
|
-
|
|
154
|
-
const [inputPath, inputSearch] = `${path}`.split('?');
|
|
155
|
-
|
|
156
|
-
let sanitizedPath = (inputPath[0] !== '/' ? `/${inputPath}` : inputPath)
|
|
157
|
-
.trim()
|
|
158
|
-
.replaceAll('//', '/')
|
|
159
|
-
.replaceAll(`\\`, '/');
|
|
160
|
-
|
|
161
|
-
if (sanitizedPath.length > 1 && sanitizedPath[sanitizedPath.length - 1] === '/')
|
|
162
|
-
sanitizedPath = sanitizedPath.slice(0, -1);
|
|
163
|
-
|
|
164
|
-
const newFullPath = `${sanitizedPath}${inputSearch ? `?${inputSearch}` : location.search}${location.hash ?? ''}`;
|
|
165
|
-
const currentFullPath = `${window.location.pathname}${location.search}${location.hash}`;
|
|
166
|
-
|
|
167
|
-
if (currentFullPath === newFullPath) {
|
|
168
|
-
console.warn('Prevent overwriting same path', {
|
|
169
|
-
newFullPath,
|
|
170
|
-
currentFullPath,
|
|
171
|
-
});
|
|
172
|
-
return;
|
|
173
|
-
}
|
|
174
|
-
const historyMethod = options.replace ? history.replaceState : history.pushState;
|
|
175
|
-
console.warn(`Set path (${options.replace ? 'replace' : 'push'})`, {
|
|
176
|
-
inputPath: inputPath,
|
|
177
|
-
inputSearch: inputSearch,
|
|
178
|
-
sanitizedPath: sanitizedPath,
|
|
179
|
-
currentLocationSearch: location.search,
|
|
180
|
-
currentLocationHash: location.hash,
|
|
181
|
-
});
|
|
182
|
-
return historyMethod.call(history, stateStorage, title, newFullPath);
|
|
183
|
-
};
|
|
184
|
-
|
|
185
|
-
/**
|
|
186
|
-
* The function `getQueryParams` extracts query parameters from the current URL and returns them as an
|
|
187
|
-
* object.
|
|
188
|
-
* @returns An object containing the query parameters from the current URL is being returned.
|
|
189
|
-
* @memberof VanillaJS
|
|
190
|
-
*/
|
|
191
|
-
const getQueryParams = () => {
|
|
192
|
-
const params = new URLSearchParams(window.location.search);
|
|
193
|
-
let queries = {};
|
|
194
|
-
for (const param of params) {
|
|
195
|
-
queries[param[0]] = param[1];
|
|
196
|
-
}
|
|
197
|
-
return queries;
|
|
198
|
-
};
|
|
199
|
-
|
|
200
135
|
/**
|
|
201
136
|
* The `preHTML` function in JavaScript replaces special characters like &, <, and > with their
|
|
202
137
|
* corresponding HTML entities.
|
|
@@ -374,21 +309,6 @@ const getBlobFromUint8ArrayFile = (data = [[]], mimetype = 'application/octet-st
|
|
|
374
309
|
return new Blob([new Uint8Array(data)], { type: mimetype });
|
|
375
310
|
};
|
|
376
311
|
|
|
377
|
-
// Router
|
|
378
|
-
/**
|
|
379
|
-
* The function `getProxyPath` returns a proxy path based on the current location pathname.
|
|
380
|
-
* @returns The `getProxyPath` function returns the path based on the current location. If the first
|
|
381
|
-
* segment of the pathname is not empty, it returns `/<first-segment>/`, otherwise it returns `/`. If
|
|
382
|
-
* the `window.Routes` object exists and the path is not `/` and the path without the trailing slash is
|
|
383
|
-
* a key in the `window.Routes` object, it returns `/`.
|
|
384
|
-
* @memberof VanillaJS
|
|
385
|
-
*/
|
|
386
|
-
const getProxyPath = () => {
|
|
387
|
-
let path = location.pathname.split('/')[1] ? `/${location.pathname.split('/')[1]}/` : '/';
|
|
388
|
-
if (window.Routes && path !== '/' && path.slice(0, -1) in window.Routes()) path = '/';
|
|
389
|
-
return path;
|
|
390
|
-
};
|
|
391
|
-
|
|
392
312
|
/**
|
|
393
313
|
* The function `isNavigator` checks if the user agent string contains a specified name.
|
|
394
314
|
* @param name - The `name` parameter is a string that represents the name of a browser or device to
|
|
@@ -477,8 +397,6 @@ export {
|
|
|
477
397
|
sa,
|
|
478
398
|
copyData,
|
|
479
399
|
pasteData,
|
|
480
|
-
setPath,
|
|
481
|
-
getQueryParams,
|
|
482
400
|
preHTML,
|
|
483
401
|
disableOptionsClick,
|
|
484
402
|
checkFullScreen,
|
|
@@ -487,7 +405,6 @@ export {
|
|
|
487
405
|
getResponsiveData,
|
|
488
406
|
isElement,
|
|
489
407
|
downloadFile,
|
|
490
|
-
getProxyPath,
|
|
491
408
|
getRawContentFile,
|
|
492
409
|
getBlobFromUint8ArrayFile,
|
|
493
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 = {
|
|
@@ -1,17 +1,11 @@
|
|
|
1
|
-
import { UserService } from '../../services/user/user.service.js';
|
|
2
1
|
import { Auth } from '../core/Auth.js';
|
|
3
2
|
import { LogIn } from '../core/LogIn.js';
|
|
4
|
-
import { s } from '../core/VanillaJs.js';
|
|
5
3
|
import { ElementsDefault } from './ElementsDefault.js';
|
|
6
4
|
|
|
7
5
|
const LogInDefault = async function () {
|
|
8
6
|
LogIn.Event['LogInDefault'] = async (options) => {
|
|
9
7
|
const { token, user } = options;
|
|
10
8
|
ElementsDefault.Data.user.main.model.user = user;
|
|
11
|
-
s(`.main-btn-log-in`).style.display = 'none';
|
|
12
|
-
s(`.main-btn-sign-up`).style.display = 'none';
|
|
13
|
-
s(`.main-btn-log-out`).style.display = null;
|
|
14
|
-
s(`.main-btn-account`).style.display = null;
|
|
15
9
|
};
|
|
16
10
|
const { user } = await Auth.sessionIn();
|
|
17
11
|
ElementsDefault.Data.user.main.model.user = user;
|
|
@@ -1,25 +1,9 @@
|
|
|
1
|
-
import { Auth } from '../core/Auth.js';
|
|
2
1
|
import { LogOut } from '../core/LogOut.js';
|
|
3
|
-
import { NotificationManager } from '../core/NotificationManager.js';
|
|
4
|
-
import { Translate } from '../core/Translate.js';
|
|
5
|
-
import { s } from '../core/VanillaJs.js';
|
|
6
2
|
import { ElementsDefault } from './ElementsDefault.js';
|
|
7
3
|
|
|
8
4
|
const LogOutDefault = async function () {
|
|
9
5
|
LogOut.Event['LogOutDefault'] = async (result = { user: { _id: '' } }) => {
|
|
10
6
|
ElementsDefault.Data.user.main.model.user = result.user;
|
|
11
|
-
|
|
12
|
-
s(`.main-btn-log-out`).style.display = 'none';
|
|
13
|
-
s(`.main-btn-account`).style.display = 'none';
|
|
14
|
-
s(`.main-btn-log-in`).style.display = null;
|
|
15
|
-
s(`.main-btn-sign-up`).style.display = null;
|
|
16
|
-
if (s(`.modal-log-out`)) s(`.btn-close-modal-log-out`).click();
|
|
17
|
-
if (s(`.modal-account`)) s(`.btn-close-modal-account`).click();
|
|
18
|
-
|
|
19
|
-
NotificationManager.Push({
|
|
20
|
-
html: Translate.Render(`success-logout`),
|
|
21
|
-
status: 'success',
|
|
22
|
-
});
|
|
23
7
|
};
|
|
24
8
|
};
|
|
25
9
|
|
|
@@ -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
|
|
|
@@ -33,7 +33,11 @@ const getWsBaseUrl = (options = { id: '', endpoint: '', wsBasePath: '' }) =>
|
|
|
33
33
|
}${options?.endpoint ? options.endpoint : ''}${options?.id ? `/${options.id}` : ''}`;
|
|
34
34
|
|
|
35
35
|
const headersFactory = (headerId = '') => {
|
|
36
|
-
const headers = {
|
|
36
|
+
const headers = {
|
|
37
|
+
Authorization: Auth.getJWT(),
|
|
38
|
+
withCredentials: true,
|
|
39
|
+
credentials: 'include', // no cors: 'same-origin'
|
|
40
|
+
};
|
|
37
41
|
switch (headerId) {
|
|
38
42
|
case 'file':
|
|
39
43
|
return headers;
|
|
@@ -7,6 +7,7 @@ import { loggerFactory } from '../../components/core/Logger.js';
|
|
|
7
7
|
import { Modal } from '../../components/core/Modal.js';
|
|
8
8
|
import { NotificationManager } from '../../components/core/NotificationManager.js';
|
|
9
9
|
import { Translate } from '../../components/core/Translate.js';
|
|
10
|
+
import { getQueryParams, RouterEvents, setQueryParams } from '../../components/core/Router.js';
|
|
10
11
|
import { s } from '../../components/core/VanillaJs.js';
|
|
11
12
|
import { DefaultService } from './default.service.js';
|
|
12
13
|
|
|
@@ -47,19 +48,48 @@ const columnDefFormatter = (obj, columnDefs, customFormat) => {
|
|
|
47
48
|
|
|
48
49
|
const DefaultManagement = {
|
|
49
50
|
Tokens: {},
|
|
51
|
+
loadTable: async function (id, options = { reload: true }) {
|
|
52
|
+
const { serviceId, columnDefs, customFormat } = this.Tokens[id];
|
|
53
|
+
const result = await this.Tokens[id].ServiceProvider.get({
|
|
54
|
+
page: this.Tokens[id].page,
|
|
55
|
+
limit: this.Tokens[id].limit,
|
|
56
|
+
id: this.Tokens[id].serviceOptions?.get?.id ?? undefined,
|
|
57
|
+
});
|
|
58
|
+
if (result.status === 'success') {
|
|
59
|
+
const { data, total, page, totalPages } = result.data;
|
|
60
|
+
this.Tokens[id].total = total;
|
|
61
|
+
this.Tokens[id].page = page;
|
|
62
|
+
this.Tokens[id].totalPages = totalPages;
|
|
63
|
+
const rowDataScope = data.map((row) => columnDefFormatter(row, columnDefs, customFormat));
|
|
64
|
+
if (options.reload) AgGrid.grids[this.Tokens[id].gridId].setGridOption('rowData', rowDataScope);
|
|
65
|
+
const paginationComp = s(`#ag-pagination-${this.Tokens[id].gridId}`);
|
|
66
|
+
paginationComp.setAttribute('current-page', this.Tokens[id].page);
|
|
67
|
+
paginationComp.setAttribute('total-pages', this.Tokens[id].totalPages);
|
|
68
|
+
paginationComp.setAttribute('total-items', this.Tokens[id].total);
|
|
69
|
+
}
|
|
70
|
+
},
|
|
50
71
|
RenderTable: async function (options = DefaultOptions) {
|
|
51
72
|
if (!options) options = DefaultOptions;
|
|
52
73
|
const { serviceId, columnDefs, entity, defaultColKeyFocus, ServiceProvider, permissions } = options;
|
|
53
74
|
logger.info('DefaultManagement RenderTable', options);
|
|
54
75
|
const id = options?.idModal ? options.idModal : getId(this.Tokens, `${serviceId}-`);
|
|
55
76
|
const gridId = `${serviceId}-grid-${id}`;
|
|
56
|
-
|
|
77
|
+
const queryParams = getQueryParams();
|
|
78
|
+
const page = parseInt(queryParams.page) || 1;
|
|
79
|
+
const limit = parseInt(queryParams.limit) || 10;
|
|
80
|
+
this.Tokens[id] = {
|
|
81
|
+
...options,
|
|
82
|
+
gridId,
|
|
83
|
+
page,
|
|
84
|
+
limit,
|
|
85
|
+
total: 0,
|
|
86
|
+
totalPages: 1,
|
|
87
|
+
};
|
|
57
88
|
|
|
89
|
+
setQueryParams({ page, limit });
|
|
58
90
|
setTimeout(async () => {
|
|
59
91
|
// https://www.ag-grid.com/javascript-data-grid/data-update-transactions/
|
|
60
92
|
|
|
61
|
-
let rowDataScope = [];
|
|
62
|
-
|
|
63
93
|
class RemoveActionGridRenderer {
|
|
64
94
|
eGui;
|
|
65
95
|
tokens;
|
|
@@ -110,6 +140,16 @@ const DefaultManagement = {
|
|
|
110
140
|
});
|
|
111
141
|
if (result.status === 'success') {
|
|
112
142
|
AgGrid.grids[gridId].applyTransaction({ remove: [params.data] });
|
|
143
|
+
const token = DefaultManagement.Tokens[id];
|
|
144
|
+
// if we are on the last page and we delete the last item, go to the previous page
|
|
145
|
+
const newTotal = token.total - 1;
|
|
146
|
+
const newTotalPages = Math.ceil(newTotal / token.limit);
|
|
147
|
+
if (token.page > newTotalPages && newTotalPages > 0) {
|
|
148
|
+
token.page = newTotalPages;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// reload the current page
|
|
152
|
+
await DefaultManagement.loadTable(id, { reload: false });
|
|
113
153
|
}
|
|
114
154
|
},
|
|
115
155
|
{ context: 'modal' },
|
|
@@ -142,13 +182,14 @@ const DefaultManagement = {
|
|
|
142
182
|
: [],
|
|
143
183
|
),
|
|
144
184
|
);
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
}
|
|
185
|
+
DefaultManagement.loadTable(id);
|
|
186
|
+
// {
|
|
187
|
+
// const result = await ServiceProvider.get();
|
|
188
|
+
// if (result.status === 'success') {
|
|
189
|
+
// rowDataScope = result.data.map((row) => columnDefFormatter(row, columnDefs, options.customFormat));
|
|
190
|
+
// AgGrid.grids[gridId].setGridOption('rowData', rowDataScope);
|
|
191
|
+
// }
|
|
192
|
+
// }
|
|
152
193
|
s(`.management-table-btn-save-${id}`).onclick = () => {
|
|
153
194
|
AgGrid.grids[gridId].stopEditing();
|
|
154
195
|
};
|
|
@@ -168,9 +209,13 @@ const DefaultManagement = {
|
|
|
168
209
|
// });
|
|
169
210
|
if (result.status === 'success') {
|
|
170
211
|
AgGrid.grids[gridId].applyTransaction({
|
|
171
|
-
add: [columnDefFormatter(
|
|
212
|
+
add: [columnDefFormatter(rowObj, columnDefs, options.customFormat)],
|
|
172
213
|
addIndex: 0,
|
|
173
214
|
});
|
|
215
|
+
// AgGrid.grids[gridId].applyTransaction({
|
|
216
|
+
// add: [columnDefFormatter(result.data, columnDefs, options.customFormat)],
|
|
217
|
+
// addIndex: 0,
|
|
218
|
+
// });
|
|
174
219
|
// AgGrid.grids[gridId].applyColumnState({
|
|
175
220
|
// state: [
|
|
176
221
|
// // { colId: 'country', sort: 'asc', sortIndex: 1 },
|
|
@@ -244,9 +289,34 @@ const DefaultManagement = {
|
|
|
244
289
|
status: result.status,
|
|
245
290
|
});
|
|
246
291
|
if (result.status === 'success') {
|
|
247
|
-
|
|
292
|
+
DefaultManagement.loadTable(id);
|
|
248
293
|
}
|
|
249
294
|
});
|
|
295
|
+
s(`#ag-pagination-${gridId}`).addEventListener('page-change', async (event) => {
|
|
296
|
+
const token = DefaultManagement.Tokens[id];
|
|
297
|
+
token.page = event.detail.page;
|
|
298
|
+
await DefaultManagement.loadTable(id);
|
|
299
|
+
});
|
|
300
|
+
s(`#ag-pagination-${gridId}`).addEventListener('limit-change', async (event) => {
|
|
301
|
+
const token = DefaultManagement.Tokens[id];
|
|
302
|
+
token.limit = event.detail.limit;
|
|
303
|
+
token.page = 1; // Reset to first page
|
|
304
|
+
await DefaultManagement.loadTable(id);
|
|
305
|
+
});
|
|
306
|
+
RouterEvents[id] = async (...args) => {
|
|
307
|
+
const queryParams = getQueryParams();
|
|
308
|
+
const page = parseInt(queryParams.page) || 1;
|
|
309
|
+
const limit = parseInt(queryParams.limit) || 10;
|
|
310
|
+
const token = DefaultManagement.Tokens[id];
|
|
311
|
+
|
|
312
|
+
// Check if the pagination state in the URL is different from the current state
|
|
313
|
+
if (token.page !== page || token.limit !== limit) {
|
|
314
|
+
token.page = page;
|
|
315
|
+
token.limit = limit;
|
|
316
|
+
// Reload the table with the new pagination state from the URL
|
|
317
|
+
await DefaultManagement.loadTable(id);
|
|
318
|
+
}
|
|
319
|
+
};
|
|
250
320
|
}, 1);
|
|
251
321
|
return html`<div class="fl">
|
|
252
322
|
${await BtnIcon.Render({
|
|
@@ -274,6 +344,7 @@ const DefaultManagement = {
|
|
|
274
344
|
<div class="in section-mp">
|
|
275
345
|
${await AgGrid.Render({
|
|
276
346
|
id: gridId,
|
|
347
|
+
usePagination: true,
|
|
277
348
|
darkTheme,
|
|
278
349
|
gridOptions: {
|
|
279
350
|
defaultColDef: {
|
|
@@ -327,7 +398,32 @@ const DefaultManagement = {
|
|
|
327
398
|
status: result.status,
|
|
328
399
|
});
|
|
329
400
|
if (result.status === 'success') {
|
|
330
|
-
|
|
401
|
+
this.Tokens[id].page = 1;
|
|
402
|
+
await DefaultManagement.loadTable(id);
|
|
403
|
+
// const newItemId = result.data?.[entity]?._id || result.data?._id;
|
|
404
|
+
// The `event.node.id` is the temporary ID assigned by AG Grid.
|
|
405
|
+
// const rowNode = AgGrid.grids[gridId].getRowNode(event.node.id);
|
|
406
|
+
setQueryParams({ page: 1, limit: this.Tokens[id].limit });
|
|
407
|
+
|
|
408
|
+
let rowNode;
|
|
409
|
+
AgGrid.grids[gridId].forEachLeafNode((_rowNode) => {
|
|
410
|
+
if (_rowNode.data._id === result.data._id) {
|
|
411
|
+
rowNode = _rowNode;
|
|
412
|
+
}
|
|
413
|
+
});
|
|
414
|
+
if (rowNode) {
|
|
415
|
+
const newRow = columnDefFormatter(result.data, columnDefs, options.customFormat);
|
|
416
|
+
// Add a temporary flag to the new row data.
|
|
417
|
+
newRow._new = true;
|
|
418
|
+
// Update the row data with the data from the server, which includes the new permanent `_id`.
|
|
419
|
+
rowNode.setData(newRow);
|
|
420
|
+
// The `rowClassRules` will automatically apply the 'row-new-highlight' class.
|
|
421
|
+
// Now, remove the flag after a delay to remove the highlight.
|
|
422
|
+
// setTimeout(() => {
|
|
423
|
+
// delete newRow._new;
|
|
424
|
+
// rowNode.setData(newRow);
|
|
425
|
+
// }, 2000);
|
|
426
|
+
}
|
|
331
427
|
}
|
|
332
428
|
} else {
|
|
333
429
|
const body = event.data ? event.data : {};
|
|
@@ -336,11 +432,12 @@ const DefaultManagement = {
|
|
|
336
432
|
html: result.status === 'error' ? result.message : `${Translate.Render('success-update-item')}`,
|
|
337
433
|
status: result.status,
|
|
338
434
|
});
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
435
|
+
if (result.status === 'success') {
|
|
436
|
+
AgGrid.grids[gridId].applyTransaction({
|
|
437
|
+
update: [event.data],
|
|
438
|
+
});
|
|
439
|
+
DefaultManagement.loadTable(id, { reload: false });
|
|
440
|
+
}
|
|
344
441
|
}
|
|
345
442
|
},
|
|
346
443
|
},
|
|
@@ -47,9 +47,13 @@ const DefaultService = {
|
|
|
47
47
|
return reject(error);
|
|
48
48
|
}),
|
|
49
49
|
),
|
|
50
|
-
get: (options = { id: '', body: {} }) =>
|
|
51
|
-
|
|
52
|
-
|
|
50
|
+
get: (options = { id: '', body: {}, page: 1, limit: 10 }) => {
|
|
51
|
+
const { id, page, limit } = options;
|
|
52
|
+
const url = new URL(getApiBaseUrl({ id, endpoint }));
|
|
53
|
+
url.searchParams.append('page', page);
|
|
54
|
+
url.searchParams.append('limit', limit);
|
|
55
|
+
return new Promise((resolve, reject) =>
|
|
56
|
+
fetch(url.toString(), {
|
|
53
57
|
method: 'GET',
|
|
54
58
|
headers: headersFactory(),
|
|
55
59
|
})
|
|
@@ -64,7 +68,8 @@ const DefaultService = {
|
|
|
64
68
|
logger.error(error);
|
|
65
69
|
return reject(error);
|
|
66
70
|
}),
|
|
67
|
-
)
|
|
71
|
+
);
|
|
72
|
+
},
|
|
68
73
|
delete: (options = { id: '', body: {} }) =>
|
|
69
74
|
new Promise((resolve, reject) =>
|
|
70
75
|
fetch(getApiBaseUrl({ id: options.id, endpoint }), {
|
|
@@ -13,6 +13,7 @@ const UserManagement = {
|
|
|
13
13
|
add: role === 'admin',
|
|
14
14
|
remove: role === 'admin',
|
|
15
15
|
},
|
|
16
|
+
usePagination: true,
|
|
16
17
|
columnDefs: [
|
|
17
18
|
{ field: 'username', headerName: 'username', editable: role === 'admin' },
|
|
18
19
|
{ field: 'email', headerName: 'email', editable: role === 'admin' },
|
|
@@ -44,6 +45,11 @@ const UserManagement = {
|
|
|
44
45
|
],
|
|
45
46
|
defaultColKeyFocus: 'username',
|
|
46
47
|
ServiceProvider: UserService,
|
|
48
|
+
serviceOptions: {
|
|
49
|
+
get: {
|
|
50
|
+
id: 'all',
|
|
51
|
+
},
|
|
52
|
+
},
|
|
47
53
|
});
|
|
48
54
|
},
|
|
49
55
|
};
|
|
@@ -36,9 +36,15 @@ const UserService = {
|
|
|
36
36
|
return reject(error);
|
|
37
37
|
}),
|
|
38
38
|
),
|
|
39
|
-
get: (options = { id: '' }) =>
|
|
40
|
-
|
|
41
|
-
|
|
39
|
+
get: (options = { id: '', page: 1, limit: 10 }) => {
|
|
40
|
+
const { id = '', page, limit } = options;
|
|
41
|
+
const query = new URLSearchParams();
|
|
42
|
+
if (page) query.set('page', page);
|
|
43
|
+
if (limit) query.set('limit', limit);
|
|
44
|
+
const queryString = query.toString();
|
|
45
|
+
const url = `${getApiBaseUrl({ id, endpoint })}${queryString ? (id.includes('?') ? '&' : '?') + queryString : ''}`;
|
|
46
|
+
return new Promise((resolve, reject) =>
|
|
47
|
+
fetch(url, {
|
|
42
48
|
method: 'GET',
|
|
43
49
|
headers: headersFactory(),
|
|
44
50
|
})
|
|
@@ -53,7 +59,8 @@ const UserService = {
|
|
|
53
59
|
logger.error(error);
|
|
54
60
|
return reject(error);
|
|
55
61
|
}),
|
|
56
|
-
)
|
|
62
|
+
);
|
|
63
|
+
},
|
|
57
64
|
delete: (options = { id: '', body: {} }) =>
|
|
58
65
|
new Promise((resolve, reject) =>
|
|
59
66
|
fetch(getApiBaseUrl({ id: options.id, endpoint }), {
|
package/src/index.js
CHANGED
|
@@ -35,7 +35,7 @@ class Underpost {
|
|
|
35
35
|
* @type {String}
|
|
36
36
|
* @memberof Underpost
|
|
37
37
|
*/
|
|
38
|
-
static version = 'v2.8.
|
|
38
|
+
static version = 'v2.8.873';
|
|
39
39
|
/**
|
|
40
40
|
* Repository cli API
|
|
41
41
|
* @static
|
|
@@ -171,6 +171,28 @@ const up = Underpost;
|
|
|
171
171
|
|
|
172
172
|
const underpost = Underpost;
|
|
173
173
|
|
|
174
|
-
export {
|
|
174
|
+
export {
|
|
175
|
+
underpost,
|
|
176
|
+
up,
|
|
177
|
+
Underpost,
|
|
178
|
+
UnderpostBaremetal,
|
|
179
|
+
UnderpostCloudInit,
|
|
180
|
+
UnderpostCluster,
|
|
181
|
+
UnderpostCron,
|
|
182
|
+
UnderpostDB,
|
|
183
|
+
UnderpostDeploy,
|
|
184
|
+
UnderpostRootEnv,
|
|
185
|
+
UnderpostFileStorage,
|
|
186
|
+
UnderpostImage,
|
|
187
|
+
UnderpostLxd,
|
|
188
|
+
UnderpostMonitor,
|
|
189
|
+
UnderpostRepository,
|
|
190
|
+
UnderpostRun,
|
|
191
|
+
UnderpostScript,
|
|
192
|
+
UnderpostSecret,
|
|
193
|
+
UnderpostSSH,
|
|
194
|
+
UnderpostTest,
|
|
195
|
+
UnderpostStartUp,
|
|
196
|
+
};
|
|
175
197
|
|
|
176
198
|
export default Underpost;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import fs from 'fs-extra';
|
|
2
|
-
import { shellCd, shellExec } from '../../server/process.js';
|
|
3
|
-
import { timer } from '../../client/components/core/CommonJs.js';
|
|
2
|
+
import { getRootDirectory, shellCd, shellExec } from '../../server/process.js';
|
|
4
3
|
import { loggerFactory } from '../../server/logger.js';
|
|
5
4
|
|
|
6
5
|
const logger = loggerFactory(import.meta);
|
|
@@ -107,6 +106,94 @@ const Lampp = {
|
|
|
107
106
|
break;
|
|
108
107
|
}
|
|
109
108
|
},
|
|
109
|
+
createApp: async ({ port, host, path, directory, rootHostPath, redirect, redirectTarget }) => {
|
|
110
|
+
if (!Lampp.enabled()) return { disabled: true };
|
|
111
|
+
if (!Lampp.ports.includes(port)) Lampp.ports.push(port);
|
|
112
|
+
if (currentPort === initPort) Lampp.removeRouter();
|
|
113
|
+
Lampp.appendRouter(`
|
|
114
|
+
Listen ${port}
|
|
115
|
+
|
|
116
|
+
<VirtualHost *:${port}>
|
|
117
|
+
DocumentRoot "${directory ? directory : `${getRootDirectory()}${rootHostPath}`}"
|
|
118
|
+
ServerName ${host}:${port}
|
|
119
|
+
|
|
120
|
+
<Directory "${directory ? directory : `${getRootDirectory()}${rootHostPath}`}">
|
|
121
|
+
Options Indexes FollowSymLinks MultiViews
|
|
122
|
+
AllowOverride All
|
|
123
|
+
Require all granted
|
|
124
|
+
</Directory>
|
|
125
|
+
|
|
126
|
+
${
|
|
127
|
+
redirect
|
|
128
|
+
? `
|
|
129
|
+
RewriteEngine on
|
|
130
|
+
|
|
131
|
+
RewriteCond %{REQUEST_URI} !^/.well-known/acme-challenge
|
|
132
|
+
RewriteRule ^(.*)$ ${redirectTarget}%{REQUEST_URI} [R=302,L]
|
|
133
|
+
`
|
|
134
|
+
: ''
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
ErrorDocument 400 ${path === '/' ? '' : path}/400.html
|
|
138
|
+
ErrorDocument 404 ${path === '/' ? '' : path}/400.html
|
|
139
|
+
ErrorDocument 500 ${path === '/' ? '' : path}/500.html
|
|
140
|
+
ErrorDocument 502 ${path === '/' ? '' : path}/500.html
|
|
141
|
+
ErrorDocument 503 ${path === '/' ? '' : path}/500.html
|
|
142
|
+
ErrorDocument 504 ${path === '/' ? '' : path}/500.html
|
|
143
|
+
|
|
144
|
+
</VirtualHost>
|
|
145
|
+
|
|
146
|
+
`);
|
|
147
|
+
// ERR too many redirects:
|
|
148
|
+
// Check: SELECT * FROM database.wp_options where option_name = 'siteurl' or option_name = 'home';
|
|
149
|
+
// Check: wp-config.php
|
|
150
|
+
// if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
|
|
151
|
+
// $_SERVER['HTTPS'] = 'on';
|
|
152
|
+
// }
|
|
153
|
+
// For plugins:
|
|
154
|
+
// define( 'FS_METHOD', 'direct' );
|
|
155
|
+
|
|
156
|
+
// ErrorDocument 404 /custom_404.html
|
|
157
|
+
// ErrorDocument 500 /custom_50x.html
|
|
158
|
+
// ErrorDocument 502 /custom_50x.html
|
|
159
|
+
// ErrorDocument 503 /custom_50x.html
|
|
160
|
+
// ErrorDocument 504 /custom_50x.html
|
|
161
|
+
|
|
162
|
+
// Respond When Error Pages are Directly Requested
|
|
163
|
+
|
|
164
|
+
// <Files "custom_404.html">
|
|
165
|
+
// <If "-z %{ENV:REDIRECT_STATUS}">
|
|
166
|
+
// RedirectMatch 404 ^/custom_404.html$
|
|
167
|
+
// </If>
|
|
168
|
+
// </Files>
|
|
169
|
+
|
|
170
|
+
// <Files "custom_50x.html">
|
|
171
|
+
// <If "-z %{ENV:REDIRECT_STATUS}">
|
|
172
|
+
// RedirectMatch 404 ^/custom_50x.html$
|
|
173
|
+
// </If>
|
|
174
|
+
// </Files>
|
|
175
|
+
|
|
176
|
+
// Add www or https with htaccess rewrite
|
|
177
|
+
|
|
178
|
+
// Options +FollowSymLinks
|
|
179
|
+
// RewriteEngine On
|
|
180
|
+
// RewriteCond %{HTTP_HOST} ^ejemplo.com [NC]
|
|
181
|
+
// RewriteRule ^(.*)$ http://ejemplo.com/$1 [R=301,L]
|
|
182
|
+
|
|
183
|
+
// Redirect http to https with htaccess rewrite
|
|
184
|
+
|
|
185
|
+
// RewriteEngine On
|
|
186
|
+
// RewriteCond %{SERVER_PORT} 80
|
|
187
|
+
// RewriteRule ^(.*)$ https://www.ejemplo.com/$1 [R,L]
|
|
188
|
+
|
|
189
|
+
// Redirect to HTTPS with www subdomain
|
|
190
|
+
|
|
191
|
+
// RewriteEngine On
|
|
192
|
+
// RewriteCond %{HTTPS} off [OR]
|
|
193
|
+
// RewriteCond %{HTTP_HOST} ^www\. [NC]
|
|
194
|
+
// RewriteCond %{HTTP_HOST} ^(?:www\.)?(.+)$ [NC]
|
|
195
|
+
// RewriteRule ^ https://%1%{REQUEST_URI} [L,NE,R=301]
|
|
196
|
+
},
|
|
110
197
|
};
|
|
111
198
|
|
|
112
199
|
export { Lampp };
|