improvements: address feedback

This commit is contained in:
Scott Wilson
2025-07-15 20:03:45 -07:00
parent bd7947c04e
commit 49afaa4d2d
4 changed files with 57 additions and 91 deletions
@@ -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;
}
@@ -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">
@@ -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