@underpostnet/underpost 2.8.0 → 2.8.31
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/.dockerignore +1 -0
- package/.github/workflows/ghpkg.yml +4 -4
- package/.vscode/extensions.json +8 -71
- package/.vscode/settings.json +2 -1
- package/CHANGELOG.md +55 -3
- package/Dockerfile +22 -36
- package/README.md +0 -27
- package/bin/deploy.js +54 -28
- package/bin/file.js +30 -2
- package/bin/index.js +6 -18
- package/bin/ssl.js +19 -11
- package/bin/util.js +18 -0
- package/bin/vs.js +3 -2
- package/conf.js +17 -1
- package/docker-compose.yml +1 -1
- package/manifests/mariadb/config.yaml +10 -0
- package/manifests/mariadb/kustomization.yaml +9 -0
- package/manifests/mariadb/pv.yaml +12 -0
- package/manifests/mariadb/pvc.yaml +10 -0
- package/manifests/mariadb/secret.yaml +8 -0
- package/manifests/mariadb/service.yaml +10 -0
- package/manifests/mariadb/statefulset.yaml +55 -0
- package/manifests/test/mongo-express.yaml +60 -0
- package/manifests/test/phpmyadmin.yaml +54 -0
- package/manifests/test/underpost-engine-mongodb-configmap.yaml +26 -0
- package/manifests/test/underpost-engine-pod.yaml +108 -0
- package/manifests/underpost-engine-backup-access.yaml +16 -0
- package/manifests/underpost-engine-backup-pv-pvc.yaml +22 -0
- package/manifests/underpost-engine-headless-service.yaml +10 -0
- package/manifests/underpost-engine-mongodb-backup-cronjob.yaml +40 -0
- package/manifests/underpost-engine-pv-pvc.yaml +23 -0
- package/manifests/underpost-engine-statefulset.yaml +91 -0
- package/manifests/valkey/kustomization.yaml +7 -0
- package/manifests/valkey/underpost-engine-valkey-service.yaml +17 -0
- package/manifests/valkey/underpost-engine-valkey-statefulset.yaml +39 -0
- package/package.json +22 -12
- package/src/api/user/user.model.js +9 -1
- package/src/api/user/user.service.js +1 -1
- package/src/client/components/core/Account.js +4 -2
- package/src/client/components/core/Auth.js +2 -2
- package/src/client/components/core/CalendarCore.js +112 -49
- package/src/client/components/core/CommonJs.js +125 -19
- package/src/client/components/core/Css.js +1 -1
- package/src/client/components/core/CssCore.js +6 -0
- package/src/client/components/core/Docs.js +2 -1
- package/src/client/components/core/DropDown.js +5 -1
- package/src/client/components/core/Input.js +17 -3
- package/src/client/components/core/JoyStick.js +8 -5
- package/src/client/components/core/Modal.js +12 -6
- package/src/client/components/core/Panel.js +82 -24
- package/src/client/components/core/PanelForm.js +11 -19
- package/src/client/components/core/SignUp.js +4 -1
- package/src/client/components/core/Translate.js +44 -8
- package/src/client/public/default/plantuml/client-conf.svg +1 -1
- package/src/client/public/default/plantuml/server-conf.svg +1 -1
- package/src/client/public/default/plantuml/server-schema.svg +1 -1
- package/src/client/public/default/plantuml/ssr-conf.svg +1 -1
- package/src/client/public/default/plantuml/ssr-schema.svg +1 -1
- package/src/client/services/core/core.service.js +2 -0
- package/src/client/ssr/body/CacheControl.js +2 -1
- package/src/client/ssr/body/DefaultSplashScreen.js +3 -3
- package/src/client/ssr/offline/Maintenance.js +63 -0
- package/src/client/sw/default.sw.js +23 -3
- package/src/db/mongo/MongooseDB.js +13 -1
- package/src/index.js +8 -0
- package/src/server/client-build.js +5 -4
- package/src/server/client-icons.js +1 -1
- package/src/server/conf.js +5 -5
- package/src/server/logger.js +8 -6
- package/src/server/process.js +25 -2
- package/src/server/ssl.js +1 -1
- package/src/server/valkey.js +3 -0
- package/startup.cjs +12 -0
- package/startup.js +0 -11
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
---
|
|
2
|
+
apiVersion: apps/v1
|
|
3
|
+
kind: StatefulSet
|
|
4
|
+
metadata:
|
|
5
|
+
name: service-valkey
|
|
6
|
+
namespace: default
|
|
7
|
+
spec:
|
|
8
|
+
serviceName: service-valkey
|
|
9
|
+
replicas: 1
|
|
10
|
+
selector:
|
|
11
|
+
matchLabels:
|
|
12
|
+
app: service-valkey
|
|
13
|
+
template:
|
|
14
|
+
metadata:
|
|
15
|
+
labels:
|
|
16
|
+
app: service-valkey
|
|
17
|
+
spec:
|
|
18
|
+
containers:
|
|
19
|
+
- name: service-valkey
|
|
20
|
+
image: docker.io/valkey/valkey:latest
|
|
21
|
+
env:
|
|
22
|
+
- name: TZ
|
|
23
|
+
value: Europe/Zurich
|
|
24
|
+
ports:
|
|
25
|
+
- containerPort: 6379
|
|
26
|
+
startupProbe:
|
|
27
|
+
tcpSocket:
|
|
28
|
+
port: 6379
|
|
29
|
+
failureThreshold: 30
|
|
30
|
+
periodSeconds: 5
|
|
31
|
+
timeoutSeconds: 5
|
|
32
|
+
livenessProbe:
|
|
33
|
+
tcpSocket:
|
|
34
|
+
port: 6379
|
|
35
|
+
failureThreshold: 2
|
|
36
|
+
periodSeconds: 30
|
|
37
|
+
timeoutSeconds: 5
|
|
38
|
+
restartPolicy: Always
|
|
39
|
+
automountServiceAccountToken: false
|
package/package.json
CHANGED
|
@@ -2,16 +2,16 @@
|
|
|
2
2
|
"type": "module",
|
|
3
3
|
"main": "src/index.js",
|
|
4
4
|
"name": "@underpostnet/underpost",
|
|
5
|
-
"version": "2.8.
|
|
5
|
+
"version": "2.8.31",
|
|
6
6
|
"description": "pwa api rest template",
|
|
7
7
|
"scripts": {
|
|
8
8
|
"start": "env-cmd -f .env.production node --max-old-space-size=8192 src/server",
|
|
9
9
|
"pm2": "env-cmd -f .env.production pm2 start src/server.js --node-args=\"--max-old-space-size=8192\" --name engine && pm2 logs",
|
|
10
10
|
"ssl": "env-cmd -f .env.production node bin/ssl",
|
|
11
11
|
"pm2-delete": "pm2 delete engine",
|
|
12
|
-
"build": "node bin/deploy build-full-client",
|
|
12
|
+
"build": "node bin/deploy build-full-client && node bin/deploy fix-deps",
|
|
13
13
|
"build-production": "env-cmd -f .env.production node bin/deploy build-full-client",
|
|
14
|
-
"dev": "env-cmd -f .env.development node src/client.dev",
|
|
14
|
+
"dev": "env-cmd -f .env.development node src/client.dev default",
|
|
15
15
|
"dev-api": "env-cmd -f .env.development nodemon --watch src --ignore src/client src/api",
|
|
16
16
|
"docs": "jsdoc -c jsdoc.json",
|
|
17
17
|
"backup": "node bin/db default.net/ export",
|
|
@@ -53,20 +53,25 @@
|
|
|
53
53
|
"homepage": "https://github.com/underpostnet/pwa-microservices-template#readme",
|
|
54
54
|
"dependencies": {
|
|
55
55
|
"@fortawesome/fontawesome-free": "^6.4.2",
|
|
56
|
+
"@fullcalendar/rrule": "^6.1.15",
|
|
57
|
+
"@google/generative-ai": "^0.21.0",
|
|
56
58
|
"@loadingio/css-spinner": "^2.0.2",
|
|
57
59
|
"@neodrag/vanilla": "^2.0.3",
|
|
58
|
-
"@
|
|
60
|
+
"@nomiclabs/hardhat-ethers": "^2.2.3",
|
|
61
|
+
"@nomiclabs/hardhat-etherscan": "^3.1.8",
|
|
62
|
+
"@nomiclabs/hardhat-waffle": "^2.0.6",
|
|
63
|
+
"@openzeppelin/contracts": "^5.0.2",
|
|
59
64
|
"adm-zip": "^0.5.10",
|
|
60
65
|
"ag-grid-community": "31.0.0",
|
|
61
66
|
"axios": "^1.5.1",
|
|
62
67
|
"chai": "^5.1.0",
|
|
63
68
|
"cli-progress": "^3.12.0",
|
|
64
69
|
"cli-spinners": "^3.0.0",
|
|
70
|
+
"clipboardy": "^4.0.0",
|
|
65
71
|
"color": "^4.2.3",
|
|
66
72
|
"colors": "^1.4.0",
|
|
67
73
|
"commander": "^12.1.0",
|
|
68
74
|
"compression": "^1.7.4",
|
|
69
|
-
"copy-paste": "^1.5.3",
|
|
70
75
|
"cors": "^2.8.5",
|
|
71
76
|
"d3": "^7.9.0",
|
|
72
77
|
"deepmerge": "^4.3.1",
|
|
@@ -84,27 +89,30 @@
|
|
|
84
89
|
"html-minifier-terser": "^7.2.0",
|
|
85
90
|
"http-proxy-middleware": "^2.0.6",
|
|
86
91
|
"ignore-walk": "^6.0.4",
|
|
92
|
+
"iovalkey": "^0.2.1",
|
|
87
93
|
"is-admin": "^4.0.0",
|
|
88
94
|
"is-ip": "^5.0.1",
|
|
89
95
|
"jimp": "^0.22.12",
|
|
90
96
|
"joystick-controller": "^1.0.15",
|
|
91
97
|
"json-colorizer": "^2.2.2",
|
|
92
98
|
"jsonwebtoken": "^9.0.2",
|
|
99
|
+
"keyword-extractor": "^0.0.28",
|
|
93
100
|
"kill-port-process": "^3.2.0",
|
|
94
101
|
"log-update": "^6.0.0",
|
|
95
102
|
"mariadb": "^3.2.2",
|
|
96
103
|
"marked": "^12.0.2",
|
|
97
|
-
"mongoose": "^8.
|
|
104
|
+
"mongoose": "^8.9.5",
|
|
98
105
|
"morgan": "^1.10.0",
|
|
99
106
|
"nodemailer": "^6.9.9",
|
|
100
107
|
"nodemon": "^3.0.1",
|
|
101
108
|
"pathfinding": "^0.4.18",
|
|
102
109
|
"peer": "^1.0.2",
|
|
103
110
|
"peerjs": "^1.5.2",
|
|
104
|
-
"pixi.js": "7.4.
|
|
111
|
+
"pixi.js": "7.4.2",
|
|
105
112
|
"prom-client": "^15.1.2",
|
|
106
113
|
"public-ip": "^6.0.1",
|
|
107
114
|
"read": "^2.1.0",
|
|
115
|
+
"rrule": "^2.8.1",
|
|
108
116
|
"sharp": "^0.32.5",
|
|
109
117
|
"shelljs": "^0.8.5",
|
|
110
118
|
"simple-git": "^3.26.0",
|
|
@@ -114,18 +122,20 @@
|
|
|
114
122
|
"sortablejs": "^1.15.0",
|
|
115
123
|
"split-file": "^2.3.0",
|
|
116
124
|
"swagger-ui-express": "^5.0.0",
|
|
117
|
-
"systeminformation": "^5.
|
|
125
|
+
"systeminformation": "^5.23.7",
|
|
118
126
|
"uglify-js": "^3.17.4",
|
|
119
127
|
"validator": "^13.11.0",
|
|
120
|
-
"
|
|
121
|
-
"
|
|
128
|
+
"vanilla-jsoneditor": "^2.3.2",
|
|
129
|
+
"web3": "^4.13.0",
|
|
130
|
+
"winston": "^3.11.0"
|
|
122
131
|
},
|
|
123
132
|
"devDependencies": {
|
|
124
133
|
"clean-jsdoc-theme": "^4.3.0",
|
|
134
|
+
"easy-json-schema": "^0.0.2-beta",
|
|
135
|
+
"hardhat": "^2.22.13",
|
|
125
136
|
"mocha": "^10.4.0",
|
|
126
137
|
"plantuml": "^0.0.2",
|
|
127
|
-
"swagger-autogen": "^2.23.7"
|
|
128
|
-
"easy-json-schema": "^0.0.2-beta"
|
|
138
|
+
"swagger-autogen": "^2.23.7"
|
|
129
139
|
},
|
|
130
140
|
"publishConfig": {
|
|
131
141
|
"provenance": true,
|
|
@@ -26,7 +26,11 @@ const UserSchema = new Schema(
|
|
|
26
26
|
profileImageId: { type: Schema.Types.ObjectId, ref: 'File' },
|
|
27
27
|
phoneNumbers: [
|
|
28
28
|
{
|
|
29
|
-
type: {
|
|
29
|
+
type: {
|
|
30
|
+
type: String,
|
|
31
|
+
enum: ['office', 'home', 'private'],
|
|
32
|
+
},
|
|
33
|
+
number: { type: String },
|
|
30
34
|
},
|
|
31
35
|
],
|
|
32
36
|
publicKey: {
|
|
@@ -58,6 +62,10 @@ const UserDto = {
|
|
|
58
62
|
},
|
|
59
63
|
},
|
|
60
64
|
auth: {
|
|
65
|
+
// TODO: -> set login device, location, ip, fingerprint
|
|
66
|
+
// and validate on authorization middleware
|
|
67
|
+
// -> dynamic refresh 100 tokens per session with 12h interval
|
|
68
|
+
// -> back secret per user, registrarion user model -> secret: { type: String }
|
|
61
69
|
payload: (user) => ({ _id: user._id.toString(), role: user.role, email: user.email }),
|
|
62
70
|
},
|
|
63
71
|
};
|
|
@@ -237,7 +237,7 @@ const UserService = {
|
|
|
237
237
|
const validatePassword = validatePasswordMiddleware(req.body.password);
|
|
238
238
|
if (validatePassword.status === 'error') throw new Error(validatePassword.message);
|
|
239
239
|
req.body.password = await hashPassword(req.body.password);
|
|
240
|
-
req.body.role = 'user';
|
|
240
|
+
req.body.role = req.body.role === 'guest' ? 'guest' : 'user';
|
|
241
241
|
req.body.profileImageId = await getDefaultProfileImageId(File);
|
|
242
242
|
const { _id } = await new User(req.body).save();
|
|
243
243
|
if (_id) {
|
|
@@ -300,8 +300,10 @@ const Account = {
|
|
|
300
300
|
s(`.account-profile-image`).style.opacity = 0;
|
|
301
301
|
for (const inputData of this.formData)
|
|
302
302
|
if (s(`.${inputData.id}`)) s(`.${inputData.id}`).value = user[inputData.model];
|
|
303
|
-
|
|
304
|
-
|
|
303
|
+
if (LogIn.Scope.user.main.model.user.profileImage) {
|
|
304
|
+
s(`.account-profile-image`).src = LogIn.Scope.user.main.model.user.profileImage.imageSrc;
|
|
305
|
+
s(`.account-profile-image`).style.opacity = 1;
|
|
306
|
+
}
|
|
305
307
|
},
|
|
306
308
|
};
|
|
307
309
|
|
|
@@ -46,8 +46,8 @@ const Auth = {
|
|
|
46
46
|
) {
|
|
47
47
|
try {
|
|
48
48
|
localStorage.setItem('jwt', result.data.token);
|
|
49
|
-
await Auth.sessionIn();
|
|
50
49
|
await SignUp.Trigger(result.data);
|
|
50
|
+
await Auth.sessionIn();
|
|
51
51
|
} catch (error) {
|
|
52
52
|
logger.error(error);
|
|
53
53
|
localStorage.removeItem('jwt');
|
|
@@ -76,7 +76,7 @@ const Auth = {
|
|
|
76
76
|
await LogIn.Trigger({ user: data.user });
|
|
77
77
|
await Account.updateForm(data.user);
|
|
78
78
|
return { user: data.user };
|
|
79
|
-
}
|
|
79
|
+
}
|
|
80
80
|
}
|
|
81
81
|
|
|
82
82
|
// anon guest session
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { EventSchedulerService } from '../../services/event-scheduler/event-scheduler.service.js';
|
|
2
2
|
import { Auth } from './Auth.js';
|
|
3
3
|
import { BtnIcon } from './BtnIcon.js';
|
|
4
|
-
import { newInstance, range, s4 } from './CommonJs.js';
|
|
4
|
+
import { isValidDate, newInstance, range, s4 } from './CommonJs.js';
|
|
5
5
|
import { renderCssAttr } from './Css.js';
|
|
6
6
|
import { Modal } from './Modal.js';
|
|
7
7
|
import { NotificationManager } from './NotificationManager.js';
|
|
@@ -13,15 +13,27 @@ import { append, getQueryParams, getTimeZone, htmls, s, sa } from './VanillaJs.j
|
|
|
13
13
|
|
|
14
14
|
// https://fullcalendar.io/docs/event-object
|
|
15
15
|
|
|
16
|
+
const daysOfWeekOptions = ['sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday'];
|
|
17
|
+
|
|
18
|
+
const eventDateFactory = (event) =>
|
|
19
|
+
newInstance({
|
|
20
|
+
event: { ...event.extendedProps, title: event._def.title },
|
|
21
|
+
start: event.start,
|
|
22
|
+
end: event.end,
|
|
23
|
+
});
|
|
24
|
+
|
|
16
25
|
const CalendarCore = {
|
|
17
26
|
RenderStyle: async function () {},
|
|
18
27
|
Data: {},
|
|
19
|
-
Render: async function (
|
|
28
|
+
Render: async function (
|
|
29
|
+
options = { idModal: '', Elements: {}, heightTopBar: 50, heightBottomBar: 50, hiddenDates: [] },
|
|
30
|
+
) {
|
|
20
31
|
this.Data[options.idModal] = {
|
|
21
32
|
data: [],
|
|
22
33
|
originData: [],
|
|
23
34
|
filesData: [],
|
|
24
35
|
calendar: {},
|
|
36
|
+
hiddenDates: options.hiddenDates ? options.hiddenDates : [],
|
|
25
37
|
};
|
|
26
38
|
|
|
27
39
|
const { heightTopBar, heightBottomBar } = options;
|
|
@@ -40,56 +52,87 @@ const CalendarCore = {
|
|
|
40
52
|
};
|
|
41
53
|
getSrrData();
|
|
42
54
|
|
|
43
|
-
const dateFormat = (date) =>
|
|
44
|
-
html`<span
|
|
45
|
-
style="${renderCssAttr({
|
|
46
|
-
style: {
|
|
47
|
-
'font-size': '14px',
|
|
48
|
-
color: '#888',
|
|
49
|
-
},
|
|
50
|
-
})}"
|
|
51
|
-
>${new Date(date).toLocaleString().replaceAll(',', '')}</span
|
|
52
|
-
>`;
|
|
53
|
-
|
|
54
55
|
const getPanelData = async () => {
|
|
55
56
|
const result = await EventSchedulerService.get({
|
|
56
|
-
id: `${getQueryParams().cid ? getQueryParams().cid : 'creatorUser'}`,
|
|
57
|
+
id: `${getQueryParams().cid ? getQueryParams().cid : Auth.getToken() ? 'creatorUser' : ''}`,
|
|
57
58
|
});
|
|
58
59
|
NotificationManager.Push({
|
|
59
60
|
html: result.status === 'success' ? Translate.Render('success-get-events-scheduler') : result.message,
|
|
60
61
|
status: result.status,
|
|
61
62
|
});
|
|
62
63
|
if (result.status === 'success') {
|
|
63
|
-
const resultData = Array.isArray(result.data) ? result.data : [result.data];
|
|
64
|
+
const resultData = Array.isArray(result.data) ? result.data : result.data ? [result.data] : [];
|
|
64
65
|
this.Data[options.idModal].filesData = [];
|
|
65
66
|
this.Data[options.idModal].originData = newInstance(resultData);
|
|
66
67
|
this.Data[options.idModal].data = resultData.map((o) => {
|
|
67
68
|
if (o.creatorUserId && options.Elements.Data.user.main.model.user._id === o.creatorUserId) o.tools = true;
|
|
68
69
|
o.id = o._id;
|
|
69
|
-
|
|
70
|
-
o.end = dateFormat(o.end);
|
|
70
|
+
|
|
71
71
|
this.Data[options.idModal].filesData.push({});
|
|
72
72
|
return o;
|
|
73
73
|
});
|
|
74
|
+
setTimeout(() => {
|
|
75
|
+
renderCalendar(
|
|
76
|
+
resultData.map((o) => {
|
|
77
|
+
// FREQ=WEEKLY;
|
|
78
|
+
// if (o.daysOfWeek && o.daysOfWeek.length > 0) {
|
|
79
|
+
// o.rrule = `RRULE:BYDAY=${o.daysOfWeek.map((d) => `${d[0]}${d[1]}`.toUpperCase()).join(',')}`;
|
|
80
|
+
// }
|
|
81
|
+
// o.rrule = 'FREQ=WEEKLY;BYDAY=SU;BYHOUR=10,11;COUNT=10';
|
|
82
|
+
if (o.daysOfWeek && o.daysOfWeek.length > 0)
|
|
83
|
+
o.daysOfWeek = o.daysOfWeek.map((v, i) => daysOfWeekOptions.indexOf(v));
|
|
84
|
+
else delete o.daysOfWeek;
|
|
85
|
+
// o.exdate = ['2024-04-02'];
|
|
86
|
+
// delete o.end;
|
|
87
|
+
// delete o.start;
|
|
88
|
+
|
|
89
|
+
return o;
|
|
90
|
+
}),
|
|
91
|
+
);
|
|
92
|
+
});
|
|
74
93
|
}
|
|
75
94
|
};
|
|
76
95
|
|
|
77
|
-
const renderCalendar = () => {
|
|
96
|
+
const renderCalendar = (events) => {
|
|
78
97
|
const calendarEl = s(`.calendar-${idPanel}`);
|
|
79
98
|
this.Data[options.idModal].calendar = new FullCalendar.Calendar(calendarEl, {
|
|
80
|
-
plugins: [
|
|
99
|
+
plugins: [
|
|
100
|
+
FullCalendar.DayGrid.default,
|
|
101
|
+
FullCalendar.TimeGrid.default,
|
|
102
|
+
FullCalendar.List.default,
|
|
103
|
+
// https://fullcalendar.io/docs/rrule-plugin
|
|
104
|
+
FullCalendar.RRule.default,
|
|
105
|
+
],
|
|
81
106
|
// initialView: 'dayGridWeek',
|
|
82
107
|
timeZone: getTimeZone(),
|
|
83
108
|
dateClick: function (arg) {
|
|
84
109
|
console.error('calendar dateClick', arg.date.toString());
|
|
85
110
|
},
|
|
86
|
-
events: [{ title: 'Meeting', start: new Date() }],
|
|
111
|
+
events: events ?? [{ title: 'Meeting', start: new Date() }],
|
|
87
112
|
initialView: 'dayGridMonth',
|
|
88
113
|
headerToolbar: {
|
|
89
114
|
left: 'prev,next today',
|
|
90
115
|
center: 'title',
|
|
91
116
|
right: 'dayGridMonth,timeGridWeek,listWeek',
|
|
92
117
|
},
|
|
118
|
+
eventClick: async function (args) {
|
|
119
|
+
const dateData = eventDateFactory(args.event);
|
|
120
|
+
// element -> args.el
|
|
121
|
+
// remove all events associated -> args.event.remove();
|
|
122
|
+
// console.error('eventClick', JSON.stringify(dateData, null, 4));
|
|
123
|
+
if (options.eventClick) await options.eventClick(dateData, args);
|
|
124
|
+
},
|
|
125
|
+
eventClassNames: function (args) {
|
|
126
|
+
// console.error('eventClassNames', JSON.stringify(dateData, null, 4));
|
|
127
|
+
if (!args.event.extendedProps._id) return args.event.remove();
|
|
128
|
+
const dateData = eventDateFactory(args.event);
|
|
129
|
+
if (
|
|
130
|
+
CalendarCore.Data[options.idModal].hiddenDates.find(
|
|
131
|
+
(d) => d.eventSchedulerId === dateData.event._id && d.date === dateData.start,
|
|
132
|
+
)
|
|
133
|
+
)
|
|
134
|
+
return ['hide'];
|
|
135
|
+
},
|
|
93
136
|
});
|
|
94
137
|
|
|
95
138
|
this.Data[options.idModal].calendar.render();
|
|
@@ -139,29 +182,52 @@ const CalendarCore = {
|
|
|
139
182
|
rules: [{ type: 'isEmpty' }],
|
|
140
183
|
},
|
|
141
184
|
{
|
|
142
|
-
id: '
|
|
143
|
-
model: '
|
|
185
|
+
id: 'title',
|
|
186
|
+
model: 'title',
|
|
144
187
|
inputType: 'text',
|
|
145
188
|
rules: [{ type: 'isEmpty' }],
|
|
146
189
|
panel: { type: 'title' },
|
|
147
190
|
},
|
|
148
191
|
{
|
|
149
|
-
id: '
|
|
150
|
-
model: '
|
|
151
|
-
inputType: '
|
|
152
|
-
rules: [],
|
|
153
|
-
panel: { type: 'info-row'
|
|
192
|
+
id: 'description',
|
|
193
|
+
model: 'description',
|
|
194
|
+
inputType: 'text',
|
|
195
|
+
rules: [{ type: 'isEmpty' }],
|
|
196
|
+
panel: { type: 'info-row' },
|
|
154
197
|
},
|
|
155
198
|
{
|
|
156
199
|
id: 'start',
|
|
157
200
|
model: 'start',
|
|
158
201
|
inputType: 'datetime-local',
|
|
159
|
-
|
|
202
|
+
translateCode: 'startTime',
|
|
203
|
+
panel: { type: 'info-row' },
|
|
160
204
|
},
|
|
161
205
|
{
|
|
162
206
|
id: 'end',
|
|
163
207
|
model: 'end',
|
|
164
208
|
inputType: 'datetime-local',
|
|
209
|
+
translateCode: 'endTime',
|
|
210
|
+
panel: { type: 'info-row' },
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
id: 'daysOfWeek',
|
|
214
|
+
model: 'daysOfWeek',
|
|
215
|
+
inputType: 'dropdown-checkbox',
|
|
216
|
+
dropdown: {
|
|
217
|
+
options: daysOfWeekOptions,
|
|
218
|
+
},
|
|
219
|
+
panel: { type: 'list' },
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
id: 'startTime',
|
|
223
|
+
model: 'startTime',
|
|
224
|
+
inputType: 'time',
|
|
225
|
+
panel: { type: 'info-row' },
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
id: 'endTime',
|
|
229
|
+
model: 'endTime',
|
|
230
|
+
inputType: 'time',
|
|
165
231
|
panel: { type: 'info-row' },
|
|
166
232
|
},
|
|
167
233
|
];
|
|
@@ -215,8 +281,7 @@ const CalendarCore = {
|
|
|
215
281
|
if (options.route) {
|
|
216
282
|
setQueryPath({ path: options.route, queryPath: payload._id });
|
|
217
283
|
if (options.parentIdModal) Modal.Data[options.parentIdModal].query = `${window.location.search}`;
|
|
218
|
-
|
|
219
|
-
await CalendarCore.Data[options.idModal].updatePanel();
|
|
284
|
+
await CalendarCore.Data[options.idModal].updatePanel();
|
|
220
285
|
}
|
|
221
286
|
},
|
|
222
287
|
titleIcon,
|
|
@@ -250,12 +315,19 @@ const CalendarCore = {
|
|
|
250
315
|
],
|
|
251
316
|
on: {
|
|
252
317
|
add: async function ({ data, editId }) {
|
|
318
|
+
if (data.daysOfWeek && data.daysOfWeek.length > 0 && daysOfWeekOptions[data.daysOfWeek[0]]) {
|
|
319
|
+
data.daysOfWeek = data.daysOfWeek.map((d) => daysOfWeekOptions[d]);
|
|
320
|
+
}
|
|
321
|
+
data.timeZoneClient = getTimeZone();
|
|
253
322
|
const {
|
|
254
323
|
status,
|
|
255
324
|
message,
|
|
256
325
|
data: documentData,
|
|
257
326
|
} = editId
|
|
258
|
-
? await EventSchedulerService.put({
|
|
327
|
+
? await EventSchedulerService.put({
|
|
328
|
+
id: editId,
|
|
329
|
+
body: { ...data, _id: undefined },
|
|
330
|
+
})
|
|
259
331
|
: await EventSchedulerService.post({ body: data });
|
|
260
332
|
NotificationManager.Push({
|
|
261
333
|
html:
|
|
@@ -268,10 +340,9 @@ const CalendarCore = {
|
|
|
268
340
|
});
|
|
269
341
|
|
|
270
342
|
if (status === 'success') {
|
|
271
|
-
|
|
272
|
-
data.
|
|
273
|
-
data
|
|
274
|
-
data._id = documentData._id;
|
|
343
|
+
documentData.tools = true;
|
|
344
|
+
// data._id = documentData._id;
|
|
345
|
+
data = documentData;
|
|
275
346
|
|
|
276
347
|
let originObj, indexOriginObj;
|
|
277
348
|
let filesData = {};
|
|
@@ -291,8 +362,7 @@ const CalendarCore = {
|
|
|
291
362
|
|
|
292
363
|
setQueryPath({ path: options.route, queryPath: documentData._id });
|
|
293
364
|
if (options.parentIdModal) Modal.Data[options.parentIdModal].query = `${window.location.search}`;
|
|
294
|
-
|
|
295
|
-
await CalendarCore.Data[options.idModal].updatePanel();
|
|
365
|
+
await CalendarCore.Data[options.idModal].updatePanel();
|
|
296
366
|
}
|
|
297
367
|
return { data, status, message };
|
|
298
368
|
},
|
|
@@ -319,11 +389,8 @@ const CalendarCore = {
|
|
|
319
389
|
status,
|
|
320
390
|
});
|
|
321
391
|
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
if (CalendarCore.Data[options.idModal].updatePanel)
|
|
325
|
-
await CalendarCore.Data[options.idModal].updatePanel();
|
|
326
|
-
}
|
|
392
|
+
setQueryPath({ path: options.route, queryPath: '' });
|
|
393
|
+
await CalendarCore.Data[options.idModal].updatePanel();
|
|
327
394
|
|
|
328
395
|
return { status };
|
|
329
396
|
}
|
|
@@ -334,17 +401,13 @@ const CalendarCore = {
|
|
|
334
401
|
<div class="in" style="margin-bottom: 100px"></div>`;
|
|
335
402
|
};
|
|
336
403
|
|
|
337
|
-
let lastCid;
|
|
338
|
-
let lasUserId;
|
|
339
404
|
this.Data[options.idModal].updatePanel = async () => {
|
|
340
405
|
const cid = getQueryParams().cid ? getQueryParams().cid : '';
|
|
341
|
-
if (lastCid === cid && lasUserId === options.Elements.Data.user.main.model.user._id) return;
|
|
342
406
|
if (options.route === 'home') Modal.homeCid = newInstance(cid);
|
|
343
|
-
lasUserId = newInstance(options.Elements.Data.user.main.model.user._id);
|
|
344
|
-
lastCid = cid;
|
|
345
407
|
if (s(`.main-body-calendar-${options.idModal}`)) {
|
|
346
|
-
if (Auth.getToken())
|
|
347
|
-
else getSrrData();
|
|
408
|
+
// if (Auth.getToken())
|
|
409
|
+
// else getSrrData();
|
|
410
|
+
await getPanelData();
|
|
348
411
|
htmls(`.main-body-calendar-${options.idModal}`, await panelRender());
|
|
349
412
|
}
|
|
350
413
|
};
|
|
@@ -518,25 +518,25 @@ function getDirname(path) {
|
|
|
518
518
|
return parts.join('/'); // Adjust separator if needed for Windows ('\')
|
|
519
519
|
}
|
|
520
520
|
|
|
521
|
-
const isDayValid = (day) => {
|
|
522
|
-
const date = new Date();
|
|
523
|
-
date.setDate(day);
|
|
524
|
-
return date.getDate() === day;
|
|
525
|
-
};
|
|
526
|
-
|
|
527
|
-
const isMonthValid = (month) => {
|
|
528
|
-
const date = new Date();
|
|
529
|
-
date.setMonth(month - 1);
|
|
530
|
-
return date.getMonth() === month - 1;
|
|
531
|
-
};
|
|
532
|
-
|
|
533
521
|
const isValidDate = (day, month, year) => {
|
|
534
|
-
if (!
|
|
535
|
-
|
|
536
|
-
|
|
522
|
+
if (!month && !year) return !(new Date(day) == 'Invalid Date');
|
|
523
|
+
// new Date('2025-12-28')
|
|
524
|
+
// Sat Dec 27 2025 19:00:00 GMT-0500 (Eastern Standard Time)
|
|
525
|
+
// new Date('2025/12/28')
|
|
526
|
+
// Sun Dec 28 2025 00:00:00 GMT-0500 (Eastern Standard Time)
|
|
527
|
+
return !(new Date(`${year}/${month}/${day}`) == 'Invalid Date');
|
|
528
|
+
};
|
|
537
529
|
|
|
538
|
-
|
|
539
|
-
|
|
530
|
+
// console.log(req.body.timeZoneClient, Intl.DateTimeFormat().resolvedOptions().timeZone);
|
|
531
|
+
// DateTime.fromISO("2017-05-15T09:10:23", { zone: "Europe/Paris" });
|
|
532
|
+
const strToDateUTC = (date = '2025-01-30T14:32') => {
|
|
533
|
+
const year = parseInt(date.split('-')[0]);
|
|
534
|
+
const month = parseInt(date.split('-')[1]);
|
|
535
|
+
const day = parseInt(date.split('-')[2].split('T')[0]);
|
|
536
|
+
const hour = parseInt(date.split('T')[1].split(':')[0]);
|
|
537
|
+
const minute = parseInt(date.split('T')[1].split(':')[1]);
|
|
538
|
+
date = new Date(Date.UTC(year, month - 1, day, hour, minute, 0, 0));
|
|
539
|
+
return date;
|
|
540
540
|
};
|
|
541
541
|
|
|
542
542
|
const isValidFormat = (value, format) => {
|
|
@@ -685,6 +685,112 @@ const hexToNumber = (hex = 0xdc) => Number(hex) || parseFloat(hex, 16);
|
|
|
685
685
|
|
|
686
686
|
const numberToHex = (number = 0) => number.toString(16);
|
|
687
687
|
|
|
688
|
+
const generateRandomPasswordSelection = (length) => {
|
|
689
|
+
const _random = (arr) => {
|
|
690
|
+
const rand = Math.floor(Math.random() * arr.length);
|
|
691
|
+
return arr[rand];
|
|
692
|
+
};
|
|
693
|
+
|
|
694
|
+
const uppercase = [
|
|
695
|
+
'A',
|
|
696
|
+
'B',
|
|
697
|
+
'C',
|
|
698
|
+
'D',
|
|
699
|
+
'E',
|
|
700
|
+
'F',
|
|
701
|
+
'G',
|
|
702
|
+
'H',
|
|
703
|
+
'I',
|
|
704
|
+
'J',
|
|
705
|
+
'K',
|
|
706
|
+
'L',
|
|
707
|
+
'M',
|
|
708
|
+
'N',
|
|
709
|
+
'O',
|
|
710
|
+
'P',
|
|
711
|
+
'Q',
|
|
712
|
+
'R',
|
|
713
|
+
'S',
|
|
714
|
+
'T',
|
|
715
|
+
'U',
|
|
716
|
+
'V',
|
|
717
|
+
'W',
|
|
718
|
+
'X',
|
|
719
|
+
'Y',
|
|
720
|
+
'Z',
|
|
721
|
+
];
|
|
722
|
+
const lowercase = [
|
|
723
|
+
'a',
|
|
724
|
+
'b',
|
|
725
|
+
'c',
|
|
726
|
+
'd',
|
|
727
|
+
'e',
|
|
728
|
+
'f',
|
|
729
|
+
'g',
|
|
730
|
+
'h',
|
|
731
|
+
'i',
|
|
732
|
+
'j',
|
|
733
|
+
'k',
|
|
734
|
+
'l',
|
|
735
|
+
'm',
|
|
736
|
+
'n',
|
|
737
|
+
'o',
|
|
738
|
+
'p',
|
|
739
|
+
'q',
|
|
740
|
+
'r',
|
|
741
|
+
's',
|
|
742
|
+
't',
|
|
743
|
+
'u',
|
|
744
|
+
'v',
|
|
745
|
+
'w',
|
|
746
|
+
'x',
|
|
747
|
+
'y',
|
|
748
|
+
'z',
|
|
749
|
+
];
|
|
750
|
+
const special = [
|
|
751
|
+
'~',
|
|
752
|
+
'!',
|
|
753
|
+
'@',
|
|
754
|
+
'#',
|
|
755
|
+
'$',
|
|
756
|
+
'%',
|
|
757
|
+
'^',
|
|
758
|
+
'&',
|
|
759
|
+
'*',
|
|
760
|
+
'(',
|
|
761
|
+
')',
|
|
762
|
+
'_',
|
|
763
|
+
'+',
|
|
764
|
+
'-',
|
|
765
|
+
'=',
|
|
766
|
+
'{',
|
|
767
|
+
'}',
|
|
768
|
+
'[',
|
|
769
|
+
']',
|
|
770
|
+
':',
|
|
771
|
+
';',
|
|
772
|
+
'?',
|
|
773
|
+
',',
|
|
774
|
+
'.',
|
|
775
|
+
'|',
|
|
776
|
+
'\\',
|
|
777
|
+
];
|
|
778
|
+
const numbers = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
|
|
779
|
+
|
|
780
|
+
const nonSpecial = [...uppercase, ...lowercase, ...numbers];
|
|
781
|
+
|
|
782
|
+
let password = '';
|
|
783
|
+
|
|
784
|
+
for (let i = 0; i < length; i++) {
|
|
785
|
+
// Previous character is a special character
|
|
786
|
+
if (i !== 0 && special.includes(password[i - 1])) {
|
|
787
|
+
password += _random(nonSpecial);
|
|
788
|
+
} else password += _random([...nonSpecial, ...special]);
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
return password;
|
|
792
|
+
};
|
|
793
|
+
|
|
688
794
|
// 0x = Hexadecimal
|
|
689
795
|
// 0b = Binary
|
|
690
796
|
// 0o = Octal
|
|
@@ -727,10 +833,9 @@ export {
|
|
|
727
833
|
getSubpaths,
|
|
728
834
|
formatBytes,
|
|
729
835
|
getDirname,
|
|
730
|
-
isDayValid,
|
|
731
|
-
isMonthValid,
|
|
732
836
|
isValidDate,
|
|
733
837
|
isValidFormat,
|
|
838
|
+
strToDateUTC,
|
|
734
839
|
getTimezoneOffset,
|
|
735
840
|
cleanString,
|
|
736
841
|
splitEveryXChar,
|
|
@@ -742,4 +847,5 @@ export {
|
|
|
742
847
|
getCapVariableName,
|
|
743
848
|
hexToNumber,
|
|
744
849
|
numberToHex,
|
|
850
|
+
generateRandomPasswordSelection,
|
|
745
851
|
};
|