feat: relation field and picker
This commit is contained in:
1 parent
b45c99be3b
commit
37a77c9c22
92 files changed
+6826
-80
No files matched your search
@@ -3,19 +3,30 @@ import type { BuiltinField } from '@/lib/contentTypes'
|
||||
import { fieldTypeSpec, type FieldCellKind } from '@/lib/fieldTypes'
|
||||
import { formatDayValue } from '@/lib/entryValue'
|
||||
import { isMissingImage, type MediaSummary } from '@/lib/mediaField'
|
||||
import { isMissingRelation, relationIdsOf, type RelationSummary } from '@/lib/relationField'
|
||||
import { formatAbsoluteDateFromIso } from '@/lib/relativeDate'
|
||||
|
||||
export { formatDayValue }
|
||||
|
||||
export type CellKind = 'empty' | FieldCellKind
|
||||
|
||||
export interface RelationChip {
|
||||
id: number
|
||||
label: string
|
||||
missing: boolean
|
||||
}
|
||||
|
||||
export interface CellView {
|
||||
kind: CellKind
|
||||
text: string
|
||||
yes?: boolean
|
||||
image?: MediaSummary
|
||||
chips?: RelationChip[]
|
||||
more?: number
|
||||
}
|
||||
|
||||
export const RELATION_CHIPS_SHOWN = 2
|
||||
|
||||
export const EMPTY_TEXT = '–'
|
||||
|
||||
const EMPTY: CellView = { kind: 'empty', text: '' }
|
||||
@@ -48,7 +59,57 @@ function thumbnailCell(value: unknown, image: MediaSummary | undefined): CellVie
|
||||
}
|
||||
}
|
||||
|
||||
export function describeCell(field: BuiltinField, value: unknown, image?: MediaSummary): CellView {
|
||||
function summaryField(first: { key: string; type: string }): BuiltinField {
|
||||
return {
|
||||
key: first.key,
|
||||
label: '',
|
||||
type: first.type,
|
||||
required: false,
|
||||
unique: false,
|
||||
default: null,
|
||||
min: null,
|
||||
max: null,
|
||||
options: null,
|
||||
}
|
||||
}
|
||||
|
||||
export function relationLabel(summary: RelationSummary) {
|
||||
if (isMissingRelation(summary)) {
|
||||
return t('Entry no longer exists')
|
||||
}
|
||||
const first = summary.first_field
|
||||
const cell = describeCell(summaryField(first), first.value)
|
||||
return cell.kind === 'empty' || cell.kind === 'thumbnail' || cell.kind === 'relation'
|
||||
? t('Entry {0}', [summary.id])
|
||||
: plainCellText(cell)
|
||||
}
|
||||
|
||||
function relationCell(value: unknown, summaries: RelationSummary[]): CellView {
|
||||
const ids = relationIdsOf(value)
|
||||
if (ids.length === 0) {
|
||||
return EMPTY
|
||||
}
|
||||
const chips = ids.map((id): RelationChip => {
|
||||
const summary = summaries.find((candidate) => candidate.id === id) ?? {
|
||||
id,
|
||||
missing: true as const,
|
||||
}
|
||||
return { id, label: relationLabel(summary), missing: isMissingRelation(summary) }
|
||||
})
|
||||
return {
|
||||
kind: 'relation',
|
||||
text: chips.map((chip) => chip.label).join(', '),
|
||||
chips: chips.slice(0, RELATION_CHIPS_SHOWN),
|
||||
more: Math.max(0, chips.length - RELATION_CHIPS_SHOWN),
|
||||
}
|
||||
}
|
||||
|
||||
export function describeCell(
|
||||
field: BuiltinField,
|
||||
value: unknown,
|
||||
image?: MediaSummary,
|
||||
relations: RelationSummary[] = [],
|
||||
): CellView {
|
||||
if (value === undefined || value === null || value === '') {
|
||||
return EMPTY
|
||||
}
|
||||
@@ -56,6 +117,8 @@ export function describeCell(field: BuiltinField, value: unknown, image?: MediaS
|
||||
switch (kind) {
|
||||
case 'thumbnail':
|
||||
return thumbnailCell(value, image)
|
||||
case 'relation':
|
||||
return relationCell(value, relations)
|
||||
case 'boolean':
|
||||
return { kind, text: '', yes: value === true }
|
||||
case 'number':
|
||||
|
||||
Reference in new issue
Block a user