Files
summercms/admin/src/state/useSettings.ts
Jakub Zych 0b09acdb0c feat(admin): open controller-link settings entries from the settings index
A settings entry with a controller opens that controller's route from
its card (settingsPath); singleton cards still open /settings/<code>.
On a linked controller with no navigation entry of its own the rail
marks Settings current, the breadcrumbs read Settings > entry label
(plus the record title on record and create routes) and the page title
uses the entry label. The settings docs describe the admin behaviour;
the embedded admin shell is rebuilt.
2026-10-07 18:24:54 +02:00

70 lines
2.4 KiB
TypeScript

// Settings pages the admin may manage (D-21), server-filtered like the
// navigation. The rail shows "Ustawienia" only when this list is non-empty.
// An entry is either a singleton settings form (/settings/<code>) or a link
// that opens an admin controller (its `controller` is set).
import { computed, readonly, ref } from 'vue'
import { api } from '../api/client'
import { controllerPath } from '../app/controllerRoutes'
import type { SettingsEntry } from '../api/types'
const entries = ref<SettingsEntry[]>([])
export const settings = readonly(entries)
export const hasSettings = computed(() => entries.value.length > 0)
export async function loadSettings(): Promise<SettingsEntry[]> {
const { data, response } = await api.GET('/settings')
entries.value = response.ok && data ? data.data : []
return entries.value
}
export function setSettings(next: SettingsEntry[]): void {
entries.value = next
}
export function settingsEntry(code: string): SettingsEntry | null {
return entries.value.find((entry) => entry.code === code) ?? null
}
/**
* Route a settings entry opens: its controller for a link entry (the index
* when the ID is malformed), otherwise its singleton form.
*/
export function settingsPath(entry: SettingsEntry): string {
if (entry.controller) {
return controllerPath(entry.controller) ?? '/settings'
}
return `/settings/${encodeURIComponent(entry.code)}`
}
/** The link entry that opens the given controller, if any. */
export function settingsLinkFor(controllerId: string | null): SettingsEntry | null {
if (!controllerId) {
return null
}
return entries.value.find((entry) => entry.controller !== '' && entry.controller === controllerId) ?? null
}
/** Entries grouped by category, categories in first-seen order, by order. */
export const settingsGroups = computed(() => {
const sorted = entries.value
.map((entry, index) => ({ entry, index }))
.sort((a, b) => a.entry.order - b.entry.order || a.index - b.index)
.map(({ entry }) => entry)
const groups: Array<{ category: string; entries: SettingsEntry[] }> = []
for (const entry of sorted) {
let group = groups.find((item) => item.category === entry.category)
if (!group) {
group = { category: entry.category, entries: [] }
groups.push(group)
}
group.entries.push(entry)
}
return groups
})
export function useSettings() {
return { settings, hasSettings, settingsGroups, loadSettings, settingsEntry, settingsPath, settingsLinkFor }
}