Passed
Push — master ( 3660fa...998d5d )
by Marcel
03:22
created

js/navigation.js   C

Complexity

Total Complexity 55
Complexity/F 2.2

Size

Lines of Code 386
Function Count 25

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 277
c 0
b 0
f 0
dl 0
loc 386
rs 6
wmc 55
mnd 30
bc 30
fnc 25
bpm 1.2
cpm 2.2
noi 1

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 2020 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" className="get-metadata icon-loading"></div>';
23
        OCA.Analytics.Navigation.getDatasets(datasetId);
24
    },
25
26
    createDemoReport: function () {
27
        OCA.Analytics.Backend.createDataset('DEMO');
28
    },
29
30
    createDemoGithubReport: function () {
31
        OC.dialogs.prompt(
32
            t('analytics', 'Crate a report which to monitor the realtime download count of your GitHub repository. Enter the GitHub User/Repository. The \'/\' is important.'),
33
            t('analytics', 'Quickstart: GitHub download statistics'),
34
            function (button, val) {
35
                if (button === true) {
36
                    OCA.Analytics.Navigation.quickstartTemp = val;
37
                    $.ajax({
38
                        type: 'POST',
39
                        url: OC.generateUrl('apps/analytics/dataset'),
40
                        data: {
41
                            'file': 'DEMO',
42
                        },
43
                        success: function (data) {
44
                            OCA.Analytics.Navigation.quickstartId = data;
45
                            let datasetName = OCA.Analytics.Navigation.quickstartTemp.split("/")[1];
46
                            $.ajax({
47
                                type: 'PUT',
48
                                url: OC.generateUrl('apps/analytics/dataset/') + data,
49
                                data: {
50
                                    'name': datasetName[0].toUpperCase() + datasetName.substring(1),
51
                                    'subheader': 'GitHub download statistics',
52
                                    'parent': 0,
53
                                    'type': OCA.Analytics.TYPE_GIT,
54
                                    'link': OCA.Analytics.Navigation.quickstartTemp,
55
                                    'visualization': 'ct',
56
                                    'chart': 'column',
57
                                    'chartoptions': '',
58
                                    'dataoptions': '',
59
                                    'dimension1': '',
60
                                    'dimension2': '',
61
                                    'value': ''
62
                                },
63
                                success: function () {
64
                                    OCA.Analytics.Navigation.init(OCA.Analytics.Navigation.quickstartId);
65
                                }
66
                            });
67
                        }
68
                    });
69
                }
70
            },
71
            true,
72
            "user/repo");
73
    },
74
75
    buildNavigation: function (data) {
76
        document.getElementById('navigationDatasets').innerHTML = '';
77
        let li = document.createElement('li');
78
        let a = document.createElement('a');
79
        a.classList.add('icon-toggle-pictures');
80
        a.innerText = t('analytics', 'Overview');
81
        a.addEventListener('click', OCA.Analytics.Navigation.handleOverviewButton);
82
        li.appendChild(a);
83
        document.getElementById('navigationDatasets').appendChild(li);
84
85
        let li2 = document.createElement('li');
86
        let a2 = document.createElement('a');
87
        a2.classList.add('icon-add');
88
        a2.innerText = t('analytics', 'New report');
89
90
        a2.id = 'newDatasetButton';
91
        a2.addEventListener('click', OCA.Analytics.Navigation.handleNewDatasetButton);
92
        li2.appendChild(a2);
93
        document.getElementById('navigationDatasets').appendChild(li2);
94
95
        for (let navigation of data) {
96
            OCA.Analytics.Navigation.buildNavigationRow(navigation);
97
        }
98
    },
