mirror of
https://github.com/DI0IK/homepage-plus.git
synced 2025-07-18 02:29:49 +00:00
Custom JS and CSS (#1950)
* First commit for custom styles and JS * Adjusted classes * Added ids and classes for services and bookmarks * Apply suggestions from code review * Remove mime dependency * Update settings.json * Detect custom css / js changes, no refresh * Added preload to custom scripts and styles so they can load earlier * Added data attribute name for bookmarks too * Update [path].js * code style, revert some pointer changes --------- Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
This commit is contained in:
parent
0741ef0427
commit
b39c79bea1
46 changed files with 176 additions and 99 deletions
|
@ -14,6 +14,7 @@ export default function ServicesGroup({ group, services, layout, fiveColumns, di
|
|||
<div
|
||||
key={services.name}
|
||||
className={classNames(
|
||||
"services-group",
|
||||
layout?.style === "row" ? "basis-full" : "basis-full md:basis-1/2 lg:basis-1/3 xl:basis-1/4",
|
||||
layout?.style !== "row" && fiveColumns ? "3xl:basis-1/5" : "",
|
||||
layout?.header === false ? "flex-1 px-1 -my-1" : "flex-1 p-1",
|
||||
|
@ -25,11 +26,11 @@ export default function ServicesGroup({ group, services, layout, fiveColumns, di
|
|||
{ layout?.header !== false &&
|
||||
<Disclosure.Button disabled={disableCollapse} className="flex w-full select-none items-center group">
|
||||
{layout?.icon &&
|
||||
<div className="flex-shrink-0 mr-2 w-7 h-7">
|
||||
<div className="flex-shrink-0 mr-2 w-7 h-7 service-group-icon">
|
||||
<ResolvedIcon icon={layout.icon} />
|
||||
</div>
|
||||
}
|
||||
<h2 className="flex text-theme-800 dark:text-theme-300 text-xl font-medium">{services.name}</h2>
|
||||
<h2 className="flex text-theme-800 dark:text-theme-300 text-xl font-medium service-group-name">{services.name}</h2>
|
||||
<MdKeyboardArrowDown className={classNames(
|
||||
disableCollapse ? 'hidden' : '',
|
||||
'transition-all opacity-0 group-hover:opacity-100 ml-auto text-theme-800 dark:text-theme-300 text-xl',
|
||||
|
|
|
@ -29,28 +29,30 @@ export default function Item({ service, group }) {
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<li key={service.name}>
|
||||
<li key={service.name} id={service.id} className="service" data-name={service.name || ""}>
|
||||
<div
|
||||
className={classNames(
|
||||
settings.cardBlur !== undefined && `backdrop-blur${settings.cardBlur.length ? '-' : ""}${settings.cardBlur}`,
|
||||
hasLink && "cursor-pointer",
|
||||
'transition-all h-15 mb-2 p-1 rounded-md font-medium text-theme-700 dark:text-theme-200 dark:hover:text-theme-300 shadow-md shadow-theme-900/10 dark:shadow-theme-900/20 bg-theme-100/20 hover:bg-theme-300/20 dark:bg-white/5 dark:hover:bg-white/10 relative overflow-clip'
|
||||
"transition-all h-15 mb-2 p-1 rounded-md font-medium text-theme-700 dark:text-theme-200 dark:hover:text-theme-300 shadow-md shadow-theme-900/10 dark:shadow-theme-900/20 bg-theme-100/20 hover:bg-theme-300/20 dark:bg-white/5 dark:hover:bg-white/10 relative overflow-clip service-card"
|
||||
)}
|
||||
>
|
||||
<div className="flex select-none z-0">
|
||||
<div className="flex select-none z-0 service-title">
|
||||
{service.icon &&
|
||||
(hasLink ? (
|
||||
<a
|
||||
href={service.href}
|
||||
target={service.target ?? settings.target ?? "_blank"}
|
||||
rel="noreferrer"
|
||||
className="flex-shrink-0 flex items-center justify-center w-12 "
|
||||
className="flex-shrink-0 flex items-center justify-center w-12 service-icon"
|
||||
>
|
||||
<ResolvedIcon icon={service.icon} />
|
||||
</a>
|
||||
) : (
|
||||
<div className="flex-shrink-0 flex items-center justify-center w-12 ">
|
||||
<div className="flex-shrink-0 flex items-center justify-center w-12 service-icon">
|
||||
<ResolvedIcon icon={service.icon} />
|
||||
</div>
|
||||
))}
|
||||
|
@ -60,25 +62,25 @@ export default function Item({ service, group }) {
|
|||
href={service.href}
|
||||
target={service.target ?? settings.target ?? "_blank"}
|
||||
rel="noreferrer"
|
||||
className="flex-1 flex items-center justify-between rounded-r-md "
|
||||
className="flex-1 flex items-center justify-between rounded-r-md service-title-text"
|
||||
>
|
||||
<div className="flex-1 px-2 py-2 text-sm text-left z-10">
|
||||
<div className="flex-1 px-2 py-2 text-sm text-left z-10 service-name">
|
||||
{service.name}
|
||||
<p className="text-theme-500 dark:text-theme-300 text-xs font-light">{service.description}</p>
|
||||
<p className="text-theme-500 dark:text-theme-300 text-xs font-light service-description">{service.description}</p>
|
||||
</div>
|
||||
</a>
|
||||
) : (
|
||||
<div className="flex-1 flex items-center justify-between rounded-r-md ">
|
||||
<div className="flex-1 px-2 py-2 text-sm text-left z-10">
|
||||
<div className="flex-1 flex items-center justify-between rounded-r-md service-title-text">
|
||||
<div className="flex-1 px-2 py-2 text-sm text-left z-10 service-name">
|
||||
{service.name}
|
||||
<p className="text-theme-500 dark:text-theme-300 text-xs font-light">{service.description}</p>
|
||||
<p className="text-theme-500 dark:text-theme-300 text-xs font-light service-description">{service.description}</p>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="absolute top-0 right-0 w-1/2 flex flex-row justify-end gap-2 mr-2 z-30 pointer-events-none">
|
||||
<div className="absolute top-0 right-0 flex flex-row justify-end gap-2 mr-2 z-30 pointer-events-none service-tags">
|
||||
{service.ping && (
|
||||
<div className="flex-shrink-0 flex items-center justify-center cursor-pointer">
|
||||
<div className="flex-shrink-0 flex items-center justify-center service-tag service-ping">
|
||||
<Ping group={group} service={service.name} />
|
||||
<span className="sr-only">Ping status</span>
|
||||
</div>
|
||||
|
@ -88,7 +90,7 @@ export default function Item({ service, group }) {
|
|||
<button
|
||||
type="button"
|
||||
onClick={() => (statsOpen ? closeStats() : setStatsOpen(true))}
|
||||
className="flex-shrink-0 flex items-center justify-center cursor-pointer"
|
||||
className="flex-shrink-0 flex items-center justify-center cursor-pointer service-tag service-container-stats"
|
||||
>
|
||||
<Status service={service} />
|
||||
<span className="sr-only">View container stats</span>
|
||||
|
@ -98,7 +100,7 @@ export default function Item({ service, group }) {
|
|||
<button
|
||||
type="button"
|
||||
onClick={() => (statsOpen ? closeStats() : setStatsOpen(true))}
|
||||
className="flex-shrink-0 flex items-center justify-center cursor-pointer"
|
||||
className="flex-shrink-0 flex items-center justify-center cursor-pointer service-tag service-app"
|
||||
>
|
||||
<KubernetesStatus service={service} />
|
||||
<span className="sr-only">View container stats</span>
|
||||
|
@ -111,7 +113,7 @@ export default function Item({ service, group }) {
|
|||
<div
|
||||
className={classNames(
|
||||
showStats || (statsOpen && !statsClosing) ? "max-h-[110px] opacity-100" : " max-h-[0] opacity-0",
|
||||
"w-full overflow-hidden transition-all duration-300 ease-in-out"
|
||||
"w-full overflow-hidden transition-all duration-300 ease-in-out service-stats"
|
||||
)}
|
||||
>
|
||||
{(showStats || statsOpen) && <Docker service={{ widget: { container: service.container, server: service.server } }} />}
|
||||
|
@ -121,7 +123,7 @@ export default function Item({ service, group }) {
|
|||
<div
|
||||
className={classNames(
|
||||
showStats || (statsOpen && !statsClosing) ? "max-h-[55px] opacity-100" : " max-h-[0] opacity-0",
|
||||
"w-full overflow-hidden transition-all duration-300 ease-in-out"
|
||||
"w-full overflow-hidden transition-all duration-300 ease-in-out service-stats"
|
||||
)}
|
||||
>
|
||||
{(showStats || statsOpen) && <Kubernetes service={{ widget: { namespace: service.namespace, app: service.app, podSelector: service.podSelector } }} />}
|
||||
|
|
|
@ -6,14 +6,14 @@ export default function KubernetesStatus({ service }) {
|
|||
const { data, error } = useSWR(`/api/kubernetes/status/${service.namespace}/${service.app}?${podSelectorString}`);
|
||||
|
||||
if (error) {
|
||||
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden" title={t("docker.error")}>
|
||||
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden k8s-status-error" title={t("docker.error")}>
|
||||
<div className="text-[8px] font-bold text-rose-500/80 uppercase">{t("docker.error")}</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
if (data && data.status === "running") {
|
||||
return (
|
||||
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden" title={data.health ?? data.status}>
|
||||
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden k8s-status" title={data.health ?? data.status}>
|
||||
<div className="text-[8px] font-bold text-emerald-500/80 uppercase">{data.health ?? data.status}</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -21,14 +21,14 @@ export default function KubernetesStatus({ service }) {
|
|||
|
||||
if (data && (data.status === "not found" || data.status === "down" || data.status === "partial")) {
|
||||
return (
|
||||
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden" title={data.status}>
|
||||
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden k8s-status-warning" title={data.status}>
|
||||
<div className="text-[8px] font-bold text-orange-400/50 dark:text-orange-400/80 uppercase">{data.status}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden">
|
||||
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden k8s-status-unknown">
|
||||
<div className="text-[8px] font-bold text-black/20 dark:text-white/40 uppercase">{t("docker.unknown")}</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -9,7 +9,7 @@ export default function List({ group, services, layout }) {
|
|||
<ul
|
||||
className={classNames(
|
||||
layout?.style === "row" ? `grid ${columnMap[layout?.columns]} gap-x-2` : "flex flex-col",
|
||||
"mt-3"
|
||||
"mt-3 services-list"
|
||||
)}
|
||||
>
|
||||
{services.map((service) => (
|
||||
|
|
|
@ -9,7 +9,7 @@ export default function Ping({ group, service }) {
|
|||
|
||||
if (error) {
|
||||
return (
|
||||
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden">
|
||||
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden ping-error">
|
||||
<div className="text-[8px] font-bold text-rose-500 uppercase">{t("ping.error")}</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -17,7 +17,7 @@ export default function Ping({ group, service }) {
|
|||
|
||||
if (!data) {
|
||||
return (
|
||||
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden">
|
||||
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden ping-ping">
|
||||
<div className="text-[8px] font-bold text-black/20 dark:text-white/40 uppercase">{t("ping.ping")}</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -27,14 +27,14 @@ export default function Ping({ group, service }) {
|
|||
|
||||
if (data.status > 403) {
|
||||
return (
|
||||
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden" title={statusText}>
|
||||
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden ping-status-invalid" title={statusText}>
|
||||
<div className="text-[8px] font-bold text-rose-500/80">{data.status}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden" title={statusText}>
|
||||
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden ping-status-valid" title={statusText}>
|
||||
<div className="text-[8px] font-bold text-emerald-500/80">{t("common.ms", { value: data.latency, style: "unit", unit: "millisecond", maximumFractionDigits: 0 })}</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -7,7 +7,7 @@ export default function Status({ service }) {
|
|||
const { data, error } = useSWR(`/api/docker/status/${service.container}/${service.server || ""}`);
|
||||
|
||||
if (error) {
|
||||
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden" title={t("docker.error")}>
|
||||
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden docker-error" title={t("docker.error")}>
|
||||
<div className="text-[8px] font-bold text-rose-500/80 uppercase">{t("docker.error")}</div>
|
||||
</div>
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ export default function Status({ service }) {
|
|||
if (data.status?.includes("running")) {
|
||||
if (data.health === "starting") {
|
||||
return (
|
||||
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden" title={t("docker.starting")}>
|
||||
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden docker-starting" title={t("docker.starting")}>
|
||||
<div className="text-[8px] font-bold text-blue-500/80 uppercase">{t("docker.starting")}</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -26,7 +26,7 @@ export default function Status({ service }) {
|
|||
|
||||
if (data.health === "unhealthy") {
|
||||
return (
|
||||
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden" title={t("docker.unhealthy")}>
|
||||
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden docker-unhealthy" title={t("docker.unhealthy")}>
|
||||
<div className="text-[8px] font-bold text-orange-400/50 dark:text-orange-400/80 uppercase">{t("docker.unhealthy")}</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -39,7 +39,7 @@ export default function Status({ service }) {
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden" title={statusLabel}>
|
||||
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden docker-status" title={statusLabel}>
|
||||
<div className="text-[8px] font-bold text-emerald-500/80 uppercase">{statusLabel}</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -50,7 +50,7 @@ export default function Status({ service }) {
|
|||
else if (data.status === "exited") statusLabel = t("docker.exited")
|
||||
else statusLabel = data.status.replace("partial", t("docker.partial"))
|
||||
return (
|
||||
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden" title={statusLabel}>
|
||||
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden docker-status-warning" title={statusLabel}>
|
||||
<div className="text-[8px] font-bold text-orange-400/50 dark:text-orange-400/80 uppercase">{statusLabel}</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -58,7 +58,7 @@ export default function Status({ service }) {
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden">
|
||||
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden docker-status-unknown">
|
||||
<div className="text-[8px] font-bold text-black/20 dark:text-white/40 uppercase">{t("docker.unknown")}</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -17,7 +17,7 @@ export default function Widget({ service }) {
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="bg-theme-200/50 dark:bg-theme-900/20 rounded m-1 flex-1 flex flex-col items-center justify-center p-1">
|
||||
<div className="bg-theme-200/50 dark:bg-theme-900/20 rounded m-1 flex-1 flex flex-col items-center justify-center p-1 service-missing">
|
||||
<div className="font-thin text-sm">{t("widget.missing_type", { type: service.widget.type })}</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -8,7 +8,8 @@ export default function Block({ value, label }) {
|
|||
<div
|
||||
className={classNames(
|
||||
"bg-theme-200/50 dark:bg-theme-900/20 rounded m-1 flex-1 flex flex-col items-center justify-center text-center p-1",
|
||||
value === undefined ? "animate-pulse" : ""
|
||||
value === undefined ? "animate-pulse" : "",
|
||||
"service-block"
|
||||
)}
|
||||
>
|
||||
<div className="font-thin text-sm">{value === undefined || value === null ? "-" : value}</div>
|
||||
|
|
|
@ -36,5 +36,5 @@ export default function Container({ error = false, children, service }) {
|
|||
}));
|
||||
}
|
||||
|
||||
return <div className="relative flex flex-row w-full">{visibleChildren}</div>;
|
||||
return <div className="relative flex flex-row w-full service-container">{visibleChildren}</div>;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue