Clone from existing custom forms Added
This commit is contained in:
parent
e9bf4a890c
commit
1bf37e65a3
7 changed files with 108 additions and 97 deletions
|
@ -10,6 +10,7 @@ import {
|
|||
AlignedRow,
|
||||
Button,
|
||||
ButtonRow,
|
||||
CheckBox,
|
||||
Dropdown,
|
||||
Fieldset,
|
||||
filterData,
|
||||
|
@ -45,7 +46,9 @@ export default class CUD extends Component {
|
|||
|
||||
this.state = {
|
||||
previewContents: null,
|
||||
previewFullscreen: false
|
||||
previewFullscreen: false,
|
||||
fromSourceCustomForms: false,
|
||||
sourceCustomForms: null,
|
||||
};
|
||||
|
||||
this.serverValidatedFields = [
|
||||
|
@ -330,8 +333,10 @@ export default class CUD extends Component {
|
|||
const data = {
|
||||
name: '',
|
||||
description: '',
|
||||
fromSourceCustomForms: false,
|
||||
sourceCustomForms: null,
|
||||
selectedTemplate: 'layout',
|
||||
namespace: mailtrainConfig.user.namespace
|
||||
namespace: mailtrainConfig.user.namespace,
|
||||
};
|
||||
this.supplyDefaults(data);
|
||||
|
||||
|
@ -350,6 +355,12 @@ export default class CUD extends Component {
|
|||
|
||||
validateNamespace(t, state);
|
||||
|
||||
if (state.getIn(['fromSourceCustomForms', 'value']) && !state.getIn(['sourceCustomForms', 'value'])) {
|
||||
state.setIn(['sourceCustomForms', 'error'], t('sourceCustomFormsMustNotBeEmpty'));
|
||||
} else {
|
||||
state.setIn(['sourceCustomForms', 'error'], null);
|
||||
}
|
||||
|
||||
let formsServerValidationRunning = false;
|
||||
const formsErrors = [];
|
||||
|
||||
|
@ -380,21 +391,20 @@ export default class CUD extends Component {
|
|||
}
|
||||
|
||||
@withFormErrorHandlers
|
||||
async submitHandler(submitAndLeave, copy) {
|
||||
async submitHandler(submitAndLeave) {
|
||||
const t = this.props.t;
|
||||
|
||||
let sendMethod, url;
|
||||
if (this.props.entity) {
|
||||
if(copy){
|
||||
sendMethod = FormSendMethod.POST;
|
||||
url = `rest/forms/${this.props.entity.id}`
|
||||
}else{
|
||||
sendMethod = FormSendMethod.PUT;
|
||||
url = `rest/forms/${this.props.entity.id}`
|
||||
}
|
||||
url = `rest/forms/${this.props.entity.id}`;
|
||||
} else {
|
||||
sendMethod = FormSendMethod.POST;
|
||||
url = 'rest/forms'
|
||||
if(this.getFormValue('sourceCustomForms')!=null){
|
||||
url = `rest/forms/${this.getFormValue('sourceCustomForms')}`;
|
||||
}else{
|
||||
url = 'rest/forms';
|
||||
}
|
||||
}
|
||||
|
||||
this.disableForm();
|
||||
|
@ -408,24 +418,16 @@ export default class CUD extends Component {
|
|||
this.navigateToWithFlashMessage('/lists/forms', 'success', t('customFormsUpdated'));
|
||||
} else {
|
||||
await this.getFormValuesFromURL(`rest/forms/${this.props.entity.id}`);
|
||||
this.enableForm();
|
||||
if(copy){
|
||||
this.navigateToWithFlashMessage(`/lists/forms`, 'success', t('customFormsCopied'));
|
||||
}else{
|
||||
this.enableForm()
|
||||
this.setFormStatusMessage('success', t('customFormsUpdated'));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (submitAndLeave) {
|
||||
this.navigateToWithFlashMessage('/lists/forms', 'success', t('customFormsCreated'));
|
||||
} else {
|
||||
if(copy){
|
||||
this.navigateToWithFlashMessage(`/lists/forms`, 'success', t('customFormsCopied'));
|
||||
}else{
|
||||
this.navigateToWithFlashMessage(`/lists/forms/${submitResult}/edit`, 'success', t('customFormsCreated'));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.enableForm();
|
||||
this.setFormStatusMessage('warning', t('thereAreErrorsInTheFormPleaseFixThemAnd'));
|
||||
|
@ -469,6 +471,12 @@ export default class CUD extends Component {
|
|||
});
|
||||
}
|
||||
|
||||
const customFormsColumns = [
|
||||
{ data: 1, title: t('name') },
|
||||
{ data: 2, title: t('description') },
|
||||
{ data: 3, title: t('namespace') }
|
||||
];
|
||||
|
||||
const listsColumns = [
|
||||
{ data: 0, title: "#" },
|
||||
{ data: 1, title: t('name') },
|
||||
|
@ -501,6 +509,15 @@ export default class CUD extends Component {
|
|||
|
||||
<NamespaceSelect/>
|
||||
|
||||
{!isEdit &&
|
||||
<CheckBox id="fromSourceCustomForms" label={t('customForms')} text={t('cloneFromAnExistingCustomForms')}/>
|
||||
}
|
||||
|
||||
{this.getFormValue('fromSourceCustomForms') &&
|
||||
<TableSelect key="sourceCustomFormsKey" id="sourceCustomForms" withHeader dropdown dataUrl='rest/forms-table' columns={customFormsColumns} selectionLabelIndex={1} />
|
||||
}
|
||||
|
||||
{!this.getFormValue('fromSourceCustomForms') &&
|
||||
<Fieldset label={t('formsPreview')}>
|
||||
<TableSelect id="previewList" label={t('listToPreviewOn')} withHeader dropdown dataUrl='rest/lists-table' columns={listsColumns} selectionLabelIndex={1} help={t('selectListWhoseFieldsWillBeUsedToPreview')}/>
|
||||
|
||||
|
@ -555,8 +572,9 @@ export default class CUD extends Component {
|
|||
</div>
|
||||
}
|
||||
</Fieldset>
|
||||
}
|
||||
|
||||
{ selectedTemplate &&
|
||||
{!this.getFormValue('fromSourceCustomForms') && selectedTemplate &&
|
||||
<Fieldset label={t('templates')}>
|
||||
<Dropdown id="selectedTemplate" label={t('edit')} options={templateOptGroups} help={this.templateSettings[selectedTemplate].help}/>
|
||||
<ACEEditor id={selectedTemplate} height="500px" mode={this.templateSettings[selectedTemplate].mode}/>
|
||||
|
@ -565,8 +583,7 @@ export default class CUD extends Component {
|
|||
|
||||
<ButtonRow>
|
||||
<Button type="submit" className="btn-primary" icon="check" label={t('save')}/>
|
||||
<Button type="submit" className="btn-primary" icon="check" label={t('saveAndLeave')} onClickAsync={async () => await this.submitHandler(true, false)}/>
|
||||
{isEdit && <Button type="submit" className="btn-success" icon="copy" label={t('copy')} onClickAsync={async () => await this.submitHandler(false, true)}/>}
|
||||
<Button type="submit" className="btn-primary" icon="check" label={t('saveAndLeave')} onClickAsync={async () => await this.submitHandler(true)}/>
|
||||
{canDelete && <LinkButton className="btn-danger" icon="trash-alt" label={t('delete')} to={`/lists/forms/${this.props.entity.id}/delete`}/>}
|
||||
</ButtonRow>
|
||||
</Form>
|
||||
|
|
|
@ -924,6 +924,7 @@
|
|||
"editTemplate": "Edit Template",
|
||||
"createTemplate": "Create Template",
|
||||
"cloneFromAnExistingTemplate": "Clone from an existing template",
|
||||
"cloneFromAnExistingCustomForms": "Clone from an existing custom forms",
|
||||
"mosaico": "Mosaico",
|
||||
"templateContentHtml": "Template content (HTML)",
|
||||
"mosaicoTemplateDesigner": "Mosaico Template Designer",
|
||||
|
|
|
@ -924,6 +924,7 @@
|
|||
"editTemplate": "Edit Template",
|
||||
"createTemplate": "Create Template",
|
||||
"cloneFromAnExistingTemplate": "Clone from an existing template",
|
||||
"cloneFromAnExistingCustomForms": "Clone from an existing custom forms",
|
||||
"mosaico": "Mosaico",
|
||||
"templateContentHtml": "Template content (HTML)",
|
||||
"mosaicoTemplateDesigner": "Mosaico Template Designer",
|
||||
|
|
|
@ -993,8 +993,8 @@
|
|||
"templateDeleted": "Template deleted",
|
||||
"editTemplate": "Edit Template",
|
||||
"createTemplate": "Create Template",
|
||||
"cloneFromAnExistingTemplate": "Clone from an existing template",
|
||||
"cloneFromAnExistingTemplate - TODO: update line above and then delete this line to mark that the translation has been fixed": "Clone from an existing template",
|
||||
"cloneFromAnExistingTemplate": "Clonar a partir de templates ya existentes",
|
||||
"cloneFromAnExistingCustomForms": "Clonar a partir de formularios personalizados ya existentes",
|
||||
"mosaico": "Mosaico",
|
||||
"templateContentHtml": "Template content (HTML)",
|
||||
"mosaicoTemplateDesigner": "Mosaico Template Designer",
|
||||
|
|
|
@ -105,7 +105,8 @@
|
|||
"save": "Salvar",
|
||||
"saveAndLeave": "Salvar e sair",
|
||||
"saveAndLeave - TODO: update line above and then delete this line to mark that the translation has been fixed": "Save and leave",
|
||||
"copy": "Copy",
|
||||
"copy": "Copia",
|
||||
"copy - TODO: update line above and then delete this line to mark that the translation has been fixed": "Copy",
|
||||
"saveAndGoToStatus": "Save and go to status",
|
||||
"saveAndGoToStatus - TODO: update line above and then delete this line to mark that the translation has been fixed": "Save and go to status",
|
||||
"testSend": "Testar envio",
|
||||
|
@ -995,6 +996,8 @@
|
|||
"createTemplate": "Criar modelo",
|
||||
"cloneFromAnExistingTemplate": "Clone from an existing template",
|
||||
"cloneFromAnExistingTemplate - TODO: update line above and then delete this line to mark that the translation has been fixed": "Clone from an existing template",
|
||||
"cloneFromAnExistingCustomForms": "Clone from an existing custom forms",
|
||||
"cloneFromAnExistingCustomForms - TODO: update line above and then delete this line to mark that the translation has been fixed": "Clone from an existing custom forms",
|
||||
"mosaico": "Mosaico",
|
||||
"templateContentHtml": "Conteúdo do modelo (HTML)",
|
||||
"mosaicoTemplateDesigner": "Editor do Modelo Mosaico",
|
||||
|
|
|
@ -175,26 +175,16 @@ async function updateWithConsistencyCheck(context, entity) {
|
|||
});
|
||||
}
|
||||
|
||||
async function copy(context, entity) {
|
||||
await knex.transaction(async tx => {
|
||||
await shares.enforceEntityPermissionTx(tx, context, 'customForm', entity.id, 'edit');
|
||||
|
||||
const existing = await _getById(tx, entity.id);
|
||||
|
||||
const existingHash = hash(existing);
|
||||
if (existingHash !== entity.originalHash) {
|
||||
throw new interoperableErrors.ChangedError();
|
||||
}
|
||||
|
||||
async function copy(context, entity, formId) {
|
||||
return await knex.transaction(async tx => {
|
||||
await shares.enforceEntityPermissionTx(tx, context, 'namespace', entity.namespace, 'createCustomForm');
|
||||
const existing = await _getById(tx, formId);
|
||||
await namespaceHelpers.validateEntity(tx, entity);
|
||||
await namespaceHelpers.validateMove(context, entity, existing, 'customForm', 'createCustomForm', 'delete');
|
||||
|
||||
const form = filterObject(entity, allowedFormKeys);
|
||||
const form = filterObject(existing, allowedFormKeys);
|
||||
enforce(!Object.keys(checkForMjmlErrors(form)).length, 'Error(s) in form templates');
|
||||
|
||||
entity.name = entity.name + '_COPY';
|
||||
const ids = await tx('custom_forms').insert(filterObject(entity, formAllowedKeys));
|
||||
|
||||
const id = ids[0];
|
||||
|
||||
for (const formKey in form) {
|
||||
|
@ -204,8 +194,8 @@ async function copy(context, entity) {
|
|||
data_value: form[formKey]
|
||||
})
|
||||
}
|
||||
await shares.rebuildPermissionsTx(tx, { entityTypeId: 'customForm', entityId: id });
|
||||
|
||||
await shares.rebuildPermissionsTx(tx, { entityTypeId: 'customForm', entityId: id });
|
||||
return id;
|
||||
});
|
||||
}
|
||||
|
|
|
@ -28,9 +28,8 @@ router.postAsync('/forms', passport.loggedIn, passport.csrfProtection, async (re
|
|||
|
||||
router.postAsync('/forms/:formId', passport.loggedIn, passport.csrfProtection, async (req, res) => {
|
||||
const entity = req.body;
|
||||
entity.id = castToInteger(req.params.formId);
|
||||
await forms.copy(req.context, entity);
|
||||
return res.json();
|
||||
const formId= castToInteger(req.params.formId);
|
||||
return res.json(await forms.copy(req.context, entity, formId));
|
||||
});
|
||||
|
||||
router.putAsync('/forms/:formId', passport.loggedIn, passport.csrfProtection, async (req, res) => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue