adminizer 4.3.0-build.99 → 4.3.1
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 +8 -8
- package/controllers/addGroup.js +3 -3
- package/controllers/addUser.js +3 -3
- package/controllers/catalog/Catalog.js +22 -21
- 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/ckeditorUpload.js +1 -1
- package/controllers/edit.js +21 -12
- package/controllers/editGroup.js +3 -3
- package/controllers/editUser.js +3 -3
- package/controllers/form.js +12 -10
- package/controllers/initUser.js +2 -2
- package/controllers/list.js +5 -5
- package/controllers/login.js +7 -4
- package/controllers/media-manager/ThumbController.js +2 -2
- package/controllers/media-manager/mediaManagerAdapter.js +2 -2
- package/controllers/media-manager/mediaManagerApi.js +2 -3
- package/controllers/navigation/edit.js +2 -2
- package/controllers/notifications/NotificationController.d.ts +1 -1
- package/controllers/notifications/NotificationController.js +6 -5
- package/controllers/register.js +1 -1
- package/controllers/remove.js +4 -4
- package/controllers/view.js +13 -11
- package/helpers/accessRightsHelper.js +1 -1
- package/helpers/controllerHelper.js +1 -1
- package/helpers/fieldsHelper.js +3 -3
- package/helpers/formHelper.js +1 -1
- package/helpers/inertiaAddHelper.js +3 -4
- package/helpers/inertiaFromHelper.js +2 -3
- package/helpers/inertiaListHelper.js +1 -1
- package/helpers/menuHelper.js +1 -1
- package/helpers/translationHelper.js +2 -2
- package/index.d.ts +5 -0
- package/index.js +31 -26
- package/interfaces/adminpanelConfig.d.ts +12 -0
- package/lib/Adminizer.d.ts +4 -3
- package/lib/Adminizer.js +41 -47
- package/lib/DataAccessor.js +3 -3
- package/lib/I18n.js +1 -1
- package/lib/PolicyManager.js +1 -1
- 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 +71 -42
- package/lib/controls/codeEditor/MonacoEditor.js +1 -1
- package/lib/controls/geojsoneditor/GeoEditor.js +1 -1
- package/lib/controls/jsoneditor/JsonEditor.js +1 -1
- package/lib/controls/markdown/ToastUiEditor.js +1 -1
- package/lib/controls/table/Handsontable.js +1 -1
- package/lib/controls/wysiwyg/CKeditor.js +1 -1
- 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 +21 -16
- package/lib/media-manager/Items.js +7 -6
- package/lib/media-manager/MediaManagerHandler.d.ts +3 -3
- package/lib/media-manager/MediaManagerHandler.js +4 -4
- 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/AbstractModel.js +1 -1
- package/lib/model/ModelHandler.js +1 -1
- package/lib/model/adapter/sequelize.js +1 -1
- package/lib/model/adapter/waterline.js +7 -1
- package/lib/notifications/AbstractNotificationService.js +1 -1
- package/lib/notifications/GeneralNotificationService.js +2 -2
- package/lib/notifications/NotificationHandler.js +1 -1
- package/lib/notifications/SystemNotificationService.js +2 -2
- package/lib/requestProcessor.js +2 -2
- package/lib/widgets/abstractAction.js +1 -1
- package/lib/widgets/abstractInfo.js +1 -1
- package/lib/widgets/abstractLink.js +1 -1
- package/lib/widgets/abstractSwitch.js +1 -1
- package/migrations/index.js +1 -1
- package/migrations/umzugExports.js +1 -1
- package/package.json +4 -2
- package/system/Router.js +31 -29
- package/system/bindAccessRights.js +7 -0
- package/system/bindAuthorization.js +4 -4
- package/system/bindControls.js +6 -6
- package/system/bindCors.d.ts +2 -0
- package/system/bindCors.js +41 -0
- package/system/bindDashboardWidgets.js +1 -1
- package/system/bindForms.js +1 -1
- package/system/bindInertia.js +4 -4
- package/system/bindMediaManager.js +2 -3
- package/system/bindModels.js +1 -1
- package/system/bindNavigation.d.ts +1 -1
- package/system/bindNavigation.js +34 -36
- package/system/bindNotifications.js +7 -7
- package/system/bindReqFunctions.js +7 -4
- package/system/bindTranslations.js +2 -2
- package/system/defaults.js +10 -2
- 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,6 +1,6 @@
|
|
|
1
|
-
import { AbstractMediaManager, } from "./AbstractMediaManager";
|
|
2
|
-
import { populateVariants } from "./helpers/MediaManagerHelper";
|
|
3
|
-
import { ApplicationItem, ImageItem, TextItem, VideoItem } from "./Items";
|
|
1
|
+
import { AbstractMediaManager, } from "./AbstractMediaManager.js";
|
|
2
|
+
import { populateVariants } from "./helpers/MediaManagerHelper.js";
|
|
3
|
+
import { ApplicationItem, ImageItem, TextItem, VideoItem } from "./Items.js";
|
|
4
4
|
export class DefaultMediaManager extends AbstractMediaManager {
|
|
5
5
|
itemTypes = [];
|
|
6
6
|
model = "mediamanagerap";
|
|
@@ -57,7 +57,7 @@ export class DefaultMediaManager extends AbstractMediaManager {
|
|
|
57
57
|
}
|
|
58
58
|
async setRelations(data, model, modelId, widgetName) {
|
|
59
59
|
let modelAssociations = await this.adminizer.modelHandler.model.get(this.modelAssoc)["_find"]({
|
|
60
|
-
where: { modelId: modelId, model: model, widgetName: widgetName },
|
|
60
|
+
where: { modelId: +modelId, model: model.toLowerCase(), widgetName: widgetName },
|
|
61
61
|
});
|
|
62
62
|
for (const modelAssociation of modelAssociations) {
|
|
63
63
|
const q = {};
|
|
@@ -69,26 +69,31 @@ export class DefaultMediaManager extends AbstractMediaManager {
|
|
|
69
69
|
for (const [key, widgetItem] of data.entries()) {
|
|
70
70
|
await this.adminizer.modelHandler.model.get(this.modelAssoc)["_create"]({
|
|
71
71
|
mediaManagerId: this.id,
|
|
72
|
-
model: model,
|
|
73
|
-
modelId: modelId,
|
|
72
|
+
model: model.toLowerCase(),
|
|
73
|
+
modelId: +modelId,
|
|
74
74
|
[fieldName]: widgetItem.id,
|
|
75
75
|
widgetName: widgetName,
|
|
76
76
|
sortOrder: key + 1,
|
|
77
77
|
});
|
|
78
78
|
}
|
|
79
79
|
}
|
|
80
|
-
async
|
|
80
|
+
async getRelations(model, widgetName, modelId) {
|
|
81
81
|
let widgetItems = [];
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
82
|
+
const fieldName = this.adminizer.ormAdapters[0].ormType === 'sequelize' ? 'fileRef' : 'file';
|
|
83
|
+
let files = await this.adminizer.modelHandler.model.get(this.modelAssoc)['_find']({
|
|
84
|
+
where: {
|
|
85
|
+
model: model.toLowerCase(),
|
|
86
|
+
widgetName: widgetName,
|
|
87
|
+
modelId: +modelId
|
|
88
|
+
},
|
|
89
|
+
sort: "sortOrder ASC"
|
|
90
|
+
}, { populate: [[fieldName, {}]] });
|
|
91
|
+
for (const file of files) {
|
|
87
92
|
widgetItems.push({
|
|
88
|
-
id: file.id,
|
|
89
|
-
mimeType: file.mimeType,
|
|
90
|
-
url: file.url,
|
|
91
|
-
variants:
|
|
93
|
+
id: file[fieldName].id,
|
|
94
|
+
mimeType: file[fieldName].mimeType,
|
|
95
|
+
url: file[fieldName].url,
|
|
96
|
+
variants: []
|
|
92
97
|
});
|
|
93
98
|
}
|
|
94
99
|
return widgetItems;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { File } from "./AbstractMediaManager";
|
|
2
|
-
import { populateVariants, randomFileName } from "./helpers/MediaManagerHelper";
|
|
1
|
+
import { File } from "./AbstractMediaManager.js";
|
|
2
|
+
import { populateVariants, randomFileName } from "./helpers/MediaManagerHelper.js";
|
|
3
3
|
import sizeOf from "image-size";
|
|
4
4
|
import sharp from "sharp";
|
|
5
5
|
import * as fs from 'fs';
|
|
6
6
|
import * as path from 'path';
|
|
7
|
+
import * as process from "node:process";
|
|
7
8
|
export class ImageItem extends File {
|
|
8
9
|
type = "image";
|
|
9
10
|
model = "mediamanagerap";
|
|
@@ -55,7 +56,7 @@ export class ImageItem extends File {
|
|
|
55
56
|
parent: null,
|
|
56
57
|
mimeType: file.mimetype,
|
|
57
58
|
size: file.size,
|
|
58
|
-
path:
|
|
59
|
+
path: `${this.fileStoragePath}/${this.urlPathPrefix}/${filename}`,
|
|
59
60
|
group: group,
|
|
60
61
|
tag: "origin",
|
|
61
62
|
filename: origFileName,
|
|
@@ -64,7 +65,7 @@ export class ImageItem extends File {
|
|
|
64
65
|
await this.createMeta(parent.id);
|
|
65
66
|
await this.addFileMeta(file.path, parent.id);
|
|
66
67
|
// create file variants
|
|
67
|
-
if (Object.keys(this.imageSizes).length) {
|
|
68
|
+
if (Object.keys(this.imageSizes).length && file.mimetype !== 'image/svg+xml') {
|
|
68
69
|
await this.createVariants(file, parent, filename, group);
|
|
69
70
|
}
|
|
70
71
|
// TODO refactor CRUD functions for DataAccessor usage
|
|
@@ -148,7 +149,7 @@ export class ImageItem extends File {
|
|
|
148
149
|
}
|
|
149
150
|
async resizeImage(input, output, width, height) {
|
|
150
151
|
// Get the directory from the output path
|
|
151
|
-
const outputDir = path.dirname(output)
|
|
152
|
+
const outputDir = `${process.cwd()}/${path.dirname(output)}`;
|
|
152
153
|
// Check if the directory exists, and create it if it doesn't
|
|
153
154
|
if (!fs.existsSync(outputDir)) {
|
|
154
155
|
fs.mkdirSync(outputDir, { recursive: true });
|
|
@@ -209,7 +210,7 @@ export class TextItem extends ImageItem {
|
|
|
209
210
|
parent: null,
|
|
210
211
|
mimeType: file.mimetype,
|
|
211
212
|
size: file.size,
|
|
212
|
-
path:
|
|
213
|
+
path: `${this.fileStoragePath}/${filename}`,
|
|
213
214
|
group: group,
|
|
214
215
|
filename: origFileName,
|
|
215
216
|
tag: "origin",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AbstractMediaManager } from "./AbstractMediaManager";
|
|
2
2
|
export declare class MediaManagerHandler {
|
|
3
|
-
private
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
private managers;
|
|
4
|
+
add(manager: AbstractMediaManager): void;
|
|
5
|
+
get(id: string): AbstractMediaManager;
|
|
6
6
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { Adminizer } from "../Adminizer";
|
|
1
|
+
import { Adminizer } from "../Adminizer.js";
|
|
2
2
|
export class MediaManagerHandler {
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
managers = [];
|
|
4
|
+
add(manager) {
|
|
5
5
|
this.managers.push(manager);
|
|
6
6
|
}
|
|
7
|
-
|
|
7
|
+
get(id) {
|
|
8
8
|
let instance = this.managers.find(e => e.id === id);
|
|
9
9
|
/**
|
|
10
10
|
* ✨ We magically get one
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Adminizer } from "../Adminizer";
|
|
1
2
|
export declare class MediaManagerThumb {
|
|
2
|
-
static getThumb(id: string, managerId: string): Promise<Buffer<ArrayBufferLike>>;
|
|
3
|
+
static getThumb(id: string, managerId: string, adminizer: Adminizer): Promise<Buffer<ArrayBufferLike>>;
|
|
3
4
|
}
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import sharp from "sharp";
|
|
2
2
|
import { promises as fs } from 'fs';
|
|
3
|
-
import { MediaManagerHandler } from "./MediaManagerHandler";
|
|
4
3
|
export class MediaManagerThumb {
|
|
5
|
-
static async getThumb(id, managerId) {
|
|
4
|
+
static async getThumb(id, managerId, adminizer) {
|
|
6
5
|
const fileExists = async (path) => !!(await fs.stat(path).catch(e => false));
|
|
7
|
-
const manager =
|
|
6
|
+
const manager = adminizer.mediaManagerHandler.get(managerId);
|
|
8
7
|
const path = await manager.getOrigin(id);
|
|
9
8
|
const baseThumbPath = `${process.cwd()}/.tmp/thumbs`;
|
|
10
9
|
await fs.mkdir(baseThumbPath, { recursive: true });
|
|
@@ -13,7 +12,7 @@ export class MediaManagerThumb {
|
|
|
13
12
|
return await fs.readFile(thumb);
|
|
14
13
|
}
|
|
15
14
|
else {
|
|
16
|
-
await sharp(path)
|
|
15
|
+
await sharp(`${process.cwd()}/${path}`)
|
|
17
16
|
.resize({ width: 150, height: 150 })
|
|
18
17
|
.toFile(thumb);
|
|
19
18
|
return await fs.readFile(thumb);
|
|
@@ -11,19 +11,24 @@ type PostParams = Record<string, string | number | boolean | object | string[] |
|
|
|
11
11
|
export declare function randomFileName(filenameOrig: string, type: string, prefix: boolean): string;
|
|
12
12
|
/**
|
|
13
13
|
* Save media manager relations to database.
|
|
14
|
+
* @param adminizer
|
|
14
15
|
* @param fields
|
|
15
16
|
* @param reqData
|
|
16
17
|
* @param model
|
|
17
18
|
* @param recordId
|
|
18
19
|
*/
|
|
19
|
-
export declare function saveRelationsMediaManager(fields: Fields, reqData: PostParams, model: string, recordId:
|
|
20
|
+
export declare function saveRelationsMediaManager(adminizer: Adminizer, fields: Fields, reqData: PostParams, model: string, recordId: number): Promise<void>;
|
|
20
21
|
/**
|
|
21
22
|
* Get realtions
|
|
23
|
+
* @param adminizer
|
|
22
24
|
* @param data
|
|
25
|
+
* @param model
|
|
26
|
+
* @param widgetName
|
|
23
27
|
*/
|
|
24
|
-
export declare function getRelationsMediaManager(data: MediaManagerWidgetJSON): Promise<import("../AbstractMediaManager").MediaManagerWidgetClientItem[]>;
|
|
28
|
+
export declare function getRelationsMediaManager(adminizer: Adminizer, data: MediaManagerWidgetJSON): Promise<import("../AbstractMediaManager").MediaManagerWidgetClientItem[]>;
|
|
25
29
|
/**
|
|
26
30
|
* Delate Ralations
|
|
31
|
+
* @param adminizer
|
|
27
32
|
* @param model
|
|
28
33
|
* @param record
|
|
29
34
|
*/
|
|
@@ -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
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { DataTypes, Op } from "sequelize";
|
|
2
|
-
import { AbstractAdapter, AbstractModel } from "../AbstractModel";
|
|
2
|
+
import { AbstractAdapter, AbstractModel } from "../AbstractModel.js";
|
|
3
3
|
import path from "path";
|
|
4
4
|
import fs from "fs";
|
|
5
5
|
import { pathToFileURL } from "url";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AbstractAdapter, AbstractModel } from "../AbstractModel";
|
|
1
|
+
import { AbstractAdapter, AbstractModel } from "../AbstractModel.js";
|
|
2
2
|
import { v4 as uuid } from "uuid";
|
|
3
3
|
import Waterline from "waterline";
|
|
4
4
|
import path from "node:path";
|
|
@@ -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]) => {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { EventEmitter } from 'events';
|
|
2
|
-
import { Adminizer } from '../Adminizer';
|
|
2
|
+
import { Adminizer } from '../Adminizer.js';
|
|
3
3
|
/**
|
|
4
4
|
* ░█████╗░██████╗░░██████╗████████╗██████╗░░█████╗░░█████╗░████████╗
|
|
5
5
|
* ██╔══██╗██╔══██╗██╔════╝╚══██╔══╝██╔══██╗██╔══██╗██╔══██╗╚══██╔══╝
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { AbstractNotificationService } from './AbstractNotificationService';
|
|
2
|
-
import { Adminizer } from '../Adminizer';
|
|
1
|
+
import { AbstractNotificationService } from './AbstractNotificationService.js';
|
|
2
|
+
import { Adminizer } from '../Adminizer.js';
|
|
3
3
|
export class GeneralNotificationService extends AbstractNotificationService {
|
|
4
4
|
notificationClass = 'general';
|
|
5
5
|
icon = 'info';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { AbstractNotificationService } from './AbstractNotificationService';
|
|
2
|
-
import { Adminizer } from '../Adminizer';
|
|
1
|
+
import { AbstractNotificationService } from './AbstractNotificationService.js';
|
|
2
|
+
import { Adminizer } from '../Adminizer.js';
|
|
3
3
|
export class SystemNotificationService extends AbstractNotificationService {
|
|
4
4
|
notificationClass = 'system';
|
|
5
5
|
icon = 'settings';
|
package/lib/requestProcessor.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { isObject } from "../helpers/JsUtils";
|
|
2
|
-
import { Adminizer } from "./Adminizer";
|
|
1
|
+
import { isObject } from "../helpers/JsUtils.js";
|
|
2
|
+
import { Adminizer } from "./Adminizer.js";
|
|
3
3
|
/**
|
|
4
4
|
* Default helper that will contain all methods
|
|
5
5
|
* that should help with processing request details and bind
|
package/migrations/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "adminizer",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "4.3.
|
|
4
|
+
"version": "4.3.1",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"exports": {
|
|
7
7
|
".": "./index.js",
|
|
@@ -16,8 +16,9 @@
|
|
|
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
|
-
"compile:backend": "tsc -p src/tsconfig.json",
|
|
21
|
+
"compile:backend": "tsc -p src/tsconfig.json && node ./scripts/appendJsExtension.js",
|
|
21
22
|
"compile:ui": "tsc -p tsconfig.ui.json",
|
|
22
23
|
"watch:backend": "tsc -w -p src/tsconfig.json",
|
|
23
24
|
"copy:backend": "node copy-backend.js",
|
|
@@ -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
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
import _dashboard from "../controllers/dashboard";
|
|
2
|
-
import _welcome from "../controllers/welcome";
|
|
3
|
-
import _list from "../controllers/list";
|
|
4
|
-
import _edit from "../controllers/edit";
|
|
5
|
-
import _add from "../controllers/add";
|
|
6
|
-
import _view from "../controllers/view";
|
|
7
|
-
import _remove from "../controllers/remove";
|
|
8
|
-
import { ckEditorUpload } from "../controllers/ckeditorUpload";
|
|
9
|
-
import _form from "../controllers/form";
|
|
10
|
-
import { widgetSwitchController } from "../controllers/widgets/switch";
|
|
11
|
-
import _getAllWidgets from "../controllers/getAllWidgets";
|
|
12
|
-
import _widgetsDB from "../controllers/widgetsDB";
|
|
13
|
-
import { widgetInfoController } from '../controllers/widgets/Info';
|
|
14
|
-
import { widgetActionController } from '../controllers/widgets/Action';
|
|
15
|
-
import { widgetCustomController } from "../controllers/widgets/Custom";
|
|
16
|
-
import { catalogController } from "../controllers/catalog/Catalog";
|
|
17
|
-
import { mediaManagerController } from "../controllers/media-manager/mediaManagerApi";
|
|
18
|
-
import { thumbController } from "../controllers/media-manager/ThumbController";
|
|
19
|
-
import { Adminizer } from "../lib/Adminizer";
|
|
20
|
-
import timezones from "../controllers/timezones";
|
|
21
|
-
import { NotificationController } from "../controllers/notifications/NotificationController";
|
|
1
|
+
import _dashboard from "../controllers/dashboard.js";
|
|
2
|
+
import _welcome from "../controllers/welcome.js";
|
|
3
|
+
import _list from "../controllers/list.js";
|
|
4
|
+
import _edit from "../controllers/edit.js";
|
|
5
|
+
import _add from "../controllers/add.js";
|
|
6
|
+
import _view from "../controllers/view.js";
|
|
7
|
+
import _remove from "../controllers/remove.js";
|
|
8
|
+
import { ckEditorUpload } from "../controllers/ckeditorUpload.js";
|
|
9
|
+
import _form from "../controllers/form.js";
|
|
10
|
+
import { widgetSwitchController } from "../controllers/widgets/switch.js";
|
|
11
|
+
import _getAllWidgets from "../controllers/getAllWidgets.js";
|
|
12
|
+
import _widgetsDB from "../controllers/widgetsDB.js";
|
|
13
|
+
import { widgetInfoController } from '../controllers/widgets/Info.js';
|
|
14
|
+
import { widgetActionController } from '../controllers/widgets/Action.js';
|
|
15
|
+
import { widgetCustomController } from "../controllers/widgets/Custom.js";
|
|
16
|
+
import { catalogController } from "../controllers/catalog/Catalog.js";
|
|
17
|
+
import { mediaManagerController } from "../controllers/media-manager/mediaManagerApi.js";
|
|
18
|
+
import { thumbController } from "../controllers/media-manager/ThumbController.js";
|
|
19
|
+
import { Adminizer } from "../lib/Adminizer.js";
|
|
20
|
+
import timezones from "../controllers/timezones.js";
|
|
21
|
+
import { NotificationController } from "../controllers/notifications/NotificationController.js";
|
|
22
22
|
export default class Router {
|
|
23
23
|
static onlyOnce = false;
|
|
24
24
|
/**
|
|
@@ -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
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import _login from "../controllers/login";
|
|
2
|
-
import _register from "../controllers/register";
|
|
3
|
-
import _initUser from "../controllers/initUser";
|
|
4
|
-
import { Adminizer } from "../lib/Adminizer";
|
|
1
|
+
import _login from "../controllers/login.js";
|
|
2
|
+
import _register from "../controllers/register.js";
|
|
3
|
+
import _initUser from "../controllers/initUser.js";
|
|
4
|
+
import { Adminizer } from "../lib/Adminizer.js";
|
|
5
5
|
import { generate } from "password-hash";
|
|
6
6
|
export default async function bindAuthorization(adminizer) {
|
|
7
7
|
let admins;
|
package/system/bindControls.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { CKeditor } from "../lib/controls/wysiwyg/CKeditor";
|
|
2
|
-
import { ToastUiEditor } from "../lib/controls/markdown/ToastUiEditor";
|
|
3
|
-
import { Handsontable } from "../lib/controls/table/Handsontable";
|
|
4
|
-
import { JsonEditor } from "../lib/controls/jsoneditor/JsonEditor";
|
|
5
|
-
import { MonacoEditor } from "../lib/controls/codeEditor/MonacoEditor";
|
|
6
|
-
import { GeoEditor } from "../lib/controls/geojsoneditor/GeoEditor";
|
|
1
|
+
import { CKeditor } from "../lib/controls/wysiwyg/CKeditor.js";
|
|
2
|
+
import { ToastUiEditor } from "../lib/controls/markdown/ToastUiEditor.js";
|
|
3
|
+
import { Handsontable } from "../lib/controls/table/Handsontable.js";
|
|
4
|
+
import { JsonEditor } from "../lib/controls/jsoneditor/JsonEditor.js";
|
|
5
|
+
import { MonacoEditor } from "../lib/controls/codeEditor/MonacoEditor.js";
|
|
6
|
+
import { GeoEditor } from "../lib/controls/geojsoneditor/GeoEditor.js";
|
|
7
7
|
export function bindControls(adminizer) {
|
|
8
8
|
// bind wysiwyg
|
|
9
9
|
adminizer.controlsHandler.add(new CKeditor(adminizer));
|
|
@@ -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
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as fs from 'fs';
|
|
2
2
|
import * as path from 'path';
|
|
3
|
-
import { Adminizer } from '../lib/Adminizer';
|
|
3
|
+
import { Adminizer } from '../lib/Adminizer.js';
|
|
4
4
|
export default async function bindDashboardWidgets(adminizer) {
|
|
5
5
|
if (adminizer.config.dashboard && typeof adminizer.config.dashboard !== "boolean" && adminizer.config.dashboard.autoloadWidgetsPath) {
|
|
6
6
|
try {
|
package/system/bindForms.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as fs from "fs";
|
|
2
|
-
import { FormHelper } from "../helpers/formHelper";
|
|
2
|
+
import { FormHelper } from "../helpers/formHelper.js";
|
|
3
3
|
export default async function bindForms(adminizer) {
|
|
4
4
|
if (fs.existsSync(adminizer.config.forms.path)) {
|
|
5
5
|
let formsDir = fs.readdirSync(adminizer.config.forms.path);
|
package/system/bindInertia.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import flash from "../lib/inertia/flash";
|
|
2
|
-
import inertia from "../lib/inertia/inertiaAdapter";
|
|
1
|
+
import flash from "../lib/inertia/flash.js";
|
|
2
|
+
import inertia from "../lib/inertia/inertiaAdapter.js";
|
|
3
3
|
import fs from "fs";
|
|
4
4
|
import path from "node:path";
|
|
5
|
-
import { InertiaMenuHelper } from "../helpers/inertiaMenuHelper";
|
|
5
|
+
import { InertiaMenuHelper } from "../helpers/inertiaMenuHelper.js";
|
|
6
6
|
export function bindInertia(adminizer) {
|
|
7
7
|
const viteRender = () => {
|
|
8
8
|
if (process.env.VITE_ENV === 'dev') {
|
|
@@ -102,7 +102,7 @@ export function bindInertia(adminizer) {
|
|
|
102
102
|
enabled: true,
|
|
103
103
|
cookieName: 'XSRF-TOKEN',
|
|
104
104
|
headerName: 'x-xsrf-token'
|
|
105
|
-
}
|
|
105
|
+
}
|
|
106
106
|
}));
|
|
107
107
|
adminizer.app.use((req, _, next) => {
|
|
108
108
|
checkAuth(req, adminizer);
|