From d247893d31ac148640fb8825fa7cd36bf51dd55f Mon Sep 17 00:00:00 2001 From: Tomas Bures Date: Fri, 26 Jul 2019 16:48:26 +0530 Subject: [PATCH] Refactoring a common pattern for "clone for existing". Applied to custom forms and templates. --- client/package.json | 1 - client/src/lib/form.js | 20 ++++++++++-- client/src/lists/forms/CUD.js | 60 +++++++++++++++++----------------- client/src/templates/CUD.js | 23 ++++++------- locales/en-US/common.json | 2 +- server/models/forms.js | 61 ++++++++++++++--------------------- server/models/templates.js | 20 ++++++------ server/routes/rest/forms.js | 6 ---- 8 files changed, 95 insertions(+), 98 deletions(-) diff --git a/client/package.json b/client/package.json index 3b0af3b5..4a300a69 100644 --- a/client/package.json +++ b/client/package.json @@ -28,7 +28,6 @@ "datatables.net": "^1.10.19", "datatables.net-bs4": "^1.10.19", "ellipsize": "^0.1.0", - "fast-deep-equal": "^2.0.1", "grapesjs": "^0.14.62", "grapesjs-mjml": "0.0.31", "grapesjs-preset-newsletter": "^0.2.20", diff --git a/client/src/lib/form.js b/client/src/lib/form.js index c429bc6a..c1d4b30f 100644 --- a/client/src/lib/form.js +++ b/client/src/lib/form.js @@ -12,7 +12,6 @@ import {TreeSelectMode, TreeTable} from './tree'; import {Table, TableSelectMode} from './table'; import {Button} from "./bootstrap-components"; import {SketchPicker} from 'react-color'; -import deepEqual from "fast-deep-equal"; import ACEEditorRaw from 'react-ace'; import 'brace/theme/github'; @@ -1373,7 +1372,24 @@ const withForm = createComponentMixin([], [], (TargetClass, InnerClass) => { const currentData = getSaveData(self, self.state.formState.get('data')); const savedData = self.state.formState.get('savedData'); - return !deepEqual(currentData, savedData); + function isDifferent(data1, data2, prefix) { + if (typeof data1 === 'object' && typeof data2 === 'object') { + const keys = new Set([...Object.keys(data1), ...Object.keys(data2)]); + for (const key of keys) { + if (isDifferent(data1[key], data2[key], `${prefix}/${key}`)) { + return true; + } + } + } else if (data1 !== data2) { + // console.log(prefix); + return true; + } + return false; + } + + const result = isDifferent(currentData, savedData, ''); + + return result; }; proto.isFormChanged = function() { diff --git a/client/src/lists/forms/CUD.js b/client/src/lists/forms/CUD.js index 79b7c57f..332cf08a 100644 --- a/client/src/lists/forms/CUD.js +++ b/client/src/lists/forms/CUD.js @@ -46,9 +46,7 @@ export default class CUD extends Component { this.state = { previewContents: null, - previewFullscreen: false, - fromSourceCustomForms: false, - sourceCustomForms: null, + previewFullscreen: false }; this.serverValidatedFields = [ @@ -300,7 +298,10 @@ export default class CUD extends Component { } submitFormValuesMutator(data) { - return filterData(data, ['name', 'description', 'layout', 'form_input_style', 'namespace', + return filterData(data, ['name', 'description', 'namespace', + 'fromExistingEntity', 'existingEntity', + + 'layout', 'form_input_style', 'web_subscribe', 'web_confirm_subscription_notice', 'mail_confirm_subscription_html', @@ -333,8 +334,8 @@ export default class CUD extends Component { const data = { name: '', description: '', - fromSourceCustomForms: false, - sourceCustomForms: null, + fromExistingEntity: false, + existingEntity: null, selectedTemplate: 'layout', namespace: mailtrainConfig.user.namespace }; @@ -355,12 +356,13 @@ export default class CUD extends Component { validateNamespace(t, state); - if (state.getIn(['fromSourceCustomForms', 'value']) && !state.getIn(['sourceCustomForms', 'value'])) { - state.setIn(['sourceCustomForms', 'error'], t('sourceCustomFormsMustNotBeEmpty')); + if (state.getIn(['fromExistingEntity', 'value']) && !state.getIn(['existingEntity', 'value'])) { + state.setIn(['existingEntity', 'error'], t('sourceCustomFormsMustNotBeEmpty')); } else { - state.setIn(['sourceCustomForms', 'error'], null); + state.setIn(['existingEntity', 'error'], null); } + let formsServerValidationRunning = false; const formsErrors = []; @@ -400,11 +402,7 @@ export default class CUD extends Component { url = `rest/forms/${this.props.entity.id}`; } else { sendMethod = FormSendMethod.POST; - if (this.getFormValue('sourceCustomForms') !== null) { - url = `rest/forms/${this.getFormValue('sourceCustomForms')}`; - } else { - url = 'rest/forms'; - } + url = 'rest/forms'; } this.disableForm(); @@ -510,18 +508,17 @@ export default class CUD extends Component { {!isEdit && - + } - {this.getFormValue('fromSourceCustomForms') && - - } + {this.getFormValue('fromExistingEntity') ? + + : + <> +
+ - {!this.getFormValue('fromSourceCustomForms') && -
- - - { previewListId && + { previewListId &&
@@ -570,15 +567,16 @@ export default class CUD extends Component {
}
- } -
- } + } +
- { selectedTemplate && -
- - -
+ { selectedTemplate && +
+ + +
+ } + } diff --git a/client/src/templates/CUD.js b/client/src/templates/CUD.js index 6042e48b..d4624038 100644 --- a/client/src/templates/CUD.js +++ b/client/src/templates/CUD.js @@ -98,7 +98,8 @@ export default class CUD extends Component { submitFormValuesMutator(data) { this.templateTypes[data.type].beforeSave(data); - return filterData(data, ['name', 'description', 'type', 'tag_language', 'data', 'html', 'text', 'namespace']); + + return filterData(data, ['name', 'description', 'type', 'tag_language', 'data', 'html', 'text', 'namespace', 'fromExistingEntity', 'existingEntity']); } async getPreSubmitFormValuesUpdater() { @@ -127,8 +128,8 @@ export default class CUD extends Component { type: mailtrainConfig.editors[0], tag_language: mailtrainConfig.tagLanguages[0], - fromSourceTemplate: false, - sourceTemplate: null, + fromExistingEntity: false, + existingEntity: null, text: '', html: '', @@ -158,10 +159,10 @@ export default class CUD extends Component { state.setIn(['tag_language', 'error'], t('Tag language must be selected')); } - if (state.getIn(['fromSourceTemplate', 'value']) && !state.getIn(['sourceTemplate', 'value'])) { - state.setIn(['sourceTemplate', 'error'], t('sourceTemplateMustNotBeEmpty')); + if (state.getIn(['fromExistingEntity', 'value']) && !state.getIn(['existingEntity', 'value'])) { + state.setIn(['existingEntity', 'error'], t('sourceTemplateMustNotBeEmpty')); } else { - state.setIn(['sourceTemplate', 'error'], null); + state.setIn(['existingEntity', 'error'], null); } validateNamespace(t, state); @@ -350,11 +351,11 @@ export default class CUD extends Component {