adminizer 4.2.0 → 4.3.0-build.74
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/assets/add-BNb5A_qF.js +1 -0
- package/assets/{add-form-BjackXJe.js → add-form-CGi_qv3J.js} +1 -1
- package/assets/add-group-RRjHTu93.js +1 -0
- package/assets/{add-group-form-YI6KS37x.js → add-group-form-DSd4UrnU.js} +1 -1
- package/assets/add-user-DSuvcKp6.js +1 -0
- package/assets/{add-user-form-bv5BNX5A.js → add-user-form-BAssKDpI.js} +1 -1
- package/assets/{app-CVnUv8s_.css → app-GsYdx39W.css} +1 -1
- package/assets/{app-layout-DecN527i.js → app-layout-ContoN1K.js} +1 -1
- package/assets/{app-sidebar-4JFP8UdU.js → app-sidebar-D7l5BJPV.js} +1 -1
- package/assets/app-sidebar-header-CK8t32cm.js +1 -0
- package/assets/app.js +13 -13
- package/assets/{breadcrumbs-Bo2z-LNC.js → breadcrumbs-DnNOEnT4.js} +1 -1
- package/assets/{catalog-DVyrGTNR.js → catalog-BavcTVb4.js} +1 -1
- package/assets/{dashboard-Dy3pk9t7.js → dashboard-xr-OyVyG.js} +1 -1
- package/assets/{date-picker-B2z-aeuv.js → date-picker-DBHnomTY.js} +1 -1
- package/assets/{del-modal-l3LxJWCN.js → del-modal-BeF4r3gk.js} +1 -1
- package/assets/{field-renderer-BHo944Cn.js → field-renderer-Sd68OLyc.js} +3 -3
- package/assets/form-C9P9m_9q.js +1 -0
- package/assets/{form-hP8sjbND.js → form-DomTBI89.js} +1 -1
- package/assets/home-BWHeZm-1.js +2 -0
- package/assets/{icon-C_X2cQ6W.js → icon-ChQBPA5l.js} +1 -1
- package/assets/{init-user-DgCD4ZN1.js → init-user-DqMDju_E.js} +1 -1
- package/assets/input-error-g1h6ps7t.js +1 -0
- package/assets/list-EEgAn-nx.js +1 -0
- package/assets/{list-table-_OiQmr2A.js → list-table-Br0K3rXg.js} +1 -1
- package/assets/login-CUDpGsHl.js +1 -0
- package/assets/manifest.json +97 -64
- package/assets/material-icon-BIcI8APG.js +1 -0
- package/assets/media-manager-CTstvyHm.js +14 -0
- package/assets/{module-Ceq6vuwa.js → module-CpZBs0fN.js} +1 -1
- package/assets/{multi-select-BbKSrMw2.js → multi-select-BFWbEjH-.js} +1 -1
- package/assets/{nav-footer-B8gMV6Wp.js → nav-footer-bO8D-Yir.js} +1 -1
- package/assets/{nav-main-BUp9qA8R.js → nav-main-DVgvko8g.js} +1 -1
- package/assets/{nav-user-DeF3SDRj.js → nav-user-vIwYShwE.js} +1 -1
- package/assets/notification-BTXEslqa.js +1 -0
- package/assets/{pagination-render-B9U_hVbB.js → pagination-render-rZ5_6g0n.js} +1 -1
- package/assets/{register-C6acWsLe.js → register-Kfu8zmmu.js} +1 -1
- package/assets/tabs-CwgzWt48.js +1 -0
- package/assets/{theme-switcher-D8T9NgWG.js → theme-switcher-fzVA8btX.js} +1 -1
- package/assets/{user-info-CAgkqARx.js → user-info-Db5Y8KeN.js} +1 -1
- package/assets/{user-menu-content-BxL0QMC9.js → user-menu-content-Bc8YNZPf.js} +1 -1
- package/assets/{welcome-Dk7GoS5R.js → welcome-MKPFhPtG.js} +1 -1
- package/controllers/add.js +2 -0
- package/controllers/edit.js +14 -0
- package/controllers/login.js +56 -21
- package/controllers/media-manager/mediaManagerApi.js +1 -1
- package/controllers/notifications/NotificationController.d.ts +11 -0
- package/controllers/notifications/NotificationController.js +203 -0
- package/controllers/remove.js +2 -0
- package/files/favicon.png +0 -0
- package/helpers/diffHelpers.d.ts +2 -0
- package/helpers/diffHelpers.js +24 -0
- package/helpers/inertiaAutHelper.js +19 -0
- package/index.d.ts +2 -0
- package/index.js +2 -0
- package/interfaces/adminpanelConfig.d.ts +18 -0
- package/interfaces/types.d.ts +22 -0
- package/lib/Adminizer.d.ts +18 -2
- package/lib/Adminizer.js +61 -1
- package/lib/media-manager/AbstractMediaManager.js +2 -2
- package/lib/v4/model/adapter/sequelize.js +4 -0
- package/lib/v4/model/adapter/typeorm.d.ts +1 -0
- package/lib/v4/model/adapter/typeorm.js +21 -1
- package/lib/v4/notifications/AbstractNotificationService.d.ts +22 -0
- package/lib/v4/notifications/AbstractNotificationService.js +149 -0
- package/lib/v4/notifications/GeneralNotificationService.d.ts +8 -0
- package/lib/v4/notifications/GeneralNotificationService.js +56 -0
- package/lib/v4/notifications/NotificationHandler.d.ts +69 -0
- package/lib/v4/notifications/NotificationHandler.js +127 -0
- package/lib/v4/notifications/SystemNotificationService.d.ts +18 -0
- package/lib/v4/notifications/SystemNotificationService.js +123 -0
- package/models/NotificationAP.d.ts +36 -0
- package/models/NotificationAP.js +22 -0
- package/models/UserNotificationAP.d.ts +26 -0
- package/models/UserNotificationAP.js +18 -0
- package/package.json +13 -5
- package/system/Router.js +18 -0
- package/system/bindAssets.js +1 -0
- package/system/bindInertia.js +5 -0
- package/system/bindMediaManager.js +2 -1
- package/system/bindNavigation.js +2 -3
- package/system/bindNotifications.d.ts +2 -0
- package/system/bindNotifications.js +14 -0
- package/system/defaults.js +6 -0
- package/translations/ar.json +5 -4
- package/translations/cn.json +5 -4
- package/translations/de.json +72 -71
- package/translations/en.json +5 -4
- package/translations/es.json +5 -4
- package/translations/fr.json +5 -4
- package/translations/hi.json +5 -4
- package/translations/jp.json +5 -4
- package/translations/ko.json +5 -4
- package/translations/pt.json +5 -4
- package/translations/ru.json +2 -1
- package/translations/ua.json +5 -4
- package/translations/uz.json +73 -72
- package/translations/vi.json +5 -4
- package/assets/add-DOaZgoTz.js +0 -1
- package/assets/add-group-Br44s2D6.js +0 -1
- package/assets/add-user-DWcH0s9-.js +0 -1
- package/assets/app-sidebar-header-CIKLfLsF.js +0 -1
- package/assets/form-BXfnz6h5.js +0 -1
- package/assets/home-BD4MWmm9.js +0 -2
- package/assets/input-error-Bab-HPbn.js +0 -1
- package/assets/list-C-27EH39.js +0 -1
- package/assets/login-jzvVXgAV.js +0 -1
- package/assets/material-icon-DsiW0iQG.js +0 -1
- package/assets/media-manager-CSB_XRcE.js +0 -14
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { AbstractNotificationService } from './AbstractNotificationService';
|
|
2
|
+
import { Adminizer } from '../../Adminizer';
|
|
3
|
+
export class SystemNotificationService extends AbstractNotificationService {
|
|
4
|
+
notificationClass = 'system';
|
|
5
|
+
icon = 'settings';
|
|
6
|
+
iconColor = '#1eb707';
|
|
7
|
+
// Добавляем каналы для CRUD операций
|
|
8
|
+
crudChannels = new Map();
|
|
9
|
+
async dispatchNotification(notification) {
|
|
10
|
+
const fullNotification = {
|
|
11
|
+
...notification,
|
|
12
|
+
notificationClass: this.notificationClass,
|
|
13
|
+
channel: notification.channel ?? ''
|
|
14
|
+
};
|
|
15
|
+
let notificationDB;
|
|
16
|
+
// Сохраняем в базу
|
|
17
|
+
if (this.adminizer.modelHandler.model.has('notificationap')) {
|
|
18
|
+
try {
|
|
19
|
+
notificationDB = await this.adminizer.modelHandler.model.get('notificationap')["_create"](fullNotification);
|
|
20
|
+
const users = await this.adminizer.modelHandler.model.get('userap')["_find"]({ isAdministrator: 1 });
|
|
21
|
+
for (const user of users) {
|
|
22
|
+
try {
|
|
23
|
+
await this.createUserNotification(notificationDB.id, user.id);
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
Adminizer.log.error('Error creating UserNotificationAP:', error);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
const event = {
|
|
30
|
+
type: 'notification',
|
|
31
|
+
data: {
|
|
32
|
+
...notificationDB.toJSON(),
|
|
33
|
+
icon: {
|
|
34
|
+
icon: this.icon,
|
|
35
|
+
iconColor: this.iconColor
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
notificationClass: this.notificationClass,
|
|
39
|
+
userId: notification.userId ?? null,
|
|
40
|
+
channel: notification.channel // Добавляем информацию о канале
|
|
41
|
+
};
|
|
42
|
+
// Отправляем на все каналы или на конкретный канал
|
|
43
|
+
if (notification.channel) {
|
|
44
|
+
this.broadcastToChannel(notification.channel, event);
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
this.broadcast(event);
|
|
48
|
+
}
|
|
49
|
+
Adminizer.log.info(`[System] Notification dispatched: ${fullNotification.title}`);
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
Adminizer.log.error('Error saving system notification to database:', error);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
// Метод для отправки на конкретный канал
|
|
59
|
+
broadcastToChannel(channel, event) {
|
|
60
|
+
const channelClients = this.crudChannels.get(channel);
|
|
61
|
+
if (channelClients) {
|
|
62
|
+
channelClients.forEach(clientId => {
|
|
63
|
+
const sendFn = this.clients.get(clientId);
|
|
64
|
+
if (sendFn) {
|
|
65
|
+
try {
|
|
66
|
+
sendFn(event);
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
Adminizer.log.error(`[${this.notificationClass}] Error sending to client ${clientId} on channel ${channel}:`, error);
|
|
70
|
+
this.removeClient(clientId);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
// Добавляем клиента к каналу
|
|
77
|
+
addClientToChannel(clientId, channel) {
|
|
78
|
+
if (!this.crudChannels.has(channel)) {
|
|
79
|
+
this.crudChannels.set(channel, new Set());
|
|
80
|
+
}
|
|
81
|
+
this.crudChannels.get(channel).add(clientId);
|
|
82
|
+
Adminizer.log.info(`[${this.notificationClass}] Client ${clientId} added to channel ${channel}`);
|
|
83
|
+
}
|
|
84
|
+
// Удаляем клиента из канала
|
|
85
|
+
removeClientFromChannel(clientId, channel) {
|
|
86
|
+
const channelClients = this.crudChannels.get(channel);
|
|
87
|
+
if (channelClients) {
|
|
88
|
+
channelClients.delete(clientId);
|
|
89
|
+
Adminizer.log.info(`[${this.notificationClass}] Client ${clientId} removed from channel ${channel}`);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
// Удаляем клиента из всех каналов
|
|
93
|
+
removeClientFromAllChannels(clientId) {
|
|
94
|
+
this.crudChannels.forEach((clients, channel) => {
|
|
95
|
+
clients.delete(clientId);
|
|
96
|
+
Adminizer.log.info(`[${this.notificationClass}] Client ${clientId} removed from channel ${channel}`);
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
// Переопределяем removeClient для очистки каналов
|
|
100
|
+
removeClient(clientId) {
|
|
101
|
+
super.removeClient(clientId);
|
|
102
|
+
this.removeClientFromAllChannels(clientId);
|
|
103
|
+
}
|
|
104
|
+
// Специальный метод для системных событий с указанием канала
|
|
105
|
+
async logSystemEvent(title, message, channel, metadata) {
|
|
106
|
+
return this.dispatchNotification({
|
|
107
|
+
title: title,
|
|
108
|
+
message: message,
|
|
109
|
+
metadata: metadata,
|
|
110
|
+
channel: channel
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
// Методы для CRUD операций
|
|
114
|
+
async logCreatedEvent(title, message, metadata) {
|
|
115
|
+
return this.logSystemEvent(title, message, 'created', metadata);
|
|
116
|
+
}
|
|
117
|
+
async logUpdatedEvent(title, message, metadata) {
|
|
118
|
+
return this.logSystemEvent(title, message, 'updated', metadata);
|
|
119
|
+
}
|
|
120
|
+
async logDeletedEvent(title, message, metadata) {
|
|
121
|
+
return this.logSystemEvent(title, message, 'deleted', metadata);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { Model } from "sequelize";
|
|
2
|
+
declare const _default: {
|
|
3
|
+
id: {
|
|
4
|
+
type: string;
|
|
5
|
+
autoIncrement: boolean;
|
|
6
|
+
primaryKey: boolean;
|
|
7
|
+
};
|
|
8
|
+
title: {
|
|
9
|
+
type: string;
|
|
10
|
+
};
|
|
11
|
+
message: {
|
|
12
|
+
type: string;
|
|
13
|
+
};
|
|
14
|
+
notificationClass: {
|
|
15
|
+
type: string;
|
|
16
|
+
};
|
|
17
|
+
channel: {
|
|
18
|
+
type: string;
|
|
19
|
+
};
|
|
20
|
+
metadata: {
|
|
21
|
+
type: string;
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
export default _default;
|
|
25
|
+
export interface NotificationAP {
|
|
26
|
+
id: string;
|
|
27
|
+
title: string;
|
|
28
|
+
message: string;
|
|
29
|
+
channel: string;
|
|
30
|
+
notificationClass: string;
|
|
31
|
+
metadata?: Record<string, unknown>;
|
|
32
|
+
createdAt: Date;
|
|
33
|
+
}
|
|
34
|
+
export interface NotificationAPModel extends Model<NotificationAP>, NotificationAP {
|
|
35
|
+
toJSON(): NotificationAP;
|
|
36
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
id: {
|
|
3
|
+
type: "number",
|
|
4
|
+
autoIncrement: true,
|
|
5
|
+
primaryKey: true
|
|
6
|
+
},
|
|
7
|
+
title: {
|
|
8
|
+
type: "string"
|
|
9
|
+
},
|
|
10
|
+
message: {
|
|
11
|
+
type: "string"
|
|
12
|
+
},
|
|
13
|
+
notificationClass: {
|
|
14
|
+
type: "string",
|
|
15
|
+
},
|
|
16
|
+
channel: {
|
|
17
|
+
type: "string",
|
|
18
|
+
},
|
|
19
|
+
metadata: {
|
|
20
|
+
type: 'json'
|
|
21
|
+
}
|
|
22
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { NotificationAP } from "./NotificationAP";
|
|
2
|
+
declare const _default: {
|
|
3
|
+
id: {
|
|
4
|
+
type: string;
|
|
5
|
+
autoIncrement: boolean;
|
|
6
|
+
primaryKey: boolean;
|
|
7
|
+
};
|
|
8
|
+
userId: {
|
|
9
|
+
type: string;
|
|
10
|
+
required: boolean;
|
|
11
|
+
};
|
|
12
|
+
notificationId: {
|
|
13
|
+
model: string;
|
|
14
|
+
};
|
|
15
|
+
read: {
|
|
16
|
+
type: string;
|
|
17
|
+
defaultsTo: boolean;
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
export default _default;
|
|
21
|
+
export interface UserNotificationAP {
|
|
22
|
+
id: number;
|
|
23
|
+
userId: number;
|
|
24
|
+
notificationId: NotificationAP;
|
|
25
|
+
read: boolean;
|
|
26
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
id: {
|
|
3
|
+
type: "number",
|
|
4
|
+
autoIncrement: true,
|
|
5
|
+
primaryKey: true
|
|
6
|
+
},
|
|
7
|
+
userId: {
|
|
8
|
+
type: "number",
|
|
9
|
+
required: true
|
|
10
|
+
},
|
|
11
|
+
notificationId: {
|
|
12
|
+
model: "NotificationAP"
|
|
13
|
+
},
|
|
14
|
+
read: {
|
|
15
|
+
type: "boolean",
|
|
16
|
+
defaultsTo: false
|
|
17
|
+
}
|
|
18
|
+
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "adminizer",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "4.
|
|
4
|
+
"version": "4.3.0-build.74",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"exports": {
|
|
7
7
|
".": "./index.js",
|
|
@@ -32,9 +32,16 @@
|
|
|
32
32
|
"demo": "cross-env ORM=sequelize tsx --tsconfig ./fixture/tsconfig.json ./fixture/index.ts"
|
|
33
33
|
},
|
|
34
34
|
"keywords": [],
|
|
35
|
-
"author": "",
|
|
35
|
+
"author": "Siziy Ivan <xziy88@gmail.com>",
|
|
36
|
+
"contributors": [
|
|
37
|
+
"Serebriakov Roman <rserebryakov1902@gmail.com>"
|
|
38
|
+
],
|
|
36
39
|
"license": "MIT",
|
|
37
|
-
"description": "",
|
|
40
|
+
"description": "A modern, framework-agnostic admin panel for Node.js with TypeScript backend and React frontend",
|
|
41
|
+
"repository": {
|
|
42
|
+
"type": "git",
|
|
43
|
+
"url": "https://github.com/adminization/adminizer"
|
|
44
|
+
},
|
|
38
45
|
"dependencies": {
|
|
39
46
|
"@minoru/react-dnd-treeview": "^3.5.2",
|
|
40
47
|
"@radix-ui/react-context-menu": "^2.2.15",
|
|
@@ -47,8 +54,10 @@
|
|
|
47
54
|
"cors": "^2.8.5",
|
|
48
55
|
"crypto-puzzle": "^5.0.2",
|
|
49
56
|
"date-fns": "^3.6.0",
|
|
57
|
+
"deep-object-diff": "^1.1.9",
|
|
50
58
|
"express": "^4.21.2",
|
|
51
59
|
"express-session": "^1.18.1",
|
|
60
|
+
"image-size": "^2.0.2",
|
|
52
61
|
"jsonwebtoken": "^9.0.2",
|
|
53
62
|
"material-icons": "^1.13.14",
|
|
54
63
|
"multer": "^1.4.5-lts.1",
|
|
@@ -62,7 +71,7 @@
|
|
|
62
71
|
"uuid": "^11.0.5",
|
|
63
72
|
"waterline": "^0.15.2",
|
|
64
73
|
"winston": "^3.17.0",
|
|
65
|
-
"
|
|
74
|
+
"sprintf-js": "^1.1.3",
|
|
66
75
|
"sequelize": "^6.37.7"
|
|
67
76
|
},
|
|
68
77
|
"devDependencies": {
|
|
@@ -140,7 +149,6 @@
|
|
|
140
149
|
"sequelize-typescript": "^2.1.6",
|
|
141
150
|
"shelljs": "^0.9.2",
|
|
142
151
|
"sonner": "^2.0.3",
|
|
143
|
-
"sprintf-js": "^1.1.3",
|
|
144
152
|
"sqlite3": "^5.1.7",
|
|
145
153
|
"tailwind-merge": "^3.0.2",
|
|
146
154
|
"tailwindcss": "^4.0.15",
|
package/system/Router.js
CHANGED
|
@@ -18,6 +18,7 @@ import { mediaManagerController } from "../controllers/media-manager/mediaManage
|
|
|
18
18
|
import { thumbController } from "../controllers/media-manager/ThumbController";
|
|
19
19
|
import { Adminizer } from "../lib/Adminizer";
|
|
20
20
|
import timezones from "../controllers/timezones";
|
|
21
|
+
import { NotificationController } from "../controllers/notifications/NotificationController";
|
|
21
22
|
export default class Router {
|
|
22
23
|
static onlyOnce = false;
|
|
23
24
|
/**
|
|
@@ -80,6 +81,23 @@ export default class Router {
|
|
|
80
81
|
adminizer.app.post(`${adminizer.config.routePrefix}/media-manager-uploader/:id/upload-variant`, adminizer.policyManager.bindPolicies(policies, mediaManagerController));
|
|
81
82
|
adminizer.app.all(`${adminizer.config.routePrefix}/media-manager-uploader/:id`, adminizer.policyManager.bindPolicies(policies, mediaManagerController));
|
|
82
83
|
adminizer.app.all(`${adminizer.config.routePrefix}/get-thumbs`, adminizer.policyManager.bindPolicies(policies, thumbController));
|
|
84
|
+
/**
|
|
85
|
+
* Notifications
|
|
86
|
+
*/
|
|
87
|
+
if (adminizer.config.notification.enabled) {
|
|
88
|
+
adminizer.app.get(`${adminizer.config.routePrefix}/notifications`, adminizer.policyManager.bindPolicies(policies, NotificationController.viewAll));
|
|
89
|
+
adminizer.app.get(`${adminizer.config.routePrefix}/api/notifications/stream`, adminizer.policyManager.bindPolicies(policies, NotificationController.getNotificationsStream));
|
|
90
|
+
adminizer.app.get(`${adminizer.config.routePrefix}/api/notifications/:notificationClass`, adminizer.policyManager.bindPolicies(policies, NotificationController.getNotificationsByClass));
|
|
91
|
+
adminizer.app.get(`${adminizer.config.routePrefix}/api/notifications`, adminizer.policyManager.bindPolicies(policies, NotificationController.getUserNotifications));
|
|
92
|
+
adminizer.app.get(`${adminizer.config.routePrefix}/api/notifications-all`, adminizer.policyManager.bindPolicies(policies, NotificationController.getAllUserNotifications));
|
|
93
|
+
adminizer.app.put(`${adminizer.config.routePrefix}/api/notifications/:notificationClass/:id/read`, adminizer.policyManager.bindPolicies(policies, NotificationController.markAsRead));
|
|
94
|
+
// adminizer.app.post(
|
|
95
|
+
// `${adminizer.config.routePrefix}/api/notifications/send`,
|
|
96
|
+
// adminizer.policyManager.bindPolicies([...policies, 'isAdmin'],
|
|
97
|
+
// (req: ReqType, res: ResType) => NotificationController.sendNotification(req, res)
|
|
98
|
+
// )
|
|
99
|
+
// );
|
|
100
|
+
}
|
|
83
101
|
/**
|
|
84
102
|
* List of records
|
|
85
103
|
*/
|
package/system/bindAssets.js
CHANGED
|
@@ -2,4 +2,5 @@ import serveStatic from 'serve-static';
|
|
|
2
2
|
import * as path from "path";
|
|
3
3
|
export default function bindAssets(app, routePrefix) {
|
|
4
4
|
app.use(`${routePrefix}/assets`, serveStatic(path.join(import.meta.dirname, '../assets')));
|
|
5
|
+
app.use(`${routePrefix}/files`, serveStatic(path.join(import.meta.dirname, '../files')));
|
|
5
6
|
}
|
package/system/bindInertia.js
CHANGED
|
@@ -17,6 +17,7 @@ export function bindInertia(adminizer) {
|
|
|
17
17
|
<script type="module" src="/@vite/client"></script>
|
|
18
18
|
<script type="module" src="/src/assets/js/app.tsx"></script>
|
|
19
19
|
<script>window.routePrefix = "${adminizer.config.routePrefix}"</script>
|
|
20
|
+
<script>window.bindPublic = ${adminizer.config.bind?.public}</script>
|
|
20
21
|
`;
|
|
21
22
|
}
|
|
22
23
|
else {
|
|
@@ -57,11 +58,14 @@ export function bindInertia(adminizer) {
|
|
|
57
58
|
});
|
|
58
59
|
// Route prefix script
|
|
59
60
|
const routePrefixScript = `<script>window.routePrefix = "${adminizer.config.routePrefix}";</script>`;
|
|
61
|
+
// For Sails JS
|
|
62
|
+
const bindPublic = `<script>window.bindPublic = ${adminizer.config.bind?.public}</script>`;
|
|
60
63
|
return `
|
|
61
64
|
${preloadLinks.join('\n')}
|
|
62
65
|
${stylesheets.join('\n')}
|
|
63
66
|
${scripts.join('\n')}
|
|
64
67
|
${routePrefixScript}
|
|
68
|
+
${bindPublic}
|
|
65
69
|
`;
|
|
66
70
|
}
|
|
67
71
|
};
|
|
@@ -71,6 +75,7 @@ export function bindInertia(adminizer) {
|
|
|
71
75
|
<head>
|
|
72
76
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
73
77
|
<meta charset="utf-8"><title inertia></title>
|
|
78
|
+
<link rel="icon" type="image/png" href="${adminizer.config.routePrefix}/files/favicon.png">
|
|
74
79
|
${viteRender()}
|
|
75
80
|
</head>
|
|
76
81
|
<body>
|
|
@@ -15,7 +15,8 @@ export default function bindMediaManager(adminizer) {
|
|
|
15
15
|
}
|
|
16
16
|
});
|
|
17
17
|
// Bind media manager public folder
|
|
18
|
-
adminizer.
|
|
18
|
+
if (adminizer.config.bind?.public && adminizer.config.mediamanager?.fileStoragePath)
|
|
19
|
+
adminizer.app.use(`/public`, serveStatic(adminizer.config.mediamanager.fileStoragePath));
|
|
19
20
|
// Bind file icons
|
|
20
21
|
adminizer.app.use(`${adminizer.config.routePrefix}/fileicons`, serveStatic(path.join(import.meta.dirname, '../fileicons')));
|
|
21
22
|
}
|
package/system/bindNavigation.js
CHANGED
|
@@ -16,7 +16,7 @@ export default function bindNavigation(adminizer) {
|
|
|
16
16
|
updatedAt: false
|
|
17
17
|
},
|
|
18
18
|
navbar: {
|
|
19
|
-
visible:
|
|
19
|
+
visible: false
|
|
20
20
|
},
|
|
21
21
|
icon: 'storage',
|
|
22
22
|
identifierField: "",
|
|
@@ -29,8 +29,7 @@ export default function bindNavigation(adminizer) {
|
|
|
29
29
|
model: adminizer.config.navigation.model.toLowerCase(),
|
|
30
30
|
remove: false,
|
|
31
31
|
title: adminizer.config.navigation.model,
|
|
32
|
-
tools: []
|
|
33
|
-
view: false
|
|
32
|
+
tools: []
|
|
34
33
|
};
|
|
35
34
|
}
|
|
36
35
|
catch (e) {
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Adminizer } from '../lib/Adminizer';
|
|
2
|
+
import { NotificationHandler } from '../lib/v4/notifications/NotificationHandler';
|
|
3
|
+
import { GeneralNotificationService } from '../lib/v4/notifications/GeneralNotificationService';
|
|
4
|
+
import { SystemNotificationService } from '../lib/v4/notifications/SystemNotificationService';
|
|
5
|
+
export async function bindNotifications(adminizer) {
|
|
6
|
+
// Создаем хендлер
|
|
7
|
+
adminizer.notificationHandler = new NotificationHandler();
|
|
8
|
+
// Регистрируем сервисы
|
|
9
|
+
const generalService = new GeneralNotificationService(adminizer);
|
|
10
|
+
const systemService = new SystemNotificationService(adminizer);
|
|
11
|
+
adminizer.notificationHandler.registerService(generalService);
|
|
12
|
+
adminizer.notificationHandler.registerService(systemService);
|
|
13
|
+
Adminizer.log.info(`Notification system initialized with 2 services: ${systemService.notificationClass}, ${systemService.notificationClass}`);
|
|
14
|
+
}
|
package/system/defaults.js
CHANGED
package/translations/ar.json
CHANGED
|
@@ -3,9 +3,10 @@
|
|
|
3
3
|
"Actions": "ﺕﺍءﺍﺮﺟﻹﺍ",
|
|
4
4
|
"All": "ﻊﻴﻤﺠﻟﺍ",
|
|
5
5
|
"Are you sure?": "؟ﺪﻛﺄﺘﻣ ﺖﻧﺃ ﻞﻫ",
|
|
6
|
-
"Back": "ﻒﻠﺧ",
|
|
7
|
-
"Back to Login": "ﻝﻮﺧﺪﻟﺍ ﻞﻴﺠﺴﺗ ﻰﻟﺇ ﺓﺩﻮﻌﻟﺍ",
|
|
8
|
-
"
|
|
6
|
+
"Back": "ﻒﻠﺧ",
|
|
7
|
+
"Back to Login": "ﻝﻮﺧﺪﻟﺍ ﻞﻴﺠﺴﺗ ﻰﻟﺇ ﺓﺩﻮﻌﻟﺍ",
|
|
8
|
+
"Additional login page": "صفحة تسجيل دخول إضافية",
|
|
9
|
+
"Clean": "Clean",
|
|
9
10
|
"Confirm Password": "ﺭﻭﺮﻤﻟﺍ ﺔﻤﻠﻛ ﺪﻴﻛﺄﺗ",
|
|
10
11
|
"Confirm Password*": "*ﺭﻭﺮﻤﻟﺍ ﺔﻤﻠﻛ ﺪﻴﻛﺄﺗ",
|
|
11
12
|
"Create": "ﻖﻠﺨﻳ",
|
|
@@ -69,4 +70,4 @@
|
|
|
69
70
|
"You don't have any widgets selected yet. You can add them by clicking on the plus sign at the top right.": ".ﻦﻴﻤﻴﻟﺍ ﻰﻠﻋﺃ ﻲﻓ Plus ﺔﻣﻼﻋ ﻕﻮﻓ ﺮﻘﻨﻟﺎﺑ ﺎﻬﺘﻓﺎﺿﺇ ﻚﻨﻜﻤﻳ .ﻥﻵﺍ ﻰﺘﺣ ﺓﺩﺪﺤﻣ ﺓﺮﻐﺼﻣ ﻱﺃ ﻚﻳﺪ",
|
|
70
71
|
"create": "ﻖﻠﺨﻳ",
|
|
71
72
|
"create new": "ﺪﻳﺪﺟ ءﺎﺸﻧﺇ"
|
|
72
|
-
}
|
|
73
|
+
}
|
package/translations/cn.json
CHANGED
|
@@ -3,9 +3,10 @@
|
|
|
3
3
|
"Actions": "动作",
|
|
4
4
|
"All": "全部",
|
|
5
5
|
"Are you sure?": "你确定吗?",
|
|
6
|
-
"Back": "后退",
|
|
7
|
-
"Back to Login": "返回登录",
|
|
8
|
-
"
|
|
6
|
+
"Back": "后退",
|
|
7
|
+
"Back to Login": "返回登录",
|
|
8
|
+
"Additional login page": "额外的登录页面",
|
|
9
|
+
"Clean": "干净的",
|
|
9
10
|
"Confirm Password": "确认密码",
|
|
10
11
|
"Confirm Password*": "确认密码*",
|
|
11
12
|
"Create": "创造",
|
|
@@ -69,4 +70,4 @@
|
|
|
69
70
|
"You don't have any widgets selected yet. You can add them by clicking on the plus sign at the top right.": "您还没有选择任何小部件。您可以通过单击右上角的加号来添加它们。",
|
|
70
71
|
"create": "创造",
|
|
71
72
|
"create new": "创建新"
|
|
72
|
-
}
|
|
73
|
+
}
|
package/translations/de.json
CHANGED
|
@@ -1,72 +1,73 @@
|
|
|
1
1
|
{
|
|
2
|
-
"Action completed": "Aktion abgeschlossen",
|
|
3
|
-
"Actions": "Aktionen",
|
|
4
|
-
"All": "Alle",
|
|
5
|
-
"Are you sure?": "Bist du sicher?",
|
|
6
|
-
"Back": "Zurück",
|
|
7
|
-
"Back to Login": "Zurück zum Anmeldung",
|
|
8
|
-
"
|
|
9
|
-
"
|
|
10
|
-
"Confirm Password
|
|
11
|
-
"
|
|
12
|
-
"Create
|
|
13
|
-
"Create
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"Full
|
|
22
|
-
"
|
|
23
|
-
"Group
|
|
24
|
-
"Group
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
"Is
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
"No
|
|
36
|
-
"No
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
"
|
|
48
|
-
"Record was removed
|
|
49
|
-
"Record was
|
|
50
|
-
"
|
|
51
|
-
"
|
|
52
|
-
"
|
|
53
|
-
"
|
|
54
|
-
"
|
|
55
|
-
"
|
|
56
|
-
"Select
|
|
57
|
-
"Select
|
|
58
|
-
"Select
|
|
59
|
-
"
|
|
60
|
-
"
|
|
61
|
-
"
|
|
62
|
-
"
|
|
63
|
-
"
|
|
64
|
-
"User
|
|
65
|
-
"
|
|
66
|
-
"
|
|
67
|
-
"
|
|
68
|
-
"
|
|
69
|
-
"
|
|
70
|
-
"
|
|
71
|
-
"create
|
|
72
|
-
|
|
2
|
+
"Action completed": "Aktion abgeschlossen",
|
|
3
|
+
"Actions": "Aktionen",
|
|
4
|
+
"All": "Alle",
|
|
5
|
+
"Are you sure?": "Bist du sicher?",
|
|
6
|
+
"Back": "Zurück",
|
|
7
|
+
"Back to Login": "Zurück zum Anmeldung",
|
|
8
|
+
"Additional login page": "Zusätzliche Anmeldeseite",
|
|
9
|
+
"Clean": "Sauber",
|
|
10
|
+
"Confirm Password": "Passwort bestätigen",
|
|
11
|
+
"Confirm Password*": "Passwort bestätigen*",
|
|
12
|
+
"Create": "Erstellen",
|
|
13
|
+
"Create a new administrator": "Erstellen Sie einen neuen Administrator",
|
|
14
|
+
"Create an Account": "Ein Konto erstellen",
|
|
15
|
+
"Custom": "Brauch",
|
|
16
|
+
"Delete": "Löschen",
|
|
17
|
+
"E-mail": "E-Mail",
|
|
18
|
+
"Edit": "Bearbeiten",
|
|
19
|
+
"Email": "E-Mail",
|
|
20
|
+
"Fast links": "Schnelle Links",
|
|
21
|
+
"Full Name": "Vollständiger Name",
|
|
22
|
+
"Full name": "Vollständiger Name",
|
|
23
|
+
"Group description": "Gruppenbeschreibung",
|
|
24
|
+
"Group name": "Gruppenname",
|
|
25
|
+
"Group settings": "Gruppeneinstellungen",
|
|
26
|
+
"Info": "Info",
|
|
27
|
+
"Is Administrator": "Ist Administrator",
|
|
28
|
+
"Is confirmed": "Wird bestätigt",
|
|
29
|
+
"Link": "Link",
|
|
30
|
+
"Locale": "Gebietsschema",
|
|
31
|
+
"Log in": "Einloggen",
|
|
32
|
+
"Login": "Login",
|
|
33
|
+
"Members": "Mitglieder",
|
|
34
|
+
"New record was created": "Neuer Rekord wurde erstellt",
|
|
35
|
+
"No": "NEIN",
|
|
36
|
+
"No records found !": "Keine Aufzeichnungen gefunden!",
|
|
37
|
+
"No widgets found": "Keine Widgets gefunden",
|
|
38
|
+
"Not found": "Nicht gefunden",
|
|
39
|
+
"OR": "ODER",
|
|
40
|
+
"Open in a new window": "Öffnen Sie in einem neuen Fenster",
|
|
41
|
+
"Password": "Passwort",
|
|
42
|
+
"Passwords do not match!": "Passwörter stimmen nicht überein!",
|
|
43
|
+
"Performing an action...": "Eine Aktion ausführen ...",
|
|
44
|
+
"Please fill out the fields below": "Bitte füllen Sie die folgenden Felder aus",
|
|
45
|
+
"Pretend to be a user": "Vorgeben, Benutzer zu sein",
|
|
46
|
+
"Profile expires": "Profil läuft ab",
|
|
47
|
+
"Quick actions": "Schnelle Aktionen",
|
|
48
|
+
"Record was not removed": "Rekord wurde nicht entfernt",
|
|
49
|
+
"Record was removed successfully !": "Rekord wurde erfolgreich entfernt!",
|
|
50
|
+
"Record was updated": "Der Datensatz wurde aktualisiert",
|
|
51
|
+
"Register": "Registrieren",
|
|
52
|
+
"Repeat password": "Passwort wiederholen",
|
|
53
|
+
"Reset": "Zurücksetzen",
|
|
54
|
+
"Save": "Speichern",
|
|
55
|
+
"Search": "Suchen",
|
|
56
|
+
"Select": "Wählen",
|
|
57
|
+
"Select Ids": "IDS auswählen",
|
|
58
|
+
"Select Item type": "Wählen Sie den Elementtyp",
|
|
59
|
+
"Select Items": "Elemente auswählen",
|
|
60
|
+
"Switcher": "Schalter",
|
|
61
|
+
"Timezone": "Zeitzone",
|
|
62
|
+
"Title": "Titel",
|
|
63
|
+
"Toggle to change the grid. To save the grid, turn it off.": "Umschalten, um das Netz zu ändern. Um das Netz zu retten, schalten Sie es aus.",
|
|
64
|
+
"User groups": "Benutzergruppen",
|
|
65
|
+
"User settings": "Benutzereinstellungen",
|
|
66
|
+
"Values in \"password\" and \"repeatPassword\" fields should be the same": "Werte in \"Passwort\" und \"RepeatPassword\" -Feldern sollten gleich sein",
|
|
67
|
+
"View": "Sicht",
|
|
68
|
+
"Welcome": "Willkommen",
|
|
69
|
+
"Yes": "Ja",
|
|
70
|
+
"You don't have any widgets selected yet. You can add them by clicking on the plus sign at the top right.": "Sie haben noch keine Widgets ausgewählt. Sie können sie hinzufügen, indem Sie oben rechts auf das Pluszeichen klicken.",
|
|
71
|
+
"create": "erstellen",
|
|
72
|
+
"create new": "neu erstellen"
|
|
73
|
+
}
|
package/translations/en.json
CHANGED
|
@@ -3,9 +3,10 @@
|
|
|
3
3
|
"Actions": "Actions",
|
|
4
4
|
"All": "All",
|
|
5
5
|
"Are you sure?": "Are you sure?",
|
|
6
|
-
"Back": "Back",
|
|
7
|
-
"Back to Login": "Back to Login",
|
|
8
|
-
"
|
|
6
|
+
"Back": "Back",
|
|
7
|
+
"Back to Login": "Back to Login",
|
|
8
|
+
"Additional login page": "Additional login page",
|
|
9
|
+
"Clean": "Clean",
|
|
9
10
|
"Confirm Password": "Confirm Password",
|
|
10
11
|
"Confirm Password*": "Confirm Password*",
|
|
11
12
|
"Create": "Create",
|
|
@@ -139,4 +140,4 @@
|
|
|
139
140
|
"Sizes/Ver": "Sizes/Ver",
|
|
140
141
|
"Locales": "Locales",
|
|
141
142
|
"Date": "Date"
|
|
142
|
-
}
|
|
143
|
+
}
|