Update GeoIntel project files
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
import { ArrowUpRight, Box, Globe2 } from "lucide-react";
|
||||
import type { DockApp, Favorite } from "../../shared/contracts";
|
||||
import { effectiveAppUrl, favoriteIconUrl } from "../../shared/domain";
|
||||
import { ServiceIcon } from "./ServiceIcon";
|
||||
|
||||
const serviceDescriptions: Array<[RegExp, string]> = [
|
||||
[/plex/i, "Media server & streaming"],
|
||||
[/jellyfin/i, "De vrije software mediaserver"],
|
||||
[/sonarr/i, "PVR voor tv-series"],
|
||||
[/radarr/i, "PVR voor films"],
|
||||
[/home.?assistant|ha-core/i, "Centrale automatisering"],
|
||||
[/adguard|pihole|pi-hole/i, "Netwerkbeveiliging & filter"],
|
||||
[/nextcloud/i, "Bestandshosting"],
|
||||
[/gitea|github|gitlab/i, "Code en samenwerking"],
|
||||
[/immich/i, "Foto's en herinneringen"],
|
||||
[/paperless/i, "Documenten en archief"],
|
||||
];
|
||||
|
||||
function describeService(app: DockApp, categoryName: string) {
|
||||
const haystack = `${app.displayName} ${app.technicalName}`;
|
||||
return (
|
||||
serviceDescriptions.find(([pattern]) => pattern.test(haystack))?.[1] ??
|
||||
`${categoryName} service`
|
||||
);
|
||||
}
|
||||
|
||||
function statusLabel(status: DockApp["status"]) {
|
||||
return status === "online"
|
||||
? "Online"
|
||||
: status === "offline"
|
||||
? "Offline"
|
||||
: "Status onbekend";
|
||||
}
|
||||
|
||||
export function AppTile({
|
||||
app,
|
||||
externalAccess,
|
||||
showStatus,
|
||||
index,
|
||||
categoryName,
|
||||
variant = "standard",
|
||||
}: {
|
||||
app: DockApp;
|
||||
externalAccess: boolean;
|
||||
showStatus: boolean;
|
||||
index: number;
|
||||
categoryName: string;
|
||||
variant?: "standard" | "feature";
|
||||
}) {
|
||||
const url = effectiveAppUrl(app, externalAccess);
|
||||
const content = (
|
||||
<>
|
||||
<ServiceIcon
|
||||
name={app.displayName}
|
||||
icon={app.icon}
|
||||
hint={`${app.technicalName} ${app.image ?? ""}`}
|
||||
index={index}
|
||||
/>
|
||||
<span className="tile-copy">
|
||||
<strong>{app.displayName}</strong>
|
||||
<small>{describeService(app, categoryName)}</small>
|
||||
</span>
|
||||
{showStatus && (
|
||||
<span className={`tile-status ${app.status}`}>
|
||||
<span /> {statusLabel(app.status)}
|
||||
</span>
|
||||
)}
|
||||
<ArrowUpRight className="tile-arrow" size={17} aria-hidden="true" />
|
||||
</>
|
||||
);
|
||||
return url ? (
|
||||
<a
|
||||
className={`app-tile ${variant}`}
|
||||
href={url}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
data-testid="app-tile"
|
||||
>
|
||||
{content}
|
||||
</a>
|
||||
) : (
|
||||
<div
|
||||
className={`app-tile ${variant} disabled`}
|
||||
aria-label={`${app.displayName} heeft geen URL`}
|
||||
>
|
||||
{content}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function FavoriteTile({
|
||||
favorite,
|
||||
index,
|
||||
}: {
|
||||
favorite: Favorite;
|
||||
index: number;
|
||||
}) {
|
||||
return (
|
||||
<a
|
||||
className="app-tile"
|
||||
href={favorite.url}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
data-testid="favorite-tile"
|
||||
>
|
||||
<ServiceIcon
|
||||
name={favorite.name}
|
||||
icon={favoriteIconUrl(favorite)}
|
||||
index={index + 2}
|
||||
/>
|
||||
<span className="tile-copy">
|
||||
<strong>{favorite.name}</strong>
|
||||
<small>Favoriet</small>
|
||||
</span>
|
||||
<Globe2 className="status-icon" size={15} aria-hidden="true" />
|
||||
<ArrowUpRight className="tile-arrow" size={17} aria-hidden="true" />
|
||||
</a>
|
||||
);
|
||||
}
|
||||
|
||||
export function EmptyIcon() {
|
||||
return (
|
||||
<div className="empty-icon" aria-hidden="true">
|
||||
<Box size={28} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user