Skip to content

Commit

Permalink
feat: add UEN field (#2100)
Browse files Browse the repository at this point in the history
* add uen field in public frontend

* add essential uen types

* make sure uen field renders

* replace isUenValid with isUenField
  • Loading branch information
aniruddha-adhikary authored Jun 14, 2021
1 parent 51dbbe7 commit 35eeeaf
Show file tree
Hide file tree
Showing 18 changed files with 321 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/app/models/field/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import createSectionFieldSchema from './sectionField'
import createShortTextFieldSchema from './shortTextField'
import createStatementFieldSchema from './statementField'
import createTableFieldSchema from './tableField'
import createUenFieldSchema from './uenField'
import createYesNoFieldSchema from './yesNoField'

export {
Expand All @@ -38,6 +39,7 @@ export {
createShortTextFieldSchema,
createStatementFieldSchema,
createTableFieldSchema,
createUenFieldSchema,
createYesNoFieldSchema,
BaseFieldSchema,
}
7 changes: 7 additions & 0 deletions src/app/models/field/uenField.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { Schema } from 'mongoose'

import { IUenFieldSchema } from '../../../types'

const createUenFieldSchema = () => new Schema<IUenFieldSchema>()

export default createUenFieldSchema
2 changes: 2 additions & 0 deletions src/app/models/form.server.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ import {
createShortTextFieldSchema,
createStatementFieldSchema,
createTableFieldSchema,
createUenFieldSchema,
createYesNoFieldSchema,
} from './field'
import LogicSchema, {
Expand Down Expand Up @@ -405,6 +406,7 @@ const compileFormModel = (db: Mongoose): IFormModel => {
FormFieldPath.discriminator(BasicField.Image, createImageFieldSchema())
FormFieldPath.discriminator(BasicField.Date, createDateFieldSchema())
FormFieldPath.discriminator(BasicField.Nric, createNricFieldSchema())
FormFieldPath.discriminator(BasicField.Uen, createUenFieldSchema())
FormFieldPath.discriminator(BasicField.YesNo, createYesNoFieldSchema())
FormFieldPath.discriminator(
BasicField.Statement,
Expand Down
4 changes: 4 additions & 0 deletions src/app/utils/field-validation/answerValidator.factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
isSectionField,
isShortTextField,
isTableField,
isUenField,
isYesNoField,
} from '../../../types/field/utils/guards'
import { ResponseValidator } from '../../../types/field/utils/validation'
Expand All @@ -43,6 +44,7 @@ import { constructRatingValidator } from './validators/ratingValidator'
import { constructSectionValidator } from './validators/sectionValidator'
import { constructTableValidator } from './validators/tableValidator'
import constructTextValidator from './validators/textValidator'
import { constructUenValidator } from './validators/uenValidator'
import { constructYesNoValidator } from './validators/yesNoValidator'

/**
Expand Down Expand Up @@ -76,6 +78,8 @@ export const constructSingleAnswerValidator = (
return constructDropdownValidator(formField)
} else if (isEmailField(formField)) {
return constructEmailValidator(formField)
} else if (isUenField(formField)) {
return constructUenValidator()
} else if (isYesNoField(formField)) {
return constructYesNoValidator()
}
Expand Down
28 changes: 28 additions & 0 deletions src/app/utils/field-validation/validators/uenValidator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
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 { ResponseValidator } from 'src/types/field/utils/validation'

import { isUenValid } from '../../../../shared/util/uen-validation'

import { notEmptySingleAnswerResponse } from './common'

type UenValidator = ResponseValidator<ProcessedSingleAnswerResponse>
type UenValidatorConstructor = () => UenValidator

/**
* Returns a validator to check if uen
* format is correct.
*/
const uenValidator: UenValidator = (response) => {
return isUenValid(response.answer)
? right(response)
: left(`UenValidator:\tanswer is not a valid UEN`)
}

/**
* Returns a validation function for a uen field when called.
*/
export const constructUenValidator: UenValidatorConstructor = () =>
flow(notEmptySingleAnswerResponse, chain(uenValidator))
6 changes: 6 additions & 0 deletions src/public/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,7 @@ require('./modules/forms/base/components/field-number.client.component.js')
require('./modules/forms/base/components/field-rating.client.component.js')
require('./modules/forms/base/components/field-section.client.component.js')
require('./modules/forms/base/components/field-statement.client.component.js')
require('./modules/forms/base/components/field-uen.client.component.js')
require('./modules/forms/base/components/field-textarea.client.component.js')

// forms base directives
Expand All @@ -244,6 +245,7 @@ require('./modules/forms/base/directives/validate-checkbox.client.directive.js')
require('./modules/forms/base/directives/validate-email-domain.client.directive.js')
require('./modules/forms/base/directives/validate-email-format.client.directive.js')
require('./modules/forms/base/directives/validate-nric.client.directive.js')
require('./modules/forms/base/directives/validate-uen.client.directive.js')
require('./modules/forms/base/directives/validate-url.client.directive.js')
require('./modules/forms/base/directives/ng-intl-tel-input.js')
require('./modules/forms/base/directives/submit-form.directive.js')
Expand Down Expand Up @@ -599,6 +601,10 @@ app.run([
'modules/forms/base/componentViews/field-textarea.client.view.html',
require('./modules/forms/base/componentViews/field-textarea.client.view.html'),
)
$templateCache.put(
'modules/forms/base/componentViews/field-uen.client.view.html',
require('./modules/forms/base/componentViews/field-uen.client.view.html'),
)

// Forms base directiveViews
$templateCache.put(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<div class="text-field field-group row">
<!-- Question -->
<label
for="{{ vm.field._id || 'defaultID'}}"
class="field-question col-xs-12"
>
<div id="label-{{ vm.field._id || 'defaultID'}}">
<span class="field-number" ng-show="vm.field.field_number"
>{{ vm.field.field_number }}.</span
>
<span class="field-title">{{ vm.field.title }}</span>
<span class="field-optional" ng-if="!vm.field.required">(optional)</span>
</div>
<div
id="description-{{ vm.field._id || 'defaultID'}}"
class="field-description"
ng-if="vm.field.description"
ng-bind-html="vm.field.description | linky:'_blank'"
></div>
</label>

<!-- Input -->
<div class="col-xs-12 field-input">
<input
id="{{ vm.field._id || 'defaultID'}}"
type="text"
name="{{ vm.field._id || 'defaultID'}}"
class="input-custom input-large"
ng-model="vm.field.fieldValue"
ng-required="vm.field.required"
ng-disabled="vm.field.disabled"
ng-model-options="{ allowInvalid: true }"
ng-keyup="vm.forms.myForm[(vm.field._id || 'defaultID')].$setTouched()"
placeholder="Enter UEN"
autocomplete="off"
ng-trim="true"
ng-class="vm.field.disabled && vm.field.fieldValue ? 'myinfo-disable' : ''"
aria-labelledby="label-{{ vm.field._id || 'defaultID'}}"
aria-describedby="description-{{ vm.field._id || 'defaultID'}}"
validate-uen
/>
</div>

<!-- Error -->
<div
class="col-xs-12"
ng-show="vm.forms.myForm[(vm.field._id || 'defaultID')].$touched"
ng-messages="vm.forms.myForm[(vm.field._id || 'defaultID')].$error"
>
<field-error-component ng-message="required"></field-error-component>
<div ng-message="uenValidator" class="alert-custom alert-error">
<i class="bx bx-exclamation bx-md icon-spacing"></i>
<span class="alert-msg">Please enter a valid UEN</span>
</div>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
'use strict'

angular.module('forms').component('uenFieldComponent', {
templateUrl: 'modules/forms/base/componentViews/field-uen.client.view.html',
bindings: {
field: '<',
forms: '<',
},
controllerAs: 'vm',
})
Original file line number Diff line number Diff line change
Expand Up @@ -101,4 +101,6 @@
forms="forms"
>
</textarea-field-component>
<uen-field-component ng-switch-when="uen" field="field" forms="forms">
</uen-field-component>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
'use strict'

const { isUenValid } = require('../../../../../shared/util/uen-validation')

angular.module('forms').directive('validateUen', validateUen)

function validateUen() {
return {
restrict: 'A',
require: 'ngModel',
link: function (_scope, _elem, _attrs, ctrl) {
ctrl.$validators.uenValidator = function (modelValue) {
return ctrl.$isEmpty(modelValue) ? true : isUenValid(modelValue)
}
},
}
}
1 change: 1 addition & 0 deletions src/public/modules/forms/base/resources/icon-types.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const iconTypeMap = {
decimal: 'bx bx-calculator',
image: 'bx bx-image',
nric: 'bx bx-user',
uen: 'bx bx-building',
attachment: 'bx bx-cloud-download',
radiobutton: 'bx bx-radio-circle-marked',
table: 'bx bx-table',
Expand Down
1 change: 1 addition & 0 deletions src/public/modules/forms/helpers/field-factory.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ const getClass = (fieldType) => {
case 'textfield':
return TextField
case 'nric':
case 'uen':
case 'yes_no':
return SingleAnswerField
case 'image':
Expand Down
6 changes: 6 additions & 0 deletions src/shared/resources/basic/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,12 @@ export const types: IBasicFieldType[] = [
submitted: true,
answerArray: false,
},
{
name: BasicField.Uen,
value: 'UEN',
submitted: true,
answerArray: false,
},
{
name: BasicField.Table,
value: 'Table',
Expand Down
Loading

0 comments on commit 35eeeaf

Please sign in to comment.