diff --git a/frontend/src/components/CampaignPreview.vue b/frontend/src/components/CampaignPreview.vue
index 636cedad..b6a4446b 100644
--- a/frontend/src/components/CampaignPreview.vue
+++ b/frontend/src/components/CampaignPreview.vue
@@ -22,7 +22,7 @@
>
diff --git a/frontend/src/components/Editor.vue b/frontend/src/components/Editor.vue
index a5c4cbea..c59e3515 100644
--- a/frontend/src/components/Editor.vue
+++ b/frontend/src/components/Editor.vue
@@ -36,12 +36,32 @@
-
+
+
+
+
+
+
+
+
+
+
+
@@ -83,7 +103,6 @@ import 'tinymce/skins/ui/oxide/skin.css';
import 'tinymce/plugins/autoresize';
import 'tinymce/plugins/autolink';
import 'tinymce/plugins/charmap';
-import 'tinymce/plugins/code';
import 'tinymce/plugins/colorpicker';
import 'tinymce/plugins/contextmenu';
import 'tinymce/plugins/emoticons';
@@ -148,8 +167,10 @@ export default {
isEditorFullscreen: false,
isReady: false,
isRichtextReady: false,
+ isRichtextSourceVisible: false,
richtextConf: {},
isTrackLink: false,
+ richTextSourceBody: '',
form: {
body: '',
format: this.contentType,
@@ -180,13 +201,20 @@ export default {
editor.on('init', () => {
this.onEditorDialogOpen(editor);
});
+
+ // Custom HTML editor.
+ editor.ui.registry.addButton('html', {
+ icon: 'sourcecode',
+ tooltip: 'Source code',
+ onAction: this.onRichtextViewSource,
+ });
},
min_height: 500,
entity_encoding: 'raw',
convert_urls: true,
plugins: [
- 'autoresize', 'autolink', 'charmap', 'code', 'emoticons', 'fullscreen', 'help',
+ 'autoresize', 'autolink', 'charmap', 'emoticons', 'fullscreen', 'help',
'hr', 'image', 'imagetools', 'link', 'lists', 'paste', 'searchreplace',
'table', 'visualblocks', 'visualchars', 'wordcount',
],
@@ -194,7 +222,7 @@ export default {
bold italic underline strikethrough forecolor backcolor subscript superscript |
alignleft aligncenter alignright alignjustify |
bullist numlist table image | outdent indent | link hr removeformat |
- code fullscreen help`,
+ html fullscreen help`,
fontsize_formats: '10px 11px 12px 14px 15px 16px 18px 24px 36px',
skin: false,
content_css: false,
@@ -242,6 +270,23 @@ export default {
return u;
},
+
+ onRichtextViewSource() {
+ this.richTextSourceBody = this.form.body;
+ this.isRichtextSourceVisible = true;
+ },
+
+ onFormatRichtextHTML() {
+ this.richTextSourceBody = this.beautifyHTML(this.richTextSourceBody);
+ },
+
+ onSaveRichTextSource() {
+ this.form.body = this.richTextSourceBody;
+ window.tinymce.editors[0].setContent(this.form.body);
+ this.richTextSourceBody = '';
+ this.isRichtextSourceVisible = false;
+ },
+
onEditorDialogOpen(editor) {
const ed = editor;
const oldEd = ed.windowManager.open;
@@ -384,7 +429,9 @@ export default {
// Preserve line breaks when converting HTML to plaintext.
const d = document.createElement('div');
d.innerHTML = this.beautifyHTML(this.form.body);
- this.form.body = this.trimLines(d.innerText.trim(), true);
+ this.$nextTick(() => {
+ this.form.body = this.trimLines(d.innerText.trim(), true);
+ });
} else if ((from === 'richtext' || from === 'html') && to === 'markdown') {
// richtext, html => markdown
this.form.body = turndown.turndown(this.form.body).replace(/\n\n+/ig, '\n\n');
diff --git a/frontend/src/components/HTMLEditor.vue b/frontend/src/components/HTMLEditor.vue
index a521755d..00d28f8c 100644
--- a/frontend/src/components/HTMLEditor.vue
+++ b/frontend/src/components/HTMLEditor.vue
@@ -14,6 +14,7 @@ export default {
data() {
return {
+ data: '',
flask: null,
};
},
@@ -43,8 +44,9 @@ export default {
readonly: this.disabled,
});
- this.flask.onUpdate((b) => {
- this.$emit('input', b);
+ this.flask.onUpdate((v) => {
+ this.data = v;
+ this.$emit('input', v);
});
// Set the initial value.
@@ -55,5 +57,13 @@ export default {
mounted() {
this.initHTMLEditor(this.$props.value || '');
},
+
+ watch: {
+ value(newVal) {
+ if (newVal !== this.data) {
+ this.flask.updateCode(newVal);
+ }
+ },
+ },
};
diff --git a/frontend/src/views/TemplateForm.vue b/frontend/src/views/TemplateForm.vue
index 0342572b..60b12244 100644
--- a/frontend/src/views/TemplateForm.vue
+++ b/frontend/src/views/TemplateForm.vue
@@ -18,7 +18,7 @@
-
+
diff --git a/i18n/cs-cz.json b/i18n/cs-cz.json
index 83ab14ea..9165632f 100644
--- a/i18n/cs-cz.json
+++ b/i18n/cs-cz.json
@@ -31,6 +31,7 @@
"campaigns.fieldInvalidName": "Neplatná délka jména.",
"campaigns.fieldInvalidSendAt": "Naplánované datum by mělo být v budoucnosti.",
"campaigns.fieldInvalidSubject": "Neplatná délka předmětu.",
+ "campaigns.formatHTML": "Format HTML",
"campaigns.fromAddress": "Z adresy",
"campaigns.fromAddressPlaceholder": "Vaše jméno ",
"campaigns.invalid": "Neplatná kampaň",
diff --git a/i18n/de.json b/i18n/de.json
index fc23bed0..5983eb0d 100644
--- a/i18n/de.json
+++ b/i18n/de.json
@@ -31,6 +31,7 @@
"campaigns.fieldInvalidName": "Ungültige Länge für `name`.",
"campaigns.fieldInvalidSendAt": "Das Datum muss in der Zukunft liegen.",
"campaigns.fieldInvalidSubject": "Ungültige Länge für `subject`.",
+ "campaigns.formatHTML": "Format HTML",
"campaigns.fromAddress": "Absender",
"campaigns.fromAddressPlaceholder": "Dein Name ",
"campaigns.invalid": "Ungültige Kampagne",
diff --git a/i18n/en.json b/i18n/en.json
index 13944b2c..be423859 100644
--- a/i18n/en.json
+++ b/i18n/en.json
@@ -31,6 +31,7 @@
"campaigns.fieldInvalidName": "Invalid length for name.",
"campaigns.fieldInvalidSendAt": "Scheduled date should be in the future.",
"campaigns.fieldInvalidSubject": "Invalid length for subject.",
+ "campaigns.formatHTML": "Format HTML",
"campaigns.fromAddress": "From address",
"campaigns.fromAddressPlaceholder": "Your Name ",
"campaigns.invalid": "Invalid campaign",
diff --git a/i18n/es.json b/i18n/es.json
index 37b7b763..508f3577 100644
--- a/i18n/es.json
+++ b/i18n/es.json
@@ -31,6 +31,7 @@
"campaigns.fieldInvalidName": "Largo de nombre inválido",
"campaigns.fieldInvalidSendAt": "La hora agendada debe ser en el futuro.",
"campaigns.fieldInvalidSubject": "Largo de asunto inválido",
+ "campaigns.formatHTML": "Format HTML",
"campaigns.fromAddress": "Dirección origen",
"campaigns.fromAddressPlaceholder": "Su Nombre ",
"campaigns.invalid": "Campaña inválida",
diff --git a/i18n/fr.json b/i18n/fr.json
index b9a95110..b5e4150f 100644
--- a/i18n/fr.json
+++ b/i18n/fr.json
@@ -31,6 +31,7 @@
"campaigns.fieldInvalidName": "Longueur du nom invalide.",
"campaigns.fieldInvalidSendAt": "La date planifiée doit être future.",
"campaigns.fieldInvalidSubject": "Longueur d'objet non valide.",
+ "campaigns.formatHTML": "Format HTML",
"campaigns.fromAddress": "Adresse d'envoi",
"campaigns.fromAddressPlaceholder": "Nom à afficher ",
"campaigns.invalid": "Campagne non valide",
diff --git a/i18n/it.json b/i18n/it.json
index 5fc83f88..bc799221 100644
--- a/i18n/it.json
+++ b/i18n/it.json
@@ -31,6 +31,7 @@
"campaigns.fieldInvalidName": "Lunghezza del nome non valida.",
"campaigns.fieldInvalidSendAt": "La data programmata deve essere futura.",
"campaigns.fieldInvalidSubject": "Lunghezza dell'oggetto non valida.",
+ "campaigns.formatHTML": "Format HTML",
"campaigns.fromAddress": "Mittente",
"campaigns.fromAddressPlaceholder": "Tuo nome ",
"campaigns.invalid": "Campagna non valida",
diff --git a/i18n/ml.json b/i18n/ml.json
index 1fb2d980..13460f8e 100644
--- a/i18n/ml.json
+++ b/i18n/ml.json
@@ -31,6 +31,7 @@
"campaigns.fieldInvalidName": "`name` ന്റെ ദൈർഘ്യം അസാധുവാണ്.",
"campaigns.fieldInvalidSendAt": "`send_at` ഭാവിയിലുള്ള തിയതിയായിരിക്കണം.",
"campaigns.fieldInvalidSubject": "`subject` ന്റെ ദൈർഘ്യം അസാധുവാണ്.",
+ "campaigns.formatHTML": "Format HTML",
"campaigns.fromAddress": "പ്രേക്ഷകൻ",
"campaigns.fromAddressPlaceholder": "നിങ്ങളുടെ പേര് ",
"campaigns.invalid": "ക്യാമ്പേയ്ൻ അസാധുവാണ്",
diff --git a/i18n/pl.json b/i18n/pl.json
index bcdda382..ccf9e1c1 100644
--- a/i18n/pl.json
+++ b/i18n/pl.json
@@ -31,6 +31,7 @@
"campaigns.fieldInvalidName": "Nieprawidłowa długość dla nazwy,",
"campaigns.fieldInvalidSendAt": "Zaplanowana data powinna być w przyszłości,",
"campaigns.fieldInvalidSubject": "Nieprawidłowa długość tytułu",
+ "campaigns.formatHTML": "Format HTML",
"campaigns.fromAddress": "Adres od",
"campaigns.fromAddressPlaceholder": "Twoja Nazwa ",
"campaigns.invalid": "Nieprawidłowa kampania",
diff --git a/i18n/pt-BR.json b/i18n/pt-BR.json
index 3bda1573..8e0e3ace 100644
--- a/i18n/pt-BR.json
+++ b/i18n/pt-BR.json
@@ -31,6 +31,7 @@
"campaigns.fieldInvalidName": "Quantidade de caracteres inválida para o nome.",
"campaigns.fieldInvalidSendAt": "A data agendada deve ser no futuro.",
"campaigns.fieldInvalidSubject": "Quantidade de caracteres inválida para o assunto.",
+ "campaigns.formatHTML": "Format HTML",
"campaigns.fromAddress": "Endereço do remetente",
"campaigns.fromAddressPlaceholder": "Seu Nome ",
"campaigns.invalid": "Campanha inválida",
diff --git a/i18n/pt.json b/i18n/pt.json
index 324db8df..bec0dcd6 100644
--- a/i18n/pt.json
+++ b/i18n/pt.json
@@ -31,6 +31,7 @@
"campaigns.fieldInvalidName": "Tamanho de nome inválido.",
"campaigns.fieldInvalidSendAt": "Data agendada deve ser no futuro.",
"campaigns.fieldInvalidSubject": "Tamanho de corpo inválido.",
+ "campaigns.formatHTML": "Format HTML",
"campaigns.fromAddress": "Endereço do Remetente",
"campaigns.fromAddressPlaceholder": "O Teu Nome ",
"campaigns.invalid": "Campanha inválida",
diff --git a/i18n/ro.json b/i18n/ro.json
index 49f43aa2..eb061b2b 100644
--- a/i18n/ro.json
+++ b/i18n/ro.json
@@ -31,6 +31,7 @@
"campaigns.fieldInvalidName": "Lungime nevalidă pentru nume",
"campaigns.fieldInvalidSendAt": "Data programată ar trebui să fie în viitor.",
"campaigns.fieldInvalidSubject": "Lungime nevalida pentru subiect.",
+ "campaigns.formatHTML": "Format HTML",
"campaigns.fromAddress": "De la adresa",
"campaigns.fromAddressPlaceholder": "Numele tau ",
"campaigns.invalid": "Campanie nevalidă",
diff --git a/i18n/ru.json b/i18n/ru.json
index 7d5af4ee..539fa85f 100644
--- a/i18n/ru.json
+++ b/i18n/ru.json
@@ -31,6 +31,7 @@
"campaigns.fieldInvalidName": "Неверная длина имени.",
"campaigns.fieldInvalidSendAt": "Запланированная дата должна быть позже текущей.",
"campaigns.fieldInvalidSubject": "Неверная длина темы.",
+ "campaigns.formatHTML": "Format HTML",
"campaigns.fromAddress": "Адрес отправителя",
"campaigns.fromAddressPlaceholder": "Ваше имя ",
"campaigns.invalid": "Неверная компания",
diff --git a/i18n/tr.json b/i18n/tr.json
index ea24a2ff..6b0c5072 100644
--- a/i18n/tr.json
+++ b/i18n/tr.json
@@ -31,6 +31,7 @@
"campaigns.fieldInvalidName": "İsim uzunluğu yanlış.",
"campaigns.fieldInvalidSendAt": "Tanımlanan tarih gelecekte olmalı.",
"campaigns.fieldInvalidSubject": "Konu uzunluğu yanlış verilmiş.",
+ "campaigns.formatHTML": "Format HTML",
"campaigns.fromAddress": "Gelen adres",
"campaigns.fromAddressPlaceholder": "isminiz ",
"campaigns.invalid": "Yanlış tanımlı kapmanya",