adminizer 4.1.0-commit.ad1476a → 4.1.0-commit.d8a06d3
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/{VanillaJSONEditor-FUe77pIA.js → VanillaJSONEditor-D-Lx670g.js} +1 -1
- package/assets/add-BP_u3Tjl.js +1 -0
- package/assets/add-form-nffmiYTh.js +1 -0
- package/assets/add-group-D4vcHlm-.js +1 -0
- package/assets/{add-group-form-dzadPSfL.js → add-group-form-gNJW11-q.js} +1 -1
- package/assets/add-user-DWh3Nas0.js +1 -0
- package/assets/add-user-form-BJ0FsZYJ.js +1 -0
- package/assets/{app-DMmad2-f.css → app-WTooYWC3.css} +1 -1
- package/assets/{app-layout-D1m9Kvxq.js → app-layout-DYsRFUuP.js} +1 -1
- package/assets/{app-shell-BWMRMkHM.js → app-shell-Dd9Eknik.js} +1 -1
- package/assets/app-sidebar-BOmu6-Sl.js +1 -0
- package/assets/{app-sidebar-header-DLAFi13E.js → app-sidebar-header-CoXSzWxk.js} +1 -1
- package/assets/app.js +2 -2
- package/assets/{breadcrumbs-CQNon4Vl.js → breadcrumbs-BmAq4fHT.js} +1 -1
- package/assets/{button-CQ9t1kLz.js → button-C9B_5Jf_.js} +1 -1
- package/assets/{checkbox-W0nGAXIj.js → checkbox-Fg27sL_1.js} +1 -1
- package/assets/{compiler-runtime-tM4jBQ-T.js → compiler-runtime-hB6dAw2d.js} +1 -1
- package/assets/dashboard-BACj996r.js +3 -0
- package/assets/dashboard-BOltB2Hq.css +1 -0
- package/assets/{date-picker-B__dVVqj.js → date-picker-DI1cCO7K.js} +1 -1
- package/assets/{dropdown-menu-SEBnEIiL.js → dropdown-menu-Bhj17ENm.js} +1 -1
- package/assets/{field-renderer-CapylJU9.js → field-renderer-DVHZF6HS.js} +3 -3
- package/assets/form-BgWdwvz1.js +1 -0
- package/assets/form-DgtErfln.js +1 -0
- package/assets/{geo-json-CwteYDGB.js → geo-json-BjiyTtMu.js} +1 -1
- package/assets/{handsontable-BCnjOpBr.js → handsontable-4mjU_b0n.js} +1 -1
- package/assets/home-CHntBHJa.js +2 -0
- package/assets/{icon-Bz9BMaD0.js → icon-Dt0vBgDO.js} +1 -1
- package/assets/index-B8BS9wMC.js +1 -0
- package/assets/{index-DEk3sC8d.js → index-BKCgnGj_.js} +1 -1
- package/assets/{index-C0SL3SHw.js → index-BykbU6Ee.js} +1 -1
- package/assets/index-CaJgc5EZ.js +1 -0
- package/assets/{index-BcE9FUM6.js → index-Cgp8OfuI.js} +1 -1
- package/assets/{index-DTRTjOmh.js → index-Cw5o84pO.js} +1 -1
- package/assets/{init-user-D9mW-g14.js → init-user-JfCKJ5Ce.js} +1 -1
- package/assets/{input-DF7Ue23C.js → input-CvRbIbk4.js} +1 -1
- package/assets/{input-error-BBygona6.js → input-error-DMK7cAt7.js} +1 -1
- package/assets/{label-Z506NKsW.js → label-CSLFe9Bz.js} +1 -1
- package/assets/list-B2Oa5O_Q.js +1 -0
- package/assets/{list-table-DB1sEQLF.js → list-table-DA9MhywL.js} +5 -5
- package/assets/{login-DrGaTWhY.js → login-DQwGtdis.js} +1 -1
- package/assets/manifest.json +491 -470
- package/assets/{material-icon-CItZiB53.js → material-icon-BJg8o_fs.js} +1 -1
- package/assets/module-DWXp59Vg.js +1 -0
- package/assets/{monaco-editor-DqAqwxw4.js → monaco-editor-CJs0_GlD.js} +1 -1
- package/assets/{multi-select-oabtVhUP.js → multi-select-BvRpAW8r.js} +1 -1
- package/assets/{nav-footer-CM-yHiRs.js → nav-footer-Bs4dmN1d.js} +1 -1
- package/assets/{nav-main-Q3xofGRT.js → nav-main-Bq3IMk4C.js} +1 -1
- package/assets/{nav-user-Ds8i0Pa2.js → nav-user-CbB22J5O.js} +1 -1
- package/assets/{pagination-render-B57pOpFy.js → pagination-render-DuXDDbC_.js} +1 -1
- package/assets/{popover-I249Gg2O.js → popover-DtoGI2b1.js} +1 -1
- package/assets/{register-C9FQIDtS.js → register-BSogVF0h.js} +1 -1
- package/assets/{select-D1N8zRPY.js → select-BWepUw-9.js} +1 -1
- package/assets/{sidebar-4D-sX2l4.js → sidebar-CAHsHdjM.js} +2 -2
- package/assets/skeleton-COOcAA8f.js +1 -0
- package/assets/{sonner-Dzckw3U3.js → sonner-BI0IFOQN.js} +1 -1
- package/assets/{toast-editor-FbrFd1ft.js → toast-editor-CMK7QtF1.js} +1 -1
- package/assets/{tooltip-D2ehgLlB.js → tooltip-DHwpLKOI.js} +1 -1
- package/assets/{use-appearance-Co6mO0dV.js → use-appearance-DRfIqTgw.js} +1 -1
- package/assets/{use-window-size-B8l6Bpkf.js → use-window-size-h0Sh_NvX.js} +1 -1
- package/assets/{user-info-DBYoAJYJ.js → user-info-DFrmpJ4y.js} +1 -1
- package/assets/{user-menu-content-qkvdkUVd.js → user-menu-content-DPXQdERj.js} +1 -1
- package/assets/welcome-B4WCIXKf.js +1 -0
- package/controllers/add.js +2 -2
- package/controllers/addGroup.js +2 -4
- package/controllers/addUser.js +4 -6
- package/controllers/catalog/Catalog.js +2 -2
- package/controllers/catalog/FrontentCatalogAdapter.js +1 -2
- package/controllers/ckeditorUpload.js +2 -3
- package/controllers/dashboard.js +16 -2
- package/controllers/edit.js +2 -3
- package/controllers/editGroup.js +2 -4
- package/controllers/editUser.js +3 -5
- package/controllers/form.js +2 -3
- package/controllers/getAllWidgets.js +3 -3
- package/controllers/initUser.js +1 -2
- package/controllers/list.js +4 -4
- package/controllers/login.js +31 -15
- package/controllers/media-manager/mediaManagerAdapter.js +1 -2
- package/controllers/media-manager/mediaManagerApi.js +2 -2
- package/controllers/navigation/edit.js +1 -1
- package/controllers/processInstallFinalize.js +2 -2
- package/controllers/processInstallStep.d.ts +0 -1
- package/controllers/processInstallStep.js +122 -132
- package/controllers/register.js +1 -4
- package/controllers/remove.js +2 -2
- package/controllers/timezones.js +1 -1
- package/controllers/view.js +2 -2
- package/controllers/welcome.js +1 -1
- package/controllers/widgets/Action.js +2 -2
- package/controllers/widgets/Custom.js +2 -2
- package/controllers/widgets/Info.js +2 -2
- package/controllers/widgets/switch.js +2 -2
- package/controllers/widgetsDB.js +5 -5
- package/helpers/accessRightsHelper.d.ts +3 -2
- package/helpers/accessRightsHelper.js +1 -1
- package/helpers/configHelper.js +2 -1
- package/helpers/fieldsHelper.d.ts +1 -1
- package/helpers/inertiaActionsHelper.js +1 -1
- package/helpers/inertiaAddHelper.d.ts +1 -1
- package/helpers/inertiaAddHelper.js +2 -0
- package/helpers/inertiaFromHelper.js +2 -0
- package/helpers/inertiaGroupHelper.d.ts +4 -2
- package/helpers/inertiaGroupHelper.js +1 -1
- package/helpers/inertiaListHelper.js +5 -5
- package/helpers/inertiaMenuHelper.js +1 -1
- package/helpers/inertiaUserHelper.d.ts +7 -1
- package/helpers/inertiaUserHelper.js +5 -1
- package/index.d.ts +7 -0
- package/index.js +7 -0
- package/interfaces/adminpanelConfig.d.ts +6 -2
- package/interfaces/global.d.ts +5 -26
- package/lib/Adminizer.d.ts +2 -0
- package/lib/Adminizer.js +17 -1
- package/lib/catalog/AbstractCatalog.js +0 -1
- package/lib/catalog/Navigation.js +6 -6
- package/lib/datatable/NodeTable.js +0 -3
- package/lib/inertia/inertiaAdapter.js +0 -1
- package/lib/installStepper/installStepper.js +5 -5
- package/lib/media-manager/AbstractMediaManager.d.ts +2 -2
- package/lib/media-manager/AbstractMediaManager.js +1 -1
- package/lib/v4/DataAccessor.d.ts +2 -1
- package/lib/v4/DataAccessor.js +2 -2
- package/lib/v4/POWCaptcha.js +0 -1
- package/lib/v4/PolicyManager.js +0 -1
- package/lib/v4/helper/jwt.d.ts +10 -0
- package/lib/v4/helper/jwt.js +18 -0
- package/lib/v4/model/AbstractModel.js +0 -2
- package/lib/v4/model/ModelHandler.js +0 -1
- package/lib/v4/model/adapter/sequelize.d.ts +3 -2
- package/lib/v4/model/adapter/sequelize.js +250 -58
- package/lib/v4/model/adapter/waterline.js +0 -1
- package/lib/widgets/abstractAction.d.ts +1 -1
- package/lib/widgets/abstractCustom.d.ts +27 -12
- package/lib/widgets/abstractCustom.js +8 -2
- package/lib/widgets/abstractInfo.d.ts +1 -1
- package/lib/widgets/abstractInfo.js +1 -1
- package/lib/widgets/abstractLink.d.ts +1 -0
- package/lib/widgets/abstractSwitch.d.ts +1 -1
- package/lib/widgets/abstractWidgetBase.d.ts +1 -1
- package/lib/widgets/widgetHandler.d.ts +20 -3
- package/lib/widgets/widgetHandler.js +25 -25
- package/models/GroupAP.d.ts +8 -0
- package/models/MediaManagerAP.d.ts +16 -0
- package/models/MediaManagerAssociationsAP.d.ts +10 -0
- package/models/MediaManagerMetaAP.d.ts +8 -0
- package/models/NavigationAP.d.ts +5 -0
- package/models/UserAP.d.ts +25 -2
- package/models/UserAP.js +2 -2
- package/package.json +17 -10
- package/policies/checkAuth.js +4 -3
- package/policies/setLocale.js +2 -2
- package/system/Router.js +14 -14
- package/system/bindAuthorization.js +4 -5
- package/system/bindInertia.js +9 -9
- package/system/bindInstallStepper.js +1 -1
- package/system/bindReqFunctions.js +16 -0
- package/translations/ru.json +17 -8
- package/assets/add-ZITr43GJ.js +0 -1
- package/assets/add-form-CYOfr0Ef.js +0 -1
- package/assets/add-group-B332wN8K.js +0 -1
- package/assets/add-user-TC-mYdsB.js +0 -1
- package/assets/add-user-form-y2f_1_lM.js +0 -1
- package/assets/app-sidebar-BCtaEFGb.js +0 -1
- package/assets/dashboard-BR602KhL.js +0 -1
- package/assets/form-DOUNk3o2.js +0 -1
- package/assets/form-lOKv4Qbw.js +0 -1
- package/assets/home-Ch6QfTIt.js +0 -2
- package/assets/index-Cdb9ACvz.js +0 -1
- package/assets/index-K81GbF6O.js +0 -1
- package/assets/list-Qyd7ecQH.js +0 -1
- package/assets/module-DBaykv8l.js +0 -1
- package/assets/welcome-D2adQ8EU.js +0 -1
|
@@ -3,53 +3,110 @@ 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
|
|
6
|
+
function resolveType(type) {
|
|
7
|
+
const sqlType = typeof type.toString === "function"
|
|
8
|
+
? type.toString().toLowerCase()
|
|
9
|
+
: "";
|
|
10
|
+
if (sqlType.includes("string") || sqlType.includes("uuid"))
|
|
11
|
+
return "string";
|
|
12
|
+
if (sqlType.includes("int") || sqlType.includes("float") || sqlType.includes("decimal"))
|
|
13
|
+
return "number";
|
|
14
|
+
if (sqlType.includes("bool"))
|
|
15
|
+
return "boolean";
|
|
16
|
+
if (sqlType.includes("json"))
|
|
17
|
+
return "json";
|
|
18
|
+
if (sqlType.includes("date"))
|
|
19
|
+
return "string";
|
|
20
|
+
return "ref";
|
|
21
|
+
}
|
|
22
|
+
export function mapSequelizeToWaterline(model) {
|
|
7
23
|
const result = {};
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
const
|
|
11
|
-
result[
|
|
12
|
-
type:
|
|
13
|
-
required: !
|
|
14
|
-
|
|
15
|
-
unique: !!
|
|
24
|
+
const rawAttrs = model.getAttributes();
|
|
25
|
+
for (const name in rawAttrs) {
|
|
26
|
+
const meta = rawAttrs[name];
|
|
27
|
+
result[name] = {
|
|
28
|
+
type: resolveType(meta.type),
|
|
29
|
+
required: meta.allowNull !== undefined ? !meta.allowNull : false,
|
|
30
|
+
allowNull: meta.allowNull,
|
|
31
|
+
unique: !!meta.unique,
|
|
32
|
+
defaultsTo: meta.defaultValue,
|
|
33
|
+
columnName: meta.field || name,
|
|
16
34
|
};
|
|
17
35
|
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
36
|
+
for (const alias in model.associations) {
|
|
37
|
+
const assoc = model.associations[alias];
|
|
38
|
+
switch (assoc.associationType) {
|
|
39
|
+
case "BelongsTo": {
|
|
40
|
+
const a = assoc;
|
|
41
|
+
result[alias] = {
|
|
42
|
+
type: "association",
|
|
43
|
+
model: a.target.name.toLowerCase(),
|
|
44
|
+
via: a.foreignKey,
|
|
45
|
+
};
|
|
46
|
+
break;
|
|
47
|
+
}
|
|
48
|
+
case "HasOne": {
|
|
49
|
+
const a = assoc;
|
|
50
|
+
result[alias] = {
|
|
51
|
+
type: "association",
|
|
52
|
+
model: a.target.name.toLowerCase(),
|
|
53
|
+
via: a.foreignKey,
|
|
54
|
+
};
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
case "HasMany": {
|
|
58
|
+
const a = assoc;
|
|
59
|
+
result[alias] = {
|
|
60
|
+
type: "association-many",
|
|
61
|
+
collection: a.target.name.toLowerCase(),
|
|
62
|
+
via: a.foreignKey,
|
|
63
|
+
};
|
|
64
|
+
break;
|
|
65
|
+
}
|
|
66
|
+
case "BelongsToMany": {
|
|
67
|
+
const a = assoc;
|
|
68
|
+
result[alias] = {
|
|
69
|
+
type: "association-many",
|
|
70
|
+
collection: a.target.name.toLowerCase(),
|
|
71
|
+
via: a.otherKey,
|
|
72
|
+
};
|
|
73
|
+
break;
|
|
74
|
+
}
|
|
75
|
+
default:
|
|
76
|
+
break;
|
|
77
|
+
}
|
|
41
78
|
}
|
|
79
|
+
return result;
|
|
42
80
|
}
|
|
81
|
+
// function resolveType(type: any): AbstractFieldType {
|
|
82
|
+
// try {
|
|
83
|
+
// const sqlType = typeof type.toString === "function"
|
|
84
|
+
// ? type.toString().toLowerCase()
|
|
85
|
+
// : "";
|
|
86
|
+
// if (sqlType.includes("string")) return "string";
|
|
87
|
+
// if (sqlType.includes("uuid")) return "string";
|
|
88
|
+
// if (sqlType.includes("int") || sqlType.includes("float") || sqlType.includes("decimal")) return "number";
|
|
89
|
+
// if (sqlType.includes("bool")) return "boolean";
|
|
90
|
+
// if (sqlType.includes("json")) return "json";
|
|
91
|
+
// if (sqlType.includes("date")) return "string";
|
|
92
|
+
// return "ref";
|
|
93
|
+
// } catch {
|
|
94
|
+
// return "ref";
|
|
95
|
+
// }
|
|
96
|
+
// }
|
|
43
97
|
/** SequelizeModel — реализация модели, совместимая с AbstractModel */
|
|
98
|
+
function capitalize(str) {
|
|
99
|
+
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
100
|
+
}
|
|
44
101
|
function convertCriteriaToSequelize(criteria) {
|
|
45
|
-
console.
|
|
102
|
+
// console.debug("waterline criteria", criteria)
|
|
46
103
|
const result = {};
|
|
47
104
|
for (const key in criteria) {
|
|
48
105
|
const value = criteria[key];
|
|
49
106
|
if (value === undefined ||
|
|
50
107
|
value === null ||
|
|
51
108
|
(typeof value === "object" && Object.keys(value).length === 0)) {
|
|
52
|
-
continue;
|
|
109
|
+
continue;
|
|
53
110
|
}
|
|
54
111
|
if (typeof value === "object" && !Array.isArray(value)) {
|
|
55
112
|
const operatorEntries = Object.entries(value)
|
|
@@ -80,7 +137,32 @@ function convertCriteriaToSequelize(criteria) {
|
|
|
80
137
|
return result;
|
|
81
138
|
}
|
|
82
139
|
function convertWaterlineCriteriaToSequelizeOptions(criteria) {
|
|
83
|
-
console.
|
|
140
|
+
// console.debug("WATERLINE CRITERIA (raw):", criteria);
|
|
141
|
+
const { where: nestedWhere, skip, limit, sort, ...rest } = criteria;
|
|
142
|
+
const rawWhere = (nestedWhere && Object.keys(nestedWhere).length > 0)
|
|
143
|
+
? nestedWhere
|
|
144
|
+
: rest;
|
|
145
|
+
// console.debug("WATERLINE CRITERIA: using rawWhere =", rawWhere);
|
|
146
|
+
const where = convertCriteriaToSequelize(rawWhere);
|
|
147
|
+
// console.debug("convertCriteriaToSequelize →", where);
|
|
148
|
+
const result = { where };
|
|
149
|
+
if (typeof skip === "number") {
|
|
150
|
+
result.offset = skip;
|
|
151
|
+
// console.debug("→ offset =", skip);
|
|
152
|
+
}
|
|
153
|
+
if (typeof limit === "number") {
|
|
154
|
+
result.limit = limit;
|
|
155
|
+
// console.debug("→ limit =", limit);
|
|
156
|
+
}
|
|
157
|
+
if (typeof sort === "string") {
|
|
158
|
+
const [field, dir] = sort.trim().split(/\s+/);
|
|
159
|
+
result.order = [[field, dir?.toUpperCase() === "DESC" ? "DESC" : "ASC"]];
|
|
160
|
+
// console.debug("→ order =", result.order);
|
|
161
|
+
}
|
|
162
|
+
return result;
|
|
163
|
+
}
|
|
164
|
+
function convertWaterlineCriteriaToSequelizeOptions____OLD(criteria) {
|
|
165
|
+
// console.debug("WATERLINE CRITERIA", criteria)
|
|
84
166
|
const { where = {}, skip, limit, sort } = criteria;
|
|
85
167
|
const result = {
|
|
86
168
|
where: convertCriteriaToSequelize(where),
|
|
@@ -100,40 +182,150 @@ function convertWaterlineCriteriaToSequelizeOptions(criteria) {
|
|
|
100
182
|
export class SequelizeModel extends AbstractModel {
|
|
101
183
|
model;
|
|
102
184
|
constructor(modelName, model) {
|
|
103
|
-
super(modelName,
|
|
185
|
+
super(modelName, mapSequelizeToWaterline(model), model.primaryKeyAttribute, model.name);
|
|
104
186
|
this.model = model;
|
|
105
187
|
}
|
|
106
188
|
// --- CREATE ---
|
|
107
189
|
async _create(data) {
|
|
108
|
-
|
|
109
|
-
const
|
|
110
|
-
|
|
190
|
+
// console.clear()
|
|
191
|
+
const assocNames = Object.keys(this.model.associations);
|
|
192
|
+
const plainData = {};
|
|
193
|
+
const assocData = {};
|
|
194
|
+
// console.debug(">> _create: входные данные:", data);
|
|
195
|
+
// console.debug(">> Доступные ассоциации:", assocNames);
|
|
196
|
+
for (const [key, val] of Object.entries(data)) {
|
|
197
|
+
if (assocNames.includes(key)) {
|
|
198
|
+
assocData[key] = val;
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
plainData[key] = val;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
// console.debug(">> Обычные поля для create():", plainData);
|
|
205
|
+
// console.debug(">> Данные ассоциаций:", assocData);
|
|
206
|
+
let instance;
|
|
207
|
+
try {
|
|
208
|
+
instance = await this.model.create(plainData);
|
|
209
|
+
// console.debug(">> Создан экземпляр (без ассоциаций):", instance.toJSON());
|
|
210
|
+
}
|
|
211
|
+
catch (err) {
|
|
212
|
+
// console.error("!! Ошибка при create(plainData):", err);
|
|
213
|
+
throw err;
|
|
214
|
+
}
|
|
215
|
+
// assocData = { example: 5, userAPs: [1,2,3], category: 7, tags: [11,22] }
|
|
216
|
+
// this.model.associations — ваш объект ассоциаций
|
|
217
|
+
for (const [alias, ids] of Object.entries(assocData)) {
|
|
218
|
+
const assoc = this.model.associations[alias];
|
|
219
|
+
if (!assoc) {
|
|
220
|
+
// console.warn(`Association "${alias}" not defined on model`);
|
|
221
|
+
continue;
|
|
222
|
+
}
|
|
223
|
+
// @ts-ignore accessors is present
|
|
224
|
+
const { set: setAccessor, add: addAccessor } = assoc.accessors;
|
|
225
|
+
if (Array.isArray(ids)) {
|
|
226
|
+
if (typeof instance[setAccessor] === 'function') {
|
|
227
|
+
await instance[setAccessor](ids);
|
|
228
|
+
continue;
|
|
229
|
+
}
|
|
230
|
+
if (typeof instance[addAccessor] === 'function') {
|
|
231
|
+
for (const id of ids) {
|
|
232
|
+
await instance[addAccessor](id);
|
|
233
|
+
}
|
|
234
|
+
continue;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
if (typeof instance[setAccessor] === 'function') {
|
|
238
|
+
await instance[setAccessor](ids);
|
|
239
|
+
}
|
|
240
|
+
else if (typeof instance[addAccessor] === 'function') {
|
|
241
|
+
await instance[addAccessor](ids);
|
|
242
|
+
}
|
|
243
|
+
else {
|
|
244
|
+
// console.warn(`No suitable accessor for "${alias}": tried set=${setAccessor}, add=${addAccessor}`);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
await instance.reload({ include: Object.values(this.model.associations) });
|
|
248
|
+
const pk = this.primaryKey;
|
|
249
|
+
const fresh = await this.model.findByPk(instance.get(pk), { include: assocNames.map(a => ({ association: a })) });
|
|
250
|
+
// console.debug(">> Результат после reload:", fresh?.toJSON());
|
|
251
|
+
return fresh;
|
|
111
252
|
}
|
|
112
253
|
// --- FIND ONE ---
|
|
113
254
|
async _findOne(criteria) {
|
|
255
|
+
// console.debug(">> _findOne: входные критерии:", criteria);
|
|
114
256
|
const { where } = convertWaterlineCriteriaToSequelizeOptions(criteria);
|
|
115
|
-
const
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
257
|
+
const includes = this._buildIncludes();
|
|
258
|
+
// console.debug(">> _findOne: преобразованные where:", where);
|
|
259
|
+
// console.debug(">> _findOne: includes:", includes);
|
|
260
|
+
let instance = null;
|
|
261
|
+
try {
|
|
262
|
+
instance = await this.model.findOne({ where, include: includes });
|
|
263
|
+
// console.debug(">> _findOne: сырое instance:", instance ? instance.toJSON() : null);
|
|
264
|
+
}
|
|
265
|
+
catch (err) {
|
|
266
|
+
// console.error("!! _findOne: ошибка при вызове findOne:", err);
|
|
267
|
+
throw err;
|
|
268
|
+
}
|
|
269
|
+
if (!instance) {
|
|
270
|
+
// console.debug(">> _findOne: ничего не найдено");
|
|
271
|
+
return null;
|
|
272
|
+
}
|
|
273
|
+
const plain = instance.get({ plain: true });
|
|
274
|
+
// console.debug(">> _findOne: plain результат:", plain);
|
|
275
|
+
return plain;
|
|
121
276
|
}
|
|
122
277
|
// --- FIND MANY ---
|
|
123
278
|
async _find(criteria = {}, options = {}) {
|
|
279
|
+
const assocNames = Object.keys(this.model.associations);
|
|
280
|
+
// console.debug(">> _find: входные criteria:", criteria, "options:", options);
|
|
124
281
|
const { where, limit, offset, order } = convertWaterlineCriteriaToSequelizeOptions(criteria);
|
|
125
|
-
const
|
|
282
|
+
const includes = options.populate
|
|
126
283
|
? options.populate.map(([field, opts]) => ({ association: field, ...opts }))
|
|
127
|
-
:
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
284
|
+
: assocNames.map(a => ({ association: a }));
|
|
285
|
+
// console.debug(">> _find: where, limit, offset, order, includes:", {
|
|
286
|
+
// where,
|
|
287
|
+
// limit,
|
|
288
|
+
// offset,
|
|
289
|
+
// order,
|
|
290
|
+
// includes,
|
|
291
|
+
// });
|
|
292
|
+
let instances;
|
|
293
|
+
try {
|
|
294
|
+
instances = await this.model.findAll({
|
|
295
|
+
where,
|
|
296
|
+
limit,
|
|
297
|
+
offset,
|
|
298
|
+
order,
|
|
299
|
+
include: includes
|
|
300
|
+
});
|
|
301
|
+
// console.debug(">> _find: получено моделей:", instances.length);
|
|
302
|
+
}
|
|
303
|
+
catch (err) {
|
|
304
|
+
// console.error("!! _find: ошибка в findAll:", err);
|
|
305
|
+
throw err;
|
|
306
|
+
}
|
|
307
|
+
for (const inst of instances) {
|
|
308
|
+
//For each association, we call getxxx () once again
|
|
309
|
+
for (const alias of assocNames) {
|
|
310
|
+
// @ts-ignore accessors is present
|
|
311
|
+
const getAccessor = this.model.associations[alias].accessors.get;
|
|
312
|
+
if (typeof inst[getAccessor] === "function") {
|
|
313
|
+
try {
|
|
314
|
+
const related = await inst[getAccessor]();
|
|
315
|
+
const mapped = Array.isArray(related)
|
|
316
|
+
? related.map((r) => r.toJSON())
|
|
317
|
+
: related?.toJSON();
|
|
318
|
+
// console.debug(`---- get${alias}():`, mapped);
|
|
319
|
+
}
|
|
320
|
+
catch (e) {
|
|
321
|
+
// console.error(`!! ошибка при вызове ${getAccessor}():`, e);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
const plain = instances.map(i => i.get({ plain: true }));
|
|
327
|
+
// console.debug(">> _find: plain результаты:", plain);
|
|
328
|
+
return plain;
|
|
137
329
|
}
|
|
138
330
|
// --- UPDATE ONE ---
|
|
139
331
|
async _updateOne(criteria, data) {
|
|
@@ -205,7 +397,7 @@ export class SequelizeAdapter extends AbstractAdapter {
|
|
|
205
397
|
const model = this.getModel(modelName);
|
|
206
398
|
return model?.getAttributes();
|
|
207
399
|
}
|
|
208
|
-
/**
|
|
400
|
+
/**Registration of system models*/
|
|
209
401
|
static async registerSystemModels(sequelize) {
|
|
210
402
|
const modelsDir = path.resolve(import.meta.dirname, "../../../../models");
|
|
211
403
|
const files = fs.readdirSync(modelsDir).filter(f => f.endsWith(".js"));
|
|
@@ -218,7 +410,7 @@ export class SequelizeAdapter extends AbstractAdapter {
|
|
|
218
410
|
await sequelize.sync();
|
|
219
411
|
}
|
|
220
412
|
}
|
|
221
|
-
/**
|
|
413
|
+
/**Generation of the SEQUELIZE model from the definition, analogue of Waterinecollection.extenD*/
|
|
222
414
|
function generateSequelizeModel(sequelize, modelName, rawAttributes) {
|
|
223
415
|
const attributes = {};
|
|
224
416
|
let primaryKey = null;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import BaseWidget from "./abstractWidgetBase";
|
|
2
2
|
export default abstract class ActionBase extends BaseWidget {
|
|
3
3
|
readonly widgetType = "action";
|
|
4
|
-
/** Widget background css
|
|
4
|
+
/** Widget background css color */
|
|
5
5
|
abstract readonly backgroundCSS: string | null;
|
|
6
6
|
abstract action(): Promise<any>;
|
|
7
7
|
}
|
|
@@ -1,13 +1,28 @@
|
|
|
1
|
-
import
|
|
2
|
-
export default abstract class CustomBase
|
|
3
|
-
/** Widget
|
|
4
|
-
abstract readonly
|
|
5
|
-
/**
|
|
6
|
-
abstract readonly
|
|
7
|
-
/**
|
|
8
|
-
abstract readonly
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
1
|
+
import { MaterialIcon } from "material-icons";
|
|
2
|
+
export default abstract class CustomBase {
|
|
3
|
+
/** Widget unique id */
|
|
4
|
+
abstract readonly id: string;
|
|
5
|
+
/** Widget Name */
|
|
6
|
+
abstract readonly name: string;
|
|
7
|
+
/** JS module file path */
|
|
8
|
+
abstract readonly jsPath: {
|
|
9
|
+
dev: string;
|
|
10
|
+
production: string;
|
|
11
|
+
};
|
|
12
|
+
/** For group access rights by department */
|
|
13
|
+
abstract readonly department: string;
|
|
14
|
+
/** Widget background css color */
|
|
15
|
+
readonly backgroundCSS: string;
|
|
16
|
+
/** Widget size */
|
|
17
|
+
abstract readonly size: {
|
|
18
|
+
h: number;
|
|
19
|
+
w: number;
|
|
20
|
+
} | null;
|
|
21
|
+
/** Widget description */
|
|
22
|
+
abstract readonly description: string;
|
|
23
|
+
/** Widget icon */
|
|
24
|
+
abstract readonly icon?: MaterialIcon | string;
|
|
25
|
+
readonly widgetType: 'custom';
|
|
26
|
+
routePrefix: string;
|
|
27
|
+
protected constructor(routePrefix: string);
|
|
13
28
|
}
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
export default class CustomBase {
|
|
2
|
+
/** Widget background css color */
|
|
3
|
+
backgroundCSS;
|
|
4
|
+
widgetType = 'custom';
|
|
5
|
+
routePrefix;
|
|
6
|
+
constructor(routePrefix) {
|
|
7
|
+
this.routePrefix = routePrefix;
|
|
8
|
+
}
|
|
3
9
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import BaseWidget from "./abstractWidgetBase";
|
|
2
2
|
export default abstract class InfoBase extends BaseWidget {
|
|
3
3
|
readonly widgetType = "info";
|
|
4
|
-
/** Widget background css
|
|
4
|
+
/** Widget background css color */
|
|
5
5
|
readonly backgroundCSS: string;
|
|
6
6
|
/** Widget size */
|
|
7
7
|
readonly size: {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import BaseWidget from "./abstractWidgetBase";
|
|
2
2
|
export default abstract class SwitchBase extends BaseWidget {
|
|
3
3
|
readonly widgetType = "switcher";
|
|
4
|
-
/** Widget background css
|
|
4
|
+
/** Widget background css color */
|
|
5
5
|
abstract readonly backgroundCSS: string | null;
|
|
6
6
|
/** Get current state */
|
|
7
7
|
abstract getState(): Promise<boolean>;
|
|
@@ -5,6 +5,8 @@ import LinkBase from "./abstractLink";
|
|
|
5
5
|
import CustomBase from "./abstractCustom";
|
|
6
6
|
import { AdminpanelIcon } from "../../interfaces/adminpanelConfig";
|
|
7
7
|
import { Adminizer } from "../Adminizer";
|
|
8
|
+
import { UserAP } from "models/UserAP";
|
|
9
|
+
import { I18n } from "../v4/I18n";
|
|
8
10
|
export type WidgetType = (SwitcherBase | InfoBase | ActionBase | LinkBase | CustomBase);
|
|
9
11
|
export interface WidgetConfig {
|
|
10
12
|
id: string;
|
|
@@ -16,6 +18,7 @@ export interface WidgetConfig {
|
|
|
16
18
|
name: string;
|
|
17
19
|
backgroundCSS: string;
|
|
18
20
|
scriptUrl?: string;
|
|
21
|
+
linkType?: 'self' | 'blank';
|
|
19
22
|
constructorName?: string;
|
|
20
23
|
constructorOption?: any;
|
|
21
24
|
size?: {
|
|
@@ -25,6 +28,14 @@ export interface WidgetConfig {
|
|
|
25
28
|
added?: boolean;
|
|
26
29
|
hideAdminPanelUI?: boolean;
|
|
27
30
|
}
|
|
31
|
+
export interface WidgetLayoutItem {
|
|
32
|
+
x: number;
|
|
33
|
+
y: number;
|
|
34
|
+
w: number;
|
|
35
|
+
h: number;
|
|
36
|
+
i: string;
|
|
37
|
+
id: string;
|
|
38
|
+
}
|
|
28
39
|
export declare class WidgetHandler {
|
|
29
40
|
private widgets;
|
|
30
41
|
adminizer: Adminizer;
|
|
@@ -32,7 +43,13 @@ export declare class WidgetHandler {
|
|
|
32
43
|
add(widget: WidgetType): void;
|
|
33
44
|
getById(id: string): WidgetType | undefined;
|
|
34
45
|
removeById(id: string): void;
|
|
35
|
-
getAll(user:
|
|
36
|
-
getWidgetsDB(id: number, auth: boolean): Promise<
|
|
37
|
-
|
|
46
|
+
getAll(user: UserAP, i18n: I18n): Promise<WidgetConfig[]>;
|
|
47
|
+
getWidgetsDB(id: number, auth: boolean, i18n: I18n): Promise<{
|
|
48
|
+
widgets: WidgetConfig[];
|
|
49
|
+
layout: WidgetLayoutItem[];
|
|
50
|
+
}>;
|
|
51
|
+
setWidgetsDB(id: number, body: {
|
|
52
|
+
widgets: WidgetConfig[];
|
|
53
|
+
layout: WidgetLayoutItem[];
|
|
54
|
+
}, auth: boolean): Promise<number>;
|
|
38
55
|
}
|