3737 </b-select >
3838 </b-field >
3939
40- <b-field v-else :label =" $t('globals.terms.copyVisualTemplate')" label-position =" on-border" >
41- <b-select :placeholder =" $t('globals.terms.none')" v-model =" templateId" name =" template" :disabled =" disabled" class =" copy-visual-template-list" >
42- <option :value =" null" key =" none" v-if =" templateId !== null" >
43- {{ $t('globals.terms.none') }}
44- </option >
45- <template v-for =" t in applicableTemplates " >
46- <option v-if =" t.type === 'campaign' || t.type === 'campaign_visual'" :value =" t.id" :key =" t.id" >
47- {{ t.name }}
48- </option >
49- </template >
50- </b-select >
51- </b-field >
40+ <div v-else >
41+ <b-button v-if =" !isVisualTplSelector" @click =" onShowVisualTplSelector" type =" is-ghost" icon-left =" file-find-outline" data-cy =" btn-select-visual-tpl" >
42+ {{ $t('globals.terms.copyVisualTemplate') }}
43+ </b-button >
44+
45+ <b-field v-else :label =" $t('globals.terms.copyVisualTemplate')" label-position =" on-border" >
46+ <b-select :placeholder =" $t('globals.terms.none')" v-model =" visualTemplateId" name =" template" :disabled =" disabled" class =" copy-visual-template-list" >
47+ <template v-for =" t in applicableTemplates " >
48+ <option :value =" t.id" :key =" t.id" >
49+ {{ t.name }}
50+ </option >
51+ </template >
52+ </b-select >
53+
54+ <b-button :disabled =" isVisualTplApplied" class =" ml-3" @click =" onApplyVisualTpl" type =" is-primary" icon-left =" content-save-outline" data-cy =" btn-save-visual-tpl" >
55+ {{ $t('globals.terms.apply') }}
56+ </b-button >
57+ </b-field >
58+ </div >
5259 </div >
5360 <div class =" column is- has-text-right" >
5461 <b-button @click =" onTogglePreview" type =" is-primary" icon-left =" file-find-outline" data-cy =" btn-preview" >
@@ -120,8 +127,11 @@ export default {
120127 data () {
121128 return {
122129 isPreviewing: false ,
130+ isVisualTplSelector: false ,
131+ isVisualTplApplied: false ,
123132 contentType: this .$props .value .contentType ,
124133 templateId: ' ' ,
134+ visualTemplateId: ' '
125135 };
126136 },
127137
@@ -151,6 +161,8 @@ export default {
151161
152162 convertContentType (to , from ) {
153163 let body;
164+ let skip = false ;
165+
154166 if ((from === ' richtext' || from === ' html' ) && to === ' plain' ) {
155167 // richtext, html => plain
156168
@@ -168,20 +180,31 @@ export default {
168180 // richtext => html
169181 body = this .beautifyHTML (this .computedValue .body );
170182 } else if (from === ' markdown' && (to === ' richtext' || to === ' html' )) {
183+ // Skip default update.
184+ skip = true ;
171185 // markdown => richtext, html.
172186 this .$api .convertCampaignContent ({
173187 id: 1 , body: this .computedValue .body , from, to,
174188 }).then ((data ) => {
175189 this .$nextTick (() => {
176190 this .computedValue .body = this .beautifyHTML (data .trim ());
191+ this .computedValue .bodySource = null ;
177192 });
178193 });
179194 }
180195
181- // Update the current body.
182- this .$nextTick (() => {
183- this .computedValue .body = body;
184- });
196+ if (! skip) {
197+ // Update the current body.
198+ this .$nextTick (() => {
199+ this .computedValue .body = body;
200+
201+ // If not visual editor then set bodySource to null
202+ // this makes sure previous bodySource is not used when switching to visual editor.
203+ if (to !== ' visual' ) {
204+ this .computedValue .bodySource = null ;
205+ }
206+ });
207+ }
185208
186209 // Reset template ID only if its converted to or from visual template.
187210 if (to === ' visual' || from === ' visual' ) {
@@ -233,6 +256,53 @@ export default {
233256
234257 return out .join (' \n ' ).replace (/ \n\s * \n\s * \n / g , ' \n\n ' );
235258 },
259+
260+ onShowVisualTplSelector () {
261+ this .isVisualTplSelector = true ;
262+ this .setDefaultTemplate ();
263+ },
264+
265+ onApplyVisualTpl () {
266+ this .$utils .confirm (
267+ this .$t (' campaigns.confirmApplyVisualTemplate' ),
268+ () => {
269+ let found = false ;
270+ this .templates .forEach ((t ) => {
271+ if (t .id === this .visualTemplateId ) {
272+ found = true ;
273+ this .computedValue .body = t .body ;
274+ this .computedValue .bodySource = t .bodySource ;
275+
276+ // Deplay update so that applied template is propogated to visual editor
277+ // and it doesn't enable the apply button again. Delay here is arbitrary.
278+ setTimeout (() => {
279+ this .isVisualTplApplied = true ;
280+ }, 250 );
281+ }
282+ });
283+
284+ if (! found) {
285+ this .computedValue .body = ' ' ;
286+ this .computedValue .bodySource = null ;
287+
288+ // Deplay update so that applied template is propogated to visual editor
289+ // and it doesn't enable the apply button again. Delay here is arbitrary.
290+ setTimeout (() => {
291+ this .isVisualTplApplied = true ;
292+ }, 250 );
293+ }
294+ }
295+ );
296+ },
297+
298+ setDefaultTemplate () {
299+ if (this .computedValue .contentType === ' visual' ) {
300+ this .visualTemplateId = this .applicableTemplates [0 ]? .id || null ;
301+ } else {
302+ const defaultTemplate = this .applicableTemplates .find ((t ) => t .isDefault === true );
303+ this .templateId = defaultTemplate? .id || this .applicableTemplates [0 ]? .id || null ;
304+ }
305+ }
236306 },
237307
238308 mounted () {
@@ -262,9 +332,8 @@ export default {
262332 applicableTemplates () {
263333 if (this .computedValue .contentType === ' visual' ) {
264334 return this .templates .filter ((t ) => t .type === ' campaign_visual' );
265- } else {
266- return this .templates .filter ((t ) => t .type === ' campaign' );
267335 }
336+ return this .templates .filter ((t ) => t .type === ' campaign' );
268337 },
269338 },
270339
@@ -278,45 +347,25 @@ export default {
278347 this .convertContentType (to, from);
279348 },
280349
281- applicableTemplates (to ) {
282- if (this .computedValue .contentType !== ' visual' ) {
283- const ctps = this .templates .filter ((t ) => t .type === ' campaign' )
284- if (! ctps .find (t => t .id === this .templateId )) {
285- const defaultTemplate = ctps .find (t => t .isDefault === true );
286- this .templateId = defaultTemplate? .id || ctps[0 ]? .id || null ;
287- }
288- }
350+ applicableTemplates () {
351+ this .setDefaultTemplate ();
289352 },
290353
291- templateId (to , from ) {
354+ templateId (to ) {
292355 if (this .computedValue .templateId === to) {
293356 return ;
294357 }
358+ this .computedValue .templateId = to;
359+ },
295360
296- if (this .computedValue .contentType === ' visual' ) {
297- this .$utils .confirm (
298- this .$t (' campaigns.confirmApplyVisualTemplate' ),
299- () => {
300- this .computedValue .templateId = to;
301-
302- if (! to) {
303- this .computedValue .body = ' ' ;
304- this .computedValue .bodySource = null ;
305- } else {
306- this .templates .forEach ((t ) => {
307- if (t .id === to) {
308- this .computedValue .body = t .body ;
309- this .computedValue .bodySource = t .bodySource ;
310- }
311- });
312- }
313- },
314- () => {
315- this .templateId = from;
316- },
317- );
318- } else {
319- this .computedValue .templateId = to;
361+ // eslint-disable-next-line func-names
362+ ' computedValue.bodySource ' : function (to , from ) {
363+ this .isVisualTplApplied = ! (JSON .stringify (to) !== JSON .stringify (from));
364+ },
365+
366+ visualTemplateId (to , from ) {
367+ if (from && from !== to) {
368+ this .isVisualTplApplied = false ;
320369 }
321370 },
322371 },
0 commit comments