Skip to content

Commit

Permalink
Merge branch 'feat/dto-form-field' into feat/dto-form
Browse files Browse the repository at this point in the history
# Conflicts:
#	src/types/field/index.ts
  • Loading branch information
karrui committed Jul 16, 2021
2 parents bdeed1a + ca42de9 commit a4ee0cb
Show file tree
Hide file tree
Showing 20 changed files with 145 additions and 81 deletions.
9 changes: 7 additions & 2 deletions shared/types/field/tableField.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,15 @@ import { FieldBase, BasicField } from './base'
import { DropdownFieldBase } from './dropdownField'
import { ShortTextFieldBase } from './shortTextField'

export interface ShortTextColumnBase extends ShortTextFieldBase {
// Column types do not have most field base props.
type ColumnBase<T extends FieldBase> = Omit<T, keyof FieldBase> & {
title: string
required: boolean
}
export interface ShortTextColumnBase extends ColumnBase<ShortTextFieldBase> {
columnType: BasicField.ShortText
}
export interface DropdownColumnBase extends DropdownFieldBase {
export interface DropdownColumnBase extends ColumnBase<DropdownFieldBase> {
columnType: BasicField.Dropdown
}

Expand Down
34 changes: 13 additions & 21 deletions src/app/utils/field-validation/answerField.factory.ts
Original file line number Diff line number Diff line change
@@ -1,37 +1,29 @@
import { BasicField, IColumnSchema } from '../../../types'
import {
IColumnSchema,
IDropdownFieldSchema,
IShortTextFieldSchema,
OmitUnusedValidatorProps,
} from '../../../types'

/**
* Return type of createAnswerFieldFromColumn().
* This is a subset of IFieldSchema (note that the
* fieldType is restricted) and allows the result to be
* passed into validateField().
* */
type ColumnWithFieldProperties = IColumnSchema & {
getQuestion: { (): string }
description: string
disabled: boolean
fieldType: BasicField.ShortText | BasicField.Dropdown
}
type ColumnWithFieldProperties =
| OmitUnusedValidatorProps<IShortTextFieldSchema>
| OmitUnusedValidatorProps<IDropdownFieldSchema>

/**
* Takes a table field column and generates a form field by
* filling in the missing attributes.
* filling in the missing fieldType attribute.
* */
export const createAnswerFieldFromColumn = (
column: IColumnSchema,
): ColumnWithFieldProperties => {
const columnField = {
// Convert mongoose document to object first,
// otherwise the values will not be correctly spread
return {
...column.toObject(),
disabled: false,
description: 'some description',
get fieldType() {
return column.columnType
},
getQuestion() {
return 'some question'
},
}
return columnField as ColumnWithFieldProperties
fieldType: column.columnType,
} as ColumnWithFieldProperties
}
10 changes: 5 additions & 5 deletions src/app/utils/field-validation/answerValidator.factory.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { left } from 'fp-ts/lib/Either'

import { BasicField, FormFieldSchema } from '../../../types'
import { BasicField, FieldValidationSchema } from '../../../types'
import { ResponseValidator } from '../../../types/field/utils/validation'
import {
ProcessedAttachmentResponse,
Expand Down Expand Up @@ -32,7 +32,7 @@ import { constructYesNoValidator } from './validators/yesNoValidator'
* @param formField A form field from a form object
*/
export const constructSingleAnswerValidator = (
formField: FormFieldSchema,
formField: FieldValidationSchema,
): ResponseValidator<ProcessedSingleAnswerResponse> => {
switch (formField.fieldType) {
case BasicField.Section:
Expand Down Expand Up @@ -72,7 +72,7 @@ export const constructSingleAnswerValidator = (
export const constructAttachmentFieldValidator = (
// Separate from constructSingleAnswerValidator as
// constructAttachmentValidator returns different type
formField: FormFieldSchema,
formField: FieldValidationSchema,
): ResponseValidator<ProcessedAttachmentResponse> => {
if (formField.fieldType === BasicField.Attachment) {
return constructAttachmentValidator(formField)
Expand All @@ -81,7 +81,7 @@ export const constructAttachmentFieldValidator = (
}

export const constructCheckboxFieldValidator = (
formField: FormFieldSchema,
formField: FieldValidationSchema,
): ResponseValidator<ProcessedCheckboxResponse> => {
if (formField.fieldType === BasicField.Checkbox) {
return constructCheckboxValidator(formField)
Expand All @@ -90,7 +90,7 @@ export const constructCheckboxFieldValidator = (
}

export const constructTableFieldValidator = (
formField: FormFieldSchema,
formField: FieldValidationSchema,
): ResponseValidator<ProcessedTableResponse> => {
if (formField.fieldType === BasicField.Table) {
return constructTableValidator(formField)
Expand Down
20 changes: 10 additions & 10 deletions src/app/utils/field-validation/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ import {
import { FIELDS_TO_REJECT } from '../../../shared/resources/basic'
import {
BasicField,
FormFieldSchema,
IFieldSchema,
FieldValidationSchema,
ITableFieldSchema,
OmitUnusedValidatorProps,
} from '../../../types/field'
import { ResponseValidator } from '../../../types/field/utils/validation'
import { createLoggerWithLabel } from '../../config/logger'
Expand Down Expand Up @@ -47,7 +47,7 @@ const isValidResponseFieldType = (response: ProcessedFieldResponse): boolean =>
* @param response The submitted response
*/
const doFieldTypesMatch = (
formField: IFieldSchema,
formField: FieldValidationSchema,
response: ProcessedFieldResponse,
): Either<string, undefined> => {
return response.fieldType !== formField.fieldType
Expand Down Expand Up @@ -100,23 +100,23 @@ const isResponsePresentOnHiddenField = (
* @param response The submitted response
*/
const singleAnswerRequiresValidation = (
formField: IFieldSchema,
formField: FieldValidationSchema,
response: ProcessedSingleAnswerResponse,
) => (formField.required && response.isVisible) || response.answer.trim() !== ''

const attachmentRequiresValidation = (
formField: IFieldSchema,
formField: FieldValidationSchema,
response: ProcessedAttachmentResponse,
) => (formField.required && response.isVisible) || response.answer.trim() !== ''

const checkboxRequiresValidation = (
formField: IFieldSchema,
formField: FieldValidationSchema,
response: ProcessedCheckboxResponse,
) =>
(formField.required && response.isVisible) || response.answerArray.length > 0

const tableRequiresValidation = (
formField: ITableFieldSchema,
formField: OmitUnusedValidatorProps<ITableFieldSchema>,
response: ProcessedTableResponse,
) => {
const { columns } = formField
Expand All @@ -138,7 +138,7 @@ const tableRequiresValidation = (
*/
const logInvalidAnswer = (
formId: string,
formField: IFieldSchema,
formField: FieldValidationSchema,
message: string,
) => {
logger.error({
Expand All @@ -159,7 +159,7 @@ const logInvalidAnswer = (
const validateResponseWithValidator = <T extends ProcessedFieldResponse>(
validator: ResponseValidator<T>,
formId: string,
formField: IFieldSchema,
formField: FieldValidationSchema,
response: T,
): Result<true, ValidateFieldError> => {
const validEither = validator(response)
Expand All @@ -180,7 +180,7 @@ const validateResponseWithValidator = <T extends ProcessedFieldResponse>(
*/
export const validateField = (
formId: string,
formField: FormFieldSchema,
formField: FieldValidationSchema,
response: ProcessedFieldResponse,
): Result<true, ValidateFieldError> => {
if (!isValidResponseFieldType(response)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@ import { chain, left, right } from 'fp-ts/lib/Either'
import { flow } from 'fp-ts/lib/function'

import { ProcessedAttachmentResponse } from 'src/app/modules/submission/submission.types'
import { IAttachmentField } from 'src/types/field'
import {
IAttachmentFieldSchema,
OmitUnusedValidatorProps,
} from 'src/types/field'
import { ResponseValidator } from 'src/types/field/utils/validation'

import { MB } from '../../../../shared/constants'

type AttachmentValidator = ResponseValidator<ProcessedAttachmentResponse>
type AttachmentValidatorConstructor = (
attachmentField: IAttachmentField,
attachmentField: OmitUnusedValidatorProps<IAttachmentFieldSchema>,
) => AttachmentValidator

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ import { chain, left, right } from 'fp-ts/lib/Either'
import { flow } from 'fp-ts/lib/function'

import { ProcessedCheckboxResponse } from 'src/app/modules/submission/submission.types'
import { ICheckboxField } from 'src/types/field'
import { ICheckboxFieldSchema, OmitUnusedValidatorProps } from 'src/types/field'
import { ResponseValidator } from 'src/types/field/utils/validation'

import { isOtherOption } from './options'

type CheckboxValidator = ResponseValidator<ProcessedCheckboxResponse>
type CheckboxValidatorConstructor = (
checkboxField: ICheckboxField,
checkboxField: OmitUnusedValidatorProps<ICheckboxFieldSchema>,
) => CheckboxValidator

/**
Expand Down
10 changes: 8 additions & 2 deletions src/app/utils/field-validation/validators/common.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import { left, right } from 'fp-ts/lib/Either'

import { ProcessedSingleAnswerResponse } from 'src/app/modules/submission/submission.types'
import { IEmailFieldSchema, IMobileFieldSchema } from 'src/types/field'
import {
IEmailFieldSchema,
IMobileFieldSchema,
OmitUnusedValidatorProps,
} from 'src/types/field'
import { ResponseValidator } from 'src/types/field/utils/validation'

import formsgSdk from '../../../config/formsg-sdk'
Expand All @@ -23,7 +27,9 @@ export const notEmptySingleAnswerResponse: ResponseValidator<ProcessedSingleAnsw
* The validator checks if field has correct signature.
*/
export const makeSignatureValidator: (
formField: IEmailFieldSchema | IMobileFieldSchema,
formField:
| OmitUnusedValidatorProps<IEmailFieldSchema>
| OmitUnusedValidatorProps<IMobileFieldSchema>,
) => ResponseValidator<ProcessedSingleAnswerResponse> =
(formField) => (response) => {
const { isVerifiable, _id } = formField
Expand Down
6 changes: 4 additions & 2 deletions src/app/utils/field-validation/validators/dateValidator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,17 @@ import { flow } from 'fp-ts/lib/function'
import moment from 'moment-timezone'

import { ProcessedSingleAnswerResponse } from 'src/app/modules/submission/submission.types'
import { IDateField } from 'src/types/field'
import { IDateFieldSchema, OmitUnusedValidatorProps } from 'src/types/field'
import { ResponseValidator } from 'src/types/field/utils/validation'

import { DateSelectedValidation } from '../../../../shared/constants'

import { notEmptySingleAnswerResponse } from './common'

type DateValidator = ResponseValidator<ProcessedSingleAnswerResponse>
type DateValidatorConstructor = (dateField: IDateField) => DateValidator
type DateValidatorConstructor = (
dateField: OmitUnusedValidatorProps<IDateFieldSchema>,
) => DateValidator

/**
* @param date
Expand Down
4 changes: 2 additions & 2 deletions src/app/utils/field-validation/validators/decimalValidator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ import isFloat from 'validator/lib/isFloat'
import isInt from 'validator/lib/isInt'

import { ProcessedSingleAnswerResponse } from 'src/app/modules/submission/submission.types'
import { IDecimalField } from 'src/types/field'
import { IDecimalFieldSchema, OmitUnusedValidatorProps } from 'src/types/field'
import { ResponseValidator } from 'src/types/field/utils/validation'

import { notEmptySingleAnswerResponse } from './common'

type DecimalValidator = ResponseValidator<ProcessedSingleAnswerResponse>
type DecimalValidatorConstructor = (
decimalField: IDecimalField,
decimalField: OmitUnusedValidatorProps<IDecimalFieldSchema>,
) => DecimalValidator
interface IIsFloatOptions {
min?: number
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { chain, left, right } from 'fp-ts/lib/Either'
import { flow } from 'fp-ts/lib/function'

import { ProcessedSingleAnswerResponse } from 'src/app/modules/submission/submission.types'
import { IDropdownField } from 'src/types/field'
import { IDropdownFieldSchema, OmitUnusedValidatorProps } from 'src/types/field'
import { ResponseValidator } from 'src/types/field/utils/validation'

import { getMyInfoFieldOptions } from '../../../modules/myinfo/myinfo.util'
Expand All @@ -12,7 +12,7 @@ import { isOneOfOptions } from './options'

type DropdownValidator = ResponseValidator<ProcessedSingleAnswerResponse>
type DropdownValidatorConstructor = (
dropdownField: IDropdownField,
dropdownField: OmitUnusedValidatorProps<IDropdownFieldSchema>,
) => DropdownValidator

/**
Expand Down
4 changes: 2 additions & 2 deletions src/app/utils/field-validation/validators/emailValidator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ import { flow } from 'fp-ts/lib/function'
import isEmail from 'validator/lib/isEmail'

import { ProcessedSingleAnswerResponse } from 'src/app/modules/submission/submission.types'
import { IEmailFieldSchema } from 'src/types/field'
import { IEmailFieldSchema, OmitUnusedValidatorProps } from 'src/types/field'
import { ResponseValidator } from 'src/types/field/utils/validation'

import { makeSignatureValidator, notEmptySingleAnswerResponse } from './common'

type EmailValidator = ResponseValidator<ProcessedSingleAnswerResponse>
type EmailValidatorConstructor = (
emailField: IEmailFieldSchema,
emailField: OmitUnusedValidatorProps<IEmailFieldSchema>,
) => EmailValidator

/**
Expand Down
4 changes: 2 additions & 2 deletions src/app/utils/field-validation/validators/homeNoValidator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { chain, left, right } from 'fp-ts/lib/Either'
import { flow } from 'fp-ts/lib/function'

import { ProcessedSingleAnswerResponse } from 'src/app/modules/submission/submission.types'
import { IHomenoField } from 'src/types/field'
import { IHomenoFieldSchema, OmitUnusedValidatorProps } from 'src/types/field'
import { ResponseValidator } from 'src/types/field/utils/validation'

import {
Expand All @@ -14,7 +14,7 @@ import { notEmptySingleAnswerResponse } from './common'

type HomeNoValidator = ResponseValidator<ProcessedSingleAnswerResponse>
type HomeNoValidatorConstructor = (
homeNumberField: IHomenoField,
homeNumberField: OmitUnusedValidatorProps<IHomenoFieldSchema>,
) => HomeNoValidator

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { chain, left, right } from 'fp-ts/lib/Either'
import { flow } from 'fp-ts/lib/function'

import { ProcessedSingleAnswerResponse } from 'src/app/modules/submission/submission.types'
import { IMobileFieldSchema } from 'src/types/field'
import { IMobileFieldSchema, OmitUnusedValidatorProps } from 'src/types/field'
import { ResponseValidator } from 'src/types/field/utils/validation'

import {
Expand All @@ -14,7 +14,7 @@ import { makeSignatureValidator, notEmptySingleAnswerResponse } from './common'

type MobileNoValidator = ResponseValidator<ProcessedSingleAnswerResponse>
type MobileNoValidatorConstructor = (
mobileNumberField: IMobileFieldSchema,
mobileNumberField: OmitUnusedValidatorProps<IMobileFieldSchema>,
) => MobileNoValidator

/**
Expand Down
6 changes: 4 additions & 2 deletions src/app/utils/field-validation/validators/numberValidator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,17 @@ import { chain, left, right } from 'fp-ts/lib/Either'
import { flow } from 'fp-ts/lib/function'

import { ProcessedSingleAnswerResponse } from 'src/app/modules/submission/submission.types'
import { INumberField } from 'src/types/field'
import { INumberFieldSchema, OmitUnusedValidatorProps } from 'src/types/field'
import { ResponseValidator } from 'src/types/field/utils/validation'

import { NumberSelectedValidation } from '../../../../types/field'

import { notEmptySingleAnswerResponse } from './common'

type NumberValidator = ResponseValidator<ProcessedSingleAnswerResponse>
type NumberValidatorConstructor = (numberField: INumberField) => NumberValidator
type NumberValidatorConstructor = (
numberField: OmitUnusedValidatorProps<INumberFieldSchema>,
) => NumberValidator

/**
* Return a validator to check if number format is correct.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@ import { chain, left, right } from 'fp-ts/lib/Either'
import { flow } from 'fp-ts/lib/function'

import { ProcessedSingleAnswerResponse } from 'src/app/modules/submission/submission.types'
import { IRadioField } from 'src/types/field'
import { IRadioFieldSchema, OmitUnusedValidatorProps } from 'src/types/field'
import { ResponseValidator } from 'src/types/field/utils/validation'

import { notEmptySingleAnswerResponse } from './common'
import { isOneOfOptions, isOtherOption } from './options'

type RadioButtonValidator = ResponseValidator<ProcessedSingleAnswerResponse>
type RadioButtonValidatorConstructor = (
radioButtonField: IRadioField,
radioButtonField: OmitUnusedValidatorProps<IRadioFieldSchema>,
) => RadioButtonValidator

/**
Expand Down
Loading

0 comments on commit a4ee0cb

Please sign in to comment.