feat(10.1-02): render header and form partials through an allowlisted node renderer

- partialNodes rebuilds the server node tree with h() under the server's tag, attribute and URL lists
- PartialHost owns the skeleton, empty and failure states and keeps nodes visible on refetch
- type: partial is a valueless group-labelled field rendered on create and update
- ListView shows headerPartial above the list card and refetches it after bulk delete
- summer-partial and summer-stats style kit in main.css, documented in the cabana README; dist rebuilt
This commit is contained in:
Jakub Zych
2026-09-29 02:10:18 +02:00
parent 107d820109
commit 9df9fae930
20 changed files with 870 additions and 22 deletions

View File

@@ -12,6 +12,7 @@ import DataTable from '../components/list/DataTable.vue'
import FilterBar from '../components/list/FilterBar.vue'
import ListToolbar from '../components/list/ListToolbar.vue'
import Pagination from '../components/list/Pagination.vue'
import PartialHost from '../components/partial/PartialHost.vue'
import Button from '../components/ui/Button.vue'
import ConfirmDialog from '../components/ui/ConfirmDialog.vue'
import { useConfirm } from '../components/ui/confirm'
@@ -46,6 +47,10 @@ const listFailed = ref(false)
const failed = computed(() => schemaFailed.value || listFailed.value)
const selected = ref<RowId[]>([])
const deleting = ref(false)
// Bumped after an action that changes the collection (bulk delete), so the
// header partial refetches. Search, filters, sorting and paging do not: the
// header describes the whole scoped collection, not the filtered page (D-11).
const partialReload = ref(0)
const confirm = useConfirm()
const query = computed(() => parseListQuery(route.query))
@@ -201,6 +206,7 @@ async function onDelete(): Promise<void> {
showToast(message(messages.value?.deleted, result.data.data.deleted))
selected.value = []
await loadList()
partialReload.value += 1
return
}
showToast(result.error?.error.message || t('backend::lang.list.delete_failed'), 'danger')
@@ -232,6 +238,13 @@ async function onDelete(): Promise<void> {
</Button>
</div>
</header>
<PartialHost
v-if="schema?.headerPartial"
variant="header"
:source="path"
:name="schema.headerPartial"
:reload-key="partialReload"
/>
<div class="overflow-hidden rounded-card border border-border bg-surface shadow-card">
<ListToolbar
v-if="schema"