feat(SPA): schema list and the sidebar Content group
This commit is contained in:
1 parent
73a75d5cb9
commit
3c67cd2314
34 files changed
+2181
-18
No files matched your search
@@ -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)}`
|
||||
}
|
||||
@@ -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}`
|
||||
}
|
||||
@@ -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)])
|
||||
}
|
||||
Reference in new issue
Block a user