feat(SPA): schema list and the sidebar Content group

This commit is contained in:
Florian Sylvain committed 2026-10-19 19:34:45 +02:00
1 parent 73a75d5cb9
commit 3c67cd2314
34 files changed
+2181 -18

No files matched your search

+34
View File
@@ -0,0 +1,34 @@
import type { ContentType } from '@/composables/useContentTypes'
export const COLLAPSED_LIMIT = 5
export function visibleContentTypes(
types: ContentType[],
selectedKey: string | undefined,
expanded: boolean,
) {
if (expanded || types.length <= COLLAPSED_LIMIT) {
return types
}
const firstTypes = types.slice(0, COLLAPSED_LIMIT)
const selected = types.find((type) => type.key === selectedKey)
return selected && !firstTypes.includes(selected) ? [...firstTypes, selected] : firstTypes
}
const CONTENT_PREFIX = '/content/'
export function selectedContentKey(path: string) {
if (!path.startsWith(CONTENT_PREFIX)) {
return undefined
}
const segment = path.slice(CONTENT_PREFIX.length).split('/')[0] ?? ''
try {
return decodeURIComponent(segment)
} catch {
return segment
}
}
export function contentLink(key: string) {
return `${CONTENT_PREFIX}${encodeURIComponent(key)}`
}
+14
View File
@@ -0,0 +1,14 @@
import lucide from 'virtual:lucide-subset'
export const DEFAULT_CONTENT_ICON = 'i-lucide-files'
function owns(record: object | undefined, key: string) {
return record !== undefined && Object.prototype.hasOwnProperty.call(record, key)
}
export function contentTypeIcon(icon: string | null | undefined) {
if (!icon || !(owns(lucide.icons, icon) || owns(lucide.aliases, icon))) {
return DEFAULT_CONTENT_ICON
}
return `i-lucide-${icon}`
}
+46
View File
@@ -0,0 +1,46 @@
import { t, formatNumber } from '@/i18n'
import type { BuiltinType, ContentType } from '@/composables/useContentTypes'
import { formatAbsoluteDateFromIso } from '@/lib/relativeDate'
export const EM_DASH = '—'
export interface SchemaRow {
id: string
name: string
key: string
fieldCount: number
updated: string
builtin: boolean
}
export function customRow(type: ContentType): SchemaRow {
return {
id: `custom-${type.id}`,
name: type.name,
key: type.key,
fieldCount: type.fields.length,
updated: formatAbsoluteDateFromIso(type.updated_at),
builtin: false,
}
}
export function builtinRow(type: BuiltinType): SchemaRow {
return {
id: `builtin-${type.key}`,
name: type.name,
key: type.key,
fieldCount: type.fields.length,
updated: EM_DASH,
builtin: true,
}
}
export function fieldCountLabel(count: number) {
return count === 1 ? t('1 field') : t('{0} fields', [formatNumber(count)])
}
export function schemaSummary(custom: number, builtin: number) {
const customLabel =
custom === 1 ? t('1 content type') : t('{0} content types', [formatNumber(custom)])
return t('{0} · {1} built-in', [customLabel, formatNumber(builtin)])
}