Completed
Pull Request — develop (#151)
by
unknown
27:07
created

main.js ➔ ... ➔ .openCategorySelectionOverlay   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 24
rs 8.9713
c 0
b 0
f 0
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
    'underscore',
12
    'services/husky/storage',
13
    'sulucontent/components/copy-locale-overlay/main',
14
    'sulucontent/components/open-ghost-overlay/main',
15
    'services/suluarticle/article-manager'
16
], function(_, storage, CopyLocale, OpenGhost, ArticleManager) {
17
18
    'use strict';
19
20
    var defaults = {
21
        options: {
22
            config: {},
23
            storageName: 'articles'
24
        },
25
26
        templates: {
27
            list: [
28
                '<div class="list-toolbar-container"></div>',
29
                '<div class="list-info"></div>',
30
                '<div class="datagrid-container"></div>',
31
                '<div class="dialog"></div>'
32
            ].join(''),
33
            draftIcon: '<span class="draft-icon" title="<%= title %>"/>',
34
            publishedIcon: '<span class="published-icon" title="<%= title %>"/>',
35
            route: [
36
                'articles',
37
                '<% if (!!type) { %>:<%=type%><% } %>',
38
                '/<%=locale%>'
39
            ].join('')
40
        },
41
42
        translations: {
43
            headline: 'sulu_article.list.title',
44
            unpublished: 'public.unpublished',
45
            publishedWithDraft: 'public.published-with-draft',
46
            filterMe: 'sulu_article.list.filter.me',
47
            filterAll: 'sulu_article.list.filter.all',
48
            filterByAuthor: 'sulu_article.list.filter.by-author',
49
            filterByCategory: 'sulu_article.list.filter.by-category',
50
            openGhostOverlay: {
51
                info: 'sulu_article.settings.open-ghost-overlay.info',
52
                new: 'sulu_article.settings.open-ghost-overlay.new',
53
                copy: 'sulu_article.settings.open-ghost-overlay.copy',
54
                ok: 'sulu_article.settings.open-ghost-overlay.ok'
55
            }
56
        }
57
    };
58
59
60
    return {
61
62
        defaults: defaults,
63
64
        data: {
65
            contactId: null
66
        },
67
68
        header: function() {
69
            this.storage = storage.get('sulu', this.options.storageName);
70
71
            var types = this.options.config.types,
72
                typeNames = this.options.config.typeNames,
73
                button = {
74
                    icon: 'plus-circle',
75
                    title: 'public.add-new'
76
                },
77
                tabs = false,
78
                tabItems,
79
                tabPreselect = null,
80
                preselectedType = this.options.type || this.storage.getWithDefault('type', null);
81
82
            if (1 === typeNames.length) {
83
                button.callback = function() {
84
                    this.toAdd(typeNames[0]);
85
                }.bind(this);
86
            } else {
87
                button.dropdownItems = _.map(typeNames, function(type) {
88
                    return {
89
                        title: types[type].title,
90
                        callback: function() {
91
                            this.toAdd(type);
92
                        }.bind(this)
93
                    };
94
                }.bind(this));
95
96
                tabItems = [];
97
98
                // add tab item 'all' if parameter is true
99
                if (this.options.config.displayTabAll === true) {
100
                    tabItems.push(
101
                        {
102
                            name: 'public.all',
103
                            key: null
104
                        }
105
                    );
106
                }
107
108
                // add tab item for each type
109
                _.each(typeNames, function(type) {
110
                    tabItems.push(
111
                        {
112
                            id: type,
113
                            name: types[type].title,
114
                            key: type
115
                        }
116
                    );
117
118
                    if (type === preselectedType) {
119
                        tabPreselect = types[type].title;
120
                    }
121
                }.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...
122
123
                tabs = {
124
                    componentOptions: {
125
                        callback: this.typeChange.bind(this),
126
                        preselector: 'name',
127
                        preselect: tabPreselect
128
                    },
129
                    data: tabItems
130
                };
131
            }
132
133
            return {
134
                noBack: true,
135
136
                tabs: tabs,
137
138
                toolbar: {
139
                    buttons: {
140
                        addArticle: {options: button},
141
                        deleteSelected: {}
142
                    },
143
144
                    languageChanger: {
145
                        data: this.options.config.languageChanger,
146
                        preSelected: this.options.locale
147
                    }
148
                }
149
            };
150
        },
151
152
        layout: {
153
            content: {
154
                width: 'max'
155
            }
156
        },
157
158
        initialize: function() {
159
            if (!!this.options.type) {
160
                this.storage.set('type', this.options.type);
161
            } else if (this.storage.has('type')) {
162
                var url = this.templates.route({type: this.storage.get('type'), locale: this.options.locale});
163
                this.sandbox.emit('sulu.router.navigate', url, false, false);
164
                this.options.type = this.storage.get('type');
165
            }
166
167
            this.render();
168
169
            this.bindCustomEvents();
170
        },
171
172
        render: function() {
173
            this.$el.html(this.templates.list());
174
175
            var urlArticleApi = '/admin/api/articles?sortBy=authored&sortOrder=desc&locale=' + this.options.locale + (this.options.type ? ('&type=' + this.options.type) : '');
176
            var filter = this.getFilterFromStorage();
177
            var filterTitle = this.getFilterTitle(filter.filterKey, filter.contact, filter.category);
178
179
            if (!!filter.contact) {
180
                urlArticleApi += '&contactId=' + filter.contact.id;
181
            }
182
            if (!!filter.category) {
183
                urlArticleApi += '&categoryId=' + filter.category.id;
184
            }
185
186
            this.sandbox.sulu.initListToolbarAndList.call(this,
187
                'article',
188
                '/admin/api/articles/fields',
189
                {
190
                    el: this.$find('.list-toolbar-container'),
191
                    instanceName: 'articles',
192
                    template: this.retrieveListToolbarTemplate(filterTitle)
193
                },
194
                {
195
                    el: this.sandbox.dom.find('.datagrid-container'),
196
                    url: urlArticleApi,
197
                    storageName: this.options.storageName,
198
                    searchInstanceName: 'articles',
199
                    searchFields: ['title'],
200
                    resultKey: 'articles',
201
                    instanceName: 'articles',
202
                    actionCallback: function(id, article) {
203
                        if ('ghost' === article.localizationState.state) {
204
                            ArticleManager.load(id, this.options.locale).then(function(response) {
205
                                OpenGhost.openGhost.call(
206
                                    this,
207
                                    response,
208
                                    this.translations.openGhostOverlay
209
                                ).then(
210
                                    function(copy, src) {
211
                                        if (!!copy) {
212
                                            CopyLocale.copyLocale.call(
213
                                                this,
214
                                                id,
215
                                                src,
216
                                                [this.options.locale],
217
                                                function() {
218
                                                    this.toEdit(id);
219
                                                }.bind(this)
220
                                            );
221
                                        } else {
222
                                            this.toEdit(id);
223
                                        }
224
                                    }.bind(this)
225
                                );
226
                            }.bind(this)).fail(function(xhr) {
227
                                this.sandbox.emit('sulu.article.error', xhr.status, data);
0 ignored issues
show
Bug introduced by
The variable data seems to be never declared. If this is a global, consider adding a /** global: data */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
228
                            }.bind(this));
229
                        } else {
230
                            this.toEdit(id);
231
                        }
232
                    }.bind(this),
233
                    viewOptions: {
234
                        table: {
235
                            actionIconColumn: 'title',
236
                            badges: [
237
                                {
238
                                    column: 'title',
239
                                    callback: function(item, badge) {
240
                                        if (!!item.localizationState &&
241
                                            item.localizationState.state === 'ghost' &&
242
                                            item.localizationState.locale !== this.options.locale
243
                                        ) {
244
                                            badge.title = item.localizationState.locale;
245
246
                                            return badge;
247
                                        }
248
249
                                        return false;
250
                                    }.bind(this)
251
                                },
252
                                {
253
                                    column: 'title',
254
                                    callback: function(item, badge) {
255
                                        var icons = '',
256
                                            tooltip = this.translations.unpublished;
257
258
                                        if (!!item.published && !item.publishedState) {
259
                                            tooltip = this.translations.publishedWithDraft;
260
                                            icons += this.templates.publishedIcon({title: tooltip});
261
                                        }
262
                                        if (!item.publishedState) {
263
                                            icons += this.templates.draftIcon({title: tooltip});
264
                                        }
265
266
                                        badge.title = icons;
267
                                        badge.cssClass = 'badge-none';
268
269
                                        return badge;
270
                                    }.bind(this)
271
                                }
272
                            ]
273
                        }
274
                    }
275
                }
276
            );
277
        },
278
279
        toEdit: function(id, locale) {
280
            this.sandbox.emit('sulu.router.navigate', 'articles/' + (locale || this.options.locale) + '/edit:' + id + '/details');
281
        },
282
283
        toAdd: function(type, locale) {
284
            this.sandbox.emit('sulu.router.navigate', 'articles/' + (locale || this.options.locale) + '/add' + (this.options.config.typeNames.length > 1 ? (':' + type) : ''));
285
        },
286
287
        toList: function(locale) {
288
            if (this.options.config.typeNames.length === 1 || !this.options.type) {
289
                this.sandbox.emit('sulu.router.navigate', 'articles/' + (locale || this.options.locale));
290
            } else {
291
                this.sandbox.emit('sulu.router.navigate', 'articles:' + (this.options.type) + '/' + (locale || this.options.locale));
292
            }
293
        },
294
295
        deleteItems: function(ids) {
296
            ArticleManager.remove(ids, this.options.locale).then(function() {
297
                _.each(ids, function(id) {
298
                    this.sandbox.emit('husky.datagrid.articles.record.remove', id);
299
                }.bind(this));
300
            }.bind(this));
301
        },
302
303
        typeChange: function(item) {
304
            var url = this.templates.route({type: item.key, locale: this.options.locale});
305
            // Save the tab key. Can be removed when issue #72 is solved:
306
            // https://github.com/sulu/SuluArticleBundle/issues/72
307
            this.options.type = item.key;
308
309
            this.sandbox.emit('husky.datagrid.articles.url.update', {page: 1, type: item.key});
310
            this.sandbox.emit('sulu.router.navigate', url, false, false);
311
312
            this.storage.set('type', item.key);
313
        },
314
315
        /**
316
         * Returns copy article from a given locale to a array of other locales url.
317
         *
318
         * @param {string} id
319
         * @param {string} src
320
         * @param {string[]} dest
321
         *
322
         * @returns {string}
323
         */
324
        getCopyLocaleUrl: function(id, src, dest) {
325
            return ArticleManager.getCopyLocaleUrl(id, src, dest);
326
        },
327
328
        bindCustomEvents: function() {
329
            this.sandbox.on('husky.datagrid.articles.number.selections', function(number) {
330
                var postfix = number > 0 ? 'enable' : 'disable';
331
                this.sandbox.emit('sulu.header.toolbar.item.' + postfix, 'deleteSelected', false);
332
            }.bind(this));
333
334
            this.sandbox.on('sulu.toolbar.delete', function() {
335
                this.sandbox.emit('husky.datagrid.articles.items.get-selected', this.deleteItems.bind(this));
336
            }.bind(this));
337
338
            this.sandbox.on('sulu.header.language-changed', function(item) {
339
                if (item.id === this.options.locale) {
340
                    return;
341
                }
342
343
                this.sandbox.sulu.saveUserSetting(this.options.config.settingsKey, item.id);
344
                this.toList(item.id);
345
            }.bind(this));
346
347
            this.sandbox.on('husky.toolbar.articles.initialized', function() {
348
                this.sandbox.emit('husky.toolbar.articles.item.mark', this.getFilterFromStorage().filterKey);
349
            }.bind(this));
350
        },
351
352
        /**
353
         * Generates list toolbar buttons.
354
         *
355
         * @param {String} title
356
         */
357
        retrieveListToolbarTemplate: function(title) {
358
            return this.sandbox.sulu.buttons.get({
359
                settings: {
360
                    options: {
361
                        dropdownItems: [
362
                            {
363
                                type: 'columnOptions'
364
                            }
365
                        ]
366
                    }
367
                },
368
                filter: {
369
                    options: {
370
                        icon: 'filter',
371
                        group: 2,
372
                        title: title,
373
                        showTitle: true,
374
                        dropdownOptions: {
375
                            idAttribute: 'id',
376
                            markSelected: true,
377
                            changeButton: false
378
                        },
379
                        dropdownItems: [
380
                            {
381
                                id: 'all',
382
                                title: this.translations.filterAll,
383
                                callback: function() {
384
                                    this.applyFilterToList.call(
385
                                        this,
386
                                        'all',
387
                                        null
388
                                    );
389
                                }.bind(this)
390
                            },
391
                            {
392
                                id: 'me',
393
                                title: this.translations.filterMe,
394
                                callback: function() {
395
                                    this.applyFilterToList.call(
396
                                        this,
397
                                        'me',
398
                                        this.sandbox.sulu.user.contact
399
                                    );
400
                                }.bind(this)
401
                            },
402
                            {
403
                                id: 'filterByAuthor',
404
                                title: this.translations.filterByAuthor + '...',
405
                                callback: this.openContactSelectionOverlay.bind(this)
406
                            },
407
                            {
408
                                divider: true
409
                            },
410
                            {
411
                                id: 'filterByCategory',
412
                                title: this.translations.filterByCategory,
413
                                callback: this.openCategorySelectionOverlay.bind(this)
414
                            }
415
                        ]
416
                    }
417
                }
418
            });
419
        },
420
421
        /**
422
         * Opens contact selection overlay.
423
         */
424
        openContactSelectionOverlay: function() {
425
            var $container = $('<div/>');
426
427
            this.$el.append($container);
428
429
            this.sandbox.start([{
430
                name: 'articles/list/contact-selection@suluarticle',
431
                options: {
432
                    el: $container,
433
                    locale: this.options.locale,
434
                    data: {
435
                        contact: this.getFilterFromStorage().contact
436
                    },
437
                    selectCallback: function(data) {
438
                        this.applyFilterToList.call(
439
                            this,
440
                            'filterByAuthor',
441
                            data.contactItem
442
                        );
443
                    }.bind(this)
444
                }
445
            }]);
446
        },
447
448
        /**
449
         * Opens contact selection overlay.
450
         */
451
        openCategorySelectionOverlay: function() {
452
            var $container = $('<div/>');
453
454
            this.$el.append($container);
455
456
            this.sandbox.start([{
457
                name: 'articles/list/category-selection@suluarticle',
458
                options: {
459
                    el: $container,
460
                    locale: this.options.locale,
461
                    data: {
462
                        category: this.getFilterFromStorage().category
463
                    },
464
                    selectCallback: function(data) {
465
                        this.applyFilterToList.call(
466
                            this,
467
                            'category',
468
                            null,
469
                            data.categoryItem
470
                        );
471
                    }.bind(this)
472
                }
473
            }]);
474
        },
475
476
        /**
477
         * Emits the url update event for the list, changes the title of the filter button
478
         * and saves the selected contact id in the storage.
479
         *
480
         * @param {string} filterKey
481
         * @param {Object} contact
482
         * @param {Object} category
483
         */
484
        applyFilterToList: function(filterKey, contact, category) {
485
            this.storage.set('filter', {
486
                contact: contact,
487
                category: category,
488
                filterKey: filterKey
489
            });
490
491
            var update = {
492
                contactId: contact ? contact.id : null,
493
                categoryId: category ? category.id : null
494
            };
495
496
            this.sandbox.emit('husky.datagrid.articles.url.update', update);
497
            this.sandbox.emit('husky.toolbar.articles.button.set', 'filter', {
498
                title: this.getFilterTitle(filterKey, contact, category)
499
            });
500
        },
501
502
        /**
503
         * Retrieves the contact filter from the storage.
504
         *
505
         * @returns {Object}
506
         */
507
        getFilterFromStorage: function() {
508
            return this.storage.getWithDefault('filter', {filterKey: 'all', contact: null, category: null});
509
        },
510
511
        /**
512
         * Returns the title for the contact filter button.
513
         *
514
         * @param {String} filterKey
515
         * @param {Object} contact
516
         * @param {Object} category
517
         * @return {String}
518
         */
519
        getFilterTitle: function(filterKey, contact, category) {
520
            var title = '';
521
522
            switch(filterKey) {
0 ignored issues
show
Coding Style introduced by
As per coding-style, switch statements should have a default case.
Loading history...
523
                case 'all':
524
                    title = this.translations.filterAll;
525
                    break;
526
                case 'filterByAuthor':
527
                    title = this.translations.filterByAuthor + ' ' + contact.firstName + ' ' + contact.lastName;
528
                    break;
529
                case 'me':
530
                    title = this.translations.filterMe;
531
                    break;
532
                case 'category':
533
                    title = this.translations.filterByCategory + ' ' + category.name;
534
                    break;
535
            }
536
537
            return title;
538
        }
539
    };
540
});
541