chore: style fixes

This commit is contained in:
Nicolas Meienberger 2026-02-25 22:15:08 +01:00
parent c959fb77cf
commit f3c753ad30
6 changed files with 62 additions and 101 deletions

View file

@ -134,15 +134,10 @@ export const FileBrowser = (props: FileBrowserProps) => {
} }
const bodyWithScroll = useScrollArea ? <ScrollArea className={scrollAreaClassName}>{body}</ScrollArea> : body; const bodyWithScroll = useScrollArea ? <ScrollArea className={scrollAreaClassName}>{body}</ScrollArea> : body;
const wrappedBody = treeContainerClassName ? (
<div className={treeContainerClassName}>{bodyWithScroll}</div>
) : (
bodyWithScroll
);
return ( return (
<div className={className}> <div className={className}>
{wrappedBody} <div className={treeContainerClassName}>{bodyWithScroll}</div>
{showSelectedPathFooter && resolvedSelectedPath && ( {showSelectedPathFooter && resolvedSelectedPath && (
<div className="bg-muted/50 border-t p-2 text-sm"> <div className="bg-muted/50 border-t p-2 text-sm">
<div className="font-medium text-muted-foreground">{selectedPathLabel}</div> <div className="font-medium text-muted-foreground">{selectedPathLabel}</div>

View file

@ -30,13 +30,6 @@ export const LocalFileBrowser = ({ initialPath = "/", enabled = true, ...uiProps
}, },
}); });
const errorDetails = parseError(error)?.message;
const errorMessage = errorDetails
? `Failed to load directories: ${errorDetails}`
: error
? "Failed to load directories"
: undefined;
return ( return (
<FileBrowser <FileBrowser
{...uiProps} {...uiProps}
@ -49,7 +42,7 @@ export const LocalFileBrowser = ({ initialPath = "/", enabled = true, ...uiProps
getFolderPagination={fileBrowser.getFolderPagination} getFolderPagination={fileBrowser.getFolderPagination}
isLoading={fileBrowser.isLoading} isLoading={fileBrowser.isLoading}
isEmpty={fileBrowser.isEmpty} isEmpty={fileBrowser.isEmpty}
errorMessage={errorMessage} errorMessage={parseError(error)?.message}
loadingMessage={uiProps.loadingMessage ?? "Loading directories..."} loadingMessage={uiProps.loadingMessage ?? "Loading directories..."}
emptyMessage={uiProps.emptyMessage ?? "No subdirectories found"} emptyMessage={uiProps.emptyMessage ?? "No subdirectories found"}
/> />

View file

@ -135,13 +135,6 @@ export const SnapshotTreeBrowser = ({
[onSelectionChange, addBasePath, onSingleSelectionKindChange, displayPathKinds], [onSelectionChange, addBasePath, onSingleSelectionKindChange, displayPathKinds],
); );
const errorDetails = parseError(error)?.message;
const errorMessage = errorDetails
? `Failed to load files: ${errorDetails}`
: error
? "Failed to load files"
: undefined;
return ( return (
<FileBrowser <FileBrowser
{...fileBrowserUiProps} {...fileBrowserUiProps}
@ -154,7 +147,7 @@ export const SnapshotTreeBrowser = ({
getFolderPagination={fileBrowser.getFolderPagination} getFolderPagination={fileBrowser.getFolderPagination}
isLoading={fileBrowser.isLoading} isLoading={fileBrowser.isLoading}
isEmpty={fileBrowser.isEmpty} isEmpty={fileBrowser.isEmpty}
errorMessage={errorMessage} errorMessage={parseError(error)?.message}
loadingMessage={fileBrowserUiProps.loadingMessage ?? "Loading files..."} loadingMessage={fileBrowserUiProps.loadingMessage ?? "Loading files..."}
selectedPaths={displaySelectedPaths} selectedPaths={displaySelectedPaths}
onSelectionChange={onSelectionChange ? handleSelectionChange : undefined} onSelectionChange={onSelectionChange ? handleSelectionChange : undefined}

View file

@ -38,13 +38,6 @@ export const VolumeFileBrowser = ({ volumeId, enabled = true, ...uiProps }: Volu
}, },
}); });
const errorDetails = parseError(error)?.message;
const errorMessage = errorDetails
? `Failed to load files: ${errorDetails}`
: error
? "Failed to load files"
: undefined;
return ( return (
<FileBrowser <FileBrowser
{...uiProps} {...uiProps}
@ -57,7 +50,7 @@ export const VolumeFileBrowser = ({ volumeId, enabled = true, ...uiProps }: Volu
getFolderPagination={fileBrowser.getFolderPagination} getFolderPagination={fileBrowser.getFolderPagination}
isLoading={fileBrowser.isLoading} isLoading={fileBrowser.isLoading}
isEmpty={fileBrowser.isEmpty} isEmpty={fileBrowser.isEmpty}
errorMessage={errorMessage} errorMessage={parseError(error)?.message}
loadingMessage={uiProps.loadingMessage ?? "Loading files..."} loadingMessage={uiProps.loadingMessage ?? "Loading files..."}
emptyMessage={uiProps.emptyMessage ?? "This volume appears to be empty."} emptyMessage={uiProps.emptyMessage ?? "This volume appears to be empty."}
/> />

View file

@ -150,30 +150,22 @@ export function RestoreForm({ repository, snapshotId, returnPath, basePath }: Re
]); ]);
const handleDownload = useCallback(() => { const handleDownload = useCallback(() => {
if (selectedPaths.size > 1) { if (selectedPaths.size > 1) return;
return;
}
const dumpUrl = new URL( const url = new URL(
`/api/v1/repositories/${repository.shortId}/snapshots/${snapshotId}/dump`, `/api/v1/repositories/${repository.shortId}/snapshots/${snapshotId}/dump`,
window.location.origin, window.location.origin,
); );
if (selectedPaths.size === 1) { const [selectedPath] = selectedPaths;
const [selectedPath] = selectedPaths; if (selectedPath) {
if (selectedPath) { url.searchParams.set("path", selectedPath);
dumpUrl.searchParams.set("path", selectedPath); if (selectedPathKind) {
if (selectedPathKind) { url.searchParams.set("kind", selectedPathKind);
dumpUrl.searchParams.set("kind", selectedPathKind);
}
} }
} }
const link = document.createElement("a"); window.location.assign(url.toString());
link.href = dumpUrl.toString();
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}, [repository.shortId, snapshotId, selectedPathKind, selectedPaths]); }, [repository.shortId, snapshotId, selectedPathKind, selectedPaths]);
const acknowledgeRestoreResult = useCallback(() => { const acknowledgeRestoreResult = useCallback(() => {

View file

@ -26,6 +26,7 @@ import { DoctorReport } from "../components/doctor-report";
import { parseError } from "~/client/lib/errors"; import { parseError } from "~/client/lib/errors";
import { useNavigate } from "@tanstack/react-router"; import { useNavigate } from "@tanstack/react-router";
import { CompressionStatsChart } from "../components/compression-stats-chart"; import { CompressionStatsChart } from "../components/compression-stats-chart";
import { cn } from "~/client/lib/utils";
type Props = { type Props = {
repository: Repository; repository: Repository;
@ -94,6 +95,12 @@ export const RepositoryInfoTabContent = ({ repository }: Props) => {
}; };
const config = repository.config as RepositoryConfig; const config = repository.config as RepositoryConfig;
const isDoctorRunning = repository.status === "doctor";
const hasLocalPath = Boolean(effectiveLocalPath);
const hasCaCert = Boolean(config.cacert);
const hasLastError = Boolean(repository.lastError);
const hasInsecureTlsConfig = config.insecureTls !== undefined;
const isTlsValidationDisabled = config.insecureTls === true;
return ( return (
<> <>
@ -112,26 +119,25 @@ export const RepositoryInfoTabContent = ({ repository }: Props) => {
<Pencil className="h-4 w-4 mr-2" /> <Pencil className="h-4 w-4 mr-2" />
Edit Edit
</Button> </Button>
{repository.status === "doctor" ? ( <Button
<Button type="button"
type="button" variant="destructive"
variant="destructive" loading={cancelDoctor.isPending}
loading={cancelDoctor.isPending} onClick={() => cancelDoctor.mutate({ path: { shortId: repository.shortId } })}
onClick={() => cancelDoctor.mutate({ path: { shortId: repository.shortId } })} className={cn({ hidden: !isDoctorRunning })}
> >
<Square className="h-4 w-4 mr-2" /> <Square className="h-4 w-4 mr-2" />
<span>Cancel doctor</span> <span>Cancel doctor</span>
</Button> </Button>
) : ( <Button
<Button type="button"
type="button" onClick={() => startDoctor.mutate({ path: { shortId: repository.shortId } })}
onClick={() => startDoctor.mutate({ path: { shortId: repository.shortId } })} disabled={startDoctor.isPending}
disabled={startDoctor.isPending} className={cn({ hidden: isDoctorRunning })}
> >
<Stethoscope className="h-4 w-4 mr-2" /> <Stethoscope className="h-4 w-4 mr-2" />
Run doctor Run doctor
</Button> </Button>
)}
<Button <Button
type="button" type="button"
variant="outline" variant="outline"
@ -178,12 +184,10 @@ export const RepositoryInfoTabContent = ({ repository }: Props) => {
<div className="text-sm font-medium text-muted-foreground">Status</div> <div className="text-sm font-medium text-muted-foreground">Status</div>
<p className="mt-1 text-sm">{repository.status || "unknown"}</p> <p className="mt-1 text-sm">{repository.status || "unknown"}</p>
</div> </div>
{effectiveLocalPath && ( <div className={cn({ hidden: !hasLocalPath })}>
<div> <div className="text-sm font-medium text-muted-foreground">Local path</div>
<div className="text-sm font-medium text-muted-foreground">Local path</div> <p className="mt-1 text-sm font-mono">{effectiveLocalPath}</p>
<p className="mt-1 text-sm font-mono">{effectiveLocalPath}</p> </div>
</div>
)}
<div> <div>
<div className="text-sm font-medium text-muted-foreground">Created at</div> <div className="text-sm font-medium text-muted-foreground">Created at</div>
<p className="mt-1 text-sm">{formatDateTime(repository.createdAt)}</p> <p className="mt-1 text-sm">{formatDateTime(repository.createdAt)}</p>
@ -192,40 +196,31 @@ export const RepositoryInfoTabContent = ({ repository }: Props) => {
<div className="text-sm font-medium text-muted-foreground">Last checked</div> <div className="text-sm font-medium text-muted-foreground">Last checked</div>
<p className="mt-1 text-sm">{formatTimeAgo(repository.lastChecked)}</p> <p className="mt-1 text-sm">{formatTimeAgo(repository.lastChecked)}</p>
</div> </div>
{config.cacert && ( <div className={cn({ hidden: !hasCaCert })}>
<div> <div className="text-sm font-medium text-muted-foreground">CA Certificate</div>
<div className="text-sm font-medium text-muted-foreground">CA Certificate</div> <p className="mt-1 text-sm">
<p className="mt-1 text-sm"> <span className="text-green-500">configured</span>
<span className="text-green-500">configured</span> </p>
</p> </div>
</div> <div className={cn({ hidden: !hasInsecureTlsConfig })}>
)} <div className="text-sm font-medium text-muted-foreground">TLS Certificate Validation</div>
{"insecureTls" in config && ( <p className="mt-1 text-sm">
<div> <span className={cn("text-red-500", { hidden: !isTlsValidationDisabled })}>disabled</span>
<div className="text-sm font-medium text-muted-foreground">TLS Certificate Validation</div> <span className={cn("text-green-500", { hidden: isTlsValidationDisabled })}>enabled</span>
<p className="mt-1 text-sm"> </p>
{config.insecureTls ? ( </div>
<span className="text-red-500">disabled</span>
) : (
<span className="text-green-500">enabled</span>
)}
</p>
</div>
)}
</div> </div>
</div> </div>
<div> <div>
{repository.lastError && ( <div className={cn({ hidden: !hasLastError })}>
<div> <div className="flex items-center justify-between mb-4">
<div className="flex items-center justify-between mb-4"> <h3 className="text-lg font-semibold text-red-500">Last Error</h3>
<h3 className="text-lg font-semibold text-red-500">Last Error</h3>
</div>
<div className="bg-red-500/10 border border-red-500/20 rounded-md p-4">
<p className="text-sm text-red-500 wrap-break-word">{repository.lastError}</p>
</div>
</div> </div>
)} <div className="bg-red-500/10 border border-red-500/20 rounded-md p-4">
<p className="text-sm text-red-500 wrap-break-word">{repository.lastError}</p>
</div>
</div>
<div> <div>
<h3 className="text-lg font-semibold mb-4">Configuration</h3> <h3 className="text-lg font-semibold mb-4">Configuration</h3>