mirror of
https://github.com/Dvorinka/Dash.git
synced 2026-10-28 07:41:27 +00:00
feat: phase 2 widgets — registry, fetchers, clock, config dialog
Backend: internal/widget registry (type metadata + Fetcher), Pi-hole v5 / AdGuard / Immich fetchers, /api/widgets/types + /api/widgets/:id/data with 30s TTL cache (failures cached too), kind+config on item create/patch. Config secrets are never logged or echoed in errors. Frontend: WidgetContent host maps config.type to a component, polls /data every 30s for server-backed types; clock renders client-side. Generic WidgetDialog builds its form from the registry's field list. Widget tiles are sortable items in both renderers. Generated with [Devin](https://devin.ai) Authored By: TDvorak <[email protected]> Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
1 parent
6004105038
commit
8afc7df53b
21 files changed
+1072
-40
No files matched your search
@@ -214,6 +214,44 @@ paths:
|
||||
"404":
|
||||
$ref: "#/components/responses/NotFound"
|
||||
|
||||
/api/widgets/types:
|
||||
get:
|
||||
operationId: widgetTypes
|
||||
summary: Widget registry metadata — drives the add-widget dialog
|
||||
responses:
|
||||
"200":
|
||||
description: Registered widget types
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/WidgetType"
|
||||
|
||||
/api/widgets/{id}/data:
|
||||
get:
|
||||
operationId: widgetData
|
||||
summary: Live data for one widget item (~30s server-side cache)
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/id"
|
||||
responses:
|
||||
"200":
|
||||
description: Widget payload; shape depends on config.type
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/WidgetData"
|
||||
"400":
|
||||
$ref: "#/components/responses/BadRequest"
|
||||
"404":
|
||||
$ref: "#/components/responses/NotFound"
|
||||
"502":
|
||||
description: Upstream service unreachable
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
|
||||
/api/status:
|
||||
get:
|
||||
operationId: getStatus
|
||||
@@ -386,10 +424,19 @@ components:
|
||||
properties:
|
||||
sectionId:
|
||||
type: string
|
||||
kind:
|
||||
type: string
|
||||
enum: [service, widget]
|
||||
default: service
|
||||
name:
|
||||
type: string
|
||||
icon:
|
||||
type: string
|
||||
config:
|
||||
type: object
|
||||
nullable: true
|
||||
additionalProperties: true
|
||||
description: Widget config — keys defined by the widget type's fields
|
||||
urls:
|
||||
type: array
|
||||
items:
|
||||
@@ -401,6 +448,10 @@ components:
|
||||
type: string
|
||||
icon:
|
||||
type: string
|
||||
config:
|
||||
type: object
|
||||
nullable: true
|
||||
additionalProperties: true
|
||||
urls:
|
||||
type: array
|
||||
description: Full replacement of the item's URL list
|
||||
@@ -467,6 +518,48 @@ components:
|
||||
checkedAt:
|
||||
type: string
|
||||
format: date-time
|
||||
WidgetField:
|
||||
type: object
|
||||
required: [key, label]
|
||||
properties:
|
||||
key:
|
||||
type: string
|
||||
label:
|
||||
type: string
|
||||
secret:
|
||||
type: boolean
|
||||
description: Render as password input; never logged
|
||||
placeholder:
|
||||
type: string
|
||||
required:
|
||||
type: boolean
|
||||
WidgetType:
|
||||
type: object
|
||||
required: [type, name, fields]
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
description:
|
||||
type: string
|
||||
local:
|
||||
type: boolean
|
||||
description: Client-rendered (e.g. clock); no /data fetch needed
|
||||
fields:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/WidgetField"
|
||||
WidgetData:
|
||||
type: object
|
||||
required: [data]
|
||||
properties:
|
||||
data:
|
||||
type: object
|
||||
additionalProperties: true
|
||||
fetchedAt:
|
||||
type: string
|
||||
format: date-time
|
||||
Export:
|
||||
type: object
|
||||
required: [version, sections]
|
||||
|
||||
Reference in new issue
Block a user