Fix: Restructured frontend

This commit is contained in:
Daniel Hougaard
2024-03-20 14:42:34 +01:00
parent a750d68363
commit a4e495ea1c
7 changed files with 122 additions and 63 deletions

View File

@@ -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<TFetchProjectFoldersResponse>("/api/v1/folders", {
const { data } = await apiRequest.get<{ folders: TSecretFolder[] }>("/api/v1/folders", {
params: {
workspaceId,
environment,
path
}
});
return data;
return data.folders;
};
export const useGetProjectFolders = ({
@@ -43,9 +43,9 @@ export const useGetProjectFolders = ({
}: TGetProjectFoldersDTO & {
options?: Omit<
UseQueryOptions<
TFetchProjectFoldersResponse,
TSecretFolder[],
unknown,
TFetchProjectFoldersResponse,
TSecretFolder[],
ReturnType<typeof folderQueryKeys.getSecretFolders>
>,
"queryKey" | "queryFn"
@@ -63,8 +63,6 @@ export const useGetFoldersByEnv = ({
projectId,
environments
}: TGetFoldersByEnvDTO) => {
const queryParams = new URLSearchParams(window.location.search);
const folders = useQueries({
queries: environments.map((environment) => ({
queryKey: folderQueryKeys.getSecretFolders({ projectId, environment, path }),
@@ -76,7 +74,7 @@ export const useGetFoldersByEnv = ({
const folderNames = useMemo(() => {
const names = new Set<string>();
folders?.forEach(({ data }) => {
data?.folders?.forEach(({ name }) => {
data?.forEach(({ name }) => {
names.add(name);
});
});
@@ -87,7 +85,7 @@ export const useGetFoldersByEnv = ({
(name: string, env: string) => {
const selectedEnvIndex = environments.indexOf(env);
if (selectedEnvIndex !== -1) {
const isPresent = folders?.[selectedEnvIndex]?.data?.folders.find(
const isPresent = folders?.[selectedEnvIndex]?.data?.find(
({ name: folderName }) => folderName === name
);
@@ -98,25 +96,7 @@ export const useGetFoldersByEnv = ({
[(folders || []).map((response) => response.data)]
);
const isImportedFolderPresentInEnv = useCallback(
(name: string, env: string) => {
const selectedEnvIndex = environments.indexOf(env);
if (selectedEnvIndex !== -1) {
const currentlyBrowsingPath = queryParams.get("secretPath") || "";
const isPresent = folders?.[selectedEnvIndex]?.data?.importedFolders.find(
({ importPath }) => importPath === `${currentlyBrowsingPath}/${name}`
);
return Boolean(isPresent);
}
return false;
},
[(folders || []).map((response) => response.data)]
);
return { folders, folderNames, isFolderPresentInEnv, isImportedFolderPresentInEnv };
return { folders, folderNames, isFolderPresentInEnv };
};
export const useCreateFolder = () => {

View File

@@ -3,24 +3,6 @@ export type TSecretFolder = {
name: string;
};
export type TImportedSecretFolder = {
id: string;
folderId: string;
importEnv: {
id: string;
name: string;
slug: string;
};
importPath: string;
// ... It got more fields, but we won't need them.
};
export type TFetchProjectFoldersResponse = {
folders: TSecretFolder[];
importedFolders: TImportedSecretFolder[];
};
export type TGetProjectFoldersDTO = {
projectId: string;
environment: string;

View File

@@ -1,2 +1,2 @@
export { useCreateSecretImport, useDeleteSecretImport, useUpdateSecretImport } from "./mutation";
export { useGetImportedSecrets, useGetSecretImports } from "./queries";
export { useGetImportedFoldersByEnv, useGetImportedSecrets, useGetSecretImports } from "./queries";

View File

@@ -1,5 +1,5 @@
import { useCallback } from "react";
import { useQuery, UseQueryOptions } from "@tanstack/react-query";
import { useQueries, useQuery, UseQueryOptions } from "@tanstack/react-query";
import {
decryptAssymmetric,
@@ -7,7 +7,15 @@ import {
} from "@app/components/utilities/cryptography/crypto";
import { apiRequest } from "@app/config/request";
import { TGetImportedSecrets, TGetSecretImports, TImportedSecrets, TSecretImport } from "./types";
import {
TGetImportedFoldersByEnvDTO,
TGetImportedSecrets,
TGetSecretImports,
TImportedSecretFolder,
TImportedSecrets,
TSecretImport,
TuseGetImportedFoldersByEnv
} from "./types";
export const secretImportKeys = {
getProjectSecretImports: ({ environment, projectId, path }: TGetSecretImports) =>
@@ -17,7 +25,9 @@ export const secretImportKeys = {
projectId,
path
}: Omit<TGetImportedSecrets, "decryptFileKey">) =>
[{ environment, path, projectId }, "secrets-import-sec"] as const
[{ environment, path, projectId }, "secrets-import-sec"] as const,
getImportedFoldersByEnv: ({ environment, projectId, path }: TGetImportedFoldersByEnvDTO) =>
[{ environment, projectId, path }, "imported-folders"] as const
};
const fetchSecretImport = async ({ projectId, environment, path = "/" }: TGetSecretImports) => {
@@ -75,6 +85,24 @@ const fetchImportedSecrets = async (
return data.secrets;
};
const fetchImportedFolders = async ({
projectId,
environment,
path
}: TGetImportedFoldersByEnvDTO) => {
const { data } = await apiRequest.get<{ secretImports: TImportedSecretFolder[] }>(
"/api/v1/secret-imports",
{
params: {
workspaceId: projectId,
environment,
path
}
}
);
return data.secretImports;
};
export const useGetImportedSecrets = ({
environment,
decryptFileKey,
@@ -159,3 +187,43 @@ export const useGetImportedSecrets = ({
[decryptFileKey]
)
});
export const useGetImportedFoldersByEnv = ({
projectId,
environments,
path = "/"
}: TuseGetImportedFoldersByEnv) => {
const queryParams = new URLSearchParams(window.location.search);
const importedFolders = useQueries({
queries: environments.map((env) => ({
queryKey: secretImportKeys.getImportedFoldersByEnv({
projectId,
environment: env,
path
}),
queryFn: async () => fetchImportedFolders({ projectId, environment: env, path }),
enabled: Boolean(projectId) && Boolean(env)
}))
});
const isImportedFolderPresentInEnv = useCallback(
(name: string, env: string) => {
const selectedEnvIndex = environments.indexOf(env);
if (selectedEnvIndex !== -1) {
const currentlyBrowsingPath = queryParams.get("secretPath") || "";
const isPresent = importedFolders?.[selectedEnvIndex]?.data?.find(
({ importPath }) => importPath === `${currentlyBrowsingPath}/${name}`
);
return Boolean(isPresent);
}
return false;
},
[(importedFolders || []).map((response) => response.data)]
);
return { importedFolders, isImportedFolderPresentInEnv };
};

View File

@@ -12,6 +12,25 @@ export type TSecretImport = {
updatedAt: string;
};
export type TImportedSecretFolder = {
id: string;
folderId: string;
importEnv: {
id: string;
name: string;
slug: string;
};
importPath: string;
// ... It got more fields, but we won't need them.
};
export type TGetImportedFoldersByEnvDTO = {
projectId: string;
environment: string;
path?: string;
};
export type TImportedSecrets = {
environment: string;
environmentInfo: WorkspaceEnv;
@@ -33,6 +52,12 @@ export type TGetImportedSecrets = {
decryptFileKey: UserWsKeyPair;
};
export type TuseGetImportedFoldersByEnv = {
environments: string[];
projectId: string;
path?: string;
};
export type TCreateSecretImportDTO = {
projectId: string;
environment: string;

View File

@@ -104,7 +104,7 @@ export const SecretMainPage = () => {
}
});
// fetch folders
const { data: folderData, isLoading: isFoldersLoading } = useGetProjectFolders({
const { data: folders, isLoading: isFoldersLoading } = useGetProjectFolders({
projectId: workspaceId,
environment,
path: secretPath
@@ -163,9 +163,7 @@ export const SecretMainPage = () => {
isPaused: !canDoReadRollback
});
const isNotEmtpy = Boolean(
secrets?.length || folderData?.folders?.length || secretImports?.length
);
const isNotEmtpy = Boolean(secrets?.length || folders?.length || secretImports?.length);
const handleSortToggle = () =>
setSortDir((state) => (state === SortDir.ASC ? SortDir.DESC : SortDir.ASC));
@@ -294,7 +292,7 @@ export const SecretMainPage = () => {
/>
)}
<FolderListView
folders={folderData?.folders}
folders={folders}
environment={environment}
workspaceId={workspaceId}
secretPath={secretPath}
@@ -314,7 +312,7 @@ export const SecretMainPage = () => {
isProtectedBranch={isProtectedBranch}
/>
)}
{!canReadSecret && folderData?.folders?.length === 0 && <PermissionDeniedBanner />}
{!canReadSecret && folders?.length === 0 && <PermissionDeniedBanner />}
</div>
</div>
<CreateSecretForm
@@ -354,7 +352,7 @@ export const SecretMainPage = () => {
workspaceId={workspaceId}
secretPath={secretPath}
secrets={secrets}
folders={folderData?.folders}
folders={folders}
snapshotCount={snapshotCount}
onGoBack={handleResetSnapshot}
onClickListSnapshot={() => handlePopUpToggle("snapshots", true)}

View File

@@ -55,6 +55,7 @@ import {
useCreateSecretV3,
useDeleteSecretV3,
useGetFoldersByEnv,
useGetImportedFoldersByEnv,
useGetProjectSecretsAllEnv,
useGetUserWsKey,
useUpdateSecretV3
@@ -125,12 +126,17 @@ export const SecretOverviewPage = () => {
secretPath,
decryptFileKey: latestFileKey!
});
const { folders, folderNames, isFolderPresentInEnv, isImportedFolderPresentInEnv } =
useGetFoldersByEnv({
projectId: workspaceId,
path: secretPath,
environments: userAvailableEnvs.map(({ slug }) => slug)
});
const { folders, folderNames, isFolderPresentInEnv } = useGetFoldersByEnv({
projectId: workspaceId,
path: secretPath,
environments: userAvailableEnvs.map(({ slug }) => slug)
});
const { isImportedFolderPresentInEnv } = useGetImportedFoldersByEnv({
projectId: workspaceId,
path: secretPath,
environments: userAvailableEnvs.map(({ slug }) => slug)
});
const { mutateAsync: createSecretV3 } = useCreateSecretV3();
const { mutateAsync: updateSecretV3 } = useUpdateSecretV3();