chore: pr feedbacks
This commit is contained in:
parent
bb102b0619
commit
221fd18820
6 changed files with 42 additions and 59 deletions
|
|
@ -1,4 +1,4 @@
|
|||
import { useCallback } from "react";
|
||||
import { useCallback, useMemo } from "react";
|
||||
import { useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import { listSnapshotFilesOptions } from "~/client/api-client/@tanstack/react-query.gen";
|
||||
import { FileBrowser, type FileBrowserUiProps } from "~/client/components/file-browsers/file-browser";
|
||||
|
|
@ -28,6 +28,7 @@ export const SnapshotTreeBrowser = ({
|
|||
enabled = true,
|
||||
...uiProps
|
||||
}: SnapshotTreeBrowserProps) => {
|
||||
const { selectedPaths, onSelectionChange, ...fileBrowserUiProps } = uiProps;
|
||||
const queryClient = useQueryClient();
|
||||
const normalizedBasePath = normalizeAbsolutePath(basePath);
|
||||
|
||||
|
|
@ -60,6 +61,31 @@ export const SnapshotTreeBrowser = ({
|
|||
[normalizedBasePath],
|
||||
);
|
||||
|
||||
const displaySelectedPaths = useMemo(() => {
|
||||
if (!selectedPaths) return undefined;
|
||||
|
||||
const displayPaths = new Set<string>();
|
||||
for (const fullPath of selectedPaths) {
|
||||
displayPaths.add(stripBasePath(fullPath));
|
||||
}
|
||||
|
||||
return displayPaths;
|
||||
}, [selectedPaths, stripBasePath]);
|
||||
|
||||
const handleSelectionChange = useCallback(
|
||||
(nextDisplayPaths: Set<string>) => {
|
||||
if (!onSelectionChange) return;
|
||||
|
||||
const nextFullPaths = new Set<string>();
|
||||
for (const displayPath of nextDisplayPaths) {
|
||||
nextFullPaths.add(addBasePath(displayPath));
|
||||
}
|
||||
|
||||
onSelectionChange(nextFullPaths);
|
||||
},
|
||||
[onSelectionChange, addBasePath],
|
||||
);
|
||||
|
||||
const fileBrowser = useFileBrowser({
|
||||
initialData: data,
|
||||
isLoading,
|
||||
|
|
@ -102,7 +128,7 @@ export const SnapshotTreeBrowser = ({
|
|||
|
||||
return (
|
||||
<FileBrowser
|
||||
{...uiProps}
|
||||
{...fileBrowserUiProps}
|
||||
fileArray={fileBrowser.fileArray}
|
||||
expandedFolders={fileBrowser.expandedFolders}
|
||||
loadingFolders={fileBrowser.loadingFolders}
|
||||
|
|
@ -113,7 +139,9 @@ export const SnapshotTreeBrowser = ({
|
|||
isLoading={fileBrowser.isLoading}
|
||||
isEmpty={fileBrowser.isEmpty}
|
||||
errorMessage={errorMessage}
|
||||
loadingMessage={uiProps.loadingMessage ?? "Loading files..."}
|
||||
loadingMessage={fileBrowserUiProps.loadingMessage ?? "Loading files..."}
|
||||
selectedPaths={displaySelectedPaths}
|
||||
onSelectionChange={onSelectionChange ? handleSelectionChange : undefined}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { useState } from "react";
|
||||
import { LocalFileBrowser } from "./file-browsers/local-file-browser";
|
||||
import { DirectoryBrowser } from "./file-browsers/directory-browser";
|
||||
import { Button } from "./ui/button";
|
||||
|
||||
type Props = {
|
||||
|
|
@ -14,21 +14,12 @@ export const PathSelector = ({ value, onChange }: Props) => {
|
|||
if (showBrowser) {
|
||||
return (
|
||||
<div className="space-y-2">
|
||||
<LocalFileBrowser
|
||||
className="border rounded-lg overflow-hidden"
|
||||
useScrollArea
|
||||
scrollAreaClassName="h-64"
|
||||
foldersOnly
|
||||
selectableFolders
|
||||
selectedFolder={value}
|
||||
onFolderSelect={(path) => {
|
||||
<DirectoryBrowser
|
||||
selectedPath={value}
|
||||
onSelectPath={(path) => {
|
||||
onChange(path);
|
||||
setShowBrowser(false);
|
||||
}}
|
||||
showSelectedPathFooter
|
||||
selectedPath={value}
|
||||
loadingMessage="Loading directories..."
|
||||
emptyMessage="No subdirectories found"
|
||||
/>
|
||||
<Button type="button" variant="ghost" size="sm" onClick={() => setShowBrowser(false)}>
|
||||
Cancel
|
||||
|
|
|
|||
|
|
@ -88,17 +88,6 @@ export function RestoreForm({ snapshot, repository, snapshotId, returnPath }: Re
|
|||
};
|
||||
}, [addEventListener, repository.id, snapshotId]);
|
||||
|
||||
const addBasePath = useCallback(
|
||||
(displayPath: string): string => {
|
||||
const vbp = volumeBasePath === "/" ? "" : volumeBasePath;
|
||||
|
||||
if (!vbp) return displayPath;
|
||||
if (displayPath === "/") return vbp;
|
||||
return `${vbp}${displayPath}`;
|
||||
},
|
||||
[volumeBasePath],
|
||||
);
|
||||
|
||||
const { mutate: restoreSnapshot, isPending: isRestoring } = useMutation({
|
||||
...restoreSnapshotMutation(),
|
||||
onError: (error) => {
|
||||
|
|
@ -117,8 +106,7 @@ export function RestoreForm({ snapshot, repository, snapshotId, returnPath }: Re
|
|||
const isCustomLocation = restoreLocation === "custom";
|
||||
const targetPath = isCustomLocation && customTargetPath.trim() ? customTargetPath.trim() : undefined;
|
||||
|
||||
const pathsArray = Array.from(selectedPaths);
|
||||
const includePaths = pathsArray.map((path) => addBasePath(path));
|
||||
const includePaths = Array.from(selectedPaths);
|
||||
|
||||
restoreCompletedRef.current = false;
|
||||
setIsRestoreActive(true);
|
||||
|
|
@ -142,7 +130,6 @@ export function RestoreForm({ snapshot, repository, snapshotId, returnPath }: Re
|
|||
restoreLocation,
|
||||
customTargetPath,
|
||||
selectedPaths,
|
||||
addBasePath,
|
||||
overwriteMode,
|
||||
restoreSnapshot,
|
||||
]);
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import type { UseFormReturn } from "react-hook-form";
|
|||
import { Check, Pencil, X, AlertTriangle } from "lucide-react";
|
||||
import { Button } from "../../../../components/ui/button";
|
||||
import { FormItem, FormLabel, FormDescription, FormField, FormControl } from "../../../../components/ui/form";
|
||||
import { LocalFileBrowser } from "../../../../components/file-browsers/local-file-browser";
|
||||
import { DirectoryBrowser } from "../../../../components/file-browsers/directory-browser";
|
||||
import {
|
||||
AlertDialog,
|
||||
AlertDialogAction,
|
||||
|
|
@ -96,20 +96,9 @@ export const LocalRepositoryForm = ({ form }: Props) => {
|
|||
</AlertDialogDescription>
|
||||
</AlertDialogHeader>
|
||||
<div className="py-4">
|
||||
<LocalFileBrowser
|
||||
className="border rounded-lg overflow-hidden"
|
||||
useScrollArea
|
||||
scrollAreaClassName="h-64"
|
||||
foldersOnly
|
||||
selectableFolders
|
||||
onFolderSelect={(path) => {
|
||||
field.onChange(path);
|
||||
}}
|
||||
selectedFolder={field.value || constants.REPOSITORY_BASE}
|
||||
showSelectedPathFooter
|
||||
<DirectoryBrowser
|
||||
onSelectPath={field.onChange}
|
||||
selectedPath={field.value || constants.REPOSITORY_BASE}
|
||||
loadingMessage="Loading directories..."
|
||||
emptyMessage="No subdirectories found"
|
||||
/>
|
||||
</div>
|
||||
<AlertDialogFooter>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { Pencil } from "lucide-react";
|
||||
import type { UseFormReturn } from "react-hook-form";
|
||||
import type { FormValues } from "../create-volume-form";
|
||||
import { LocalFileBrowser } from "../../../../components/file-browsers/local-file-browser";
|
||||
import { DirectoryBrowser } from "../../../../components/file-browsers/directory-browser";
|
||||
import { Button } from "../../../../components/ui/button";
|
||||
import {
|
||||
FormControl,
|
||||
|
|
@ -38,19 +38,7 @@ export const DirectoryForm = ({ form }: Props) => {
|
|||
</Button>
|
||||
</div>
|
||||
) : (
|
||||
<LocalFileBrowser
|
||||
className="border rounded-lg overflow-hidden"
|
||||
useScrollArea
|
||||
scrollAreaClassName="h-64"
|
||||
foldersOnly
|
||||
selectableFolders
|
||||
onFolderSelect={(path) => field.onChange(path)}
|
||||
selectedFolder={field.value}
|
||||
showSelectedPathFooter
|
||||
selectedPath={field.value}
|
||||
loadingMessage="Loading directories..."
|
||||
emptyMessage="No subdirectories found"
|
||||
/>
|
||||
<DirectoryBrowser onSelectPath={field.onChange} selectedPath={field.value} />
|
||||
)}
|
||||
</FormControl>
|
||||
<FormDescription>Browse and select a directory on the host filesystem to track.</FormDescription>
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ export const findCommonAncestor = (paths: string[]): string => {
|
|||
const splitPaths = paths.map((path) => path.split("/").filter(Boolean));
|
||||
const minLength = Math.min(...splitPaths.map((parts) => parts.length));
|
||||
|
||||
let commonParts: string[] = [];
|
||||
const commonParts: string[] = [];
|
||||
for (let i = 0; i < minLength; i++) {
|
||||
const partSet = new Set(splitPaths.map((parts) => parts[i]));
|
||||
if (partSet.size === 1) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue