Passed
Push — master ( 0d32dd...265c4a )
by Marcel
02:32
created

js/navigation.js   F

Complexity

Total Complexity 66
Complexity/F 2.36

Size

Lines of Code 475
Function Count 28

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 325
c 0
b 0
f 0
dl 0
loc 475
rs 3.12
wmc 66
mnd 38
bc 38
fnc 28
bpm 1.3571
cpm 2.3571
noi 2

How to fix   Complexity   

Complexity

Complex classes like js/navigation.js often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
/**
2
 * Analytics
3
 *
4
 * This file is licensed under the Affero General Public License version 3 or
5
 * later. See the LICENSE.md file.
6
 *
7
 * @author Marcel Scherello <[email protected]>
8
 * @copyright 2021 Marcel Scherello
9
 */
10
/** global: OCA */
11
/** global: OCP */
12
/** global: OC */
13
'use strict';
14
/**
15
 * @namespace OCA.Analytics.Navigation
16
 */
17
OCA.Analytics.Navigation = {
18
    quickstartValue: '',
19
    quickstartId: 0,
20
21
    init: function (datasetId) {
22
        document.getElementById('navigationDatasets').innerHTML = '<div style="text-align:center; padding-top:100px" class="get-metadata icon-loading"></div>';
23
        OCA.Analytics.Navigation.getDatasets(datasetId);
24
        OCA.Analytics.Backend.getDatasetDefinitions();
25
    },
26
27
    buildNavigation: function (data) {
28
        OCA.Analytics.Sidebar.hideSidebar();
29
        document.getElementById('navigationDatasets').innerHTML = '';
30
31
        let li = OCA.Analytics.Navigation.buildOverviewButton();
32
        document.getElementById('navigationDatasets').appendChild(li);
33
34
        let li2 = document.createElement('li');
35
        li2.classList.add('pinned', 'first-pinned');
36
        let a2 = document.createElement('a');
37
        a2.classList.add('icon-add', 'svg');
38
        a2.id = 'newDatasetButton';
39
        a2.addEventListener('click', OCA.Analytics.Navigation.handleNewButton);
40
        if (OCA.Analytics.isAdvanced) {
41
            a2.innerText = t('analytics', 'New dataset');
42
        } else {
43
            a2.innerText = t('analytics', 'New report');
44
        }
45
        li2.appendChild(a2);
46
        document.getElementById('navigationDatasets').appendChild(li2);
47
48
        if (!OCA.Analytics.isAdvanced) {
49
            let li3 = document.createElement('li');
50
            li3.classList.add('pinned', 'second-pinned');
51
            let a3 = document.createElement('a');
52
            a3.classList.add('icon-category-customization', 'svg');
53
            a3.innerText = t('analytics', 'Dataset maintenance');
54
            a3.addEventListener('click', OCA.Analytics.Navigation.handleAdvancedClicked);
55
            li3.appendChild(a3);
56
            document.getElementById('navigationDatasets').appendChild(li3);
57
        }
58
59
        for (let navigation of data) {
60
            OCA.Analytics.Navigation.buildNavigationRow(navigation);
61
        }
62
    },
63
64
    buildOverviewButton: function () {
65
        let li = document.createElement('li');
66
        let a = document.createElement('a');
67
        a.id = 'overviewButton'
68
        if (OCA.Analytics.isAdvanced) {
69
            a.classList.add('icon-view-previous', 'svg');
70
            a.innerText = t('analytics', 'Back to reports');
71
            a.addEventListener('click', OCA.Analytics.Navigation.handleReportClicked);
72
        } else {
73
            a.classList.add('icon-toggle-pictures', 'svg');
74
            a.innerText = t('analytics', 'Overview');
75
            a.addEventListener('click', OCA.Analytics.Navigation.handleOverviewButton);
76
        }
77
        li.appendChild(a);
78
        return li;
79
    },
80
81
    buildNavigationRow: function (data) {
82
        let li = document.createElement('li');
83
        let typeIcon;
84
85
        let a = document.createElement('a');
86
        a.setAttribute('href', '#/r/' + data['id']);
87
        a.style.position = 'relative';
88
        let typeINT = parseInt(data['type']);
89
        if (typeINT === OCA.Analytics.TYPE_INTERNAL_FILE || typeINT === OCA.Analytics.TYPE_EXCEL) {
90
            typeIcon = 'icon-file';
91
        } else if (typeINT === OCA.Analytics.TYPE_INTERNAL_DB) {
92
            typeIcon = 'icon-projects';
93
        } else if (typeINT === OCA.Analytics.TYPE_SHARED) {
94
            if (OCA.Analytics.isAdvanced) {
95
                // don´t show shared reports in advanced config mode at all as no config is possible
96
                return;
97
            }
98
            typeIcon = 'icon-shared';
99
        } else if (typeINT === OCA.Analytics.TYPE_EMPTY_GROUP) {
100
            typeIcon = 'icon-folder';
101
            li.classList.add('collapsible');
102
        } else {
103
            typeIcon = 'icon-external';
104
        }
105
        a.classList.add(typeIcon);
106
        a.classList.add('svg');
107
108
        a.innerText = data['name'];
109
        a.dataset.id = data['id'];
110
        a.dataset.type = data['type'];
111
        a.dataset.name = data['name'];
112
        li.appendChild(a);
113
114
        let ulSublist = document.createElement('ul');
115
        ulSublist.id = 'dataset-' + data['id'];
116
117
        if (parseInt(data['favorite']) === 1) {
118
            let divFav = OCA.Analytics.Navigation.buildFavoriteIcon(data['id'], data['name'])
119
            a.appendChild(divFav);
120
        }
121
122
        if (!OCA.Analytics.isAdvanced) {
123
            let divUtils = OCA.Analytics.Navigation.buildNavigationUtils(data);
124
            let divMenu = OCA.Analytics.Navigation.buildNavigationMenu(data);
125
            li.appendChild(divUtils);
126
            li.appendChild(divMenu);
127
        }
128
129
        if (typeINT === OCA.Analytics.TYPE_EMPTY_GROUP) {
130
            li.appendChild(ulSublist);
131
            a.addEventListener('click', OCA.Analytics.Navigation.handleGroupClicked);
132
        } else {
133
            a.addEventListener('click', OCA.Analytics.Navigation.handleNavigationClicked);
134
        }
135
136
        // add navigation row to navigation list or to an existing parent node
137
        let categoryList;
138
        if (parseInt(data['parent']) !== 0 && document.getElementById('dataset-' + data['parent'])) {
139
            categoryList = document.getElementById('dataset-' + data['parent']);
140
            categoryList.appendChild(li);
141
        } else {
142
            categoryList = document.getElementById('navigationDatasets');
143
            if (parseInt(data['favorite']) === 1) {
144
                categoryList.insertBefore(li, categoryList.children[2]);
145
            } else {
146
                categoryList.appendChild(li);
147
            }
148
        }
149
150
    },
151
152
    buildFavoriteIcon: function (id, name) {
153
        let divFav = document.createElement('div');
154
        divFav.classList.add('favorite-mark');
155
        divFav.id = 'fav-' + id;
156
        let spanFav = document.createElement('span');
157
        spanFav.classList.add('icon', 'icon-starred', 'favorite-star');
158
        spanFav.dataset.testing = 'favI' + name;
159
        divFav.appendChild(spanFav)
160
        return divFav;
161
    },
162
163
    buildNavigationUtils: function (data) {
164
        let divUtils = document.createElement('div');
165
        divUtils.classList.add('app-navigation-entry-utils');
166
        let ulUtils = document.createElement('ul');
167
168
        // add indicators when a dataload or schedule is existing
169
        if (OCA.Analytics.isAdvanced) {
170
            if (data.schedules && parseInt(data.schedules) !== 0) {
171
                let liScheduleButton = document.createElement('li');
172
                liScheduleButton.classList.add('app-navigation-entry-utils-menu-button');
173
                let ScheduleButton = document.createElement('button');
174
                ScheduleButton.classList.add('icon-history', 'toolTip');
175
                ScheduleButton.setAttribute('title', t('analytics', 'scheduled dataload'));
176
                liScheduleButton.appendChild(ScheduleButton);
177
                ulUtils.appendChild(liScheduleButton);
178
            }
179
            if (data.dataloads && parseInt(data.dataloads) !== 0) {
180
                let liScheduleButton = document.createElement('li');
181
                liScheduleButton.classList.add('app-navigation-entry-utils-menu-button');
182
                let ScheduleButton = document.createElement('button');
183
                ScheduleButton.classList.add('icon-category-workflow', 'toolTip');
184
                ScheduleButton.setAttribute('title', t('analytics', 'Dataload'));
185
                liScheduleButton.appendChild(ScheduleButton);
186
                ulUtils.appendChild(liScheduleButton);
187
            }
188
        }
189
190
        let liMenuButton = document.createElement('li');
191
        liMenuButton.classList.add('app-navigation-entry-utils-menu-button');
192
        let button = document.createElement('button');
193
        button.addEventListener('click', OCA.Analytics.Navigation.handleOptionsClicked);
194
        button.dataset.id = data.id;
195
        button.dataset.name = data.name;
196
        button.dataset.type = data.type;
197
        button.classList.add('menuButton');
198
        liMenuButton.appendChild(button);
199
        ulUtils.appendChild(liMenuButton);
200
        divUtils.appendChild(ulUtils);
201
202
        return divUtils;
203
    },
204
205
    buildNavigationMenu: function (data) {
206
        // clone the DOM template
207
        let navigationMenu = document.importNode(document.getElementById('templateNavigationMenu').content, true);
208
209
        let menu = navigationMenu.getElementById('navigationMenu');
210
        menu.dataset.id = data.id;
211
        menu.dataset.type = data.type;
212
        menu.dataset.name = data.name;
213
214
        let edit = navigationMenu.getElementById('navigationMenuEdit');
215
        edit.addEventListener('click', OCA.Analytics.Navigation.handleBasicClicked);
216
        edit.children[1].innerText = t('analytics', 'Basic settings');
217
        edit.dataset.testing = 'basic' + data.name;
218
219
        let favorite = navigationMenu.getElementById('navigationMenueFavorite');
220
        favorite.addEventListener('click', OCA.Analytics.Navigation.handleFavoriteClicked);
221
        favorite.dataset.testing = 'fav' + data.name;
222
223
/*
224
        let advanced = navigationMenu.getElementById('navigationMenuAdvanced');
225
        if (OCA.Analytics.isAdvanced) {
226
            edit.remove();
227
            advanced.addEventListener('click', OCA.Analytics.Navigation.handleReportClicked);
228
            advanced.children[0].classList.add('icon-category-monitoring');
229
            advanced.children[1].innerText = t('analytics', 'Back to report');
230
            advanced.dataset.testing = 'back' + data.name;
231
        } else {
232
            advanced.addEventListener('click', OCA.Analytics.Navigation.handleAdvancedClicked);
233
            advanced.children[0].classList.add('icon-category-customization');
234
            advanced.children[1].innerText = t('analytics', 'Advanced');
235
            advanced.dataset.testing = 'adv' + data.name;
236
        }
237
*/
238
239
        if (parseInt(data.favorite) === 1) {
240
            favorite.firstElementChild.classList.replace('icon-star', 'icon-starred');
241
            favorite.children[1].innerHTML = t('analytics', 'Remove from favorites');
242
        } else {
243
            favorite.children[1].innerHTML = t('analytics', 'Add to favorites');
244
        }
245
246
        let deleteReport = navigationMenu.getElementById('navigationMenuDelete');
247
        deleteReport.dataset.id = data.id;
248
        deleteReport.addEventListener('click', OCA.Analytics.Sidebar.Report.handleDeleteButton);
249
250
        let unshareReport = navigationMenu.getElementById('navigationMenuUnshare');
251
252
        if (parseInt(data['type']) === OCA.Analytics.TYPE_EMPTY_GROUP) {
253
            unshareReport.remove();
254
            favorite.remove();
255
            deleteReport.children[1].innerHTML = t('analytics', 'Delete folder');
256
            //advanced.remove();
257
        } else if (parseInt(data['type']) === OCA.Analytics.TYPE_SHARED) {
258
            advanced.remove();
259
            deleteReport.remove();
260
            edit.remove();
261
            unshareReport.dataset.shareId = data.shareId;
262
            unshareReport.addEventListener('click', OCA.Analytics.Navigation.handleUnshareButton);
263
        } else {
264
            unshareReport.remove();
265
        }
266
267
        return navigationMenu;
268
    },
269
270
    handleNewButton: function () {
271
        if (OCA.Analytics.isAdvanced) {
272
            OCA.Analytics.Wizard.sildeArray = [
273
                ['',''],
274
                ['wizardDatasetGeneral', OCA.Analytics.Advanced.Dataset.wizard],
275
            ];
276
            OCA.Analytics.Wizard.show();
277
        } else {
278
            OCA.Analytics.Wizard.sildeArray = [
279
                ['',''],
280
                ['wizardNewGeneral', OCA.Analytics.Sidebar.Report.wizard],
281
                ['wizardNewType',''],
282
                ['wizardNewVisual','']
283
            ];
284
            OCA.Analytics.Wizard.show();
285
        }
286
    },
287
288
    handleOverviewButton: function () {
289
        OCA.Analytics.Sidebar.hideSidebar();
290
        if (document.querySelector('#navigationDatasets .active')) {
291
            document.querySelector('#navigationDatasets .active').classList.remove('active');
292
        }
293
        OCA.Analytics.UI.hideElement('analytics-content');
294
        OCA.Analytics.UI.showElement('analytics-intro');
295
        document.getElementById('ulAnalytics').innerHTML = '';
296
        window.location.href = '#'
297
        OCA.Analytics.Dashboard.init()
298
    },
299
300
    handleNavigationClicked: function (evt) {
301
        if (document.querySelector('.app-navigation-entry-menu.open') !== null) {
302
            document.querySelector('.app-navigation-entry-menu.open').classList.remove('open');
303
        }
304
        let activeCategory = document.querySelector('#navigationDatasets .active');
305
        if (evt) {
306
            if (activeCategory) {
307
                activeCategory.classList.remove('active');
308
            }
309
            evt.target.parentElement.classList.add('active');
310
        }
311
        if (OCA.Analytics.isAdvanced) {
312
            OCA.Analytics.Advanced.showSidebar(evt);
313
            evt.stopPropagation();
314
        } else {
315
            document.getElementById('filterVisualisation').innerHTML = '';
316
            if (typeof (OCA.Analytics.currentReportData.options) !== 'undefined') {
317
                // reset any user-filters and display the filters stored for the report
318
                delete OCA.Analytics.currentReportData.options;
319
            }
320
            OCA.Analytics.unsavedFilters = false;
321
            OCA.Analytics.Sidebar.hideSidebar();
322
            OCA.Analytics.Backend.getData();
323
        }
324
    },
325
326
    handleOptionsClicked: function (evt) {
327
        OCA.Analytics.UI.hideReportMenu();
328
        let openMenu;
329
        if (document.querySelector('.app-navigation-entry-menu.open') !== null) {
330
            openMenu = document.querySelector('.app-navigation-entry-menu.open').previousElementSibling.firstElementChild.firstElementChild.firstElementChild.dataset.id;
331
            document.querySelector('.app-navigation-entry-menu.open').classList.remove('open');
332
        }
333
        if (openMenu !== evt.target.dataset.id) {
334
            evt.target.parentElement.parentElement.parentElement.nextElementSibling.classList.add('open');
335
        }
336
    },
337
338
    handleBasicClicked: function (evt) {
339
        if (document.querySelector('.app-navigation-entry-menu.open') !== null) {
340
            document.querySelector('.app-navigation-entry-menu.open').classList.remove('open');
341
        }
342
        evt.stopPropagation();
343
        OCA.Analytics.Sidebar.showSidebar(evt);
344
    },
345
346
    handleAdvancedClicked: function (evt) {
347
        window.location = OC.generateUrl('apps/analytics/a/#');
348
        evt.stopPropagation();
349
    },
350
351
    handleFavoriteClicked: function (evt) {
352
        let datasetId = evt.target.closest('div').dataset.id;
353
        let icon = evt.target.parentNode.firstElementChild;
354
        let isFavorite = 'false';
355
356
        if (icon.classList.contains('icon-star')) {
357
            icon.classList.replace('icon-star', 'icon-starred');
358
            evt.target.parentNode.children[1].innerHTML = t('analytics', 'Remove from favorites');
359
            isFavorite = 'true';
360
361
            let divFav = OCA.Analytics.Navigation.buildFavoriteIcon(datasetId, '');
362
            evt.target.closest('div').parentElement.firstElementChild.appendChild(divFav);
363
364
        } else {
365
            icon.classList.replace('icon-starred', 'icon-star');
366
            evt.target.parentNode.children[1].innerHTML = t('analytics', 'Add to favorites');
367
            document.getElementById('fav-' + datasetId).remove();
368
        }
369
        OCA.Analytics.Navigation.favoriteUpdate(datasetId, isFavorite);
370
        document.querySelector('.app-navigation-entry-menu.open').classList.remove('open');
371
    },
372
373
    handleReportClicked: function (evt) {
374
        const datasetId = evt.target.closest('div').dataset.id;
375
        window.location = OC.generateUrl('apps/analytics/') + '#/r/' + datasetId;
376
        evt.stopPropagation();
377
    },
378
379
    handleGroupClicked: function (evt) {
380
        if (evt.target.parentNode.classList.contains('open')) {
381
            evt.target.parentNode.classList.remove('open');
382
        } else {
383
            evt.target.parentNode.classList.add('open');
384
        }
385
        evt.stopPropagation();
386
    },
387
388
    handleImportButton: function () {
389
        const mimeparts = ['text/plain'];
390
        OC.dialogs.filepicker(t('analytics', 'Select file'), OCA.Analytics.Sidebar.Report.import.bind(this), false, mimeparts, true, 1);
391
    },
392
393
    handleUnshareButton: function (evt) {
394
        let shareId = evt.target.parentNode.dataset.shareId;
395
396
        let xhr = new XMLHttpRequest();
397
        xhr.open('DELETE', OC.generateUrl('apps/analytics/share/' + shareId, true), true);
398
        xhr.setRequestHeader('requesttoken', OC.requestToken);
399
        xhr.setRequestHeader('OCS-APIREQUEST', 'true');
400
        xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
401
402
        xhr.onreadystatechange = function () {
403
            if (xhr.readyState === 4) {
404
                OCA.Analytics.Navigation.init();
405
            }
406
        };
407
408
        xhr.send();
409
    },
410
411
    getDatasets: function (datasetId) {
412
        let datatype;
413
        if (OCA.Analytics.isAdvanced) {
414
            datatype = 'dataset';
415
        } else {
416
            datatype = 'report';
417
        }
418
        $.ajax({
419
            type: 'GET',
420
            url: OC.generateUrl('apps/analytics/' + datatype),
421
            success: function (data) {
422
                OCA.Analytics.Navigation.buildNavigation(data);
423
                OCA.Analytics.reports = data;
424
                if (datasetId && data.indexOf(data.find(o => o.id === datasetId)) !== -1) {
425
                    OCA.Analytics.Sidebar.hideSidebar();
426
                    let navigationItem = document.querySelector('#navigationDatasets [data-id="' + datasetId + '"]');
427
                    if (navigationItem.parentElement.parentElement.parentElement.classList.contains('collapsible')) {
428
                        navigationItem.parentElement.parentElement.parentElement.classList.add('open');
429
                    }
430
                    navigationItem.click();
431
                }
432
            }
433
        });
434
    },
435
436
    favoriteUpdate: function (datasetId, isFavorite) {
437
        let params = 'favorite=' + isFavorite;
438
        let xhr = new XMLHttpRequest();
439
        xhr.open('POST', OC.generateUrl('apps/analytics/favorite/' + datasetId, true), true);
440
        xhr.setRequestHeader('requesttoken', OC.requestToken);
441
        xhr.setRequestHeader('OCS-APIREQUEST', 'true');
442
        xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
443
        xhr.send(params);
444
    },
445
};
446
447
document.addEventListener('DOMContentLoaded', function () {
448
    if (!OCA.Analytics.isAdvanced) {
449
        OCA.Analytics.WhatsNew.whatsnew();
450
        document.getElementById('wizardStart').addEventListener('click', OCA.Analytics.Wizard.showFirstStart);
451
        if (OCA.Analytics.Core.getInitialState('wizard') !== '1') {
452
            OCA.Analytics.Wizard.showFirstStart();
453
        }
454
    }
455
    document.getElementById('importDatasetButton').addEventListener('click', OCA.Analytics.Navigation.handleImportButton);
456
});