@solidxai/core-ui 0.1.13-beta.3 → 0.1.13-beta.5
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/dist/components/auth/AuthTabs.d.ts.map +1 -1
- package/dist/components/auth/AuthTabs.js +1 -1
- package/dist/components/auth/AuthTabs.js.map +1 -1
- package/dist/components/auth/AuthTabs.tsx +1 -0
- package/dist/components/auth/SolidChangeForcePassword.d.ts.map +1 -1
- package/dist/components/auth/SolidChangeForcePassword.js +2 -2
- package/dist/components/auth/SolidChangeForcePassword.js.map +1 -1
- package/dist/components/auth/SolidChangeForcePassword.tsx +9 -8
- package/dist/components/common/SettingsComponent.d.ts.map +1 -1
- package/dist/components/common/SettingsComponent.js +1 -1
- package/dist/components/common/SettingsComponent.js.map +1 -1
- package/dist/components/common/SettingsComponent.tsx +1 -0
- package/dist/components/common/SolidFieldTooltip.d.ts.map +1 -1
- package/dist/components/common/SolidFieldTooltip.js +1 -33
- package/dist/components/common/SolidFieldTooltip.js.map +1 -1
- package/dist/components/common/SolidFieldTooltip.tsx +8 -64
- package/dist/components/common/SolidMaterialSymbol.d.ts +1 -1
- package/dist/components/common/SolidMaterialSymbol.d.ts.map +1 -1
- package/dist/components/common/SolidMaterialSymbol.js +6 -37
- package/dist/components/common/SolidMaterialSymbol.js.map +1 -1
- package/dist/components/common/SolidMaterialSymbol.tsx +6 -54
- package/dist/components/common/SolidSettings/LlmSettings/AiModelConfigTab.d.ts.map +1 -1
- package/dist/components/common/SolidSettings/LlmSettings/AiModelConfigTab.js +2 -2
- package/dist/components/common/SolidSettings/LlmSettings/AiModelConfigTab.js.map +1 -1
- package/dist/components/common/SolidSettings/LlmSettings/AiModelConfigTab.tsx +2 -0
- package/dist/components/core/card/CardItem.d.ts.map +1 -1
- package/dist/components/core/card/CardItem.js +1 -1
- package/dist/components/core/card/CardItem.js.map +1 -1
- package/dist/components/core/card/CardItem.tsx +16 -14
- package/dist/components/core/card/SolidCardView.d.ts.map +1 -1
- package/dist/components/core/card/SolidCardView.js +75 -51
- package/dist/components/core/card/SolidCardView.js.map +1 -1
- package/dist/components/core/card/SolidCardView.tsx +61 -35
- package/dist/components/core/card/SolidCardViewConfigure.d.ts.map +1 -1
- package/dist/components/core/card/SolidCardViewConfigure.js +3 -7
- package/dist/components/core/card/SolidCardViewConfigure.js.map +1 -1
- package/dist/components/core/card/SolidCardViewConfigure.tsx +3 -9
- package/dist/components/core/common/SolidAccountSettings/SolidAccountSettings.module.css +99 -0
- package/dist/components/core/common/SolidAccountSettings/SolidVersionInfo.d.ts.map +1 -1
- package/dist/components/core/common/SolidAccountSettings/SolidVersionInfo.js +76 -5
- package/dist/components/core/common/SolidAccountSettings/SolidVersionInfo.js.map +1 -1
- package/dist/components/core/common/SolidAccountSettings/SolidVersionInfo.tsx +39 -4
- package/dist/components/core/common/SolidGlobalSearchElement.d.ts.map +1 -1
- package/dist/components/core/common/SolidGlobalSearchElement.js +172 -124
- package/dist/components/core/common/SolidGlobalSearchElement.js.map +1 -1
- package/dist/components/core/common/SolidGlobalSearchElement.tsx +73 -84
- package/dist/components/core/common/globalSearchPersistence.d.ts +3 -0
- package/dist/components/core/common/globalSearchPersistence.d.ts.map +1 -1
- package/dist/components/core/common/globalSearchPersistence.js +33 -24
- package/dist/components/core/common/globalSearchPersistence.js.map +1 -1
- package/dist/components/core/common/globalSearchPersistence.ts +34 -27
- package/dist/components/core/filter/fields/SolidMediaMultipleField.js +2 -2
- package/dist/components/core/filter/fields/SolidMediaMultipleField.js.map +1 -1
- package/dist/components/core/filter/fields/SolidMediaMultipleField.tsx +2 -2
- package/dist/components/core/filter/fields/SolidMediaSingleField.js +2 -2
- package/dist/components/core/filter/fields/SolidMediaSingleField.js.map +1 -1
- package/dist/components/core/filter/fields/SolidMediaSingleField.tsx +2 -2
- package/dist/components/core/filter/fields/SolidShortTextField.js +2 -2
- package/dist/components/core/filter/fields/SolidShortTextField.js.map +1 -1
- package/dist/components/core/filter/fields/SolidShortTextField.tsx +2 -2
- package/dist/components/core/form/SolidFormView.d.ts.map +1 -1
- package/dist/components/core/form/SolidFormView.js +2 -10
- package/dist/components/core/form/SolidFormView.js.map +1 -1
- package/dist/components/core/form/SolidFormView.tsx +2 -10
- package/dist/components/core/kanban/KanbanCard.d.ts.map +1 -1
- package/dist/components/core/kanban/KanbanCard.js +1 -1
- package/dist/components/core/kanban/KanbanCard.js.map +1 -1
- package/dist/components/core/kanban/KanbanCard.tsx +18 -16
- package/dist/components/core/kanban/SolidKanbanView.d.ts.map +1 -1
- package/dist/components/core/kanban/SolidKanbanView.js +73 -59
- package/dist/components/core/kanban/SolidKanbanView.js.map +1 -1
- package/dist/components/core/kanban/SolidKanbanView.tsx +57 -22
- package/dist/components/core/kanban/SolidKanbanViewConfigure.d.ts +1 -1
- package/dist/components/core/kanban/SolidKanbanViewConfigure.d.ts.map +1 -1
- package/dist/components/core/kanban/SolidKanbanViewConfigure.js +14 -9
- package/dist/components/core/kanban/SolidKanbanViewConfigure.js.map +1 -1
- package/dist/components/core/kanban/SolidKanbanViewConfigure.tsx +38 -9
- package/dist/components/core/list/SolidEmptyListViewPlaceholder.d.ts.map +1 -1
- package/dist/components/core/list/SolidEmptyListViewPlaceholder.js +2 -3
- package/dist/components/core/list/SolidEmptyListViewPlaceholder.js.map +1 -1
- package/dist/components/core/list/SolidEmptyListViewPlaceholder.tsx +2 -3
- package/dist/components/core/list/SolidListView.d.ts.map +1 -1
- package/dist/components/core/list/SolidListView.js +8 -16
- package/dist/components/core/list/SolidListView.js.map +1 -1
- package/dist/components/core/list/SolidListView.tsx +9 -15
- package/dist/components/core/list/SolidListViewConfigure.d.ts.map +1 -1
- package/dist/components/core/list/SolidListViewConfigure.js +22 -16
- package/dist/components/core/list/SolidListViewConfigure.js.map +1 -1
- package/dist/components/core/list/SolidListViewConfigure.tsx +32 -11
- package/dist/components/core/list/SolidListViewHeaderContextMenuButton.d.ts +1 -1
- package/dist/components/core/list/SolidListViewHeaderContextMenuButton.d.ts.map +1 -1
- package/dist/components/core/list/SolidListViewHeaderContextMenuButton.js +3 -1
- package/dist/components/core/list/SolidListViewHeaderContextMenuButton.js.map +1 -1
- package/dist/components/core/list/SolidListViewHeaderContextMenuButton.tsx +3 -1
- package/dist/components/core/list/columns/SolidMediaMultipleColumn.d.ts.map +1 -1
- package/dist/components/core/list/columns/SolidMediaMultipleColumn.js +7 -0
- package/dist/components/core/list/columns/SolidMediaMultipleColumn.js.map +1 -1
- package/dist/components/core/list/columns/SolidMediaMultipleColumn.tsx +5 -0
- package/dist/components/core/list/columns/SolidMediaSingleColumn.d.ts.map +1 -1
- package/dist/components/core/list/columns/SolidMediaSingleColumn.js +3 -0
- package/dist/components/core/list/columns/SolidMediaSingleColumn.js.map +1 -1
- package/dist/components/core/list/columns/SolidMediaSingleColumn.tsx +2 -0
- package/dist/components/core/list/widgets/SolidShortTextFieldImageRenderModeWidget.d.ts.map +1 -1
- package/dist/components/core/list/widgets/SolidShortTextFieldImageRenderModeWidget.js +3 -0
- package/dist/components/core/list/widgets/SolidShortTextFieldImageRenderModeWidget.js.map +1 -1
- package/dist/components/core/list/widgets/SolidShortTextFieldImageRenderModeWidget.tsx +2 -0
- package/dist/components/core/model/CreateModel.css +10 -0
- package/dist/components/core/model/FieldMetaDataForm.css +10 -0
- package/dist/components/core/model/FieldMetaDataForm.js +8 -8
- package/dist/components/core/model/FieldMetaDataForm.js.map +1 -1
- package/dist/components/core/model/FieldMetaDataForm.tsx +13 -13
- package/dist/components/core/module/ModuleMetadataExplorer.css +23 -0
- package/dist/components/core/module/ModuleMetadataExplorer.d.ts.map +1 -1
- package/dist/components/core/module/ModuleMetadataExplorer.js +1 -1
- package/dist/components/core/module/ModuleMetadataExplorer.js.map +1 -1
- package/dist/components/core/module/ModuleMetadataExplorer.tsx +9 -0
- package/dist/components/core/tree/SolidTreeView.d.ts.map +1 -1
- package/dist/components/core/tree/SolidTreeView.js +251 -152
- package/dist/components/core/tree/SolidTreeView.js.map +1 -1
- package/dist/components/core/tree/SolidTreeView.tsx +222 -106
- package/dist/components/core/users/ApiKeysTab/GenerateApiKeyModal.d.ts.map +1 -1
- package/dist/components/core/users/ApiKeysTab/GenerateApiKeyModal.js +1 -1
- package/dist/components/core/users/ApiKeysTab/GenerateApiKeyModal.js.map +1 -1
- package/dist/components/core/users/ApiKeysTab/GenerateApiKeyModal.tsx +1 -0
- package/dist/components/layout/AdminHeaderActions.js +6 -13
- package/dist/components/layout/AdminHeaderActions.js.map +1 -1
- package/dist/components/layout/AdminHeaderActions.tsx +11 -11
- package/dist/components/layout/AdminLayout.d.ts.map +1 -1
- package/dist/components/layout/AdminLayout.js +2 -2
- package/dist/components/layout/AdminLayout.js.map +1 -1
- package/dist/components/layout/AdminLayout.tsx +5 -4
- package/dist/components/layout/AppSidebar.d.ts.map +1 -1
- package/dist/components/layout/AppSidebar.js +17 -2
- package/dist/components/layout/AppSidebar.js.map +1 -1
- package/dist/components/layout/AppSidebar.tsx +21 -2
- package/dist/components/shad-cn-ui/SolidDatePicker.d.ts +1 -1
- package/dist/components/shad-cn-ui/SolidDatePicker.d.ts.map +1 -1
- package/dist/components/shad-cn-ui/SolidDatePicker.js +35 -3
- package/dist/components/shad-cn-ui/SolidDatePicker.js.map +1 -1
- package/dist/components/shad-cn-ui/SolidDatePicker.tsx +84 -0
- package/dist/components/shad-cn-ui/SolidTooltip.d.ts.map +1 -1
- package/dist/components/shad-cn-ui/SolidTooltip.js +55 -2
- package/dist/components/shad-cn-ui/SolidTooltip.js.map +1 -1
- package/dist/components/shad-cn-ui/SolidTooltip.tsx +95 -1
- package/dist/helpers/permissions.d.ts +13 -0
- package/dist/helpers/permissions.d.ts.map +1 -1
- package/dist/helpers/permissions.js +79 -0
- package/dist/helpers/permissions.js.map +1 -1
- package/dist/helpers/permissions.ts +92 -1
- package/dist/resources/globals.css +109 -1
- package/dist/resources/solid-custom.css +53 -3
- package/dist/resources/solid-tailwind-generated.css +1 -1
- package/dist/routes/pages/admin/core/DashboardPage.d.ts.map +1 -1
- package/dist/routes/pages/admin/core/DashboardPage.js +2 -2
- package/dist/routes/pages/admin/core/DashboardPage.js.map +1 -1
- package/dist/routes/pages/admin/core/DashboardPage.tsx +2 -0
- package/dist/routes/pages/admin/core/DatasourceIntrospectionPage.d.ts.map +1 -1
- package/dist/routes/pages/admin/core/DatasourceIntrospectionPage.js +1 -1
- package/dist/routes/pages/admin/core/DatasourceIntrospectionPage.js.map +1 -1
- package/dist/routes/pages/admin/core/DatasourceIntrospectionPage.tsx +1 -0
- package/dist/types/css-modules.d.ts +2 -0
- package/package.json +1 -1
|
@@ -14,7 +14,7 @@ import { useGetSolidViewLayoutQuery } from "../../../redux/api/solidViewApi";
|
|
|
14
14
|
import qs from "qs";
|
|
15
15
|
import { useSearchParams } from "../../../hooks/useSearchParams";
|
|
16
16
|
import { SolidGlobalSearchElement } from "../common/SolidGlobalSearchElement";
|
|
17
|
-
import { permissionExpression } from "../../../helpers/permissions";
|
|
17
|
+
import { getCollectionViewPermissionNames, permissionExpression } from "../../../helpers/permissions";
|
|
18
18
|
import { SolidCreateButton } from "../common/SolidCreateButton";
|
|
19
19
|
import { createSolidEntityApi } from "../../../redux/api/solidEntityApi";
|
|
20
20
|
import { AggregationRule, GroupingRule } from "../common/GroupingComponent";
|
|
@@ -27,19 +27,24 @@ import CompactImage from '../../../resources/images/layout/images/compact.png';
|
|
|
27
27
|
import CozyImage from '../../../resources/images/layout/images/cozy.png';
|
|
28
28
|
import ComfortableImage from '../../../resources/images/layout/images/comfortable.png';
|
|
29
29
|
import { ERROR_MESSAGES } from "../../../constants/error-messages";
|
|
30
|
-
import { getFilterObjectFromLocalStorage, hasStoredFilterPredicates, setFilterObjectToLocalStorage } from "../common/globalSearchPersistence";
|
|
30
|
+
import { getFilterObjectFromLocalStorage, hasStoredFilterPredicates, hasStoredSearchUiState, setFilterObjectToLocalStorage } from "../common/globalSearchPersistence";
|
|
31
31
|
import { SolidBeforeTreeNodeLoad } from "../../../types";
|
|
32
32
|
import { getExtensionFunction } from "../../../helpers/registry";
|
|
33
33
|
import { SolidTreeLoad, SolidTreeUiEventResponse } from "../../../types/solid-core";
|
|
34
|
+
import { getMediaTypeFromUrl } from "../../../helpers/mediaType";
|
|
34
35
|
import { useRouter } from "../../../hooks/useRouter";
|
|
35
36
|
import { normalizeSolidListTreeKanbanActionPath } from "../../../helpers/routePaths";
|
|
36
37
|
import { usePathname } from "../../../hooks/usePathname";
|
|
37
38
|
import { useHandleListCustomButtonClick } from "../../../components/common/useHandleListCustomButtonClick";
|
|
38
|
-
import {
|
|
39
|
+
import { isButtonVisibleInCurrentEnv } from "../../../helpers/buttonEnvironment";
|
|
40
|
+
import { SolidButton, SolidConfirmDialog, SolidDialog, SolidDialogBody, SolidDialogDescription, SolidDialogFooter, SolidDialogHeader, SolidDialogSeparator, SolidDialogTitle, SolidDropdownMenu, SolidDropdownMenuContent, SolidDropdownMenuItem, SolidDropdownMenuSeparator, SolidDropdownMenuTrigger, SolidIcon, SolidSelect } from "../../shad-cn-ui";
|
|
39
41
|
import { SolidHeaderRequestStatus } from "../../common/SolidHeaderRequestStatus";
|
|
42
|
+
import { SolidLightbox } from "../../shad-cn-ui/SolidLightbox";
|
|
43
|
+
import type { SolidLightboxSlide } from "../../shad-cn-ui/SolidLightbox";
|
|
40
44
|
import { storeCurrentModelViewContext } from "../../../helpers/modelViewPersistence";
|
|
41
45
|
import { getRelationDisplayText } from "../../../helpers/relationDisplay";
|
|
42
46
|
import { Column as SolidTreeColumn, SolidTreeNode as TreeNode, SolidTreeSelectionKeys, SolidTreeTable } from "./SolidTreeTable";
|
|
47
|
+
import { SolidListViewHeaderButton } from "../list/SolidListViewHeaderButton";
|
|
43
48
|
|
|
44
49
|
// ─── Types ────────────────────────────────────────────────────────────────────
|
|
45
50
|
|
|
@@ -160,6 +165,8 @@ export const SolidTreeView = forwardRef<SolidTreeViewHandle, SolidTreeViewParams
|
|
|
160
165
|
const [isDeleteRecordsDialogVisible, setDeleteRecordsDialogVisible] = useState(false);
|
|
161
166
|
const [isRecoverDialogVisible, setRecoverDialogVisible] = useState(false);
|
|
162
167
|
const [showArchived, setShowArchived] = useState(false);
|
|
168
|
+
const [openLightbox, setOpenLightbox] = useState(false);
|
|
169
|
+
const [lightboxUrls, setLightboxUrls] = useState<any[]>([]);
|
|
163
170
|
|
|
164
171
|
|
|
165
172
|
const [createButtonUrl, setCreateButtonUrl] = useState<string>();
|
|
@@ -178,6 +185,25 @@ export const SolidTreeView = forwardRef<SolidTreeViewHandle, SolidTreeViewParams
|
|
|
178
185
|
|
|
179
186
|
const [size, setSize] = useState<string | any>(sizeOptions[1].value);
|
|
180
187
|
const [viewModes, setViewModes] = useState<any>([]);
|
|
188
|
+
const lightboxSlides: SolidLightboxSlide[] = Array.isArray(lightboxUrls)
|
|
189
|
+
? lightboxUrls
|
|
190
|
+
.map((item: any) => {
|
|
191
|
+
const src = item?.src || item?.downloadUrl || "";
|
|
192
|
+
if (!src) {
|
|
193
|
+
return null;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
const mediaType = getMediaTypeFromUrl(src);
|
|
197
|
+
const slide: SolidLightboxSlide = { src };
|
|
198
|
+
|
|
199
|
+
if (mediaType !== "image") {
|
|
200
|
+
slide.type = mediaType;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
return slide;
|
|
204
|
+
})
|
|
205
|
+
.filter((slide): slide is SolidLightboxSlide => !!slide)
|
|
206
|
+
: [];
|
|
181
207
|
|
|
182
208
|
const headerRequestStatusLabel = treeLoading ? "Loading..." : null;
|
|
183
209
|
|
|
@@ -282,19 +308,7 @@ export const SolidTreeView = forwardRef<SolidTreeViewHandle, SolidTreeViewParams
|
|
|
282
308
|
useEffect(() => {
|
|
283
309
|
const fetchPermissions = async () => {
|
|
284
310
|
if (params.modelName) {
|
|
285
|
-
const permissionNames =
|
|
286
|
-
permissionExpression(params.modelName, 'create'),
|
|
287
|
-
permissionExpression(params.modelName, 'delete'),
|
|
288
|
-
permissionExpression(params.modelName, 'update'),
|
|
289
|
-
permissionExpression(params.modelName, 'deleteMany'),
|
|
290
|
-
permissionExpression(params.modelName, 'findOne'),
|
|
291
|
-
permissionExpression(params.modelName, 'findMany'),
|
|
292
|
-
permissionExpression(params.modelName, 'insertMany'),
|
|
293
|
-
permissionExpression('importTransaction', 'create'),
|
|
294
|
-
permissionExpression('exportTransaction', 'create'),
|
|
295
|
-
permissionExpression('userViewMetadata', 'create'),
|
|
296
|
-
permissionExpression('savedFilters', 'create')
|
|
297
|
-
];
|
|
311
|
+
const permissionNames = getCollectionViewPermissionNames(params.modelName);
|
|
298
312
|
const queryData = {
|
|
299
313
|
permissionNames: permissionNames,
|
|
300
314
|
};
|
|
@@ -616,6 +630,18 @@ export const SolidTreeView = forwardRef<SolidTreeViewHandle, SolidTreeViewParams
|
|
|
616
630
|
groupPath
|
|
617
631
|
.map((item) => buildImplicitFilterCondition(item));
|
|
618
632
|
|
|
633
|
+
const getGroupNodeKey = (groupPath: GroupPathItem[] = []) =>
|
|
634
|
+
groupPath.reduce(
|
|
635
|
+
(parentKey, item) => `${parentKey}-g-${encodeURIComponent(JSON.stringify({
|
|
636
|
+
ruleIndex: item.ruleIndex,
|
|
637
|
+
fieldName: item.fieldName,
|
|
638
|
+
filterField: item.filterField,
|
|
639
|
+
value: item.value,
|
|
640
|
+
dateGranularity: item.dateGranularity ?? null,
|
|
641
|
+
}))}`,
|
|
642
|
+
"root",
|
|
643
|
+
);
|
|
644
|
+
|
|
619
645
|
const mergeFiltersWithImplicit = (implicitFilters: any[]) => {
|
|
620
646
|
const baseFilters = latestFiltersRef.current;
|
|
621
647
|
const hasBaseFilters = baseFilters && Object.keys(baseFilters).length > 0;
|
|
@@ -771,7 +797,8 @@ export const SolidTreeView = forwardRef<SolidTreeViewHandle, SolidTreeViewParams
|
|
|
771
797
|
|
|
772
798
|
const queryString = qs.stringify(queryData, { encodeValuesOnly: true });
|
|
773
799
|
|
|
774
|
-
const
|
|
800
|
+
const request = triggerGetSolidEntities(queryString);
|
|
801
|
+
const response = await request.unwrap().finally(() => request.unsubscribe());
|
|
775
802
|
return { queryData, queryString, response };
|
|
776
803
|
};
|
|
777
804
|
|
|
@@ -837,7 +864,8 @@ export const SolidTreeView = forwardRef<SolidTreeViewHandle, SolidTreeViewParams
|
|
|
837
864
|
|
|
838
865
|
|
|
839
866
|
|
|
840
|
-
const
|
|
867
|
+
const request = triggerGetSolidEntities(queryString);
|
|
868
|
+
const response = await request.unwrap().finally(() => request.unsubscribe());
|
|
841
869
|
return { queryData, queryString, response };
|
|
842
870
|
};
|
|
843
871
|
|
|
@@ -847,7 +875,6 @@ export const SolidTreeView = forwardRef<SolidTreeViewHandle, SolidTreeViewParams
|
|
|
847
875
|
groupMetaRows: any[],
|
|
848
876
|
ruleIndex: number,
|
|
849
877
|
parentPath: GroupPathItem[],
|
|
850
|
-
parentKey: string
|
|
851
878
|
): TreeNode[] => {
|
|
852
879
|
const rule = activeGroupingRules[ruleIndex];
|
|
853
880
|
if (!rule?.fieldName) return [];
|
|
@@ -856,7 +883,7 @@ export const SolidTreeView = forwardRef<SolidTreeViewHandle, SolidTreeViewParams
|
|
|
856
883
|
const filterField = getResolvedGroupField(fieldName);
|
|
857
884
|
// const dateGranularity = dateTimeImplicitFilter(rule);
|
|
858
885
|
const dateGranularity = getDateGranularity(rule);
|
|
859
|
-
return (groupMetaRows || []).map((groupMeta
|
|
886
|
+
return (groupMetaRows || []).map((groupMeta) => {
|
|
860
887
|
const rawGroupLabel = groupMeta?.groupName;
|
|
861
888
|
const normalizedGroupLabel =
|
|
862
889
|
rawGroupLabel === "[object Object]"
|
|
@@ -872,7 +899,7 @@ export const SolidTreeView = forwardRef<SolidTreeViewHandle, SolidTreeViewParams
|
|
|
872
899
|
];
|
|
873
900
|
|
|
874
901
|
return {
|
|
875
|
-
key:
|
|
902
|
+
key: getGroupNodeKey(groupPath),
|
|
876
903
|
data: {
|
|
877
904
|
__treeMeta: {
|
|
878
905
|
nodeType: "group",
|
|
@@ -927,12 +954,60 @@ export const SolidTreeView = forwardRef<SolidTreeViewHandle, SolidTreeViewParams
|
|
|
927
954
|
});
|
|
928
955
|
};
|
|
929
956
|
|
|
957
|
+
const fetchNodeChildren = async (node: TreeNode,offset: number,limit: number,): Promise<{ children: TreeNode[]; total: number }> => {
|
|
958
|
+
const meta = (node.data as TreeRowData)?.__treeMeta;
|
|
959
|
+
if (!meta || meta.nodeType !== "group") {
|
|
960
|
+
return { children: [], total: 0 };
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
const nodeKey = String(node.key);
|
|
964
|
+
const nextRuleIndex = meta.ruleIndex + 1;
|
|
965
|
+
|
|
966
|
+
if (nextRuleIndex < activeGroupingRules.length) {
|
|
967
|
+
const { response } = await runGroupedQuery(
|
|
968
|
+
nextRuleIndex,
|
|
969
|
+
meta.groupPath || [],
|
|
970
|
+
offset,
|
|
971
|
+
limit
|
|
972
|
+
);
|
|
973
|
+
|
|
974
|
+
return {
|
|
975
|
+
children: buildGroupNodes(
|
|
976
|
+
response?.groupMeta || [],
|
|
977
|
+
nextRuleIndex,
|
|
978
|
+
meta.groupPath || [],
|
|
979
|
+
),
|
|
980
|
+
total: response?.meta.totalRecords ?? 0,
|
|
981
|
+
};
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
const { response } = await runLeafQuery(meta.groupPath || [], offset, limit);
|
|
985
|
+
return {
|
|
986
|
+
children: buildRecordNodes(response?.records || [], nodeKey, meta.groupPath || []),
|
|
987
|
+
total: response?.meta.totalRecords ?? 0,
|
|
988
|
+
};
|
|
989
|
+
};
|
|
990
|
+
|
|
991
|
+
const mergeNodesWithCurrentState = (freshNodes: TreeNode[], currentNodes: TreeNode[]) => {
|
|
992
|
+
const currentNodesByKey = new Map(
|
|
993
|
+
currentNodes.map((node) => [String(node.key), node]),
|
|
994
|
+
);
|
|
995
|
+
|
|
996
|
+
return freshNodes.map((node) => {
|
|
997
|
+
const currentNode = currentNodesByKey.get(String(node.key));
|
|
998
|
+
return currentNode?.children?.length
|
|
999
|
+
? { ...node, children: currentNode.children }
|
|
1000
|
+
: node;
|
|
1001
|
+
});
|
|
1002
|
+
};
|
|
1003
|
+
|
|
930
1004
|
// ─── Root group load / paginate ───────────────────────────────────────────
|
|
931
1005
|
|
|
932
|
-
const loadRootGroups = async (offset = 0) => {
|
|
1006
|
+
const loadRootGroups = async (offset = 0, affectedGroupPaths: GroupPathItem[][] = []) => {
|
|
933
1007
|
if (!solidTreeViewMetaData || activeGroupingRules.length === 0) {
|
|
934
1008
|
setTreeNodes([]);
|
|
935
1009
|
setExpandedKeys({});
|
|
1010
|
+
setPaginationMap({});
|
|
936
1011
|
|
|
937
1012
|
const queryObject = getFilterObjectFromLocalStorage();
|
|
938
1013
|
if (queryObject) {
|
|
@@ -948,13 +1023,46 @@ export const SolidTreeView = forwardRef<SolidTreeViewHandle, SolidTreeViewParams
|
|
|
948
1023
|
setTreeLoading(true);
|
|
949
1024
|
try {
|
|
950
1025
|
const { response } = await runGroupedQuery(0, [], offset, limit);
|
|
951
|
-
const rootNodes = buildGroupNodes(response?.groupMeta || [], 0, []
|
|
952
|
-
setTreeNodes(rootNodes);
|
|
953
|
-
setExpandedKeys({});
|
|
954
|
-
setSelectedNodeKeys({});
|
|
955
|
-
// Collapse expanded keys since data changed
|
|
1026
|
+
const rootNodes = buildGroupNodes(response?.groupMeta || [], 0, []);
|
|
956
1027
|
const total = response?.meta.totalRecords ?? 0;
|
|
957
|
-
|
|
1028
|
+
const rootPaginationEntry: PaginationEntry = { offset, total, limit };
|
|
1029
|
+
|
|
1030
|
+
let nextTreeNodes = affectedGroupPaths.length > 0
|
|
1031
|
+
? mergeNodesWithCurrentState(rootNodes, treeNodes)
|
|
1032
|
+
: rootNodes;
|
|
1033
|
+
const nextPaginationMap: Record<string, PaginationEntry> = affectedGroupPaths.length > 0
|
|
1034
|
+
? { ...paginationMap, root: rootPaginationEntry }
|
|
1035
|
+
: { root: rootPaginationEntry };
|
|
1036
|
+
const refreshedNodeKeys = new Set<string>();
|
|
1037
|
+
|
|
1038
|
+
for (const groupPath of affectedGroupPaths) {
|
|
1039
|
+
for (let depth = 0; depth < groupPath.length; depth += 1) {
|
|
1040
|
+
const nodeKey = getGroupNodeKey(groupPath.slice(0, depth + 1));
|
|
1041
|
+
if (refreshedNodeKeys.has(nodeKey)) continue;
|
|
1042
|
+
|
|
1043
|
+
const node = findNodeByKey(nextTreeNodes, nodeKey);
|
|
1044
|
+
if (!node) break;
|
|
1045
|
+
|
|
1046
|
+
const pagination = getPagination(nodeKey);
|
|
1047
|
+
const { children, total: childTotal } = await fetchNodeChildren(
|
|
1048
|
+
node,
|
|
1049
|
+
pagination.offset,
|
|
1050
|
+
pagination.limit,
|
|
1051
|
+
);
|
|
1052
|
+
const nextChildren = depth < groupPath.length - 1
|
|
1053
|
+
? mergeNodesWithCurrentState(children, node.children || [])
|
|
1054
|
+
: children;
|
|
1055
|
+
|
|
1056
|
+
nextTreeNodes = updateNodeChildren(nextTreeNodes, nodeKey, nextChildren);
|
|
1057
|
+
nextPaginationMap[nodeKey] = { ...pagination, total: childTotal };
|
|
1058
|
+
refreshedNodeKeys.add(nodeKey);
|
|
1059
|
+
}
|
|
1060
|
+
}
|
|
1061
|
+
|
|
1062
|
+
setTreeNodes(nextTreeNodes);
|
|
1063
|
+
setSelectedNodeKeys({});
|
|
1064
|
+
setPaginationMap(nextPaginationMap);
|
|
1065
|
+
if (affectedGroupPaths.length === 0) setExpandedKeys({});
|
|
958
1066
|
|
|
959
1067
|
if (latestFilterPredicatesRef.current && latestFilterPredicatesRef.current.persistFilter) {
|
|
960
1068
|
let queryData: any = {
|
|
@@ -978,7 +1086,6 @@ export const SolidTreeView = forwardRef<SolidTreeViewHandle, SolidTreeViewParams
|
|
|
978
1086
|
}
|
|
979
1087
|
|
|
980
1088
|
} catch (error: any) {
|
|
981
|
-
setTreeNodes([]);
|
|
982
1089
|
dispatch(showToast({ severity: "error", summary: "Failed to load tree", detail: error?.data?.message || error?.message || "Unable to load grouped data", life: 4000 }));
|
|
983
1090
|
} finally {
|
|
984
1091
|
setTreeLoading(false);
|
|
@@ -1002,33 +1109,10 @@ export const SolidTreeView = forwardRef<SolidTreeViewHandle, SolidTreeViewParams
|
|
|
1002
1109
|
|
|
1003
1110
|
const nodeKey = String(node.key);
|
|
1004
1111
|
const limit = getPagination(nodeKey).limit || globalLimit || DEFAULT_PAGE_SIZE;
|
|
1005
|
-
const nextRuleIndex = meta.ruleIndex + 1;
|
|
1006
1112
|
|
|
1007
1113
|
setTreeLoading(true);
|
|
1008
1114
|
try {
|
|
1009
|
-
|
|
1010
|
-
let total = 0;
|
|
1011
|
-
|
|
1012
|
-
if (nextRuleIndex < activeGroupingRules.length) {
|
|
1013
|
-
|
|
1014
|
-
const { response } = await runGroupedQuery(
|
|
1015
|
-
nextRuleIndex,
|
|
1016
|
-
meta.groupPath || [],
|
|
1017
|
-
offset,
|
|
1018
|
-
limit
|
|
1019
|
-
);
|
|
1020
|
-
children = buildGroupNodes(
|
|
1021
|
-
response?.groupMeta || [],
|
|
1022
|
-
nextRuleIndex,
|
|
1023
|
-
meta.groupPath || [],
|
|
1024
|
-
nodeKey
|
|
1025
|
-
);
|
|
1026
|
-
total = response?.meta.totalRecords ?? 0;
|
|
1027
|
-
} else {
|
|
1028
|
-
const { response } = await runLeafQuery(meta.groupPath || [], offset, limit);
|
|
1029
|
-
children = buildRecordNodes(response?.records || [], nodeKey, meta.groupPath || []);
|
|
1030
|
-
total = response?.meta.totalRecords ?? 0;
|
|
1031
|
-
}
|
|
1115
|
+
const { children, total } = await fetchNodeChildren(node, offset, limit);
|
|
1032
1116
|
|
|
1033
1117
|
setTreeNodes((prev) => updateNodeChildren(prev, nodeKey, children));
|
|
1034
1118
|
setPagination(node.key as string, { offset, total: total, limit });
|
|
@@ -1225,6 +1309,9 @@ export const SolidTreeView = forwardRef<SolidTreeViewHandle, SolidTreeViewParams
|
|
|
1225
1309
|
// handle bulk deletion
|
|
1226
1310
|
const deleteBulk = async () => {
|
|
1227
1311
|
const deleteList = selectedRecords.map((element: any) => element.id);
|
|
1312
|
+
const affectedGroupPaths = selectedRecords
|
|
1313
|
+
.map((record: TreeRowData) => record?.__treeMeta?.groupPath)
|
|
1314
|
+
.filter((groupPath): groupPath is GroupPathItem[] => Array.isArray(groupPath));
|
|
1228
1315
|
if (deleteList.length === 0) {
|
|
1229
1316
|
setDeleteRecordsDialogVisible(false);
|
|
1230
1317
|
return;
|
|
@@ -1234,7 +1321,7 @@ export const SolidTreeView = forwardRef<SolidTreeViewHandle, SolidTreeViewParams
|
|
|
1234
1321
|
await deleteManySolidEntities(deleteList).unwrap();
|
|
1235
1322
|
dispatch(showToast({ severity: 'success', summary: 'Deleted', detail: ERROR_MESSAGES.RECORD_DELETE, life: 3000 }));
|
|
1236
1323
|
setDeleteRecordsDialogVisible(false);
|
|
1237
|
-
await loadRootGroups(getPagination("root").offset);
|
|
1324
|
+
await loadRootGroups(getPagination("root").offset, affectedGroupPaths);
|
|
1238
1325
|
} catch (error: any) {
|
|
1239
1326
|
dispatch(showToast({ severity: 'error', summary: 'Delete Failed', detail: error?.data?.message, life: 4000 }));
|
|
1240
1327
|
}
|
|
@@ -1250,6 +1337,9 @@ export const SolidTreeView = forwardRef<SolidTreeViewHandle, SolidTreeViewParams
|
|
|
1250
1337
|
|
|
1251
1338
|
const recoverAll = async () => {
|
|
1252
1339
|
const recoverList = selectedRecoverRecords.map((element: any) => element.id);
|
|
1340
|
+
const affectedGroupPaths = selectedRecoverRecords
|
|
1341
|
+
.map((record: TreeRowData) => record?.__treeMeta?.groupPath)
|
|
1342
|
+
.filter((groupPath): groupPath is GroupPathItem[] => Array.isArray(groupPath));
|
|
1253
1343
|
if (recoverList.length === 0) {
|
|
1254
1344
|
setRecoverDialogVisible(false);
|
|
1255
1345
|
return;
|
|
@@ -1264,7 +1354,7 @@ export const SolidTreeView = forwardRef<SolidTreeViewHandle, SolidTreeViewParams
|
|
|
1264
1354
|
detail: response?.data?.message || "Records recovered successfully.",
|
|
1265
1355
|
life: 3000,
|
|
1266
1356
|
}));
|
|
1267
|
-
await loadRootGroups(getPagination("root").offset);
|
|
1357
|
+
await loadRootGroups(getPagination("root").offset, affectedGroupPaths);
|
|
1268
1358
|
} catch (error: any) {
|
|
1269
1359
|
dispatch(showToast({
|
|
1270
1360
|
severity: "error",
|
|
@@ -1304,8 +1394,8 @@ export const SolidTreeView = forwardRef<SolidTreeViewHandle, SolidTreeViewParams
|
|
|
1304
1394
|
solidListViewMetaData: solidTreeViewMetaData,
|
|
1305
1395
|
fieldMetadata,
|
|
1306
1396
|
column,
|
|
1307
|
-
setLightboxUrls
|
|
1308
|
-
setOpenLightbox
|
|
1397
|
+
setLightboxUrls,
|
|
1398
|
+
setOpenLightbox,
|
|
1309
1399
|
});
|
|
1310
1400
|
|
|
1311
1401
|
if (!React.isValidElement(listColumn)) return null;
|
|
@@ -1502,9 +1592,19 @@ export const SolidTreeView = forwardRef<SolidTreeViewHandle, SolidTreeViewParams
|
|
|
1502
1592
|
|
|
1503
1593
|
|
|
1504
1594
|
const handleCustomButtonClick = useHandleListCustomButtonClick();
|
|
1595
|
+
const shouldShowMobileSearchElement = showGlobalSearchElement || hasStoredSearchUiState(filterPredicates) || hasStoredSearchUiState(getFilterObjectFromLocalStorage());
|
|
1596
|
+
|
|
1597
|
+
const visibleHeaderButtons = useMemo(
|
|
1598
|
+
() =>
|
|
1599
|
+
(solidTreeViewLayout?.attrs?.headerButtons ?? []).filter(
|
|
1600
|
+
(button: any) => isButtonVisibleInCurrentEnv(button?.attrs),
|
|
1601
|
+
),
|
|
1602
|
+
[solidTreeViewLayout?.attrs?.headerButtons],
|
|
1603
|
+
);
|
|
1505
1604
|
|
|
1506
1605
|
const [selectedSolidViewData, setSelectedSolidViewData] = useState<any>();
|
|
1507
1606
|
const [deleteEntity, setDeleteEntity] = useState(false);
|
|
1607
|
+
const entityDisplayName = solidTreeViewMetaData?.data?.solidView?.model?.displayName || params?.modelName;
|
|
1508
1608
|
const openRowForEdit = (rowData: any, viewMode: "edit" | "view") => {
|
|
1509
1609
|
storeCurrentModelViewContext();
|
|
1510
1610
|
|
|
@@ -1549,13 +1649,16 @@ export const SolidTreeView = forwardRef<SolidTreeViewHandle, SolidTreeViewParams
|
|
|
1549
1649
|
throw new Error(ERROR_MESSAGES.NO_ENTITY_SELECTED);
|
|
1550
1650
|
}
|
|
1551
1651
|
|
|
1652
|
+
const affectedGroupPath = selectedSolidViewData?.__treeMeta?.groupPath;
|
|
1552
1653
|
const response: any = await deleteSolidSingleEntiry(selectedSolidViewData.id);
|
|
1553
|
-
|
|
1554
1654
|
if (response?.data?.statusCode === 200) {
|
|
1555
1655
|
setDeleteEntity(false);
|
|
1556
1656
|
setSelectedSolidViewData(undefined);
|
|
1557
1657
|
dispatch(showToast({ severity: "success", summary: ERROR_MESSAGES.DELETED, detail: ERROR_MESSAGES.ENTITY_DELETE, life: 3000 }));
|
|
1558
|
-
await loadRootGroups(
|
|
1658
|
+
await loadRootGroups(
|
|
1659
|
+
getPagination("root").offset,
|
|
1660
|
+
Array.isArray(affectedGroupPath) ? [affectedGroupPath] : [],
|
|
1661
|
+
);
|
|
1559
1662
|
} else {
|
|
1560
1663
|
dispatch(showToast({ severity: "error", summary: ERROR_MESSAGES.DELETE_FAIELD, detail: response?.error?.data?.error, sticky: true }));
|
|
1561
1664
|
}
|
|
@@ -1575,7 +1678,10 @@ export const SolidTreeView = forwardRef<SolidTreeViewHandle, SolidTreeViewParams
|
|
|
1575
1678
|
detail: response?.data?.message || "Record recovered successfully.",
|
|
1576
1679
|
life: 3000,
|
|
1577
1680
|
}));
|
|
1578
|
-
await loadRootGroups(
|
|
1681
|
+
await loadRootGroups(
|
|
1682
|
+
getPagination("root").offset,
|
|
1683
|
+
Array.isArray(record?.__treeMeta?.groupPath) ? [record.__treeMeta.groupPath] : [],
|
|
1684
|
+
);
|
|
1579
1685
|
} catch (error: any) {
|
|
1580
1686
|
dispatch(showToast({
|
|
1581
1687
|
severity: "error",
|
|
@@ -1780,6 +1886,7 @@ export const SolidTreeView = forwardRef<SolidTreeViewHandle, SolidTreeViewParams
|
|
|
1780
1886
|
ref={solidGlobalSearchElementRef}
|
|
1781
1887
|
viewData={solidTreeViewMetaData}
|
|
1782
1888
|
handleApplyCustomFilter={handleApplyCustomFilter}
|
|
1889
|
+
filterPredicates={filterPredicates}
|
|
1783
1890
|
/>
|
|
1784
1891
|
</div>
|
|
1785
1892
|
)}
|
|
@@ -1801,6 +1908,22 @@ export const SolidTreeView = forwardRef<SolidTreeViewHandle, SolidTreeViewParams
|
|
|
1801
1908
|
</div>
|
|
1802
1909
|
)}
|
|
1803
1910
|
|
|
1911
|
+
<div className="solid-header-buttons-wrapper hidden items-center lg:flex">
|
|
1912
|
+
{visibleHeaderButtons
|
|
1913
|
+
?.filter((button: any) => button?.attrs?.actionInContextMenu !== true)
|
|
1914
|
+
?.map((button: any, index: number) => (
|
|
1915
|
+
<SolidListViewHeaderButton
|
|
1916
|
+
key={index}
|
|
1917
|
+
button={button}
|
|
1918
|
+
params={params}
|
|
1919
|
+
solidListViewMetaData={solidTreeViewMetaData}
|
|
1920
|
+
handleCustomButtonClick={handleCustomButtonClick}
|
|
1921
|
+
selectedRecords={selectedRecords}
|
|
1922
|
+
filters={filters}
|
|
1923
|
+
/>
|
|
1924
|
+
))}
|
|
1925
|
+
</div>
|
|
1926
|
+
|
|
1804
1927
|
{actionsAllowed.includes(`${permissionExpression(params.modelName, "create")}`) &&
|
|
1805
1928
|
solidTreeViewMetaData?.data?.solidView?.layout?.attrs.create !== false && (
|
|
1806
1929
|
<SolidCreateButton
|
|
@@ -1870,7 +1993,7 @@ export const SolidTreeView = forwardRef<SolidTreeViewHandle, SolidTreeViewParams
|
|
|
1870
1993
|
</div>
|
|
1871
1994
|
|
|
1872
1995
|
{solidTreeViewMetaData?.data?.solidView?.layout?.attrs.enableGlobalSearch === true &&
|
|
1873
|
-
|
|
1996
|
+
shouldShowMobileSearchElement && (
|
|
1874
1997
|
<div className="flex lg:hidden">
|
|
1875
1998
|
<SolidGlobalSearchElement
|
|
1876
1999
|
viewType="tree"
|
|
@@ -1879,6 +2002,7 @@ export const SolidTreeView = forwardRef<SolidTreeViewHandle, SolidTreeViewParams
|
|
|
1879
2002
|
ref={solidGlobalSearchElementRef}
|
|
1880
2003
|
viewData={solidTreeViewMetaData}
|
|
1881
2004
|
handleApplyCustomFilter={handleApplyCustomFilter}
|
|
2005
|
+
filterPredicates={filterPredicates}
|
|
1882
2006
|
/>
|
|
1883
2007
|
</div>
|
|
1884
2008
|
)}
|
|
@@ -2062,53 +2186,37 @@ export const SolidTreeView = forwardRef<SolidTreeViewHandle, SolidTreeViewParams
|
|
|
2062
2186
|
</div>
|
|
2063
2187
|
</div>
|
|
2064
2188
|
|
|
2065
|
-
<
|
|
2189
|
+
<SolidConfirmDialog
|
|
2066
2190
|
open={deleteEntity}
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
</SolidDialogDescription>
|
|
2083
|
-
</SolidDialogBody>
|
|
2084
|
-
<SolidDialogFooter>
|
|
2085
|
-
<SolidButton label="Cancel" size="sm" variant="outline" onClick={() => setDeleteEntity(false)} />
|
|
2086
|
-
<SolidButton label="Delete" size="sm" severity="danger" onClick={handleDeleteEntity} />
|
|
2087
|
-
</SolidDialogFooter>
|
|
2088
|
-
</SolidDialog>
|
|
2089
|
-
|
|
2090
|
-
<SolidDialog
|
|
2191
|
+
onCancel={() => setDeleteEntity(false)}
|
|
2192
|
+
onConfirm={handleDeleteEntity}
|
|
2193
|
+
className="solid-shadcn-confirm-dialog solid-delete-confirm-dialog"
|
|
2194
|
+
headerClassName="solid-shadcn-dialog-head"
|
|
2195
|
+
bodyClassName="solid-shadcn-dialog-body"
|
|
2196
|
+
footerClassName="solid-shadcn-dialog-actions"
|
|
2197
|
+
separatorClassName="solid-shadcn-dialog-sep"
|
|
2198
|
+
showSeparator
|
|
2199
|
+
title={`Delete ${entityDisplayName}`}
|
|
2200
|
+
message={<p className="solid-shadcn-dialog-text">{`Are you sure you want to delete this ${entityDisplayName}?`}</p>}
|
|
2201
|
+
confirmLabel="Delete"
|
|
2202
|
+
cancelLabel="Cancel"
|
|
2203
|
+
/>
|
|
2204
|
+
|
|
2205
|
+
<SolidConfirmDialog
|
|
2091
2206
|
open={isDeleteRecordsDialogVisible}
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
<
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
</SolidDialogDescription>
|
|
2106
|
-
</SolidDialogBody>
|
|
2107
|
-
<SolidDialogFooter>
|
|
2108
|
-
<SolidButton label="Cancel" size="sm" variant="outline" onClick={onDeleteClose} />
|
|
2109
|
-
<SolidButton label="Delete" size="sm" severity="danger" onClick={deleteBulk} />
|
|
2110
|
-
</SolidDialogFooter>
|
|
2111
|
-
</SolidDialog>
|
|
2207
|
+
onCancel={onDeleteClose}
|
|
2208
|
+
onConfirm={deleteBulk}
|
|
2209
|
+
className="solid-shadcn-confirm-dialog solid-delete-confirm-dialog"
|
|
2210
|
+
headerClassName="solid-shadcn-dialog-head"
|
|
2211
|
+
bodyClassName="solid-shadcn-dialog-body"
|
|
2212
|
+
footerClassName="solid-shadcn-dialog-actions"
|
|
2213
|
+
separatorClassName="solid-shadcn-dialog-sep"
|
|
2214
|
+
showSeparator
|
|
2215
|
+
title="Delete Records"
|
|
2216
|
+
message={<p className="solid-shadcn-dialog-text">Are you sure you want to delete the selected records?</p>}
|
|
2217
|
+
confirmLabel="Delete"
|
|
2218
|
+
cancelLabel="Cancel"
|
|
2219
|
+
/>
|
|
2112
2220
|
|
|
2113
2221
|
<SolidDialog
|
|
2114
2222
|
open={isRecoverDialogVisible}
|
|
@@ -2133,6 +2241,14 @@ export const SolidTreeView = forwardRef<SolidTreeViewHandle, SolidTreeViewParams
|
|
|
2133
2241
|
</SolidDialogFooter>
|
|
2134
2242
|
</SolidDialog>
|
|
2135
2243
|
|
|
2244
|
+
{openLightbox && (
|
|
2245
|
+
<SolidLightbox
|
|
2246
|
+
open={openLightbox}
|
|
2247
|
+
slides={lightboxSlides}
|
|
2248
|
+
onClose={() => setOpenLightbox(false)}
|
|
2249
|
+
/>
|
|
2250
|
+
)}
|
|
2251
|
+
|
|
2136
2252
|
</div>
|
|
2137
2253
|
);
|
|
2138
2254
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GenerateApiKeyModal.d.ts","sourceRoot":"","sources":["../../../../../src/components/core/users/ApiKeysTab/GenerateApiKeyModal.tsx"],"names":[],"mappings":"AAmBA,OAAO,EAAE,KAAK,YAAY,EAAoC,MAAM,iCAAiC,CAAC;AAiCtG,UAAU,wBAAwB;IAChC,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,SAAS,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,KAAK,IAAI,CAAC;IAC9E,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,mBAAmB,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,wBAAwB,
|
|
1
|
+
{"version":3,"file":"GenerateApiKeyModal.d.ts","sourceRoot":"","sources":["../../../../../src/components/core/users/ApiKeysTab/GenerateApiKeyModal.tsx"],"names":[],"mappings":"AAmBA,OAAO,EAAE,KAAK,YAAY,EAAoC,MAAM,iCAAiC,CAAC;AAiCtG,UAAU,wBAAwB;IAChC,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,SAAS,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,KAAK,IAAI,CAAC;IAC9E,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,mBAAmB,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,wBAAwB,2CAmIjG"}
|
|
@@ -152,6 +152,6 @@ export function GenerateApiKeyModal(_a) {
|
|
|
152
152
|
formik.setFieldValue("expiryOption", value);
|
|
153
153
|
if (value !== "custom")
|
|
154
154
|
setCustomDate(null);
|
|
155
|
-
} }), formik.values.expiryOption === "custom" && (_jsx(SolidDatePicker, { selected: customDate, onChange: function (date) { return setCustomDate(date); }, minDate: new Date(), placeholderText: "Select expiry date", dateFormat: "dd/MM/yyyy" })), formik.values.expiryOption !== "custom" ? (_jsx("p", { className: "solid-api-key-dialog-hint m-0", children: "Choose how long this key should remain valid." })) : null, expiryError && _jsx(SolidMessage, { severity: "error", text: expiryError })] })] }) }) }), _jsx(SolidDialogSeparator, {}), _jsxs(SolidDialogFooter, { className: "solid-api-key-dialog-footer", children: [_jsx(SolidButton, { variant: "outline", type: "button", onClick: handleClose, disabled: isLoading, children: "Cancel" }), _jsx(SolidButton, { type: "submit", form: "generate-api-key-form", loading: isLoading, children: "Generate Key" })] })] }));
|
|
155
|
+
}, native: false }), formik.values.expiryOption === "custom" && (_jsx(SolidDatePicker, { selected: customDate, onChange: function (date) { return setCustomDate(date); }, minDate: new Date(), placeholderText: "Select expiry date", dateFormat: "dd/MM/yyyy" })), formik.values.expiryOption !== "custom" ? (_jsx("p", { className: "solid-api-key-dialog-hint m-0", children: "Choose how long this key should remain valid." })) : null, expiryError && _jsx(SolidMessage, { severity: "error", text: expiryError })] })] }) }) }), _jsx(SolidDialogSeparator, {}), _jsxs(SolidDialogFooter, { className: "solid-api-key-dialog-footer", children: [_jsx(SolidButton, { variant: "outline", type: "button", onClick: handleClose, disabled: isLoading, children: "Cancel" }), _jsx(SolidButton, { type: "submit", form: "generate-api-key-form", loading: isLoading, children: "Generate Key" })] })] }));
|
|
156
156
|
}
|
|
157
157
|
//# sourceMappingURL=GenerateApiKeyModal.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GenerateApiKeyModal.js","sourceRoot":"","sources":["../../../../../src/components/core/users/ApiKeysTab/GenerateApiKeyModal.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useEffect, useState } from \"react\";\nimport { useDispatch } from \"react-redux\";\nimport { useFormik } from \"formik\";\nimport * as Yup from \"yup\";\nimport {\n SolidButton,\n SolidDatePicker,\n SolidDialog,\n SolidDialogBody,\n SolidDialogDescription,\n SolidDialogFooter,\n SolidDialogHeader,\n SolidDialogSeparator,\n SolidDialogTitle,\n SolidInput,\n SolidMessage,\n SolidSelect,\n} from \"../../../shad-cn-ui\";\nimport { showToast } from \"../../../../redux/features/toastSlice\";\nimport { type ApiKeyRecord, useGenerateApiKeyForUserMutation } from \"../../../../redux/api/apiKeyApi\";\n\nconst EXPIRY_OPTIONS = [\n { label: \"30 days\", value: \"30d\" },\n { label: \"60 days\", value: \"60d\" },\n { label: \"90 days\", value: \"90d\" },\n { label: \"Never\", value: \"never\" },\n { label: \"Custom date\", value: \"custom\" },\n];\n\nfunction addDays(days: number): string {\n const d = new Date();\n d.setDate(d.getDate() + days);\n return d.toISOString();\n}\n\nfunction resolveExpiresAt(expiryOption: string, customDate: Date | null): string | undefined {\n switch (expiryOption) {\n case \"30d\":\n return addDays(30);\n case \"60d\":\n return addDays(60);\n case \"90d\":\n return addDays(90);\n case \"never\":\n return undefined;\n case \"custom\":\n return customDate ? customDate.toISOString() : undefined;\n default:\n return undefined;\n }\n}\n\ninterface GenerateApiKeyModalProps {\n open: boolean;\n onClose: () => void;\n onCreated: (rawApiKey: string, keyName: string, record: ApiKeyRecord) => void;\n userId?: number;\n}\n\nexport function GenerateApiKeyModal({ open, onClose, onCreated, userId }: GenerateApiKeyModalProps) {\n const dispatch = useDispatch();\n const [generateApiKeyForUser, { isLoading }] = useGenerateApiKeyForUserMutation();\n const [customDate, setCustomDate] = useState<Date | null>(null);\n\n const formik = useFormik({\n initialValues: {\n name: \"\",\n expiryOption: \"30d\",\n },\n validationSchema: Yup.object({\n name: Yup.string()\n .trim()\n .min(2, \"Name must be at least 2 characters\")\n .max(64, \"Name must be 64 characters or fewer\")\n .required(\"Key name is required\"),\n expiryOption: Yup.string().required(\"Expiry is required\"),\n }),\n onSubmit: async (values, helpers) => {\n if (values.expiryOption === \"custom\" && !customDate) {\n helpers.setFieldError(\"expiryOption\", \"Please select a custom expiry date\");\n return;\n }\n\n const expiresAt = resolveExpiresAt(values.expiryOption, customDate);\n\n try {\n const body = { name: values.name.trim(), ...(expiresAt ? { expiresAt } : {}) };\n const response = await generateApiKeyForUser({ userId: userId!, body }).unwrap();\n\n onCreated(response.data.apiKey, values.name.trim(), response.data.record);\n handleClose();\n } catch (err: any) {\n const detail = err?.data?.message || \"Failed to generate API key. Please try again.\";\n dispatch(showToast({ severity: \"error\", summary: \"Error\", detail }));\n }\n },\n });\n\n const handleClose = () => {\n formik.resetForm();\n setCustomDate(null);\n onClose();\n };\n\n // Reset form when modal opens\n useEffect(() => {\n if (open) {\n formik.resetForm();\n setCustomDate(null);\n }\n }, [open]);\n\n const nameError =\n formik.touched.name && formik.errors.name ? String(formik.errors.name) : \"\";\n const expiryError =\n formik.touched.expiryOption && formik.errors.expiryOption\n ? String(formik.errors.expiryOption)\n : \"\";\n\n return (\n <SolidDialog open={open} onOpenChange={handleClose} style={{ maxWidth: 480 }} className=\"solid-api-key-dialog\">\n <SolidDialogHeader className=\"solid-api-key-dialog-header\">\n <SolidDialogTitle>Generate API Key</SolidDialogTitle>\n <SolidDialogDescription>\n Create a named key for this user. The raw key will be shown only once after generation.\n </SolidDialogDescription>\n </SolidDialogHeader>\n <SolidDialogSeparator />\n <SolidDialogBody className=\"solid-api-key-dialog-body\">\n <form id=\"generate-api-key-form\" onSubmit={formik.handleSubmit}>\n <div className=\"solid-api-key-dialog-fields\">\n <div className=\"solid-api-key-dialog-field\">\n <label htmlFor=\"api-key-name\" className=\"form-field-label\">\n Key Name <span style={{ color: \"var(--solid-danger-color, #ef4444)\" }}>*</span>\n </label>\n <SolidInput\n id=\"api-key-name\"\n name=\"name\"\n autoComplete=\"off\"\n placeholder=\"e.g. CI/CD pipeline, Mobile app\"\n value={formik.values.name}\n onChange={formik.handleChange}\n onBlur={formik.handleBlur}\n />\n {nameError && <SolidMessage severity=\"error\" text={nameError} />}\n </div>\n\n <div className=\"solid-api-key-dialog-field\">\n <label htmlFor=\"api-key-expiry\" className=\"form-field-label\">\n Expires\n </label>\n <SolidSelect\n value={formik.values.expiryOption}\n options={EXPIRY_OPTIONS}\n optionLabel=\"label\"\n optionValue=\"value\"\n onChange={({ value }) => {\n formik.setFieldValue(\"expiryOption\", value);\n if (value !== \"custom\") setCustomDate(null);\n }}\n />\n {formik.values.expiryOption === \"custom\" && (\n <SolidDatePicker\n selected={customDate}\n onChange={(date: Date | null) => setCustomDate(date)}\n minDate={new Date()}\n placeholderText=\"Select expiry date\"\n dateFormat=\"dd/MM/yyyy\"\n />\n )}\n {formik.values.expiryOption !== \"custom\" ? (\n <p className=\"solid-api-key-dialog-hint m-0\">Choose how long this key should remain valid.</p>\n ) : null}\n {expiryError && <SolidMessage severity=\"error\" text={expiryError} />}\n </div>\n </div>\n </form>\n </SolidDialogBody>\n <SolidDialogSeparator />\n <SolidDialogFooter className=\"solid-api-key-dialog-footer\">\n <SolidButton variant=\"outline\" type=\"button\" onClick={handleClose} disabled={isLoading}>\n Cancel\n </SolidButton>\n <SolidButton type=\"submit\" form=\"generate-api-key-form\" loading={isLoading}>\n Generate Key\n </SolidButton>\n </SolidDialogFooter>\n </SolidDialog>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"GenerateApiKeyModal.js","sourceRoot":"","sources":["../../../../../src/components/core/users/ApiKeysTab/GenerateApiKeyModal.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useEffect, useState } from \"react\";\nimport { useDispatch } from \"react-redux\";\nimport { useFormik } from \"formik\";\nimport * as Yup from \"yup\";\nimport {\n SolidButton,\n SolidDatePicker,\n SolidDialog,\n SolidDialogBody,\n SolidDialogDescription,\n SolidDialogFooter,\n SolidDialogHeader,\n SolidDialogSeparator,\n SolidDialogTitle,\n SolidInput,\n SolidMessage,\n SolidSelect,\n} from \"../../../shad-cn-ui\";\nimport { showToast } from \"../../../../redux/features/toastSlice\";\nimport { type ApiKeyRecord, useGenerateApiKeyForUserMutation } from \"../../../../redux/api/apiKeyApi\";\n\nconst EXPIRY_OPTIONS = [\n { label: \"30 days\", value: \"30d\" },\n { label: \"60 days\", value: \"60d\" },\n { label: \"90 days\", value: \"90d\" },\n { label: \"Never\", value: \"never\" },\n { label: \"Custom date\", value: \"custom\" },\n];\n\nfunction addDays(days: number): string {\n const d = new Date();\n d.setDate(d.getDate() + days);\n return d.toISOString();\n}\n\nfunction resolveExpiresAt(expiryOption: string, customDate: Date | null): string | undefined {\n switch (expiryOption) {\n case \"30d\":\n return addDays(30);\n case \"60d\":\n return addDays(60);\n case \"90d\":\n return addDays(90);\n case \"never\":\n return undefined;\n case \"custom\":\n return customDate ? customDate.toISOString() : undefined;\n default:\n return undefined;\n }\n}\n\ninterface GenerateApiKeyModalProps {\n open: boolean;\n onClose: () => void;\n onCreated: (rawApiKey: string, keyName: string, record: ApiKeyRecord) => void;\n userId?: number;\n}\n\nexport function GenerateApiKeyModal({ open, onClose, onCreated, userId }: GenerateApiKeyModalProps) {\n const dispatch = useDispatch();\n const [generateApiKeyForUser, { isLoading }] = useGenerateApiKeyForUserMutation();\n const [customDate, setCustomDate] = useState<Date | null>(null);\n\n const formik = useFormik({\n initialValues: {\n name: \"\",\n expiryOption: \"30d\",\n },\n validationSchema: Yup.object({\n name: Yup.string()\n .trim()\n .min(2, \"Name must be at least 2 characters\")\n .max(64, \"Name must be 64 characters or fewer\")\n .required(\"Key name is required\"),\n expiryOption: Yup.string().required(\"Expiry is required\"),\n }),\n onSubmit: async (values, helpers) => {\n if (values.expiryOption === \"custom\" && !customDate) {\n helpers.setFieldError(\"expiryOption\", \"Please select a custom expiry date\");\n return;\n }\n\n const expiresAt = resolveExpiresAt(values.expiryOption, customDate);\n\n try {\n const body = { name: values.name.trim(), ...(expiresAt ? { expiresAt } : {}) };\n const response = await generateApiKeyForUser({ userId: userId!, body }).unwrap();\n\n onCreated(response.data.apiKey, values.name.trim(), response.data.record);\n handleClose();\n } catch (err: any) {\n const detail = err?.data?.message || \"Failed to generate API key. Please try again.\";\n dispatch(showToast({ severity: \"error\", summary: \"Error\", detail }));\n }\n },\n });\n\n const handleClose = () => {\n formik.resetForm();\n setCustomDate(null);\n onClose();\n };\n\n // Reset form when modal opens\n useEffect(() => {\n if (open) {\n formik.resetForm();\n setCustomDate(null);\n }\n }, [open]);\n\n const nameError =\n formik.touched.name && formik.errors.name ? String(formik.errors.name) : \"\";\n const expiryError =\n formik.touched.expiryOption && formik.errors.expiryOption\n ? String(formik.errors.expiryOption)\n : \"\";\n\n return (\n <SolidDialog open={open} onOpenChange={handleClose} style={{ maxWidth: 480 }} className=\"solid-api-key-dialog\">\n <SolidDialogHeader className=\"solid-api-key-dialog-header\">\n <SolidDialogTitle>Generate API Key</SolidDialogTitle>\n <SolidDialogDescription>\n Create a named key for this user. The raw key will be shown only once after generation.\n </SolidDialogDescription>\n </SolidDialogHeader>\n <SolidDialogSeparator />\n <SolidDialogBody className=\"solid-api-key-dialog-body\">\n <form id=\"generate-api-key-form\" onSubmit={formik.handleSubmit}>\n <div className=\"solid-api-key-dialog-fields\">\n <div className=\"solid-api-key-dialog-field\">\n <label htmlFor=\"api-key-name\" className=\"form-field-label\">\n Key Name <span style={{ color: \"var(--solid-danger-color, #ef4444)\" }}>*</span>\n </label>\n <SolidInput\n id=\"api-key-name\"\n name=\"name\"\n autoComplete=\"off\"\n placeholder=\"e.g. CI/CD pipeline, Mobile app\"\n value={formik.values.name}\n onChange={formik.handleChange}\n onBlur={formik.handleBlur}\n />\n {nameError && <SolidMessage severity=\"error\" text={nameError} />}\n </div>\n\n <div className=\"solid-api-key-dialog-field\">\n <label htmlFor=\"api-key-expiry\" className=\"form-field-label\">\n Expires\n </label>\n <SolidSelect\n value={formik.values.expiryOption}\n options={EXPIRY_OPTIONS}\n optionLabel=\"label\"\n optionValue=\"value\"\n onChange={({ value }) => {\n formik.setFieldValue(\"expiryOption\", value);\n if (value !== \"custom\") setCustomDate(null);\n }}\n native={false}\n />\n {formik.values.expiryOption === \"custom\" && (\n <SolidDatePicker\n selected={customDate}\n onChange={(date: Date | null) => setCustomDate(date)}\n minDate={new Date()}\n placeholderText=\"Select expiry date\"\n dateFormat=\"dd/MM/yyyy\"\n />\n )}\n {formik.values.expiryOption !== \"custom\" ? (\n <p className=\"solid-api-key-dialog-hint m-0\">Choose how long this key should remain valid.</p>\n ) : null}\n {expiryError && <SolidMessage severity=\"error\" text={expiryError} />}\n </div>\n </div>\n </form>\n </SolidDialogBody>\n <SolidDialogSeparator />\n <SolidDialogFooter className=\"solid-api-key-dialog-footer\">\n <SolidButton variant=\"outline\" type=\"button\" onClick={handleClose} disabled={isLoading}>\n Cancel\n </SolidButton>\n <SolidButton type=\"submit\" form=\"generate-api-key-form\" loading={isLoading}>\n Generate Key\n </SolidButton>\n </SolidDialogFooter>\n </SolidDialog>\n );\n}\n"]}
|
|
@@ -158,6 +158,7 @@ export function GenerateApiKeyModal({ open, onClose, onCreated, userId }: Genera
|
|
|
158
158
|
formik.setFieldValue("expiryOption", value);
|
|
159
159
|
if (value !== "custom") setCustomDate(null);
|
|
160
160
|
}}
|
|
161
|
+
native={false}
|
|
161
162
|
/>
|
|
162
163
|
{formik.values.expiryOption === "custom" && (
|
|
163
164
|
<SolidDatePicker
|