adminizer 4.6.0 → 4.7.0-build.221
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/Readme.md +12 -0
- package/assets/RelationDialogStack-CnHFOYyR.css +1 -0
- package/assets/RelationDialogStack-DI2bZxQX.js +20 -0
- package/assets/add-4213XScp.js +1 -0
- package/assets/add-group--F1XxfJ1.js +1 -0
- package/assets/add-group-form-DKRXC2n-.js +1 -0
- package/assets/add-user-b9HfMq7z.js +1 -0
- package/assets/add-user-form-UXAToWQd.js +1 -0
- package/assets/app-Clx8f5hd.css +1 -0
- package/assets/app-layout-C02ja4OI.js +1 -0
- package/assets/app-shell-D8wtkECO.js +1 -0
- package/assets/app-sidebar-BR5_zwxj.js +1 -0
- package/assets/app-sidebar-header-BZbIBQjq.js +1 -0
- package/assets/app.js +59 -7990
- package/assets/breadcrumbs-CODaqVkB.js +1 -0
- package/assets/catalog-6ZZjWdFs.js +6 -0
- package/assets/dashboard-CftAdKiH.js +3 -0
- package/assets/date-picker-DSOkNiNo.js +1 -0
- package/assets/del-modal-Cd4M7af8.js +1 -0
- package/assets/dynamic-controls-BsrJhPDY.js +1 -0
- package/assets/geo-json-CzR5JBXL.js +1 -0
- package/assets/handsontable-BI98OF5R.js +336 -0
- package/assets/history-DLHSU7Ak.js +1 -0
- package/assets/home-NcQ7nnU0.js +2 -0
- package/assets/icon-C2JNaLxH.js +1 -0
- package/assets/init-user-D2HSyXup.js +1 -0
- package/assets/input-error-CH2caTtO.js +1 -0
- package/assets/jsoneditor-DVNQmA6G.js +3869 -0
- package/assets/list-CFU0-TgN.js +4 -0
- package/assets/login-DFSLEO17.js +1 -0
- package/assets/manifest.json +246 -273
- package/assets/material-icon-Bx9pGQiQ.js +1 -0
- package/assets/media-manager-WcKe1EvD.js +6 -0
- package/assets/module-CT7PC6pc.js +1 -0
- package/assets/monaco-Bl4zdWCn.js +11 -0
- package/assets/nav-footer-BiSQkPt4.js +1 -0
- package/assets/nav-main-rTH0PfDw.js +1 -0
- package/assets/nav-user-Bj6cWs0a.js +1 -0
- package/assets/notification-Bi-PX87D.js +20 -0
- package/assets/pagination-render-AKJvTIRA.js +1 -0
- package/assets/register-BTP4uxsK.js +1 -0
- package/assets/ru-eW0WKkga.js +1 -0
- package/assets/theme-switcher-Dm8EOGzx.js +1 -0
- package/assets/toast-editor-DOg_gvSp.js +668 -0
- package/assets/user-filters-list-YUfR4XMI.js +1 -0
- package/assets/user-info-BgSbT02v.js +1 -0
- package/assets/user-menu-content-TQTXHIv6.js +1 -0
- package/assets/{vanilla-picker-l5rcX3cq.js → vanilla-picker-B3LgXoKV.js} +1 -7
- package/assets/welcome-vLwTu1R6.js +1 -0
- package/controllers/add.d.ts +1 -1
- package/controllers/add.js +20 -26
- package/controllers/addGroup.d.ts +1 -1
- package/controllers/addGroup.js +7 -15
- package/controllers/addUser.d.ts +1 -1
- package/controllers/addUser.js +10 -16
- package/controllers/catalog/Catalog.d.ts +1 -1
- package/controllers/catalog/Catalog.js +1 -10
- package/controllers/catalog/FrontendCatalogAdapter.d.ts +3 -3
- package/controllers/catalog/FrontendCatalogAdapter.js +0 -6
- package/controllers/catalog/FrontentCatalogAdapter.d.ts +3 -3
- package/controllers/catalog/FrontentCatalogAdapter.js +0 -4
- package/controllers/ckeditorUpload.js +2 -18
- package/controllers/dashboard.d.ts +1 -1
- package/controllers/dashboard.js +2 -5
- package/controllers/edit.js +24 -37
- package/controllers/editGroup.d.ts +1 -1
- package/controllers/editGroup.js +10 -21
- package/controllers/editUser.d.ts +1 -1
- package/controllers/editUser.js +11 -23
- package/controllers/exportData.d.ts +6 -0
- package/controllers/exportData.js +315 -0
- package/controllers/feed.d.ts +6 -0
- package/controllers/feed.js +73 -0
- package/controllers/feedback/feedbackController.d.ts +1 -1
- package/controllers/feedback/feedbackController.js +5 -7
- package/controllers/filter-fields/columns.d.ts +11 -0
- package/controllers/filter-fields/columns.js +106 -0
- package/controllers/filter-fields/filterFields.d.ts +10 -0
- package/controllers/filter-fields/filterFields.js +141 -0
- package/controllers/filter-fields/getAllUserFilters.d.ts +6 -0
- package/controllers/filter-fields/getAllUserFilters.js +115 -0
- package/controllers/filter-fields/groups.d.ts +5 -0
- package/controllers/filter-fields/groups.js +26 -0
- package/controllers/filter-fields/savedFilters.d.ts +25 -0
- package/controllers/filter-fields/savedFilters.js +317 -0
- package/controllers/getAllWidgets.d.ts +1 -1
- package/controllers/getAllWidgets.js +1 -9
- package/controllers/history-actions/HistoryController.js +6 -31
- package/controllers/initUser.js +6 -5
- package/controllers/inlineUpdate.d.ts +7 -0
- package/controllers/inlineUpdate.js +148 -0
- package/controllers/list.d.ts +1 -1
- package/controllers/list.js +383 -70
- package/controllers/listUserFilters.d.ts +5 -0
- package/controllers/listUserFilters.js +26 -0
- package/controllers/login.js +2 -2
- package/controllers/media-manager/mediaManagerApi.js +0 -9
- package/controllers/navigation/edit.js +3 -9
- package/controllers/notifications/NotificationController.d.ts +1 -1
- package/controllers/notifications/NotificationController.js +12 -36
- package/controllers/register.js +10 -9
- package/controllers/remove.js +10 -19
- package/controllers/timezones.d.ts +1 -1
- package/controllers/timezones.js +0 -6
- package/controllers/userApiKey.d.ts +7 -0
- package/controllers/userApiKey.js +36 -0
- package/controllers/view.js +14 -26
- package/controllers/welcome.d.ts +1 -1
- package/controllers/welcome.js +0 -4
- package/controllers/widgets/Action.d.ts +1 -1
- package/controllers/widgets/Action.js +1 -9
- package/controllers/widgets/Custom.d.ts +1 -1
- package/controllers/widgets/Custom.js +1 -9
- package/controllers/widgets/Info.d.ts +1 -1
- package/controllers/widgets/Info.js +1 -9
- package/controllers/widgets/filterInfo.d.ts +1 -0
- package/controllers/widgets/filterInfo.js +44 -0
- package/controllers/widgets/switch.d.ts +1 -1
- package/controllers/widgets/switch.js +1 -9
- package/controllers/widgetsDB.d.ts +1 -1
- package/controllers/widgetsDB.js +2 -8
- package/helpers/accessRightsHelper.d.ts +1 -1
- package/helpers/accessRightsHelper.js +5 -4
- package/helpers/apiKeyHelper.d.ts +5 -0
- package/helpers/apiKeyHelper.js +8 -0
- package/helpers/configHelper.js +12 -15
- package/helpers/controllerHelper.d.ts +14 -21
- package/helpers/controllerHelper.js +50 -83
- package/helpers/fieldsHelper.js +3 -3
- package/helpers/filterDatetimeHelper.d.ts +5 -0
- package/helpers/filterDatetimeHelper.js +84 -0
- package/helpers/inertiaActionsHelper.d.ts +2 -2
- package/helpers/inertiaActionsHelper.js +5 -4
- package/helpers/inertiaAddHelper.d.ts +3 -414
- package/helpers/inertiaAddHelper.js +39 -15
- package/helpers/inertiaGroupHelper.d.ts +2 -2
- package/helpers/inertiaGroupHelper.js +3 -3
- package/helpers/inertiaListHelper.d.ts +7 -3
- package/helpers/inertiaListHelper.js +26 -12
- package/helpers/inertiaMenuHelper.d.ts +1 -0
- package/helpers/inertiaMenuHelper.js +15 -3
- package/helpers/inertiaUserHelper.d.ts +3 -2
- package/helpers/inertiaUserHelper.js +7 -3
- package/helpers/menuHelper.d.ts +5 -2
- package/helpers/menuHelper.js +64 -12
- package/helpers/viteHelper.js +1 -2
- package/index.d.ts +6 -2
- package/index.js +6 -2
- package/interfaces/adminpanelConfig.d.ts +126 -39
- package/interfaces/internalModelAccess.d.ts +37 -0
- package/interfaces/internalModelAccess.js +1 -0
- package/interfaces/listQueryBuilder.d.ts +22 -0
- package/interfaces/listQueryBuilder.js +1 -0
- package/interfaces/queryCriteria.d.ts +54 -0
- package/interfaces/queryCriteria.js +1 -0
- package/interfaces/types.d.ts +1 -13
- package/lib/Adminizer.d.ts +4 -2
- package/lib/Adminizer.js +29 -10
- package/lib/DataAccessor.d.ts +8 -5
- package/lib/DataAccessor.js +89 -42
- package/lib/I18n.d.ts +5 -1
- package/lib/I18n.js +45 -19
- package/lib/MiddlewareManager.d.ts +8 -0
- package/lib/MiddlewareManager.js +53 -0
- package/lib/ai-assistant/OpenAiModelService.d.ts +3 -3
- package/lib/ai-assistant/OpenAiModelService.js +23 -24
- package/lib/catalog/Navigation.d.ts +1 -0
- package/lib/catalog/Navigation.js +12 -11
- package/lib/controls/jsoneditor/JsonEditor.d.ts +1 -2
- package/lib/controls/markdown/ToastUiEditor.d.ts +1 -2
- package/lib/feedback/FeedbackHandler.js +2 -2
- package/lib/filters/ConditionValidator.d.ts +107 -0
- package/lib/filters/ConditionValidator.js +483 -0
- package/lib/filters/CustomFilterHandler.d.ts +122 -0
- package/lib/filters/CustomFilterHandler.js +131 -0
- package/lib/filters/FilterCustomFieldHandler.d.ts +2 -0
- package/lib/filters/FilterCustomFieldHandler.js +2 -0
- package/lib/filters/FilterService.d.ts +82 -0
- package/lib/filters/FilterService.js +323 -0
- package/lib/filters/index.d.ts +6 -0
- package/lib/filters/index.js +4 -0
- package/lib/history-actions/AbstractHistoryAdapter.d.ts +5 -4
- package/lib/history-actions/AbstractHistoryAdapter.js +45 -30
- package/lib/history-actions/DefaultHistoryAdapter.d.ts +2 -0
- package/lib/history-actions/DefaultHistoryAdapter.js +12 -6
- package/lib/history-actions/HistoryHandler.js +1 -1
- package/lib/list-query-builder/ListQueryBuilder.d.ts +117 -0
- package/lib/list-query-builder/ListQueryBuilder.js +707 -0
- package/lib/media-manager/AbstractMediaManager.d.ts +9 -8
- package/lib/media-manager/DefaultMediaManager.d.ts +2 -0
- package/lib/media-manager/DefaultMediaManager.js +27 -15
- package/lib/media-manager/Items.d.ts +4 -1
- package/lib/media-manager/Items.js +62 -59
- package/lib/media-manager/MediaManagerHandler.js +1 -1
- package/lib/media-manager/helpers/MediaManagerHelper.d.ts +5 -1
- package/lib/media-manager/helpers/MediaManagerHelper.js +38 -4
- package/lib/model/AbstractModel.d.ts +33 -25
- package/lib/model/AbstractModel.js +54 -2
- package/lib/model/InternalModelAccessFactory.d.ts +18 -0
- package/lib/model/InternalModelAccessFactory.js +82 -0
- package/lib/model/ModelHandler.d.ts +6 -0
- package/lib/model/ModelHandler.js +14 -0
- package/lib/model/adapter/sequelize.d.ts +32 -10
- package/lib/model/adapter/sequelize.js +409 -62
- package/lib/model/adapter/typeorm.d.ts +62 -0
- package/lib/model/adapter/typeorm.js +777 -0
- package/lib/model/internalModelAccessToken.d.ts +1 -0
- package/lib/model/internalModelAccessToken.js +1 -0
- package/lib/model/internalModelRepository.d.ts +3 -0
- package/lib/model/internalModelRepository.js +4 -0
- package/lib/notifications/AbstractNotificationService.d.ts +3 -0
- package/lib/notifications/AbstractNotificationService.js +42 -36
- package/lib/notifications/GeneralNotificationService.js +37 -40
- package/lib/notifications/SystemNotificationService.js +33 -36
- package/lib/requestProcessor.js +0 -3
- package/lib/ui-i18n/getUiTranslations.d.ts +1 -0
- package/lib/ui-i18n/getUiTranslations.js +3 -0
- package/lib/ui-i18n/uiTranslationKeys.d.ts +6 -0
- package/lib/ui-i18n/uiTranslationKeys.js +268 -0
- package/lib/widgets/widgetHandler.d.ts +7 -2
- package/lib/widgets/widgetHandler.js +98 -18
- package/models/FilterAP.d.ts +116 -0
- package/models/FilterAP.js +68 -0
- package/models/FilterColumnAP.d.ts +32 -0
- package/models/FilterColumnAP.js +21 -0
- package/models/GroupAP.d.ts +1 -1
- package/models/HistoryActionsAP.d.ts +3 -3
- package/models/MediaManagerMetaAP.d.ts +1 -1
- package/models/NavigationAP.d.ts +1 -1
- package/models/UserAP.d.ts +6 -1
- package/models/UserAP.js +4 -0
- package/package.json +39 -32
- package/policies/authPolicies.d.ts +12 -0
- package/policies/authPolicies.js +104 -0
- package/policies/permissionResolvers.d.ts +12 -0
- package/policies/permissionResolvers.js +52 -0
- package/services/FeedService.d.ts +70 -0
- package/services/FeedService.js +334 -0
- package/system/Router.d.ts +1 -0
- package/system/Router.js +136 -59
- package/system/bindAccessRights.js +11 -30
- package/system/bindAuthorization.js +18 -18
- package/system/bindCors.js +16 -1
- package/system/bindCustomFilterHandlers.d.ts +2 -0
- package/system/bindCustomFilterHandlers.js +4 -0
- package/system/bindInertia.js +18 -61
- package/system/bindReqFunctions.js +10 -2
- package/system/bindTranslations.js +7 -3
- package/system/buildInternalModelAccess.d.ts +4 -0
- package/system/buildInternalModelAccess.js +59 -0
- package/system/defaults.js +18 -14
- package/system/routePolicies.d.ts +2 -0
- package/system/routePolicies.js +29 -0
- package/translations/en.json +151 -39
- package/translations/ru.json +211 -64
- package/ui/components/handsontable.js +13 -27
- package/ui/components/ui/dialog-stack.js +1 -3
- package/ui/components/ui/popover.js +1 -1
- package/ui/components/ui/sidebar.js +1 -1
- package/assets/RelationDialogStack-D9UVEF9s.js +0 -407
- package/assets/RelationDialogStack-DV8OITPR.css +0 -4
- package/assets/add-BlvzWQKF.js +0 -1
- package/assets/add-group-1Uoq9NWe.js +0 -1
- package/assets/add-group-form-B01gwDGu.js +0 -1
- package/assets/add-user-BQCAsaRy.js +0 -1
- package/assets/add-user-form-Cgwc9JkI.js +0 -1
- package/assets/app-DaOMy1nl.css +0 -72
- package/assets/app-layout-CAm60qoE.js +0 -1
- package/assets/app-shell-QWCtn9ye.js +0 -1
- package/assets/app-sidebar-CfaYbnSy.js +0 -1
- package/assets/app-sidebar-header-BsPFDhZ8.js +0 -1
- package/assets/breadcrumbs-CZZirDj8.js +0 -1
- package/assets/catalog-k5myk7fk.js +0 -6
- package/assets/dashboard-BkL9ybBw.js +0 -3
- package/assets/date-picker-B5AZ_7Q9.js +0 -1
- package/assets/del-modal-BoyXZloG.js +0 -1
- package/assets/dynamic-controls-k61T9W2P.js +0 -1
- package/assets/form-1WGY0YgG.js +0 -1
- package/assets/form-DJapG3qF.js +0 -1
- package/assets/geo-json-DsMUHo0l.js +0 -4
- package/assets/handsontable-PxYdjN8c.js +0 -298
- package/assets/history-CluyR-yJ.js +0 -1
- package/assets/home-Dug9zBzM.js +0 -2
- package/assets/icon-DfDLMG5f.js +0 -1
- package/assets/init-user-CF80MEnT.js +0 -1
- package/assets/input-error-DuuqFgZa.js +0 -1
- package/assets/jsoneditor-De1FvcYu.js +0 -3882
- package/assets/list-CuexshNt.js +0 -1
- package/assets/list-table-BsEWjTKY.js +0 -22
- package/assets/login-eDemYzN-.js +0 -1
- package/assets/material-icon-DMT8KdmE.js +0 -1
- package/assets/media-manager-DfYa_mT_.js +0 -14
- package/assets/module-Cd4Tm6uq.js +0 -1
- package/assets/monaco-BhBYtg3d.js +0 -11
- package/assets/nav-footer-D3olYxtz.js +0 -1
- package/assets/nav-main-BctqyzeV.js +0 -1
- package/assets/nav-user-Bn1Lt-BZ.js +0 -1
- package/assets/notification-D64qvni-.js +0 -27
- package/assets/pagination-render-DxD78ahJ.js +0 -1
- package/assets/register-349PwYbe.js +0 -1
- package/assets/theme-switcher-DfExsHW2.js +0 -1
- package/assets/toast-editor-ESK5iWPx.js +0 -845
- package/assets/user-info-DtBK5Kh8.js +0 -1
- package/assets/user-menu-content-0XYOCMaA.js +0 -1
- package/assets/welcome-PDp-gUei.js +0 -1
- package/controllers/form.d.ts +0 -1
- package/controllers/form.js +0 -86
- package/helpers/formHelper.d.ts +0 -6
- package/helpers/formHelper.js +0 -38
- package/helpers/inertiaFromHelper.d.ts +0 -11
- package/helpers/inertiaFromHelper.js +0 -98
- package/helpers/runtimeMode.d.ts +0 -1
- package/helpers/runtimeMode.js +0 -3
- package/lib/PolicyManager.d.ts +0 -8
- package/lib/PolicyManager.js +0 -53
- package/lib/datatable/NodeTable.d.ts +0 -49
- package/lib/datatable/NodeTable.js +0 -207
- package/lib/model/adapter/waterline.d.ts +0 -32
- package/lib/model/adapter/waterline.js +0 -180
- package/migrations/index.d.ts +0 -3
- package/migrations/index.js +0 -4
- package/migrations/knex/20250106000001_adminizer_init.d.ts +0 -8
- package/migrations/knex/20250106000001_adminizer_init.js +0 -164
- package/migrations/umzug/0001.d.ts +0 -7
- package/migrations/umzug/0001.js +0 -121
- package/migrations/umzugExports.d.ts +0 -2
- package/migrations/umzugExports.js +0 -9
- package/system/bindForms.d.ts +0 -2
- package/system/bindForms.js +0 -20
- /package/{policies → middlewares}/addMessages.d.ts +0 -0
- /package/{policies → middlewares}/addMessages.js +0 -0
- /package/{policies → middlewares}/checkAuth.d.ts +0 -0
- /package/{policies → middlewares}/checkAuth.js +0 -0
- /package/{policies → middlewares}/setLocale.d.ts +0 -0
- /package/{policies → middlewares}/setLocale.js +0 -0
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base custom filter handler contract.
|
|
3
|
+
* Stores model and field separately and builds a full handler ID as "Model.field".
|
|
4
|
+
*/
|
|
5
|
+
export class AbstractCustomFilter {
|
|
6
|
+
modelName;
|
|
7
|
+
fieldName;
|
|
8
|
+
constructor(modelName, fieldName) {
|
|
9
|
+
if (!modelName?.trim()) {
|
|
10
|
+
throw new Error("Custom filter handler requires non-empty model name.");
|
|
11
|
+
}
|
|
12
|
+
if (!fieldName?.trim()) {
|
|
13
|
+
throw new Error("Custom filter handler requires non-empty field name.");
|
|
14
|
+
}
|
|
15
|
+
this.modelName = modelName;
|
|
16
|
+
this.fieldName = fieldName;
|
|
17
|
+
}
|
|
18
|
+
get id() {
|
|
19
|
+
return `${this.modelName}.${this.fieldName}`;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Handler description
|
|
23
|
+
*/
|
|
24
|
+
description;
|
|
25
|
+
/**
|
|
26
|
+
* Optional input config for UI (up to 3 inputs).
|
|
27
|
+
* Example:
|
|
28
|
+
* {
|
|
29
|
+
* from: { placeholder: "From", type: "number" },
|
|
30
|
+
* to: { placeholder: "To", type: "number" }
|
|
31
|
+
* }
|
|
32
|
+
*/
|
|
33
|
+
inputConfig;
|
|
34
|
+
getInputDefinitions() {
|
|
35
|
+
if (!this.inputConfig) {
|
|
36
|
+
return [];
|
|
37
|
+
}
|
|
38
|
+
return Object.entries(this.inputConfig).map(([id, config]) => ({
|
|
39
|
+
id,
|
|
40
|
+
placeholder: config?.placeholder || id,
|
|
41
|
+
type: config?.type === "number" ? "number" : "text",
|
|
42
|
+
}));
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* CustomFilterHandler - registry for custom field handlers
|
|
47
|
+
*/
|
|
48
|
+
export class CustomFilterHandler {
|
|
49
|
+
handlers = new Map();
|
|
50
|
+
validateInputConfig(handler) {
|
|
51
|
+
const definitions = handler.getInputDefinitions();
|
|
52
|
+
if (definitions.length > 3) {
|
|
53
|
+
throw new Error(`Custom filter handler '${handler.id}' supports at most 3 inputs.`);
|
|
54
|
+
}
|
|
55
|
+
for (const definition of definitions) {
|
|
56
|
+
if (!definition.id.trim()) {
|
|
57
|
+
throw new Error(`Custom filter handler '${handler.id}' has an input with empty id.`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Register a custom handler
|
|
63
|
+
* @param handler - Handler instance
|
|
64
|
+
* @param options - Registration options
|
|
65
|
+
*/
|
|
66
|
+
add(handler, options) {
|
|
67
|
+
this.validateInputConfig(handler);
|
|
68
|
+
if (this.handlers.has(handler.id) && !options?.force) {
|
|
69
|
+
throw new Error(`Handler '${handler.id}' is already registered. Use force: true to overwrite.`);
|
|
70
|
+
}
|
|
71
|
+
this.handlers.set(handler.id, handler);
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Alias for add()
|
|
75
|
+
*/
|
|
76
|
+
register(handler, options) {
|
|
77
|
+
this.add(handler, options);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Get handler by ID
|
|
81
|
+
*/
|
|
82
|
+
get(id) {
|
|
83
|
+
return this.handlers.get(id);
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Check if handler exists
|
|
87
|
+
*/
|
|
88
|
+
has(id) {
|
|
89
|
+
return this.handlers.has(id);
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Get all handlers
|
|
93
|
+
*/
|
|
94
|
+
getAll() {
|
|
95
|
+
return new Map(this.handlers);
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Get handlers for a specific model
|
|
99
|
+
* @param modelName - Model name (e.g., "Order")
|
|
100
|
+
* @returns Map of field handlers for the model
|
|
101
|
+
*/
|
|
102
|
+
getForModel(modelName) {
|
|
103
|
+
const modelHandlers = new Map();
|
|
104
|
+
const prefix = `${modelName}.`;
|
|
105
|
+
for (const [id, handler] of this.handlers.entries()) {
|
|
106
|
+
if (id.startsWith(prefix)) {
|
|
107
|
+
modelHandlers.set(id, handler);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return modelHandlers;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Unregister a handler
|
|
114
|
+
*/
|
|
115
|
+
unregister(id) {
|
|
116
|
+
return this.handlers.delete(id);
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Clear all handlers (useful for testing)
|
|
120
|
+
*/
|
|
121
|
+
clear() {
|
|
122
|
+
this.handlers.clear();
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Get count of registered handlers
|
|
126
|
+
*/
|
|
127
|
+
count() {
|
|
128
|
+
return this.handlers.size;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
export default CustomFilterHandler;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { Adminizer } from '../Adminizer';
|
|
2
|
+
import { FilterAP } from '../../models/FilterAP';
|
|
3
|
+
import { FilterColumnAP } from '../../models/FilterColumnAP';
|
|
4
|
+
import { UserAP } from '../../models/UserAP';
|
|
5
|
+
/**
|
|
6
|
+
* FilterService - manages filter operations
|
|
7
|
+
*
|
|
8
|
+
* Key responsibilities:
|
|
9
|
+
* - Check if filters are enabled for a model
|
|
10
|
+
* - Apply saved filters to queries
|
|
11
|
+
* - Integrate with ListQueryBuilder
|
|
12
|
+
* - Handle filter access control
|
|
13
|
+
*/
|
|
14
|
+
export declare class FilterService {
|
|
15
|
+
private adminizer;
|
|
16
|
+
constructor(adminizer: Adminizer);
|
|
17
|
+
/**
|
|
18
|
+
* Get ModelResource object by model name
|
|
19
|
+
* Similar to ControllerHelper.findModelResource but without req dependency
|
|
20
|
+
*/
|
|
21
|
+
private getModelResourceByModelName;
|
|
22
|
+
/**
|
|
23
|
+
* Get filter by ID with access control
|
|
24
|
+
* Returns null when filter is not found or user has no access.
|
|
25
|
+
*/
|
|
26
|
+
getFilterById(filterId: string, user: UserAP): Promise<FilterAP | null>;
|
|
27
|
+
/**
|
|
28
|
+
* Get filters for a model accessible by user
|
|
29
|
+
*/
|
|
30
|
+
getFiltersForModel(modelName: string, user: UserAP, options?: {
|
|
31
|
+
includePublic?: boolean;
|
|
32
|
+
includeSystem?: boolean;
|
|
33
|
+
}): Promise<FilterAP[]>;
|
|
34
|
+
/**
|
|
35
|
+
* Check if user can view a filter
|
|
36
|
+
*/
|
|
37
|
+
canViewFilter(filter: FilterAP, user: UserAP): boolean;
|
|
38
|
+
/**
|
|
39
|
+
* Check if user can edit a filter
|
|
40
|
+
*/
|
|
41
|
+
canEditFilter(filter: FilterAP, user: UserAP): boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Check if user can delete a filter
|
|
44
|
+
*/
|
|
45
|
+
canDeleteFilter(filter: FilterAP, user: UserAP): boolean;
|
|
46
|
+
/**
|
|
47
|
+
* Count records matching a filter's conditions
|
|
48
|
+
*
|
|
49
|
+
* @param filter - Filter to count results for
|
|
50
|
+
* @param user - User requesting the count (for access control)
|
|
51
|
+
* @returns Number of matching records, or -1 on error
|
|
52
|
+
*/
|
|
53
|
+
countFilterResults(filter: FilterAP, user: UserAP): Promise<number>;
|
|
54
|
+
/**
|
|
55
|
+
* Create a new filter
|
|
56
|
+
*/
|
|
57
|
+
createFilter(data: Partial<FilterAP>, user: UserAP): Promise<FilterAP>;
|
|
58
|
+
/**
|
|
59
|
+
* Update a filter
|
|
60
|
+
*/
|
|
61
|
+
updateFilter(filterId: string, data: Partial<FilterAP>, user: UserAP): Promise<FilterAP>;
|
|
62
|
+
/**
|
|
63
|
+
* Delete a filter
|
|
64
|
+
*/
|
|
65
|
+
deleteFilter(filterId: string, user: UserAP): Promise<void>;
|
|
66
|
+
/**
|
|
67
|
+
* Get columns for a filter
|
|
68
|
+
*/
|
|
69
|
+
getFilterColumns(filterId: string): Promise<FilterColumnAP[]>;
|
|
70
|
+
/**
|
|
71
|
+
* Update columns for a filter (replace all)
|
|
72
|
+
*/
|
|
73
|
+
updateFilterColumns(filterId: string, columns: Partial<FilterColumnAP>[], user: UserAP): Promise<FilterColumnAP[]>;
|
|
74
|
+
/**
|
|
75
|
+
* Get filter with columns loaded
|
|
76
|
+
*/
|
|
77
|
+
getFilterWithColumns(filterId: string, user: UserAP): Promise<{
|
|
78
|
+
filter: FilterAP | null;
|
|
79
|
+
columns: FilterColumnAP[];
|
|
80
|
+
}>;
|
|
81
|
+
}
|
|
82
|
+
export default FilterService;
|
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
import { Adminizer } from '../Adminizer.js';
|
|
2
|
+
import { DataAccessor } from '../DataAccessor.js';
|
|
3
|
+
import { ListQueryBuilder } from '../list-query-builder/ListQueryBuilder.js';
|
|
4
|
+
import { convertDatetimeConditions } from '../../helpers/filterDatetimeHelper.js';
|
|
5
|
+
/**
|
|
6
|
+
* FilterService - manages filter operations
|
|
7
|
+
*
|
|
8
|
+
* Key responsibilities:
|
|
9
|
+
* - Check if filters are enabled for a model
|
|
10
|
+
* - Apply saved filters to queries
|
|
11
|
+
* - Integrate with ListQueryBuilder
|
|
12
|
+
* - Handle filter access control
|
|
13
|
+
*/
|
|
14
|
+
export class FilterService {
|
|
15
|
+
adminizer;
|
|
16
|
+
constructor(adminizer) {
|
|
17
|
+
this.adminizer = adminizer;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Get ModelResource object by model name
|
|
21
|
+
* Similar to ControllerHelper.findModelResource but without req dependency
|
|
22
|
+
*/
|
|
23
|
+
getModelResourceByModelName(modelName) {
|
|
24
|
+
const models = this.adminizer.config.models;
|
|
25
|
+
if (!models) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
// Find config (case-insensitive)
|
|
29
|
+
const foundKey = Object.keys(models).find(key => key.toLowerCase() === modelName.toLowerCase());
|
|
30
|
+
if (!foundKey) {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
const config = models[foundKey];
|
|
34
|
+
if (!config || typeof config === 'boolean') {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
// Get AbstractModel
|
|
38
|
+
const model = this.adminizer.modelHandler.model.get(config.model);
|
|
39
|
+
if (!model) {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
return {
|
|
43
|
+
name: foundKey,
|
|
44
|
+
config,
|
|
45
|
+
model,
|
|
46
|
+
uri: `${this.adminizer.config.routePrefix}/model/${foundKey}`
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Get filter by ID with access control
|
|
51
|
+
* Returns null when filter is not found or user has no access.
|
|
52
|
+
*/
|
|
53
|
+
async getFilterById(filterId, user) {
|
|
54
|
+
const filterModel = this.adminizer.modelHandler.internal('filters').get('FilterAP');
|
|
55
|
+
const filter = await filterModel.findOne({ where: { id: filterId } });
|
|
56
|
+
if (!filter) {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
const filterAP = filter;
|
|
60
|
+
if (!this.canViewFilter(filterAP, user)) {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
return filterAP;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Get filters for a model accessible by user
|
|
67
|
+
*/
|
|
68
|
+
async getFiltersForModel(modelName, user, options) {
|
|
69
|
+
const filterModel = this.adminizer.modelHandler.internal('filters').get('FilterAP');
|
|
70
|
+
const filters = [];
|
|
71
|
+
// Build base criteria
|
|
72
|
+
const baseCriteria = { modelName };
|
|
73
|
+
// 1. Get user's own filters
|
|
74
|
+
const ownFilters = await filterModel.find({
|
|
75
|
+
where: {
|
|
76
|
+
...baseCriteria,
|
|
77
|
+
ownerId: user.id
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
filters.push(...ownFilters);
|
|
81
|
+
// 2. Get public filters (if requested)
|
|
82
|
+
if (options?.includePublic !== false) {
|
|
83
|
+
const publicFilters = await filterModel.find({
|
|
84
|
+
where: {
|
|
85
|
+
...baseCriteria,
|
|
86
|
+
visibility: 'public'
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
// Deduplicate
|
|
90
|
+
for (const filter of publicFilters) {
|
|
91
|
+
if (!filters.find(f => f.id === filter.id)) {
|
|
92
|
+
filters.push(filter);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
// 3. Get group filters if user has groups
|
|
97
|
+
if (user.groups && user.groups.length > 0) {
|
|
98
|
+
const groupIds = user.groups.map(g => g.id);
|
|
99
|
+
const groupFilters = await filterModel.find({
|
|
100
|
+
where: {
|
|
101
|
+
...baseCriteria,
|
|
102
|
+
visibility: 'groups'
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
// Check if user's groups intersect with filter's groups
|
|
106
|
+
for (const filter of groupFilters) {
|
|
107
|
+
if (filter.groupIds && filter.groupIds.some(gid => groupIds.includes(gid))) {
|
|
108
|
+
if (!filters.find(f => f.id === filter.id)) {
|
|
109
|
+
filters.push(filter);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
// 4. Admin sees all filters
|
|
115
|
+
if (user.isAdministrator) {
|
|
116
|
+
const allFilters = await filterModel.find({ where: baseCriteria });
|
|
117
|
+
for (const filter of allFilters) {
|
|
118
|
+
if (!filters.find(f => f.id === filter.id)) {
|
|
119
|
+
filters.push(filter);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
if (!options?.includeSystem) {
|
|
124
|
+
return filters.filter(f => f.visibility !== 'system');
|
|
125
|
+
}
|
|
126
|
+
return filters;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Check if user can view a filter
|
|
130
|
+
*/
|
|
131
|
+
canViewFilter(filter, user) {
|
|
132
|
+
// Admin can view all
|
|
133
|
+
if (user.isAdministrator) {
|
|
134
|
+
return true;
|
|
135
|
+
}
|
|
136
|
+
// Owner can view
|
|
137
|
+
if (filter.ownerId === user.id) {
|
|
138
|
+
return true;
|
|
139
|
+
}
|
|
140
|
+
// Public filters
|
|
141
|
+
if (filter.visibility === 'public') {
|
|
142
|
+
return true;
|
|
143
|
+
}
|
|
144
|
+
// System filters (accessible via API)
|
|
145
|
+
if (filter.visibility === 'system') {
|
|
146
|
+
return true;
|
|
147
|
+
}
|
|
148
|
+
// Group filters
|
|
149
|
+
if (filter.visibility === 'groups' && filter.groupIds && user.groups) {
|
|
150
|
+
const userGroupIds = user.groups.map(g => g.id);
|
|
151
|
+
return filter.groupIds.some(gid => userGroupIds.includes(gid));
|
|
152
|
+
}
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Check if user can edit a filter
|
|
157
|
+
*/
|
|
158
|
+
canEditFilter(filter, user) {
|
|
159
|
+
// Admin can edit all
|
|
160
|
+
if (user.isAdministrator) {
|
|
161
|
+
return true;
|
|
162
|
+
}
|
|
163
|
+
// Only owner can edit
|
|
164
|
+
return filter.ownerId === user.id;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Check if user can delete a filter
|
|
168
|
+
*/
|
|
169
|
+
canDeleteFilter(filter, user) {
|
|
170
|
+
return this.canEditFilter(filter, user);
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Count records matching a filter's conditions
|
|
174
|
+
*
|
|
175
|
+
* @param filter - Filter to count results for
|
|
176
|
+
* @param user - User requesting the count (for access control)
|
|
177
|
+
* @returns Number of matching records, or -1 on error
|
|
178
|
+
*/
|
|
179
|
+
async countFilterResults(filter, user) {
|
|
180
|
+
try {
|
|
181
|
+
const modelResource = this.getModelResourceByModelName(filter.modelName);
|
|
182
|
+
if (!modelResource || !modelResource.model) {
|
|
183
|
+
Adminizer.log.warn(`FilterService.countFilterResults: Model '${filter.modelName}' not found`);
|
|
184
|
+
return -1;
|
|
185
|
+
}
|
|
186
|
+
const dataAccessor = new DataAccessor(this.adminizer, user, modelResource, 'list');
|
|
187
|
+
const fields = dataAccessor.getFieldsConfig();
|
|
188
|
+
// Convert datetime conditions to date ranges
|
|
189
|
+
const convertedConditions = convertDatetimeConditions(filter.conditions || []);
|
|
190
|
+
const queryParams = {
|
|
191
|
+
page: 1,
|
|
192
|
+
limit: 1, // We only need count
|
|
193
|
+
filters: convertedConditions
|
|
194
|
+
};
|
|
195
|
+
const listQueryBuilder = new ListQueryBuilder(modelResource.model, fields, dataAccessor, this.adminizer.customFilterHandler);
|
|
196
|
+
const result = await listQueryBuilder.execute(queryParams);
|
|
197
|
+
return result.filtered;
|
|
198
|
+
}
|
|
199
|
+
catch (error) {
|
|
200
|
+
Adminizer.log.error(`FilterService.countFilterResults error for filter '${filter.id}':`, error);
|
|
201
|
+
return -1;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Create a new filter
|
|
206
|
+
*/
|
|
207
|
+
async createFilter(data, user) {
|
|
208
|
+
const filterModel = this.adminizer.modelHandler.internal('filters').get('FilterAP');
|
|
209
|
+
// Generate UUID if not provided
|
|
210
|
+
if (!data.id) {
|
|
211
|
+
data.id = crypto.randomUUID();
|
|
212
|
+
}
|
|
213
|
+
// Set owner
|
|
214
|
+
data.ownerId = user.id;
|
|
215
|
+
// Set defaults
|
|
216
|
+
data.visibility = data.visibility || 'private';
|
|
217
|
+
data.version = data.version || 1;
|
|
218
|
+
data.apiEnabled = data.apiEnabled || false;
|
|
219
|
+
data.conditions = data.conditions || [];
|
|
220
|
+
return await filterModel.create(data);
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Update a filter
|
|
224
|
+
*/
|
|
225
|
+
async updateFilter(filterId, data, user) {
|
|
226
|
+
const filter = await this.getFilterById(filterId, user);
|
|
227
|
+
if (!filter) {
|
|
228
|
+
throw new Error(`Filter '${filterId}' not found`);
|
|
229
|
+
}
|
|
230
|
+
if (!this.canEditFilter(filter, user)) {
|
|
231
|
+
throw new Error('Access denied');
|
|
232
|
+
}
|
|
233
|
+
const filterModel = this.adminizer.modelHandler.internal('filters').get('FilterAP');
|
|
234
|
+
// Don't allow changing owner
|
|
235
|
+
delete data.ownerId;
|
|
236
|
+
delete data.id;
|
|
237
|
+
await filterModel.updateOne({ where: { id: filterId } }, data);
|
|
238
|
+
const updated = await this.getFilterById(filterId, user);
|
|
239
|
+
if (!updated) {
|
|
240
|
+
throw new Error(`Filter '${filterId}' not found after update`);
|
|
241
|
+
}
|
|
242
|
+
return updated;
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Delete a filter
|
|
246
|
+
*/
|
|
247
|
+
async deleteFilter(filterId, user) {
|
|
248
|
+
const filter = await this.getFilterById(filterId, user);
|
|
249
|
+
if (!filter) {
|
|
250
|
+
throw new Error(`Filter '${filterId}' not found`);
|
|
251
|
+
}
|
|
252
|
+
if (!this.canDeleteFilter(filter, user)) {
|
|
253
|
+
throw new Error('Access denied');
|
|
254
|
+
}
|
|
255
|
+
// Delete columns first - find by filter association and delete by ID
|
|
256
|
+
const columnModel = this.adminizer.modelHandler.internal('filters').get('FilterColumnAP');
|
|
257
|
+
if (columnModel) {
|
|
258
|
+
// Find columns for this filter
|
|
259
|
+
const columns = await columnModel.find({ where: { filter: filterId } });
|
|
260
|
+
// Delete each column by ID to avoid cascade issues
|
|
261
|
+
for (const column of columns) {
|
|
262
|
+
await columnModel.destroyOne({ where: { id: column.id } });
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
// Delete filter by ID only
|
|
266
|
+
const filterModel = this.adminizer.modelHandler.internal('filters').get('FilterAP');
|
|
267
|
+
if (filterModel) {
|
|
268
|
+
// Use destroyOne with explicit ID to avoid cascade
|
|
269
|
+
await filterModel.destroyOne({ where: { id: filterId } });
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Get columns for a filter
|
|
274
|
+
*/
|
|
275
|
+
async getFilterColumns(filterId) {
|
|
276
|
+
const columnModel = this.adminizer.modelHandler.internal('filters').get('FilterColumnAP');
|
|
277
|
+
const columns = await columnModel.find({ where: { filter: filterId } });
|
|
278
|
+
// Sort by order
|
|
279
|
+
return columns.sort((a, b) => (a.order || 0) - (b.order || 0));
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Update columns for a filter (replace all)
|
|
283
|
+
*/
|
|
284
|
+
async updateFilterColumns(filterId, columns, user) {
|
|
285
|
+
const filter = await this.getFilterById(filterId, user);
|
|
286
|
+
if (!filter) {
|
|
287
|
+
throw new Error(`Filter '${filterId}' not found`);
|
|
288
|
+
}
|
|
289
|
+
if (!this.canEditFilter(filter, user)) {
|
|
290
|
+
throw new Error('Access denied');
|
|
291
|
+
}
|
|
292
|
+
const columnModel = this.adminizer.modelHandler.internal('filters').get('FilterColumnAP');
|
|
293
|
+
// Delete existing columns
|
|
294
|
+
await columnModel.destroy({ where: { filter: filterId } });
|
|
295
|
+
// Create new columns
|
|
296
|
+
if (columns.length > 0) {
|
|
297
|
+
for (let i = 0; i < columns.length; i++) {
|
|
298
|
+
const col = columns[i];
|
|
299
|
+
await columnModel.create({
|
|
300
|
+
filter: filterId,
|
|
301
|
+
fieldName: col.fieldName,
|
|
302
|
+
order: col.order ?? i
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
return this.getFilterColumns(filterId);
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Get filter with columns loaded
|
|
310
|
+
*/
|
|
311
|
+
async getFilterWithColumns(filterId, user) {
|
|
312
|
+
const filter = await this.getFilterById(filterId, user);
|
|
313
|
+
if (!filter) {
|
|
314
|
+
return { filter: null, columns: [] };
|
|
315
|
+
}
|
|
316
|
+
if (!this.canViewFilter(filter, user)) {
|
|
317
|
+
return { filter: null, columns: [] };
|
|
318
|
+
}
|
|
319
|
+
const columns = await this.getFilterColumns(filterId);
|
|
320
|
+
return { filter, columns };
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
export default FilterService;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { FilterService, default as FilterServiceDefault } from './FilterService';
|
|
2
|
+
export { CustomFilterHandler, default as CustomFilterHandlerDefault } from './CustomFilterHandler';
|
|
3
|
+
export { AbstractCustomFilter } from './CustomFilterHandler';
|
|
4
|
+
export type { FilterCustomFieldCondition, RegisterOptions, FilterCustomFieldInputConfig, FilterCustomFieldInputDefinition, FilterCustomFieldInputType } from './CustomFilterHandler';
|
|
5
|
+
export { ConditionValidator, default as ConditionValidatorDefault } from './ConditionValidator';
|
|
6
|
+
export type { ValidationResult, ValidationError, FieldConfig, SecurityEvent, SecurityEventType } from './ConditionValidator';
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { FilterService, default as FilterServiceDefault } from './FilterService.js';
|
|
2
|
+
export { CustomFilterHandler, default as CustomFilterHandlerDefault } from './CustomFilterHandler.js';
|
|
3
|
+
export { AbstractCustomFilter } from './CustomFilterHandler.js';
|
|
4
|
+
export { ConditionValidator, default as ConditionValidatorDefault } from './ConditionValidator.js';
|
|
@@ -3,7 +3,7 @@ import { UserAP } from "../../models/UserAP";
|
|
|
3
3
|
import { Adminizer } from "../Adminizer";
|
|
4
4
|
import { Fields } from "../../helpers/fieldsHelper";
|
|
5
5
|
import { ActionType } from "../../interfaces/adminpanelConfig";
|
|
6
|
-
import {
|
|
6
|
+
import { ModelResource } from "../../interfaces/types";
|
|
7
7
|
/**
|
|
8
8
|
* Abstract base class for handling history operations in the AdminPanel.
|
|
9
9
|
* Provides common methods and structure for retrieving, filtering, and formatting historical data.
|
|
@@ -33,6 +33,7 @@ export declare abstract class AbstractHistoryAdapter {
|
|
|
33
33
|
* @param adminizer - The main Adminizer instance.
|
|
34
34
|
*/
|
|
35
35
|
protected constructor(adminizer: Adminizer);
|
|
36
|
+
private internalModel;
|
|
36
37
|
/**
|
|
37
38
|
* Registers access rights for this history adapter.
|
|
38
39
|
* Called during construction with a slight delay to ensure Adminizer is ready.
|
|
@@ -139,14 +140,14 @@ export declare abstract class AbstractHistoryAdapter {
|
|
|
139
140
|
*/
|
|
140
141
|
protected getModelRelationsHistory<T extends string | number>(model: string, ids: T[]): Promise<T[]>;
|
|
141
142
|
/**
|
|
142
|
-
* Constructs an
|
|
143
|
+
* Constructs an ModelResource object from a history record.
|
|
143
144
|
* Used to access model configuration and instance.
|
|
144
145
|
*
|
|
145
146
|
* @param history - The history record.
|
|
146
|
-
* @returns
|
|
147
|
+
* @returns ModelResource object with name, URI, model instance, and config.
|
|
147
148
|
* @protected
|
|
148
149
|
*/
|
|
149
|
-
protected
|
|
150
|
+
protected findModelResource(history: HistoryActionsAP): ModelResource;
|
|
150
151
|
/**
|
|
151
152
|
* Loads associated records for association-type fields.
|
|
152
153
|
* Populates `records` array in field config for widget rendering.
|