mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-09-22 13:39:35 +00:00
Feat: Visualize imported folders in overview page
This commit is contained in:
@@ -13,9 +13,9 @@ import { secretSnapshotKeys } from "../secretSnapshots/queries";
|
||||
import {
|
||||
TCreateFolderDTO,
|
||||
TDeleteFolderDTO,
|
||||
TFetchProjectFoldersResponse,
|
||||
TGetFoldersByEnvDTO,
|
||||
TGetProjectFoldersDTO,
|
||||
TSecretFolder,
|
||||
TUpdateFolderDTO
|
||||
} from "./types";
|
||||
|
||||
@@ -25,14 +25,14 @@ export const folderQueryKeys = {
|
||||
};
|
||||
|
||||
const fetchProjectFolders = async (workspaceId: string, environment: string, path = "/") => {
|
||||
const { data } = await apiRequest.get<{ folders: TSecretFolder[] }>("/api/v1/folders", {
|
||||
const { data } = await apiRequest.get<TFetchProjectFoldersResponse>("/api/v1/folders", {
|
||||
params: {
|
||||
workspaceId,
|
||||
environment,
|
||||
path
|
||||
}
|
||||
});
|
||||
return data.folders;
|
||||
return data;
|
||||
};
|
||||
|
||||
export const useGetProjectFolders = ({
|
||||
@@ -43,9 +43,9 @@ export const useGetProjectFolders = ({
|
||||
}: TGetProjectFoldersDTO & {
|
||||
options?: Omit<
|
||||
UseQueryOptions<
|
||||
TSecretFolder[],
|
||||
TFetchProjectFoldersResponse,
|
||||
unknown,
|
||||
TSecretFolder[],
|
||||
TFetchProjectFoldersResponse,
|
||||
ReturnType<typeof folderQueryKeys.getSecretFolders>
|
||||
>,
|
||||
"queryKey" | "queryFn"
|
||||
@@ -74,7 +74,7 @@ export const useGetFoldersByEnv = ({
|
||||
const folderNames = useMemo(() => {
|
||||
const names = new Set<string>();
|
||||
folders?.forEach(({ data }) => {
|
||||
data?.forEach(({ name }) => {
|
||||
data?.folders?.forEach(({ name }) => {
|
||||
names.add(name);
|
||||
});
|
||||
});
|
||||
@@ -85,16 +85,34 @@ export const useGetFoldersByEnv = ({
|
||||
(name: string, env: string) => {
|
||||
const selectedEnvIndex = environments.indexOf(env);
|
||||
if (selectedEnvIndex !== -1) {
|
||||
return Boolean(
|
||||
folders?.[selectedEnvIndex]?.data?.find(({ name: folderName }) => folderName === name)
|
||||
const isPresent = folders?.[selectedEnvIndex]?.data?.folders.find(
|
||||
({ name: folderName }) => folderName === name
|
||||
);
|
||||
|
||||
return Boolean(isPresent);
|
||||
}
|
||||
return false;
|
||||
},
|
||||
[(folders || []).map((folder) => folder.data)]
|
||||
);
|
||||
|
||||
return { folders, folderNames, isFolderPresentInEnv };
|
||||
const isImportedFolderPresentInEnv = useCallback(
|
||||
(name: string, env: string) => {
|
||||
const selectedEnvIndex = environments.indexOf(env);
|
||||
|
||||
if (selectedEnvIndex !== -1) {
|
||||
const isPresent = folders?.[selectedEnvIndex]?.data?.importedFolders.find(
|
||||
({ importPath }) => importPath === `/${name}`
|
||||
);
|
||||
|
||||
return Boolean(isPresent);
|
||||
}
|
||||
return false;
|
||||
},
|
||||
[(folders || []).map((folder) => folder.data)]
|
||||
);
|
||||
|
||||
return { folders, folderNames, isFolderPresentInEnv, isImportedFolderPresentInEnv };
|
||||
};
|
||||
|
||||
export const useCreateFolder = () => {
|
||||
|
||||
@@ -104,7 +104,7 @@ export const SecretMainPage = () => {
|
||||
}
|
||||
});
|
||||
// fetch folders
|
||||
const { data: folders, isLoading: isFoldersLoading } = useGetProjectFolders({
|
||||
const { data: folderData, isLoading: isFoldersLoading } = useGetProjectFolders({
|
||||
projectId: workspaceId,
|
||||
environment,
|
||||
path: secretPath
|
||||
@@ -163,7 +163,9 @@ export const SecretMainPage = () => {
|
||||
isPaused: !canDoReadRollback
|
||||
});
|
||||
|
||||
const isNotEmtpy = Boolean(secrets?.length || folders?.length || secretImports?.length);
|
||||
const isNotEmtpy = Boolean(
|
||||
secrets?.length || folderData?.folders?.length || secretImports?.length
|
||||
);
|
||||
|
||||
const handleSortToggle = () =>
|
||||
setSortDir((state) => (state === SortDir.ASC ? SortDir.DESC : SortDir.ASC));
|
||||
@@ -292,7 +294,7 @@ export const SecretMainPage = () => {
|
||||
/>
|
||||
)}
|
||||
<FolderListView
|
||||
folders={folders}
|
||||
folders={folderData?.folders}
|
||||
environment={environment}
|
||||
workspaceId={workspaceId}
|
||||
secretPath={secretPath}
|
||||
@@ -312,7 +314,7 @@ export const SecretMainPage = () => {
|
||||
isProtectedBranch={isProtectedBranch}
|
||||
/>
|
||||
)}
|
||||
{!canReadSecret && folders?.length === 0 && <PermissionDeniedBanner />}
|
||||
{!canReadSecret && folderData?.folders?.length === 0 && <PermissionDeniedBanner />}
|
||||
</div>
|
||||
</div>
|
||||
<CreateSecretForm
|
||||
@@ -352,7 +354,7 @@ export const SecretMainPage = () => {
|
||||
workspaceId={workspaceId}
|
||||
secretPath={secretPath}
|
||||
secrets={secrets}
|
||||
folders={folders}
|
||||
folders={folderData?.folders}
|
||||
snapshotCount={snapshotCount}
|
||||
onGoBack={handleResetSnapshot}
|
||||
onClickListSnapshot={() => handlePopUpToggle("snapshots", true)}
|
||||
|
||||
@@ -125,11 +125,12 @@ export const SecretOverviewPage = () => {
|
||||
secretPath,
|
||||
decryptFileKey: latestFileKey!
|
||||
});
|
||||
const { folders, folderNames, isFolderPresentInEnv } = useGetFoldersByEnv({
|
||||
projectId: workspaceId,
|
||||
path: secretPath,
|
||||
environments: userAvailableEnvs.map(({ slug }) => slug)
|
||||
});
|
||||
const { folders, folderNames, isFolderPresentInEnv, isImportedFolderPresentInEnv } =
|
||||
useGetFoldersByEnv({
|
||||
projectId: workspaceId,
|
||||
path: secretPath,
|
||||
environments: userAvailableEnvs.map(({ slug }) => slug)
|
||||
});
|
||||
|
||||
const { mutateAsync: createSecretV3 } = useCreateSecretV3();
|
||||
const { mutateAsync: updateSecretV3 } = useUpdateSecretV3();
|
||||
@@ -639,6 +640,7 @@ export const SecretOverviewPage = () => {
|
||||
<SecretOverviewFolderRow
|
||||
folderName={folderName}
|
||||
isFolderPresentInEnv={isFolderPresentInEnv}
|
||||
isImportedFolderPresentInEnv={isImportedFolderPresentInEnv}
|
||||
environments={visibleEnvs}
|
||||
key={`overview-${folderName}-${index + 1}`}
|
||||
onClick={handleFolderClick}
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
import { faCheck, faFolder, faXmark } from "@fortawesome/free-solid-svg-icons";
|
||||
import { faCheck, faFileImport, faFolder, faXmark } from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
|
||||
import { Td, Tr } from "@app/components/v2";
|
||||
import { Td, Tooltip, Tr } from "@app/components/v2";
|
||||
|
||||
type Props = {
|
||||
folderName: string;
|
||||
environments: { name: string; slug: string }[];
|
||||
isFolderPresentInEnv: (name: string, env: string) => boolean;
|
||||
isImportedFolderPresentInEnv: (name: string, env: string) => boolean;
|
||||
onClick: (path: string) => void;
|
||||
};
|
||||
|
||||
@@ -15,6 +16,7 @@ export const SecretOverviewFolderRow = ({
|
||||
folderName,
|
||||
environments = [],
|
||||
isFolderPresentInEnv,
|
||||
isImportedFolderPresentInEnv,
|
||||
onClick
|
||||
}: Props) => {
|
||||
return (
|
||||
@@ -29,17 +31,24 @@ export const SecretOverviewFolderRow = ({
|
||||
</Td>
|
||||
{environments.map(({ slug }, i) => {
|
||||
const isPresent = isFolderPresentInEnv(folderName, slug);
|
||||
const isImportPresent = isImportedFolderPresentInEnv(folderName, slug);
|
||||
return (
|
||||
<Td
|
||||
key={`sec-overview-${slug}-${i + 1}-folder`}
|
||||
className={twMerge(
|
||||
"border-r border-mineshaft-600 py-3 group-hover:bg-mineshaft-700",
|
||||
isPresent ? "text-green-600" : "text-red-600"
|
||||
// eslint-disable-next-line no-nested-ternary
|
||||
isPresent || isImportPresent ? "text-green-600" : "text-red-600"
|
||||
)}
|
||||
>
|
||||
<div className="flex justify-center">
|
||||
<FontAwesomeIcon icon={isPresent ? faCheck : faXmark} />
|
||||
</div>
|
||||
<Tooltip isDisabled={!isImportPresent} content="Folder is imported">
|
||||
<div className="flex justify-center">
|
||||
<FontAwesomeIcon
|
||||
// eslint-disable-next-line no-nested-ternary
|
||||
icon={isPresent ? faCheck : isImportPresent ? faFileImport : faXmark}
|
||||
/>
|
||||
</div>
|
||||
</Tooltip>
|
||||
</Td>
|
||||
);
|
||||
})}
|
||||
|
||||
Reference in New Issue
Block a user