adminizer 4.1.0-build.15 → 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
|
@@ -100,7 +100,6 @@ export class DataAccessor {
|
|
|
100
100
|
result[key] = { config: fldConfig, model: modelField, populated: populatedModelFieldsConfig };
|
|
101
101
|
});
|
|
102
102
|
this.fields = result;
|
|
103
|
-
console.log(result);
|
|
104
103
|
return result;
|
|
105
104
|
}
|
|
106
105
|
getAssociatedFieldsConfig(modelName) {
|
|
@@ -377,10 +376,11 @@ export class DataAccessor {
|
|
|
377
376
|
const relation = modelAttributes[accessField];
|
|
378
377
|
if (relation && ['userap', 'groupap'].includes(relation.model.toLowerCase())) {
|
|
379
378
|
if (relation.model.toLowerCase() === 'userap') {
|
|
380
|
-
|
|
379
|
+
if (!this.user.isAdministrator) {
|
|
380
|
+
updatedRecord[accessField] = this.user.id;
|
|
381
|
+
}
|
|
381
382
|
}
|
|
382
383
|
else if (relation.model.toLowerCase() === 'groupap') {
|
|
383
|
-
// Works only for users with only one group, later it can be resolved with group weight
|
|
384
384
|
const userGroups = this.user.groups || [];
|
|
385
385
|
if (userGroups.length === 1) {
|
|
386
386
|
updatedRecord[accessField] = userGroups[0].id;
|
|
@@ -432,6 +432,7 @@ export class DataAccessor {
|
|
|
432
432
|
updatedRecord[field] = intermediateRecord.id;
|
|
433
433
|
}
|
|
434
434
|
}
|
|
435
|
+
console.log(updatedRecord, "<<<<<<<<<<<<<<<<<<<,");
|
|
435
436
|
return updatedRecord;
|
|
436
437
|
}
|
|
437
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 || '');
|