mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-16 15:31:19 +00:00
feature: clear filters when navigating down and restore filters when navigating up folders in secrets dashboard
This commit is contained in:
@@ -79,7 +79,7 @@ export const SecretMainPage = () => {
|
||||
ProjectPermissionSub.SecretRollback
|
||||
);
|
||||
|
||||
const [filter, setFilter] = useState<Filter>({
|
||||
const defaultFilterState = {
|
||||
tags: {},
|
||||
searchFilter: (router.query.searchFilter as string) || "",
|
||||
include: {
|
||||
@@ -88,8 +88,11 @@ export const SecretMainPage = () => {
|
||||
[RowType.DynamicSecret]: canReadSecret,
|
||||
[RowType.Secret]: canReadSecret
|
||||
}
|
||||
});
|
||||
const debouncedSearchFilter = useDebounce(filter.searchFilter);
|
||||
};
|
||||
|
||||
const [filter, setFilter] = useState<Filter>(defaultFilterState);
|
||||
const [debouncedSearchFilter, setDebouncedSearchFilter] = useDebounce(filter.searchFilter);
|
||||
const [filterHistory, setFilterHistory] = useState<Map<string, Filter>>(new Map());
|
||||
|
||||
// change filters if permissions change at different paths/env
|
||||
useEffect(() => {
|
||||
@@ -255,10 +258,39 @@ export const SecretMainPage = () => {
|
||||
if (totalCount < paginationOffset) setPage(1);
|
||||
}, [totalCount]);
|
||||
|
||||
useEffect(() => {
|
||||
// restore filters for path if set
|
||||
const restore = filterHistory.get(secretPath);
|
||||
setFilter(restore ?? defaultFilterState);
|
||||
setDebouncedSearchFilter(restore?.searchFilter ?? "");
|
||||
const { searchFilter, ...query } = router.query;
|
||||
|
||||
// this is a temp work around until we fully transition state to query params,
|
||||
// setting the initial search filter by query and then moving it to internal state
|
||||
if (router.query.searchFilter) {
|
||||
router.push({
|
||||
pathname: router.pathname,
|
||||
query
|
||||
});
|
||||
}
|
||||
}, [secretPath]);
|
||||
|
||||
if (isDetailsLoading) {
|
||||
return <ContentLoader text={LOADER_TEXT} />;
|
||||
}
|
||||
|
||||
const handleResetFilter = () => {
|
||||
// store for breadcrumb nav to restore previously used filters
|
||||
setFilterHistory((prev) => {
|
||||
const curr = new Map(prev);
|
||||
curr.set(secretPath, filter);
|
||||
return curr;
|
||||
});
|
||||
|
||||
setFilter(defaultFilterState);
|
||||
setDebouncedSearchFilter("");
|
||||
};
|
||||
|
||||
return (
|
||||
<StoreProvider>
|
||||
<div className="container mx-auto flex flex-col px-6 text-mineshaft-50 dark:[color-scheme:dark]">
|
||||
@@ -339,6 +371,7 @@ export const SecretMainPage = () => {
|
||||
environment={environment}
|
||||
workspaceId={workspaceId}
|
||||
secretPath={secretPath}
|
||||
onNavigateToFolder={handleResetFilter}
|
||||
/>
|
||||
)}
|
||||
{canReadSecret && dynamicSecrets?.length && (
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { useState } from "react";
|
||||
import { TypeOptions } from "react-toastify";
|
||||
import { subject } from "@casl/ability";
|
||||
import {
|
||||
@@ -56,7 +55,6 @@ import { usePopUp } from "@app/hooks";
|
||||
import { useCreateFolder, useDeleteSecretBatch, useMoveSecrets } from "@app/hooks/api";
|
||||
import { fetchProjectSecrets } from "@app/hooks/api/secrets/queries";
|
||||
import { SecretType, SecretV3RawSanitized, WsTag } from "@app/hooks/api/types";
|
||||
import { debounce } from "@app/lib/fn/debounce";
|
||||
|
||||
import {
|
||||
PopUpNames,
|
||||
@@ -118,7 +116,6 @@ export const ActionBar = ({
|
||||
] as const);
|
||||
const { subscription } = useSubscription();
|
||||
const { openPopUp } = usePopUpAction();
|
||||
const [search, setSearch] = useState(filter.searchFilter);
|
||||
|
||||
const { mutateAsync: createFolder } = useCreateFolder();
|
||||
const { mutateAsync: deleteBatchSecretV3 } = useDeleteSecretBatch();
|
||||
@@ -134,8 +131,6 @@ export const ActionBar = ({
|
||||
(rule.subject as ProjectPermissionSub[]).includes(ProjectPermissionSub.SecretFolders)
|
||||
);
|
||||
|
||||
const debouncedOnSearch = debounce(onSearchChange, 500);
|
||||
|
||||
const handleFolderCreate = async (folderName: string) => {
|
||||
try {
|
||||
await createFolder({
|
||||
@@ -286,11 +281,15 @@ export const ActionBar = ({
|
||||
<Input
|
||||
className="bg-mineshaft-800 placeholder-mineshaft-50 duration-200 focus:bg-mineshaft-700/80"
|
||||
placeholder="Search by folder name, key name, comment..."
|
||||
leftIcon={<FontAwesomeIcon icon={faMagnifyingGlass} />}
|
||||
value={search}
|
||||
leftIcon={
|
||||
<FontAwesomeIcon
|
||||
className={filter.searchFilter ? "text-primary" : ""}
|
||||
icon={faMagnifyingGlass}
|
||||
/>
|
||||
}
|
||||
value={filter.searchFilter}
|
||||
onChange={(evt) => {
|
||||
setSearch(evt.target.value);
|
||||
debouncedOnSearch(evt.target.value);
|
||||
onSearchChange(evt.target.value);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -18,13 +18,15 @@ type Props = {
|
||||
environment: string;
|
||||
workspaceId: string;
|
||||
secretPath?: string;
|
||||
onNavigateToFolder: (path: string) => void;
|
||||
};
|
||||
|
||||
export const FolderListView = ({
|
||||
folders = [],
|
||||
environment,
|
||||
workspaceId,
|
||||
secretPath = "/"
|
||||
secretPath = "/",
|
||||
onNavigateToFolder
|
||||
}: Props) => {
|
||||
const { popUp, handlePopUpToggle, handlePopUpOpen, handlePopUpClose } = usePopUp([
|
||||
"updateFolder",
|
||||
@@ -88,13 +90,16 @@ export const FolderListView = ({
|
||||
};
|
||||
|
||||
const handleFolderClick = (name: string) => {
|
||||
router.push({
|
||||
pathname: router.pathname,
|
||||
query: {
|
||||
...router.query,
|
||||
secretPath: `${router.query?.secretPath || ""}/${name}`
|
||||
}
|
||||
});
|
||||
const path = `${router.query?.secretPath || ""}/${name}`;
|
||||
router
|
||||
.push({
|
||||
pathname: router.pathname,
|
||||
query: {
|
||||
...router.query,
|
||||
secretPath: path
|
||||
}
|
||||
})
|
||||
.then(() => onNavigateToFolder(path));
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
+1
-1
@@ -84,7 +84,7 @@ export const CopySecretsFromBoard = ({
|
||||
|
||||
const envCopySecPath = watch("secretPath");
|
||||
const selectedEnvSlug = watch("environment");
|
||||
const debouncedEnvCopySecretPath = useDebounce(envCopySecPath);
|
||||
const [debouncedEnvCopySecretPath] = useDebounce(envCopySecPath);
|
||||
|
||||
const { data: secrets, isLoading: isSecretsLoading } = useGetProjectSecrets({
|
||||
workspaceId,
|
||||
|
||||
Reference in New Issue
Block a user