refactor: move api-client to client

This commit is contained in:
Nicolas Meienberger 2025-11-13 19:50:46 +01:00
parent 44c62a9c7e
commit 8eb0f24585
35 changed files with 71 additions and 71 deletions

View file

@ -2,12 +2,12 @@ import { useMutation } from "@tanstack/react-query";
import { Plus } from "lucide-react";
import { useId } from "react";
import { toast } from "sonner";
import { createRepositoryMutation } from "~/api-client/@tanstack/react-query.gen";
import { parseError } from "~/client/lib/errors";
import { CreateRepositoryForm } from "./create-repository-form";
import { Button } from "./ui/button";
import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from "./ui/dialog";
import { ScrollArea } from "./ui/scroll-area";
import { createRepositoryMutation } from "../api-client/@tanstack/react-query.gen";
type Props = {
open: boolean;

View file

@ -8,13 +8,13 @@ import { Button } from "./ui/button";
import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage } from "./ui/form";
import { Input } from "./ui/input";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "./ui/select";
import { listRcloneRemotesOptions } from "~/api-client/@tanstack/react-query.gen";
import { useQuery } from "@tanstack/react-query";
import { Alert, AlertDescription } from "./ui/alert";
import { ExternalLink } from "lucide-react";
import { Tooltip, TooltipContent, TooltipTrigger } from "./ui/tooltip";
import { useSystemInfo } from "~/client/hooks/use-system-info";
import { COMPRESSION_MODES, repositoryConfigSchema } from "~/schemas/restic";
import { listRcloneRemotesOptions } from "../api-client/@tanstack/react-query.gen";
export const formSchema = type({
name: "2<=string<=32",

View file

@ -2,12 +2,12 @@ import { useMutation } from "@tanstack/react-query";
import { Plus } from "lucide-react";
import { useId } from "react";
import { toast } from "sonner";
import { createVolumeMutation } from "~/api-client/@tanstack/react-query.gen";
import { parseError } from "~/client/lib/errors";
import { CreateVolumeForm } from "./create-volume-form";
import { Button } from "./ui/button";
import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from "./ui/dialog";
import { ScrollArea } from "./ui/scroll-area";
import { createVolumeMutation } from "../api-client/@tanstack/react-query.gen";
type Props = {
open: boolean;

View file

@ -4,7 +4,6 @@ import { type } from "arktype";
import { CheckCircle, Loader2, XCircle } from "lucide-react";
import { useEffect, useState } from "react";
import { useForm } from "react-hook-form";
import { testConnectionMutation } from "~/api-client/@tanstack/react-query.gen";
import { cn, slugify } from "~/client/lib/utils";
import { deepClean } from "~/utils/object";
import { DirectoryBrowser } from "./directory-browser";
@ -13,6 +12,7 @@ import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, For
import { Input } from "./ui/input";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "./ui/select";
import { volumeConfigSchema } from "~/schemas/volumes";
import { testConnectionMutation } from "../api-client/@tanstack/react-query.gen";
export const formSchema = type({
name: "2<=string<=32",

View file

@ -1,8 +1,8 @@
import { useQuery, useQueryClient } from "@tanstack/react-query";
import { useCallback, useMemo, useState } from "react";
import { browseFilesystemOptions } from "~/api-client/@tanstack/react-query.gen";
import { FileTree, type FileEntry } from "./file-tree";
import { ScrollArea } from "./ui/scroll-area";
import { browseFilesystemOptions } from "../api-client/@tanstack/react-query.gen";
type Props = {
onSelectPath: (path: string) => void;

View file

@ -17,7 +17,7 @@ export function EmptyState(props: EmptyStateProps) {
<div className="absolute inset-0 animate-pulse">
<div className="w-32 h-32 rounded-full bg-primary/10 blur-2xl" />
</div>
<div className="relative flex items-center justify-center w-32 h-32 rounded-full bg-gradient-to-br from-primary/20 to-primary/5 border-2 border-primary/20">
<div className="relative flex items-center justify-center w-32 h-32 rounded-full bg-linear-to-br from-primary/20 to-primary/5 border-2 border-primary/20">
<Cicon className="w-16 h-16 text-primary/70" strokeWidth={1.5} />
</div>
</div>

View file

@ -12,9 +12,9 @@ export function GridBackground({ children, className, containerClassName }: Grid
<div
className={cn(
"relative min-h-full w-full overflow-x-hidden",
"[background-size:20px_20px] sm:[background-size:40px_40px]",
"[background-image:linear-gradient(to_right,#e4e4e7_1px,transparent_1px),linear-gradient(to_bottom,#e4e4e7_1px,transparent_1px)]",
"dark:[background-image:linear-gradient(to_right,#262626_1px,transparent_1px),linear-gradient(to_bottom,#262626_1px,transparent_1px)]",
"bg-size-[20px_20px] sm:bg-size-[40px_40px]",
"bg-[linear-gradient(to_right,#e4e4e7_1px,transparent_1px),linear-gradient(to_bottom,#e4e4e7_1px,transparent_1px)]",
"dark:bg-[linear-gradient(to_right,#262626_1px,transparent_1px),linear-gradient(to_bottom,#262626_1px,transparent_1px)]",
containerClassName,
)}
>

View file

@ -2,7 +2,6 @@ import { useMutation } from "@tanstack/react-query";
import { LifeBuoy } from "lucide-react";
import { Outlet, redirect, useNavigate } from "react-router";
import { toast } from "sonner";
import { logoutMutation } from "~/api-client/@tanstack/react-query.gen";
import { appContext } from "~/context";
import { authMiddleware } from "~/middleware/auth";
import type { Route } from "./+types/layout";
@ -11,6 +10,7 @@ import { GridBackground } from "./grid-background";
import { Button } from "./ui/button";
import { SidebarProvider, SidebarTrigger } from "./ui/sidebar";
import { AppSidebar } from "./app-sidebar";
import { logoutMutation } from "../api-client/@tanstack/react-query.gen";
export const clientMiddleware = [authMiddleware];
@ -42,7 +42,7 @@ export default function Layout({ loaderData }: Route.ComponentProps) {
<SidebarProvider defaultOpen={true}>
<AppSidebar />
<div className="w-full relative flex flex-col h-screen overflow-hidden">
<header className="z-50 bg-card-header border-b border-border/50 flex-shrink-0">
<header className="z-50 bg-card-header border-b border-border/50 shrink-0">
<div className="flex items-center justify-between py-3 sm:py-4 px-2 sm:px-8 mx-auto container">
<div className="flex items-center gap-4">
<SidebarTrigger />

View file

@ -1,10 +1,10 @@
import { Calendar, Clock, Database, FolderTree, HardDrive } from "lucide-react";
import { useNavigate } from "react-router";
import type { ListSnapshotsResponse } from "~/api-client/types.gen";
import { ByteSize } from "~/client/components/bytes-size";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "~/client/components/ui/table";
import { Tooltip, TooltipContent, TooltipTrigger } from "~/client/components/ui/tooltip";
import { formatDuration } from "~/utils/utils";
import type { ListSnapshotsResponse } from "../api-client";
type Snapshot = ListSnapshotsResponse[number];

View file

@ -1,8 +1,8 @@
import { useQuery, useQueryClient } from "@tanstack/react-query";
import { FolderOpen } from "lucide-react";
import { useCallback, useMemo, useState } from "react";
import { listFilesOptions } from "~/api-client/@tanstack/react-query.gen";
import { FileTree } from "~/client/components/file-tree";
import { listFilesOptions } from "../api-client/@tanstack/react-query.gen";
interface FileEntry {
name: string;

View file

@ -1,5 +1,5 @@
import { useQuery } from "@tanstack/react-query";
import { getSystemInfoOptions } from "~/api-client/@tanstack/react-query.gen";
import { getSystemInfoOptions } from "../api-client/@tanstack/react-query.gen";
export function useSystemInfo() {
const { data, isLoading, error } = useQuery({

View file

@ -4,7 +4,7 @@ import type {
GetRepositoryResponse,
GetVolumeResponse,
ListSnapshotsResponse,
} from "~/api-client";
} from "../api-client";
export type Volume = GetVolumeResponse["volume"];
export type StatFs = GetVolumeResponse["statfs"];

View file

@ -3,7 +3,6 @@ import { AlertTriangle, Download } from "lucide-react";
import { useState } from "react";
import { useNavigate } from "react-router";
import { toast } from "sonner";
import { downloadResticPasswordMutation } from "~/api-client/@tanstack/react-query.gen";
import { AuthLayout } from "~/client/components/auth-layout";
import { Alert, AlertDescription, AlertTitle } from "~/client/components/ui/alert";
import { Button } from "~/client/components/ui/button";
@ -11,6 +10,7 @@ import { Input } from "~/client/components/ui/input";
import { Label } from "~/client/components/ui/label";
import { authMiddleware } from "~/middleware/auth";
import type { Route } from "./+types/download-recovery-key";
import { downloadResticPasswordMutation } from "~/client/api-client/@tanstack/react-query.gen";
export const clientMiddleware = [authMiddleware];

View file

@ -4,13 +4,13 @@ import { type } from "arktype";
import { useForm } from "react-hook-form";
import { useNavigate } from "react-router";
import { toast } from "sonner";
import { loginMutation } from "~/api-client/@tanstack/react-query.gen";
import { AuthLayout } from "~/client/components/auth-layout";
import { Button } from "~/client/components/ui/button";
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "~/client/components/ui/form";
import { Input } from "~/client/components/ui/input";
import { authMiddleware } from "~/middleware/auth";
import type { Route } from "./+types/login";
import { loginMutation } from "~/client/api-client/@tanstack/react-query.gen";
export const clientMiddleware = [authMiddleware];

View file

@ -4,7 +4,6 @@ import { type } from "arktype";
import { useForm } from "react-hook-form";
import { useNavigate } from "react-router";
import { toast } from "sonner";
import { registerMutation } from "~/api-client/@tanstack/react-query.gen";
import {
Form,
FormControl,
@ -19,6 +18,7 @@ import type { Route } from "./+types/onboarding";
import { AuthLayout } from "~/client/components/auth-layout";
import { Input } from "~/client/components/ui/input";
import { Button } from "~/client/components/ui/button";
import { registerMutation } from "~/client/api-client/@tanstack/react-query.gen";
export const clientMiddleware = [authMiddleware];

View file

@ -3,7 +3,7 @@ import { useQuery } from "@tanstack/react-query";
import { type } from "arktype";
import { useCallback, useState } from "react";
import { useForm } from "react-hook-form";
import { listRepositoriesOptions } from "~/api-client/@tanstack/react-query.gen";
import { listRepositoriesOptions } from "~/client/api-client/@tanstack/react-query.gen";
import { RepositoryIcon } from "~/client/components/repository-icon";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "~/client/components/ui/card";
import {
@ -136,7 +136,7 @@ export const CreateScheduleForm = ({ initialValues, formId, onSubmit, volume }:
<Form {...form}>
<form
onSubmit={form.handleSubmit(handleSubmit)}
className="grid gap-4 xl:grid-cols-[minmax(0,_2.3fr)_minmax(320px,_1fr)]"
className="grid gap-4 xl:grid-cols-[minmax(0,2.3fr)_minmax(320px,1fr)]"
id={formId}
>
<div className="grid gap-4">

View file

@ -1,7 +1,6 @@
import { useCallback, useMemo, useState } from "react";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { FileIcon } from "lucide-react";
import { listSnapshotFilesOptions, restoreSnapshotMutation } from "~/api-client/@tanstack/react-query.gen";
import { FileTree, type FileEntry } from "~/client/components/file-tree";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "~/client/components/ui/card";
import { Button } from "~/client/components/ui/button";
@ -20,6 +19,7 @@ import {
import { Tooltip, TooltipContent, TooltipTrigger } from "~/client/components/ui/tooltip";
import type { Snapshot, Volume } from "~/client/lib/types";
import { toast } from "sonner";
import { listSnapshotFilesOptions, restoreSnapshotMutation } from "~/client/api-client/@tanstack/react-query.gen";
interface Props {
snapshot: Snapshot;

View file

@ -1,8 +1,8 @@
import type { ListSnapshotsResponse } from "~/api-client/types.gen";
import { cn } from "~/client/lib/utils";
import { Card } from "~/client/components/ui/card";
import { ByteSize } from "~/client/components/bytes-size";
import { useEffect } from "react";
import type { ListSnapshotsResponse } from "~/client/api-client";
interface Props {
snapshots: ListSnapshotsResponse;
@ -56,7 +56,7 @@ export const SnapshotTimeline = (props: Props) => {
<div className="w-full bg-card">
<div className="relative flex items-center">
<div className="flex-1 overflow-hidden">
<div className="flex gap-4 overflow-x-auto pb-2 [&>:first-child]:ml-2 [&>:last-child]:mr-2">
<div className="flex gap-4 overflow-x-auto pb-2 *:first:ml-2 *:last:mr-2">
{snapshots.map((snapshot, index) => {
const date = new Date(snapshot.time);
const isSelected = snapshotId === snapshot.short_id;

View file

@ -10,15 +10,15 @@ import {
listSnapshotsOptions,
updateBackupScheduleMutation,
stopBackupMutation,
} from "~/api-client/@tanstack/react-query.gen";
} from "~/client/api-client/@tanstack/react-query.gen";
import { parseError } from "~/client/lib/errors";
import { getCronExpression } from "~/utils/utils";
import { CreateScheduleForm, type BackupScheduleFormValues } from "../components/create-schedule-form";
import { ScheduleSummary } from "../components/schedule-summary";
import { getBackupSchedule } from "~/api-client";
import type { Route } from "./+types/backup-details";
import { SnapshotFileBrowser } from "../components/snapshot-file-browser";
import { SnapshotTimeline } from "../components/snapshot-timeline";
import { getBackupSchedule } from "~/client/api-client";
export function meta(_: Route.MetaArgs) {
return [

View file

@ -1,13 +1,13 @@
import { useQuery } from "@tanstack/react-query";
import { CalendarClock, Database, HardDrive, Plus } from "lucide-react";
import { Link } from "react-router";
import { listBackupSchedules } from "~/api-client";
import { listBackupSchedulesOptions } from "~/api-client/@tanstack/react-query.gen";
import { BackupStatusDot } from "../components/backup-status-dot";
import { EmptyState } from "~/client/components/empty-state";
import { Button } from "~/client/components/ui/button";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "~/client/components/ui/card";
import type { Route } from "./+types/backups";
import { listBackupSchedules } from "~/client/api-client";
import { listBackupSchedulesOptions } from "~/client/api-client/@tanstack/react-query.gen";
export function meta(_: Route.MetaArgs) {
return [
@ -68,7 +68,7 @@ export default function Backups({ loaderData }: Route.ComponentProps) {
<CardHeader className="pb-3">
<div className="flex items-start justify-between gap-2">
<div className="flex items-center gap-2 flex-1 min-w-0">
<HardDrive className="h-5 w-5 text-muted-foreground flex-shrink-0" />
<HardDrive className="h-5 w-5 text-muted-foreground shrink-0" />
<CardTitle className="text-lg truncate">
Volume <span className="text-strong-accent">{schedule.volume.name}</span>
</CardTitle>

View file

@ -7,7 +7,7 @@ import {
createBackupScheduleMutation,
listRepositoriesOptions,
listVolumesOptions,
} from "~/api-client/@tanstack/react-query.gen";
} from "~/client/api-client/@tanstack/react-query.gen";
import { Button } from "~/client/components/ui/button";
import { Card, CardContent } from "~/client/components/ui/card";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "~/client/components/ui/select";
@ -16,7 +16,7 @@ import { EmptyState } from "~/client/components/empty-state";
import { getCronExpression } from "~/utils/utils";
import { CreateScheduleForm, type BackupScheduleFormValues } from "../components/create-schedule-form";
import type { Route } from "./+types/create-backup";
import { listRepositories, listVolumes } from "~/api-client";
import { listRepositories, listVolumes } from "~/client/api-client";
export function meta(_: Route.MetaArgs) {
return [
@ -168,7 +168,7 @@ export default function CreateBackup({ loaderData }: Route.ComponentProps) {
<div className="absolute inset-0 animate-pulse">
<div className="w-24 h-24 rounded-full bg-primary/10 blur-2xl" />
</div>
<div className="relative flex items-center justify-center w-24 h-24 rounded-full bg-gradient-to-br from-primary/20 to-primary/5 border-2 border-primary/20">
<div className="relative flex items-center justify-center w-24 h-24 rounded-full bg-linear-to-br from-primary/20 to-primary/5 border-2 border-primary/20">
<Database className="w-12 h-12 text-primary/70" strokeWidth={1.5} />
</div>
</div>

View file

@ -2,7 +2,7 @@ import { useMutation } from "@tanstack/react-query";
import { RotateCcw } from "lucide-react";
import { useId, useState } from "react";
import { toast } from "sonner";
import { restoreSnapshotMutation } from "~/api-client/@tanstack/react-query.gen";
import { restoreSnapshotMutation } from "~/client/api-client/@tanstack/react-query.gen";
import { parseError } from "~/client/lib/errors";
import { Button } from "~/client/components/ui/button";
import {

View file

@ -2,8 +2,8 @@ import { useQuery } from "@tanstack/react-query";
import { Database, RotateCcw } from "lucide-react";
import { useState } from "react";
import { useNavigate } from "react-router";
import { listRepositories } from "~/api-client/sdk.gen";
import { listRepositoriesOptions } from "~/api-client/@tanstack/react-query.gen";
import { listRepositories } from "~/client/api-client/sdk.gen";
import { listRepositoriesOptions } from "~/client/api-client/@tanstack/react-query.gen";
import { CreateRepositoryDialog } from "~/client/components/create-repository-dialog";
import { RepositoryIcon } from "~/client/components/repository-icon";
import { Button } from "~/client/components/ui/button";
@ -79,13 +79,13 @@ export default function Repositories({ loaderData }: Route.ComponentProps) {
<div className="flex flex-col lg:flex-row items-stretch lg:items-center gap-2 md:justify-between p-4 bg-card-header py-4">
<span className="flex flex-col sm:flex-row items-stretch md:items-center gap-0 flex-wrap ">
<Input
className="w-full lg:w-[180px] min-w-[180px] mr-[-1px] mt-[-1px]"
className="w-full lg:w-[180px] min-w-[180px] -mr-px -mt-px"
placeholder="Search repositories…"
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
/>
<Select value={statusFilter} onValueChange={setStatusFilter}>
<SelectTrigger className="w-full lg:w-[180px] min-w-[180px] mr-[-1px] mt-[-1px]">
<SelectTrigger className="w-full lg:w-[180px] min-w-[180px] -mr-px -mt-px">
<SelectValue placeholder="All status" />
</SelectTrigger>
<SelectContent>
@ -95,7 +95,7 @@ export default function Repositories({ loaderData }: Route.ComponentProps) {
</SelectContent>
</Select>
<Select value={backendFilter} onValueChange={setBackendFilter}>
<SelectTrigger className="w-full lg:w-[180px] min-w-[180px] mt-[-1px]">
<SelectTrigger className="w-full lg:w-[180px] min-w-[180px] -mt-px">
<SelectValue placeholder="All backends" />
</SelectTrigger>
<SelectContent>

View file

@ -7,7 +7,7 @@ import {
doctorRepositoryMutation,
getRepositoryOptions,
listSnapshotsOptions,
} from "~/api-client/@tanstack/react-query.gen";
} from "~/client/api-client/@tanstack/react-query.gen";
import { Button } from "~/client/components/ui/button";
import {
AlertDialog,
@ -19,7 +19,7 @@ import {
AlertDialogTitle,
} from "~/client/components/ui/alert-dialog";
import { parseError } from "~/client/lib/errors";
import { getRepository } from "~/api-client/sdk.gen";
import { getRepository } from "~/client/api-client/sdk.gen";
import type { Route } from "./+types/repository-details";
import { cn } from "~/client/lib/utils";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "~/client/components/ui/tabs";

View file

@ -1,10 +1,10 @@
import { useQuery } from "@tanstack/react-query";
import { redirect, useParams } from "react-router";
import { listSnapshotFilesOptions } from "~/api-client/@tanstack/react-query.gen";
import { listSnapshotFilesOptions } from "~/client/api-client/@tanstack/react-query.gen";
import { Card, CardContent, CardHeader, CardTitle } from "~/client/components/ui/card";
import { RestoreSnapshotDialog } from "../components/restore-snapshot-dialog";
import { SnapshotFileBrowser } from "~/client/modules/backups/components/snapshot-file-browser";
import { getSnapshotDetails } from "~/api-client";
import { getSnapshotDetails } from "~/client/api-client";
import type { Route } from "./+types/snapshot-details";
export function meta({ params }: Route.MetaArgs) {

View file

@ -1,7 +1,7 @@
import { useQuery } from "@tanstack/react-query";
import { Database } from "lucide-react";
import { useState } from "react";
import { listSnapshotsOptions } from "~/api-client/@tanstack/react-query.gen";
import { listSnapshotsOptions } from "~/client/api-client/@tanstack/react-query.gen";
import { SnapshotsTable } from "~/client/components/snapshots-table";
import { Button } from "~/client/components/ui/button";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "~/client/components/ui/card";
@ -83,7 +83,7 @@ export const RepositorySnapshotsTabContent = ({ repository }: Props) => {
<div className="absolute inset-0 animate-pulse">
<div className="w-32 h-32 rounded-full bg-primary/10 blur-2xl" />
</div>
<div className="relative flex items-center justify-center w-32 h-32 rounded-full bg-gradient-to-br from-primary/20 to-primary/5 border-2 border-primary/20">
<div className="relative flex items-center justify-center w-32 h-32 rounded-full bg-linear-to-br from-primary/20 to-primary/5 border-2 border-primary/20">
<Database className="w-16 h-16 text-primary/70" strokeWidth={1.5} />
</div>
</div>
@ -110,7 +110,7 @@ export const RepositorySnapshotsTabContent = ({ repository }: Props) => {
</div>
<div className="flex gap-2 items-center">
<Input
className="w-full lg:w-[240px]"
className="w-full lg:w-60"
placeholder="Search snapshots..."
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}

View file

@ -3,11 +3,6 @@ import { Download, KeyRound, User } from "lucide-react";
import { useState } from "react";
import { useNavigate } from "react-router";
import { toast } from "sonner";
import {
changePasswordMutation,
downloadResticPasswordMutation,
logoutMutation,
} from "~/api-client/@tanstack/react-query.gen";
import { Button } from "~/client/components/ui/button";
import { Card, CardContent, CardDescription, CardTitle } from "~/client/components/ui/card";
import {
@ -23,6 +18,11 @@ import { Input } from "~/client/components/ui/input";
import { Label } from "~/client/components/ui/label";
import { appContext } from "~/context";
import type { Route } from "./+types/settings";
import {
changePasswordMutation,
downloadResticPasswordMutation,
logoutMutation,
} from "~/client/api-client/@tanstack/react-query.gen";
export function meta(_: Route.MetaArgs) {
return [

View file

@ -2,7 +2,7 @@ import { useMutation } from "@tanstack/react-query";
import { formatDistanceToNow } from "date-fns";
import { HeartIcon } from "lucide-react";
import { toast } from "sonner";
import { healthCheckVolumeMutation, updateVolumeMutation } from "~/api-client/@tanstack/react-query.gen";
import { healthCheckVolumeMutation, updateVolumeMutation } from "~/client/api-client/@tanstack/react-query.gen";
import { OnOff } from "~/client/components/onoff";
import { Button } from "~/client/components/ui/button";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "~/client/components/ui/card";
@ -54,7 +54,7 @@ export const HealthchecksCard = ({ volume }: Props) => {
</CardHeader>
<CardContent>
<div className="flex flex-col flex-1 justify-start">
{volume.lastError && <span className="text-sm text-red-500 break-words">{volume.lastError}</span>}
{volume.lastError && <span className="text-sm text-red-500 wrap-break-word">{volume.lastError}</span>}
{volume.status === "mounted" && <span className="text-md text-emerald-500">Healthy</span>}
{volume.status !== "unmounted" && (
<span className="text-xs text-muted-foreground mb-4">Checked {timeAgo || "never"}</span>

View file

@ -2,12 +2,6 @@ import { useMutation, useQuery } from "@tanstack/react-query";
import { useNavigate, useParams, useSearchParams } from "react-router";
import { toast } from "sonner";
import { useState } from "react";
import {
deleteVolumeMutation,
getVolumeOptions,
mountVolumeMutation,
unmountVolumeMutation,
} from "~/api-client/@tanstack/react-query.gen";
import { StatusDot } from "~/client/components/status-dot";
import { Button } from "~/client/components/ui/button";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "~/client/components/ui/tabs";
@ -24,12 +18,18 @@ import { VolumeIcon } from "~/client/components/volume-icon";
import { parseError } from "~/client/lib/errors";
import { cn } from "~/client/lib/utils";
import type { Route } from "./+types/volume-details";
import { getVolume } from "~/api-client";
import { VolumeInfoTabContent } from "../tabs/info";
import { FilesTabContent } from "../tabs/files";
import { DockerTabContent } from "../tabs/docker";
import { Tooltip, TooltipContent, TooltipTrigger } from "~/client/components/ui/tooltip";
import { useSystemInfo } from "~/client/hooks/use-system-info";
import { getVolume } from "~/client/api-client";
import {
deleteVolumeMutation,
getVolumeOptions,
mountVolumeMutation,
unmountVolumeMutation,
} from "~/client/api-client/@tanstack/react-query.gen";
export function meta({ params }: Route.MetaArgs) {
return [

View file

@ -2,8 +2,6 @@ import { useQuery } from "@tanstack/react-query";
import { HardDrive, RotateCcw } from "lucide-react";
import { useState } from "react";
import { useNavigate } from "react-router";
import { listVolumes } from "~/api-client";
import { listVolumesOptions } from "~/api-client/@tanstack/react-query.gen";
import { CreateVolumeDialog } from "~/client/components/create-volume-dialog";
import { EmptyState } from "~/client/components/empty-state";
import { StatusDot } from "~/client/components/status-dot";
@ -14,6 +12,8 @@ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "~
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "~/client/components/ui/table";
import { VolumeIcon } from "~/client/components/volume-icon";
import type { Route } from "./+types/volumes";
import { listVolumes } from "~/client/api-client";
import { listVolumesOptions } from "~/client/api-client/@tanstack/react-query.gen";
export function meta(_: Route.MetaArgs) {
return [
@ -79,13 +79,13 @@ export default function Volumes({ loaderData }: Route.ComponentProps) {
<div className="flex flex-col lg:flex-row items-stretch lg:items-center gap-2 md:justify-between p-4 bg-card-header py-4">
<span className="flex flex-col sm:flex-row items-stretch md:items-center gap-0 flex-wrap ">
<Input
className="w-full lg:w-[180px] min-w-[180px] mr-[-1px] mt-[-1px]"
className="w-full lg:w-[180px] min-w-[180px] -mr-px -mt-px"
placeholder="Search volumes…"
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
/>
<Select value={statusFilter} onValueChange={setStatusFilter}>
<SelectTrigger className="w-full lg:w-[180px] min-w-[180px] mr-[-1px] mt-[-1px]">
<SelectTrigger className="w-full lg:w-[180px] min-w-[180px] -mr-px -mt-px">
<SelectValue placeholder="All status" />
</SelectTrigger>
<SelectContent>
@ -95,7 +95,7 @@ export default function Volumes({ loaderData }: Route.ComponentProps) {
</SelectContent>
</Select>
<Select value={backendFilter} onValueChange={setBackendFilter}>
<SelectTrigger className="w-full lg:w-[180px] min-w-[180px] mt-[-1px]">
<SelectTrigger className="w-full lg:w-[180px] min-w-[180px] -mt-px">
<SelectValue placeholder="All backends" />
</SelectTrigger>
<SelectContent>

View file

@ -1,7 +1,7 @@
import { useQuery } from "@tanstack/react-query";
import { Unplug } from "lucide-react";
import * as YML from "yaml";
import { getContainersUsingVolumeOptions } from "~/api-client/@tanstack/react-query.gen";
import { getContainersUsingVolumeOptions } from "~/client/api-client/@tanstack/react-query.gen";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "~/client/components/ui/card";
import { CodeBlock } from "~/client/components/ui/code-block";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "~/client/components/ui/table";

View file

@ -1,7 +1,6 @@
import { useMutation } from "@tanstack/react-query";
import { useState } from "react";
import { toast } from "sonner";
import { updateVolumeMutation } from "~/api-client/@tanstack/react-query.gen";
import { CreateVolumeForm, type FormValues } from "~/client/components/create-volume-form";
import {
AlertDialog,
@ -17,6 +16,7 @@ import { Card } from "~/client/components/ui/card";
import type { StatFs, Volume } from "~/client/lib/types";
import { HealthchecksCard } from "../components/healthchecks-card";
import { StorageChart } from "../components/storage-chart";
import { updateVolumeMutation } from "~/client/api-client/@tanstack/react-query.gen";
type Props = {
volume: Volume;

View file

@ -1,5 +1,5 @@
import { redirect, type MiddlewareFunction } from "react-router";
import { getMe, getStatus } from "~/api-client";
import { getMe, getStatus } from "~/client/api-client";
import { appContext } from "~/context";
export const authMiddleware: MiddlewareFunction = async ({ context, request }) => {

View file

@ -3,9 +3,9 @@ import { isRouteErrorResponse, Links, Meta, Outlet, Scripts, ScrollRestoration }
import type { Route } from "./+types/root";
import "./app.css";
import { client } from "./api-client/client.gen";
import { Toaster } from "./client/components/ui/sonner";
import { useServerEvents } from "./client/hooks/use-server-events";
import { client } from "./client/api-client/client.gen";
client.setConfig({
baseUrl: "/",

View file

@ -48,10 +48,10 @@ const app = new Hono()
.route("/api/v1/repositories", repositoriesController.use(requireAuth))
.route("/api/v1/backups", backupScheduleController.use(requireAuth))
.route("/api/v1/system", systemController.use(requireAuth))
.route("/api/v1/events", eventsController.use(requireAuth))
.get("/assets/*", serveStatic({ root: "./assets/frontend" }))
.get("/images/*", serveStatic({ root: "./assets/frontend" }))
.get("*", serveStatic({ path: "./assets/frontend/index.html" }));
.route("/api/v1/events", eventsController.use(requireAuth));
// .get("/assets/*", serveStatic({ root: "./assets/frontend" }))
// .get("/images/*", serveStatic({ root: "./assets/frontend" }))
// .get("*", serveStatic({ path: "./assets/frontend/index.html" }));
app.get("/api/v1/openapi.json", generalDescriptor(app));
app.get("/api/v1/docs", scalarDescriptor);