mirror of
https://github.com/nicotsx/ironmount.git
synced 2025-12-10 12:10:51 +01:00
feat: volume type icon
This commit is contained in:
@@ -13,9 +13,25 @@ export type ListVolumesResponses = {
|
|||||||
*/
|
*/
|
||||||
200: {
|
200: {
|
||||||
volumes: Array<{
|
volumes: Array<{
|
||||||
|
config:
|
||||||
|
| {
|
||||||
|
backend: "directory";
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
backend: "nfs";
|
||||||
|
exportPath: string;
|
||||||
|
server: string;
|
||||||
|
version: "3" | "4" | "4.1";
|
||||||
|
port?: number | string;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
backend: "smb";
|
||||||
|
};
|
||||||
createdAt: number;
|
createdAt: number;
|
||||||
name: string;
|
name: string;
|
||||||
path: string;
|
path: string;
|
||||||
|
type: "directory" | "nfs" | "smb";
|
||||||
|
updatedAt: number;
|
||||||
}>;
|
}>;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -153,7 +169,7 @@ export type GetVolumeResponses = {
|
|||||||
createdAt: number;
|
createdAt: number;
|
||||||
name: string;
|
name: string;
|
||||||
path: string;
|
path: string;
|
||||||
type: string;
|
type: "directory" | "nfs" | "smb";
|
||||||
updatedAt: number;
|
updatedAt: number;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
47
apps/client/app/components/volume-icon.tsx
Normal file
47
apps/client/app/components/volume-icon.tsx
Normal 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>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { useMutation, useQuery } from "@tanstack/react-query";
|
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||||
import { Copy, Folder } from "lucide-react";
|
import { Copy } from "lucide-react";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import { type ListVolumesResponse, listVolumes } from "~/api-client";
|
import { type ListVolumesResponse, listVolumes } from "~/api-client";
|
||||||
@@ -10,6 +10,7 @@ import { Button } from "~/components/ui/button";
|
|||||||
import { Input } from "~/components/ui/input";
|
import { Input } from "~/components/ui/input";
|
||||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "~/components/ui/select";
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "~/components/ui/select";
|
||||||
import { Table, TableBody, TableCaption, TableCell, TableHead, TableHeader, TableRow } from "~/components/ui/table";
|
import { Table, TableBody, TableCaption, TableCell, TableHead, TableHeader, TableRow } from "~/components/ui/table";
|
||||||
|
import { VolumeIcon } from "~/components/volume-icon";
|
||||||
import { parseError } from "~/lib/errors";
|
import { parseError } from "~/lib/errors";
|
||||||
import { cn } from "~/lib/utils";
|
import { cn } from "~/lib/utils";
|
||||||
import type { Route } from "./+types/home";
|
import type { Route } from "./+types/home";
|
||||||
@@ -114,10 +115,7 @@ export default function Home({ loaderData }: Route.ComponentProps) {
|
|||||||
<TableRow key={volume.name}>
|
<TableRow key={volume.name}>
|
||||||
<TableCell className="font-medium">{volume.name}</TableCell>
|
<TableCell className="font-medium">{volume.name}</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<span className="mx-auto flex items-center gap-2 text-purple-800 dark:text-purple-300 rounded-md px-2 py-1">
|
<VolumeIcon backend={volume.type} />
|
||||||
<Folder size={10} />
|
|
||||||
Volume
|
|
||||||
</span>
|
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<span className="flex items-center gap-2">
|
<span className="flex items-center gap-2">
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { volumeConfigSchema } from "@ironmount/schemas";
|
import type { BackendType, volumeConfigSchema } from "@ironmount/schemas";
|
||||||
import { sql } from "drizzle-orm";
|
import { sql } from "drizzle-orm";
|
||||||
import { int, sqliteTable, text } from "drizzle-orm/sqlite-core";
|
import { int, sqliteTable, text } from "drizzle-orm/sqlite-core";
|
||||||
|
|
||||||
@@ -6,7 +6,7 @@ export const volumesTable = sqliteTable("volumes_table", {
|
|||||||
id: int().primaryKey({ autoIncrement: true }),
|
id: int().primaryKey({ autoIncrement: true }),
|
||||||
name: text().notNull().unique(),
|
name: text().notNull().unique(),
|
||||||
path: text().notNull(),
|
path: text().notNull(),
|
||||||
type: text().notNull(),
|
type: text().$type<BackendType>().notNull(),
|
||||||
createdAt: int("created_at", { mode: "timestamp" }).notNull().default(sql`(unixepoch())`),
|
createdAt: int("created_at", { mode: "timestamp" }).notNull().default(sql`(unixepoch())`),
|
||||||
updatedAt: int("updated_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(),
|
config: text("config", { mode: "json" }).$type<typeof volumeConfigSchema.inferOut>().notNull(),
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { resolver } from "hono-openapi/arktype";
|
|||||||
const volumeSchema = type({
|
const volumeSchema = type({
|
||||||
name: "string",
|
name: "string",
|
||||||
path: "string",
|
path: "string",
|
||||||
type: "string",
|
type: type.enumerated("nfs", "smb", "directory"),
|
||||||
createdAt: "number",
|
createdAt: "number",
|
||||||
updatedAt: "number",
|
updatedAt: "number",
|
||||||
config: volumeConfigSchema,
|
config: volumeConfigSchema,
|
||||||
|
|||||||
Reference in New Issue
Block a user