mirror of
https://github.com/nicotsx/ironmount.git
synced 2025-12-10 12:10:51 +01:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
df6b70c96f | ||
|
|
94423bd0a5 | ||
|
|
ed2a625fa7 | ||
|
|
a3e027694a | ||
|
|
0d36484c04 |
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@@ -74,6 +74,8 @@ jobs:
|
|||||||
push: true
|
push: true
|
||||||
tags: ${{ steps.meta.outputs.tags }}
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
labels: ${{ steps.meta.outputs.labels }}
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
|
build-args: |
|
||||||
|
APP_VERSION=${{ needs.determine-release-type.outputs.tagname }}
|
||||||
|
|
||||||
publish-release:
|
publish-release:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|||||||
@@ -59,6 +59,8 @@ CMD ["bun", "run", "dev"]
|
|||||||
# ------------------------------
|
# ------------------------------
|
||||||
FROM oven/bun:${BUN_VERSION} AS builder
|
FROM oven/bun:${BUN_VERSION} AS builder
|
||||||
|
|
||||||
|
ARG APP_VERSION=dev
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
COPY ./package.json ./bun.lock ./
|
COPY ./package.json ./bun.lock ./
|
||||||
@@ -66,6 +68,9 @@ RUN bun install --frozen-lockfile
|
|||||||
|
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
|
RUN touch .env
|
||||||
|
RUN echo "VITE_APP_VERSION=${APP_VERSION}" >> .env
|
||||||
|
|
||||||
RUN bun run build
|
RUN bun run build
|
||||||
|
|
||||||
FROM base AS production
|
FROM base AS production
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { Link, NavLink } from "react-router";
|
|||||||
import {
|
import {
|
||||||
Sidebar,
|
Sidebar,
|
||||||
SidebarContent,
|
SidebarContent,
|
||||||
|
SidebarFooter,
|
||||||
SidebarGroup,
|
SidebarGroup,
|
||||||
SidebarGroupContent,
|
SidebarGroupContent,
|
||||||
SidebarHeader,
|
SidebarHeader,
|
||||||
@@ -13,6 +14,7 @@ import {
|
|||||||
} from "~/client/components/ui/sidebar";
|
} from "~/client/components/ui/sidebar";
|
||||||
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "~/client/components/ui/tooltip";
|
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "~/client/components/ui/tooltip";
|
||||||
import { cn } from "~/client/lib/utils";
|
import { cn } from "~/client/lib/utils";
|
||||||
|
import { APP_VERSION } from "~/client/lib/version";
|
||||||
|
|
||||||
const items = [
|
const items = [
|
||||||
{
|
{
|
||||||
@@ -85,6 +87,15 @@ export function AppSidebar() {
|
|||||||
</SidebarGroupContent>
|
</SidebarGroupContent>
|
||||||
</SidebarGroup>
|
</SidebarGroup>
|
||||||
</SidebarContent>
|
</SidebarContent>
|
||||||
|
<SidebarFooter className="p-4 border-r border-t border-border/50">
|
||||||
|
<div
|
||||||
|
className={cn("text-xs text-muted-foreground transition-all duration-200", {
|
||||||
|
"opacity-0 w-0 overflow-hidden": state === "collapsed",
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
{APP_VERSION}
|
||||||
|
</div>
|
||||||
|
</SidebarFooter>
|
||||||
</Sidebar>
|
</Sidebar>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -207,7 +207,12 @@ export const CreateVolumeForm = ({ onSubmit, mode = "create", initialValues, for
|
|||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>Port</FormLabel>
|
<FormLabel>Port</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input type="number" placeholder="2049" {...field} />
|
<Input
|
||||||
|
type="number"
|
||||||
|
placeholder="2049"
|
||||||
|
{...field}
|
||||||
|
onChange={(e) => field.onChange(parseInt(e.target.value, 10) || undefined)}
|
||||||
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<FormDescription>NFS server port (default: 2049).</FormDescription>
|
<FormDescription>NFS server port (default: 2049).</FormDescription>
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
@@ -332,7 +337,12 @@ export const CreateVolumeForm = ({ onSubmit, mode = "create", initialValues, for
|
|||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>Port</FormLabel>
|
<FormLabel>Port</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input type="number" placeholder="80" {...field} />
|
<Input
|
||||||
|
type="number"
|
||||||
|
placeholder="80"
|
||||||
|
{...field}
|
||||||
|
onChange={(e) => field.onChange(parseInt(e.target.value, 10) || undefined)}
|
||||||
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<FormDescription>WebDAV server port (default: 80 for HTTP, 443 for HTTPS).</FormDescription>
|
<FormDescription>WebDAV server port (default: 80 for HTTP, 443 for HTTPS).</FormDescription>
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
|
|||||||
1
app/client/lib/version.ts
Normal file
1
app/client/lib/version.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export const APP_VERSION = import.meta.env.VITE_APP_VERSION || "dev";
|
||||||
@@ -16,7 +16,7 @@ export const clientMiddleware = [authMiddleware];
|
|||||||
|
|
||||||
export function meta(_: Route.MetaArgs) {
|
export function meta(_: Route.MetaArgs) {
|
||||||
return [
|
return [
|
||||||
{ title: "Download Recovery Key" },
|
{ title: "Ironmount - Download Recovery Key" },
|
||||||
{
|
{
|
||||||
name: "description",
|
name: "description",
|
||||||
content: "Download your backup recovery key to ensure you can restore your data.",
|
content: "Download your backup recovery key to ensure you can restore your data.",
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export const clientMiddleware = [authMiddleware];
|
|||||||
|
|
||||||
export function meta(_: Route.MetaArgs) {
|
export function meta(_: Route.MetaArgs) {
|
||||||
return [
|
return [
|
||||||
{ title: "Login" },
|
{ title: "Ironmount - Login" },
|
||||||
{
|
{
|
||||||
name: "description",
|
name: "description",
|
||||||
content: "Sign in to your Ironmount account.",
|
content: "Sign in to your Ironmount account.",
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ export const clientMiddleware = [authMiddleware];
|
|||||||
|
|
||||||
export function meta(_: Route.MetaArgs) {
|
export function meta(_: Route.MetaArgs) {
|
||||||
return [
|
return [
|
||||||
{ title: "Onboarding" },
|
{ title: "Ironmount - Onboarding" },
|
||||||
{
|
{
|
||||||
name: "description",
|
name: "description",
|
||||||
content: "Welcome to Ironmount. Create your admin account to get started.",
|
content: "Welcome to Ironmount. Create your admin account to get started.",
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ export const handle = {
|
|||||||
|
|
||||||
export function meta(_: Route.MetaArgs) {
|
export function meta(_: Route.MetaArgs) {
|
||||||
return [
|
return [
|
||||||
{ title: "Backup Job Details" },
|
{ title: "Ironmount - Backup Job Details" },
|
||||||
{
|
{
|
||||||
name: "description",
|
name: "description",
|
||||||
content: "View and manage backup job configuration, schedule, and snapshots.",
|
content: "View and manage backup job configuration, schedule, and snapshots.",
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ export const handle = {
|
|||||||
|
|
||||||
export function meta(_: Route.MetaArgs) {
|
export function meta(_: Route.MetaArgs) {
|
||||||
return [
|
return [
|
||||||
{ title: "Backup Jobs" },
|
{ title: "Ironmount - Backup Jobs" },
|
||||||
{
|
{
|
||||||
name: "description",
|
name: "description",
|
||||||
content: "Automate volume backups with scheduled jobs and retention policies.",
|
content: "Automate volume backups with scheduled jobs and retention policies.",
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ export const handle = {
|
|||||||
|
|
||||||
export function meta(_: Route.MetaArgs) {
|
export function meta(_: Route.MetaArgs) {
|
||||||
return [
|
return [
|
||||||
{ title: "Create Backup Job" },
|
{ title: "Ironmount - Create Backup Job" },
|
||||||
{
|
{
|
||||||
name: "description",
|
name: "description",
|
||||||
content: "Create a new automated backup job for your volumes.",
|
content: "Create a new automated backup job for your volumes.",
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ export const handle = {
|
|||||||
|
|
||||||
export function meta(_: Route.MetaArgs) {
|
export function meta(_: Route.MetaArgs) {
|
||||||
return [
|
return [
|
||||||
{ title: "Create Repository" },
|
{ title: "Ironmount - Create Repository" },
|
||||||
{
|
{
|
||||||
name: "description",
|
name: "description",
|
||||||
content: "Create a new backup repository with encryption and compression.",
|
content: "Create a new backup repository with encryption and compression.",
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ export const handle = {
|
|||||||
|
|
||||||
export function meta(_: Route.MetaArgs) {
|
export function meta(_: Route.MetaArgs) {
|
||||||
return [
|
return [
|
||||||
{ title: "Repositories" },
|
{ title: "Ironmount - Repositories" },
|
||||||
{
|
{
|
||||||
name: "description",
|
name: "description",
|
||||||
content: "Manage your backup repositories with encryption and compression.",
|
content: "Manage your backup repositories with encryption and compression.",
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ export const handle = {
|
|||||||
|
|
||||||
export function meta({ params }: Route.MetaArgs) {
|
export function meta({ params }: Route.MetaArgs) {
|
||||||
return [
|
return [
|
||||||
{ title: params.name },
|
{ title: `Ironmount - ${params.name}` },
|
||||||
{
|
{
|
||||||
name: "description",
|
name: "description",
|
||||||
content: "View repository configuration, status, and snapshots.",
|
content: "View repository configuration, status, and snapshots.",
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ export const handle = {
|
|||||||
|
|
||||||
export function meta({ params }: Route.MetaArgs) {
|
export function meta({ params }: Route.MetaArgs) {
|
||||||
return [
|
return [
|
||||||
{ title: `Snapshot ${params.snapshotId}` },
|
{ title: `Ironmount - Snapshot ${params.snapshotId}` },
|
||||||
{
|
{
|
||||||
name: "description",
|
name: "description",
|
||||||
content: "Browse and restore files from a backup snapshot.",
|
content: "Browse and restore files from a backup snapshot.",
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ export const handle = {
|
|||||||
|
|
||||||
export function meta(_: Route.MetaArgs) {
|
export function meta(_: Route.MetaArgs) {
|
||||||
return [
|
return [
|
||||||
{ title: "Settings" },
|
{ title: "Ironmount - Settings" },
|
||||||
{
|
{
|
||||||
name: "description",
|
name: "description",
|
||||||
content: "Manage your account settings and preferences.",
|
content: "Manage your account settings and preferences.",
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ export const handle = {
|
|||||||
|
|
||||||
export function meta(_: Route.MetaArgs) {
|
export function meta(_: Route.MetaArgs) {
|
||||||
return [
|
return [
|
||||||
{ title: "Create Volume" },
|
{ title: "Ironmount - Create Volume" },
|
||||||
{
|
{
|
||||||
name: "description",
|
name: "description",
|
||||||
content: "Create a new storage volume with automatic mounting and health checks.",
|
content: "Create a new storage volume with automatic mounting and health checks.",
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ export const handle = {
|
|||||||
|
|
||||||
export function meta({ params }: Route.MetaArgs) {
|
export function meta({ params }: Route.MetaArgs) {
|
||||||
return [
|
return [
|
||||||
{ title: params.name },
|
{ title: `Ironmount - ${params.name}` },
|
||||||
{
|
{
|
||||||
name: "description",
|
name: "description",
|
||||||
content: "View and manage volume details, configuration, and files.",
|
content: "View and manage volume details, configuration, and files.",
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ export const handle = {
|
|||||||
|
|
||||||
export function meta(_: Route.MetaArgs) {
|
export function meta(_: Route.MetaArgs) {
|
||||||
return [
|
return [
|
||||||
{ title: "Volumes" },
|
{ title: "Ironmount - Volumes" },
|
||||||
{
|
{
|
||||||
name: "description",
|
name: "description",
|
||||||
content: "Create, manage, monitor, and automate your Docker volumes with ease.",
|
content: "Create, manage, monitor, and automate your Docker volumes with ease.",
|
||||||
|
|||||||
8
bun.lock
8
bun.lock
@@ -4,7 +4,6 @@
|
|||||||
"": {
|
"": {
|
||||||
"name": "@ironmount/client",
|
"name": "@ironmount/client",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@hono/node-server": "^1.19.6",
|
|
||||||
"@hono/standard-validator": "^0.1.5",
|
"@hono/standard-validator": "^0.1.5",
|
||||||
"@hookform/resolvers": "^5.2.2",
|
"@hookform/resolvers": "^5.2.2",
|
||||||
"@radix-ui/react-alert-dialog": "^1.1.15",
|
"@radix-ui/react-alert-dialog": "^1.1.15",
|
||||||
@@ -23,8 +22,6 @@
|
|||||||
"@react-router/serve": "^7.9.3",
|
"@react-router/serve": "^7.9.3",
|
||||||
"@scalar/hono-api-reference": "^0.9.24",
|
"@scalar/hono-api-reference": "^0.9.24",
|
||||||
"@tanstack/react-query": "^5.90.2",
|
"@tanstack/react-query": "^5.90.2",
|
||||||
"@tanstack/react-query-devtools": "^5.90.2",
|
|
||||||
"@tanstack/react-table": "^8.21.3",
|
|
||||||
"arktype": "^2.1.26",
|
"arktype": "^2.1.26",
|
||||||
"class-variance-authority": "^0.7.1",
|
"class-variance-authority": "^0.7.1",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
@@ -60,6 +57,7 @@
|
|||||||
"@hey-api/openapi-ts": "^0.87.4",
|
"@hey-api/openapi-ts": "^0.87.4",
|
||||||
"@react-router/dev": "^7.9.3",
|
"@react-router/dev": "^7.9.3",
|
||||||
"@tailwindcss/vite": "^4.1.14",
|
"@tailwindcss/vite": "^4.1.14",
|
||||||
|
"@tanstack/react-query-devtools": "^5.90.2",
|
||||||
"@types/bun": "^1.3.2",
|
"@types/bun": "^1.3.2",
|
||||||
"@types/dockerode": "^3.3.45",
|
"@types/dockerode": "^3.3.45",
|
||||||
"@types/node": "^24.6.2",
|
"@types/node": "^24.6.2",
|
||||||
@@ -482,10 +480,6 @@
|
|||||||
|
|
||||||
"@tanstack/react-query-devtools": ["@tanstack/react-query-devtools@5.90.2", "", { "dependencies": { "@tanstack/query-devtools": "5.90.1" }, "peerDependencies": { "@tanstack/react-query": "^5.90.2", "react": "^18 || ^19" } }, "sha512-vAXJzZuBXtCQtrY3F/yUNJCV4obT/A/n81kb3+YqLbro5Z2+phdAbceO+deU3ywPw8B42oyJlp4FhO0SoivDFQ=="],
|
"@tanstack/react-query-devtools": ["@tanstack/react-query-devtools@5.90.2", "", { "dependencies": { "@tanstack/query-devtools": "5.90.1" }, "peerDependencies": { "@tanstack/react-query": "^5.90.2", "react": "^18 || ^19" } }, "sha512-vAXJzZuBXtCQtrY3F/yUNJCV4obT/A/n81kb3+YqLbro5Z2+phdAbceO+deU3ywPw8B42oyJlp4FhO0SoivDFQ=="],
|
||||||
|
|
||||||
"@tanstack/react-table": ["@tanstack/react-table@8.21.3", "", { "dependencies": { "@tanstack/table-core": "8.21.3" }, "peerDependencies": { "react": ">=16.8", "react-dom": ">=16.8" } }, "sha512-5nNMTSETP4ykGegmVkhjcS8tTLW6Vl4axfEGQN3v0zdHYbK4UfoqfPChclTrJ4EoK9QynqAu9oUf8VEmrpZ5Ww=="],
|
|
||||||
|
|
||||||
"@tanstack/table-core": ["@tanstack/table-core@8.21.3", "", {}, "sha512-ldZXEhOBb8Is7xLs01fR3YEc3DERiz5silj8tnGkFZytt1abEvl/GhUmCE0PMLaMPTa3Jk4HbKmRlHmu+gCftg=="],
|
|
||||||
|
|
||||||
"@types/bun": ["@types/bun@1.3.2", "", { "dependencies": { "bun-types": "1.3.2" } }, "sha512-t15P7k5UIgHKkxwnMNkJbWlh/617rkDGEdSsDbu+qNHTaz9SKf7aC8fiIlUdD5RPpH6GEkP0cK7WlvmrEBRtWg=="],
|
"@types/bun": ["@types/bun@1.3.2", "", { "dependencies": { "bun-types": "1.3.2" } }, "sha512-t15P7k5UIgHKkxwnMNkJbWlh/617rkDGEdSsDbu+qNHTaz9SKf7aC8fiIlUdD5RPpH6GEkP0cK7WlvmrEBRtWg=="],
|
||||||
|
|
||||||
"@types/d3-array": ["@types/d3-array@3.2.2", "", {}, "sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw=="],
|
"@types/d3-array": ["@types/d3-array@3.2.2", "", {}, "sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw=="],
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
"studio": "drizzle-kit studio"
|
"studio": "drizzle-kit studio"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@hono/node-server": "^1.19.6",
|
|
||||||
"@hono/standard-validator": "^0.1.5",
|
"@hono/standard-validator": "^0.1.5",
|
||||||
"@hookform/resolvers": "^5.2.2",
|
"@hookform/resolvers": "^5.2.2",
|
||||||
"@radix-ui/react-alert-dialog": "^1.1.15",
|
"@radix-ui/react-alert-dialog": "^1.1.15",
|
||||||
@@ -36,8 +35,6 @@
|
|||||||
"@react-router/serve": "^7.9.3",
|
"@react-router/serve": "^7.9.3",
|
||||||
"@scalar/hono-api-reference": "^0.9.24",
|
"@scalar/hono-api-reference": "^0.9.24",
|
||||||
"@tanstack/react-query": "^5.90.2",
|
"@tanstack/react-query": "^5.90.2",
|
||||||
"@tanstack/react-query-devtools": "^5.90.2",
|
|
||||||
"@tanstack/react-table": "^8.21.3",
|
|
||||||
"arktype": "^2.1.26",
|
"arktype": "^2.1.26",
|
||||||
"class-variance-authority": "^0.7.1",
|
"class-variance-authority": "^0.7.1",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
@@ -73,6 +70,7 @@
|
|||||||
"@hey-api/openapi-ts": "^0.87.4",
|
"@hey-api/openapi-ts": "^0.87.4",
|
||||||
"@react-router/dev": "^7.9.3",
|
"@react-router/dev": "^7.9.3",
|
||||||
"@tailwindcss/vite": "^4.1.14",
|
"@tailwindcss/vite": "^4.1.14",
|
||||||
|
"@tanstack/react-query-devtools": "^5.90.2",
|
||||||
"@types/bun": "^1.3.2",
|
"@types/bun": "^1.3.2",
|
||||||
"@types/dockerode": "^3.3.45",
|
"@types/dockerode": "^3.3.45",
|
||||||
"@types/node": "^24.6.2",
|
"@types/node": "^24.6.2",
|
||||||
|
|||||||
Reference in New Issue
Block a user