99
100
    buildNavigationRow: function (data) {
101
        let li = document.createElement('li');
102
        let typeIcon;
103
104
        let a = document.createElement('a');
105
        a.setAttribute('href', '#/r/' + data['id']);
106
        let typeINT = parseInt(data['type']);
107
        if (typeINT === OCA.Analytics.TYPE_INTERNAL_FILE) {
108
            typeIcon = 'icon-file';
109
        } else if (typeINT === OCA.Analytics.TYPE_INTERNAL_DB) {
110
            typeIcon = 'icon-projects';
111
        } else if (typeINT === OCA.Analytics.TYPE_SHARED) {
112
            if (document.getElementById('advanced').value === 'true') {
113
                // don´t show shared reports in advanced config mode as no config is possible
114
                return;
115
            }
116
            typeIcon = 'icon-shared';
117
        } else if (typeINT === OCA.Analytics.TYPE_EMPTY_GROUP) {
118
            typeIcon = 'icon-folder';
119
            li.classList.add('collapsible');
120
        } else {
121
            typeIcon = 'icon-external';
122
        }
123
124
        if (typeIcon) {
125
            a.classList.add(typeIcon);
126
        }
127
        a.innerText = data['name'];
128
        a.dataset.id = data['id'];
129
        a.dataset.type = data['type'];
130
        a.dataset.name = data['name'];
131
132
        let ulSublist = document.createElement('ul');
133
        ulSublist.id = 'dataset-' + data['id'];
134
135
        li.appendChild(a);
136
137
        if (parseInt(data['favorite']) === 1 && typeINT !== OCA.Analytics.TYPE_SHARED) {
138
            let spanFav = document.createElement('span');
139
            spanFav.id = 'fav-' + data['id'];
140
            spanFav.classList.add('icon', 'icon-starred');
141
            spanFav.style.opacity = '0.5';
142
            spanFav.dataset.testing = 'favI' + data['name'];
143
            li.appendChild(spanFav);
144
        }
145
146
        if (typeINT !== OCA.Analytics.TYPE_SHARED) {
147
            let divUtils = OCA.Analytics.Navigation.buildNavigationUtils(data);
148
            let divMenu = OCA.Analytics.Navigation.buildNavigationMenu(data);
149
            li.appendChild(divUtils);
150
            li.appendChild(divMenu);
151
        }
152
153
        if (typeINT === OCA.Analytics.TYPE_EMPTY_GROUP) {
154
            li.appendChild(ulSublist);
155
            a.addEventListener('click', OCA.Analytics.Navigation.handleGroupClicked);
156
        } else {
157
            a.addEventListener('click', OCA.Analytics.Navigation.handleNavigationClicked);
158
        }
159
160
        let categoryList;
161
        if (parseInt(data['parent']) !== 0 && document.getElementById('dataset-' + data['parent'])) {
162
            categoryList = document.getElementById('dataset-' + data['parent']);
163
        } else {
164
            categoryList = document.getElementById('navigationDatasets');
165
        }
166
        categoryList.appendChild(li);
167
    },
168
169
    buildNavigationUtils: function (data) {
170
        let divUtils = document.createElement('div');
171
        divUtils.classList.add('app-navigation-entry-utils');
172
        let ulUtils = document.createElement('ul');
173
174
        if (document.getElementById('advanced').value === 'true') {
175
            if (data.schedules && parseInt(data.schedules) !== 0) {
176
                let liScheduleButton = document.createElement('li');
177
                liScheduleButton.classList.add('app-navigation-entry-utils-menu-button');
178
                let ScheduleButton = document.createElement('button');
179
                ScheduleButton.classList.add('icon-history', 'toolTip');
180
                ScheduleButton.setAttribute('title', t('analytics', 'scheduled dataload'));
181
                liScheduleButton.appendChild(ScheduleButton);
182
                ulUtils.appendChild(liScheduleButton);
183
            }
184
            if (data.dataloads && parseInt(data.dataloads) !== 0) {
185
                let liScheduleButton = document.createElement('li');
186
                liScheduleButton.classList.add('app-navigation-entry-utils-menu-button');
187
                let ScheduleButton = document.createElement('button');
188
                ScheduleButton.classList.add('icon-category-workflow', 'toolTip');
189
                ScheduleButton.setAttribute('title', t('analytics', 'Dataload'));
190
                liScheduleButton.appendChild(ScheduleButton);
191
                ulUtils.appendChild(liScheduleButton);
192
            }
193
        }
194
195
        let liMenuButton = document.createElement('li');
196
        liMenuButton.classList.add('app-navigation-entry-utils-menu-button');
197
        let button = document.createElement('button');
198
        button.addEventListener('click', OCA.Analytics.Navigation.handleOptionsClicked);
199
        button.dataset.id = data.id;
200
        button.dataset.name = data.name;
201
        button.dataset.type = data.type;
202
        liMenuButton.appendChild(button);
203
        ulUtils.appendChild(liMenuButton);
204
        divUtils.appendChild(ulUtils);
205
206
        return divUtils;
207
    },
