mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-06 09:26:47 +00:00
improvements: address feedback
This commit is contained in:
@@ -1,8 +1,9 @@
|
|||||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
import { useInfiniteQuery, useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||||
|
import { format } from "date-fns";
|
||||||
|
|
||||||
import { apiRequest } from "@app/config/request";
|
import { apiRequest } from "@app/config/request";
|
||||||
|
|
||||||
import { CommitHistoryItem, CommitWithChanges, RollbackPreview } from "./types";
|
import { Commit, CommitHistoryItem, CommitWithChanges, RollbackPreview } from "./types";
|
||||||
|
|
||||||
export const commitKeys = {
|
export const commitKeys = {
|
||||||
count: ({
|
count: ({
|
||||||
@@ -242,7 +243,6 @@ export const useGetFolderCommitHistory = ({
|
|||||||
workspaceId,
|
workspaceId,
|
||||||
environment,
|
environment,
|
||||||
directory,
|
directory,
|
||||||
offset = 0,
|
|
||||||
limit = 20,
|
limit = 20,
|
||||||
search,
|
search,
|
||||||
sort = "desc"
|
sort = "desc"
|
||||||
@@ -250,23 +250,33 @@ export const useGetFolderCommitHistory = ({
|
|||||||
workspaceId: string;
|
workspaceId: string;
|
||||||
environment: string;
|
environment: string;
|
||||||
directory: string;
|
directory: string;
|
||||||
offset?: number;
|
|
||||||
limit?: number;
|
limit?: number;
|
||||||
search?: string;
|
search?: string;
|
||||||
sort?: "asc" | "desc";
|
sort?: "asc" | "desc";
|
||||||
}) => {
|
}) => {
|
||||||
return useQuery({
|
return useInfiniteQuery({
|
||||||
queryKey: [
|
initialPageParam: 0,
|
||||||
commitKeys.history({ workspaceId, environment, directory }),
|
queryKey: [commitKeys.history({ workspaceId, environment, directory }), limit, search, sort],
|
||||||
offset,
|
queryFn: ({ pageParam }) =>
|
||||||
limit,
|
fetchFolderCommitHistory(workspaceId, environment, directory, pageParam, limit, search, sort),
|
||||||
search,
|
|
||||||
sort
|
|
||||||
],
|
|
||||||
queryFn: () =>
|
|
||||||
fetchFolderCommitHistory(workspaceId, environment, directory, offset, limit, search, sort),
|
|
||||||
enabled: Boolean(workspaceId && environment),
|
enabled: Boolean(workspaceId && environment),
|
||||||
placeholderData: (prev) => prev
|
select: (data) => {
|
||||||
|
return (data?.pages ?? [])
|
||||||
|
?.map((page) => page.commits)
|
||||||
|
.flat()
|
||||||
|
.reduce(
|
||||||
|
(acc, commit) => {
|
||||||
|
const date = format(new Date(commit.createdAt), "MMM d, yyyy");
|
||||||
|
if (!acc[date]) {
|
||||||
|
acc[date] = [];
|
||||||
|
}
|
||||||
|
acc[date].push(commit);
|
||||||
|
return acc;
|
||||||
|
},
|
||||||
|
{} as Record<string, Commit[]>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
getNextPageParam: (lastPage, pages) => (lastPage.hasMore ? pages.length * limit : undefined)
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -62,3 +62,16 @@ export type RollbackPreview = {
|
|||||||
folderPath: string;
|
folderPath: string;
|
||||||
changes: RollbackChange[];
|
changes: RollbackChange[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
interface CommitActorMetadata {
|
||||||
|
email?: string;
|
||||||
|
name?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Commit {
|
||||||
|
id: string;
|
||||||
|
message: string;
|
||||||
|
createdAt: string;
|
||||||
|
actorType: string;
|
||||||
|
actorMetadata?: CommitActorMetadata;
|
||||||
|
}
|
||||||
|
|||||||
+3
-3
@@ -291,10 +291,10 @@ export const CommitDetailsTab = ({
|
|||||||
Restore Options
|
Restore Options
|
||||||
</Button>
|
</Button>
|
||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
<DropdownMenuContent align="end" sideOffset={2}>
|
<DropdownMenuContent align="end" className="max-w-sm bg-bunker-500" sideOffset={2}>
|
||||||
{!parsedCommitDetails.changes.isLatest && (
|
{!parsedCommitDetails.changes.isLatest && (
|
||||||
<DropdownMenuItem
|
<DropdownMenuItem
|
||||||
className="group cursor-pointer rounded-md px-3 py-3 transition-colors hover:bg-mineshaft-700"
|
className="group cursor-pointer border-b border-mineshaft-600 px-3 py-3 transition-colors hover:bg-mineshaft-700"
|
||||||
onClick={() => goToRollbackPreview()}
|
onClick={() => goToRollbackPreview()}
|
||||||
>
|
>
|
||||||
<div className="flex items-center space-x-3">
|
<div className="flex items-center space-x-3">
|
||||||
@@ -311,7 +311,7 @@ export const CommitDetailsTab = ({
|
|||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
)}
|
)}
|
||||||
<DropdownMenuItem
|
<DropdownMenuItem
|
||||||
className="group cursor-pointer rounded-md px-3 py-3 transition-colors hover:bg-mineshaft-700"
|
className="group cursor-pointer px-3 py-3 transition-colors hover:bg-mineshaft-700"
|
||||||
onClick={() => handlePopUpOpen("revertChanges")}
|
onClick={() => handlePopUpOpen("revertChanges")}
|
||||||
>
|
>
|
||||||
<div className="flex items-center space-x-3">
|
<div className="flex items-center space-x-3">
|
||||||
|
|||||||
+16
-73
@@ -1,4 +1,4 @@
|
|||||||
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
import { useCallback, useEffect, useRef, useState } from "react";
|
||||||
import {
|
import {
|
||||||
faArrowDownWideShort,
|
faArrowDownWideShort,
|
||||||
faArrowUpWideShort,
|
faArrowUpWideShort,
|
||||||
@@ -7,24 +7,11 @@ import {
|
|||||||
faSearch
|
faSearch
|
||||||
} from "@fortawesome/free-solid-svg-icons";
|
} from "@fortawesome/free-solid-svg-icons";
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
import { format, formatDistanceToNow } from "date-fns";
|
import { formatDistanceToNow } from "date-fns";
|
||||||
|
|
||||||
import { Button, ContentLoader, EmptyState, IconButton, Input } from "@app/components/v2";
|
import { Button, ContentLoader, EmptyState, IconButton, Input } from "@app/components/v2";
|
||||||
import { CopyButton } from "@app/components/v2/CopyButton";
|
import { CopyButton } from "@app/components/v2/CopyButton";
|
||||||
import { useGetFolderCommitHistory } from "@app/hooks/api/folderCommits";
|
import { Commit, useGetFolderCommitHistory } from "@app/hooks/api/folderCommits";
|
||||||
|
|
||||||
interface CommitActorMetadata {
|
|
||||||
email?: string;
|
|
||||||
name?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Commit {
|
|
||||||
id: string;
|
|
||||||
message: string;
|
|
||||||
createdAt: string;
|
|
||||||
actorType: string;
|
|
||||||
actorMetadata?: CommitActorMetadata;
|
|
||||||
}
|
|
||||||
|
|
||||||
const formatTimeAgo = (timestamp: string): string => {
|
const formatTimeAgo = (timestamp: string): string => {
|
||||||
return formatDistanceToNow(new Date(timestamp), { addSuffix: true });
|
return formatDistanceToNow(new Date(timestamp), { addSuffix: true });
|
||||||
@@ -50,10 +37,10 @@ const CommitItem = ({
|
|||||||
className="w-full border border-b-0 border-mineshaft-600 bg-mineshaft-800 first:rounded-t-md last:rounded-b-md last:border-b"
|
className="w-full border border-b-0 border-mineshaft-600 bg-mineshaft-800 first:rounded-t-md last:rounded-b-md last:border-b"
|
||||||
>
|
>
|
||||||
<div className="flex gap-2 px-4 py-3 transition-colors duration-200 hover:bg-zinc-800">
|
<div className="flex gap-2 px-4 py-3 transition-colors duration-200 hover:bg-zinc-800">
|
||||||
<div className="flex flex-1 flex-col items-start">
|
<div className="flex min-w-0 flex-1 flex-col items-start">
|
||||||
<span className="w-min whitespace-nowrap text-sm text-mineshaft-100">
|
<p className="block w-full truncate text-left text-sm text-mineshaft-100">
|
||||||
{commit.message}
|
{commit.message}
|
||||||
</span>
|
</p>
|
||||||
<p className="text-left text-xs text-mineshaft-300">
|
<p className="text-left text-xs text-mineshaft-300">
|
||||||
{commit.actorMetadata?.email || commit.actorMetadata?.name || commit.actorType}{" "}
|
{commit.actorMetadata?.email || commit.actorMetadata?.name || commit.actorType}{" "}
|
||||||
committed <time dateTime={commit.createdAt}>{formatTimeAgo(commit.createdAt)}</time>
|
committed <time dateTime={commit.createdAt}>{formatTimeAgo(commit.createdAt)}</time>
|
||||||
@@ -122,8 +109,6 @@ export const CommitHistoryTab = ({
|
|||||||
const [searchTerm, setSearchTerm] = useState("");
|
const [searchTerm, setSearchTerm] = useState("");
|
||||||
const [debouncedSearchTerm, setDebouncedSearchTerm] = useState("");
|
const [debouncedSearchTerm, setDebouncedSearchTerm] = useState("");
|
||||||
const [sortDirection, setSortDirection] = useState<"asc" | "desc">("desc");
|
const [sortDirection, setSortDirection] = useState<"asc" | "desc">("desc");
|
||||||
const [offset, setOffset] = useState(0);
|
|
||||||
const [allCommits, setAllCommits] = useState<Commit[]>([]);
|
|
||||||
const debounceTimeoutRef = useRef<NodeJS.Timeout>();
|
const debounceTimeoutRef = useRef<NodeJS.Timeout>();
|
||||||
const limit = 10;
|
const limit = 10;
|
||||||
|
|
||||||
@@ -145,55 +130,20 @@ export const CommitHistoryTab = ({
|
|||||||
}, [searchTerm]);
|
}, [searchTerm]);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
data: response,
|
data: groupedCommits,
|
||||||
isLoading,
|
isLoading,
|
||||||
isFetching
|
fetchNextPage,
|
||||||
|
isFetchingNextPage,
|
||||||
|
hasNextPage
|
||||||
} = useGetFolderCommitHistory({
|
} = useGetFolderCommitHistory({
|
||||||
workspaceId: projectId,
|
workspaceId: projectId,
|
||||||
environment,
|
environment,
|
||||||
directory: secretPath,
|
directory: secretPath,
|
||||||
offset,
|
|
||||||
limit,
|
limit,
|
||||||
search: debouncedSearchTerm,
|
search: debouncedSearchTerm,
|
||||||
sort: sortDirection
|
sort: sortDirection
|
||||||
});
|
});
|
||||||
|
|
||||||
const commits = response?.commits || [];
|
|
||||||
const hasMore = response?.hasMore || false;
|
|
||||||
|
|
||||||
// Reset accumulated commits when search or sort changes
|
|
||||||
useEffect(() => {
|
|
||||||
setAllCommits([]);
|
|
||||||
setOffset(0);
|
|
||||||
}, [debouncedSearchTerm, sortDirection]);
|
|
||||||
|
|
||||||
// Accumulate commits instead of replacing them
|
|
||||||
useEffect(() => {
|
|
||||||
if (commits.length > 0) {
|
|
||||||
if (offset === 0) {
|
|
||||||
// First load or after search/sort change - replace all commits
|
|
||||||
setAllCommits(commits);
|
|
||||||
} else {
|
|
||||||
// Subsequent loads - append new commits
|
|
||||||
setAllCommits((prev) => [...prev, ...commits]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, [commits, offset]);
|
|
||||||
|
|
||||||
const groupedCommits = useMemo(() => {
|
|
||||||
return allCommits.reduce(
|
|
||||||
(acc, commit) => {
|
|
||||||
const date = format(new Date(commit.createdAt), "MMM d, yyyy");
|
|
||||||
if (!acc[date]) {
|
|
||||||
acc[date] = [];
|
|
||||||
}
|
|
||||||
acc[date].push(commit);
|
|
||||||
return acc;
|
|
||||||
},
|
|
||||||
{} as Record<string, Commit[]>
|
|
||||||
);
|
|
||||||
}, [allCommits]);
|
|
||||||
|
|
||||||
const handleSort = useCallback(() => {
|
const handleSort = useCallback(() => {
|
||||||
setSortDirection((prev) => (prev === "desc" ? "asc" : "desc"));
|
setSortDirection((prev) => (prev === "desc" ? "asc" : "desc"));
|
||||||
}, []);
|
}, []);
|
||||||
@@ -202,12 +152,6 @@ export const CommitHistoryTab = ({
|
|||||||
setSearchTerm(value);
|
setSearchTerm(value);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const loadMoreCommits = useCallback(() => {
|
|
||||||
if (hasMore && !isFetching) {
|
|
||||||
setOffset((prev) => prev + limit);
|
|
||||||
}
|
|
||||||
}, [hasMore, isFetching, limit]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mt-4 w-full rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
|
<div className="mt-4 w-full rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
|
||||||
<p className="mb-4 text-xl font-semibold text-mineshaft-100">Commit History</p>
|
<p className="mb-4 text-xl font-semibold text-mineshaft-100">Commit History</p>
|
||||||
@@ -236,11 +180,11 @@ export const CommitHistoryTab = ({
|
|||||||
</IconButton>
|
</IconButton>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{isLoading && offset === 0 ? (
|
{isLoading ? (
|
||||||
<ContentLoader className="h-80" />
|
<ContentLoader className="h-80" />
|
||||||
) : (
|
) : (
|
||||||
<div>
|
<div>
|
||||||
{Object.keys(groupedCommits).length > 0 ? (
|
{groupedCommits && Object.keys(groupedCommits).length > 0 ? (
|
||||||
<>
|
<>
|
||||||
{Object.entries(groupedCommits).map(([date, dateCommits]) => (
|
{Object.entries(groupedCommits).map(([date, dateCommits]) => (
|
||||||
<DateGroup
|
<DateGroup
|
||||||
@@ -254,16 +198,15 @@ export const CommitHistoryTab = ({
|
|||||||
) : (
|
) : (
|
||||||
<EmptyState title="No commits found." icon={faCodeCommit} />
|
<EmptyState title="No commits found." icon={faCodeCommit} />
|
||||||
)}
|
)}
|
||||||
|
{hasNextPage && (
|
||||||
{hasMore && (
|
|
||||||
<div className="flex justify-center pb-2">
|
<div className="flex justify-center pb-2">
|
||||||
<Button
|
<Button
|
||||||
variant="outline_bg"
|
variant="outline_bg"
|
||||||
size="sm"
|
size="sm"
|
||||||
className="ml-10 mt-4 w-full"
|
className="ml-10 mt-4 w-full"
|
||||||
onClick={loadMoreCommits}
|
onClick={() => fetchNextPage()}
|
||||||
disabled={isFetching}
|
disabled={isFetchingNextPage}
|
||||||
isLoading={isFetching}
|
isLoading={isFetchingNextPage}
|
||||||
aria-label="Load more commits"
|
aria-label="Load more commits"
|
||||||
>
|
>
|
||||||
Load More Commits
|
Load More Commits
|
||||||
|
|||||||
Reference in New Issue
Block a user