From 9731391515cc94fede5dea2fad233c4156d85436 Mon Sep 17 00:00:00 2001 From: Yuanruo Liang Date: Sat, 20 Feb 2021 16:42:55 +0800 Subject: [PATCH 01/23] refactor: rearrange /adminform/formId route documentation --- src/app/routes/admin-forms.server.routes.js | 153 ++++++++++---------- 1 file changed, 77 insertions(+), 76 deletions(-) diff --git a/src/app/routes/admin-forms.server.routes.js b/src/app/routes/admin-forms.server.routes.js index d7aad31f8a..e2fc6cd29b 100644 --- a/src/app/routes/admin-forms.server.routes.js +++ b/src/app/routes/admin-forms.server.routes.js @@ -61,29 +61,29 @@ module.exports = function (app) { * @property {object} form.required - the form to be created */ - /** - * List the forms managed by the user - * @route GET /adminform - * @group admin - endpoints to manage forms - * @produces application/json - * @returns {Array.} 200 - the forms managed by the user - * @returns {ErrorMessage.model} 400 - error encountered while finding the forms - * @security OTP - */ - /** - * Create a new form in FormSG - * @route POST /adminform - * @group admin - endpoints to manage forms - * @param {FormCreateRequest.model} form.body.required - the form - * @produces application/json - * @returns {object} 200 - the created form - * @returns {ErrorMessage.model} 400 - invalid input - * @returns {ErrorMessage.model} 405 - error encountered while creating the form - * @security OTP - */ app .route('/adminform') + /** + * List the forms managed by the user + * @route GET /adminform + * @group admin - endpoints to manage forms + * @produces application/json + * @returns {Array.} 200 - the forms managed by the user + * @returns {ErrorMessage.model} 400 - error encountered while finding the forms + * @security OTP + */ .get(withUserAuthentication, AdminFormController.handleListDashboardForms) + /** + * Create a new form in FormSG + * @route POST /adminform + * @group admin - endpoints to manage forms + * @param {FormCreateRequest.model} form.body.required - the form + * @produces application/json + * @returns {object} 200 - the created form + * @returns {ErrorMessage.model} 400 - invalid input + * @returns {ErrorMessage.model} 405 - error encountered while creating the form + * @security OTP + */ .post( withUserAuthentication, celebrate({ @@ -130,67 +130,68 @@ module.exports = function (app) { * @property {number} name.required - the number suffix to apply to the duplicated form */ - /** - * Return the specified form to the user - * @route GET /{formId}/adminform - * @group admin - endpoints to manage forms - * @param {string} formId.path.required - the form id - * @produces application/json - * @returns {ErrorMessage.model} 400 - invalid formId - * @returns {ErrorMessage.model} 401 - user not logged in - * @returns {ErrorMessage.model} 403 - user does not have write permission - * @returns {ErrorMessage.model} 404 - form has been archived or form not found - * @returns {AdminForm.model} 200 - the form - * @security OTP - */ - /** - * Update the specified form - * @route PUT /{formId}/adminform - * @group admin - endpoints to manage forms - * @param {string} formId.path.required - the form id - * @produces application/json - * @returns {ErrorMessage.model} 400 - invalid formId - * @returns {ErrorMessage.model} 401 - user not logged in - * @returns {ErrorMessage.model} 403 - user does not have write permission - * @returns {ErrorMessage.model} 404 - form has been archived or form not found - * @returns {ErrorMessage.model} 405 - error encountered while saving the form - * @returns {object} 200 - the updated form - * @security OTP - */ - /** - * Archive the specified form - * @route DELETE /{formId}/adminform - * @group admin - endpoints to manage forms - * @param {string} formId.path.required - the form id - * @produces application/json - * @returns {ErrorMessage.model} 400 - invalid formId - * @returns {ErrorMessage.model} 401 - user not logged in - * @returns {ErrorMessage.model} 403 - user does not have delete permission - * @returns {ErrorMessage.model} 404 - form has been archived or form not found - * @returns {ErrorMessage.model} 405 - error encountered while archiving the form - * @returns {object} 200 - the archived form - * @security OTP - */ - /** - * Duplicate the specified form - * @route POST /{formId}/adminform - * @group admin - endpoints to manage forms - * @param {string} formId.path.required - the form id - * @param {DuplicateRequest.model} name.body.required - the suffix to apply to the duplicated form - * @produces application/json - * @returns {ErrorMessage.model} 400 - error encountered while retrieving the form - * @returns {ErrorMessage.model} 401 - user not logged in - * @returns {ErrorMessage.model} 403 - user does not have write permission - * @returns {ErrorMessage.model} 404 - form has been archived or form not found - * @returns {ErrorMessage.model} 405 - error encountered while duplicating the form - * @returns {object} 200 - the duplicated form - * @security OTP - */ + // Collection of routes that operate on the entire form object app .route('/:formId([a-fA-F0-9]{24})/adminform') + /** + * Return the specified form to the user + * @route GET /{formId}/adminform + * @group admin - endpoints to manage forms + * @param {string} formId.path.required - the form id + * @produces application/json + * @returns {ErrorMessage.model} 400 - invalid formId + * @returns {ErrorMessage.model} 401 - user not logged in + * @returns {ErrorMessage.model} 403 - user does not have write permission + * @returns {ErrorMessage.model} 404 - form has been archived or form not found + * @returns {AdminForm.model} 200 - the form + * @security OTP + */ .get(withUserAuthentication, AdminFormController.handleGetAdminForm) + /** + * Update the specified form + * @route PUT /{formId}/adminform + * @group admin - endpoints to manage forms + * @param {string} formId.path.required - the form id + * @produces application/json + * @returns {ErrorMessage.model} 400 - invalid formId + * @returns {ErrorMessage.model} 401 - user not logged in + * @returns {ErrorMessage.model} 403 - user does not have write permission + * @returns {ErrorMessage.model} 404 - form has been archived or form not found + * @returns {ErrorMessage.model} 405 - error encountered while saving the form + * @returns {object} 200 - the updated form + * @security OTP + */ .put(withUserAuthentication, AdminFormController.handleUpdateForm) + /** + * Archive the specified form + * @route DELETE /{formId}/adminform + * @group admin - endpoints to manage forms + * @param {string} formId.path.required - the form id + * @produces application/json + * @returns {ErrorMessage.model} 400 - invalid formId + * @returns {ErrorMessage.model} 401 - user not logged in + * @returns {ErrorMessage.model} 403 - user does not have delete permission + * @returns {ErrorMessage.model} 404 - form has been archived or form not found + * @returns {ErrorMessage.model} 405 - error encountered while archiving the form + * @returns {object} 200 - the archived form + * @security OTP + */ .delete(withUserAuthentication, AdminFormController.handleArchiveForm) + /** + * Duplicate the specified form + * @route POST /{formId}/adminform + * @group admin - endpoints to manage forms + * @param {string} formId.path.required - the form id + * @param {DuplicateRequest.model} name.body.required - the suffix to apply to the duplicated form + * @produces application/json + * @returns {ErrorMessage.model} 400 - error encountered while retrieving the form + * @returns {ErrorMessage.model} 401 - user not logged in + * @returns {ErrorMessage.model} 403 - user does not have write permission + * @returns {ErrorMessage.model} 404 - form has been archived or form not found + * @returns {ErrorMessage.model} 405 - error encountered while duplicating the form + * @returns {object} 200 - the duplicated form + * @security OTP + */ .post( withUserAuthentication, celebrate({ From 962ac234328269786098b6760ddcf1523efc4891 Mon Sep 17 00:00:00 2001 From: Yuanruo Liang Date: Sat, 20 Feb 2021 17:16:55 +0800 Subject: [PATCH 02/23] refactor(FormLogic): convert from AngularJS service into regular file --- src/public/main.js | 1 - .../edit-logic-modal.client.controller.js | 5 +- .../services/form-logic.client.service.js | 86 ++++++++++--------- 3 files changed, 46 insertions(+), 46 deletions(-) diff --git a/src/public/main.js b/src/public/main.js index dbacf97608..fcef8dfd53 100644 --- a/src/public/main.js +++ b/src/public/main.js @@ -269,7 +269,6 @@ require('./modules/forms/services/submissions.client.factory.js') require('./modules/forms/services/toastr.client.factory.js') require('./modules/forms/services/attachment.client.service.js') require('./modules/forms/services/color-themes.client.service.js') -require('./modules/forms/services/form-logic.client.service.js') require('./modules/forms/services/rating.client.service.js') require('./modules/forms/services/betas.client.factory.js') require('./modules/forms/services/verification.client.factory.js') diff --git a/src/public/modules/forms/admin/controllers/edit-logic-modal.client.controller.js b/src/public/modules/forms/admin/controllers/edit-logic-modal.client.controller.js index 3a2c11989c..da0777dc54 100644 --- a/src/public/modules/forms/admin/controllers/edit-logic-modal.client.controller.js +++ b/src/public/modules/forms/admin/controllers/edit-logic-modal.client.controller.js @@ -2,12 +2,12 @@ const { range } = require('lodash') const { LogicType } = require('../../../../../types') - +const FormLogic = require('../../services/form-logic.client.service') +console.log('FormLogic', FormLogic) angular .module('forms') .controller('EditLogicModalController', [ '$uibModalInstance', - 'FormLogic', 'externalScope', 'updateLogic', 'FormFields', @@ -16,7 +16,6 @@ angular function EditLogicModalController( $uibModalInstance, - FormLogic, externalScope, updateLogic, FormFields, diff --git a/src/public/modules/forms/services/form-logic.client.service.js b/src/public/modules/forms/services/form-logic.client.service.js index f571b9220a..71ad1e168b 100644 --- a/src/public/modules/forms/services/form-logic.client.service.js +++ b/src/public/modules/forms/services/form-logic.client.service.js @@ -1,45 +1,47 @@ -angular.module('forms').service('FormLogic', [FormLogic]) +const conditions = [ + { + fieldType: 'dropdown', + states: ['is equals to', 'is either'], + }, + { + fieldType: 'number', + states: [ + 'is equals to', + 'is less than or equal to', + 'is more than or equal to', + ], + }, + { + fieldType: 'decimal', + states: [ + 'is equals to', + 'is less than or equal to', + 'is more than or equal to', + ], + }, + { + fieldType: 'rating', + states: [ + 'is equals to', + 'is less than or equal to', + 'is more than or equal to', + ], + }, + { + fieldType: 'yes_no', + states: ['is equals to'], + }, + { + fieldType: 'radiobutton', + states: ['is equals to', 'is either'], + }, +] -function FormLogic() { - this.conditions = [ - { - fieldType: 'dropdown', - states: ['is equals to', 'is either'], - }, - { - fieldType: 'number', - states: [ - 'is equals to', - 'is less than or equal to', - 'is more than or equal to', - ], - }, - { - fieldType: 'decimal', - states: [ - 'is equals to', - 'is less than or equal to', - 'is more than or equal to', - ], - }, - { - fieldType: 'rating', - states: [ - 'is equals to', - 'is less than or equal to', - 'is more than or equal to', - ], - }, - { - fieldType: 'yes_no', - states: ['is equals to'], - }, - { - fieldType: 'radiobutton', - states: ['is equals to', 'is either'], - }, - ] - this.fieldTypes = this.conditions.map(function (condition) { +const FormLogic = { + conditions, + fieldTypes: conditions.map(function (condition) { return condition.fieldType - }) + }), } + +module.exports = FormLogic From f8e41b729f56b6421f17f02fd597d7a72eb45afc Mon Sep 17 00:00:00 2001 From: Yuanruo Liang Date: Sat, 20 Feb 2021 17:27:42 +0800 Subject: [PATCH 03/23] refactor(FormLogic): convert fieldtype to enum --- .../edit-logic-modal.client.controller.js | 4 ++-- ...t.service.js => form-logic.client.service.ts} | 16 +++++++++------- 2 files changed, 11 insertions(+), 9 deletions(-) rename src/public/modules/forms/services/{form-logic.client.service.js => form-logic.client.service.ts} (70%) diff --git a/src/public/modules/forms/admin/controllers/edit-logic-modal.client.controller.js b/src/public/modules/forms/admin/controllers/edit-logic-modal.client.controller.js index da0777dc54..e88b76e367 100644 --- a/src/public/modules/forms/admin/controllers/edit-logic-modal.client.controller.js +++ b/src/public/modules/forms/admin/controllers/edit-logic-modal.client.controller.js @@ -2,8 +2,8 @@ const { range } = require('lodash') const { LogicType } = require('../../../../../types') -const FormLogic = require('../../services/form-logic.client.service') -console.log('FormLogic', FormLogic) +const FormLogic = require('../../services/form-logic.client.service').default + angular .module('forms') .controller('EditLogicModalController', [ diff --git a/src/public/modules/forms/services/form-logic.client.service.js b/src/public/modules/forms/services/form-logic.client.service.ts similarity index 70% rename from src/public/modules/forms/services/form-logic.client.service.js rename to src/public/modules/forms/services/form-logic.client.service.ts index 71ad1e168b..110b09cf65 100644 --- a/src/public/modules/forms/services/form-logic.client.service.js +++ b/src/public/modules/forms/services/form-logic.client.service.ts @@ -1,10 +1,12 @@ +import { BasicField } from 'src/types' + const conditions = [ { - fieldType: 'dropdown', + fieldType: BasicField.Dropdown, states: ['is equals to', 'is either'], }, { - fieldType: 'number', + fieldType: BasicField.Number, states: [ 'is equals to', 'is less than or equal to', @@ -12,7 +14,7 @@ const conditions = [ ], }, { - fieldType: 'decimal', + fieldType: BasicField.Decimal, states: [ 'is equals to', 'is less than or equal to', @@ -20,7 +22,7 @@ const conditions = [ ], }, { - fieldType: 'rating', + fieldType: BasicField.Rating, states: [ 'is equals to', 'is less than or equal to', @@ -28,11 +30,11 @@ const conditions = [ ], }, { - fieldType: 'yes_no', + fieldType: BasicField.YesNo, states: ['is equals to'], }, { - fieldType: 'radiobutton', + fieldType: BasicField.Radio, states: ['is equals to', 'is either'], }, ] @@ -44,4 +46,4 @@ const FormLogic = { }), } -module.exports = FormLogic +export default FormLogic From fb80ad10d9bc5f9744f5f55d06f873b009b89bd3 Mon Sep 17 00:00:00 2001 From: Yuanruo Liang Date: Sat, 20 Feb 2021 17:34:04 +0800 Subject: [PATCH 04/23] refactor(FormLogic): convert states to TypeScript --- .../services/form-logic.client.service.ts | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/public/modules/forms/services/form-logic.client.service.ts b/src/public/modules/forms/services/form-logic.client.service.ts index 110b09cf65..05d3cdeec8 100644 --- a/src/public/modules/forms/services/form-logic.client.service.ts +++ b/src/public/modules/forms/services/form-logic.client.service.ts @@ -1,41 +1,41 @@ -import { BasicField } from 'src/types' +import { BasicField, LogicConditionState } from '../../../../types' const conditions = [ { fieldType: BasicField.Dropdown, - states: ['is equals to', 'is either'], + states: [LogicConditionState.Equal, LogicConditionState.Either], }, { fieldType: BasicField.Number, states: [ - 'is equals to', - 'is less than or equal to', - 'is more than or equal to', + LogicConditionState.Equal, + LogicConditionState.Lte, + LogicConditionState.Gte, ], }, { fieldType: BasicField.Decimal, states: [ - 'is equals to', - 'is less than or equal to', - 'is more than or equal to', + LogicConditionState.Equal, + LogicConditionState.Lte, + LogicConditionState.Gte, ], }, { fieldType: BasicField.Rating, states: [ - 'is equals to', - 'is less than or equal to', - 'is more than or equal to', + LogicConditionState.Equal, + LogicConditionState.Lte, + LogicConditionState.Gte, ], }, { fieldType: BasicField.YesNo, - states: ['is equals to'], + states: [LogicConditionState.Equal], }, { fieldType: BasicField.Radio, - states: ['is equals to', 'is either'], + states: [LogicConditionState.Equal, LogicConditionState.Either], }, ] From 64d10102fcb7af7bd80177c00a552eea321caa5d Mon Sep 17 00:00:00 2001 From: Yuanruo Liang Date: Sat, 20 Feb 2021 17:59:07 +0800 Subject: [PATCH 05/23] feat: type the valid logic conditions that are allowed to exist --- .../services/form-logic.client.service.ts | 40 ++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/src/public/modules/forms/services/form-logic.client.service.ts b/src/public/modules/forms/services/form-logic.client.service.ts index 05d3cdeec8..f1db4dcbfe 100644 --- a/src/public/modules/forms/services/form-logic.client.service.ts +++ b/src/public/modules/forms/services/form-logic.client.service.ts @@ -1,6 +1,44 @@ import { BasicField, LogicConditionState } from '../../../../types' -const conditions = [ +type LogicValidConditions = + | { + fieldType: BasicField.Dropdown + states: Array + } + | { + fieldType: BasicField.Number + states: Array< + | LogicConditionState.Equal + | LogicConditionState.Lte + | LogicConditionState.Gte + > + } + | { + fieldType: BasicField.Decimal + states: Array< + | LogicConditionState.Equal + | LogicConditionState.Lte + | LogicConditionState.Gte + > + } + | { + fieldType: BasicField.Rating + states: Array< + | LogicConditionState.Equal + | LogicConditionState.Lte + | LogicConditionState.Gte + > + } + | { + fieldType: BasicField.YesNo + states: Array + } + | { + fieldType: BasicField.Radio + states: Array + } + +const conditions: LogicValidConditions[] = [ { fieldType: BasicField.Dropdown, states: [LogicConditionState.Equal, LogicConditionState.Either], From 6616853e91d4ffd40bc47824f7ed39917f75b211 Mon Sep 17 00:00:00 2001 From: Yuanruo Liang Date: Sat, 20 Feb 2021 18:07:43 +0800 Subject: [PATCH 06/23] refactor: move LogicValidConditions into types folder --- .../services/form-logic.client.service.ts | 44 +++---------------- src/types/form_logic.ts | 39 ++++++++++++++++ 2 files changed, 44 insertions(+), 39 deletions(-) diff --git a/src/public/modules/forms/services/form-logic.client.service.ts b/src/public/modules/forms/services/form-logic.client.service.ts index f1db4dcbfe..69a352cce7 100644 --- a/src/public/modules/forms/services/form-logic.client.service.ts +++ b/src/public/modules/forms/services/form-logic.client.service.ts @@ -1,42 +1,8 @@ -import { BasicField, LogicConditionState } from '../../../../types' - -type LogicValidConditions = - | { - fieldType: BasicField.Dropdown - states: Array - } - | { - fieldType: BasicField.Number - states: Array< - | LogicConditionState.Equal - | LogicConditionState.Lte - | LogicConditionState.Gte - > - } - | { - fieldType: BasicField.Decimal - states: Array< - | LogicConditionState.Equal - | LogicConditionState.Lte - | LogicConditionState.Gte - > - } - | { - fieldType: BasicField.Rating - states: Array< - | LogicConditionState.Equal - | LogicConditionState.Lte - | LogicConditionState.Gte - > - } - | { - fieldType: BasicField.YesNo - states: Array - } - | { - fieldType: BasicField.Radio - states: Array - } +import { + BasicField, + LogicConditionState, + LogicValidConditions, +} from '../../../../types' const conditions: LogicValidConditions[] = [ { diff --git a/src/types/form_logic.ts b/src/types/form_logic.ts index 4f58b95e46..2274e50e63 100644 --- a/src/types/form_logic.ts +++ b/src/types/form_logic.ts @@ -1,6 +1,7 @@ import { Document } from 'mongoose' import { IFieldSchema } from './field/baseField' +import { BasicField } from './field/fieldTypes' export enum LogicConditionState { Equal = 'is equals to', @@ -51,3 +52,41 @@ export interface IPreventSubmitLogic extends ILogic { export interface IPreventSubmitLogicSchema extends IPreventSubmitLogic, Document {} + +export type LogicValidConditions = + | { + fieldType: BasicField.Dropdown + states: Array + } + | { + fieldType: BasicField.Number + states: Array< + | LogicConditionState.Equal + | LogicConditionState.Lte + | LogicConditionState.Gte + > + } + | { + fieldType: BasicField.Decimal + states: Array< + | LogicConditionState.Equal + | LogicConditionState.Lte + | LogicConditionState.Gte + > + } + | { + fieldType: BasicField.Rating + states: Array< + | LogicConditionState.Equal + | LogicConditionState.Lte + | LogicConditionState.Gte + > + } + | { + fieldType: BasicField.YesNo + states: Array + } + | { + fieldType: BasicField.Radio + states: Array + } From 28c9456733e06b5df315ea935f872983c5b78e73 Mon Sep 17 00:00:00 2001 From: Yuanruo Liang Date: Mon, 1 Mar 2021 14:21:33 +0800 Subject: [PATCH 07/23] refactor: rename conditions variable to LOGIC_VALID_CONDITIONS --- .../modules/forms/services/form-logic.client.service.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/public/modules/forms/services/form-logic.client.service.ts b/src/public/modules/forms/services/form-logic.client.service.ts index 69a352cce7..0430b7eea6 100644 --- a/src/public/modules/forms/services/form-logic.client.service.ts +++ b/src/public/modules/forms/services/form-logic.client.service.ts @@ -4,7 +4,7 @@ import { LogicValidConditions, } from '../../../../types' -const conditions: LogicValidConditions[] = [ +const LOGIC_VALID_CONDITIONS: LogicValidConditions[] = [ { fieldType: BasicField.Dropdown, states: [LogicConditionState.Equal, LogicConditionState.Either], @@ -44,8 +44,8 @@ const conditions: LogicValidConditions[] = [ ] const FormLogic = { - conditions, - fieldTypes: conditions.map(function (condition) { + conditions: LOGIC_VALID_CONDITIONS, + fieldTypes: LOGIC_VALID_CONDITIONS.map(function (condition) { return condition.fieldType }), } From 278bca109d812be8bd4eec9d4f57c8199a2bd3bd Mon Sep 17 00:00:00 2001 From: Yuanruo Liang Date: Mon, 1 Mar 2021 16:19:28 +0800 Subject: [PATCH 08/23] refactor: extract getApplicableIfFields --- .../edit-logic-modal.client.controller.js | 4 +--- .../forms/services/form-logic.client.service.ts | 12 +++++++++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/public/modules/forms/admin/controllers/edit-logic-modal.client.controller.js b/src/public/modules/forms/admin/controllers/edit-logic-modal.client.controller.js index e88b76e367..08c6ec756f 100644 --- a/src/public/modules/forms/admin/controllers/edit-logic-modal.client.controller.js +++ b/src/public/modules/forms/admin/controllers/edit-logic-modal.client.controller.js @@ -47,10 +47,8 @@ function EditLogicModalController( vm.getFieldTitle = FormFields.getFieldTitle + vm.ifFields = FormLogic.getApplicableIfFields(vm.myform.form_fields) vm.thenFields = vm.myform.form_fields - vm.ifFields = vm.myform.form_fields.filter((field) => - FormLogic.fieldTypes.includes(field.fieldType), - ) vm.logicTypeSelection = { showFields: diff --git a/src/public/modules/forms/services/form-logic.client.service.ts b/src/public/modules/forms/services/form-logic.client.service.ts index 0430b7eea6..228a35ada2 100644 --- a/src/public/modules/forms/services/form-logic.client.service.ts +++ b/src/public/modules/forms/services/form-logic.client.service.ts @@ -1,5 +1,6 @@ import { BasicField, + IField, LogicConditionState, LogicValidConditions, } from '../../../../types' @@ -43,11 +44,16 @@ const LOGIC_VALID_CONDITIONS: LogicValidConditions[] = [ }, ] +export const getApplicableIfFields = (formFields: IField[]): IField[] => + formFields.filter((field) => + LOGIC_VALID_CONDITIONS.find( + (validCondition) => validCondition.fieldType === field.fieldType, + ), + ) + const FormLogic = { conditions: LOGIC_VALID_CONDITIONS, - fieldTypes: LOGIC_VALID_CONDITIONS.map(function (condition) { - return condition.fieldType - }), + getApplicableIfFields, } export default FormLogic From b49543d656358bb725bf2ca0988236ff72200877 Mon Sep 17 00:00:00 2001 From: Yuanruo Liang Date: Mon, 8 Mar 2021 12:52:35 +0800 Subject: [PATCH 09/23] refactor: remove export default and add JSDocs --- .../edit-logic-modal.client.controller.js | 2 +- .../forms/services/form-logic.client.service.ts | 13 +++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/public/modules/forms/admin/controllers/edit-logic-modal.client.controller.js b/src/public/modules/forms/admin/controllers/edit-logic-modal.client.controller.js index 08c6ec756f..a3aed2fb2f 100644 --- a/src/public/modules/forms/admin/controllers/edit-logic-modal.client.controller.js +++ b/src/public/modules/forms/admin/controllers/edit-logic-modal.client.controller.js @@ -2,7 +2,7 @@ const { range } = require('lodash') const { LogicType } = require('../../../../../types') -const FormLogic = require('../../services/form-logic.client.service').default +const FormLogic = require('../../services/form-logic.client.service') angular .module('forms') diff --git a/src/public/modules/forms/services/form-logic.client.service.ts b/src/public/modules/forms/services/form-logic.client.service.ts index 228a35ada2..35b5aebc0c 100644 --- a/src/public/modules/forms/services/form-logic.client.service.ts +++ b/src/public/modules/forms/services/form-logic.client.service.ts @@ -44,6 +44,12 @@ const LOGIC_VALID_CONDITIONS: LogicValidConditions[] = [ }, ] +/** + * Given a list of form fields, returns only the elements that are + * allowed to be present in the if-condition dropdown in the Logic tab. + * @param formFields + * @returns + */ export const getApplicableIfFields = (formFields: IField[]): IField[] => formFields.filter((field) => LOGIC_VALID_CONDITIONS.find( @@ -51,9 +57,4 @@ export const getApplicableIfFields = (formFields: IField[]): IField[] => ), ) -const FormLogic = { - conditions: LOGIC_VALID_CONDITIONS, - getApplicableIfFields, -} - -export default FormLogic +export const conditions = LOGIC_VALID_CONDITIONS From 12acb2e9fa307c893f9018ac1c0be371f5c00e2d Mon Sep 17 00:00:00 2001 From: Yuanruo Liang Date: Mon, 8 Mar 2021 13:06:05 +0800 Subject: [PATCH 10/23] refactor: extract getApplicableIfStates --- .../edit-logic-modal.client.controller.js | 6 +++--- .../forms/services/form-logic.client.service.ts | 14 ++++++++++++++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/public/modules/forms/admin/controllers/edit-logic-modal.client.controller.js b/src/public/modules/forms/admin/controllers/edit-logic-modal.client.controller.js index a3aed2fb2f..20508a7ed1 100644 --- a/src/public/modules/forms/admin/controllers/edit-logic-modal.client.controller.js +++ b/src/public/modules/forms/admin/controllers/edit-logic-modal.client.controller.js @@ -146,9 +146,9 @@ function EditLogicModalController( } condition.fieldInfo = externalScope.getField(condition.field) if (condition.fieldInfo) { - condition.ifStates = FormLogic.conditions.find(function (c) { - return c.fieldType === condition.fieldInfo.fieldType - }).states + condition.ifStates = FormLogic.getApplicableIfStates( + condition.fieldInfo.fieldType, + ) } } diff --git a/src/public/modules/forms/services/form-logic.client.service.ts b/src/public/modules/forms/services/form-logic.client.service.ts index 35b5aebc0c..8cd8c3b84c 100644 --- a/src/public/modules/forms/services/form-logic.client.service.ts +++ b/src/public/modules/forms/services/form-logic.client.service.ts @@ -57,4 +57,18 @@ export const getApplicableIfFields = (formFields: IField[]): IField[] => ), ) +/** + * Given a form field type, returns the applicable logic states for that field. + * @param formFields + * @returns + */ +export const getApplicableIfStates = ( + fieldType: BasicField, +): LogicConditionState[] => { + const condition = LOGIC_VALID_CONDITIONS.find( + (c) => c.fieldType === fieldType, + ) + return condition ? condition.states : [] +} + export const conditions = LOGIC_VALID_CONDITIONS From 772ee1adab2c6760ae39e819f87553e01ecd5fb3 Mon Sep 17 00:00:00 2001 From: Yuanruo Liang Date: Mon, 8 Mar 2021 13:10:18 +0800 Subject: [PATCH 11/23] refactor: remove unnecessary LogicFieldArray type --- src/shared/util/logic.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/shared/util/logic.ts b/src/shared/util/logic.ts index 4aac238e41..1beaa7ad71 100644 --- a/src/shared/util/logic.ts +++ b/src/shared/util/logic.ts @@ -15,7 +15,6 @@ type FieldIdSet = Set // This module handles logic on both the client side (IFieldSchema[]) // and server side (FieldResponse[]) type LogicField = IClientFieldSchema | FieldResponse -type LogicFieldArray = LogicField[] // Returns typed ShowFields logic unit const isShowFieldsLogic = ( @@ -125,7 +124,7 @@ const getPreventSubmitConditions = ( * @returns a condition if submission is to prevented, otherwise `undefined` */ export const getLogicUnitPreventingSubmit = ( - submission: LogicFieldArray, + submission: LogicField[], form: IFormDocument, visibleFieldIds?: FieldIdSet, ): IPreventSubmitLogicSchema | undefined => { @@ -164,7 +163,7 @@ const allConditionsExist = ( * @returns a set of IDs of visible fields in the submission */ export const getVisibleFieldIds = ( - submission: LogicFieldArray, + submission: LogicField[], form: IFormDocument, ): FieldIdSet => { const logicUnitsGroupedByField = groupLogicUnitsByField(form) @@ -206,7 +205,7 @@ export const getVisibleFieldIds = ( * @returns true if all the conditions are satisfied, false otherwise */ const isLogicUnitSatisfied = ( - submission: LogicFieldArray, + submission: LogicField[], logicUnit: IConditionSchema[], visibleFieldIds: FieldIdSet, ): boolean => { @@ -307,7 +306,7 @@ const isConditionFulfilled = ( * @returns the condition field if it exists, `undefined` otherwise */ const findConditionField = ( - submission: LogicFieldArray, + submission: LogicField[], fieldId: IConditionSchema['field'], ): LogicField | undefined => { return submission.find( From 3c675552a6e15b5bb7f72670c433048b54a821ad Mon Sep 17 00:00:00 2001 From: Yuanruo Liang Date: Mon, 8 Mar 2021 13:13:37 +0800 Subject: [PATCH 12/23] refactor: rename LogicField to LogicFieldSchemaOrResponse --- src/shared/util/logic.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/shared/util/logic.ts b/src/shared/util/logic.ts index 1beaa7ad71..2685a1501b 100644 --- a/src/shared/util/logic.ts +++ b/src/shared/util/logic.ts @@ -14,7 +14,7 @@ type GroupedLogic = Record type FieldIdSet = Set // This module handles logic on both the client side (IFieldSchema[]) // and server side (FieldResponse[]) -type LogicField = IClientFieldSchema | FieldResponse +type LogicFieldSchemaOrResponse = IClientFieldSchema | FieldResponse // Returns typed ShowFields logic unit const isShowFieldsLogic = ( @@ -124,7 +124,7 @@ const getPreventSubmitConditions = ( * @returns a condition if submission is to prevented, otherwise `undefined` */ export const getLogicUnitPreventingSubmit = ( - submission: LogicField[], + submission: LogicFieldSchemaOrResponse[], form: IFormDocument, visibleFieldIds?: FieldIdSet, ): IPreventSubmitLogicSchema | undefined => { @@ -163,7 +163,7 @@ const allConditionsExist = ( * @returns a set of IDs of visible fields in the submission */ export const getVisibleFieldIds = ( - submission: LogicField[], + submission: LogicFieldSchemaOrResponse[], form: IFormDocument, ): FieldIdSet => { const logicUnitsGroupedByField = groupLogicUnitsByField(form) @@ -205,7 +205,7 @@ export const getVisibleFieldIds = ( * @returns true if all the conditions are satisfied, false otherwise */ const isLogicUnitSatisfied = ( - submission: LogicField[], + submission: LogicFieldSchemaOrResponse[], logicUnit: IConditionSchema[], visibleFieldIds: FieldIdSet, ): boolean => { @@ -220,7 +220,7 @@ const isLogicUnitSatisfied = ( } const getCurrentValue = ( - field: LogicField, + field: LogicFieldSchemaOrResponse, ): string | null | undefined | string[] => { if ('fieldValue' in field) { // client @@ -238,7 +238,7 @@ const getCurrentValue = ( * @param {String} condition.state - The type of condition */ const isConditionFulfilled = ( - field: LogicField, + field: LogicFieldSchemaOrResponse, condition: IConditionSchema, ): boolean => { if (!field || !condition) { @@ -306,9 +306,9 @@ const isConditionFulfilled = ( * @returns the condition field if it exists, `undefined` otherwise */ const findConditionField = ( - submission: LogicField[], + submission: LogicFieldSchemaOrResponse[], fieldId: IConditionSchema['field'], -): LogicField | undefined => { +): LogicFieldSchemaOrResponse | undefined => { return submission.find( (submittedField) => String(submittedField._id) === String(fieldId), ) From f96af78a100e7b3b911ec333835210818176db47 Mon Sep 17 00:00:00 2001 From: Yuanruo Liang Date: Mon, 8 Mar 2021 13:52:37 +0800 Subject: [PATCH 13/23] refactor: extract LogicValidCondition type into a generic --- src/types/form_logic.ts | 71 ++++++++++++++++++++--------------------- 1 file changed, 35 insertions(+), 36 deletions(-) diff --git a/src/types/form_logic.ts b/src/types/form_logic.ts index 2274e50e63..77678843dc 100644 --- a/src/types/form_logic.ts +++ b/src/types/form_logic.ts @@ -53,40 +53,39 @@ export interface IPreventSubmitLogicSchema extends IPreventSubmitLogic, Document {} +type LogicValidCondition< + F extends BasicField, + S extends LogicConditionState +> = { + fieldType: F + states: Array +} + export type LogicValidConditions = - | { - fieldType: BasicField.Dropdown - states: Array - } - | { - fieldType: BasicField.Number - states: Array< - | LogicConditionState.Equal - | LogicConditionState.Lte - | LogicConditionState.Gte - > - } - | { - fieldType: BasicField.Decimal - states: Array< - | LogicConditionState.Equal - | LogicConditionState.Lte - | LogicConditionState.Gte - > - } - | { - fieldType: BasicField.Rating - states: Array< - | LogicConditionState.Equal - | LogicConditionState.Lte - | LogicConditionState.Gte - > - } - | { - fieldType: BasicField.YesNo - states: Array - } - | { - fieldType: BasicField.Radio - states: Array - } + | LogicValidCondition< + BasicField.Dropdown, + LogicConditionState.Equal | LogicConditionState.Either + > + | LogicValidCondition + | LogicValidCondition< + BasicField.Radio, + LogicConditionState.Equal | LogicConditionState.Either + > + | LogicValidCondition< + BasicField.Number, + | LogicConditionState.Equal + | LogicConditionState.Lte + | LogicConditionState.Gte + > + | LogicValidCondition< + BasicField.Decimal, + | LogicConditionState.Equal + | LogicConditionState.Lte + | LogicConditionState.Gte + > + | LogicValidCondition< + BasicField.Rating, + | LogicConditionState.Equal + | LogicConditionState.Lte + | LogicConditionState.Gte + > From fc7dc2575e934ead46ff3849cbda017b852ce843 Mon Sep 17 00:00:00 2001 From: Yuanruo Liang Date: Mon, 8 Mar 2021 13:57:47 +0800 Subject: [PATCH 14/23] refactor: extract LogicField --- src/types/form_logic.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/types/form_logic.ts b/src/types/form_logic.ts index 77678843dc..c341f31459 100644 --- a/src/types/form_logic.ts +++ b/src/types/form_logic.ts @@ -53,8 +53,18 @@ export interface IPreventSubmitLogicSchema extends IPreventSubmitLogic, Document {} +type LogicField = Extract< + BasicField, + | BasicField.Dropdown + | BasicField.Radio + | BasicField.YesNo + | BasicField.Number + | BasicField.Decimal + | BasicField.Rating +> + type LogicValidCondition< - F extends BasicField, + F extends LogicField, S extends LogicConditionState > = { fieldType: F From fa0e53eb7b2cd8cf73c31b38513f3251c6b4eab5 Mon Sep 17 00:00:00 2001 From: Yuanruo Liang Date: Mon, 8 Mar 2021 14:31:37 +0800 Subject: [PATCH 15/23] refactor: separate logic conditions into categorical, binary and numerical --- src/types/form_logic.ts | 67 ++++++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 31 deletions(-) diff --git a/src/types/form_logic.ts b/src/types/form_logic.ts index c341f31459..d95a9e7abe 100644 --- a/src/types/form_logic.ts +++ b/src/types/form_logic.ts @@ -63,39 +63,44 @@ type LogicField = Extract< | BasicField.Rating > -type LogicValidCondition< - F extends LogicField, - S extends LogicConditionState -> = { +type LogicCondition = { fieldType: F states: Array } +// Logic fields that are categorical +type CategoricalLogicField = Extract< + BasicField, + BasicField.Dropdown | BasicField.Radio +> +type CategoricalLogicStates = + | LogicConditionState.Equal + | LogicConditionState.Either +type CategoricalLogicCondition = LogicCondition< + CategoricalLogicField, + CategoricalLogicStates +> + +// Logic fields that are boolean +type BinaryLogicField = Extract +type BinaryLogicStates = LogicConditionState.Equal +type BinaryLogicCondition = LogicCondition + +// Logic fields that can be numerically compared +type NumericalLogicField = Extract< + BasicField, + BasicField.Number | BasicField.Decimal | BasicField.Rating +> +type NumericalLogicStates = + | LogicConditionState.Equal + | LogicConditionState.Lte + | LogicConditionState.Gte +type NumericalLogicCondition = LogicCondition< + NumericalLogicField, + NumericalLogicStates +> + export type LogicValidConditions = - | LogicValidCondition< - BasicField.Dropdown, - LogicConditionState.Equal | LogicConditionState.Either - > - | LogicValidCondition - | LogicValidCondition< - BasicField.Radio, - LogicConditionState.Equal | LogicConditionState.Either - > - | LogicValidCondition< - BasicField.Number, - | LogicConditionState.Equal - | LogicConditionState.Lte - | LogicConditionState.Gte - > - | LogicValidCondition< - BasicField.Decimal, - | LogicConditionState.Equal - | LogicConditionState.Lte - | LogicConditionState.Gte - > - | LogicValidCondition< - BasicField.Rating, - | LogicConditionState.Equal - | LogicConditionState.Lte - | LogicConditionState.Gte - > + | CategoricalLogicCondition + | BinaryLogicCondition + | NumericalLogicCondition From 58b2a88b31c7a0d78cca12c81addd34eb466b25d Mon Sep 17 00:00:00 2001 From: Yuanruo Liang Date: Mon, 8 Mar 2021 16:15:23 +0800 Subject: [PATCH 16/23] refactor: type to an Array representation in order to construct a Map --- .../services/form-logic.client.service.ts | 73 +++++++------------ src/types/form_logic.ts | 10 +-- 2 files changed, 33 insertions(+), 50 deletions(-) diff --git a/src/public/modules/forms/services/form-logic.client.service.ts b/src/public/modules/forms/services/form-logic.client.service.ts index 8cd8c3b84c..13b0757d5e 100644 --- a/src/public/modules/forms/services/form-logic.client.service.ts +++ b/src/public/modules/forms/services/form-logic.client.service.ts @@ -1,74 +1,57 @@ import { BasicField, IField, + LogicConditions, LogicConditionState, - LogicValidConditions, } from '../../../../types' -const LOGIC_VALID_CONDITIONS: LogicValidConditions[] = [ - { - fieldType: BasicField.Dropdown, - states: [LogicConditionState.Equal, LogicConditionState.Either], - }, - { - fieldType: BasicField.Number, - states: [ +const LOGIC_VALID_CONDITIONS: LogicConditions[] = [ + [ + BasicField.Dropdown, + [LogicConditionState.Equal, LogicConditionState.Either], + ], + [ + BasicField.Number, + [ LogicConditionState.Equal, LogicConditionState.Lte, LogicConditionState.Gte, ], - }, - { - fieldType: BasicField.Decimal, - states: [ + ], + [ + BasicField.Decimal, + [ LogicConditionState.Equal, LogicConditionState.Lte, LogicConditionState.Gte, ], - }, - { - fieldType: BasicField.Rating, - states: [ + ], + [ + BasicField.Rating, + [ LogicConditionState.Equal, LogicConditionState.Lte, LogicConditionState.Gte, ], - }, - { - fieldType: BasicField.YesNo, - states: [LogicConditionState.Equal], - }, - { - fieldType: BasicField.Radio, - states: [LogicConditionState.Equal, LogicConditionState.Either], - }, + ], + [BasicField.YesNo, [LogicConditionState.Equal]], + [BasicField.Radio, [LogicConditionState.Equal, LogicConditionState.Either]], ] +const LOGIC_MAP = new Map( + LOGIC_VALID_CONDITIONS, +) + /** - * Given a list of form fields, returns only the elements that are + * Given a list of form fields, returns only the fields that are * allowed to be present in the if-condition dropdown in the Logic tab. - * @param formFields - * @returns */ export const getApplicableIfFields = (formFields: IField[]): IField[] => - formFields.filter((field) => - LOGIC_VALID_CONDITIONS.find( - (validCondition) => validCondition.fieldType === field.fieldType, - ), - ) + formFields.filter((field) => !!LOGIC_MAP.get(field.fieldType)) /** - * Given a form field type, returns the applicable logic states for that field. - * @param formFields - * @returns + * Given a single form field type, returns the applicable logic states for that field type. */ export const getApplicableIfStates = ( fieldType: BasicField, -): LogicConditionState[] => { - const condition = LOGIC_VALID_CONDITIONS.find( - (c) => c.fieldType === fieldType, - ) - return condition ? condition.states : [] -} - -export const conditions = LOGIC_VALID_CONDITIONS +): LogicConditionState[] => LOGIC_MAP.get(fieldType) || [] diff --git a/src/types/form_logic.ts b/src/types/form_logic.ts index d95a9e7abe..5d3ed979cc 100644 --- a/src/types/form_logic.ts +++ b/src/types/form_logic.ts @@ -63,10 +63,10 @@ type LogicField = Extract< | BasicField.Rating > -type LogicCondition = { - fieldType: F - states: Array -} +type LogicCondition = [ + K, + Array, +] // Logic fields that are categorical type CategoricalLogicField = Extract< @@ -100,7 +100,7 @@ type NumericalLogicCondition = LogicCondition< NumericalLogicStates > -export type LogicValidConditions = +export type LogicConditions = | CategoricalLogicCondition | BinaryLogicCondition | NumericalLogicCondition From a5823aa43e4731cb49fa5cdf57b1afe3edea4617 Mon Sep 17 00:00:00 2001 From: Yuanruo Liang Date: Tue, 9 Mar 2021 10:25:10 +0800 Subject: [PATCH 17/23] refactor: move into form-logic folder --- .../admin/controllers/edit-logic-modal.client.controller.js | 2 +- .../services/{ => form-logic}/form-logic.client.service.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename src/public/modules/forms/services/{ => form-logic}/form-logic.client.service.ts (97%) diff --git a/src/public/modules/forms/admin/controllers/edit-logic-modal.client.controller.js b/src/public/modules/forms/admin/controllers/edit-logic-modal.client.controller.js index 20508a7ed1..d3a817f195 100644 --- a/src/public/modules/forms/admin/controllers/edit-logic-modal.client.controller.js +++ b/src/public/modules/forms/admin/controllers/edit-logic-modal.client.controller.js @@ -2,7 +2,7 @@ const { range } = require('lodash') const { LogicType } = require('../../../../../types') -const FormLogic = require('../../services/form-logic.client.service') +const FormLogic = require('../../services/form-logic/form-logic.client.service') angular .module('forms') diff --git a/src/public/modules/forms/services/form-logic.client.service.ts b/src/public/modules/forms/services/form-logic/form-logic.client.service.ts similarity index 97% rename from src/public/modules/forms/services/form-logic.client.service.ts rename to src/public/modules/forms/services/form-logic/form-logic.client.service.ts index 13b0757d5e..4a00e2d84a 100644 --- a/src/public/modules/forms/services/form-logic.client.service.ts +++ b/src/public/modules/forms/services/form-logic/form-logic.client.service.ts @@ -3,7 +3,7 @@ import { IField, LogicConditions, LogicConditionState, -} from '../../../../types' +} from '../../../../../types' const LOGIC_VALID_CONDITIONS: LogicConditions[] = [ [ From ec90f69347e6690c1c1e1937fc737c13d3b997ae Mon Sep 17 00:00:00 2001 From: Yuanruo Liang Date: Tue, 9 Mar 2021 11:17:46 +0800 Subject: [PATCH 18/23] build(jest-extended): installation and configuration --- jest.config.js | 1 + package-lock.json | 359 ++++++++++++++++++++++++++++ package.json | 1 + src/types/vendor/jest-extended.d.ts | 1 + tests/unit/frontend/jest.config.js | 1 + 5 files changed, 363 insertions(+) create mode 100644 src/types/vendor/jest-extended.d.ts diff --git a/jest.config.js b/jest.config.js index e913bc9c03..570da92d1c 100644 --- a/jest.config.js +++ b/jest.config.js @@ -24,4 +24,5 @@ module.exports = { isolatedModules: true, }, }, + setupFilesAfterEnv: ['jest-extended'], } diff --git a/package-lock.json b/package-lock.json index dda0474292..fe9edc85d7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14286,6 +14286,365 @@ "jest-util": "^26.6.2" } }, + "jest-extended": { + "version": "0.11.5", + "resolved": "https://registry.npmjs.org/jest-extended/-/jest-extended-0.11.5.tgz", + "integrity": "sha512-3RsdFpLWKScpsLD6hJuyr/tV5iFOrw7v6YjA3tPdda9sJwoHwcMROws5gwiIZfcwhHlJRwFJB2OUvGmF3evV/Q==", + "dev": true, + "requires": { + "expect": "^24.1.0", + "jest-get-type": "^22.4.3", + "jest-matcher-utils": "^22.0.0" + }, + "dependencies": { + "@jest/console": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-24.9.0.tgz", + "integrity": "sha512-Zuj6b8TnKXi3q4ymac8EQfc3ea/uhLeCGThFqXeC8H9/raaH8ARPUTdId+XyGd03Z4In0/VjD2OYFcBF09fNLQ==", + "dev": true, + "requires": { + "@jest/source-map": "^24.9.0", + "chalk": "^2.0.1", + "slash": "^2.0.0" + } + }, + "@jest/source-map": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-24.9.0.tgz", + "integrity": "sha512-/Xw7xGlsZb4MJzNDgB7PW5crou5JqWiBQaz6xyPd3ArOg2nfn/PunV8+olXbbEZzNl591o5rWKE9BRDaFAuIBg==", + "dev": true, + "requires": { + "callsites": "^3.0.0", + "graceful-fs": "^4.1.15", + "source-map": "^0.6.0" + } + }, + "@jest/test-result": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-24.9.0.tgz", + "integrity": "sha512-XEFrHbBonBJ8dGp2JmF8kP/nQI/ImPpygKHwQ/SY+es59Z3L5PI4Qb9TQQMAEeYsThG1xF0k6tmG0tIKATNiiA==", + "dev": true, + "requires": { + "@jest/console": "^24.9.0", + "@jest/types": "^24.9.0", + "@types/istanbul-lib-coverage": "^2.0.0" + } + }, + "@jest/types": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", + "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^1.1.1", + "@types/yargs": "^13.0.0" + } + }, + "@types/istanbul-reports": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-1.1.2.tgz", + "integrity": "sha512-P/W9yOX/3oPZSpaYOCQzGqgCQRXn0FFO/V8bWrCQs+wLmvVVxk6CRBXALEvNs9OHIatlnlFokfhuDo2ug01ciw==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "*", + "@types/istanbul-lib-report": "*" + } + }, + "@types/stack-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-1.0.1.tgz", + "integrity": "sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw==", + "dev": true + }, + "@types/yargs": { + "version": "13.0.11", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.11.tgz", + "integrity": "sha512-NRqD6T4gktUrDi1o1wLH3EKC1o2caCr7/wR87ODcbVITQF106OM3sFN92ysZ++wqelOd1CTzatnOBRDYYG6wGQ==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "diff-sequences": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-24.9.0.tgz", + "integrity": "sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew==", + "dev": true + }, + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true + }, + "expect": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-24.9.0.tgz", + "integrity": "sha512-wvVAx8XIol3Z5m9zvZXiyZOQ+sRJqNTIm6sGjdWlaZIeupQGO3WbYI+15D/AmEwZywL6wtJkbAbJtzkOfBuR0Q==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "ansi-styles": "^3.2.0", + "jest-get-type": "^24.9.0", + "jest-matcher-utils": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-regex-util": "^24.9.0" + }, + "dependencies": { + "jest-get-type": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.9.0.tgz", + "integrity": "sha512-lUseMzAley4LhIcpSP9Jf+fTrQ4a1yHQwLNeeVa2cEmbCGeoZAtYPOIv8JaxLD/sUpKxetKGP+gsHl8f8TSj8Q==", + "dev": true + }, + "jest-matcher-utils": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-24.9.0.tgz", + "integrity": "sha512-OZz2IXsu6eaiMAwe67c1T+5tUAtQyQx27/EMEkbFAGiw52tB9em+uGbzpcgYVpA8wl0hlxKPZxrly4CXU/GjHA==", + "dev": true, + "requires": { + "chalk": "^2.0.1", + "jest-diff": "^24.9.0", + "jest-get-type": "^24.9.0", + "pretty-format": "^24.9.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "jest-diff": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-24.9.0.tgz", + "integrity": "sha512-qMfrTs8AdJE2iqrTp0hzh7kTd2PQWrsFyj9tORoKmu32xjPjeE4NyjVRDz8ybYwqS2ik8N4hsIpiVTyFeo2lBQ==", + "dev": true, + "requires": { + "chalk": "^2.0.1", + "diff-sequences": "^24.9.0", + "jest-get-type": "^24.9.0", + "pretty-format": "^24.9.0" + }, + "dependencies": { + "jest-get-type": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.9.0.tgz", + "integrity": "sha512-lUseMzAley4LhIcpSP9Jf+fTrQ4a1yHQwLNeeVa2cEmbCGeoZAtYPOIv8JaxLD/sUpKxetKGP+gsHl8f8TSj8Q==", + "dev": true + } + } + }, + "jest-get-type": { + "version": "22.4.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-22.4.3.tgz", + "integrity": "sha512-/jsz0Y+V29w1chdXVygEKSz2nBoHoYqNShPe+QgxSNjAuP1i8+k4LbQNrfoliKej0P45sivkSCh7yiD6ubHS3w==", + "dev": true + }, + "jest-matcher-utils": { + "version": "22.4.3", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-22.4.3.tgz", + "integrity": "sha512-lsEHVaTnKzdAPR5t4B6OcxXo9Vy4K+kRRbG5gtddY8lBEC+Mlpvm1CJcsMESRjzUhzkz568exMV1hTB76nAKbA==", + "dev": true, + "requires": { + "chalk": "^2.0.1", + "jest-get-type": "^22.4.3", + "pretty-format": "^22.4.3" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "pretty-format": { + "version": "22.4.3", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-22.4.3.tgz", + "integrity": "sha512-S4oT9/sT6MN7/3COoOy+ZJeA92VmOnveLHgrwBE3Z1W5N9S2A1QGNYiE1z75DAENbJrXXUb+OWXhpJcg05QKQQ==", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0", + "ansi-styles": "^3.2.0" + } + } + } + }, + "jest-message-util": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-24.9.0.tgz", + "integrity": "sha512-oCj8FiZ3U0hTP4aSui87P4L4jC37BtQwUMqk+zk/b11FR19BJDeZsZAvIHutWnmtw7r85UmR3CEWZ0HWU2mAlw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", + "@types/stack-utils": "^1.0.1", + "chalk": "^2.0.1", + "micromatch": "^3.1.10", + "slash": "^2.0.0", + "stack-utils": "^1.0.1" + } + }, + "jest-regex-util": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-24.9.0.tgz", + "integrity": "sha512-05Cmb6CuxaA+Ys6fjr3PhvV3bGQmO+2p2La4hFbU+W5uOc479f7FdLXUWXw4pYMAhhSZIuKHwSXSu6CsSBAXQA==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "pretty-format": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.9.0.tgz", + "integrity": "sha512-00ZMZUiHaJrNfk33guavqgvfJS30sLYf0f8+Srklv0AMPodGGHcoHgksZ3OThYnIvOd+8yMCn0YiEOogjlgsnA==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "ansi-regex": "^4.0.0", + "ansi-styles": "^3.2.0", + "react-is": "^16.8.4" + } + }, + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "stack-utils": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-1.0.4.tgz", + "integrity": "sha512-IPDJfugEGbfizBwBZRZ3xpccMdRyP5lqsBWXGQWimVjua/ccLCeMOAVjlc1R7LxFjo5sEDhyNIXd8mo/AiDS9w==", + "dev": true, + "requires": { + "escape-string-regexp": "^2.0.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + } + } + }, "jest-get-type": { "version": "26.3.0", "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-26.3.0.tgz", diff --git a/package.json b/package.json index 72e8036ea3..3270688f90 100644 --- a/package.json +++ b/package.json @@ -225,6 +225,7 @@ "jasmine-sinon": "^0.4.0", "jasmine-spec-reporter": "^6.0.0", "jest": "^26.6.3", + "jest-extended": "^0.11.5", "jest-mock-axios": "^4.3.0", "lint-staged": "^10.5.4", "maildev": "^1.1.0", diff --git a/src/types/vendor/jest-extended.d.ts b/src/types/vendor/jest-extended.d.ts new file mode 100644 index 0000000000..b68ae07700 --- /dev/null +++ b/src/types/vendor/jest-extended.d.ts @@ -0,0 +1 @@ +import 'jest-extended' diff --git a/tests/unit/frontend/jest.config.js b/tests/unit/frontend/jest.config.js index b1e655ce2d..17526446ae 100644 --- a/tests/unit/frontend/jest.config.js +++ b/tests/unit/frontend/jest.config.js @@ -11,4 +11,5 @@ module.exports = { }, }, clearMocks: true, + setupFilesAfterEnv: ['jest-extended'], } From 4c146f366219c915a3b9152009d02f2acb88f94a Mon Sep 17 00:00:00 2001 From: Yuanruo Liang Date: Tue, 9 Mar 2021 11:36:05 +0800 Subject: [PATCH 19/23] test: write tests --- .../form-logic.client.service.spec.ts | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 src/public/modules/forms/services/form-logic/__tests__/form-logic.client.service.spec.ts diff --git a/src/public/modules/forms/services/form-logic/__tests__/form-logic.client.service.spec.ts b/src/public/modules/forms/services/form-logic/__tests__/form-logic.client.service.spec.ts new file mode 100644 index 0000000000..fc5b46512b --- /dev/null +++ b/src/public/modules/forms/services/form-logic/__tests__/form-logic.client.service.spec.ts @@ -0,0 +1,78 @@ +import { + BasicField, + IField, + LogicConditionState, +} from '../../../../../../types' +import * as FormLogic from '../form-logic.client.service' + +const VALID_IF_CONDITION_FIELDS = [ + BasicField.Dropdown, + BasicField.Number, + BasicField.Decimal, + BasicField.Rating, + BasicField.YesNo, + BasicField.Radio, +] + +const INVALID_IF_CONDITION_FIELDS = Object.values(BasicField).filter( + (fieldType) => !VALID_IF_CONDITION_FIELDS.includes(fieldType), +) +describe('form-logic.client.service', () => { + describe('getApplicableIfFields', () => { + it('should not filter fields suitable as an if-conditional', () => { + const validIfFields: IField[] = VALID_IF_CONDITION_FIELDS.map( + (fieldType) => (({ fieldType } as unknown) as IField), + ) + const fields = FormLogic.getApplicableIfFields(validIfFields) + validIfFields.forEach((v, i) => expect(v).toStrictEqual(fields[i])) + }) + it('should filter fields not suitable as an if-conditional', () => { + const invalidIfFields: IField[] = INVALID_IF_CONDITION_FIELDS.map( + (x) => (x as unknown) as IField, + ) + const fields = FormLogic.getApplicableIfFields(invalidIfFields) + expect(fields).toStrictEqual([]) + }) + }) + + describe('getApplicableIfStates', () => { + it('should return valid logic states for categorical field types', () => { + const categoricalFields = [BasicField.Dropdown, BasicField.Radio] + categoricalFields.forEach((fieldType) => { + const states = FormLogic.getApplicableIfStates(fieldType) + expect(states).toIncludeSameMembers([ + LogicConditionState.Equal, + LogicConditionState.Either, + ]) + expect(states).toBeArrayOfSize(2) + }) + }) + it('should return valid logic states for binary field types', () => { + const states = FormLogic.getApplicableIfStates(BasicField.YesNo) + expect(states).toIncludeSameMembers([LogicConditionState.Equal]) + expect(states).toBeArrayOfSize(1) + }) + it('should return valid logic states for numerical field types', () => { + const numericalFields = [ + BasicField.Number, + BasicField.Decimal, + BasicField.Rating, + ] + numericalFields.forEach((fieldType) => { + const states = FormLogic.getApplicableIfStates(fieldType) + expect(states).toIncludeSameMembers([ + LogicConditionState.Equal, + LogicConditionState.Lte, + LogicConditionState.Gte, + ]) + expect(states).toBeArrayOfSize(3) + }) + }) + it('should return empty array for invalid conditional fields', () => { + INVALID_IF_CONDITION_FIELDS.forEach((fieldType) => { + const states = FormLogic.getApplicableIfStates(fieldType) + expect(states).toStrictEqual([]) + }) + }) + }) +}) From ca8c4e35cb1cdbbdb7e8f1c55b9614b6cdde5ecf Mon Sep 17 00:00:00 2001 From: Yuanruo Liang Date: Tue, 9 Mar 2021 12:04:23 +0800 Subject: [PATCH 20/23] fix: exclude tests from frontend build --- ts-loader-config.json | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/ts-loader-config.json b/ts-loader-config.json index 293ff88e66..4de2db59c7 100644 --- a/ts-loader-config.json +++ b/ts-loader-config.json @@ -60,5 +60,11 @@ "skipLibCheck": true, /* Skip type checking of declaration files. */ "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ }, - "include": ["src/public", "src/shared"] + "include": ["src/public", "src/shared"], + "exclude": [ + "tests/", + "**/*.spec.ts", + "**/*.test.ts", + "**/__tests__/" + ] } From 30fa0137b9b22f9a803984bc087df68dbe914bd1 Mon Sep 17 00:00:00 2001 From: Yuanruo Liang Date: Tue, 9 Mar 2021 16:05:37 +0800 Subject: [PATCH 21/23] refactor: rename LOGIC_CONDITIONS variable, PossibleLogicCondition type --- .../services/form-logic/form-logic.client.service.ts | 8 +++----- src/types/form_logic.ts | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/public/modules/forms/services/form-logic/form-logic.client.service.ts b/src/public/modules/forms/services/form-logic/form-logic.client.service.ts index 4a00e2d84a..6ac6897ee8 100644 --- a/src/public/modules/forms/services/form-logic/form-logic.client.service.ts +++ b/src/public/modules/forms/services/form-logic/form-logic.client.service.ts @@ -1,11 +1,11 @@ import { BasicField, IField, - LogicConditions, LogicConditionState, + PossibleLogicCondition, } from '../../../../../types' -const LOGIC_VALID_CONDITIONS: LogicConditions[] = [ +const LOGIC_CONDITIONS: PossibleLogicCondition[] = [ [ BasicField.Dropdown, [LogicConditionState.Equal, LogicConditionState.Either], @@ -38,9 +38,7 @@ const LOGIC_VALID_CONDITIONS: LogicConditions[] = [ [BasicField.Radio, [LogicConditionState.Equal, LogicConditionState.Either]], ] -const LOGIC_MAP = new Map( - LOGIC_VALID_CONDITIONS, -) +const LOGIC_MAP = new Map(LOGIC_CONDITIONS) /** * Given a list of form fields, returns only the fields that are diff --git a/src/types/form_logic.ts b/src/types/form_logic.ts index 5d3ed979cc..55d19ff160 100644 --- a/src/types/form_logic.ts +++ b/src/types/form_logic.ts @@ -100,7 +100,7 @@ type NumericalLogicCondition = LogicCondition< NumericalLogicStates > -export type LogicConditions = +export type PossibleLogicCondition = | CategoricalLogicCondition | BinaryLogicCondition | NumericalLogicCondition From 3a987acae2fcedb4694ddb7f27d307310bfd1097 Mon Sep 17 00:00:00 2001 From: Yuanruo Liang Date: Tue, 9 Mar 2021 16:10:31 +0800 Subject: [PATCH 22/23] refactor: use nullish coalescing operator --- .../forms/services/form-logic/form-logic.client.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/public/modules/forms/services/form-logic/form-logic.client.service.ts b/src/public/modules/forms/services/form-logic/form-logic.client.service.ts index 6ac6897ee8..0cc58c1928 100644 --- a/src/public/modules/forms/services/form-logic/form-logic.client.service.ts +++ b/src/public/modules/forms/services/form-logic/form-logic.client.service.ts @@ -52,4 +52,4 @@ export const getApplicableIfFields = (formFields: IField[]): IField[] => */ export const getApplicableIfStates = ( fieldType: BasicField, -): LogicConditionState[] => LOGIC_MAP.get(fieldType) || [] +): LogicConditionState[] => LOGIC_MAP.get(fieldType) ?? [] From a51ff97f59644dcadb36952a6f48441c34c15446 Mon Sep 17 00:00:00 2001 From: Yuanruo Liang Date: Tue, 9 Mar 2021 16:21:49 +0800 Subject: [PATCH 23/23] refactor: rename to LogicAssociation, LogicCondition --- .../form-logic/form-logic.client.service.ts | 4 ++-- src/types/form_logic.ts | 15 +++++++++------ 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/public/modules/forms/services/form-logic/form-logic.client.service.ts b/src/public/modules/forms/services/form-logic/form-logic.client.service.ts index 0cc58c1928..544af894c9 100644 --- a/src/public/modules/forms/services/form-logic/form-logic.client.service.ts +++ b/src/public/modules/forms/services/form-logic/form-logic.client.service.ts @@ -1,11 +1,11 @@ import { BasicField, IField, + LogicCondition, LogicConditionState, - PossibleLogicCondition, } from '../../../../../types' -const LOGIC_CONDITIONS: PossibleLogicCondition[] = [ +const LOGIC_CONDITIONS: LogicCondition[] = [ [ BasicField.Dropdown, [LogicConditionState.Equal, LogicConditionState.Either], diff --git a/src/types/form_logic.ts b/src/types/form_logic.ts index 55d19ff160..0a488b7d11 100644 --- a/src/types/form_logic.ts +++ b/src/types/form_logic.ts @@ -63,9 +63,9 @@ type LogicField = Extract< | BasicField.Rating > -type LogicCondition = [ +type LogicAssociation = [ K, - Array, + Array, ] // Logic fields that are categorical @@ -76,7 +76,7 @@ type CategoricalLogicField = Extract< type CategoricalLogicStates = | LogicConditionState.Equal | LogicConditionState.Either -type CategoricalLogicCondition = LogicCondition< +type CategoricalLogicCondition = LogicAssociation< CategoricalLogicField, CategoricalLogicStates > @@ -84,7 +84,10 @@ type CategoricalLogicCondition = LogicCondition< // Logic fields that are boolean type BinaryLogicField = Extract type BinaryLogicStates = LogicConditionState.Equal -type BinaryLogicCondition = LogicCondition +type BinaryLogicCondition = LogicAssociation< + BinaryLogicField, + BinaryLogicStates +> // Logic fields that can be numerically compared type NumericalLogicField = Extract< @@ -95,12 +98,12 @@ type NumericalLogicStates = | LogicConditionState.Equal | LogicConditionState.Lte | LogicConditionState.Gte -type NumericalLogicCondition = LogicCondition< +type NumericalLogicCondition = LogicAssociation< NumericalLogicField, NumericalLogicStates > -export type PossibleLogicCondition = +export type LogicCondition = | CategoricalLogicCondition | BinaryLogicCondition | NumericalLogicCondition