feat: volume type icon

This commit is contained in:
Nicolas Meienberger
2025-09-03 21:55:01 +02:00
parent 91020e6f23
commit 63b983b1b1
5 changed files with 70 additions and 9 deletions

View File

@@ -13,9 +13,25 @@ export type ListVolumesResponses = {
*/
200: {
volumes: Array<{
config:
| {
backend: "directory";
}
| {
backend: "nfs";
exportPath: string;
server: string;
version: "3" | "4" | "4.1";
port?: number | string;
}
| {
backend: "smb";
};
createdAt: number;
name: string;
path: string;
type: "directory" | "nfs" | "smb";
updatedAt: number;
}>;
};
};
@@ -153,7 +169,7 @@ export type GetVolumeResponses = {
createdAt: number;
name: string;
path: string;
type: string;
type: "directory" | "nfs" | "smb";
updatedAt: number;
};
};

View File

@@ -0,0 +1,47 @@
import type { BackendType } from "@ironmount/schemas";
import { Folder, Server, Share2 } from "lucide-react";
type VolumeIconProps = {
backend: BackendType;
size?: number;
};
const getIconAndColor = (backend: BackendType) => {
switch (backend) {
case "directory":
return {
icon: Folder,
color: "text-blue-600 dark:text-blue-400",
label: "Directory",
};
case "nfs":
return {
icon: Server,
color: "text-orange-600 dark:text-orange-400",
label: "NFS",
};
case "smb":
return {
icon: Share2,
color: "text-purple-600 dark:text-purple-400",
label: "SMB",
};
default:
return {
icon: Folder,
color: "text-gray-600 dark:text-gray-400",
label: "Unknown",
};
}
};
export const VolumeIcon = ({ backend, size = 10 }: VolumeIconProps) => {
const { icon: Icon, color, label } = getIconAndColor(backend);
return (
<span className={`flex items-center gap-2 ${color} rounded-md px-2 py-1`}>
<Icon size={size} />
{label}
</span>
);
};

View File

@@ -1,5 +1,5 @@
import { useMutation, useQuery } from "@tanstack/react-query";
import { Copy, Folder } from "lucide-react";
import { Copy } from "lucide-react";
import { useState } from "react";
import { toast } from "sonner";
import { type ListVolumesResponse, listVolumes } from "~/api-client";
@@ -10,6 +10,7 @@ import { Button } from "~/components/ui/button";
import { Input } from "~/components/ui/input";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "~/components/ui/select";
import { Table, TableBody, TableCaption, TableCell, TableHead, TableHeader, TableRow } from "~/components/ui/table";
import { VolumeIcon } from "~/components/volume-icon";
import { parseError } from "~/lib/errors";
import { cn } from "~/lib/utils";
import type { Route } from "./+types/home";
@@ -114,10 +115,7 @@ export default function Home({ loaderData }: Route.ComponentProps) {
<TableRow key={volume.name}>
<TableCell className="font-medium">{volume.name}</TableCell>
<TableCell>
<span className="mx-auto flex items-center gap-2 text-purple-800 dark:text-purple-300 rounded-md px-2 py-1">
<Folder size={10} />
Volume
</span>
<VolumeIcon backend={volume.type} />
</TableCell>
<TableCell>
<span className="flex items-center gap-2">

View File

@@ -1,4 +1,4 @@
import type { volumeConfigSchema } from "@ironmount/schemas";
import type { BackendType, volumeConfigSchema } from "@ironmount/schemas";
import { sql } from "drizzle-orm";
import { int, sqliteTable, text } from "drizzle-orm/sqlite-core";
@@ -6,7 +6,7 @@ export const volumesTable = sqliteTable("volumes_table", {
id: int().primaryKey({ autoIncrement: true }),
name: text().notNull().unique(),
path: text().notNull(),
type: text().notNull(),
type: text().$type<BackendType>().notNull(),
createdAt: int("created_at", { mode: "timestamp" }).notNull().default(sql`(unixepoch())`),
updatedAt: int("updated_at", { mode: "timestamp" }).notNull().default(sql`(unixepoch())`),
config: text("config", { mode: "json" }).$type<typeof volumeConfigSchema.inferOut>().notNull(),

View File

@@ -6,7 +6,7 @@ import { resolver } from "hono-openapi/arktype";
const volumeSchema = type({
name: "string",
path: "string",
type: "string",
type: type.enumerated("nfs", "smb", "directory"),
createdAt: "number",
updatedAt: "number",
config: volumeConfigSchema,