style(services): apply formatter to App and ServicesPage
This commit is contained in:
@@ -454,7 +454,10 @@ function AppInner() {
|
|||||||
<Route path="/observability" element={<ObservabilityPage />} />
|
<Route path="/observability" element={<ObservabilityPage />} />
|
||||||
<Route path="/settings" element={<Settings />} />
|
<Route path="/settings" element={<Settings />} />
|
||||||
<Route path="/services" element={<ServicesPage />} />
|
<Route path="/services" element={<ServicesPage />} />
|
||||||
<Route path="/services/:serviceType/:serviceId" element={<ServicePage />} />
|
<Route
|
||||||
|
path="/services/:serviceType/:serviceId"
|
||||||
|
element={<ServicePage />}
|
||||||
|
/>
|
||||||
</Route>
|
</Route>
|
||||||
</Routes>
|
</Routes>
|
||||||
</BrowserRouter>
|
</BrowserRouter>
|
||||||
@@ -487,7 +490,10 @@ function AppInner() {
|
|||||||
<Route path="/observability" element={<ObservabilityPage />} />
|
<Route path="/observability" element={<ObservabilityPage />} />
|
||||||
<Route path="/settings" element={<Settings />} />
|
<Route path="/settings" element={<Settings />} />
|
||||||
<Route path="/services" element={<ServicesPage />} />
|
<Route path="/services" element={<ServicesPage />} />
|
||||||
<Route path="/services/:serviceType/:serviceId" element={<ServicePage />} />
|
<Route
|
||||||
|
path="/services/:serviceType/:serviceId"
|
||||||
|
element={<ServicePage />}
|
||||||
|
/>
|
||||||
</Route>
|
</Route>
|
||||||
</Routes>
|
</Routes>
|
||||||
</BrowserRouter>
|
</BrowserRouter>
|
||||||
|
|||||||
@@ -57,7 +57,9 @@ function Field({
|
|||||||
<div className="flex flex-col gap-1.5">
|
<div className="flex flex-col gap-1.5">
|
||||||
<Label htmlFor={htmlFor}>{label}</Label>
|
<Label htmlFor={htmlFor}>{label}</Label>
|
||||||
{children}
|
{children}
|
||||||
{helper ? <p className="text-xs text-muted-foreground">{helper}</p> : null}
|
{helper ? (
|
||||||
|
<p className="text-xs text-muted-foreground">{helper}</p>
|
||||||
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -71,13 +73,23 @@ function ServiceConfigFields({
|
|||||||
config: Record<string, unknown>;
|
config: Record<string, unknown>;
|
||||||
onChange: (config: Record<string, unknown>) => void;
|
onChange: (config: Record<string, unknown>) => void;
|
||||||
}) {
|
}) {
|
||||||
const properties = (type.config_schema as { properties?: Record<string, { type?: string; description?: string }> }).properties ?? {};
|
const properties =
|
||||||
|
(
|
||||||
|
type.config_schema as {
|
||||||
|
properties?: Record<string, { type?: string; description?: string }>;
|
||||||
|
}
|
||||||
|
).properties ?? {};
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col gap-3">
|
<div className="flex flex-col gap-3">
|
||||||
{Object.entries(properties).map(([key, schema]) => {
|
{Object.entries(properties).map(([key, schema]) => {
|
||||||
const isNumber = schema.type === "integer" || schema.type === "number";
|
const isNumber = schema.type === "integer" || schema.type === "number";
|
||||||
return (
|
return (
|
||||||
<Field key={key} label={key} htmlFor={`cfg-${key}`} helper={schema.description}>
|
<Field
|
||||||
|
key={key}
|
||||||
|
label={key}
|
||||||
|
htmlFor={`cfg-${key}`}
|
||||||
|
helper={schema.description}
|
||||||
|
>
|
||||||
<Input
|
<Input
|
||||||
id={`cfg-${key}`}
|
id={`cfg-${key}`}
|
||||||
type={isNumber ? "number" : "text"}
|
type={isNumber ? "number" : "text"}
|
||||||
@@ -123,7 +135,9 @@ function ServiceSecretFields({
|
|||||||
id={`secret-${field.key}`}
|
id={`secret-${field.key}`}
|
||||||
type="password"
|
type="password"
|
||||||
value={secrets[field.key] ?? ""}
|
value={secrets[field.key] ?? ""}
|
||||||
onChange={(e) => onChange({ ...secrets, [field.key]: e.target.value })}
|
onChange={(e) =>
|
||||||
|
onChange({ ...secrets, [field.key]: e.target.value })
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</Field>
|
</Field>
|
||||||
))}
|
))}
|
||||||
@@ -193,7 +207,9 @@ function CreateServiceDialog({
|
|||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<p className="text-sm text-muted-foreground">{selectedType?.description}</p>
|
<p className="text-sm text-muted-foreground">
|
||||||
|
{selectedType?.description}
|
||||||
|
</p>
|
||||||
<Field label="Name" htmlFor="service-name">
|
<Field label="Name" htmlFor="service-name">
|
||||||
<Input
|
<Input
|
||||||
id="service-name"
|
id="service-name"
|
||||||
@@ -219,7 +235,9 @@ function CreateServiceDialog({
|
|||||||
<Switch
|
<Switch
|
||||||
id="service-enabled"
|
id="service-enabled"
|
||||||
checked={draft.enabled}
|
checked={draft.enabled}
|
||||||
onCheckedChange={(checked) => setDraft({ ...draft, enabled: checked })}
|
onCheckedChange={(checked) =>
|
||||||
|
setDraft({ ...draft, enabled: checked })
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
<Label htmlFor="service-enabled">Enabled</Label>
|
<Label htmlFor="service-enabled">Enabled</Label>
|
||||||
</div>
|
</div>
|
||||||
@@ -258,7 +276,9 @@ export function ServicesPage() {
|
|||||||
}, [services]);
|
}, [services]);
|
||||||
|
|
||||||
const typeName = (t: string) =>
|
const typeName = (t: string) =>
|
||||||
types.find((x) => x.service_type === t)?.name ?? getServiceBinding(t)?.name ?? t;
|
types.find((x) => x.service_type === t)?.name ??
|
||||||
|
getServiceBinding(t)?.name ??
|
||||||
|
t;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col gap-4">
|
<div className="flex flex-col gap-4">
|
||||||
@@ -275,14 +295,17 @@ export function ServicesPage() {
|
|||||||
{services.length === 0 ? (
|
{services.length === 0 ? (
|
||||||
<Alert>
|
<Alert>
|
||||||
<AlertDescription>
|
<AlertDescription>
|
||||||
No services yet. Add a Grafana, Prometheus, Jellyfin, Nextcloud, or SSH task runner.
|
No services yet. Add a Grafana, Prometheus, Jellyfin, Nextcloud,
|
||||||
|
or SSH task runner.
|
||||||
</AlertDescription>
|
</AlertDescription>
|
||||||
</Alert>
|
</Alert>
|
||||||
) : (
|
) : (
|
||||||
<div className="flex flex-col gap-4">
|
<div className="flex flex-col gap-4">
|
||||||
{grouped.map(([serviceType, instances]) => (
|
{grouped.map(([serviceType, instances]) => (
|
||||||
<div key={serviceType} className="flex flex-col gap-2">
|
<div key={serviceType} className="flex flex-col gap-2">
|
||||||
<div className="text-sm font-medium">{typeName(serviceType)}</div>
|
<div className="text-sm font-medium">
|
||||||
|
{typeName(serviceType)}
|
||||||
|
</div>
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2">
|
||||||
{instances.map((s) => (
|
{instances.map((s) => (
|
||||||
<div
|
<div
|
||||||
@@ -293,7 +316,9 @@ export function ServicesPage() {
|
|||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<span className="font-medium">{s.name}</span>
|
<span className="font-medium">{s.name}</span>
|
||||||
<Badge variant="outline">{s.service_type}</Badge>
|
<Badge variant="outline">{s.service_type}</Badge>
|
||||||
{!s.enabled ? <Badge variant="secondary">disabled</Badge> : null}
|
{!s.enabled ? (
|
||||||
|
<Badge variant="secondary">disabled</Badge>
|
||||||
|
) : null}
|
||||||
{Object.entries(s.secrets_set).some(([, v]) => v) ? (
|
{Object.entries(s.secrets_set).some(([, v]) => v) ? (
|
||||||
<Badge variant="outline">secrets set</Badge>
|
<Badge variant="outline">secrets set</Badge>
|
||||||
) : null}
|
) : null}
|
||||||
@@ -303,7 +328,9 @@ export function ServicesPage() {
|
|||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
size="sm"
|
size="sm"
|
||||||
onClick={() => navigate(`/services/${s.service_type}/${s.id}`)}
|
onClick={() =>
|
||||||
|
navigate(`/services/${s.service_type}/${s.id}`)
|
||||||
|
}
|
||||||
>
|
>
|
||||||
Open <ExternalLink className="ml-1 h-3 w-3" />
|
Open <ExternalLink className="ml-1 h-3 w-3" />
|
||||||
</Button>
|
</Button>
|
||||||
@@ -325,7 +352,10 @@ export function ServicesPage() {
|
|||||||
)}
|
)}
|
||||||
</SectionCard>
|
</SectionCard>
|
||||||
|
|
||||||
<CreateServiceDialog open={createOpen} onClose={() => setCreateOpen(false)} />
|
<CreateServiceDialog
|
||||||
|
open={createOpen}
|
||||||
|
onClose={() => setCreateOpen(false)}
|
||||||
|
/>
|
||||||
<ConfirmDialog
|
<ConfirmDialog
|
||||||
open={Boolean(deleteId)}
|
open={Boolean(deleteId)}
|
||||||
title="Delete service?"
|
title="Delete service?"
|
||||||
|
|||||||
Reference in New Issue
Block a user