208
209
    buildNavigationMenu: function (data) {
210
        // clone the DOM template
211
        let navigationMenu = document.importNode(document.getElementById('templateNavigationMenu').content, true);
212
213
        let menu = navigationMenu.getElementById('navigationMenu');
214
        menu.dataset.id = data.id;
215
        menu.dataset.type = data.type;
216
        menu.dataset.name = data.name;
217
218
        let edit = navigationMenu.getElementById('navigationMenuEdit');
219
        edit.addEventListener('click', OCA.Analytics.Navigation.handleBasicClicked);
220
        edit.children[1].innerText = t('analytics', 'Basic settings');
221
        edit.dataset.testing = 'basic' + data.name;
222
223
        let favorite = navigationMenu.getElementById('navigationMenueFavorite');
224
        favorite.addEventListener('click', OCA.Analytics.Navigation.handleFavoriteClicked);
225
        favorite.dataset.testing = 'fav' + data.name;
226
227
        let advanced = navigationMenu.getElementById('navigationMenuAdvanced');
228
        if (document.getElementById('advanced').value === 'true') {
229
            edit.remove();
230
            advanced.addEventListener('click', OCA.Analytics.Navigation.handleReportClicked);
231
            advanced.children[0].classList.add('icon-category-monitoring');
232
            advanced.children[1].innerText = t('analytics', 'Back to report');
233
            advanced.dataset.testing = 'back' + data.name;
234
        } else {
235
            advanced.addEventListener('click', OCA.Analytics.Navigation.handleAdvancedClicked);
236
            advanced.children[0].classList.add('icon-category-customization');
237
            advanced.children[1].innerText = t('analytics', 'Advanced');
238
            advanced.dataset.testing = 'adv' + data.name;
239
        }
240
241
        if (parseInt(data.favorite) === 1) {
242
            favorite.firstElementChild.classList.replace('icon-star', 'icon-starred');
243
            favorite.children[1].innerHTML = t('analytics', 'Remove from favorites');
244
        } else {
245
            favorite.children[1].innerHTML = t('analytics', 'Add to favorites');
246
        }
247
248
        let deleteReport = navigationMenu.getElementById('navigationMenuDelete');
249
        deleteReport.dataset.id = data.id;
250
        deleteReport.addEventListener('click', OCA.Analytics.Sidebar.Dataset.handleDeleteButton);
251
252
        if (parseInt(data['type']) === OCA.Analytics.TYPE_EMPTY_GROUP) {
253
            favorite.remove();
254
            deleteReport.children[1].innerHTML = t('analytics', 'Delete folder');
255
            advanced.remove();
256
        }
257
258
        return navigationMenu;
259
    },
260
261
    handleNewDatasetButton: function () {
262
        OCA.Analytics.Backend.createDataset();
263
    },
264
    handleOverviewButton: function () {
265
        if (document.querySelector('#navigationDatasets .active')) {
266
            document.querySelector('#navigationDatasets .active').classList.remove('active');
267
        }
268
        document.getElementById('analytics-content').hidden = true;
269
        document.getElementById('analytics-intro').removeAttribute('hidden');
270
        document.getElementById('ulAnalytics').innerHTML = '';
271
        window.location.href = '#'
272
        OCA.Analytics.Dashboard.init()
273
    },
274
275
    handleNavigationClicked: function (evt) {
276
        if (document.querySelector('.app-navigation-entry-menu.open') !== null) {
277
            document.querySelector('.app-navigation-entry-menu.open').classList.remove('open');
278
        }
279
        let activeCategory = document.querySelector('#navigationDatasets .active');
280
        if (evt) {
281
            if (activeCategory) {
282
                activeCategory.classList.remove('active');
283
            }
284
            evt.target.parentElement.classList.add('active');
285
        }
286
        if (document.getElementById('advanced').value === 'true') {
287
            OCA.Analytics.Sidebar.showSidebar(evt);
288
            evt.stopPropagation();
289
        } else {
290
            document.getElementById('filterVisualisation').innerHTML = '';
291
            if (typeof (OCA.Analytics.currentReportData.options) !== 'undefined') {
292
                // reset any user-filters and display the filters stored for the report
293
                delete OCA.Analytics.currentReportData.options.filteroptions;
294
            }
295
            OCA.Analytics.unsavedFilters = false;
296
            OCA.Analytics.Sidebar.hideSidebar();
297
            OCA.Analytics.Backend.getData();
298
        }
299
    },
