create model & record - validation hooked up again
This commit is contained in:
parent
53ff560e42
commit
0d637260be
3 changed files with 69 additions and 34 deletions
|
@ -13,17 +13,33 @@
|
||||||
|
|
||||||
const FIELD_TYPES = ["string", "number", "boolean"]
|
const FIELD_TYPES = ["string", "number", "boolean"]
|
||||||
|
|
||||||
export let field = { type: "string" }
|
export let field = { type: "string", constraints: { type: "string", presence: false } }
|
||||||
export let schema
|
export let schema
|
||||||
export let goBack
|
export let goBack
|
||||||
|
|
||||||
let errors = []
|
let errors = []
|
||||||
let draftField = cloneDeep(field)
|
let draftField = cloneDeep(field)
|
||||||
|
|
||||||
|
let type = field.type
|
||||||
|
let constraints = field.constraints
|
||||||
|
let required = field.constraints.presence && !field.constraints.presence.allowEmpty
|
||||||
|
|
||||||
const save = () => {
|
const save = () => {
|
||||||
|
constraints.presence = required ? { allowEmpty: false } : false
|
||||||
|
draftField.constraints = constraints
|
||||||
|
draftField.type = type
|
||||||
schema[field.name] = draftField
|
schema[field.name] = draftField
|
||||||
goBack()
|
goBack()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$: constraints =
|
||||||
|
type === "string" ? { type: "string", length: {}, presence: false }
|
||||||
|
: type === "number" ? { type: "number", presence: false, numericality: {} }
|
||||||
|
: type === "boolean" ? { type: "boolean", presence: false }
|
||||||
|
: type === "datetime" ? { type: "date", datetime: {}, presence: false }
|
||||||
|
: type.startsWith('array') ? { type: "array", presence: false }
|
||||||
|
: { type: "string", presence: false }
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="root">
|
<div class="root">
|
||||||
|
@ -34,30 +50,22 @@
|
||||||
<Textbox label="Name" bind:text={field.name} />
|
<Textbox label="Name" bind:text={field.name} />
|
||||||
<Dropdown
|
<Dropdown
|
||||||
label="Type"
|
label="Type"
|
||||||
bind:selected={draftField.type}
|
bind:selected={type}
|
||||||
options={FIELD_TYPES} />
|
options={FIELD_TYPES} />
|
||||||
|
|
||||||
{#if field.type === 'string'}
|
<Checkbox label="Required" bind:checked={required} />
|
||||||
<NumberBox label="Max Length" bind:value={draftField.maxLength} />
|
|
||||||
<ValuesList label="Categories" bind:values={draftField.values} />
|
|
||||||
{:else if field.type === 'boolean'}
|
{#if type === 'string'}
|
||||||
|
<NumberBox label="Max Length" bind:value={constraints.length.maximum} />
|
||||||
|
<ValuesList label="Categories" bind:values={constraints.inclusion} />
|
||||||
|
{:else if type === 'datetime'}
|
||||||
<!-- TODO: revisit and fix with JSON schema -->
|
<!-- TODO: revisit and fix with JSON schema -->
|
||||||
<Checkbox label="Allow Null" bind:checked={draftField.allowNulls} />
|
<DatePicker label="Min Value" bind:value={constraints.datetime.earliest} />
|
||||||
{:else if field.format === 'datetime'}
|
<DatePicker label="Max Value" bind:value={constraints.datetime.latest} />
|
||||||
<!-- TODO: revisit and fix with JSON schema -->
|
{:else if type === 'number'}
|
||||||
<DatePicker label="Min Value" bind:value={draftField.minValue} />
|
<NumberBox label="Min Value" bind:value={constraints.numericality.greaterThanOrEqualTo} />
|
||||||
<DatePicker label="Max Value" bind:value={draftField.maxValue} />
|
<NumberBox label="Max Value" bind:value={constraints.numericality.lessThanOrEqualTo} />
|
||||||
{:else if field.type === 'number'}
|
|
||||||
<NumberBox label="Min Value" bind:value={draftField.minimum} />
|
|
||||||
<NumberBox label="Max Value" bind:value={draftField.maximum} />
|
|
||||||
{:else if draftField.type.startsWith('array')}
|
|
||||||
<!-- TODO: revisit and fix with JSON schema -->
|
|
||||||
<NumberBox
|
|
||||||
label="Min Length"
|
|
||||||
bind:value={draftField.typeOptions.minLength} />
|
|
||||||
<NumberBox
|
|
||||||
label="Max Length"
|
|
||||||
bind:value={draftField.typeOptions.maxLength} />
|
|
||||||
{/if}
|
{/if}
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -8,10 +8,6 @@
|
||||||
import * as api from "../api"
|
import * as api from "../api"
|
||||||
import ErrorsBox from "components/common/ErrorsBox.svelte"
|
import ErrorsBox from "components/common/ErrorsBox.svelte"
|
||||||
|
|
||||||
const CLASS_NAME_MAP = {
|
|
||||||
boolean: "uk-checkbox",
|
|
||||||
}
|
|
||||||
|
|
||||||
export let record = {}
|
export let record = {}
|
||||||
export let onClosed
|
export let onClosed
|
||||||
|
|
||||||
|
@ -28,14 +24,25 @@
|
||||||
onClosed()
|
onClosed()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isSelect = meta =>
|
||||||
|
meta.type === "string"
|
||||||
|
&& meta.constraints
|
||||||
|
&& meta.constraints.inclusion
|
||||||
|
&& meta.constraints.inclusion.length > 0
|
||||||
|
|
||||||
function determineInputType(meta) {
|
function determineInputType(meta) {
|
||||||
if (meta.type === "datetime") return "date"
|
if (meta.type === "datetime") return "date"
|
||||||
if (meta.type === "number") return "number"
|
if (meta.type === "number") return "number"
|
||||||
if (meta.type === "boolean") return "checkbox"
|
if (meta.type === "boolean") return "checkbox"
|
||||||
|
if (isSelect(meta)) return "select"
|
||||||
|
|
||||||
return "text"
|
return "text"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function determineOptions(meta) {
|
||||||
|
return isSelect(meta) ? meta.constraints.inclusion : []
|
||||||
|
}
|
||||||
|
|
||||||
async function saveRecord() {
|
async function saveRecord() {
|
||||||
const recordResponse = await api.saveRecord(
|
const recordResponse = await api.saveRecord(
|
||||||
{
|
{
|
||||||
|
@ -46,7 +53,9 @@
|
||||||
$backendUiStore.selectedModel._id
|
$backendUiStore.selectedModel._id
|
||||||
)
|
)
|
||||||
if (recordResponse.errors) {
|
if (recordResponse.errors) {
|
||||||
errors = recordResponse.errors
|
errors = Object.keys(recordResponse.errors)
|
||||||
|
.map(k => ({dataPath: k, message: recordResponse.errors[k]}))
|
||||||
|
.flat()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,8 +74,8 @@
|
||||||
{#each modelSchema as [key, meta]}
|
{#each modelSchema as [key, meta]}
|
||||||
<div class="uk-margin">
|
<div class="uk-margin">
|
||||||
<RecordFieldControl
|
<RecordFieldControl
|
||||||
className={CLASS_NAME_MAP[meta.type]}
|
|
||||||
type={determineInputType(meta)}
|
type={determineInputType(meta)}
|
||||||
|
options={determineOptions(meta)}
|
||||||
label={key}
|
label={key}
|
||||||
bind:value={record[key]} />
|
bind:value={record[key]} />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -3,10 +3,16 @@
|
||||||
export let value = ""
|
export let value = ""
|
||||||
export let label
|
export let label
|
||||||
export let errors = []
|
export let errors = []
|
||||||
export let className = "uk-input"
|
export let options = []
|
||||||
|
|
||||||
let checked = type === "checkbox" ? value : false
|
let checked = type === "checkbox" ? value : false
|
||||||
|
|
||||||
|
const determineClassName = type => {
|
||||||
|
if (type === "checkbox") return "uk-checkbox"
|
||||||
|
if (type === "select") return "uk-select"
|
||||||
|
return "uk-input"
|
||||||
|
}
|
||||||
|
|
||||||
const handleInput = event => {
|
const handleInput = event => {
|
||||||
if (event.target.type === "checkbox") {
|
if (event.target.type === "checkbox") {
|
||||||
value = event.target.checked
|
value = event.target.checked
|
||||||
|
@ -23,11 +29,23 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<label>{label}</label>
|
<label>{label}</label>
|
||||||
|
|
||||||
|
{#if type === "select"}
|
||||||
|
<select
|
||||||
|
class={determineClassName(type)}
|
||||||
|
bind:value={value}
|
||||||
|
class:uk-form-danger={errors.length > 0} >
|
||||||
|
{#each options as opt}
|
||||||
|
<option value={opt}>{ opt }</option>
|
||||||
|
{/each}
|
||||||
|
</select>
|
||||||
|
{:else}
|
||||||
<input
|
<input
|
||||||
class={className}
|
class={determineClassName(type)}
|
||||||
class:uk-form-danger={errors.length > 0}
|
class:uk-form-danger={errors.length > 0}
|
||||||
{checked}
|
{checked}
|
||||||
{type}
|
{type}
|
||||||
{value}
|
{value}
|
||||||
on:input={handleInput}
|
on:input={handleInput}
|
||||||
on:change={handleInput} />
|
on:change={handleInput} />
|
||||||
|
{/if}
|
||||||
|
|
Loading…
Reference in a new issue