Completed
Push — develop ( 292cbe...631186 )
by Alexander
15:04
created

main.js ➔ ... ➔ ???   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
/*
2
 * This file is part of Sulu.
3
 *
4
 * (c) MASSIVE ART WebServices GmbH
5
 *
6
 * This source file is subject to the MIT license that is bundled
7
 * with this source code in the file LICENSE.
8
 */
9
10
define([
11
    'jquery',
12
    'underscore',
13
    'config',
14
    'services/suluarticle/article-manager',
15
    'sulusecurity/services/user-manager',
16
    'services/sulupreview/preview',
17
    'sulusecurity/services/security-checker',
18
    'sulucontent/components/copy-locale-overlay/main',
19
    'sulucontent/components/open-ghost-overlay/main'
20
], function($, _, config, ArticleManager, UserManager, Preview, SecurityChecker, CopyLocale, OpenGhost) {
21
22
    'use strict';
23
24
    return {
25
26
        defaults: {
27
            options: {
28
                config: {}
29
            },
30
31
            templates: {
32
                url: '/admin/api/articles<% if (!!id) { %>/<%= id %><% } %>?locale=<%= locale %>'
33
            },
34
35
            translations: {
36
                headline: 'sulu_article.edit.title',
37
                draftLabel: 'sulu-document-manager.draft-label',
38
                removeDraft: 'sulu-content.delete-draft',
39
                unpublish: 'sulu-document-manager.unpublish',
40
                unpublishConfirmTextNoDraft: 'sulu-content.unpublish-confirm-text-no-draft',
41
                unpublishConfirmTextWithDraft: 'sulu-content.unpublish-confirm-text-with-draft',
42
                unpublishConfirmTitle: 'sulu-content.unpublish-confirm-title',
43
                deleteDraftConfirmTitle: 'sulu-content.delete-draft-confirm-title',
44
                deleteDraftConfirmText: 'sulu-content.delete-draft-confirm-text',
45
                copy: 'sulu_article.edit.copy',
46
                openGhostOverlay: {
47
                    info: 'sulu_article.settings.open-ghost-overlay.info',
48
                    new: 'sulu_article.settings.open-ghost-overlay.new',
49
                    copy: 'sulu_article.settings.open-ghost-overlay.copy',
50
                    ok: 'sulu_article.settings.open-ghost-overlay.ok'
51
                },
52
                copyLocaleOverlay: {
53
                    info: 'sulu_article.settings.copy-locale-overlay.info'
54
                }
55
            }
56
        },
57
58
        layout: function(){
59
            return {
60
                navigation: {
61
                    collapsed: true
62
                },
63
                content: {
64
                    shrinkable: !!this.options.id
65
                },
66
                sidebar: (!!this.options.id) ? 'max' : false
67
            };
68
        },
69
70
        header: function() {
71
            var buttons = {}, editDropdown = {}, saveDropdown = {};
72
73
            if (SecurityChecker.hasPermission(this.data, 'edit')) {
74
                saveDropdown.saveDraft = {};
75
76
                if (SecurityChecker.hasPermission(this.data, 'live')) {
77
                    saveDropdown.savePublish = {};
78
                    saveDropdown.publish = {};
79
                }
80
81
                if (!!config.has('sulu_automation.enabled')) {
82
                    saveDropdown.automationInfo = {
83
                        options: {
84
                            entityId: this.options.id,
85
                            entityClass: 'Sulu\\Bundle\\ArticleBundle\\Document\\ArticleDocument',
86
                            handlerClass: [
87
                                'Sulu\\Bundle\\ContentBundle\\Automation\\DocumentPublishHandler',
88
                                'Sulu\\Bundle\\ContentBundle\\Automation\\DocumentUnpublishHandler'
89
                            ]
90
                        }
91
                    };
92
                }
93
94
                buttons.save = {
95
                    parent: 'saveWithDraft',
96
                    options: {
97
                        callback: function() {
98
                            this.sandbox.emit('sulu.toolbar.save', 'publish');
99
                        }.bind(this),
100
                        dropdownItems: saveDropdown
101
                    }
102
                };
103
104
                buttons.template = {
105
                    options: {
106
                        dropdownOptions: {
107
                            url: '/admin/articles/templates?type=' + (this.options.type || this.data.articleType),
108
                            callback: function(item) {
109
                                this.template = item.template;
110
                                this.sandbox.emit('sulu.tab.template-change', item);
111
                            }.bind(this)
112
                        }
113
                    }
114
                }
115
            }
116
117
            if (SecurityChecker.hasPermission(this.data, 'live')) {
118
                editDropdown.unpublish = {
119
                    options: {
120
                        title: this.translations.unpublish,
121
                        disabled: !this.data.published,
122
                        callback: this.unpublish.bind(this)
123
                    }
124
                };
125
126
                editDropdown.divider = {
127
                    options: {
128
                        divider: true
129
                    }
130
                };
131
            }
132
133
            if (SecurityChecker.hasPermission(this.data, 'delete')) {
134
                editDropdown.delete = {
135
                    options: {
136
                        disabled: !this.options.id,
137
                        callback: this.deleteArticle.bind(this)
138
                    }
139
                };
140
            }
141
142
            editDropdown.copyLocale = {
143
                options: {
144
                    title: this.sandbox.translate('toolbar.copy-locale'),
145
                        callback: function() {
146
                        CopyLocale.startCopyLocalesOverlay.call(
147
                            this,
148
                            this.translations.copyLocaleOverlay
149
                        ).then(function(newLocales) {
150
                            // reload form when the current locale is in newLocales
151
                            if (_.contains(newLocales, this.options.locale)) {
152
                                this.toEdit(this.options.locale);
153
154
                                return;
155
                            }
156
157
                            // save new created locales to data and show success label
158
                            this.data.concreteLanguages = _.uniq(this.data.concreteLanguages.concat(newLocales));
159
                            this.sandbox.emit('sulu.labels.success.show', 'labels.success.copy-locale-desc', 'labels.success');
160
                        }.bind(this));
161
                    }.bind(this)
162
                }
163
            };
164
165
            if (SecurityChecker.hasPermission(this.data, 'edit')) {
166
                editDropdown.copy = {
167
                    options: {
168
                        title: this.translations.copy,
169
                        callback: this.copy.bind(this)
170
                    }
171
                };
172
            }
173
            
174
            
175
            if (!this.sandbox.util.isEmpty(editDropdown)) {
176
                buttons.edit = {
177
                    options: {
178
                        dropdownItems: editDropdown
179
                    }
180
                };
181
            }
182
183
            buttons.statePublished = {};
184
            buttons.stateTest = {};
185
186
            return {
187
                tabs: {
188
                    url: '/admin/content-navigations?alias=article&id=' + this.options.id + '&locale=' + this.options.locale,
189
                    options: {
190
                        data: function() {
191
                            return this.sandbox.util.deepCopy(this.data);
192
                        }.bind(this),
193
                        url: function() {
194
                            return this.templates.url({id: this.options.id, locale: this.options.locale});
195
                        }.bind(this),
196
                        config: this.options.config,
197
                        preview: this.preview
198
                    },
199
                    componentOptions: {
200
                        values: _.defaults(this.data, {type: null})
201
                    }
202
                },
203
204
                toolbar: {
205
                    buttons: buttons,
206
                    languageChanger: {
207
                        data: this.options.config.languageChanger,
208
                        preSelected: this.options.locale
209
                    }
210
                }
211
            };
212
        },
213
214
        initialize: function() {
215
            this.bindCustomEvents();
216
            this.showDraftLabel();
217
            this.setHeaderBar(true);
218
            this.loadLocalizations();
219
220
            // the open ghost overlay component needs the current locale in `this.options.language`
221
            this.options.language = this.options.locale;
222
        },
223
224
        bindCustomEvents: function() {
225
            this.sandbox.on('sulu.header.back', this.toList.bind(this));
226
            this.sandbox.on('sulu.tab.dirty', this.setHeaderBar.bind(this));
227
            this.sandbox.on('sulu.toolbar.save', this.save.bind(this));
228
            this.sandbox.on('sulu.tab.data-changed', this.setData.bind(this));
229
            this.sandbox.on('sulu.article.error', this.handleError.bind(this));
230
            this.sandbox.on('husky.tabs.header.item.select', this.tabChanged.bind(this));
231
            this.sandbox.on('sulu.header.language-changed', this.languageChanged.bind(this));
232
        },
233
234
        /**
235
         * Language changed event.
236
         *
237
         * @param {Object} item
238
         */
239
        languageChanged: function(item) {
240
            if (item.id === this.options.locale) {
241
                return;
242
            }
243
244
            this.sandbox.sulu.saveUserSetting(this.options.config.settingsKey, item.id);
245
246
            if (-1 === _(this.data.concreteLanguages).indexOf(item.id)) {
247
                OpenGhost.openGhost.call(this, this.data, this.translations.openGhostOverlay).then(function(copy, src) {
248
                    if (!!copy) {
249
                        CopyLocale.copyLocale.call(
250
                            this,
251
                            this.data.id,
252
                            src,
253
                            [item.id],
254
                            function() {
255
                                this.toEdit(item.id);
256
                            }.bind(this)
257
                        );
258
                    } else {
259
                        // new article will be created
260
                        this.toEdit(item.id);
261
                    }
262
                }.bind(this)).fail(function() {
263
                    // the open-ghost page got canceled, so reset the language changer
264
                    this.sandbox.emit('sulu.header.change-language', this.options.language);
265
                }.bind(this));
266
            } else {
267
                this.toEdit(item.id);
268
            }
269
        },
270
271
        /**
272
         * Tab changed event, save the new tab id to `this.options.content`.
273
         * Can be removed when issue #72 is solved: https://github.com/sulu/SuluArticleBundle/issues/72
274
         *
275
         * @param {Object} item
276
         */
277
        tabChanged: function(item) {
278
            this.options.content = item.id;
279
        },
280
281
        /**
282
         * Handles the error based on its error code.
283
         *
284
         * @param {Number} errorCode
285
         * @param {Object} data
286
         * @param {string} action
287
         */
288
        handleError: function(errorCode, data, action) {
0 ignored issues
show
Unused Code introduced by
The parameter action is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
Unused Code introduced by
The parameter data is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
289
            switch (errorCode) {
0 ignored issues
show
Unused Code introduced by
You have a switch statement with only a default case. This statement can be turned into a normal statement.
Loading history...
290
                default:
291
                    this.sandbox.emit('sulu.labels.error.show', 'labels.error.content-save-desc', 'labels.error');
292
                    this.sandbox.emit('sulu.header.toolbar.item.enable', 'save');
293
            }
294
        },
295
296
        deleteArticle: function() {
297
            this.sandbox.sulu.showDeleteDialog(function(wasConfirmed) {
298
                if (wasConfirmed) {
299
                    ArticleManager.remove(this.options.id, this.options.locale).then(function() {
300
                        this.toList();
301
                    }.bind(this));
302
                }
303
            }.bind(this));
304
        },
305
306
        toEdit: function(locale, id) {
307
            this.sandbox.emit('sulu.router.navigate', 'articles/' + (locale || this.options.locale) + '/edit:' + (id || this.options.id) + '/' + (this.options.content  || 'details'), true, true);
308
        },
309
310
        toList: function() {
311
            if (this.options.config.typeNames.length === 1) {
312
                this.sandbox.emit('sulu.router.navigate', 'articles/' + this.options.locale);
313
            } else {
314
                this.sandbox.emit('sulu.router.navigate', 'articles:' + (this.options.type || this.data.articleType) + '/' + this.options.locale);
315
            }
316
        },
317
318
        toAdd: function() {
319
            if (this.options.config.typeNames.length === 1) {
320
                this.sandbox.emit('sulu.router.navigate', 'articles/' + this.options.locale + '/add', true, true);
321
            } else {
322
                this.sandbox.emit('sulu.router.navigate', 'articles/' + this.options.locale + '/add:' + (this.options.type || this.data.articleType), true, true);
323
            }
324
        },
325
326
        save: function(action) {
327
            this.loadingSave();
328
329
            this.saveTab(action).then(function(data) {
330
                this.saved(data.id, data, action);
331
            }.bind(this));
332
        },
333
334
        setData: function(data) {
335
            this.data = data;
336
        },
337
338
        saveTab: function(action) {
339
            var promise = $.Deferred();
340
341
            // Display loading animation.
342
            this.sandbox.emit('sulu.header.toolbar.item.loading', 'save');
343
344
            this.sandbox.once('sulu.tab.saved', function(id, data) {
345
                promise.resolve(_.defaults(data, {type: null}));
346
            }.bind(this));
0 ignored issues
show
unused-code introduced by
The call to bind does not seem necessary since the function does not use this. Consider calling it directly.
Loading history...
347
348
            this.sandbox.emit('sulu.tab.save', action);
349
350
            return promise;
351
        },
352
353
        setHeaderBar: function(saved) {
354
            var saveDraft = !saved,
355
                savePublish = !saved,
356
                publish = !!saved && !this.data.publishedState;
357
358
            this.setSaveToolbarItems.call(this, 'saveDraft', saveDraft);
359
            this.setSaveToolbarItems.call(this, 'savePublish', savePublish);
360
            this.setSaveToolbarItems.call(this, 'publish', publish);
361
            this.setSaveToolbarItems.call(this, 'unpublish', !!this.data.published);
362
363
            if (!!saveDraft || !!savePublish || !!publish) {
364
                this.sandbox.emit('sulu.header.toolbar.item.enable', 'save', false);
365
            } else {
366
                this.sandbox.emit('sulu.header.toolbar.item.disable', 'save', false);
367
            }
368
369
            this.showState(!!this.data.published);
370
        },
371
372
        setSaveToolbarItems: function(item, value) {
373
            this.sandbox.emit('sulu.header.toolbar.item.' + (!!value ? 'enable' : 'disable'), item, false);
374
        },
375
376
        loadingSave: function() {
377
            this.sandbox.emit('sulu.header.toolbar.item.loading', 'save');
378
        },
379
380
        /**
381
         * Routes either to the list, article-add or article-edit, depending on the passed parameter.
382
         *
383
         * @param action {String} 'new', 'add' or null
384
         * @param toEdit {Boolean} if true and no action has been passed the method routes to 'edit'
385
         */
386
        afterSaveAction: function(action, toEdit) {
387
            if (action === 'back') {
388
                this.toList();
389
            } else if (action === 'new') {
390
                this.toAdd();
391
            } else if (toEdit) {
392
                this.toEdit(this.options.locale, this.data.id);
393
            }
394
        },
395
396
        showDraftLabel: function() {
397
            this.sandbox.emit('sulu.header.tabs.label.hide');
398
399
            if (this.hasDraft(this.data)) {
400
                return;
401
            }
402
403
            UserManager.find(this.data.changer).then(function(response) {
404
                this.sandbox.emit(
405
                    'sulu.header.tabs.label.show',
406
                    this.sandbox.util.sprintf(
407
                        this.translations.draftLabel,
408
                        {
409
                            changed: this.sandbox.date.format(this.data.changed, true),
410
                            user: response.username
411
                        }
412
                    ),
413
                    [
414
                        {
415
                            id: 'delete-draft',
416
                            title: this.translations.removeDraft,
417
                            skin: 'critical',
418
                            onClick: this.deleteDraft.bind(this)
419
                        }
420
                    ]
421
                );
422
            }.bind(this));
423
        },
424
425
        deleteDraft: function() {
426
            this.sandbox.sulu.showDeleteDialog(
427
                function(wasConfirmed) {
428
                    if (!wasConfirmed) {
429
                        return;
430
                    }
431
432
                    this.sandbox.emit('husky.label.header.loading');
433
434
                    ArticleManager.removeDraft(this.data.id, this.options.locale).always(function() {
435
                        this.sandbox.emit('sulu.header.toolbar.item.enable', 'edit');
436
                    }.bind(this)).then(function(response) {
437
                        this.sandbox.emit(
438
                            'sulu.router.navigate',
439
                            this.sandbox.mvc.history.fragment,
440
                            true,
441
                            true
442
                        );
443
                        this.saved(response.id, response);
444
                    }.bind(this)).fail(function() {
445
                        this.sandbox.emit('husky.label.header.reset');
446
                        this.sandbox.emit(
447
                            'sulu.labels.error.show',
448
                            'labels.error.remove-draft-desc',
449
                            'labels.error'
450
                        );
451
                    }.bind(this));
452
                }.bind(this),
453
                this.translations.deleteDraftConfirmTitle,
454
                this.translations.deleteDraftConfirmText
455
            )
456
        },
457
458
        hasDraft: function(data) {
459
            return !data.id || !!data.publishedState || !data.published;
460
        },
461
462
        getUrl: function(action) {
463
            var url = _.template(this.defaults.templates.url, {
464
                id: this.options.id,
465
                locale: this.options.locale
466
            });
467
468
            if (action) {
469
                url += '&action=' + action;
470
            }
471
472
            return url;
473
        },
474
475
        loadComponentData: function() {
476
            var promise = $.Deferred();
477
478
            if (!this.options.id) {
479
                promise.resolve({});
480
481
                return promise;
482
            }
483
484
            this.sandbox.util.load(this.getUrl()).done(function(data) {
485
                this.preview = Preview.initialize({});
486
                this.preview.start(
487
                    'Sulu\\Bundle\\ArticleBundle\\Document\\ArticleDocument',
488
                    this.options.id,
489
                    this.options.locale,
490
                    data
491
                );
492
493
                promise.resolve(data);
494
            }.bind(this));
495
496
            return promise;
497
        },
498
499
        destroy: function() {
500
            if (!!this.preview) {
501
                Preview.destroy(this.preview);
502
            }
503
        },
504
505
        showState: function(published) {
506
            if (!!published) {
507
                this.sandbox.emit('sulu.header.toolbar.item.hide', 'stateTest');
508
                this.sandbox.emit('sulu.header.toolbar.item.show', 'statePublished');
509
            } else {
510
                this.sandbox.emit('sulu.header.toolbar.item.hide', 'statePublished');
511
                this.sandbox.emit('sulu.header.toolbar.item.show', 'stateTest');
512
            }
513
        },
514
515
        unpublish: function() {
516
            this.sandbox.sulu.showConfirmationDialog({
517
                callback: function(wasConfirmed) {
518
                    if (!wasConfirmed) {
519
                        return;
520
                    }
521
522
                    this.sandbox.emit('sulu.header.toolbar.item.loading', 'edit');
523
524
                    ArticleManager.unpublish(this.data.id, this.options.locale).always(function() {
525
                        this.sandbox.emit('sulu.header.toolbar.item.enable', 'edit');
526
                    }.bind(this)).then(function(response) {
527
                        this.sandbox.emit(
528
                            'sulu.labels.success.show',
529
                            'labels.success.content-unpublish-desc',
530
                            'labels.success'
531
                        );
532
                        this.saved(response.id, response);
533
                    }.bind(this)).fail(function() {
534
                        this.sandbox.emit(
535
                            'sulu.labels.error.show',
536
                            'labels.error.content-unpublish-desc',
537
                            'labels.error'
538
                        );
539
                    }.bind(this));
540
                }.bind(this),
541
                title: this.translations.unpublishConfirmTitle,
542
                description: !!this.hasDraft(this.data) ?
543
                    this.translations.unpublishConfirmTextNoDraft :
544
                    this.translations.unpublishConfirmTextWithDraft
545
            });
546
        },
547
548
        copy: function() {
549
            ArticleManager.copy(this.data.id, this.options.locale).done(function(data) {
550
                this.toEdit(this.options.locale, data.id);
551
            }.bind(this));
552
        },
553
554
        saved: function(id, data, action) {
555
            this.setData(data);
556
557
            if (!this.options.id) {
558
                this.sandbox.sulu.viewStates.justSaved = true;
559
            } else {
560
                this.setHeaderBar(true);
561
                this.showDraftLabel();
562
563
                this.sandbox.emit('sulu.header.saved', data);
564
                this.sandbox.emit('sulu.labels.success.show', 'labels.success.content-save-desc', 'labels.success');
565
            }
566
567
            this.afterSaveAction(action, !this.options.id);
568
        },
569
570
        loadLocalizations: function() {
571
            this.sandbox.util.load('/admin/api/localizations').then(function(data) {
572
                this.localizations = data._embedded.localizations.map(function(localization) {
573
                    return {
574
                        id: localization.localization,
575
                        title: localization.localization
576
                    };
577
                });
578
            }.bind(this));
579
        },
580
581
        /**
582
         * Returns copy article from a given locale to a array of other locales url.
583
         *
584
         * @param {string} id
585
         * @param {string} src
586
         * @param {string[]} dest
587
         *
588
         * @returns {string}
589
         */
590
        getCopyLocaleUrl: function(id, src, dest) {
591
            return ArticleManager.getCopyLocaleUrl(id, src, dest);
592
        }
593
    }
594
});
595