306739faf1020873012e9ba901c6c3f91f894cb1
1 (function(angular
, $, _
) {
3 var TRANSLATED
= ['msg_subject', 'msg_html', 'msg_text'];
6 * Create an APIv4 request to replace a series of translations.
9 * The ID of the translated entity.
11 * The language of the translation ('fr_CA', 'en_GB').
13 * The status of the translation ('active', 'draft').
15 * Key-value pairs. ({msg_title: 'Cheerio'})
17 * An API call which replaces the translations ([entity,action,params]).
19 function reqReplaceTranslations(id
, lang
, status
, values
) {
20 if (!values
._exists
) {
21 return reqDeleteTranslations(id
, lang
, status
);
24 angular
.forEach(TRANSLATED
, function(key
) {
25 records
.push({"entity_field":key
, "string":values
[key
]});
27 return ['Translation', 'replace', {
30 ["entity_table", "=", "civicrm_msg_template"],
31 ["entity_id", "=", id
],
32 ["language", "=", lang
],
33 ["status_id:name", "=", status
]
38 function reqDeleteTranslations(id
, lang
, status
) {
39 return ['Translation', 'delete', {
41 ["entity_table", "=", "civicrm_msg_template"],
42 ["entity_id", "=", id
],
43 ["language", "=", lang
],
44 ["status_id:name", "=", status
]
50 * Create an APIv4 request to read a series of translations.
53 * The language of the translation ('fr_CA', 'en_GB').
55 * The status of the translation ('active', 'draft').
57 * An API call which replaces the translations ([entity,action,params]).
59 function reqChainTranslations(lang
, status
) {
60 return ["Translation", "get", {
61 "select": ['id', 'entity_field', 'string'],
63 ['entity_table', '=', 'civicrm_msg_template'],
64 ['entity_id', '=', '$id'],
65 ['language', '=', lang
],
66 ['status_id:name', '=', status
]
71 function respMergeTranslations(prefetch
) {
72 angular
.forEach(prefetch
, function(results
, queryName
) {
73 var forceExists
= (queryName
=== 'txActive');
74 angular
.forEach(results
, function(result
) {
75 if (result
.translations
) {
76 angular
.forEach(result
.translations
, function(tx
) {
77 result
[tx
.entity_field
] = tx
.string
;
79 result
._exists
= forceExists
|| (result
.translations
.length
> 0);
86 function pickFirsts(prefetch
) {
87 return _
.reduce(prefetch
, function(all
, record
, key
){
88 all
[key
] = record
[0] || undefined;
93 function copyTranslations(src
, dest
) {
94 dest
._exists
= false; // Starting assumption - prove otherwise in a moment.
95 TRANSLATED
.forEach(function(fld
) {
96 if (src
[fld
] !== undefined) {
106 angular
.module('msgtplui').config(function($routeProvider
) {
107 $routeProvider
.when('/edit', {
108 controller
: 'MsgtpluiEdit',
109 controllerAs
: '$ctrl',
110 templateUrl
: '~/msgtplui/Edit.html',
112 // If you need to look up data when opening the page, list it out
115 prefetch: function(crmApi4
, crmStatus
, $location
) {
116 var args
= $location
.search();
119 requests
.main
= ['MessageTemplate', 'get', {
120 where
: [['id', '=', args
.id
]],
123 requests
.original
= ['MessageTemplate', 'get', {
124 join
: [["MessageTemplate AS other", "INNER", null, ["workflow_name", "=", "other.workflow_name"]]],
125 where
: [["other.id", "=", args
.id
], ["is_reserved", "=", true]],
130 requests
.txActive
= ['MessageTemplate', 'get', {
132 where
: [['id', '=', args
.id
]],
133 chain
: {translations
: reqChainTranslations(args
.lang
, 'active')}
136 requests
.txDraft
= ['MessageTemplate', 'get', {
138 where
: [['id', '=', args
.id
]],
139 chain
: {translations
: reqChainTranslations(args
.lang
, 'draft')}
143 return crmStatus({start
: ts('Loading...'), success
: ''}, crmApi4(requests
).then(respMergeTranslations
).then(pickFirsts
));
145 tokenList: function () {
146 return CRM
.crmMailing
.mailTokens
;
153 angular
.module('msgtplui').controller('MsgtpluiEdit', function($q
, $scope
, crmApi4
, crmBlocker
, crmStatus
, crmUiAlert
, crmUiHelp
, $location
, prefetch
, tokenList
, $rootScope
, dialogService
) {
154 var block
= $scope
.block
= crmBlocker();
155 var ts
= $scope
.ts
= CRM
.ts('msgtplui');
156 var hs
= $scope
.hs
= crmUiHelp({file
: 'CRM/Msgtplui/Edit'}); // See: templates/CRM/Msgtplui/Edit.hlp
158 var args
= $location
.search();
160 $ctrl
.locales
= CRM
.msgtplui
.uiLanguages
;
161 $ctrl
.records
= prefetch
;
162 $ctrl
.tokenList
= tokenList
;
164 $ctrl
.lang
= args
.lang
;
165 $ctrl
.tab
= (args
.status
=== 'draft' && $ctrl
.records
.txDraft
&& $ctrl
.records
.txDraft
._exists
) ? 'txDraft' : 'txActive';
172 var revisionTypes
= [
173 {name
: 'original', label
: ts('Original')},
174 {name
: 'main', label
: ts('Standard')},
175 {name
: 'txActive', label
: ts('%1 - Current translation', {1: $ctrl
.locales
[$ctrl
.lang
]})},
176 {name
: 'txDraft', label
: ts('%1 - Draft translation', {1: $ctrl
.locales
[$ctrl
.lang
]})}
179 $ctrl
.switchTab
= function switchTab(tgt
) {
181 // Experimenting with action buttons in the tab-bar. This makes the scroll unnecessary.
182 // $('html, body').animate({scrollTop: $("a[name=msgtplui-tabs]").offset().top - $('#civicrm-menu').height()}, 200);
184 $ctrl
.allowDraft
= function allowDraft() {
187 $ctrl
.hasDraft
= function hasDraft() {
188 return $ctrl
.allowDraft() && $ctrl
.records
.txDraft
&& $ctrl
.records
.txDraft
._exists
;
190 $ctrl
.hasRevType
= function hasRevType(name
) {
192 case 'txDraft': return $ctrl
.hasDraft();
193 case 'txActive': return !!$ctrl
.lang
;
194 case 'original': return !!$ctrl
.records
.original
;
195 case 'main': return !$ctrl
.lang
; // !!$ctrl.records.main;
198 $ctrl
.createDraft
= function createDraft(src
) {
199 copyTranslations(src
, $ctrl
.records
.txDraft
);
200 $ctrl
.switchTab('txDraft');
201 crmStatus({success
: ts('Beginning draft...')}, $q
.resolve());
203 $ctrl
.deleteDraft
= function deleteDraft() {
204 copyTranslations({}, $ctrl
.records
.txDraft
);
205 $ctrl
.switchTab('txActive');
206 crmStatus({error
: ts('Abandoned draft.')}, $q
.reject()).then(function(){},function(){});
208 $ctrl
.activateDraft
= function activateDraft() {
209 copyTranslations($ctrl
.records
.txDraft
, $ctrl
.records
.txActive
);
210 copyTranslations({}, $ctrl
.records
.txDraft
);
211 $ctrl
.switchTab('txActive');
212 crmStatus({success
: ts('Activated draft.')}, $q
.resolve());
215 $ctrl
.save
= function save() {
218 requests
.txActive
= reqReplaceTranslations($ctrl
.records
.main
.id
, $ctrl
.lang
, 'active', $ctrl
.records
.txActive
);
219 requests
.txDraft
= reqReplaceTranslations($ctrl
.records
.main
.id
, $ctrl
.lang
, 'draft', $ctrl
.records
.txDraft
);
222 requests
.main
= ['MessageTemplate', 'update', {
223 where
: [['id', '=', $ctrl
.records
.main
.id
]],
224 values
: $ctrl
.records
.main
227 return block(crmStatus({start
: ts('Saving...'), success
: ts('Saved')}, crmApi4(requests
)));
229 $ctrl
.cancel = function() {
230 window
.location
= '#/workflow';
232 $ctrl
.delete = function() {
235 requests
.txActive
= reqDeleteTranslations($ctrl
.records
.main
.id
, $ctrl
.lang
, 'active');
236 requests
.txDraft
= reqDeleteTranslations($ctrl
.records
.main
.id
, $ctrl
.lang
, 'draft');
239 requests
.main
= ['MessageTemplate', 'delete', {where
: [['id', '=', $ctrl
.records
.main
.id
]]}];
241 return block(crmStatus({start
: ts('Deleting...'), success
: ts('Deleted')}, crmApi4(requests
)))
245 // Ex: $rootScope.$emit('previewMsgTpl', {revisionName: 'txDraft', formatName: 'msg_text'})
246 function onPreview(event
, args
) {
248 // exampleName: 'fix-this-example',
250 // {id: 0, name: 'fix-this-example', title: ts('Fix this example')},
251 // {id: 1, name: 'another-example', title: ts('Another example')}
253 formatName
: 'msg_html',
255 {id
: 0, name
: 'msg_html', label
: ts('HTML')},
256 {id
: 1, name
: 'msg_text', label
: ts('Text')}
258 revisionName
: $ctrl
.tab
,
259 revisions
: _
.reduce(revisionTypes
, function(acc
, revType
){
260 if ($ctrl
.hasRevType(revType
.name
)) {
261 acc
.push(angular
.extend({id
: acc
.length
, rec
: $ctrl
.records
[revType
.name
]}, revType
));
268 crmApi4('WorkflowMessageExample', 'get', {
269 // FIXME: workflow name
270 where
: [["tags", "CONTAINS", "preview"], ["workflow", "=", $ctrl
.records
.main
.workflow_name
]],
272 }).then(function(workflowMessageExamples
) {
273 defaults
.exampleName
= workflowMessageExamples
.length
> 0 ? workflowMessageExamples
[0].name
: null;
275 angular
.forEach(workflowMessageExamples
, function(ex
) {
278 defaults
.examples
= workflowMessageExamples
;
280 var model
= angular
.extend({}, defaults
, args
);
281 var options
= CRM
.utils
.adjustDialogDefaults({
282 dialogClass
: 'msgtplui-dialog',
287 return dialogService
.open('previewMsgDlg', '~/msgtplui/Preview.html', model
, options
)
288 // Nothing to do but hide warnings. The field was edited live.
289 .then(function(){}, function(){});
290 }, function(failure
) {
295 $rootScope
.$on('previewMsgTpl', onPreview
);
296 $rootScope
.$on('$destroy', function (){
297 $rootScope
.$off('previewMsgTpl', onPreview
);
301 })(angular
, CRM
.$, CRM
._
);