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,73 @@
|
|
|
1
|
+
import { FeedService } from "../services/FeedService.js";
|
|
2
|
+
import { Adminizer } from "../lib/Adminizer.js";
|
|
3
|
+
/**
|
|
4
|
+
* Public feed controller — exports data by apiKey with userKey authentication
|
|
5
|
+
* GET /adminizer/api/feed/:apiKey.json?userKey=xxx
|
|
6
|
+
* GET /adminizer/api/feed/:apiKey.xml?userKey=xxx
|
|
7
|
+
*/
|
|
8
|
+
export default async function feedController(req, res) {
|
|
9
|
+
const { apiKey, format } = req.params;
|
|
10
|
+
const userKey = req.query.userKey;
|
|
11
|
+
// Validate format
|
|
12
|
+
const exportFormat = (format || 'json').toLowerCase();
|
|
13
|
+
if (!['json', 'xml'].includes(exportFormat)) {
|
|
14
|
+
return res.status(400).json({ error: 'Invalid format. Supported: json, xml' });
|
|
15
|
+
}
|
|
16
|
+
if (!apiKey) {
|
|
17
|
+
return res.status(400).json({ error: 'apiKey is required' });
|
|
18
|
+
}
|
|
19
|
+
if (!userKey) {
|
|
20
|
+
return res.status(401).json({ error: 'userKey is required' });
|
|
21
|
+
}
|
|
22
|
+
try {
|
|
23
|
+
const feedService = new FeedService(req.adminizer);
|
|
24
|
+
// Find filter by apiKey
|
|
25
|
+
Adminizer.log.debug(`Feed: looking for filter with apiKey=${apiKey}`);
|
|
26
|
+
const filter = await feedService.findFilterByApiKey(apiKey);
|
|
27
|
+
if (!filter) {
|
|
28
|
+
return res.status(404).json({
|
|
29
|
+
error: 'Filter not found or API access is disabled',
|
|
30
|
+
message: 'Check your apiKey or ensure API access is enabled for this filter'
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
// Authenticate user by userKey
|
|
34
|
+
if (!req.adminizer.config.auth.enable) {
|
|
35
|
+
return res.status(403).json({ error: 'Auth is required for feed access' });
|
|
36
|
+
}
|
|
37
|
+
const user = await req.adminizer.modelHandler
|
|
38
|
+
.internal("feed")
|
|
39
|
+
.get("UserAP")
|
|
40
|
+
.findOne({ where: { apiKey: userKey } });
|
|
41
|
+
if (!user) {
|
|
42
|
+
return res.status(403).json({ error: 'Invalid userKey' });
|
|
43
|
+
}
|
|
44
|
+
Adminizer.log.info(`Feed access: filter "${filter.name}" (${filter.modelName}) by user ${user.login} via ${exportFormat}`);
|
|
45
|
+
Adminizer.log.debug(`Feed: filter conditions type=${typeof filter.conditions}, isArray=${Array.isArray(filter.conditions)}`);
|
|
46
|
+
// Generate feed based on format
|
|
47
|
+
if (exportFormat === 'json') {
|
|
48
|
+
const data = await feedService.generateJsonFeed(filter, req.adminizer, user);
|
|
49
|
+
res.setHeader('Content-Type', 'application/json; charset=utf-8');
|
|
50
|
+
// inline — отображать в браузере вместо скачивания
|
|
51
|
+
res.setHeader('Content-Disposition', `inline; filename="${filter.modelName}_feed.json"`);
|
|
52
|
+
return res.json(data);
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
const xml = await feedService.generateAtomFeed(filter, req.adminizer, user);
|
|
56
|
+
res.setHeader('Content-Type', 'application/atom+xml; charset=utf-8');
|
|
57
|
+
// inline — отображать в браузере вместо скачивания
|
|
58
|
+
res.setHeader('Content-Disposition', `inline; filename="${filter.modelName}_feed.xml"`);
|
|
59
|
+
return res.send(xml);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
console.error('Feed export error:', error);
|
|
64
|
+
console.error('Stack:', error?.stack);
|
|
65
|
+
if (error?.cause) {
|
|
66
|
+
console.error('Cause:', error.cause);
|
|
67
|
+
}
|
|
68
|
+
return res.status(500).json({
|
|
69
|
+
error: 'Failed to generate feed',
|
|
70
|
+
message: error?.message || 'Unknown error'
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { Adminizer } from '../../lib/Adminizer';
|
|
2
|
-
export declare function bindFeedbackController(adminizer: Adminizer,
|
|
2
|
+
export declare function bindFeedbackController(adminizer: Adminizer, middlewares: MiddlewareType[]): void;
|
|
@@ -1,19 +1,17 @@
|
|
|
1
1
|
import multer from 'multer';
|
|
2
2
|
import { Adminizer } from '../../lib/Adminizer.js';
|
|
3
|
+
import { requireAuthAPI } from '../../policies/authPolicies.js';
|
|
4
|
+
import { bindWithMiddlewares } from '../../system/routePolicies.js';
|
|
3
5
|
const MAX_FILE_SIZE = 5 * 1024 * 1024; // 5 MB
|
|
4
6
|
const upload = multer({
|
|
5
7
|
storage: multer.memoryStorage(),
|
|
6
8
|
limits: { fileSize: MAX_FILE_SIZE },
|
|
7
9
|
});
|
|
8
|
-
export function bindFeedbackController(adminizer,
|
|
9
|
-
const { app, config
|
|
10
|
+
export function bindFeedbackController(adminizer, middlewares) {
|
|
11
|
+
const { app, config } = adminizer;
|
|
10
12
|
const prefix = config.routePrefix;
|
|
11
13
|
const uploadMiddleware = upload.array('files', 10);
|
|
12
14
|
const handler = async (req, res) => {
|
|
13
|
-
if (adminizer.config.auth?.enable && !req.user) {
|
|
14
|
-
res.status(401).json({ error: req.i18n.__('Unauthorized') });
|
|
15
|
-
return;
|
|
16
|
-
}
|
|
17
15
|
uploadMiddleware(req, res, async (err) => {
|
|
18
16
|
if (err) {
|
|
19
17
|
if (err.code === 'LIMIT_FILE_SIZE') {
|
|
@@ -63,5 +61,5 @@ export function bindFeedbackController(adminizer, policies) {
|
|
|
63
61
|
}
|
|
64
62
|
});
|
|
65
63
|
};
|
|
66
|
-
app.post(`${prefix}/api/feedback`, ...
|
|
64
|
+
app.post(`${prefix}/api/feedback`, ...bindWithMiddlewares(adminizer, middlewares, handler, [requireAuthAPI()]));
|
|
67
65
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GET /adminizer/model/:model/columns
|
|
3
|
+
* Returns available columns for the model (considering DataAccessor rights)
|
|
4
|
+
* Also returns columns for a specific filter if filterId is provided
|
|
5
|
+
*/
|
|
6
|
+
export declare function getModelColumns(req: ReqType, res: ResType): Promise<ResType>;
|
|
7
|
+
/**
|
|
8
|
+
* POST /adminizer/model/:model/filter/:filterId/columns
|
|
9
|
+
* Update column configuration for a specific filter
|
|
10
|
+
*/
|
|
11
|
+
export declare function updateFilterColumns(req: ReqType, res: ResType): Promise<ResType>;
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { ControllerHelper } from "../../helpers/controllerHelper.js";
|
|
2
|
+
import { DataAccessor } from "../../lib/DataAccessor.js";
|
|
3
|
+
import { FilterService } from "../../lib/filters/FilterService.js";
|
|
4
|
+
/**
|
|
5
|
+
* GET /adminizer/model/:model/columns
|
|
6
|
+
* Returns available columns for the model (considering DataAccessor rights)
|
|
7
|
+
* Also returns columns for a specific filter if filterId is provided
|
|
8
|
+
*/
|
|
9
|
+
export async function getModelColumns(req, res) {
|
|
10
|
+
const modelResource = ControllerHelper.findModelResource(req);
|
|
11
|
+
if (!modelResource.model) {
|
|
12
|
+
return res.status(404).send({ error: req.i18n.__('Model not found') });
|
|
13
|
+
}
|
|
14
|
+
// Get available fields from DataAccessor (respects user permissions)
|
|
15
|
+
const dataAccessor = new DataAccessor(req.adminizer, req.user, modelResource, "list");
|
|
16
|
+
const fields = dataAccessor.getFieldsConfig();
|
|
17
|
+
// Convert fields to column format
|
|
18
|
+
const availableColumns = Object.entries(fields).map(([fieldName, field]) => {
|
|
19
|
+
// Get label and type from config
|
|
20
|
+
const config = typeof field.config === 'object' ? field.config : null;
|
|
21
|
+
const label = config?.title || fieldName;
|
|
22
|
+
const type = config?.type || 'string';
|
|
23
|
+
return {
|
|
24
|
+
fieldName,
|
|
25
|
+
label,
|
|
26
|
+
type,
|
|
27
|
+
order: 0
|
|
28
|
+
};
|
|
29
|
+
});
|
|
30
|
+
// If filterId provided, also return filter's column configuration
|
|
31
|
+
const filterId = req.query.filterId ? req.query.filterId.toString() : undefined;
|
|
32
|
+
let filterColumns = [];
|
|
33
|
+
if (filterId && filterId !== 'temporary') {
|
|
34
|
+
try {
|
|
35
|
+
const filterService = new FilterService(req.adminizer);
|
|
36
|
+
const result = await filterService.getFilterWithColumns(filterId, req.user);
|
|
37
|
+
if (result.filter) {
|
|
38
|
+
filterColumns = result.columns;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
catch (err) {
|
|
42
|
+
// Ignore errors, return available columns without filter config
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
else if (filterId === 'temporary') {
|
|
46
|
+
// Get temporary filter columns from session
|
|
47
|
+
if (req.session?.temporaryFilters?.[modelResource.name]?.columns) {
|
|
48
|
+
const tempColumns = req.session.temporaryFilters[modelResource.name].columns;
|
|
49
|
+
filterColumns = tempColumns.map((col, index) => ({
|
|
50
|
+
id: index + 1,
|
|
51
|
+
filter: 'temporary',
|
|
52
|
+
fieldName: col.fieldName,
|
|
53
|
+
order: col.order !== undefined ? col.order : index
|
|
54
|
+
}));
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return res.json({
|
|
58
|
+
model: modelResource.name,
|
|
59
|
+
availableColumns,
|
|
60
|
+
filterColumns: filterColumns,
|
|
61
|
+
hasFilterConfig: filterColumns.length > 0
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* POST /adminizer/model/:model/filter/:filterId/columns
|
|
66
|
+
* Update column configuration for a specific filter
|
|
67
|
+
*/
|
|
68
|
+
export async function updateFilterColumns(req, res) {
|
|
69
|
+
const modelResource = ControllerHelper.findModelResource(req);
|
|
70
|
+
if (!modelResource.model) {
|
|
71
|
+
return res.status(404).send({ error: req.i18n.__('Model not found') });
|
|
72
|
+
}
|
|
73
|
+
const filterId = req.params.filterId ? String(req.params.filterId) : undefined;
|
|
74
|
+
if (!filterId) {
|
|
75
|
+
return res.status(400).send({ error: req.i18n.__('Filter ID is required') });
|
|
76
|
+
}
|
|
77
|
+
const { columns } = req.body;
|
|
78
|
+
if (!columns || !Array.isArray(columns)) {
|
|
79
|
+
return res.status(400).send({ error: req.i18n.__('Columns array is required') });
|
|
80
|
+
}
|
|
81
|
+
const filterService = new FilterService(req.adminizer);
|
|
82
|
+
try {
|
|
83
|
+
// Validate filter exists and user has access
|
|
84
|
+
const filter = await filterService.getFilterById(filterId, req.user);
|
|
85
|
+
if (!filter) {
|
|
86
|
+
return res.status(404).send({ error: req.i18n.__('Filter not found or access denied') });
|
|
87
|
+
}
|
|
88
|
+
// Convert frontend column format to FilterColumnAP format
|
|
89
|
+
const filterColumns = columns.map((col, index) => ({
|
|
90
|
+
fieldName: col.fieldName,
|
|
91
|
+
order: col.order !== undefined ? col.order : index
|
|
92
|
+
}));
|
|
93
|
+
// Save columns
|
|
94
|
+
const result = await filterService.updateFilterColumns(filterId, filterColumns, req.user);
|
|
95
|
+
return res.json({
|
|
96
|
+
success: true,
|
|
97
|
+
columns: result
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
return res.status(500).json({
|
|
102
|
+
error: req.i18n.__('Failed to update filter columns'),
|
|
103
|
+
message: error.message
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Get filter fields for ANY model
|
|
3
|
+
*
|
|
4
|
+
* Takes fields from DataAccessor (merged config + access rights)
|
|
5
|
+
* Excludes: system fields, complex JSON fields, model-level filters.excludeFromFilters
|
|
6
|
+
* For Sequelize, includes simple relation filters (association/association-many + simple related fields)
|
|
7
|
+
*
|
|
8
|
+
* This controller is universal - works with any model
|
|
9
|
+
*/
|
|
10
|
+
export default function filterFields(req: ReqType, res: ResType): Promise<ResType>;
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { ControllerHelper } from "../../helpers/controllerHelper.js";
|
|
2
|
+
import { DataAccessor } from "../../lib/DataAccessor.js";
|
|
3
|
+
function getFieldType(field) {
|
|
4
|
+
const cfg = typeof field.config === 'object' && field.config !== null ? field.config : null;
|
|
5
|
+
return (cfg?.type || field.model?.type || 'string');
|
|
6
|
+
}
|
|
7
|
+
function getFieldLabel(req, fieldName, field) {
|
|
8
|
+
const cfg = typeof field.config === 'object' && field.config !== null ? field.config : null;
|
|
9
|
+
return req.i18n.__(cfg?.title || fieldName) || fieldName;
|
|
10
|
+
}
|
|
11
|
+
function getFieldOptions(req, field) {
|
|
12
|
+
const cfg = typeof field.config === 'object' && field.config !== null ? field.config : null;
|
|
13
|
+
const type = (cfg?.type || field.model?.type);
|
|
14
|
+
const isIn = cfg?.isIn;
|
|
15
|
+
if ((type !== 'select' && type !== 'select-many') || !isIn) {
|
|
16
|
+
return undefined;
|
|
17
|
+
}
|
|
18
|
+
if (Array.isArray(isIn)) {
|
|
19
|
+
return isIn.map((val) => ({ value: val, label: String(val) }));
|
|
20
|
+
}
|
|
21
|
+
if (typeof isIn === 'object') {
|
|
22
|
+
return Object.entries(isIn).map(([value, label]) => ({
|
|
23
|
+
value,
|
|
24
|
+
label: req.i18n.__(String(label)) || String(label),
|
|
25
|
+
}));
|
|
26
|
+
}
|
|
27
|
+
return undefined;
|
|
28
|
+
}
|
|
29
|
+
function isSimpleFilterField(type) {
|
|
30
|
+
return ![
|
|
31
|
+
'association',
|
|
32
|
+
'association-many',
|
|
33
|
+
'json',
|
|
34
|
+
'jsoneditor',
|
|
35
|
+
'object',
|
|
36
|
+
'array',
|
|
37
|
+
].includes(type);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Get filter fields for ANY model
|
|
41
|
+
*
|
|
42
|
+
* Takes fields from DataAccessor (merged config + access rights)
|
|
43
|
+
* Excludes: system fields, complex JSON fields, model-level filters.excludeFromFilters
|
|
44
|
+
* For Sequelize, includes simple relation filters (association/association-many + simple related fields)
|
|
45
|
+
*
|
|
46
|
+
* This controller is universal - works with any model
|
|
47
|
+
*/
|
|
48
|
+
export default async function filterFields(req, res) {
|
|
49
|
+
const modelResource = ControllerHelper.findModelResource(req);
|
|
50
|
+
if (!modelResource.model) {
|
|
51
|
+
return res.status(404).send({ error: req.i18n.__('Model not found') });
|
|
52
|
+
}
|
|
53
|
+
// Get fields via DataAccessor (respects access rights and merged field config)
|
|
54
|
+
const dataAccessor = new DataAccessor(req.adminizer, req.user, modelResource, "list");
|
|
55
|
+
const fields = dataAccessor.getFieldsConfig() || {};
|
|
56
|
+
// Get filter config for this model (optional)
|
|
57
|
+
// Preferred: model-level `models.<Model>.filters`; fallback: legacy top-level `modelFilters.<Model>`
|
|
58
|
+
const filterConfig = modelResource.config?.filters ?? req.adminizer.config.modelFilters?.[modelResource.name];
|
|
59
|
+
const filterFields = [];
|
|
60
|
+
for (const [fieldName, field] of Object.entries(fields)) {
|
|
61
|
+
const type = getFieldType(field);
|
|
62
|
+
const cfg = typeof field.config === 'object' && field.config !== null ? field.config : null;
|
|
63
|
+
const customFilterHandlerId = cfg?.customFilter?.handlerId
|
|
64
|
+
? String(cfg.customFilter.handlerId)
|
|
65
|
+
: undefined;
|
|
66
|
+
const customFilterHandler = customFilterHandlerId
|
|
67
|
+
? req.adminizer.customFilterHandler?.get(customFilterHandlerId)
|
|
68
|
+
: undefined;
|
|
69
|
+
const customFilter = customFilterHandlerId
|
|
70
|
+
? {
|
|
71
|
+
handlerId: customFilterHandlerId,
|
|
72
|
+
conditionLabel: customFilterHandler?.name
|
|
73
|
+
|| (cfg?.customFilter?.label ? String(cfg.customFilter.label) : undefined)
|
|
74
|
+
|| customFilterHandlerId,
|
|
75
|
+
inputConfig: customFilterHandler?.inputConfig,
|
|
76
|
+
}
|
|
77
|
+
: null;
|
|
78
|
+
// Skip model-specific excluded fields
|
|
79
|
+
if (filterConfig?.excludeFromFilters?.includes(fieldName)) {
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
// Skip system fields (universal rule for all models)
|
|
83
|
+
if (fieldName === 'id' || fieldName === 'ownerId' || fieldName === 'updatedAt') {
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
const isRelationField = type === 'association' || type === 'association-many';
|
|
87
|
+
// Base (non-relation) fields
|
|
88
|
+
if (!isRelationField) {
|
|
89
|
+
if (!isSimpleFilterField(type) && !customFilter) {
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
filterFields.push({
|
|
93
|
+
id: fieldName,
|
|
94
|
+
label: getFieldLabel(req, fieldName, field),
|
|
95
|
+
type,
|
|
96
|
+
isCustomFilter: Boolean(customFilter),
|
|
97
|
+
customFilterHandlerId: customFilter?.handlerId,
|
|
98
|
+
customFilterConditionLabel: customFilter?.conditionLabel,
|
|
99
|
+
customFilterInputConfig: customFilter?.inputConfig,
|
|
100
|
+
required: Boolean((typeof field.config === 'object' && field.config !== null ? field.config.required : false)),
|
|
101
|
+
options: getFieldOptions(req, field),
|
|
102
|
+
});
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
const ormType = req.adminizer.ormAdapters?.[0]?.ormType;
|
|
106
|
+
const isSequelize = ormType === 'sequelize';
|
|
107
|
+
// Relations in filter UI are supported only for Sequelize
|
|
108
|
+
if (!isSequelize) {
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
// Include relation with only simple fields of related model
|
|
112
|
+
const relationFields = Object.entries(field.populated || {})
|
|
113
|
+
.map(([relatedFieldName, relatedField]) => {
|
|
114
|
+
const relatedType = getFieldType(relatedField);
|
|
115
|
+
if (!isSimpleFilterField(relatedType)) {
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
return {
|
|
119
|
+
id: relatedFieldName,
|
|
120
|
+
label: getFieldLabel(req, relatedFieldName, relatedField),
|
|
121
|
+
type: relatedType,
|
|
122
|
+
options: getFieldOptions(req, relatedField),
|
|
123
|
+
};
|
|
124
|
+
})
|
|
125
|
+
.filter((item) => !!item);
|
|
126
|
+
if (relationFields.length === 0) {
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
filterFields.push({
|
|
130
|
+
id: fieldName,
|
|
131
|
+
label: getFieldLabel(req, fieldName, field),
|
|
132
|
+
type,
|
|
133
|
+
isRelation: true,
|
|
134
|
+
relationFields,
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
return res.json({
|
|
138
|
+
model: modelResource.name,
|
|
139
|
+
fields: filterFields,
|
|
140
|
+
});
|
|
141
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GET /adminizer/api/all-user-filters
|
|
3
|
+
* Returns all filters accessible to the current user across all models.
|
|
4
|
+
* Supports search by name, filter by modelName, and pagination.
|
|
5
|
+
*/
|
|
6
|
+
export declare function getAllUserFilters(req: ReqType, res: ResType): Promise<ResType>;
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { FilterService } from "../../lib/filters/FilterService.js";
|
|
2
|
+
import { Adminizer } from "../../lib/Adminizer.js";
|
|
3
|
+
/**
|
|
4
|
+
* GET /adminizer/api/all-user-filters
|
|
5
|
+
* Returns all filters accessible to the current user across all models.
|
|
6
|
+
* Supports search by name, filter by modelName, and pagination.
|
|
7
|
+
*/
|
|
8
|
+
export async function getAllUserFilters(req, res) {
|
|
9
|
+
const filterService = new FilterService(req.adminizer);
|
|
10
|
+
const userModel = req.adminizer.modelHandler.model.get('userap');
|
|
11
|
+
const groupModel = req.adminizer.modelHandler.model.get('groupap');
|
|
12
|
+
// Cache for group names: { groupId: groupName }
|
|
13
|
+
const groupNamesCache = {};
|
|
14
|
+
const getGroupName = async (groupId) => {
|
|
15
|
+
if (groupNamesCache[groupId])
|
|
16
|
+
return groupNamesCache[groupId];
|
|
17
|
+
try {
|
|
18
|
+
const group = await groupModel?.['_findOne']({ where: { id: groupId } });
|
|
19
|
+
if (group) {
|
|
20
|
+
groupNamesCache[groupId] = group.name || String(groupId);
|
|
21
|
+
return groupNamesCache[groupId];
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
catch (e) { /* ignore */ }
|
|
25
|
+
groupNamesCache[groupId] = String(groupId);
|
|
26
|
+
return groupNamesCache[groupId];
|
|
27
|
+
};
|
|
28
|
+
// Extract query parameters
|
|
29
|
+
const search = typeof req.query.search === 'string' ? req.query.search : undefined;
|
|
30
|
+
const modelNameFilter = typeof req.query.modelName === 'string' ? req.query.modelName : undefined;
|
|
31
|
+
const offset = parseInt(String(req.query.offset || 0), 10) || 0;
|
|
32
|
+
const limit = parseInt(String(req.query.limit || 50), 10) || 50;
|
|
33
|
+
// Get all models from config
|
|
34
|
+
const allModels = req.adminizer.config.models || {};
|
|
35
|
+
const modelNames = Object.keys(allModels);
|
|
36
|
+
// Determine which models to query
|
|
37
|
+
const modelsToQuery = modelNameFilter
|
|
38
|
+
? modelNames.filter(name => name === modelNameFilter)
|
|
39
|
+
: modelNames;
|
|
40
|
+
// Collect all filters from all models
|
|
41
|
+
const allFilters = [];
|
|
42
|
+
for (const modelName of modelsToQuery) {
|
|
43
|
+
try {
|
|
44
|
+
const filters = await filterService.getFiltersForModel(modelName, req.user, {
|
|
45
|
+
includePublic: true,
|
|
46
|
+
includeSystem: false
|
|
47
|
+
});
|
|
48
|
+
const modelConfig = allModels[modelName];
|
|
49
|
+
const modelTitle = modelConfig?.title || modelName;
|
|
50
|
+
for (const filter of filters) {
|
|
51
|
+
// Load owner info
|
|
52
|
+
let ownerName;
|
|
53
|
+
if (userModel && filter.ownerId) {
|
|
54
|
+
try {
|
|
55
|
+
const owner = await userModel['_findOne']({ where: { id: filter.ownerId } });
|
|
56
|
+
if (owner) {
|
|
57
|
+
ownerName = owner.fullName || owner.login || String(owner.id);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
catch (e) {
|
|
61
|
+
// Ignore owner load errors
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
// Load group names for 'groups' visibility
|
|
65
|
+
let groupNames;
|
|
66
|
+
if (filter.visibility === 'groups' && filter.groupIds && filter.groupIds.length > 0) {
|
|
67
|
+
groupNames = [];
|
|
68
|
+
for (const gid of filter.groupIds) {
|
|
69
|
+
const gName = await getGroupName(gid);
|
|
70
|
+
groupNames.push(gName);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
allFilters.push({
|
|
74
|
+
id: filter.id,
|
|
75
|
+
name: filter.name,
|
|
76
|
+
modelName: filter.modelName,
|
|
77
|
+
modelTitle,
|
|
78
|
+
visibility: filter.visibility,
|
|
79
|
+
apiEnabled: filter.apiEnabled === true,
|
|
80
|
+
ownerId: filter.ownerId,
|
|
81
|
+
ownerName,
|
|
82
|
+
isOwner: filter.ownerId === req.user?.id,
|
|
83
|
+
groupNames
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
catch (e) {
|
|
88
|
+
Adminizer.log.debug(`Error loading filters for model ${modelName}:`, e);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
// Apply search filter (by name, case-insensitive)
|
|
92
|
+
let filteredFilters = allFilters;
|
|
93
|
+
if (search) {
|
|
94
|
+
const searchLower = search.toLowerCase();
|
|
95
|
+
filteredFilters = allFilters.filter(f => f.name.toLowerCase().includes(searchLower));
|
|
96
|
+
}
|
|
97
|
+
// Calculate pagination
|
|
98
|
+
const total = filteredFilters.length;
|
|
99
|
+
const paginatedFilters = filteredFilters.slice(offset, offset + limit);
|
|
100
|
+
const hasMore = offset + limit < total;
|
|
101
|
+
// Build models list for frontend dropdown
|
|
102
|
+
const modelsList = modelNames.map(name => {
|
|
103
|
+
const config = allModels[name];
|
|
104
|
+
return {
|
|
105
|
+
name,
|
|
106
|
+
title: config?.title || name
|
|
107
|
+
};
|
|
108
|
+
});
|
|
109
|
+
return res.json({
|
|
110
|
+
filters: paginatedFilters,
|
|
111
|
+
models: modelsList,
|
|
112
|
+
total,
|
|
113
|
+
hasMore
|
|
114
|
+
});
|
|
115
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GET /adminizer/groups
|
|
3
|
+
* Returns list of all groups (for filter visibility settings)
|
|
4
|
+
*/
|
|
5
|
+
export async function getAllGroups(req, res) {
|
|
6
|
+
try {
|
|
7
|
+
const groupModel = req.adminizer.modelHandler.model.get('groupap');
|
|
8
|
+
if (!groupModel) {
|
|
9
|
+
return res.status(500).send({ error: req.i18n.__('GroupAP model not found') });
|
|
10
|
+
}
|
|
11
|
+
const groups = await groupModel['_find']({});
|
|
12
|
+
return res.json({
|
|
13
|
+
groups: groups.map((g) => ({
|
|
14
|
+
id: g.id,
|
|
15
|
+
name: g.name,
|
|
16
|
+
description: g.description || ''
|
|
17
|
+
}))
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
catch (error) {
|
|
21
|
+
return res.status(500).json({
|
|
22
|
+
error: req.i18n.__('Failed to load groups'),
|
|
23
|
+
message: error.message
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* POST /adminizer/model/:model/filter/apply
|
|
3
|
+
* Apply temporary filter (without saving) - stores filter in session keyed by model name
|
|
4
|
+
*/
|
|
5
|
+
export declare function applyTemporaryFilter(req: ReqType, res: ResType): Promise<ResType>;
|
|
6
|
+
/**
|
|
7
|
+
* GET /adminizer/model/:model/filter/temporary
|
|
8
|
+
* Returns temporary filter from server session.
|
|
9
|
+
*/
|
|
10
|
+
export declare function getTemporaryFilter(req: ReqType, res: ResType): Promise<ResType>;
|
|
11
|
+
/**
|
|
12
|
+
* GET /adminizer/model/:model/saved-filters
|
|
13
|
+
* Returns list of saved filters for the model
|
|
14
|
+
*/
|
|
15
|
+
export declare function getSavedFilters(req: ReqType, res: ResType): Promise<ResType>;
|
|
16
|
+
/**
|
|
17
|
+
* POST /adminizer/model/:model/filter
|
|
18
|
+
* Create or update a saved filter
|
|
19
|
+
*/
|
|
20
|
+
export declare function saveFilter(req: ReqType, res: ResType): Promise<ResType>;
|
|
21
|
+
/**
|
|
22
|
+
* DELETE /adminizer/model/:model/filter/:id
|
|
23
|
+
* Delete a saved filter
|
|
24
|
+
*/
|
|
25
|
+
export declare function deleteFilter(req: ReqType, res: ResType): Promise<ResType>;
|