mirror of
https://github.com/Crosstalk-Solutions/project-nomad.git
synced 2026-10-18 21:55:58 +02:00
A link tile rendered on a flat surface colour, which read as a stark white card against the filled green app tiles. Tiles now take one of six colours from the brand palette, chosen when creating or editing one, and the card is tinted from it. Tiles stay visually distinct from managed apps regardless of colour: the dashed border and the external-link marker carry that, not the hue, and the tint is deliberately light so the distinction survives every option. Class names are written out in full rather than interpolated, because Tailwind scans source text for literal class strings and would silently drop a computed one, leaving the tile untinted. A test asserts that. Added as a separate migration from the one introducing is_link_tile, since that has already run on the test box and editing it in place would leave fresh and upgraded installs with different schemas. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01F8Mgg1vd2eKSs8StZiuyMV
160 lines
4.2 KiB
TypeScript
160 lines
4.2 KiB
TypeScript
import { BaseModel, belongsTo, column, hasMany, SnakeCaseNamingStrategy } from '@adonisjs/lucid/orm'
|
|
import type { BelongsTo, HasMany } from '@adonisjs/lucid/types/relations'
|
|
import { DateTime } from 'luxon'
|
|
|
|
export default class Service extends BaseModel {
|
|
static namingStrategy = new SnakeCaseNamingStrategy()
|
|
|
|
@column({ isPrimary: true })
|
|
declare id: number
|
|
|
|
@column()
|
|
declare service_name: string
|
|
|
|
@column()
|
|
declare container_image: string
|
|
|
|
@column()
|
|
declare container_command: string | null
|
|
|
|
@column()
|
|
declare container_config: string | null
|
|
|
|
@column()
|
|
declare friendly_name: string | null
|
|
|
|
@column()
|
|
declare description: string | null
|
|
|
|
@column()
|
|
declare powered_by: string | null
|
|
|
|
@column()
|
|
declare display_order: number | null
|
|
|
|
@column()
|
|
declare icon: string | null // must be a TablerIcons name to be properly rendered in the UI (e.g. "IconBrandDocker")
|
|
|
|
@column({
|
|
serialize(value) {
|
|
return Boolean(value)
|
|
},
|
|
})
|
|
declare installed: boolean
|
|
|
|
@column()
|
|
declare installation_status: 'idle' | 'installing' | 'error'
|
|
|
|
@column()
|
|
declare depends_on: string | null
|
|
|
|
// For services that are dependencies for other services - not intended to be installed directly by users
|
|
@column({
|
|
serialize(value) {
|
|
return Boolean(value)
|
|
},
|
|
})
|
|
declare is_dependency_service: boolean
|
|
|
|
@column()
|
|
declare ui_location: string | null
|
|
|
|
// User-set override for the launch ("Open") link (e.g. a reverse-proxy/local-DNS host like
|
|
// https://jellyfin.myhomelab.net). When null, the default host + port link derived from
|
|
// ui_location is used. Only affects user-facing links — never internal service-to-service URLs.
|
|
@column()
|
|
declare custom_url: string | null
|
|
|
|
@column()
|
|
declare metadata: string | null
|
|
|
|
@column({
|
|
serialize(value) {
|
|
return Boolean(value)
|
|
},
|
|
})
|
|
declare is_custom: boolean
|
|
|
|
@column({
|
|
serialize(value) {
|
|
return Boolean(value)
|
|
},
|
|
})
|
|
declare is_user_modified: boolean
|
|
|
|
// True when this row is only a dashboard shortcut: a name, icon and URL with no
|
|
// container behind it. Distinct from is_custom, which is still a real container
|
|
// NOMAD installs and manages. A link tile has no lifecycle, so no Start/Stop/
|
|
// Update/Uninstall may be offered for one.
|
|
@column({
|
|
serialize(value) {
|
|
return Boolean(value)
|
|
},
|
|
})
|
|
declare is_link_tile: boolean
|
|
|
|
@column()
|
|
declare link_color: string | null
|
|
|
|
@column()
|
|
declare category: string | null
|
|
|
|
// When true the service is sunset: hidden from the install catalog unless it is already
|
|
// installed (see SystemService.getServices). Lets a deprecated app stay manageable for users who
|
|
// still run it while keeping new users from installing it.
|
|
@column({
|
|
serialize(value) {
|
|
return Boolean(value)
|
|
},
|
|
})
|
|
declare is_deprecated: boolean
|
|
|
|
@column()
|
|
declare source_repo: string | null
|
|
|
|
@column()
|
|
declare available_update_version: string | null
|
|
|
|
@column.dateTime()
|
|
declare update_checked_at: DateTime | null
|
|
|
|
// Per-app opt-in for automatic updates. An app auto-updates only when both this
|
|
// and the global `appAutoUpdate.enabled` master switch are on.
|
|
@column({
|
|
serialize(value) {
|
|
return Boolean(value)
|
|
},
|
|
})
|
|
declare auto_update_enabled: boolean
|
|
|
|
// When the current `available_update_version` was first detected — the anchor for
|
|
// the auto-update cool-off (registry tags carry no publish timestamp).
|
|
@column.dateTime()
|
|
declare available_update_first_seen_at: DateTime | null
|
|
|
|
// Per-app auto-update failure backoff; at the threshold the app self-disables via
|
|
// `auto_update_disabled_reason` without affecting other apps.
|
|
@column()
|
|
declare auto_update_consecutive_failures: number
|
|
|
|
@column()
|
|
declare auto_update_disabled_reason: string | null
|
|
|
|
@column.dateTime({ autoCreate: true })
|
|
declare created_at: DateTime
|
|
|
|
@column.dateTime({ autoCreate: true, autoUpdate: true })
|
|
declare updated_at: DateTime | null
|
|
|
|
// Define a self-referential relationship for dependencies
|
|
@belongsTo(() => Service, {
|
|
foreignKey: 'depends_on',
|
|
})
|
|
declare dependency: BelongsTo<typeof Service>
|
|
|
|
@hasMany(() => Service, {
|
|
foreignKey: 'depends_on',
|
|
})
|
|
declare dependencies: HasMany<typeof Service>
|
|
}
|