From c277f1b83c7ebd062d07e26cc1bd6f7fbdb75291 Mon Sep 17 00:00:00 2001 From: Aarni Halinen Date: Fri, 24 Jul 2020 17:10:31 +0300 Subject: [PATCH] Combine Schema creation functions --- src/models/SignupForm.ts | 8 +- src/pages/admin/SignupCreatePage.tsx | 4 +- src/views/SignUpPage/FormUtils.tsx | 158 ++++++++---------------- src/views/SignUpPage/SignUpPageView.tsx | 4 +- 4 files changed, 63 insertions(+), 111 deletions(-) diff --git a/src/models/SignupForm.ts b/src/models/SignupForm.ts index adedde1..4106731 100644 --- a/src/models/SignupForm.ts +++ b/src/models/SignupForm.ts @@ -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 { diff --git a/src/pages/admin/SignupCreatePage.tsx b/src/pages/admin/SignupCreatePage.tsx index 99c5b91..3a19dca 100644 --- a/src/pages/admin/SignupCreatePage.tsx +++ b/src/pages/admin/SignupCreatePage.tsx @@ -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 { - 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 = { diff --git a/src/views/SignUpPage/SignUpPageView.tsx b/src/views/SignUpPage/SignUpPageView.tsx index 62d208a..34f4b3f 100644 --- a/src/views/SignUpPage/SignUpPageView.tsx +++ b/src/views/SignUpPage/SignUpPageView.tsx @@ -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 = ({ }) => { const renderForm = () => { - const schema = buildSchema(signUpForm); + const schema = buildFormSchema(signUpForm); const uiSchema = buildUISchema(signUpForm); return (