A settings link to a singleton controller only worked on a plain left click; a new tab landed on the list route, which answers 404, and every non-singleton link paid an extra /singleton request. The settings index now links like any controller link, and the list view opens the controller's one record when its list answers 404 and the singleton route answers an id.
58 lines
2.3 KiB
Vue
58 lines
2.3 KiB
Vue
<script setup lang="ts">
|
|
import { RouterLink } from 'vue-router'
|
|
import { t } from '../app/i18n'
|
|
import { iconFor } from '../app/icons'
|
|
import { settingsGroups, settingsPath } from '../state/useSettings'
|
|
|
|
// Settings index (D-21): every permitted settings page, grouped by category,
|
|
// with its icon, label and description. The server filters the list. A
|
|
// singleton entry opens its settings form; a link entry opens its controller.
|
|
// A link to a singleton controller (D-11) points at the controller's list
|
|
// route like any other, so a click, a new tab and a bookmark behave the
|
|
// same; the list view opens the controller's one record when the list
|
|
// answers 404 (ListView openSingleton).
|
|
</script>
|
|
|
|
<template>
|
|
<section class="flex flex-col gap-5">
|
|
<header>
|
|
<h1 class="text-[26px] font-bold tracking-[-0.02em]">{{ t('backend::lang.settings.title') }}</h1>
|
|
</header>
|
|
<p v-if="settingsGroups.length === 0" class="text-muted">{{ t('backend::lang.settings.empty') }}</p>
|
|
<section
|
|
v-for="group in settingsGroups"
|
|
:key="group.category"
|
|
data-settings-group
|
|
class="flex flex-col gap-3"
|
|
>
|
|
<h2 v-if="group.category" class="text-[13px] font-semibold tracking-[0.02em] text-muted uppercase">
|
|
{{ group.category }}
|
|
</h2>
|
|
<div class="grid grid-cols-1 gap-3 min-[900px]:grid-cols-2">
|
|
<RouterLink
|
|
v-for="entry in group.entries"
|
|
:key="entry.code"
|
|
v-slot="{ href, navigate }"
|
|
:to="settingsPath(entry)"
|
|
custom
|
|
>
|
|
<a
|
|
:href="href"
|
|
:data-settings="entry.code"
|
|
class="flex items-start gap-3.5 rounded-card border border-border bg-surface p-5 text-text no-underline shadow-card hover:bg-hover"
|
|
@click="navigate"
|
|
>
|
|
<span class="flex size-10 shrink-0 items-center justify-center rounded-inner bg-subtle text-muted">
|
|
<component :is="iconFor(entry.icon)" :size="20" aria-hidden="true" />
|
|
</span>
|
|
<span class="flex min-w-0 flex-col">
|
|
<span class="font-semibold">{{ entry.label }}</span>
|
|
<span v-if="entry.description" class="text-[13px] text-muted">{{ entry.description }}</span>
|
|
</span>
|
|
</a>
|
|
</RouterLink>
|
|
</div>
|
|
</section>
|
|
</section>
|
|
</template>
|