300
301
    handleOptionsClicked: function (evt) {
302
        let openMenu;
303
        if (document.querySelector('.app-navigation-entry-menu.open') !== null) {
304
            openMenu = document.querySelector('.app-navigation-entry-menu.open').previousElementSibling.firstElementChild.firstElementChild.firstElementChild.dataset.id;
305
            document.querySelector('.app-navigation-entry-menu.open').classList.remove('open');
306
        }
307
        if (openMenu !== evt.target.dataset.id) {
0 ignored issues
show
Bug introduced by
The variable openMenu does not seem to be initialized in case document.querySelector("...ry-menu.open") !== null on line 303 is false. Are you sure this can never be the case?
Loading history...
308
            evt.target.parentElement.parentElement.parentElement.nextElementSibling.classList.add('open');
309
        }
310
    },
311
312
    handleBasicClicked: function (evt) {
313
        document.querySelector('.app-navigation-entry-menu.open').classList.remove('open');
314
        evt.stopPropagation();
315
        OCA.Analytics.Sidebar.showSidebar(evt);
316
    },
317
318
    handleAdvancedClicked: function (evt) {
319
        document.querySelector('.app-navigation-entry-menu.open').classList.remove('open');
320
        const datasetId = evt.target.closest('div').dataset.id;
321
        window.location = OC.generateUrl('apps/analytics/a/') + '#/r/' + datasetId;
322
        evt.stopPropagation();
323
    },
324
325
    handleFavoriteClicked: function (evt) {
326
        let datasetId = evt.target.closest('div').dataset.id;
327
        let icon = evt.target.parentNode.firstElementChild;
328
        let isFavorite = 'false';
329
330
        if (icon.classList.contains('icon-star')) {
331
            icon.classList.replace('icon-star', 'icon-starred');
332
            evt.target.parentNode.children[1].innerHTML = t('analytics', 'Remove from favorites');
333
            isFavorite = 'true';
334
        } else {
335
            icon.classList.replace('icon-starred', 'icon-star');
336
            evt.target.parentNode.children[1].innerHTML = t('analytics', 'Add to favorites');
337
            document.getElementById('fav-' + datasetId).remove();
338
        }
339
        OCA.Analytics.Backend.favoriteUpdate(datasetId, isFavorite);
340
    },
341
342
    handleReportClicked: function (evt) {
343
        const datasetId = evt.target.closest('div').dataset.id;
344
        window.location = OC.generateUrl('apps/analytics/') + '#/r/' + datasetId;
345
        evt.stopPropagation();
346
    },
347
348
    handleGroupClicked: function (evt) {
349
        if (evt.target.parentNode.classList.contains('open')) {
350
            evt.target.parentNode.classList.remove('open');
351
        } else {
352
            evt.target.parentNode.classList.add('open');
353
        }
354
        evt.stopPropagation();
355
    },
356
357
    handleImportButton: function () {
358
        const mimeparts = ['text/csv', 'text/plain'];
359
        OC.dialogs.filepicker(t('analytics', 'Select file'), OCA.Analytics.Navigation.importDataset.bind(this), false, mimeparts, true, 1);
360
    },
361
362
    importDataset: function (path) {
363
        $.ajax({
364
            type: 'POST',
365
            url: OC.generateUrl('apps/analytics/dataset/import/'),
366
            data: {
367
                'path': path,
368
            },
369
            success: function () {
370
                OCA.Analytics.Navigation.init();
371
            }
372
        });
373
374
    },
375
376
    getDatasets: function (datasetId) {
377
        $.ajax({
378
            type: 'GET',
379
            url: OC.generateUrl('apps/analytics/dataset'),
380
            success: function (data) {
381
                OCA.Analytics.Navigation.buildNavigation(data);
382
                OCA.Analytics.datasets = data;
383
                if (datasetId) {
384
                    OCA.Analytics.Sidebar.hideSidebar();
385
                    let navigationItem = document.querySelector('#navigationDatasets [data-id="' + datasetId + '"]');
386
                    if (navigationItem.parentElement.parentElement.parentElement.classList.contains('collapsible')) {
387
                        navigationItem.parentElement.parentElement.parentElement.classList.add('open');
388
                    }
389
                    navigationItem.click();
390
                }
391
            }
392
        });
393
    },
394
};
395
396
document.addEventListener('DOMContentLoaded', function () {
397
    document.getElementById('importDatasetButton').addEventListener('click', OCA.Analytics.Navigation.handleImportButton);
398
});
399