diff --git a/apps/client/app/modules/repositories/routes/repository-details.tsx b/apps/client/app/modules/repositories/routes/repository-details.tsx
index dc15d17..c2cf51a 100644
--- a/apps/client/app/modules/repositories/routes/repository-details.tsx
+++ b/apps/client/app/modules/repositories/routes/repository-details.tsx
@@ -1,9 +1,10 @@
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
-import { useNavigate, useParams, useSearchParams } from "react-router";
+import { redirect, useNavigate, useSearchParams } from "react-router";
import { toast } from "sonner";
import { useState, useEffect } from "react";
import {
deleteRepositoryMutation,
+ doctorRepositoryMutation,
getRepositoryOptions,
listSnapshotsOptions,
} from "~/api-client/@tanstack/react-query.gen";
@@ -24,6 +25,7 @@ import { cn } from "~/lib/utils";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "~/components/ui/tabs";
import { RepositoryInfoTabContent } from "../tabs/info";
import { RepositorySnapshotsTabContent } from "../tabs/snapshots";
+import { Loader2 } from "lucide-react";
export function meta({ params }: Route.MetaArgs) {
return [
@@ -38,10 +40,13 @@ export function meta({ params }: Route.MetaArgs) {
export const clientLoader = async ({ params }: Route.ClientLoaderArgs) => {
const repository = await getRepository({ path: { name: params.name ?? "" } });
if (repository.data) return repository.data;
+
+ return redirect("/repositories");
};
export default function RepositoryDetailsPage({ loaderData }: Route.ComponentProps) {
- const { name } = useParams<{ name: string }>();
+ const [showDoctorResults, setShowDoctorResults] = useState(false);
+
const navigate = useNavigate();
const queryClient = useQueryClient();
const [showDeleteConfirm, setShowDeleteConfirm] = useState(false);
@@ -50,17 +55,15 @@ export default function RepositoryDetailsPage({ loaderData }: Route.ComponentPro
const activeTab = searchParams.get("tab") || "info";
const { data } = useQuery({
- ...getRepositoryOptions({ path: { name: name ?? "" } }),
+ ...getRepositoryOptions({ path: { name: loaderData.name } }),
initialData: loaderData,
refetchInterval: 10000,
refetchOnWindowFocus: true,
});
useEffect(() => {
- if (name) {
- queryClient.prefetchQuery(listSnapshotsOptions({ path: { name } }));
- }
- }, [name, queryClient]);
+ queryClient.prefetchQuery(listSnapshotsOptions({ path: { name: data.name } }));
+ }, [queryClient, data.name]);
const deleteRepo = useMutation({
...deleteRepositoryMutation(),
@@ -75,18 +78,48 @@ export default function RepositoryDetailsPage({ loaderData }: Route.ComponentPro
},
});
+ const doctorMutation = useMutation({
+ ...doctorRepositoryMutation(),
+ onSuccess: (data) => {
+ if (data) {
+ setShowDoctorResults(true);
+
+ if (data.success) {
+ toast.success("Repository doctor completed successfully");
+ } else {
+ toast.warning("Doctor completed with some issues", {
+ description: "Check the details for more information",
+ richColors: true,
+ });
+ }
+ }
+ },
+ onError: (error) => {
+ toast.error("Failed to run doctor", {
+ description: parseError(error)?.message,
+ });
+ },
+ });
+
const handleConfirmDelete = () => {
setShowDeleteConfirm(false);
- deleteRepo.mutate({ path: { name: name ?? "" } });
+ deleteRepo.mutate({ path: { name: data.name } });
};
- if (!name) {
- return
Repository not found
;
- }
-
- if (!data) {
- return Loading...
;
- }
+ const getStepLabel = (step: string) => {
+ switch (step) {
+ case "unlock":
+ return "Unlock Repository";
+ case "check":
+ return "Check Repository";
+ case "repair_index":
+ return "Repair Index";
+ case "recheck":
+ return "Re-check Repository";
+ default:
+ return step;
+ }
+ };
return (
<>
@@ -103,6 +136,20 @@ export default function RepositoryDetailsPage({ loaderData }: Route.ComponentPro
{data.type}
+
doctorMutation.mutate({ path: { name: data.name } })}
+ disabled={doctorMutation.isPending}
+ variant={"outline"}
+ >
+ {doctorMutation.isPending ? (
+ <>
+
+ Running Doctor...
+ >
+ ) : (
+ "Run Doctor"
+ )}
+
setShowDeleteConfirm(true)} disabled={deleteRepo.isPending}>
Delete
@@ -127,8 +174,8 @@ export default function RepositoryDetailsPage({ loaderData }: Route.ComponentPro
Delete repository?
- Are you sure you want to delete the repository {name} ? This action cannot be undone and
- will remove all backup data.
+ Are you sure you want to delete the repository {data.name} ? This action cannot be undone
+ and will remove all backup data.
@@ -142,6 +189,46 @@ export default function RepositoryDetailsPage({ loaderData }: Route.ComponentPro
+
+
+
+
+ Doctor Results
+ Repository doctor operation completed
+
+
+ {doctorMutation.data && (
+
+ {doctorMutation.data.steps.map((step) => (
+
+
+ {getStepLabel(step.step)}
+
+ {step.success ? "Success" : "Warning"}
+
+
+ {step.error &&
{step.error}
}
+
+ ))}
+
+ )}
+
+
+ setShowDoctorResults(false)}>Close
+
+
+
>
);
}
diff --git a/apps/client/app/modules/repositories/tabs/info.tsx b/apps/client/app/modules/repositories/tabs/info.tsx
index 0dd3f42..d2d8507 100644
--- a/apps/client/app/modules/repositories/tabs/info.tsx
+++ b/apps/client/app/modules/repositories/tabs/info.tsx
@@ -1,175 +1,63 @@
-import { useMutation } from "@tanstack/react-query";
-import { useState } from "react";
-import { toast } from "sonner";
import { Card } from "~/components/ui/card";
-import { Button } from "~/components/ui/button";
-import {
- AlertDialog,
- AlertDialogContent,
- AlertDialogDescription,
- AlertDialogHeader,
- AlertDialogTitle,
-} from "~/components/ui/alert-dialog";
-import { Loader2 } from "lucide-react";
import type { Repository } from "~/lib/types";
-import { parseError } from "~/lib/errors";
-import { doctorRepositoryMutation } from "~/api-client/@tanstack/react-query.gen";
-import { cn } from "~/lib/utils";
type Props = {
repository: Repository;
};
export const RepositoryInfoTabContent = ({ repository }: Props) => {
- const [showDoctorResults, setShowDoctorResults] = useState(false);
-
- const doctorMutation = useMutation({
- ...doctorRepositoryMutation(),
- onSuccess: (data) => {
- if (data) {
- setShowDoctorResults(true);
-
- if (data.success) {
- toast.success("Repository doctor completed successfully");
- } else {
- toast.warning("Doctor completed with some issues", {
- description: "Check the details for more information",
- richColors: true,
- });
- }
- }
- },
- onError: (error) => {
- toast.error("Failed to run doctor", {
- description: parseError(error)?.message,
- });
- },
- });
-
- const handleDoctor = () => {
- doctorMutation.mutate({ path: { name: repository.name } });
- };
-
- const getStepLabel = (step: string) => {
- switch (step) {
- case "unlock":
- return "Unlock Repository";
- case "check":
- return "Check Repository";
- case "repair_index":
- return "Repair Index";
- case "recheck":
- return "Re-check Repository";
- default:
- return step;
- }
- };
-
return (
- <>
-
-
-
-
Repository Information
-
-
-
Name
-
{repository.name}
-
-
-
Backend
-
{repository.type}
-
-
-
Compression Mode
-
{repository.compressionMode || "off"}
-
-
-
Status
-
{repository.status || "unknown"}
-
-
-
Created At
-
{new Date(repository.createdAt).toLocaleString()}
-
-
-
Last Checked
-
- {repository.lastChecked ? new Date(repository.lastChecked).toLocaleString() : "Never"}
-
-
-
-
-
- {repository.lastError && (
+
+
+
+
Repository Information
+
-
-
Last Error
-
- {doctorMutation.isPending ? (
- <>
-
- Running Doctor...
- >
- ) : (
- "Run Doctor"
- )}
-
-
-
-
{repository.lastError}
-
+
Name
+
{repository.name}
- )}
-
-
-
Configuration
-
-
{JSON.stringify(repository.config, null, 2)}
+
+
Backend
+
{repository.type}
+
+
+
Compression Mode
+
{repository.compressionMode || "off"}
+
+
+
Status
+
{repository.status || "unknown"}
+
+
+
Created At
+
{new Date(repository.createdAt).toLocaleString()}
+
+
+
Last Checked
+
+ {repository.lastChecked ? new Date(repository.lastChecked).toLocaleString() : "Never"}
+
-
-
-
-
-
- Doctor Results
- Repository doctor operation completed
-
-
- {doctorMutation.data && (
-
- {doctorMutation.data.steps.map((step) => (
-
-
- {getStepLabel(step.step)}
-
- {step.success ? "Success" : "Warning"}
-
-
- {step.error &&
{step.error}
}
-
- ))}
+ {repository.lastError && (
+
+
+
Last Error
- )}
-
-
setShowDoctorResults(false)}>Close
+
+
{repository.lastError}
+
-
-
- >
+ )}
+
+
Configuration
+
+
{JSON.stringify(repository.config, null, 2)}
+
+
+
+
);
};