adminizer 4.3.0-build.99 → 4.3.0
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-9NSjG6Jx.js +1 -0
- package/assets/add-form-uUiOWEy_.js +1 -0
- package/assets/add-group-Db0HkA1m.js +1 -0
- package/assets/add-group-form-DMz0_Oo9.js +1 -0
- package/assets/add-user-BMklpOqf.js +1 -0
- package/assets/{add-user-form-DrclnTOd.js → add-user-form-izlXhv2-.js} +1 -1
- package/assets/{app-D8oqdt8J.css → app-BJd5vD4i.css} +1 -1
- package/assets/app-layout-DcgYmhNb.js +1 -0
- package/assets/{app-shell-CHEYhVco.js → app-shell-C8Cnr5Hy.js} +1 -1
- package/assets/app-sidebar-HwvXNZzk.js +1 -0
- package/assets/app-sidebar-header-C8TTx8yd.js +1 -0
- package/assets/app.js +5 -5
- package/assets/{breadcrumbs-C439DWrC.js → breadcrumbs-DSMzNYiS.js} +1 -1
- package/assets/catalog-C2INmTwI.js +6 -0
- package/assets/catalog-D4n6dpGl.css +1 -0
- package/assets/{dashboard-Bi5KeZu2.js → dashboard-DwFL6nqn.js} +1 -1
- package/assets/{date-picker-DbJ8nHp5.js → date-picker-kW3wZQr_.js} +1 -1
- package/assets/{del-modal-_b3CSNHb.js → del-modal-DyIWFflP.js} +1 -1
- package/assets/{field-renderer-4obZ_jUo.js → field-renderer-BNQVfOir.js} +3 -3
- package/assets/form-CAIoGuhZ.js +1 -0
- package/assets/form-NUd-JZJN.js +1 -0
- package/assets/{geo-json-CadjdhwW.js → geo-json-YeWQOYnT.js} +1 -1
- package/assets/{home-BUoDaWe0.js → home-CteDT1us.js} +2 -2
- package/assets/{icon-DM49pZW3.js → icon-DpkedrXG.js} +1 -1
- package/assets/{init-user-DNrB8Xt5.js → init-user-DaOvt0vG.js} +1 -1
- package/assets/{input-error--IOnWghB.js → input-error-CmXZF6xy.js} +1 -1
- package/assets/list-CXQmJbH8.js +1 -0
- package/assets/{list-table-BKxxQkCW.js → list-table-BPpHDVPf.js} +4 -4
- package/assets/{login-6Xb8bcPq.js → login-DR6fvKtm.js} +1 -1
- package/assets/manifest.json +82 -82
- package/assets/{material-icon-BedgD2NE.js → material-icon-DwkE6wKL.js} +1 -1
- package/assets/media-manager-DYOfUh8F.js +14 -0
- package/assets/{module-B4-7WkY5.js → module-BIUqcf4-.js} +1 -1
- package/assets/{nav-footer-BwkQkwow.js → nav-footer-B85HLj-j.js} +1 -1
- package/assets/{nav-main-9Eb_A0rf.js → nav-main-BqKm87JZ.js} +1 -1
- package/assets/nav-user-DuCZNsZX.js +1 -0
- package/assets/notification-BQTjxH2H.js +27 -0
- package/assets/pagination-render-io0M2m2O.js +1 -0
- package/assets/{register-BIyjCy8M.js → register-hJD1ETdf.js} +1 -1
- package/assets/{tabs-BK_5wdPA.js → tabs-BhkFoerH.js} +1 -1
- package/assets/{theme-switcher-CKiJbMkh.js → theme-switcher-cgyA7_cO.js} +1 -1
- package/assets/{toast-editor-BZM5RHph.js → toast-editor-DwRk6WqT.js} +1 -1
- package/assets/{user-info-CcYdmjMZ.js → user-info-BGQvqBmO.js} +1 -1
- package/assets/{user-menu-content-DbUk8ZeY.js → user-menu-content-BDm88xaM.js} +1 -1
- package/assets/welcome-ks57d2us.js +1 -0
- package/controllers/add.js +1 -1
- package/controllers/catalog/Catalog.js +21 -20
- package/controllers/catalog/FrontendCatalogAdapter.d.ts +82 -0
- package/controllers/catalog/FrontendCatalogAdapter.js +228 -0
- package/controllers/catalog/FrontentCatalogAdapter.d.ts +4 -4
- package/controllers/catalog/FrontentCatalogAdapter.js +28 -10
- package/controllers/edit.js +14 -5
- package/controllers/form.js +8 -6
- package/controllers/login.js +3 -0
- package/controllers/media-manager/ThumbController.js +1 -1
- package/controllers/media-manager/mediaManagerAdapter.js +1 -1
- package/controllers/media-manager/mediaManagerApi.js +1 -2
- package/controllers/notifications/NotificationController.d.ts +1 -1
- package/controllers/notifications/NotificationController.js +5 -4
- package/controllers/view.js +5 -3
- package/helpers/inertiaAddHelper.js +1 -2
- package/helpers/inertiaFromHelper.js +1 -2
- package/index.d.ts +5 -0
- package/index.js +5 -0
- package/interfaces/adminpanelConfig.d.ts +12 -0
- package/lib/Adminizer.d.ts +4 -3
- package/lib/Adminizer.js +16 -22
- package/lib/catalog/AbstractCatalog.d.ts +6 -4
- package/lib/catalog/AbstractCatalog.js +5 -4
- package/lib/catalog/Navigation.d.ts +9 -7
- package/lib/catalog/Navigation.js +69 -40
- package/lib/inertia/inertiaAdapter.js +31 -13
- package/lib/media-manager/AbstractMediaManager.d.ts +5 -3
- package/lib/media-manager/DefaultMediaManager.d.ts +3 -3
- package/lib/media-manager/DefaultMediaManager.js +18 -13
- package/lib/media-manager/Items.js +5 -4
- package/lib/media-manager/MediaManagerHandler.d.ts +3 -3
- package/lib/media-manager/MediaManagerHandler.js +3 -3
- package/lib/media-manager/Thumb.d.ts +2 -1
- package/lib/media-manager/Thumb.js +3 -4
- package/lib/media-manager/helpers/MediaManagerHelper.d.ts +7 -2
- package/lib/media-manager/helpers/MediaManagerHelper.js +12 -8
- package/lib/model/adapter/waterline.js +6 -0
- package/package.json +3 -1
- package/system/Router.js +10 -8
- package/system/bindAccessRights.js +7 -0
- package/system/bindCors.d.ts +2 -0
- package/system/bindCors.js +41 -0
- package/system/bindInertia.js +1 -1
- package/system/bindMediaManager.js +1 -2
- package/system/bindNavigation.d.ts +1 -1
- package/system/bindNavigation.js +33 -35
- package/system/bindNotifications.js +4 -4
- package/system/bindReqFunctions.js +4 -1
- package/system/defaults.js +8 -0
- package/translations/ru.json +121 -120
- package/ui/components/handsontable.js +6 -3
- package/ui/lib/utils.d.ts +1 -0
- package/ui/lib/utils.js +16 -0
- package/assets/add-1E1UsMVZ.js +0 -1
- package/assets/add-form-CGa9QbwE.js +0 -1
- package/assets/add-group-7yAK6uFY.js +0 -1
- package/assets/add-group-form-BNmpvW8K.js +0 -1
- package/assets/add-user-NoYkTfZi.js +0 -1
- package/assets/app-layout-i2zN9Rn-.js +0 -1
- package/assets/app-sidebar-DeF8WNmW.js +0 -1
- package/assets/app-sidebar-header-DdM1EOrb.js +0 -1
- package/assets/catalog-B9hdop59.js +0 -6
- package/assets/catalog-C71LuRag.css +0 -1
- package/assets/form-Bte5kzjB.js +0 -1
- package/assets/form-oUlsuu7h.js +0 -1
- package/assets/list-C04Krl_W.js +0 -1
- package/assets/media-manager-UQT6RhI8.js +0 -14
- package/assets/nav-user-CRAfyE-x.js +0 -1
- package/assets/notification-ma2x7vka.js +0 -27
- package/assets/pagination-render-D3UyVAlr.js +0 -1
- package/assets/welcome-cWh1qnl_.js +0 -1
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { MediaManagerHandler } from "../MediaManagerHandler";
|
|
2
1
|
/**
|
|
3
2
|
* Create a random file name with prefix and type. If prefix is true, the file name will be prefixed with a random string.
|
|
4
3
|
* @param filenameOrig
|
|
@@ -13,32 +12,37 @@ export function randomFileName(filenameOrig, type, prefix) {
|
|
|
13
12
|
}
|
|
14
13
|
/**
|
|
15
14
|
* Save media manager relations to database.
|
|
15
|
+
* @param adminizer
|
|
16
16
|
* @param fields
|
|
17
17
|
* @param reqData
|
|
18
18
|
* @param model
|
|
19
19
|
* @param recordId
|
|
20
20
|
*/
|
|
21
|
-
export async function saveRelationsMediaManager(fields, reqData, model, recordId) {
|
|
21
|
+
export async function saveRelationsMediaManager(adminizer, fields, reqData, model, recordId) {
|
|
22
22
|
for (let prop in reqData) {
|
|
23
23
|
let fieldConfigConfig = fields[prop].config;
|
|
24
24
|
let options = fieldConfigConfig.options;
|
|
25
25
|
if (fieldConfigConfig.type === 'mediamanager') {
|
|
26
26
|
let data = reqData[prop];
|
|
27
|
-
let mediaManager =
|
|
27
|
+
let mediaManager = adminizer.mediaManagerHandler.get(options?.id ?? 'default');
|
|
28
28
|
await mediaManager.setRelations(data, model, recordId, prop);
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
/**
|
|
33
33
|
* Get realtions
|
|
34
|
+
* @param adminizer
|
|
34
35
|
* @param data
|
|
36
|
+
* @param model
|
|
37
|
+
* @param widgetName
|
|
35
38
|
*/
|
|
36
|
-
export async function getRelationsMediaManager(data) {
|
|
37
|
-
let mediaManager =
|
|
38
|
-
return await mediaManager.
|
|
39
|
+
export async function getRelationsMediaManager(adminizer, data) {
|
|
40
|
+
let mediaManager = adminizer.mediaManagerHandler.get(data.mediaManagerId);
|
|
41
|
+
return await mediaManager.getRelations(data.model, data.widgetName, data.modelId);
|
|
39
42
|
}
|
|
40
43
|
/**
|
|
41
44
|
* Delate Ralations
|
|
45
|
+
* @param adminizer
|
|
42
46
|
* @param model
|
|
43
47
|
* @param record
|
|
44
48
|
*/
|
|
@@ -48,9 +52,9 @@ export async function deleteRelationsMediaManager(adminizer, model, record) {
|
|
|
48
52
|
let field = config.fields[key];
|
|
49
53
|
if (field && field.type === 'mediamanager') {
|
|
50
54
|
const option = field.options;
|
|
51
|
-
let mediaManager =
|
|
55
|
+
let mediaManager = adminizer.mediaManagerHandler.get(option?.id ?? 'default');
|
|
52
56
|
let emptyData = [];
|
|
53
|
-
await mediaManager.setRelations(emptyData, model, record[0].id, key);
|
|
57
|
+
await mediaManager.setRelations(emptyData, model, +record[0].id, key);
|
|
54
58
|
}
|
|
55
59
|
}
|
|
56
60
|
}
|
|
@@ -33,6 +33,12 @@ export class WaterlineModel extends AbstractModel {
|
|
|
33
33
|
return await query;
|
|
34
34
|
}
|
|
35
35
|
async _find(criteria = {}, options = {}) {
|
|
36
|
+
// Hack
|
|
37
|
+
const attributes = this.model.attributes;
|
|
38
|
+
const associations = Object.keys(attributes).filter(attr => attributes[attr].model || attributes[attr].collection);
|
|
39
|
+
//@ts-ignore
|
|
40
|
+
if (associations.includes(criteria?.sort?.split(' ')[0]) && JSON.stringify(criteria.where) === '{}')
|
|
41
|
+
criteria.sort = undefined;
|
|
36
42
|
let query = this.model.find(criteria);
|
|
37
43
|
if (options.populate && Array.isArray(options.populate) && options.populate.length > 0) {
|
|
38
44
|
options.populate.forEach(([field, populateCriteria]) => {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "adminizer",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "4.3.0
|
|
4
|
+
"version": "4.3.0",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"exports": {
|
|
7
7
|
".": "./index.js",
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
"dev:no-seed-clean": "cross-env VITE_ENV=dev NO_SEED_DATA=true CLEAN_TMP=true ORM=sequelize tsx watch --tsconfig ./fixture/tsconfig.json ./fixture/index.ts",
|
|
17
17
|
"dev:waterline": "cross-env VITE_ENV=dev ORM=waterline tsx watch --tsconfig ./fixture/tsconfig.json ./fixture/index.ts",
|
|
18
18
|
"dev:waterline:no-seed": "cross-env VITE_ENV=dev NO_SEED_DATA=true ORM=waterline tsx watch --tsconfig ./fixture/tsconfig.json ./fixture/index.ts",
|
|
19
|
+
"dev:cors": "cross-env VITE_ENV=dev NO_SEED_DATA=true ORM=waterline FRONTEND_URL=http://localhost:8080 tsx watch --tsconfig ./fixture/tsconfig.json ./fixture/index.ts",
|
|
19
20
|
"build:assets": "vite build",
|
|
20
21
|
"compile:backend": "tsc -p src/tsconfig.json",
|
|
21
22
|
"compile:ui": "tsc -p tsconfig.ui.json",
|
|
@@ -72,6 +73,7 @@
|
|
|
72
73
|
"typeorm": "^0.3.20",
|
|
73
74
|
"uuid": "^11.0.5",
|
|
74
75
|
"waterline": "^0.15.2",
|
|
76
|
+
"sequelize": "^6.37.7",
|
|
75
77
|
"winston": "^3.17.0"
|
|
76
78
|
},
|
|
77
79
|
"devDependencies": {
|
package/system/Router.js
CHANGED
|
@@ -67,7 +67,9 @@ export default class Router {
|
|
|
67
67
|
* Edit form
|
|
68
68
|
* */
|
|
69
69
|
adminizer.app.all(`${adminizer.config.routePrefix}/form/:slug`, adminizer.policyManager.bindPolicies(policies, _form));
|
|
70
|
-
|
|
70
|
+
/**
|
|
71
|
+
* Create a base entity route
|
|
72
|
+
*/
|
|
71
73
|
let baseRoute = `${adminizer.config.routePrefix}/:entityType(form|model)/:entityName`;
|
|
72
74
|
/**
|
|
73
75
|
* Catalog
|
|
@@ -91,13 +93,13 @@ export default class Router {
|
|
|
91
93
|
if (adminizer.config.notifications.enabled) {
|
|
92
94
|
adminizer.app.get(`${adminizer.config.routePrefix}/notifications`, adminizer.policyManager.bindPolicies(policies, NotificationController.viewAll));
|
|
93
95
|
adminizer.app.post(`${adminizer.config.routePrefix}/notifications`, adminizer.policyManager.bindPolicies(policies, NotificationController.viewAll));
|
|
94
|
-
adminizer.app.get(`${adminizer.config.routePrefix}/api/
|
|
95
|
-
adminizer.app.get(`${adminizer.config.routePrefix}/api/
|
|
96
|
-
adminizer.app.get(`${adminizer.config.routePrefix}/api
|
|
97
|
-
adminizer.app.get(`${adminizer.config.routePrefix}/api
|
|
98
|
-
adminizer.app.put(`${adminizer.config.routePrefix}/api
|
|
99
|
-
adminizer.app.put(`${adminizer.config.routePrefix}/api/
|
|
100
|
-
adminizer.app.post(`${adminizer.config.routePrefix}/api/
|
|
96
|
+
adminizer.app.get(`${adminizer.config.routePrefix}/notifications/api/stream`, adminizer.policyManager.bindPolicies(policies, NotificationController.getNotificationsStream));
|
|
97
|
+
adminizer.app.get(`${adminizer.config.routePrefix}/notifications/api/get-classes`, adminizer.policyManager.bindPolicies(policies, NotificationController.getNotificationClasses));
|
|
98
|
+
adminizer.app.get(`${adminizer.config.routePrefix}/notifications/api/:notificationClass`, adminizer.policyManager.bindPolicies(policies, NotificationController.getNotificationsByClass));
|
|
99
|
+
adminizer.app.get(`${adminizer.config.routePrefix}/notifications/api`, adminizer.policyManager.bindPolicies(policies, NotificationController.getUserNotifications));
|
|
100
|
+
adminizer.app.put(`${adminizer.config.routePrefix}/notifications/api/:notificationClass/:id/read`, adminizer.policyManager.bindPolicies(policies, NotificationController.markAsRead));
|
|
101
|
+
adminizer.app.put(`${adminizer.config.routePrefix}/notifications/api/read-all`, adminizer.policyManager.bindPolicies(policies, NotificationController.markAllAsRead));
|
|
102
|
+
adminizer.app.post(`${adminizer.config.routePrefix}/notifications/api/search`, adminizer.policyManager.bindPolicies(policies, NotificationController.search));
|
|
101
103
|
}
|
|
102
104
|
/**
|
|
103
105
|
* List of records
|
|
@@ -60,6 +60,13 @@ export default async function bindAccessRights(adminizer) {
|
|
|
60
60
|
id: `widgets`, name: "Widgets",
|
|
61
61
|
description: "Access to widgets", department: "Widgets"
|
|
62
62
|
});
|
|
63
|
+
// Allow access login
|
|
64
|
+
adminizer.accessRightsHelper.registerToken({
|
|
65
|
+
id: 'access-to-adminpanel',
|
|
66
|
+
name: "Allowed log in",
|
|
67
|
+
description: "Are users allowed to log in to the admin panel?",
|
|
68
|
+
department: "Admin panel"
|
|
69
|
+
});
|
|
63
70
|
// Default user group
|
|
64
71
|
if (adminizer.config.registration && adminizer.config.registration.enable) {
|
|
65
72
|
// TODO refactor CRUD functions for DataAccessor usage
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export function bindCors(adminizer) {
|
|
2
|
+
if (adminizer.config?.cors?.enabled) {
|
|
3
|
+
const corsConfig = adminizer.config.cors;
|
|
4
|
+
// Поддерживаем массив разрешенных origin
|
|
5
|
+
const allowedOrigins = Array.isArray(corsConfig.origin)
|
|
6
|
+
? corsConfig.origin
|
|
7
|
+
: [corsConfig.origin];
|
|
8
|
+
adminizer.app.all(`${adminizer.config.routePrefix}/${corsConfig.path}`, (req, res, next) => {
|
|
9
|
+
const requestOrigin = req.headers.origin;
|
|
10
|
+
// Проверяем разрешен ли origin
|
|
11
|
+
const isOriginAllowed = !requestOrigin || allowedOrigins.includes(requestOrigin);
|
|
12
|
+
if (requestOrigin && !isOriginAllowed) {
|
|
13
|
+
console.log(`❌ CORS: Blocked request from ${requestOrigin}`);
|
|
14
|
+
if (req.method === 'OPTIONS') {
|
|
15
|
+
// Для preflight - 200 без CORS headers
|
|
16
|
+
return res.status(200).end();
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
// Для основных запросов - ошибка
|
|
20
|
+
return res.status(403).json({
|
|
21
|
+
error: 'CORS policy: Origin not allowed'
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
// Запрос с разрешенного origin или без Origin
|
|
26
|
+
if (isOriginAllowed) {
|
|
27
|
+
// Для CORS запросов возвращаем тот же origin (или первый из списка)
|
|
28
|
+
const allowOrigin = requestOrigin || allowedOrigins[0];
|
|
29
|
+
res.header('Access-Control-Allow-Origin', allowOrigin);
|
|
30
|
+
res.header('Access-Control-Allow-Credentials', corsConfig.credentials !== false ? 'true' : 'false');
|
|
31
|
+
res.header('Access-Control-Allow-Methods', corsConfig.methods?.join(',') || 'GET,POST,PUT,DELETE,OPTIONS');
|
|
32
|
+
res.header('Access-Control-Allow-Headers', corsConfig.allowedHeaders?.join(',') || 'Content-Type,Authorization,X-Requested-With,X-CSRF-Token,x-xsrf-token');
|
|
33
|
+
}
|
|
34
|
+
if (req.method === 'OPTIONS') {
|
|
35
|
+
return res.status(200).end();
|
|
36
|
+
}
|
|
37
|
+
next();
|
|
38
|
+
});
|
|
39
|
+
console.log('✅ API CORS middleware enabled. Allowed origins:', allowedOrigins);
|
|
40
|
+
}
|
|
41
|
+
}
|
package/system/bindInertia.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { DefaultMediaManager } from "../lib/media-manager/DefaultMediaManager";
|
|
2
|
-
import { MediaManagerHandler } from "../lib/media-manager/MediaManagerHandler";
|
|
3
2
|
import serveStatic from "serve-static";
|
|
4
3
|
import path from "path";
|
|
5
4
|
export default function bindMediaManager(adminizer) {
|
|
@@ -8,7 +7,7 @@ export default function bindMediaManager(adminizer) {
|
|
|
8
7
|
adminizer.emitter.on("adminizer:loaded", async () => {
|
|
9
8
|
try {
|
|
10
9
|
let mediaManager = new DefaultMediaManager(adminizer, 'default', 'media-manager', adminizer.config.mediamanager.fileStoragePath);
|
|
11
|
-
|
|
10
|
+
adminizer.mediaManagerHandler.add(mediaManager);
|
|
12
11
|
}
|
|
13
12
|
catch (e) {
|
|
14
13
|
console.log(e);
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { Adminizer } from "../lib/Adminizer";
|
|
2
|
-
export
|
|
2
|
+
export declare function bindNavigation(adminizer: Adminizer): Promise<void>;
|
package/system/bindNavigation.js
CHANGED
|
@@ -1,40 +1,38 @@
|
|
|
1
1
|
import { Navigation } from "../lib/catalog/Navigation";
|
|
2
|
-
export
|
|
3
|
-
adminizer.
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
2
|
+
export async function bindNavigation(adminizer) {
|
|
3
|
+
if (adminizer.config.navigation) {
|
|
4
|
+
try {
|
|
5
|
+
adminizer.config.navigation.model = adminizer.config.navigation.model ? adminizer.config.navigation.model : 'NavigationAP';
|
|
6
|
+
let navigation = new Navigation(adminizer, adminizer.config.navigation);
|
|
7
|
+
adminizer.catalogHandler.add(navigation);
|
|
8
|
+
adminizer.config.models[adminizer.config.navigation.model.toLowerCase()] = {
|
|
9
|
+
add: false,
|
|
10
|
+
edit: {
|
|
11
|
+
controller: '../controllers/navigation/edit',
|
|
12
|
+
},
|
|
13
|
+
fields: {
|
|
14
|
+
createdAt: false,
|
|
15
|
+
updatedAt: false
|
|
16
|
+
},
|
|
17
|
+
navbar: {
|
|
18
|
+
visible: false
|
|
19
|
+
},
|
|
20
|
+
icon: 'storage',
|
|
21
|
+
identifierField: "",
|
|
22
|
+
list: {
|
|
14
23
|
fields: {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
},
|
|
18
|
-
navbar: {
|
|
19
|
-
visible: false
|
|
24
|
+
tree: false,
|
|
25
|
+
id: false,
|
|
20
26
|
},
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
remove: false,
|
|
31
|
-
title: adminizer.config.navigation.model,
|
|
32
|
-
tools: []
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
catch (e) {
|
|
36
|
-
console.log('bindNavigation Error: ', e);
|
|
37
|
-
}
|
|
27
|
+
},
|
|
28
|
+
model: adminizer.config.navigation.model.toLowerCase(),
|
|
29
|
+
remove: false,
|
|
30
|
+
title: adminizer.config.navigation.model,
|
|
31
|
+
tools: []
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
catch (e) {
|
|
35
|
+
console.log('bindNavigation Error: ', e);
|
|
38
36
|
}
|
|
39
|
-
}
|
|
37
|
+
}
|
|
40
38
|
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { Adminizer } from '../lib/Adminizer';
|
|
2
1
|
import { NotificationHandler } from '../lib/notifications/NotificationHandler';
|
|
3
2
|
import { GeneralNotificationService } from '../lib/notifications/GeneralNotificationService';
|
|
4
3
|
import { SystemNotificationService } from '../lib/notifications/SystemNotificationService';
|
|
@@ -6,9 +5,10 @@ export async function bindNotifications(adminizer) {
|
|
|
6
5
|
// Создаем хендлер
|
|
7
6
|
adminizer.notificationHandler = new NotificationHandler();
|
|
8
7
|
// Регистрируем сервисы
|
|
9
|
-
const generalService = new GeneralNotificationService(adminizer);
|
|
10
8
|
const systemService = new SystemNotificationService(adminizer);
|
|
11
|
-
adminizer.notificationHandler.registerService(generalService);
|
|
12
9
|
adminizer.notificationHandler.registerService(systemService);
|
|
13
|
-
|
|
10
|
+
if (adminizer.config.notifications.enableGeneral) {
|
|
11
|
+
const generalService = new GeneralNotificationService(adminizer);
|
|
12
|
+
adminizer.notificationHandler.registerService(generalService);
|
|
13
|
+
}
|
|
14
14
|
}
|
|
@@ -11,7 +11,10 @@ export default function bindReqFunctions(adminizer) {
|
|
|
11
11
|
/**
|
|
12
12
|
* Add i18n
|
|
13
13
|
* */
|
|
14
|
-
req.i18n = new I18n({
|
|
14
|
+
req.i18n = new I18n({
|
|
15
|
+
locales: adminizer.config.translation !== false ? adminizer.config.translation.locales : [],
|
|
16
|
+
directory: adminizer.config.translation !== false ? adminizer.config.translation.path ?? null : null
|
|
17
|
+
});
|
|
15
18
|
if (res.locals) {
|
|
16
19
|
req.i18n.registerMethods(res.locals, req);
|
|
17
20
|
}
|
package/system/defaults.js
CHANGED
|
@@ -140,6 +140,14 @@ let adminpanelConfig = {
|
|
|
140
140
|
},
|
|
141
141
|
notifications: {
|
|
142
142
|
enabled: false
|
|
143
|
+
},
|
|
144
|
+
cors: {
|
|
145
|
+
enabled: false,
|
|
146
|
+
origin: 'http://localhost:8080',
|
|
147
|
+
path: 'api/*'
|
|
148
|
+
},
|
|
149
|
+
mediamanager: {
|
|
150
|
+
fileStoragePath: '.tmp/public',
|
|
143
151
|
}
|
|
144
152
|
};
|
|
145
153
|
export function setDefaultConfig(config) {
|
package/translations/ru.json
CHANGED
|
@@ -1,122 +1,123 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
2
|
+
"Action completed": "Действие завершено",
|
|
3
|
+
"Actions": "Действия",
|
|
4
|
+
"All": "Все",
|
|
5
|
+
"Are you sure?": "Вы уверены?",
|
|
6
|
+
"Back": " Назад",
|
|
7
|
+
"Back to Login": "Назад ко входу",
|
|
8
|
+
"Additional login page": "Дополнительная страница входа",
|
|
9
|
+
"Clean": "Очистить",
|
|
10
|
+
"Confirm Password": "Подтвердите пароль",
|
|
11
|
+
"Confirm Password*": "Подтвердите пароль*",
|
|
12
|
+
"Create": "Создать",
|
|
13
|
+
"Create a new administrator": "Создание нового администратора",
|
|
14
|
+
"Create an Account": "Создать аккаунт",
|
|
15
|
+
"Custom": "Пользовательский виджет",
|
|
16
|
+
"Delete": "Удалить",
|
|
17
|
+
"E-mail": "E-mail",
|
|
18
|
+
"Edit": "Редактировать",
|
|
19
|
+
"Email": "Электронная почта",
|
|
20
|
+
"Fast links": "Быстрые ссылки",
|
|
21
|
+
"Full Name": "Полное имя",
|
|
22
|
+
"Full name": "Полное имя",
|
|
23
|
+
"Group description": "Описание группы",
|
|
24
|
+
"Group name": "Название группы",
|
|
25
|
+
"Group settings": "Настройки группы",
|
|
26
|
+
"Info": "Информация",
|
|
27
|
+
"Is Administrator": "Администратор",
|
|
28
|
+
"Is confirmed": "Подтверждено",
|
|
29
|
+
"Link": "Ссылка",
|
|
30
|
+
"Locale": "Локаль",
|
|
31
|
+
"Log in": "Вход",
|
|
32
|
+
"Login": "Вход",
|
|
33
|
+
"Members": "Участники",
|
|
34
|
+
"New record was created": "Новая запись создана",
|
|
35
|
+
"No": "Нет",
|
|
36
|
+
"No records found !": "Записей не найдено",
|
|
37
|
+
"No widgets found": "Виджеты не найдены",
|
|
38
|
+
"Not found": "Ничего не найдено",
|
|
39
|
+
"OR": "ИЛИ",
|
|
40
|
+
"Open in a new window": "Открывать в новом окне",
|
|
41
|
+
"Password": "Пароль",
|
|
42
|
+
"Passwords do not match!": "Пароли не совпадают!",
|
|
43
|
+
"Performing an action...": "Выполняется действие...",
|
|
44
|
+
"Please fill out the fields below": "Пожалуйста, заполните поля ниже",
|
|
45
|
+
"Pretend to be a user": "Притворится пользователем",
|
|
46
|
+
"Profile expires": "Профиль истекает",
|
|
47
|
+
"Quick actions": "Быстрые действия",
|
|
48
|
+
"Record was not removed": "Запись не удалена",
|
|
49
|
+
"Record was removed successfully !": "Запись удалена успешно!",
|
|
50
|
+
"Record was updated": "Запись обновлена",
|
|
51
|
+
"Register": "Регистрация",
|
|
52
|
+
"Repeat password": "Повторить пароль",
|
|
53
|
+
"Reset": "Сброс",
|
|
54
|
+
"Save": "Сохранить",
|
|
55
|
+
"Search": "Поиск",
|
|
56
|
+
"Select": "Выберите",
|
|
57
|
+
"Select Ids": "Выберите ID",
|
|
58
|
+
"Select Item type": "Выберите Элемент",
|
|
59
|
+
"Select Items": "Ничего не выбрано",
|
|
60
|
+
"Switcher": "Переключатель",
|
|
61
|
+
"Timezone": "Временная зона",
|
|
62
|
+
"Title": "Title",
|
|
63
|
+
"Toggle to change the grid. To save the grid, turn it off.": "Переключите для изменения сетки. Чтобы сохранить сетку, отключите.",
|
|
64
|
+
"User groups": "Группы пользователя",
|
|
65
|
+
"User settings": "Настроики пользователя",
|
|
66
|
+
"Values in \"password\" and \"repeatPassword\" fields should be the same": "Значения в полях \"password\" и \"repeatPassword\" должны быть одинаковыми.",
|
|
67
|
+
"View": "Просмотреть",
|
|
68
|
+
"Welcome": "Здравствуйте",
|
|
69
|
+
"Yes": "Да",
|
|
70
|
+
"You don't have any widgets selected yet. You can add them by clicking on the plus sign at the top right.": "У вас пока нет выбранных виджетов. Вы можете добавить их, нажав на значок плюса в правом верхнем углу.",
|
|
71
|
+
"create": "Создать",
|
|
72
|
+
"create new": "создать новую",
|
|
73
|
+
"Widget Switcher One": "Widget Switcher One",
|
|
74
|
+
"Site Switcher": "Site Switcher",
|
|
75
|
+
"Widget Switcher Two": "Widget Switcher Two",
|
|
76
|
+
"Switcher Two": "Switcher Two",
|
|
77
|
+
"Test": "Test",
|
|
78
|
+
"Add Test Model": "Add Test Model",
|
|
79
|
+
"example.com": "example.com",
|
|
80
|
+
"link to example.com": "link to example.com",
|
|
81
|
+
"Global Settings": "Global Settings",
|
|
82
|
+
"Info widget One": "Info widget One",
|
|
83
|
+
"Info One": "Info One",
|
|
84
|
+
"Info widget Two": "Info widget Two",
|
|
85
|
+
"Info Two": "Info Two",
|
|
86
|
+
"Info widget 3": "Info widget 3",
|
|
87
|
+
"Info 31111": "Info 31111",
|
|
88
|
+
"Info widget 4": "Info widget 4",
|
|
89
|
+
"Info 4": "Info 4",
|
|
90
|
+
"Action One": "Action One",
|
|
91
|
+
"Action Two": "Action Two",
|
|
92
|
+
"Widget Custom One": "Widget Custom One",
|
|
93
|
+
"Site Custom": "Site Custom",
|
|
94
|
+
"id": "id",
|
|
95
|
+
"Textarea": "Textarea",
|
|
96
|
+
"Disabled": "Disabled",
|
|
97
|
+
"Boolean": "Boolean",
|
|
98
|
+
"time": "time",
|
|
99
|
+
"Number": "Number",
|
|
100
|
+
"Editor": "Editor",
|
|
101
|
+
"Date and time": "Date and time",
|
|
102
|
+
"testRelationExample": "testRelationExample",
|
|
103
|
+
"owner": "owner",
|
|
104
|
+
"title": "title",
|
|
105
|
+
"slug": "slug",
|
|
106
|
+
"Images 1": "Images 1",
|
|
107
|
+
"Images": "Изображения",
|
|
108
|
+
"Videos": "Видео",
|
|
109
|
+
"Texts": "Текст",
|
|
110
|
+
"Applications": "Приложения",
|
|
111
|
+
"Table": "Таблица",
|
|
112
|
+
"Tile": "Плитка",
|
|
113
|
+
"Load more": "Загрузить еще",
|
|
114
|
+
"File": "Файл",
|
|
115
|
+
"Name": "Имя",
|
|
116
|
+
"Date": "Дата",
|
|
117
|
+
"Type": "Тип",
|
|
118
|
+
"Size (orig.)": "Размер (orig.)",
|
|
119
|
+
"W x H (orig.)": "W x H (orig.)",
|
|
120
|
+
"Sizes/Ver": "Sizes/Ver",
|
|
121
|
+
"Locales": "Locales",
|
|
122
|
+
"Leave this field empty if you don't want to change the password": "Оставьте это поле пустым, если не хотите менять пароль"
|
|
122
123
|
}
|
|
@@ -34,9 +34,12 @@ const HandsonTable = ({ config, data = [], onChange, disabled }) => {
|
|
|
34
34
|
}, []);
|
|
35
35
|
const hotTableRef = useRef(null);
|
|
36
36
|
useEffect(() => {
|
|
37
|
-
|
|
38
|
-
hotTableRef.current
|
|
39
|
-
|
|
37
|
+
const timer = setTimeout(() => {
|
|
38
|
+
if (hotTableRef.current?.hotInstance) {
|
|
39
|
+
hotTableRef.current.hotInstance.loadData(data);
|
|
40
|
+
}
|
|
41
|
+
}, 100);
|
|
42
|
+
return () => clearTimeout(timer);
|
|
40
43
|
}, [data]);
|
|
41
44
|
useEffect(() => {
|
|
42
45
|
if (appearance === 'dark') {
|
package/ui/lib/utils.d.ts
CHANGED