adminizer 4.1.0-build.16 → 4.1.0-build.17
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/lib/v4/DataAccessor.js
CHANGED
|
@@ -376,10 +376,11 @@ export class DataAccessor {
|
|
|
376
376
|
const relation = modelAttributes[accessField];
|
|
377
377
|
if (relation && ['userap', 'groupap'].includes(relation.model.toLowerCase())) {
|
|
378
378
|
if (relation.model.toLowerCase() === 'userap') {
|
|
379
|
-
|
|
379
|
+
if (!this.user.isAdministrator) {
|
|
380
|
+
updatedRecord[accessField] = this.user.id;
|
|
381
|
+
}
|
|
380
382
|
}
|
|
381
383
|
else if (relation.model.toLowerCase() === 'groupap') {
|
|
382
|
-
// Works only for users with only one group, later it can be resolved with group weight
|
|
383
384
|
const userGroups = this.user.groups || [];
|
|
384
385
|
if (userGroups.length === 1) {
|
|
385
386
|
updatedRecord[accessField] = userGroups[0].id;
|
|
@@ -431,6 +432,7 @@ export class DataAccessor {
|
|
|
431
432
|
updatedRecord[field] = intermediateRecord.id;
|
|
432
433
|
}
|
|
433
434
|
}
|
|
435
|
+
console.log(updatedRecord, "<<<<<<<<<<<<<<<<<<<,");
|
|
434
436
|
return updatedRecord;
|
|
435
437
|
}
|
|
436
438
|
}
|
|
@@ -3,6 +3,64 @@ import { AbstractAdapter, AbstractModel } from "../AbstractModel";
|
|
|
3
3
|
import path from "path";
|
|
4
4
|
import fs from "fs";
|
|
5
5
|
import { pathToFileURL } from "url";
|
|
6
|
+
function generateAssociationsFromSchema(models, schemas) {
|
|
7
|
+
for (const modelName in schemas) {
|
|
8
|
+
const schema = schemas[modelName];
|
|
9
|
+
const model = models[modelName];
|
|
10
|
+
if (!model)
|
|
11
|
+
continue;
|
|
12
|
+
for (const fieldName in schema) {
|
|
13
|
+
const field = schema[fieldName];
|
|
14
|
+
if (field.collection && field.via) {
|
|
15
|
+
const targetModel = models[field.collection];
|
|
16
|
+
const targetSchema = schemas[field.collection];
|
|
17
|
+
const inverseField = targetSchema?.[field.via];
|
|
18
|
+
const throughTableName = [modelName, field.collection].sort().join("");
|
|
19
|
+
// 💡 M:N связь
|
|
20
|
+
if (inverseField && inverseField.collection === modelName) {
|
|
21
|
+
model.belongsToMany(targetModel, {
|
|
22
|
+
through: throughTableName,
|
|
23
|
+
as: fieldName,
|
|
24
|
+
foreignKey: `${modelName}Id`,
|
|
25
|
+
otherKey: `${field.collection}Id`
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
// 💡 O:M связь (один ко многим)
|
|
29
|
+
else {
|
|
30
|
+
model.hasMany(targetModel, {
|
|
31
|
+
as: fieldName,
|
|
32
|
+
foreignKey: `${modelName}Id`,
|
|
33
|
+
});
|
|
34
|
+
targetModel.belongsTo(model, {
|
|
35
|
+
as: field.via,
|
|
36
|
+
foreignKey: `${modelName}Id`,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
// 💡 O:1 или 1:1 (belongsTo)
|
|
41
|
+
if (field.model) {
|
|
42
|
+
const targetModel = models[field.model];
|
|
43
|
+
if (!targetModel)
|
|
44
|
+
continue;
|
|
45
|
+
// Avoid naming collision by making FK explicit: `${fieldName}Id`
|
|
46
|
+
const foreignKey = `${fieldName}Id`;
|
|
47
|
+
const alias = fieldName;
|
|
48
|
+
// Если поле уже существует — избегаем конфликта
|
|
49
|
+
if (model.rawAttributes[alias]) {
|
|
50
|
+
model.belongsTo(targetModel, {
|
|
51
|
+
as: alias,
|
|
52
|
+
foreignKey,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
model.belongsTo(targetModel, {
|
|
57
|
+
foreignKey: alias, // если нет конфликта, можно использовать alias как FK
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
6
64
|
function resolveType(type) {
|
|
7
65
|
const sqlType = typeof type.toString === "function"
|
|
8
66
|
? type.toString().toLowerCase()
|
|
@@ -401,19 +459,22 @@ export class SequelizeAdapter extends AbstractAdapter {
|
|
|
401
459
|
static async registerSystemModels(sequelize) {
|
|
402
460
|
const modelsDir = path.resolve(import.meta.dirname, "../../../../models");
|
|
403
461
|
let files = fs.readdirSync(modelsDir).filter(f => f.endsWith(".js"));
|
|
404
|
-
// Try with ts files (exclude .d.ts)
|
|
405
462
|
if (!files.length) {
|
|
406
463
|
files = fs.readdirSync(modelsDir).filter(f => f.endsWith(".ts") && !f.endsWith(".d.ts"));
|
|
407
464
|
}
|
|
408
465
|
if (!files.length) {
|
|
409
466
|
throw `Model files not found in dir ${modelsDir}`;
|
|
410
467
|
}
|
|
468
|
+
const schemas = {};
|
|
411
469
|
for (const file of files) {
|
|
412
470
|
const modelName = path.basename(file, path.extname(file));
|
|
413
471
|
const filePath = path.resolve(modelsDir, file);
|
|
414
|
-
const
|
|
472
|
+
const mod = await import(pathToFileURL(filePath).href);
|
|
473
|
+
const definition = mod.default;
|
|
474
|
+
schemas[modelName] = definition;
|
|
415
475
|
generateSequelizeModel(sequelize, modelName, definition);
|
|
416
476
|
}
|
|
477
|
+
generateAssociationsFromSchema(sequelize.models, schemas);
|
|
417
478
|
await sequelize.sync();
|
|
418
479
|
}
|
|
419
480
|
}
|
package/models/MediaManagerAP.js
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "adminizer",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "4.1.0-build.
|
|
4
|
+
"version": "4.1.0-build.17",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"test": "vitest --reporter verbose",
|
|
@@ -51,6 +51,7 @@
|
|
|
51
51
|
"devDependencies": {
|
|
52
52
|
"@babel/plugin-proposal-decorators": "^7.27.1",
|
|
53
53
|
"@ckeditor/ckeditor5-react": "^9.5.0",
|
|
54
|
+
"@eslint/compat": "^1.2.9",
|
|
54
55
|
"@faker-js/faker": "^9.7.0",
|
|
55
56
|
"@handsontable/react": "^15.2.0",
|
|
56
57
|
"@inertiajs/react": "^2.0.0",
|
|
@@ -61,14 +62,14 @@
|
|
|
61
62
|
"@radix-ui/react-dialog": "^1.1.7",
|
|
62
63
|
"@radix-ui/react-dropdown-menu": "^2.1.6",
|
|
63
64
|
"@radix-ui/react-label": "^2.1.2",
|
|
64
|
-
"@radix-ui/react-popover": "^1.1.7",
|
|
65
65
|
"@radix-ui/react-menubar": "^1.1.12",
|
|
66
|
+
"@radix-ui/react-popover": "^1.1.7",
|
|
66
67
|
"@radix-ui/react-portal": "^1.1.6",
|
|
67
|
-
"@radix-ui/react-switch": "^1.2.4",
|
|
68
68
|
"@radix-ui/react-select": "^2.1.6",
|
|
69
69
|
"@radix-ui/react-separator": "^1.1.3",
|
|
70
70
|
"@radix-ui/react-slider": "^1.2.3",
|
|
71
71
|
"@radix-ui/react-slot": "^1.2.0",
|
|
72
|
+
"@radix-ui/react-switch": "^1.2.4",
|
|
72
73
|
"@radix-ui/react-tooltip": "^1.1.8",
|
|
73
74
|
"@tailwindcss/vite": "^4.0.15",
|
|
74
75
|
"@tanstack/react-table": "^8.21.2",
|
|
@@ -91,12 +92,14 @@
|
|
|
91
92
|
"@types/sprintf-js": "^1.1.4",
|
|
92
93
|
"@types/uuid": "^10.0.0",
|
|
93
94
|
"@types/waterline": "^0.13.9",
|
|
95
|
+
"@typescript-eslint/eslint-plugin": "^8.32.1",
|
|
94
96
|
"@vitejs/plugin-react": "^4.3.4",
|
|
95
97
|
"babel-plugin-react-compiler": "^19.0.0-beta-e993439-20250405",
|
|
96
98
|
"ckeditor5": "^45.0.0",
|
|
97
99
|
"class-variance-authority": "^0.7.1",
|
|
98
100
|
"clsx": "^2.1.1",
|
|
99
101
|
"cross-env": "^7.0.3",
|
|
102
|
+
"eslint": "^9.26.0",
|
|
100
103
|
"handsontable": "^15.2.0",
|
|
101
104
|
"json-schema": "^0.4.0",
|
|
102
105
|
"leaflet": "^1.9.4",
|
|
@@ -33,7 +33,6 @@ export default function bindReqFunctions(adminizer) {
|
|
|
33
33
|
if (res.locals) {
|
|
34
34
|
req.i18n.registerMethods(res.locals, req);
|
|
35
35
|
}
|
|
36
|
-
// TODO: I made it quickly, you need to spread for architecture to different files, or re -ize this file to a girlfriend
|
|
37
36
|
// NOTE: This is here because inertia should receive data to routes
|
|
38
37
|
// JWT token
|
|
39
38
|
const cookies = parse(req.headers.cookie || '');
|