'use strict'; import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { translate, Trans } from 'react-i18next'; import {requiresAuthenticatedUser, withPageHelpers, Title, NavButton} from '../lib/page' import { withForm, Form, FormSendMethod, InputField, TextArea, Dropdown, ACEEditor, ButtonRow, Button, AlignedRow, StaticField } from '../lib/form'; import { withErrorHandling, withAsyncErrorHandler } from '../lib/error-handling'; import { validateNamespace, NamespaceSelect } from '../lib/namespace'; import {DeleteModalDialog} from "../lib/modals"; import mailtrainConfig from 'mailtrainConfig'; import { getTemplateTypes } from './helpers'; import {ActionLink} from "../lib/bootstrap-components"; import axios from '../lib/axios'; import styles from "../lib/styles.scss"; @translate() @withForm @withPageHelpers @withErrorHandling @requiresAuthenticatedUser export default class CUD extends Component { constructor(props) { super(props); this.templateTypes = getTemplateTypes(props.t); this.state = { showMergeTagReference: false }; this.initForm(); } static propTypes = { action: PropTypes.string.isRequired, wizard: PropTypes.string, entity: PropTypes.object } @withAsyncErrorHandler async loadFormValues() { await this.getFormValuesFromURL(`/rest/templates/${this.props.entity.id}`); } componentDidMount() { if (this.props.entity) { this.getFormValuesFromEntity(this.props.entity); } else { this.populateFormValues({ name: '', description: '', namespace: mailtrainConfig.user.namespace, type: mailtrainConfig.editors[0], text: '', html: '' }); } } localValidateFormValues(state) { const t = this.props.t; if (!state.getIn(['name', 'value'])) { state.setIn(['name', 'error'], t('Name must not be empty')); } else { state.setIn(['name', 'error'], null); } if (!state.getIn(['type', 'value'])) { state.setIn(['type', 'error'], t('Type must be selected')); } else { state.setIn(['type', 'error'], null); } validateNamespace(t, state); } async submitHandler() { const t = this.props.t; let sendMethod, url; if (this.props.entity) { sendMethod = FormSendMethod.PUT; url = `/rest/templates/${this.props.entity.id}` } else { sendMethod = FormSendMethod.POST; url = '/rest/templates' } this.disableForm(); this.setFormStatusMessage('info', t('Saving ...')); const submitResponse = await this.validateAndSendFormValuesToURL(sendMethod, url, data => { }); if (submitResponse) { if (this.props.entity) { this.navigateToWithFlashMessage('/templates', 'success', t('Template saved')); } else { this.navigateToWithFlashMessage(`/templates/${submitResponse}/edit`, 'success', t('Template saved')); } } else { this.enableForm(); this.setFormStatusMessage('warning', t('There are errors in the form. Please fix them and submit again.')); } } async extractPlainText() { const html = this.getFormValue('html'); if (!html) { alert('Missing HTML content'); return; } if (this.isFormDisabled()) { return; } this.disableForm(); const response = await axios.post('/rest/html-to-text', { html }); this.updateFormValue('text', response.data.text); this.enableForm(); } async toggleMergeTagReference() { this.setState({ showMergeTagReference: !this.state.showMergeTagReference }); } render() { const t = this.props.t; const isEdit = !!this.props.entity; const canDelete = isEdit && this.props.entity.permissions.includes('delete'); const typeOptions = []; for (const key of mailtrainConfig.editors) { typeOptions.push({key, label: this.templateTypes[key].typeName}); } // TODO: Toggle HTML preview const typeKey = this.getFormValue('type'); let editForm = null; if (isEdit && typeKey) { editForm =
Merge tags are tags that are replaced before sending out the message. The format of the merge tag is the following: [TAG_NAME]
or [TAG_NAME/fallback]
where fallback
is an optional text value used when TAG_NAME
is empty.
|
|
---|---|
[LINK_UNSUBSCRIBE] |
|
[LINK_PREFERENCES] |
|
[LINK_BROWSER] |
|
[EMAIL] |
|
[FIRST_NAME] |
|
[LAST_NAME] |
|
[FULL_NAME] |
|
[SUBSCRIPTION_ID] |
|
[LIST_ID] |
|
[CAMPAIGN_ID] |
|
In addition to that any custom field can have its own merge tag.