From d36f16cea14b855bb2db7843e48b6c56b9b4d53f Mon Sep 17 00:00:00 2001 From: maxsoch Date: Fri, 24 Jul 2026 14:46:51 +0200 Subject: [PATCH] feat: configurable icon_size (small/medium/large) --- config/dashboard.yml | 135 ++++++++++++------ docker-compose.yml | 2 +- src/components/dashboard/Dashboard.tsx | 4 +- src/components/dashboard/DashboardSection.tsx | 8 +- src/components/dashboard/ServiceCard.tsx | 28 ++-- src/lib/validation.ts | 2 + src/types/config.ts | 3 + 7 files changed, 124 insertions(+), 58 deletions(-) diff --git a/config/dashboard.yml b/config/dashboard.yml index 4988676..fbb4018 100644 --- a/config/dashboard.yml +++ b/config/dashboard.yml @@ -1,15 +1,14 @@ site: name: "Soch Family" title: " " - #title: "Les applications de la famille" logoUrl: "https://immich.socheleau.fr/api/assets/e010423f-ca95-45a4-a9ee-9bb1a5a48688/thumbnail?slug=us_6&size=preview&c=IhgKJYiHg4ZfhXh6h5aJp5eAdQlJ&edited=true" - #description: "Accès rapide à nos services" showFooter: false theme: mode: "dark" accent: "#8b5cf6" background: "gradient" + icon_size: "large" authentication: logout_url: "https://auth.socheleau.fr/logout" @@ -19,66 +18,114 @@ authentication: header_group: "Remote-Groups" sections: - - id: "global" - title: "Global" - #description: "Services accessibles à toute la famille" + - id: "soch-services" + title: "Soch's services" cardLayout: "horizontal" - visible_by_group: "arr" links: - - id: "nextcloud" - name: "Nextcloud" - description: "Fichiers et documents" - url: "https://cloud.example.com" - icon: "Cloud" - iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/nextcloud.svg" - color: "#2daae1" + - id: "authelia" + name: "Authelia" + description: "Authentification unique" + url: "https://auth.socheleau.fr" + icon: "Shield" + iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/authelia.svg" + color: "#1a7f37" openInNewTab: false - visible_by_user: "jean" - - id: "jellyfin" - name: "Jellyfin" + - id: "plex" + name: "Plex" description: "Films et séries" - url: "https://jellyfin.example.com" + url: "https://plex.socheleau.fr" icon: "Film" - iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/jellyfin.svg" - color: "#aa5cc3" + iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/plex.svg" + color: "#e5a00d" openInNewTab: false - - id: "navidrome" - name: "Navidrome" - description: "Musique" - url: "https://music.example.com" - icon: "Music" - iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/navidrome.svg" - color: "#22c55e" + - id: "bitwarden" + name: "Bitwarden" + description: "Mots de passe" + url: "https://bitwarden.socheleau.fr" + icon: "Shield" + iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/bitwarden.svg" + color: "#175ddc" openInNewTab: false - - id: "minecraft" - name: "Minecraft" - description: "Serveur de jeu" - url: "https://minecraft.example.com" - icon: "Gamepad2" - iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/minecraft.svg" - color: "#f97316" + - id: "immich" + name: "Immich" + description: "Photos et vidéos" + url: "https://immich.socheleau.fr" + icon: "Image" + iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/immich.svg" + color: "#4250af" openInNewTab: false - - id: "custom" - title: "Liens personnalisés" + - id: "freshrss" + name: "FreshRSS" + description: "Flux RSS" + url: "https://rss.socheleau.fr" + icon: "Rss" + iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/freshrss.svg" + color: "#0979b0" + openInNewTab: false + + - id: "tandoor" + name: "Tandoor" + description: "Recettes de cuisine" + url: "https://tandoor.socheleau.fr" + icon: "ChefHat" + iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/tandoor-recipes.svg" + color: "#dc7b2a" + openInNewTab: false + + - id: "readeck" + name: "Readeck" + description: "Lecture différée" + url: "https://readeck.socheleau.fr" + icon: "BookOpen" + iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/readeck.svg" + color: "#14b8a6" + openInNewTab: false + + - id: "homes" + title: "Homes" cardLayout: "horizontal" links: - - id: "homeassistant" - name: "Home Assistant" + - id: "arasu" + name: "Arasu" description: "Domotique" - url: "https://ha.example.com" + url: "https://arasu.socheleau.fr" icon: "House" iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/home-assistant.svg" color: "#22c55e" openInNewTab: false - - id: "router" - name: "Routeur" - description: "Administration réseau" - url: "http://192.168.1.1" - icon: "Router" - color: "#f59e0b" + - id: "arr" + title: "*arr" + cardLayout: "horizontal" + visible_by_group: "arr" + links: + - id: "radarr" + name: "Radarr" + description: "Gestion de films" + url: "https://radarr.arr.socheleau.fr" + icon: "Clapperboard" + iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/radarr.svg" + color: "#e73a2e" + openInNewTab: false + + - id: "sonarr" + name: "Sonarr" + description: "Gestion de séries" + url: "https://sonarr.arr.socheleau.fr" + icon: "Tv" + iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/sonarr.svg" + color: "#35c5f4" + openInNewTab: false + + - id: "prowlarr" + name: "Prowlarr" + description: "Indexeur de torrents" + url: "https://prowlarr.arr.socheleau.fr" + icon: "Search" + iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/prowlarr.svg" + color: "#e65c21" openInNewTab: false diff --git a/docker-compose.yml b/docker-compose.yml index f3610b5..cda9bdb 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,6 +1,6 @@ services: sochboard: - build: . + image: registry2.socheleau.fr/maxence/sochboard:latest container_name: sochboard ports: - "3000:3000" diff --git a/src/components/dashboard/Dashboard.tsx b/src/components/dashboard/Dashboard.tsx index 8f7d5df..fd750cc 100644 --- a/src/components/dashboard/Dashboard.tsx +++ b/src/components/dashboard/Dashboard.tsx @@ -22,7 +22,7 @@ export function Dashboard({ config, isAuthenticated = false, username = null, cu />
{config.sections.map((section, index) => ( - + ))}
{config.site.showFooter !== false && ( @@ -32,4 +32,4 @@ export function Dashboard({ config, isAuthenticated = false, username = null, cu )} ) -} +} \ No newline at end of file diff --git a/src/components/dashboard/DashboardSection.tsx b/src/components/dashboard/DashboardSection.tsx index a0a046e..22b4fbd 100644 --- a/src/components/dashboard/DashboardSection.tsx +++ b/src/components/dashboard/DashboardSection.tsx @@ -1,15 +1,16 @@ import { ServiceCard } from "./ServiceCard" import { isVisible } from "@/lib/visibility" -import type { SectionConfig } from "@/types/config" +import type { SectionConfig, IconSize } from "@/types/config" interface DashboardSectionProps { section: SectionConfig sectionIndex?: number currentUser?: string | null userGroups?: string[] + iconSize?: IconSize } -export function DashboardSection({ section, sectionIndex = 0, currentUser = null, userGroups = [] }: DashboardSectionProps) { +export function DashboardSection({ section, sectionIndex = 0, currentUser = null, userGroups = [], iconSize = "medium" }: DashboardSectionProps) { if (!isVisible(section, currentUser, userGroups)) return null const visibleLinks = section.links.filter((link) => isVisible(link, currentUser, userGroups)) @@ -32,13 +33,14 @@ export function DashboardSection({ section, sectionIndex = 0, currentUser = null

{section.description}

)} -
+
{visibleLinks.map((link, index) => ( ))}
diff --git a/src/components/dashboard/ServiceCard.tsx b/src/components/dashboard/ServiceCard.tsx index d03e1d7..239d8f6 100644 --- a/src/components/dashboard/ServiceCard.tsx +++ b/src/components/dashboard/ServiceCard.tsx @@ -1,18 +1,26 @@ import { IconRenderer } from "./IconRenderer" -import type { LinkConfig } from "@/types/config" +import type { LinkConfig, IconSize } from "@/types/config" interface ServiceCardProps { link: LinkConfig index?: number layout?: "horizontal" | "vertical" + iconSize?: IconSize } -export function ServiceCard({ link, index = 0, layout = "horizontal" }: ServiceCardProps) { +const sizeMap: Record = { + small: { hCont: 10, hImg: "size-5", hIcon: 18, vCont: 12, vImg: "size-6", vIcon: 22 }, + medium: { hCont: 12, hImg: "size-7", hIcon: 24, vCont: 14, vImg: "size-8", vIcon: 30 }, + large: { hCont: 12, hImg: "size-8", hIcon: 28, vCont: 14, vImg: "size-9", vIcon: 34 }, +} + +export function ServiceCard({ link, index = 0, layout = "horizontal", iconSize = "medium" }: ServiceCardProps) { const linkProps = link.openInNewTab ? { target: "_blank", rel: "noopener noreferrer" } : {} const isHorizontal = layout === "horizontal" + const s = sizeMap[iconSize] return (
{link.iconUrl ? ( - + ) : ( - + )}
@@ -73,16 +83,18 @@ export function ServiceCard({ link, index = 0, layout = "horizontal" }: ServiceC <>
{link.iconUrl ? ( - + ) : ( - + )}
{link.openInNewTab && ( diff --git a/src/lib/validation.ts b/src/lib/validation.ts index 8aa41f1..274a7b0 100644 --- a/src/lib/validation.ts +++ b/src/lib/validation.ts @@ -32,6 +32,7 @@ export const themeSchema = z.object({ .regex(hexColorRegex, "Invalid accent color") .default("#8b5cf6"), background: z.enum(["gradient", "solid"]).default("gradient"), + icon_size: z.enum(["small", "medium", "large"]).optional().default("medium"), }) export const siteSchema = z.object({ @@ -57,6 +58,7 @@ export const dashboardConfigSchema = z.object({ mode: "dark", accent: "#8b5cf6", background: "gradient", + icon_size: "medium", }), authentication: authenticationSchema.optional(), sections: z.array(sectionSchema).default([]), diff --git a/src/types/config.ts b/src/types/config.ts index 7594e53..61e3941 100644 --- a/src/types/config.ts +++ b/src/types/config.ts @@ -7,10 +7,13 @@ export interface SiteConfig { showFooter?: boolean } +export type IconSize = "small" | "medium" | "large" + export interface ThemeConfig { mode: "dark" | "light" accent: string background: "gradient" | "solid" + icon_size?: IconSize } export interface LinkConfig {