feat: schema builder's create flow
This commit is contained in:
1 parent
f514146fed
commit
083cc9e23e
71 files changed
+7223
-61
No files matched your search
@@ -0,0 +1,127 @@
|
||||
export const FIELD_TYPES = ['text', 'richtext', 'number', 'boolean', 'date', 'select'] as const
|
||||
|
||||
export type FieldType = (typeof FIELD_TYPES)[number]
|
||||
export type KeyMode = 'auto' | 'manual'
|
||||
export type KeyDisplayMode = KeyMode | 'empty'
|
||||
export type BuilderStatus = 'saving' | 'offline' | 'failed' | 'problems' | 'dirty' | '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[]
|
||||
}
|
||||
|
||||
export interface BuilderForm {
|
||||
name: string
|
||||
key: string
|
||||
keyMode: KeyMode
|
||||
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: [],
|
||||
...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', 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 type !== 'richtext' && type !== 'boolean'
|
||||
}
|
||||
|
||||
export function supportsLimits(type: FieldType) {
|
||||
return type === 'text' || type === 'richtext' || type === 'number' || type === 'date'
|
||||
}
|
||||
|
||||
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 effectiveDefault(field: BuilderField) {
|
||||
if (isUnique(field) || field.defaultValue === '') {
|
||||
return ''
|
||||
}
|
||||
if (field.type === 'select') {
|
||||
return trimmedOptions(field).includes(field.defaultValue) ? field.defaultValue : ''
|
||||
}
|
||||
return field.defaultValue
|
||||
}
|
||||
Reference in new issue
Block a user