@solidxai/core-ui 0.1.13-beta.4 → 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 +69 -40
- package/dist/components/core/card/SolidCardView.js.map +1 -1
- package/dist/components/core/card/SolidCardView.tsx +55 -24
- 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/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 +67 -48
- package/dist/components/core/kanban/SolidKanbanView.js.map +1 -1
- package/dist/components/core/kanban/SolidKanbanView.tsx +51 -11
- 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 +11 -2
- package/dist/components/core/kanban/SolidKanbanViewConfigure.js.map +1 -1
- package/dist/components/core/kanban/SolidKanbanViewConfigure.tsx +35 -0
- package/dist/components/core/list/SolidListView.d.ts.map +1 -1
- package/dist/components/core/list/SolidListView.js +6 -2
- package/dist/components/core/list/SolidListView.js.map +1 -1
- package/dist/components/core/list/SolidListView.tsx +7 -1
- package/dist/components/core/list/SolidListViewConfigure.d.ts.map +1 -1
- package/dist/components/core/list/SolidListViewConfigure.js +15 -11
- package/dist/components/core/list/SolidListViewConfigure.js.map +1 -1
- package/dist/components/core/list/SolidListViewConfigure.tsx +25 -6
- 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 +249 -138
- package/dist/components/core/tree/SolidTreeView.js.map +1 -1
- package/dist/components/core/tree/SolidTreeView.tsx +220 -92
- 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/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
|
@@ -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
|
|
|
@@ -604,6 +630,18 @@ export const SolidTreeView = forwardRef<SolidTreeViewHandle, SolidTreeViewParams
|
|
|
604
630
|
groupPath
|
|
605
631
|
.map((item) => buildImplicitFilterCondition(item));
|
|
606
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
|
+
|
|
607
645
|
const mergeFiltersWithImplicit = (implicitFilters: any[]) => {
|
|
608
646
|
const baseFilters = latestFiltersRef.current;
|
|
609
647
|
const hasBaseFilters = baseFilters && Object.keys(baseFilters).length > 0;
|
|
@@ -759,7 +797,8 @@ export const SolidTreeView = forwardRef<SolidTreeViewHandle, SolidTreeViewParams
|
|
|
759
797
|
|
|
760
798
|
const queryString = qs.stringify(queryData, { encodeValuesOnly: true });
|
|
761
799
|
|
|
762
|
-
const
|
|
800
|
+
const request = triggerGetSolidEntities(queryString);
|
|
801
|
+
const response = await request.unwrap().finally(() => request.unsubscribe());
|
|
763
802
|
return { queryData, queryString, response };
|
|
764
803
|
};
|
|
765
804
|
|
|
@@ -825,7 +864,8 @@ export const SolidTreeView = forwardRef<SolidTreeViewHandle, SolidTreeViewParams
|
|
|
825
864
|
|
|
826
865
|
|
|
827
866
|
|
|
828
|
-
const
|
|
867
|
+
const request = triggerGetSolidEntities(queryString);
|
|
868
|
+
const response = await request.unwrap().finally(() => request.unsubscribe());
|
|
829
869
|
return { queryData, queryString, response };
|
|
830
870
|
};
|
|
831
871
|
|
|
@@ -835,7 +875,6 @@ export const SolidTreeView = forwardRef<SolidTreeViewHandle, SolidTreeViewParams
|
|
|
835
875
|
groupMetaRows: any[],
|
|
836
876
|
ruleIndex: number,
|
|
837
877
|
parentPath: GroupPathItem[],
|
|
838
|
-
parentKey: string
|
|
839
878
|
): TreeNode[] => {
|
|
840
879
|
const rule = activeGroupingRules[ruleIndex];
|
|
841
880
|
if (!rule?.fieldName) return [];
|
|
@@ -844,7 +883,7 @@ export const SolidTreeView = forwardRef<SolidTreeViewHandle, SolidTreeViewParams
|
|
|
844
883
|
const filterField = getResolvedGroupField(fieldName);
|
|
845
884
|
// const dateGranularity = dateTimeImplicitFilter(rule);
|
|
846
885
|
const dateGranularity = getDateGranularity(rule);
|
|
847
|
-
return (groupMetaRows || []).map((groupMeta
|
|
886
|
+
return (groupMetaRows || []).map((groupMeta) => {
|
|
848
887
|
const rawGroupLabel = groupMeta?.groupName;
|
|
849
888
|
const normalizedGroupLabel =
|
|
850
889
|
rawGroupLabel === "[object Object]"
|
|
@@ -860,7 +899,7 @@ export const SolidTreeView = forwardRef<SolidTreeViewHandle, SolidTreeViewParams
|
|
|
860
899
|
];
|
|
861
900
|
|
|
862
901
|
return {
|
|
863
|
-
key:
|
|
902
|
+
key: getGroupNodeKey(groupPath),
|
|
864
903
|
data: {
|
|
865
904
|
__treeMeta: {
|
|
866
905
|
nodeType: "group",
|
|
@@ -915,12 +954,60 @@ export const SolidTreeView = forwardRef<SolidTreeViewHandle, SolidTreeViewParams
|
|
|
915
954
|
});
|
|
916
955
|
};
|
|
917
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
|
+
|
|
918
1004
|
// ─── Root group load / paginate ───────────────────────────────────────────
|
|
919
1005
|
|
|
920
|
-
const loadRootGroups = async (offset = 0) => {
|
|
1006
|
+
const loadRootGroups = async (offset = 0, affectedGroupPaths: GroupPathItem[][] = []) => {
|
|
921
1007
|
if (!solidTreeViewMetaData || activeGroupingRules.length === 0) {
|
|
922
1008
|
setTreeNodes([]);
|
|
923
1009
|
setExpandedKeys({});
|
|
1010
|
+
setPaginationMap({});
|
|
924
1011
|
|
|
925
1012
|
const queryObject = getFilterObjectFromLocalStorage();
|
|
926
1013
|
if (queryObject) {
|
|
@@ -936,13 +1023,46 @@ export const SolidTreeView = forwardRef<SolidTreeViewHandle, SolidTreeViewParams
|
|
|
936
1023
|
setTreeLoading(true);
|
|
937
1024
|
try {
|
|
938
1025
|
const { response } = await runGroupedQuery(0, [], offset, limit);
|
|
939
|
-
const rootNodes = buildGroupNodes(response?.groupMeta || [], 0, []
|
|
940
|
-
setTreeNodes(rootNodes);
|
|
941
|
-
setExpandedKeys({});
|
|
942
|
-
setSelectedNodeKeys({});
|
|
943
|
-
// Collapse expanded keys since data changed
|
|
1026
|
+
const rootNodes = buildGroupNodes(response?.groupMeta || [], 0, []);
|
|
944
1027
|
const total = response?.meta.totalRecords ?? 0;
|
|
945
|
-
|
|
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({});
|
|
946
1066
|
|
|
947
1067
|
if (latestFilterPredicatesRef.current && latestFilterPredicatesRef.current.persistFilter) {
|
|
948
1068
|
let queryData: any = {
|
|
@@ -966,7 +1086,6 @@ export const SolidTreeView = forwardRef<SolidTreeViewHandle, SolidTreeViewParams
|
|
|
966
1086
|
}
|
|
967
1087
|
|
|
968
1088
|
} catch (error: any) {
|
|
969
|
-
setTreeNodes([]);
|
|
970
1089
|
dispatch(showToast({ severity: "error", summary: "Failed to load tree", detail: error?.data?.message || error?.message || "Unable to load grouped data", life: 4000 }));
|
|
971
1090
|
} finally {
|
|
972
1091
|
setTreeLoading(false);
|
|
@@ -990,33 +1109,10 @@ export const SolidTreeView = forwardRef<SolidTreeViewHandle, SolidTreeViewParams
|
|
|
990
1109
|
|
|
991
1110
|
const nodeKey = String(node.key);
|
|
992
1111
|
const limit = getPagination(nodeKey).limit || globalLimit || DEFAULT_PAGE_SIZE;
|
|
993
|
-
const nextRuleIndex = meta.ruleIndex + 1;
|
|
994
1112
|
|
|
995
1113
|
setTreeLoading(true);
|
|
996
1114
|
try {
|
|
997
|
-
|
|
998
|
-
let total = 0;
|
|
999
|
-
|
|
1000
|
-
if (nextRuleIndex < activeGroupingRules.length) {
|
|
1001
|
-
|
|
1002
|
-
const { response } = await runGroupedQuery(
|
|
1003
|
-
nextRuleIndex,
|
|
1004
|
-
meta.groupPath || [],
|
|
1005
|
-
offset,
|
|
1006
|
-
limit
|
|
1007
|
-
);
|
|
1008
|
-
children = buildGroupNodes(
|
|
1009
|
-
response?.groupMeta || [],
|
|
1010
|
-
nextRuleIndex,
|
|
1011
|
-
meta.groupPath || [],
|
|
1012
|
-
nodeKey
|
|
1013
|
-
);
|
|
1014
|
-
total = response?.meta.totalRecords ?? 0;
|
|
1015
|
-
} else {
|
|
1016
|
-
const { response } = await runLeafQuery(meta.groupPath || [], offset, limit);
|
|
1017
|
-
children = buildRecordNodes(response?.records || [], nodeKey, meta.groupPath || []);
|
|
1018
|
-
total = response?.meta.totalRecords ?? 0;
|
|
1019
|
-
}
|
|
1115
|
+
const { children, total } = await fetchNodeChildren(node, offset, limit);
|
|
1020
1116
|
|
|
1021
1117
|
setTreeNodes((prev) => updateNodeChildren(prev, nodeKey, children));
|
|
1022
1118
|
setPagination(node.key as string, { offset, total: total, limit });
|
|
@@ -1213,6 +1309,9 @@ export const SolidTreeView = forwardRef<SolidTreeViewHandle, SolidTreeViewParams
|
|
|
1213
1309
|
// handle bulk deletion
|
|
1214
1310
|
const deleteBulk = async () => {
|
|
1215
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));
|
|
1216
1315
|
if (deleteList.length === 0) {
|
|
1217
1316
|
setDeleteRecordsDialogVisible(false);
|
|
1218
1317
|
return;
|
|
@@ -1222,7 +1321,7 @@ export const SolidTreeView = forwardRef<SolidTreeViewHandle, SolidTreeViewParams
|
|
|
1222
1321
|
await deleteManySolidEntities(deleteList).unwrap();
|
|
1223
1322
|
dispatch(showToast({ severity: 'success', summary: 'Deleted', detail: ERROR_MESSAGES.RECORD_DELETE, life: 3000 }));
|
|
1224
1323
|
setDeleteRecordsDialogVisible(false);
|
|
1225
|
-
await loadRootGroups(getPagination("root").offset);
|
|
1324
|
+
await loadRootGroups(getPagination("root").offset, affectedGroupPaths);
|
|
1226
1325
|
} catch (error: any) {
|
|
1227
1326
|
dispatch(showToast({ severity: 'error', summary: 'Delete Failed', detail: error?.data?.message, life: 4000 }));
|
|
1228
1327
|
}
|
|
@@ -1238,6 +1337,9 @@ export const SolidTreeView = forwardRef<SolidTreeViewHandle, SolidTreeViewParams
|
|
|
1238
1337
|
|
|
1239
1338
|
const recoverAll = async () => {
|
|
1240
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));
|
|
1241
1343
|
if (recoverList.length === 0) {
|
|
1242
1344
|
setRecoverDialogVisible(false);
|
|
1243
1345
|
return;
|
|
@@ -1252,7 +1354,7 @@ export const SolidTreeView = forwardRef<SolidTreeViewHandle, SolidTreeViewParams
|
|
|
1252
1354
|
detail: response?.data?.message || "Records recovered successfully.",
|
|
1253
1355
|
life: 3000,
|
|
1254
1356
|
}));
|
|
1255
|
-
await loadRootGroups(getPagination("root").offset);
|
|
1357
|
+
await loadRootGroups(getPagination("root").offset, affectedGroupPaths);
|
|
1256
1358
|
} catch (error: any) {
|
|
1257
1359
|
dispatch(showToast({
|
|
1258
1360
|
severity: "error",
|
|
@@ -1292,8 +1394,8 @@ export const SolidTreeView = forwardRef<SolidTreeViewHandle, SolidTreeViewParams
|
|
|
1292
1394
|
solidListViewMetaData: solidTreeViewMetaData,
|
|
1293
1395
|
fieldMetadata,
|
|
1294
1396
|
column,
|
|
1295
|
-
setLightboxUrls
|
|
1296
|
-
setOpenLightbox
|
|
1397
|
+
setLightboxUrls,
|
|
1398
|
+
setOpenLightbox,
|
|
1297
1399
|
});
|
|
1298
1400
|
|
|
1299
1401
|
if (!React.isValidElement(listColumn)) return null;
|
|
@@ -1490,9 +1592,19 @@ export const SolidTreeView = forwardRef<SolidTreeViewHandle, SolidTreeViewParams
|
|
|
1490
1592
|
|
|
1491
1593
|
|
|
1492
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
|
+
);
|
|
1493
1604
|
|
|
1494
1605
|
const [selectedSolidViewData, setSelectedSolidViewData] = useState<any>();
|
|
1495
1606
|
const [deleteEntity, setDeleteEntity] = useState(false);
|
|
1607
|
+
const entityDisplayName = solidTreeViewMetaData?.data?.solidView?.model?.displayName || params?.modelName;
|
|
1496
1608
|
const openRowForEdit = (rowData: any, viewMode: "edit" | "view") => {
|
|
1497
1609
|
storeCurrentModelViewContext();
|
|
1498
1610
|
|
|
@@ -1537,13 +1649,16 @@ export const SolidTreeView = forwardRef<SolidTreeViewHandle, SolidTreeViewParams
|
|
|
1537
1649
|
throw new Error(ERROR_MESSAGES.NO_ENTITY_SELECTED);
|
|
1538
1650
|
}
|
|
1539
1651
|
|
|
1652
|
+
const affectedGroupPath = selectedSolidViewData?.__treeMeta?.groupPath;
|
|
1540
1653
|
const response: any = await deleteSolidSingleEntiry(selectedSolidViewData.id);
|
|
1541
|
-
|
|
1542
1654
|
if (response?.data?.statusCode === 200) {
|
|
1543
1655
|
setDeleteEntity(false);
|
|
1544
1656
|
setSelectedSolidViewData(undefined);
|
|
1545
1657
|
dispatch(showToast({ severity: "success", summary: ERROR_MESSAGES.DELETED, detail: ERROR_MESSAGES.ENTITY_DELETE, life: 3000 }));
|
|
1546
|
-
await loadRootGroups(
|
|
1658
|
+
await loadRootGroups(
|
|
1659
|
+
getPagination("root").offset,
|
|
1660
|
+
Array.isArray(affectedGroupPath) ? [affectedGroupPath] : [],
|
|
1661
|
+
);
|
|
1547
1662
|
} else {
|
|
1548
1663
|
dispatch(showToast({ severity: "error", summary: ERROR_MESSAGES.DELETE_FAIELD, detail: response?.error?.data?.error, sticky: true }));
|
|
1549
1664
|
}
|
|
@@ -1563,7 +1678,10 @@ export const SolidTreeView = forwardRef<SolidTreeViewHandle, SolidTreeViewParams
|
|
|
1563
1678
|
detail: response?.data?.message || "Record recovered successfully.",
|
|
1564
1679
|
life: 3000,
|
|
1565
1680
|
}));
|
|
1566
|
-
await loadRootGroups(
|
|
1681
|
+
await loadRootGroups(
|
|
1682
|
+
getPagination("root").offset,
|
|
1683
|
+
Array.isArray(record?.__treeMeta?.groupPath) ? [record.__treeMeta.groupPath] : [],
|
|
1684
|
+
);
|
|
1567
1685
|
} catch (error: any) {
|
|
1568
1686
|
dispatch(showToast({
|
|
1569
1687
|
severity: "error",
|
|
@@ -1768,6 +1886,7 @@ export const SolidTreeView = forwardRef<SolidTreeViewHandle, SolidTreeViewParams
|
|
|
1768
1886
|
ref={solidGlobalSearchElementRef}
|
|
1769
1887
|
viewData={solidTreeViewMetaData}
|
|
1770
1888
|
handleApplyCustomFilter={handleApplyCustomFilter}
|
|
1889
|
+
filterPredicates={filterPredicates}
|
|
1771
1890
|
/>
|
|
1772
1891
|
</div>
|
|
1773
1892
|
)}
|
|
@@ -1789,6 +1908,22 @@ export const SolidTreeView = forwardRef<SolidTreeViewHandle, SolidTreeViewParams
|
|
|
1789
1908
|
</div>
|
|
1790
1909
|
)}
|
|
1791
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
|
+
|
|
1792
1927
|
{actionsAllowed.includes(`${permissionExpression(params.modelName, "create")}`) &&
|
|
1793
1928
|
solidTreeViewMetaData?.data?.solidView?.layout?.attrs.create !== false && (
|
|
1794
1929
|
<SolidCreateButton
|
|
@@ -1858,7 +1993,7 @@ export const SolidTreeView = forwardRef<SolidTreeViewHandle, SolidTreeViewParams
|
|
|
1858
1993
|
</div>
|
|
1859
1994
|
|
|
1860
1995
|
{solidTreeViewMetaData?.data?.solidView?.layout?.attrs.enableGlobalSearch === true &&
|
|
1861
|
-
|
|
1996
|
+
shouldShowMobileSearchElement && (
|
|
1862
1997
|
<div className="flex lg:hidden">
|
|
1863
1998
|
<SolidGlobalSearchElement
|
|
1864
1999
|
viewType="tree"
|
|
@@ -1867,6 +2002,7 @@ export const SolidTreeView = forwardRef<SolidTreeViewHandle, SolidTreeViewParams
|
|
|
1867
2002
|
ref={solidGlobalSearchElementRef}
|
|
1868
2003
|
viewData={solidTreeViewMetaData}
|
|
1869
2004
|
handleApplyCustomFilter={handleApplyCustomFilter}
|
|
2005
|
+
filterPredicates={filterPredicates}
|
|
1870
2006
|
/>
|
|
1871
2007
|
</div>
|
|
1872
2008
|
)}
|
|
@@ -2050,53 +2186,37 @@ export const SolidTreeView = forwardRef<SolidTreeViewHandle, SolidTreeViewParams
|
|
|
2050
2186
|
</div>
|
|
2051
2187
|
</div>
|
|
2052
2188
|
|
|
2053
|
-
<
|
|
2189
|
+
<SolidConfirmDialog
|
|
2054
2190
|
open={deleteEntity}
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
</SolidDialogDescription>
|
|
2071
|
-
</SolidDialogBody>
|
|
2072
|
-
<SolidDialogFooter>
|
|
2073
|
-
<SolidButton label="Cancel" size="sm" variant="outline" onClick={() => setDeleteEntity(false)} />
|
|
2074
|
-
<SolidButton label="Delete" size="sm" severity="danger" onClick={handleDeleteEntity} />
|
|
2075
|
-
</SolidDialogFooter>
|
|
2076
|
-
</SolidDialog>
|
|
2077
|
-
|
|
2078
|
-
<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
|
|
2079
2206
|
open={isDeleteRecordsDialogVisible}
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
<
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
</SolidDialogDescription>
|
|
2094
|
-
</SolidDialogBody>
|
|
2095
|
-
<SolidDialogFooter>
|
|
2096
|
-
<SolidButton label="Cancel" size="sm" variant="outline" onClick={onDeleteClose} />
|
|
2097
|
-
<SolidButton label="Delete" size="sm" severity="danger" onClick={deleteBulk} />
|
|
2098
|
-
</SolidDialogFooter>
|
|
2099
|
-
</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
|
+
/>
|
|
2100
2220
|
|
|
2101
2221
|
<SolidDialog
|
|
2102
2222
|
open={isRecoverDialogVisible}
|
|
@@ -2121,6 +2241,14 @@ export const SolidTreeView = forwardRef<SolidTreeViewHandle, SolidTreeViewParams
|
|
|
2121
2241
|
</SolidDialogFooter>
|
|
2122
2242
|
</SolidDialog>
|
|
2123
2243
|
|
|
2244
|
+
{openLightbox && (
|
|
2245
|
+
<SolidLightbox
|
|
2246
|
+
open={openLightbox}
|
|
2247
|
+
slides={lightboxSlides}
|
|
2248
|
+
onClose={() => setOpenLightbox(false)}
|
|
2249
|
+
/>
|
|
2250
|
+
)}
|
|
2251
|
+
|
|
2124
2252
|
</div>
|
|
2125
2253
|
);
|
|
2126
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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACnC,OAAO,KAAK,GAAG,MAAM,KAAK,CAAC;AAC3B,OAAO,EACL,WAAW,EACX,eAAe,EACf,WAAW,EACX,eAAe,EACf,sBAAsB,EACtB,iBAAiB,EACjB,iBAAiB,EACjB,oBAAoB,EACpB,gBAAgB,EAChB,UAAU,EACV,YAAY,EACZ,WAAW,GACZ,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,SAAS,EAAE,MAAM,uCAAuC,CAAC;AAClE,OAAO,EAAqB,gCAAgC,EAAE,MAAM,iCAAiC,CAAC;AAEtG,IAAM,cAAc,GAAG;IACrB,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE;IAClC,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE;IAClC,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE;IAClC,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE;IAClC,EAAE,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,QAAQ,EAAE;CAC1C,CAAC;AAEF,SAAS,OAAO,CAAC,IAAY;IAC3B,IAAM,CAAC,GAAG,IAAI,IAAI,EAAE,CAAC;IACrB,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,CAAC;IAC9B,OAAO,CAAC,CAAC,WAAW,EAAE,CAAC;AACzB,CAAC;AAED,SAAS,gBAAgB,CAAC,YAAoB,EAAE,UAAuB;IACrE,QAAQ,YAAY,EAAE;QACpB,KAAK,KAAK;YACR,OAAO,OAAO,CAAC,EAAE,CAAC,CAAC;QACrB,KAAK,KAAK;YACR,OAAO,OAAO,CAAC,EAAE,CAAC,CAAC;QACrB,KAAK,KAAK;YACR,OAAO,OAAO,CAAC,EAAE,CAAC,CAAC;QACrB,KAAK,OAAO;YACV,OAAO,SAAS,CAAC;QACnB,KAAK,QAAQ;YACX,OAAO,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;QAC3D;YACE,OAAO,SAAS,CAAC;KACpB;AACH,CAAC;AASD,MAAM,UAAU,mBAAmB,CAAC,EAA8D;IAAlG,iBAkIC;QAlIqC,IAAI,UAAA,EAAE,OAAO,aAAA,EAAE,SAAS,eAAA,EAAE,MAAM,YAAA;IACpE,IAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;IACzB,IAAA,KAAyC,gCAAgC,EAAE,EAA1E,qBAAqB,QAAA,EAAI,SAAS,kBAAwC,CAAC;IAC5E,IAAA,KAA8B,QAAQ,CAAc,IAAI,CAAC,EAAxD,UAAU,QAAA,EAAE,aAAa,QAA+B,CAAC;IAEhE,IAAM,MAAM,GAAG,SAAS,CAAC;QACvB,aAAa,EAAE;YACb,IAAI,EAAE,EAAE;YACR,YAAY,EAAE,KAAK;SACpB;QACD,gBAAgB,EAAE,GAAG,CAAC,MAAM,CAAC;YAC3B,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE;iBACf,IAAI,EAAE;iBACN,GAAG,CAAC,CAAC,EAAE,oCAAoC,CAAC;iBAC5C,GAAG,CAAC,EAAE,EAAE,qCAAqC,CAAC;iBAC9C,QAAQ,CAAC,sBAAsB,CAAC;YACnC,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,oBAAoB,CAAC;SAC1D,CAAC;QACF,QAAQ,EAAE,UAAO,MAAM,EAAE,OAAO;;;;;;wBAC9B,IAAI,MAAM,CAAC,YAAY,KAAK,QAAQ,IAAI,CAAC,UAAU,EAAE;4BACnD,OAAO,CAAC,aAAa,CAAC,cAAc,EAAE,oCAAoC,CAAC,CAAC;4BAC5E,sBAAO;yBACR;wBAEK,SAAS,GAAG,gBAAgB,CAAC,MAAM,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC;;;;wBAG5D,IAAI,cAAK,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,IAAK,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,WAAA,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAE,CAAC;wBAC9D,qBAAM,qBAAqB,CAAC,EAAE,MAAM,EAAE,MAAO,EAAE,IAAI,MAAA,EAAE,CAAC,CAAC,MAAM,EAAE,EAAA;;wBAA1E,QAAQ,GAAG,SAA+D;wBAEhF,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;wBAC1E,WAAW,EAAE,CAAC;;;;wBAER,MAAM,GAAG,CAAA,MAAA,KAAG,aAAH,KAAG,uBAAH,KAAG,CAAE,IAAI,0CAAE,OAAO,KAAI,+CAA+C,CAAC;wBACrF,QAAQ,CAAC,SAAS,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,QAAA,EAAE,CAAC,CAAC,CAAC;;;;;aAExE;KACF,CAAC,CAAC;IAEH,IAAM,WAAW,GAAG;QAClB,MAAM,CAAC,SAAS,EAAE,CAAC;QACnB,aAAa,CAAC,IAAI,CAAC,CAAC;QACpB,OAAO,EAAE,CAAC;IACZ,CAAC,CAAC;IAEF,8BAA8B;IAC9B,SAAS,CAAC;QACR,IAAI,IAAI,EAAE;YACR,MAAM,CAAC,SAAS,EAAE,CAAC;YACnB,aAAa,CAAC,IAAI,CAAC,CAAC;SACrB;IACH,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAEX,IAAM,SAAS,GACb,MAAM,CAAC,OAAO,CAAC,IAAI,IAAI,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC9E,IAAM,WAAW,GACf,MAAM,CAAC,OAAO,CAAC,YAAY,IAAI,MAAM,CAAC,MAAM,CAAC,YAAY;QACvD,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC;QACpC,CAAC,CAAC,EAAE,CAAC;IAET,OAAO,CACL,MAAC,WAAW,IAAC,IAAI,EAAE,IAAI,EAAE,YAAY,EAAE,WAAW,EAAE,KAAK,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE,EAAE,SAAS,EAAC,sBAAsB,aAC5G,MAAC,iBAAiB,IAAC,SAAS,EAAC,6BAA6B,aACxD,KAAC,gBAAgB,mCAAoC,EACrD,KAAC,sBAAsB,0GAEE,IACP,EACpB,KAAC,oBAAoB,KAAG,EACxB,KAAC,eAAe,IAAC,SAAS,EAAC,2BAA2B,YACpD,eAAM,EAAE,EAAC,uBAAuB,EAAC,QAAQ,EAAE,MAAM,CAAC,YAAY,YAC5D,eAAK,SAAS,EAAC,6BAA6B,aAC1C,eAAK,SAAS,EAAC,4BAA4B,aACzC,iBAAO,OAAO,EAAC,cAAc,EAAC,SAAS,EAAC,kBAAkB,0BAC/C,eAAM,KAAK,EAAE,EAAE,KAAK,EAAE,oCAAoC,EAAE,kBAAU,IACzE,EACR,KAAC,UAAU,IACT,EAAE,EAAC,cAAc,EACjB,IAAI,EAAC,MAAM,EACX,YAAY,EAAC,KAAK,EAClB,WAAW,EAAC,iCAAiC,EAC7C,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,EACzB,QAAQ,EAAE,MAAM,CAAC,YAAY,EAC7B,MAAM,EAAE,MAAM,CAAC,UAAU,GACzB,EACD,SAAS,IAAI,KAAC,YAAY,IAAC,QAAQ,EAAC,OAAO,EAAC,IAAI,EAAE,SAAS,GAAI,IAC5D,EAEN,eAAK,SAAS,EAAC,4BAA4B,aACzC,gBAAO,OAAO,EAAC,gBAAgB,EAAC,SAAS,EAAC,kBAAkB,wBAEpD,EACR,KAAC,WAAW,IACV,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,YAAY,EACjC,OAAO,EAAE,cAAc,EACvB,WAAW,EAAC,OAAO,EACnB,WAAW,EAAC,OAAO,EACnB,QAAQ,EAAE,UAAC,EAAS;gDAAP,KAAK,WAAA;4CAChB,MAAM,CAAC,aAAa,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;4CAC5C,IAAI,KAAK,KAAK,QAAQ;gDAAE,aAAa,CAAC,IAAI,CAAC,CAAC;wCAC9C,CAAC,GACD,EACD,MAAM,CAAC,MAAM,CAAC,YAAY,KAAK,QAAQ,IAAI,CAC1C,KAAC,eAAe,IACd,QAAQ,EAAE,UAAU,EACpB,QAAQ,EAAE,UAAC,IAAiB,IAAK,OAAA,aAAa,CAAC,IAAI,CAAC,EAAnB,CAAmB,EACpD,OAAO,EAAE,IAAI,IAAI,EAAE,EACnB,eAAe,EAAC,oBAAoB,EACpC,UAAU,EAAC,YAAY,GACvB,CACH,EACA,MAAM,CAAC,MAAM,CAAC,YAAY,KAAK,QAAQ,CAAC,CAAC,CAAC,CACzC,YAAG,SAAS,EAAC,+BAA+B,8DAAkD,CAC/F,CAAC,CAAC,CAAC,IAAI,EACP,WAAW,IAAI,KAAC,YAAY,IAAC,QAAQ,EAAC,OAAO,EAAC,IAAI,EAAE,WAAW,GAAI,IAChE,IACF,GACD,GACS,EAClB,KAAC,oBAAoB,KAAG,EACxB,MAAC,iBAAiB,IAAC,SAAS,EAAC,6BAA6B,aACxD,KAAC,WAAW,IAAC,OAAO,EAAC,SAAS,EAAC,IAAI,EAAC,QAAQ,EAAC,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,SAAS,uBAExE,EACd,KAAC,WAAW,IAAC,IAAI,EAAC,QAAQ,EAAC,IAAI,EAAC,uBAAuB,EAAC,OAAO,EAAE,SAAS,6BAE5D,IACI,IACR,CACf,CAAC;AACJ,CAAC","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
|