Combine Schema creation functions

This commit is contained in:
Aarni Halinen
2020-07-24 17:10:31 +03:00
parent b6230fb6aa
commit c277f1b83c
4 changed files with 63 additions and 111 deletions
+7 -1
View File
@@ -11,7 +11,13 @@ export interface SignupForm {
questions: Question[];
signups: string[];
quota: number;
schema: object;
schema: {
title?: string;
type: string;
required: string[];
properties: any;
minProperties?: number;
};
}
export async function getForms(): Promise<SignupForm[]> {
+2 -2
View File
@@ -6,7 +6,7 @@ import Form from "react-jsonschema-form";
import { createForm, getForm, updateForm, SignupForm } from "@models/SignupForm";
import DatetimeWidget from "@components/DatetimeWidget";
import SignupQuestionsWidget from "@components/SignupQuestionsWidget";
import { buildQuestionsSchema } from "@views/SignUpPage/FormUtils";
import { buildValidationSchema } from "@views/SignUpPage/FormUtils";
const widgets = {
datetime: DatetimeWidget,
@@ -64,7 +64,7 @@ class SignupCreatePage extends React.Component<SignupCreatePageProps, SignupCrea
const payload: SignupForm = {
...data.formData,
questions,
schema: buildQuestionsSchema(questions)
schema: buildValidationSchema(questions)
}
if (payload.id === undefined) {
+52 -106
View File
@@ -3,86 +3,6 @@ import { Question } from "@components/SignupQuestionsWidget";
import { SignupForm } from "@models/SignupForm";
import { EMAIL_REGEX } from "@utils/regexes";
const questionToSchemaProp = (question: Question): {} => {
let obj: any;
if (question.type === "text" || question.type === "name") {
obj = {
type: "string",
title: question.name,
default: "",
};
}
else if (question.type === "radiobutton") {
obj = {
type: "string",
title: question.name,
enum: question.options,
};
}
else if (question.type === "checkbox") {
obj = {
type: "array",
title: question.name,
items: {
type: "string",
enum: question.options,
},
uniqueItems: true,
};
}
else if (question.type === "email") {
obj = {
type: "string",
title: question.name,
format: "email",
default: ""
}
}
else if (question.type === "info") {
obj = {
type: "null",
title: question.name,
description: question.options
}
}
// https://json-schema.org/understanding-json-schema/reference/numeric.html
else if (question.type === "integer") {
if (question.options.length === 1) {
obj = {
type: "number",
multipleOf: 1.0,
title: `${question.name} (Max: ${question.options[0]})`,
maximum: Number(question.options[0]),
}
}
else if (question.options.length === 2) {
obj = {
type: "number",
multipleOf: 1.0,
title: `${question.name} (${question.options[0]} -- ${question.options[1]})`,
minimum: Number(question.options[0]),
maximum: Number(question.options[1]),
}
}
else {
obj = {
type: "number",
multipleOf: 1.0,
title: question.name,
}
}
}
else {
throw new Error(`No mapping to schema prop for question type ${question.type}`);
}
return {
[question.id]: obj,
}
}
const questionToUISchemaProp = (question: Question): {} => {
let obj = {};
if (question.type == "checkbox") {
@@ -104,33 +24,48 @@ const questionToUISchemaProp = (question: Question): {} => {
}
const questionToValidationSchema = (question: Question) => {
let obj = {};
if (question.type === "text" || question.type === "name") {
return {
obj = {
type: "string",
title: question.name,
default: "",
};
}
if (question.type == "email") {
else if(question.type === "info") {
obj = {
type: "null",
title: question.name,
description: question.options
};
}
else if (question.type === "email") {
// Format is just a "FYI" field, so we also have pattern.
return {
obj = {
type: "string",
title: question.name,
format: "email",
pattern: EMAIL_REGEX.source
pattern: EMAIL_REGEX.source,
default: ""
}
}
if (question.type == "radiobutton") {
return {
"type": "string",
"pattern": question.options.map(x => `^${x}$`).join("|"),
else if (question.type === "radiobutton") {
obj = {
type: "string",
title: question.name,
pattern: question.options.map(x => `^${x}$`).join("|"),
enum: question.options,
}
}
if (question.type == "checkbox") {
return {
else if (question.type === "checkbox") {
obj = {
type: "array",
title: question.name,
uniqueItems: true,
maxItems: question.options.length,
items: {
type: "string",
enum: question.options,
pattern: question.options.map(x => `^${x}$`).join("|"),
}
}
@@ -138,37 +73,45 @@ const questionToValidationSchema = (question: Question) => {
// https://json-schema.org/understanding-json-schema/reference/numeric.html
else if (question.type === "integer") {
if (question.options.length === 1) {
return {
obj = {
type: "number",
multipleOf: 1.0,
title: `${question.name} (Max: ${question.options[0]})`,
multipleOf: 1.0,
maximum: Number(question.options[0]),
}
}
else if (question.options.length === 2) {
return {
obj = {
type: "number",
multipleOf: 1.0,
title: `${question.name} (${question.options[0]} -- ${question.options[1]})`,
multipleOf: 1.0,
minimum: Number(question.options[0]),
maximum: Number(question.options[1]),
}
}
else {
return {
obj = {
type: "number",
multipleOf: 1.0,
title: question.name,
multipleOf: 1.0,
}
}
}
throw new Error(`No mapping to schema prop for question type ${question.type}`);
else {
throw new Error(`No mapping to schema prop for question type ${question.type}`);
}
return {
[question.id]: obj,
}
}
export const buildSchema = (signUpForm: SignupForm) => {
const {questions} = signUpForm;
const schemaPropsArray = questions.map(questionToSchemaProp);
export const buildFormSchema = (signUpForm: SignupForm) => {
let schemaProps = {};
const {questions} = signUpForm;
const filtered = questions.filter(x => x.type !== "info");
const ids = filtered.map(q => q.id);
const schemaPropsArray = questions.map(questionToValidationSchema);
schemaPropsArray.forEach((schemaProp) => {
schemaProps = {
...schemaProps,
@@ -179,20 +122,23 @@ export const buildSchema = (signUpForm: SignupForm) => {
const schema = {
title: signUpForm.id ? signUpForm.title : "Loading...",
type: "object",
required: [],
required: ids,
properties: schemaProps,
};
return schema;
}
export const buildQuestionsSchema = (questions: Question[]) => {
const schemaProps = {};
export const buildValidationSchema = (questions: Question[]) => {
let schemaProps = {};
const filtered = questions.filter(x => x.type !== "info");
const ids = filtered.map(q => q.id);
const schemaPropsArray = filtered.map(questionToValidationSchema);
schemaPropsArray.forEach((schemaProp, idx) => {
schemaProps[ids[idx]] = schemaProp;
schemaPropsArray.forEach((schemaProp) => {
schemaProps = {
...schemaProps,
...schemaProp,
};
});
const validationSchema = {
+2 -2
View File
@@ -3,7 +3,7 @@ import Form, { IChangeEvent, ISubmitEvent, ErrorSchema } from "react-jsonschema-
import "./SignUpPage.scss";
import PageSection from "@components/PageSection";
import { SignupForm } from "@models/SignupForm";
import { buildSchema, buildUISchema } from "./FormUtils";
import { buildFormSchema, buildUISchema } from "./FormUtils";
import AsideSection from "@components/AsideSection";
import MainSection from "@components/MainSection";
import Checkboxes from "@components/Checkbox/Checkboxes";
@@ -46,7 +46,7 @@ const SignUpPageView: React.FC<SignUpPageViewProps> = ({
}) => {
const renderForm = () => {
const schema = buildSchema(signUpForm);
const schema = buildFormSchema(signUpForm);
const uiSchema = buildUISchema(signUpForm);
return (