underpost 2.8.55 → 2.8.61
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/ghpkg.yml +1 -1
- package/.github/workflows/npmpkg.yml +1 -1
- package/.github/workflows/pwa-microservices-template.page.yml +1 -1
- package/.vscode/settings.json +3 -0
- package/bin/build.js +9 -0
- package/bin/index.js +31 -6
- package/bin/vs.js +1 -0
- package/docker-compose.yml +1 -1
- package/manifests/kind-config-dev.yaml +12 -0
- package/manifests/mongodb/kustomization.yaml +2 -2
- package/manifests/mongodb-4.4/service-deployment.yaml +4 -4
- package/package.json +8 -7
- package/src/cli/cluster.js +56 -30
- package/src/cli/cron.js +1 -1
- package/src/cli/db.js +102 -38
- package/src/cli/deploy.js +27 -6
- package/src/cli/fs.js +149 -0
- package/src/cli/image.js +36 -4
- package/src/cli/repository.js +21 -0
- package/src/cli/test.js +17 -6
- package/src/client/components/core/CalendarCore.js +12 -1
- package/src/client/components/core/CommonJs.js +52 -1
- package/src/client/components/core/CssCore.js +2 -4
- package/src/client/components/core/Docs.js +1 -2
- package/src/client/components/core/Input.js +4 -2
- package/src/client/components/core/LoadingAnimation.js +8 -1
- package/src/client/components/core/Modal.js +30 -6
- package/src/client/components/core/Panel.js +8 -6
- package/src/client/components/core/PanelForm.js +23 -7
- package/src/client/services/core/core.service.js +15 -10
- package/src/client/ssr/Render.js +4 -1
- package/src/client/ssr/body/CacheControl.js +2 -3
- package/src/client/sw/default.sw.js +3 -3
- package/src/index.js +9 -1
- package/src/server/backup.js +2 -2
- package/src/server/client-build.js +32 -23
- package/src/server/client-formatted.js +2 -1
- package/src/server/conf.js +1 -1
- package/src/server/dns.js +2 -2
- package/src/server/runtime.js +16 -1
- package/manifests/valkey/underpost-engine-valkey-service.yaml +0 -17
- package/manifests/valkey/underpost-engine-valkey-statefulset.yaml +0 -39
package/src/cli/deploy.js
CHANGED
|
@@ -32,7 +32,7 @@ class UnderpostDeploy {
|
|
|
32
32
|
await Config.build(undefined, 'proxy', deployList);
|
|
33
33
|
return buildPortProxyRouter(env === 'development' ? 80 : 443, buildProxyRouter());
|
|
34
34
|
},
|
|
35
|
-
async buildManifest(deployList, env) {
|
|
35
|
+
async buildManifest(deployList, env, version) {
|
|
36
36
|
for (const _deployId of deployList.split(',')) {
|
|
37
37
|
const deployId = _deployId.trim();
|
|
38
38
|
if (!deployId) continue;
|
|
@@ -69,7 +69,18 @@ spec:
|
|
|
69
69
|
spec:
|
|
70
70
|
containers:
|
|
71
71
|
- name: ${deployId}-${env}
|
|
72
|
-
image: localhost
|
|
72
|
+
image: localhost/underpost-engine:${version && typeof version === 'string' ? version : Underpost.version}
|
|
73
|
+
lifecycle:
|
|
74
|
+
postStart:
|
|
75
|
+
exec:
|
|
76
|
+
command:
|
|
77
|
+
- /bin/sh
|
|
78
|
+
- -c
|
|
79
|
+
- >
|
|
80
|
+
sleep 60 &&
|
|
81
|
+
underpost config set deploy-id ${deployId} &&
|
|
82
|
+
underpost config set deploy-env ${env}
|
|
83
|
+
# image: localhost/${deployId}-${env}:${version && typeof version === 'string' ? version : Underpost.version}
|
|
73
84
|
---
|
|
74
85
|
apiVersion: v1
|
|
75
86
|
kind: Service
|
|
@@ -180,7 +191,16 @@ spec:
|
|
|
180
191
|
async callback(
|
|
181
192
|
deployList = 'default',
|
|
182
193
|
env = 'development',
|
|
183
|
-
options = {
|
|
194
|
+
options = {
|
|
195
|
+
remove: false,
|
|
196
|
+
infoRouter: false,
|
|
197
|
+
sync: false,
|
|
198
|
+
buildManifest: false,
|
|
199
|
+
infoUtil: false,
|
|
200
|
+
expose: false,
|
|
201
|
+
cert: false,
|
|
202
|
+
version: '',
|
|
203
|
+
},
|
|
184
204
|
) {
|
|
185
205
|
if (options.infoUtil === true)
|
|
186
206
|
return logger.info(`
|
|
@@ -191,7 +211,7 @@ kubectl scale statefulsets <stateful-set-name> --replicas=<new-replicas>
|
|
|
191
211
|
if (deployList === 'dd' && fs.existsSync(`./engine-private/deploy/dd.router`))
|
|
192
212
|
deployList = fs.readFileSync(`./engine-private/deploy/dd.router`, 'utf8');
|
|
193
213
|
if (options.sync) UnderpostDeploy.API.sync(deployList);
|
|
194
|
-
if (options.buildManifest === true) await UnderpostDeploy.API.buildManifest(deployList, env);
|
|
214
|
+
if (options.buildManifest === true) await UnderpostDeploy.API.buildManifest(deployList, env, options.version);
|
|
195
215
|
if (options.infoRouter === true)
|
|
196
216
|
return logger.info('router', await UnderpostDeploy.API.routerFactory(deployList, env));
|
|
197
217
|
const etcHost = (
|
|
@@ -219,7 +239,7 @@ kubectl scale statefulsets <stateful-set-name> --replicas=<new-replicas>
|
|
|
219
239
|
const confServer = JSON.parse(fs.readFileSync(`./engine-private/conf/${deployId}/conf.server.json`, 'utf8'));
|
|
220
240
|
for (const host of Object.keys(confServer)) {
|
|
221
241
|
shellExec(`sudo kubectl delete HTTPProxy ${host}`);
|
|
222
|
-
if (env === 'production') shellExec(`sudo kubectl delete Certificate ${host}`);
|
|
242
|
+
if (env === 'production' && options.cert === true) shellExec(`sudo kubectl delete Certificate ${host}`);
|
|
223
243
|
if (!options.remove === true && env === 'development') concatHots += ` ${host}`;
|
|
224
244
|
}
|
|
225
245
|
|
|
@@ -231,7 +251,8 @@ kubectl scale statefulsets <stateful-set-name> --replicas=<new-replicas>
|
|
|
231
251
|
if (!options.remove === true) {
|
|
232
252
|
shellExec(`sudo kubectl apply -f ./${manifestsPath}/deployment.yaml`);
|
|
233
253
|
shellExec(`sudo kubectl apply -f ./${manifestsPath}/proxy.yaml`);
|
|
234
|
-
if (env === 'production'
|
|
254
|
+
if (env === 'production' && options.cert === true)
|
|
255
|
+
shellExec(`sudo kubectl apply -f ./${manifestsPath}/secret.yaml`);
|
|
235
256
|
}
|
|
236
257
|
}
|
|
237
258
|
let renderHosts;
|
package/src/cli/fs.js
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { v2 as cloudinary } from 'cloudinary';
|
|
2
|
+
import { loggerFactory } from '../server/logger.js';
|
|
3
|
+
import dotenv from 'dotenv';
|
|
4
|
+
import AdmZip from 'adm-zip';
|
|
5
|
+
import * as dir from 'path';
|
|
6
|
+
import fs from 'fs-extra';
|
|
7
|
+
import { Downloader } from '../server/downloader.js';
|
|
8
|
+
import UnderpostRepository from './repository.js';
|
|
9
|
+
import { shellExec } from '../server/process.js';
|
|
10
|
+
dotenv.config();
|
|
11
|
+
|
|
12
|
+
const logger = loggerFactory(import.meta);
|
|
13
|
+
|
|
14
|
+
class UnderpostFileStorage {
|
|
15
|
+
static API = {
|
|
16
|
+
cloudinaryConfig() {
|
|
17
|
+
// https://console.cloudinary.com/
|
|
18
|
+
cloudinary.config({
|
|
19
|
+
cloud_name: process.env.CLOUDINARY_CLOUD_NAME,
|
|
20
|
+
api_key: process.env.CLOUDINARY_API_KEY,
|
|
21
|
+
api_secret: process.env.CLOUDINARY_API_SECRET,
|
|
22
|
+
});
|
|
23
|
+
},
|
|
24
|
+
getStorageConf(options) {
|
|
25
|
+
let storage, storageConf;
|
|
26
|
+
if (options.deployId && typeof options.deployId === 'string') {
|
|
27
|
+
storageConf = `./engine-private/conf/${options.deployId}/storage.json`;
|
|
28
|
+
if (!fs.existsSync(storageConf)) fs.writeFileSync(storageConf, JSON.stringify({}), 'utf8');
|
|
29
|
+
storage = JSON.parse(fs.readFileSync(storageConf, 'utf8'));
|
|
30
|
+
}
|
|
31
|
+
return { storage, storageConf };
|
|
32
|
+
},
|
|
33
|
+
writeStorageConf(storage, storageConf) {
|
|
34
|
+
if (storage) fs.writeFileSync(storageConf, JSON.stringify(storage, null, 4), 'utf8');
|
|
35
|
+
},
|
|
36
|
+
async recursiveCallback(
|
|
37
|
+
path,
|
|
38
|
+
options = { rm: false, recursive: false, deployId: '', force: false, pull: false, git: false },
|
|
39
|
+
) {
|
|
40
|
+
const { storage, storageConf } = UnderpostFileStorage.API.getStorageConf(options);
|
|
41
|
+
const deleteFiles = UnderpostRepository.API.getDeleteFiles(path);
|
|
42
|
+
for (const relativePath of deleteFiles) {
|
|
43
|
+
const _path = path + '/' + relativePath;
|
|
44
|
+
if (_path in storage) {
|
|
45
|
+
await UnderpostFileStorage.API.delete(_path);
|
|
46
|
+
delete storage[_path];
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
const files =
|
|
50
|
+
options.git === true
|
|
51
|
+
? UnderpostRepository.API.getChangedFiles(path)
|
|
52
|
+
: await fs.readdir(path, { recursive: true });
|
|
53
|
+
if (options.pull === true) {
|
|
54
|
+
for (const _path of Object.keys(storage)) {
|
|
55
|
+
if (!fs.existsSync(_path) || options.force === true) {
|
|
56
|
+
if (options.force === true && fs.existsSync(_path)) fs.removeSync(_path);
|
|
57
|
+
await UnderpostFileStorage.API.pull(_path, options);
|
|
58
|
+
} else logger.warn(`Pull path already exists`, _path);
|
|
59
|
+
}
|
|
60
|
+
} else
|
|
61
|
+
for (const relativePath of files) {
|
|
62
|
+
const _path = path + '/' + relativePath;
|
|
63
|
+
if (fs.statSync(_path).isDirectory()) {
|
|
64
|
+
if (options.pull === true && !fs.existsSync(_path)) fs.mkdirSync(_path, { recursive: true });
|
|
65
|
+
continue;
|
|
66
|
+
} else if (!(_path in storage) || options.force === true) {
|
|
67
|
+
await UnderpostFileStorage.API.upload(_path, options);
|
|
68
|
+
if (storage) storage[_path] = {};
|
|
69
|
+
} else logger.warn('File already exists', _path);
|
|
70
|
+
}
|
|
71
|
+
UnderpostFileStorage.API.writeStorageConf(storage, storageConf);
|
|
72
|
+
if (options.git === true) {
|
|
73
|
+
shellExec(`cd ${path} && git add .`);
|
|
74
|
+
shellExec(`underpost cmt ${path} feat`);
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
async callback(
|
|
78
|
+
path,
|
|
79
|
+
options = { rm: false, recursive: false, deployId: '', force: false, pull: false, git: false },
|
|
80
|
+
) {
|
|
81
|
+
if (options.recursive === true || options.git === true)
|
|
82
|
+
return await UnderpostFileStorage.API.recursiveCallback(path, options);
|
|
83
|
+
if (options.pull === true) return await UnderpostFileStorage.API.pull(path, options);
|
|
84
|
+
if (options.rm === true) return await UnderpostFileStorage.API.delete(path, options);
|
|
85
|
+
return await UnderpostFileStorage.API.upload(path, options);
|
|
86
|
+
},
|
|
87
|
+
async upload(path, options = { rm: false, recursive: false, deployId: '', force: false, pull: false }) {
|
|
88
|
+
UnderpostFileStorage.API.cloudinaryConfig();
|
|
89
|
+
const { storage, storageConf } = UnderpostFileStorage.API.getStorageConf(options);
|
|
90
|
+
// path = UnderpostFileStorage.API.file2Zip(path);
|
|
91
|
+
const uploadResult = await cloudinary.uploader
|
|
92
|
+
.upload(path, {
|
|
93
|
+
public_id: path,
|
|
94
|
+
resource_type: 'raw',
|
|
95
|
+
overwrite: options.force === true ? true : false,
|
|
96
|
+
})
|
|
97
|
+
.catch((error) => {
|
|
98
|
+
logger.error(error, { path, stack: error.stack });
|
|
99
|
+
});
|
|
100
|
+
logger.info('upload result', uploadResult);
|
|
101
|
+
if (storage) storage[path] = {};
|
|
102
|
+
UnderpostFileStorage.API.writeStorageConf(storage, storageConf);
|
|
103
|
+
return uploadResult;
|
|
104
|
+
},
|
|
105
|
+
async pull(path) {
|
|
106
|
+
UnderpostFileStorage.API.cloudinaryConfig();
|
|
107
|
+
const folder = dir.dirname(path);
|
|
108
|
+
if (!fs.existsSync(folder)) fs.mkdirSync(folder, { recursive: true });
|
|
109
|
+
const downloadResult = await cloudinary.utils.download_archive_url({
|
|
110
|
+
public_ids: [path],
|
|
111
|
+
resource_type: 'raw',
|
|
112
|
+
});
|
|
113
|
+
logger.info('download result', downloadResult);
|
|
114
|
+
await Downloader(downloadResult, path + '.zip');
|
|
115
|
+
path = UnderpostFileStorage.API.zip2File(path + '.zip');
|
|
116
|
+
fs.removeSync(path + '.zip');
|
|
117
|
+
},
|
|
118
|
+
async delete(path) {
|
|
119
|
+
UnderpostFileStorage.API.cloudinaryConfig();
|
|
120
|
+
const deleteResult = await cloudinary.api
|
|
121
|
+
.delete_resources([path], { type: 'upload', resource_type: 'raw' })
|
|
122
|
+
.catch((error) => {
|
|
123
|
+
logger.error(error, { path, stack: error.stack });
|
|
124
|
+
});
|
|
125
|
+
logger.info('delete result', deleteResult);
|
|
126
|
+
return deleteResult;
|
|
127
|
+
},
|
|
128
|
+
file2Zip(path) {
|
|
129
|
+
const zip = new AdmZip();
|
|
130
|
+
zip.addLocalFile(path, '/');
|
|
131
|
+
path = path + '.zip';
|
|
132
|
+
zip.writeZip(path);
|
|
133
|
+
return path;
|
|
134
|
+
},
|
|
135
|
+
zip2File(path) {
|
|
136
|
+
const zip = new AdmZip(path);
|
|
137
|
+
path = path.replaceAll('.zip', '');
|
|
138
|
+
zip.extractEntryTo(
|
|
139
|
+
/*entry name*/ path.split('/').pop(),
|
|
140
|
+
/*target path*/ dir.dirname(path),
|
|
141
|
+
/*maintainEntryPath*/ false,
|
|
142
|
+
/*overwrite*/ true,
|
|
143
|
+
);
|
|
144
|
+
return path;
|
|
145
|
+
},
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export default UnderpostFileStorage;
|
package/src/cli/image.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import fs from 'fs-extra';
|
|
2
2
|
import Underpost from '../index.js';
|
|
3
|
-
import { shellExec } from '../server/process.js';
|
|
3
|
+
import { shellCd, shellExec } from '../server/process.js';
|
|
4
4
|
import dotenv from 'dotenv';
|
|
5
5
|
import { getNpmRootPath } from '../server/conf.js';
|
|
6
6
|
import { timer } from '../client/components/core/CommonJs.js';
|
|
7
|
+
import UnderpostRootEnv from './env.js';
|
|
7
8
|
|
|
8
9
|
dotenv.config();
|
|
9
10
|
|
|
@@ -17,9 +18,13 @@ class UnderpostImage {
|
|
|
17
18
|
deployId = 'default',
|
|
18
19
|
env = 'development',
|
|
19
20
|
path = '.',
|
|
20
|
-
options = { imageArchive: false, podmanSave: false },
|
|
21
|
+
options = { imageArchive: false, podmanSave: false, imageName: '', imageVersion: '' },
|
|
21
22
|
) {
|
|
22
|
-
const imgName = `${
|
|
23
|
+
const imgName = `${
|
|
24
|
+
options.imageName && typeof options.imageName === 'string' ? options.imageName : `${deployId}-${env}`
|
|
25
|
+
}:${
|
|
26
|
+
options.imageVersion && typeof options.imageVersions === 'string' ? options.imageVersion : Underpost.version
|
|
27
|
+
}`;
|
|
23
28
|
const podManImg = `localhost/${imgName}`;
|
|
24
29
|
const imagesStoragePath = `/images`;
|
|
25
30
|
if (!fs.existsSync(`${path}${imagesStoragePath}`))
|
|
@@ -48,7 +53,34 @@ class UnderpostImage {
|
|
|
48
53
|
shellExec(`cd ${path} && podman save -o ${tarFile} ${podManImg}`);
|
|
49
54
|
shellExec(`cd ${path} && sudo kind load image-archive ${tarFile}`);
|
|
50
55
|
},
|
|
51
|
-
async script(deployId = 'default', env = 'development', options = { run: false }) {
|
|
56
|
+
async script(deployId = 'default', env = 'development', options = { run: false, build: false }) {
|
|
57
|
+
if (deployId === 'deploy') {
|
|
58
|
+
const _deployId = UnderpostRootEnv.API.get('deploy-id');
|
|
59
|
+
const _env = UnderpostRootEnv.API.get('deploy-env');
|
|
60
|
+
const _path = UnderpostRootEnv.API.get('deploy-path');
|
|
61
|
+
if (_deployId) {
|
|
62
|
+
deployId = _deployId;
|
|
63
|
+
if (_env) env = _env;
|
|
64
|
+
if (_path) path = _path;
|
|
65
|
+
} else {
|
|
66
|
+
await timer(30 * 1000);
|
|
67
|
+
return await UnderpostImage.API.script(deployId, env, path, options);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
if (options.build === true) {
|
|
71
|
+
const buildBasePath = `/home/dd`;
|
|
72
|
+
const repoName = `engine-${deployId.split('-')[1]}`;
|
|
73
|
+
fs.mkdirSync(buildBasePath, { recursive: true });
|
|
74
|
+
shellExec(`cd ${buildBasePath} && underpost clone underpostnet/${repoName}`);
|
|
75
|
+
shellExec(`cd ${buildBasePath} && sudo mv ./${repoName} ./engine`);
|
|
76
|
+
shellExec(`cd ${buildBasePath}/engine && underpost clone underpostnet/${repoName}-private`);
|
|
77
|
+
shellExec(`cd ${buildBasePath}/engine && sudo mv ./${repoName}-private ./engine-private`);
|
|
78
|
+
shellCd(`${buildBasePath}/engine`);
|
|
79
|
+
shellExec(`npm install`);
|
|
80
|
+
const itcScripts = fs.readdir('./engine-private/itc-scripts');
|
|
81
|
+
for (const itcScript of itcScripts)
|
|
82
|
+
if (itcScript.match(deployId)) shellExec(`node ./engine-private/itc-scripts/${itcScript}`);
|
|
83
|
+
}
|
|
52
84
|
switch (deployId) {
|
|
53
85
|
case 'dd-lampp':
|
|
54
86
|
{
|
package/src/cli/repository.js
CHANGED
|
@@ -98,6 +98,27 @@ class UnderpostRepository {
|
|
|
98
98
|
}
|
|
99
99
|
});
|
|
100
100
|
},
|
|
101
|
+
|
|
102
|
+
getDeleteFiles(path = '.') {
|
|
103
|
+
const commandUntrack = `cd ${path} && git ls-files --deleted`;
|
|
104
|
+
const diffUntrackOutput = shellExec(commandUntrack, { stdout: true, silent: true });
|
|
105
|
+
return diffUntrackOutput.toString().split('\n').filter(Boolean);
|
|
106
|
+
},
|
|
107
|
+
|
|
108
|
+
getChangedFiles(path = '.', extension = '', head = false) {
|
|
109
|
+
const extensionFilter = extension ? `-- '***.${extension}'` : '';
|
|
110
|
+
const command = `cd ${path} && git diff ${head ? 'HEAD^ HEAD ' : ''}--name-only ${extensionFilter}`;
|
|
111
|
+
const commandUntrack = `cd ${path} && git ls-files --others --exclude-standard`;
|
|
112
|
+
const diffOutput = shellExec(command, { stdout: true, silent: true });
|
|
113
|
+
const diffUntrackOutput = shellExec(commandUntrack, { stdout: true, silent: true });
|
|
114
|
+
const deleteFiles = UnderpostRepository.API.getDeleteFiles(path);
|
|
115
|
+
return diffOutput
|
|
116
|
+
.toString()
|
|
117
|
+
.split('\n')
|
|
118
|
+
.filter(Boolean)
|
|
119
|
+
.concat(diffUntrackOutput.toString().split('\n').filter(Boolean))
|
|
120
|
+
.filter((f) => !deleteFiles.includes(f));
|
|
121
|
+
},
|
|
101
122
|
};
|
|
102
123
|
}
|
|
103
124
|
|
package/src/cli/test.js
CHANGED
|
@@ -36,7 +36,7 @@ class UnderpostTest {
|
|
|
36
36
|
options.podStatus &&
|
|
37
37
|
typeof options.podStatus === 'string'
|
|
38
38
|
)
|
|
39
|
-
return await UnderpostTest.API.
|
|
39
|
+
return await UnderpostTest.API.statusMonitor(options.podName, options.podStatus, options.kindType);
|
|
40
40
|
|
|
41
41
|
if (options.sh === true || options.logs === true) {
|
|
42
42
|
const [pod] = UnderpostDeploy.API.get(deployList);
|
|
@@ -86,16 +86,27 @@ class UnderpostTest {
|
|
|
86
86
|
}
|
|
87
87
|
} else return UnderpostTest.API.run();
|
|
88
88
|
},
|
|
89
|
-
|
|
89
|
+
statusMonitor(podName, status = 'Running', kindType = '', deltaMs = 1000, maxAttempts = 60 * 5) {
|
|
90
|
+
if (!(kindType && typeof kindType === 'string')) kindType = 'pods';
|
|
90
91
|
return new Promise(async (resolve) => {
|
|
91
92
|
let index = 0;
|
|
92
|
-
logger.info(`Loading
|
|
93
|
+
logger.info(`Loading instance`, { podName, status, kindType, deltaMs, maxAttempts });
|
|
93
94
|
const _monitor = async () => {
|
|
94
95
|
await timer(deltaMs);
|
|
95
|
-
const
|
|
96
|
-
|
|
97
|
-
|
|
96
|
+
const pods = UnderpostDeploy.API.get(podName, kindType);
|
|
97
|
+
const result = pods.find((p) => p.STATUS === status);
|
|
98
|
+
logger.info(
|
|
99
|
+
`Testing pod ${podName}... ${result ? 1 : 0}/1 - elapsed time ${deltaMs * (index + 1)}s - attempt ${
|
|
100
|
+
index + 1
|
|
101
|
+
}/${maxAttempts}`,
|
|
102
|
+
pods[0] ? pods[0].STATUS : 'Not found kind object',
|
|
103
|
+
);
|
|
104
|
+
if (result) return resolve(true);
|
|
98
105
|
index++;
|
|
106
|
+
if (index === maxAttempts) {
|
|
107
|
+
logger.error(`Failed to test pod ${podName} within ${maxAttempts} attempts`);
|
|
108
|
+
return resolve(false);
|
|
109
|
+
}
|
|
99
110
|
return _monitor();
|
|
100
111
|
};
|
|
101
112
|
await _monitor();
|
|
@@ -404,7 +404,15 @@ const CalendarCore = {
|
|
|
404
404
|
<div class="in" style="margin-bottom: 100px"></div>`;
|
|
405
405
|
};
|
|
406
406
|
|
|
407
|
+
let delayBlock = false;
|
|
407
408
|
this.Data[options.idModal].updatePanel = async () => {
|
|
409
|
+
if (delayBlock) return;
|
|
410
|
+
else {
|
|
411
|
+
delayBlock = true;
|
|
412
|
+
setTimeout(() => {
|
|
413
|
+
delayBlock = false;
|
|
414
|
+
}, 500);
|
|
415
|
+
}
|
|
408
416
|
const cid = getQueryParams().cid ? getQueryParams().cid : '';
|
|
409
417
|
if (options.route === 'home') Modal.homeCid = newInstance(cid);
|
|
410
418
|
if (s(`.main-body-calendar-${options.idModal}`)) {
|
|
@@ -426,7 +434,10 @@ const CalendarCore = {
|
|
|
426
434
|
},
|
|
427
435
|
});
|
|
428
436
|
|
|
429
|
-
if (options.route === 'home')
|
|
437
|
+
// if (options.route === 'home')
|
|
438
|
+
setTimeout(() => {
|
|
439
|
+
CalendarCore.Data[options.idModal].updatePanel();
|
|
440
|
+
});
|
|
430
441
|
|
|
431
442
|
return html`
|
|
432
443
|
<style>
|
|
@@ -890,8 +890,58 @@ const commitData = {
|
|
|
890
890
|
},
|
|
891
891
|
};
|
|
892
892
|
|
|
893
|
-
const
|
|
893
|
+
const emotionsData = [
|
|
894
|
+
{
|
|
895
|
+
name: 'like',
|
|
896
|
+
ad_display: {
|
|
897
|
+
es: 'Me gusta',
|
|
898
|
+
en: 'Like',
|
|
899
|
+
},
|
|
900
|
+
emoji: '👍',
|
|
901
|
+
},
|
|
902
|
+
{
|
|
903
|
+
name: 'love',
|
|
904
|
+
ad_display: {
|
|
905
|
+
es: 'Me encanta',
|
|
906
|
+
en: 'Love',
|
|
907
|
+
},
|
|
908
|
+
emoji: '❤️',
|
|
909
|
+
},
|
|
910
|
+
{
|
|
911
|
+
name: 'haha',
|
|
912
|
+
ad_display: {
|
|
913
|
+
es: 'Me divierte',
|
|
914
|
+
en: 'Haha',
|
|
915
|
+
},
|
|
916
|
+
emoji: '😂',
|
|
917
|
+
},
|
|
918
|
+
{
|
|
919
|
+
name: 'wow',
|
|
920
|
+
ad_display: {
|
|
921
|
+
es: 'Me asombra',
|
|
922
|
+
en: 'Wow',
|
|
923
|
+
},
|
|
924
|
+
emoji: '😮',
|
|
925
|
+
},
|
|
926
|
+
{
|
|
927
|
+
name: 'sad',
|
|
928
|
+
ad_display: {
|
|
929
|
+
es: 'Me entristece',
|
|
930
|
+
en: 'Sad',
|
|
931
|
+
},
|
|
932
|
+
emoji: '😢',
|
|
933
|
+
},
|
|
934
|
+
{
|
|
935
|
+
name: 'angry',
|
|
936
|
+
ad_display: {
|
|
937
|
+
es: 'Me enoja',
|
|
938
|
+
en: 'Angry',
|
|
939
|
+
},
|
|
940
|
+
emoji: '😠',
|
|
941
|
+
},
|
|
942
|
+
];
|
|
894
943
|
|
|
944
|
+
const userRoleEnum = ['admin', 'moderator', 'user', 'guest'];
|
|
895
945
|
const commonAdminGuard = (role) => userRoleEnum.indexOf(role) === userRoleEnum.indexOf('admin');
|
|
896
946
|
const commonModeratorGuard = (role) => userRoleEnum.indexOf(role) <= userRoleEnum.indexOf('moderator');
|
|
897
947
|
|
|
@@ -954,4 +1004,5 @@ export {
|
|
|
954
1004
|
getCurrentTrace,
|
|
955
1005
|
userRoleEnum,
|
|
956
1006
|
commitData,
|
|
1007
|
+
emotionsData,
|
|
957
1008
|
};
|
|
@@ -396,8 +396,7 @@ const CssCoreDark = {
|
|
|
396
396
|
text-align: center;
|
|
397
397
|
background: #1a1a1a;
|
|
398
398
|
font-size: 17px;
|
|
399
|
-
|
|
400
|
-
padding-bottom: 6px;
|
|
399
|
+
height: 35px;
|
|
401
400
|
}
|
|
402
401
|
::placeholder {
|
|
403
402
|
color: #c6c4c4;
|
|
@@ -701,8 +700,7 @@ const CssCoreLight = {
|
|
|
701
700
|
text-align: center;
|
|
702
701
|
background: #eaeaea;
|
|
703
702
|
font-size: 17px;
|
|
704
|
-
|
|
705
|
-
padding-bottom: 6px;
|
|
703
|
+
height: 35px;
|
|
706
704
|
}
|
|
707
705
|
::placeholder {
|
|
708
706
|
color: #333;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { _VERSION, CoreService } from '../../services/core/core.service.js';
|
|
2
1
|
import { Badge } from './Badge.js';
|
|
3
2
|
import { BtnIcon } from './BtnIcon.js';
|
|
4
3
|
import { rgbToHex } from './CommonJs.js';
|
|
@@ -80,7 +79,7 @@ const Docs = {
|
|
|
80
79
|
icon: html`<i class="fa-brands fa-osi"></i>`,
|
|
81
80
|
text: 'Source Docs',
|
|
82
81
|
url: function () {
|
|
83
|
-
return `${getProxyPath()}docs/engine/${
|
|
82
|
+
return `${getProxyPath()}docs/engine/${window.renderPayload.version}`;
|
|
84
83
|
},
|
|
85
84
|
},
|
|
86
85
|
{
|
|
@@ -88,8 +88,10 @@ const Input = {
|
|
|
88
88
|
<div class="fl input-row-${id}">
|
|
89
89
|
<div class="in fll" style="width: 80%;">${inputElement}</div>
|
|
90
90
|
<div class="in fll btn-eye-password btn-eye-${id}" style="width: 20%;">
|
|
91
|
-
<
|
|
92
|
-
|
|
91
|
+
<div class="abs center">
|
|
92
|
+
<i class="fas fa-eye fa-eye-${id} eye-password"></i>
|
|
93
|
+
<i class="fas fa-eye-slash fa-eye-slash-${id} eye-password" style="display: none"></i>
|
|
94
|
+
</div>
|
|
93
95
|
</div>
|
|
94
96
|
</div>
|
|
95
97
|
`
|
|
@@ -75,12 +75,17 @@ const LoadingAnimation = {
|
|
|
75
75
|
const style = {
|
|
76
76
|
'text-align': 'center',
|
|
77
77
|
};
|
|
78
|
-
|
|
79
78
|
if (s(container).classList) {
|
|
80
79
|
const classes = Array.from(s(container).classList);
|
|
81
80
|
if (classes.find((e) => e.match('management-table-btn-mini'))) {
|
|
82
81
|
style.top = '-2px';
|
|
83
82
|
style.left = '-2px';
|
|
83
|
+
} else if (classes.find((e) => e.match('-btn-tool'))) {
|
|
84
|
+
style.top = '-26px';
|
|
85
|
+
style.left = '-10px';
|
|
86
|
+
} else if (classes.find((e) => e.match('main-btn-')) && !classes.find((e) => e.match('main-btn-square-menu'))) {
|
|
87
|
+
style.top = '-8px';
|
|
88
|
+
style.left = '-10px';
|
|
84
89
|
} else if (classes.find((e) => e.match('action-bar-box'))) {
|
|
85
90
|
style.top = '-30px';
|
|
86
91
|
style.left = '-12px';
|
|
@@ -145,6 +150,8 @@ const LoadingAnimation = {
|
|
|
145
150
|
s(backgroundContainer).style.opacity = 0;
|
|
146
151
|
setTimeout(async () => {
|
|
147
152
|
s(backgroundContainer).style.display = 'none';
|
|
153
|
+
if (s(`.modal-menu`)) s(`.modal-menu`).classList.remove('hide');
|
|
154
|
+
if (s(`.main-body-btn-container`)) s(`.main-body-btn-container`).classList.remove('hide');
|
|
148
155
|
if (callBack) callBack();
|
|
149
156
|
}, 300);
|
|
150
157
|
});
|
|
@@ -49,6 +49,7 @@ const Modal = {
|
|
|
49
49
|
mode: '' /* slide-menu */,
|
|
50
50
|
RouterInstance: {},
|
|
51
51
|
disableTools: [],
|
|
52
|
+
observer: false,
|
|
52
53
|
},
|
|
53
54
|
) {
|
|
54
55
|
if (options.heightBottomBar === undefined) options.heightBottomBar = 50;
|
|
@@ -76,6 +77,8 @@ const Modal = {
|
|
|
76
77
|
options,
|
|
77
78
|
onCloseListener: {},
|
|
78
79
|
onMenuListener: {},
|
|
80
|
+
onCollapseMenuListener: {},
|
|
81
|
+
onExtendMenuListener: {},
|
|
79
82
|
onDragEndListener: {},
|
|
80
83
|
onObserverListener: {},
|
|
81
84
|
onClickListener: {},
|
|
@@ -156,7 +159,8 @@ const Modal = {
|
|
|
156
159
|
};
|
|
157
160
|
options.mode === 'slide-menu-right' ? (options.style.right = '0px') : (options.style.left = '0px');
|
|
158
161
|
const contentIconClass = 'abs center';
|
|
159
|
-
|
|
162
|
+
if (options.class) options.class += ' hide';
|
|
163
|
+
else options.class = 'hide';
|
|
160
164
|
options.dragDisabled = true;
|
|
161
165
|
options.titleClass = 'hide';
|
|
162
166
|
top = '0px';
|
|
@@ -238,7 +242,7 @@ const Modal = {
|
|
|
238
242
|
'body',
|
|
239
243
|
html`
|
|
240
244
|
<div
|
|
241
|
-
class="abs main-body-btn-container"
|
|
245
|
+
class="abs main-body-btn-container hide"
|
|
242
246
|
style="top: ${options.heightTopBar + 50}px; z-index: 9; ${true ||
|
|
243
247
|
(options.mode && options.mode.match('right'))
|
|
244
248
|
? 'right'
|
|
@@ -1383,6 +1387,9 @@ const Modal = {
|
|
|
1383
1387
|
if (options.onCollapseMenu) options.onCollapseMenu();
|
|
1384
1388
|
s(`.sub-menu-title-container-${'modal-menu'}`).classList.add('hide');
|
|
1385
1389
|
s(`.nav-path-container-${'modal-menu'}`).classList.add('hide');
|
|
1390
|
+
Object.keys(this.Data[idModal].onCollapseMenuListener).map((keyListener) =>
|
|
1391
|
+
this.Data[idModal].onCollapseMenuListener[keyListener](),
|
|
1392
|
+
);
|
|
1386
1393
|
} else {
|
|
1387
1394
|
slideMenuWidth = originSlideMenuWidth;
|
|
1388
1395
|
setTimeout(() => {
|
|
@@ -1403,6 +1410,9 @@ const Modal = {
|
|
|
1403
1410
|
if (options.onExtendMenu) options.onExtendMenu();
|
|
1404
1411
|
s(`.sub-menu-title-container-${'modal-menu'}`).classList.remove('hide');
|
|
1405
1412
|
s(`.nav-path-container-${'modal-menu'}`).classList.remove('hide');
|
|
1413
|
+
Object.keys(this.Data[idModal].onExtendMenuListener).map((keyListener) =>
|
|
1414
|
+
this.Data[idModal].onExtendMenuListener[keyListener](),
|
|
1415
|
+
);
|
|
1406
1416
|
}
|
|
1407
1417
|
// btn-bar-center-icon-menu
|
|
1408
1418
|
this.actionBtnCenter();
|
|
@@ -1781,20 +1791,34 @@ const renderMenuLabel = ({ img, text, icon }) => {
|
|
|
1781
1791
|
<div class="abs center main-btn-menu-text">${text}</div>`;
|
|
1782
1792
|
};
|
|
1783
1793
|
|
|
1784
|
-
const renderViewTitle = (
|
|
1785
|
-
|
|
1794
|
+
const renderViewTitle = (
|
|
1795
|
+
options = { icon: '', img: '', text: '', assetFolder: '', 'ui-icons': '', dim, top, topText: '' },
|
|
1796
|
+
) => {
|
|
1797
|
+
if (options.dim === undefined) options.dim = 30;
|
|
1786
1798
|
const { img, text, icon, dim, top } = options;
|
|
1787
1799
|
if (!img && !options['ui-icon']) return html`<span class="view-title-icon">${icon}</span> ${text}`;
|
|
1788
1800
|
return html`<img
|
|
1789
1801
|
class="abs img-btn-square-view-title"
|
|
1790
1802
|
style="${renderCssAttr({
|
|
1791
|
-
style: {
|
|
1803
|
+
style: {
|
|
1804
|
+
width: `${dim}px`,
|
|
1805
|
+
height: `${dim}px`,
|
|
1806
|
+
top: top !== undefined ? `${top}px !important` : undefined,
|
|
1807
|
+
},
|
|
1792
1808
|
})}"
|
|
1793
1809
|
src="${options['ui-icon']
|
|
1794
1810
|
? `${getProxyPath()}assets/${options.assetFolder ? options.assetFolder : 'ui-icons'}/${options['ui-icon']}`
|
|
1795
1811
|
: img}"
|
|
1796
1812
|
/>
|
|
1797
|
-
<div
|
|
1813
|
+
<div
|
|
1814
|
+
class="in text-btn-square-view-title"
|
|
1815
|
+
style="${renderCssAttr({
|
|
1816
|
+
style: {
|
|
1817
|
+
// 'padding-left': `${20 + dim}px`,
|
|
1818
|
+
...(options.topText !== undefined ? { top: options.topText + 'px !important' } : {}),
|
|
1819
|
+
},
|
|
1820
|
+
})}"
|
|
1821
|
+
>
|
|
1798
1822
|
${text}
|
|
1799
1823
|
</div>`;
|
|
1800
1824
|
};
|
|
@@ -26,6 +26,7 @@ const Panel = {
|
|
|
26
26
|
idPanel: '',
|
|
27
27
|
parentIdModal: '',
|
|
28
28
|
scrollClassContainer: '',
|
|
29
|
+
htmlFormHeader: async () => '',
|
|
29
30
|
formData: [],
|
|
30
31
|
data: [],
|
|
31
32
|
originData: () => [],
|
|
@@ -244,12 +245,13 @@ const Panel = {
|
|
|
244
245
|
|
|
245
246
|
let render = '';
|
|
246
247
|
let renderForm = html` <div class="in modal stq" style="top: 0px; z-index: 1; padding-bottom: 5px">
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
248
|
+
${await BtnIcon.Render({
|
|
249
|
+
class: `section-mp btn-custom btn-${idPanel}-close`,
|
|
250
|
+
label: html`<i class="fa-solid fa-xmark"></i> ${Translate.Render('close')}`,
|
|
251
|
+
type: 'button',
|
|
252
|
+
})}
|
|
253
|
+
</div>
|
|
254
|
+
${options?.htmlFormHeader ? await options.htmlFormHeader() : ''}`;
|
|
253
255
|
|
|
254
256
|
for (const modelData of formData) {
|
|
255
257
|
if (modelData.disableRender) continue;
|