161 lines
3.5 KiB
TypeScript
161 lines
3.5 KiB
TypeScript
import { FIELD_TYPE_SPECS, FIELD_TYPES, type FieldType } from '@/lib/fieldTypes'
|
|
import { DEFAULT_RELATION_KIND, type RelationKind } from '@/lib/relationField'
|
|
|
|
export { FIELD_TYPES, type FieldType }
|
|
export type KeyMode = 'auto' | 'manual'
|
|
export type KeyDisplayMode = KeyMode | 'empty'
|
|
export type BuilderStatus =
|
|
| 'saving'
|
|
| 'offline'
|
|
| 'failed'
|
|
| 'problems'
|
|
| 'dirty'
|
|
| 'saved'
|
|
| 'none'
|
|
|
|
export const BUILDER_LIMITS = {
|
|
nameMax: 100,
|
|
typeKeyMin: 2,
|
|
typeKeyMax: 40,
|
|
fieldsMax: 50,
|
|
fieldKeyMax: 40,
|
|
choicesMax: 50,
|
|
}
|
|
|
|
export const RESERVED_TYPE_KEYS = ['new']
|
|
export const PREVIEW_KEY_FALLBACK = 'events'
|
|
export const STARTER_LABEL = 'Title'
|
|
export const STARTER_KEY = 'title'
|
|
|
|
export interface BuilderField {
|
|
uid: number
|
|
label: string
|
|
key: string
|
|
keyMode: KeyMode
|
|
type: FieldType
|
|
required: boolean
|
|
unique: boolean
|
|
defaultValue: string
|
|
defaultOn: boolean
|
|
min: string
|
|
max: string
|
|
options: string[]
|
|
relationType: string
|
|
relationKind: RelationKind
|
|
saved: boolean
|
|
}
|
|
|
|
export interface BuilderForm {
|
|
name: string
|
|
key: string
|
|
keyMode: KeyMode
|
|
keyLocked: boolean
|
|
fields: BuilderField[]
|
|
}
|
|
|
|
export function keyDisplayMode(mode: KeyMode, key: string): KeyDisplayMode {
|
|
if (mode === 'manual') {
|
|
return 'manual'
|
|
}
|
|
return key ? 'auto' : 'empty'
|
|
}
|
|
|
|
export function createField(uid: number, overrides: Partial<BuilderField> = {}): BuilderField {
|
|
return {
|
|
uid,
|
|
label: '',
|
|
key: '',
|
|
keyMode: 'auto',
|
|
type: 'text',
|
|
required: false,
|
|
unique: false,
|
|
defaultValue: '',
|
|
defaultOn: false,
|
|
min: '',
|
|
max: '',
|
|
options: [],
|
|
relationType: '',
|
|
relationKind: DEFAULT_RELATION_KIND,
|
|
saved: false,
|
|
...overrides,
|
|
}
|
|
}
|
|
|
|
export function starterField(uid: number): BuilderField {
|
|
return createField(uid, { label: STARTER_LABEL, key: STARTER_KEY })
|
|
}
|
|
|
|
export function blankForm(uid: number): BuilderForm {
|
|
return {
|
|
name: '',
|
|
key: '',
|
|
keyMode: 'auto',
|
|
keyLocked: false,
|
|
fields: [starterField(uid)],
|
|
}
|
|
}
|
|
|
|
export function changeFieldType(field: BuilderField, type: FieldType): BuilderField {
|
|
if (field.type === type) {
|
|
return field
|
|
}
|
|
return createField(field.uid, {
|
|
label: field.label,
|
|
key: field.key,
|
|
keyMode: field.keyMode,
|
|
required: field.required,
|
|
type,
|
|
})
|
|
}
|
|
|
|
export function supportsUnique(type: FieldType) {
|
|
return FIELD_TYPE_SPECS[type].supportsUnique
|
|
}
|
|
|
|
export function supportsChoices(type: FieldType) {
|
|
return FIELD_TYPE_SPECS[type].supportsChoices
|
|
}
|
|
|
|
export function holdsRelation(type: FieldType) {
|
|
return FIELD_TYPE_SPECS[type].holdsRelation
|
|
}
|
|
|
|
export function supportsLimits(type: FieldType) {
|
|
return FIELD_TYPE_SPECS[type].supportsLimits
|
|
}
|
|
|
|
export function hasDefaultValue(field: BuilderField) {
|
|
return !field.unique && field.defaultValue !== ''
|
|
}
|
|
|
|
export function trimmedOptions(field: BuilderField) {
|
|
return field.options.map((option) => option.trim())
|
|
}
|
|
|
|
export function clearStaleDefault(field: BuilderField): BuilderField {
|
|
if (field.type !== 'select' || field.defaultValue === '') {
|
|
return field
|
|
}
|
|
return trimmedOptions(field).includes(field.defaultValue)
|
|
? field
|
|
: { ...field, defaultValue: '' }
|
|
}
|
|
|
|
export function isUnique(field: BuilderField) {
|
|
return field.unique && supportsUnique(field.type)
|
|
}
|
|
|
|
export function supportsDefault(type: FieldType) {
|
|
return FIELD_TYPE_SPECS[type].supportsDefault
|
|
}
|
|
|
|
export function effectiveDefault(field: BuilderField) {
|
|
if (!supportsDefault(field.type) || isUnique(field) || field.defaultValue === '') {
|
|
return ''
|
|
}
|
|
if (field.type === 'select') {
|
|
return trimmedOptions(field).includes(field.defaultValue) ? field.defaultValue : ''
|
|
}
|
|
return field.defaultValue
|
|
}
|