Passed
Push — master ( 1c8d2c...5ea7b1 )
by Marcel
02:39
created

js/navigation.js   B

Complexity

Total Complexity 44
Complexity/F 2.44

Size

Lines of Code 302
Function Count 18

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 219
dl 0
loc 302
rs 8.8798
c 0
b 0
f 0
wmc 44
mnd 26
bc 26
fnc 18
bpm 1.4443
cpm 2.4444
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 = '';
23
        OCA.Analytics.Backend.getDatasets(datasetId);
24
    },
25
26
    handleNewDatasetButton: function () {
27
        OCA.Analytics.Backend.createDataset();
28
    },
29
30
    createDemoReport: function () {
31
        OCA.Analytics.Backend.createDataset('DEMO');
32
    },
33
34
    createDemoGithubReport: function () {
35
        OC.dialogs.prompt(
36
            t('analytics', 'Crate a report which to monitor the realtime download count of your GitHub repository. Enter the GitHub User/Repository. The \'/\' is important.'),
37
            t('analytics', 'Quickstart: GitHub download statistics'),
38
            function (button, val) {
39
                if (button === true) {
40
                    OCA.Analytics.Navigation.quickstartTemp = val;
41
                    $.ajax({
42
                        type: 'POST',
43
                        url: OC.generateUrl('apps/analytics/dataset'),
44
                        data: {
45
                            'file': 'DEMO',
46
                        },
47
                        success: function (data) {
48
                            OCA.Analytics.Navigation.quickstartId = data;
49
                            let datasetName = OCA.Analytics.Navigation.quickstartTemp.split("/")[1];
50
                            $.ajax({
51
                                type: 'PUT',
52
                                url: OC.generateUrl('apps/analytics/dataset/') + data,
53
                                data: {
54
                                    'name': datasetName[0].toUpperCase() + datasetName.substring(1),
55
                                    'subheader': 'GitHub download statistics',
56
                                    'parent': 0,
57
                                    'type': OCA.Analytics.TYPE_GIT,
58
                                    'link': OCA.Analytics.Navigation.quickstartTemp,
59
                                    'visualization': 'ct',
60
                                    'chart': 'column',
61
                                    'chartoptions': '',
62
                                    'dataoptions': '',
63
                                    'dimension1': '',
64
                                    'dimension2': '',
65
                                    'value': ''
66
                                },
67
                                success: function () {
68
                                    OCA.Analytics.Navigation.init(OCA.Analytics.Navigation.quickstartId);
69
                                }
70
                            });
71
                        }
72
                    });
73
                }
74
            },
75
            true,
76
            "user/repo");
77
    },
78
79
    buildNavigation: function (data) {
80
        for (let navigation of data) {
81
            OCA.Analytics.Navigation.buildNavigationRow(navigation);
82
        }
83
    },
84
85
    buildNavigationRow: function (data) {
86
        let li = document.createElement('li');
87
        let typeIcon;
88
89
        let a = document.createElement('a');
90
        a.setAttribute('href', '#/r/' + data['id']);
91
        let typeINT = parseInt(data['type']);
92
        if (typeINT === OCA.Analytics.TYPE_INTERNAL_FILE) {
93
            typeIcon = 'icon-file';
94
        } else if (typeINT === OCA.Analytics.TYPE_INTERNAL_DB) {
95
            typeIcon = 'icon-projects';
96
        } else if (typeINT === OCA.Analytics.TYPE_GIT || typeINT === OCA.Analytics.TYPE_EXTERNAL_FILE) {
97
            typeIcon = 'icon-external';
98
        } else if (typeINT === OCA.Analytics.TYPE_SHARED) {
99
            if (document.getElementById('advanced').value === 'true') {
100
                // don´t show shared reports in advanced config mode as no config is possible
101
                return;
102
            }
103
            typeIcon = 'icon-shared';
104
        } else if (typeINT === OCA.Analytics.TYPE_EMPTY_GROUP) {
105
            typeIcon = 'icon-folder';
106
            li.classList.add('collapsible');
107
        } else {
108
            typeIcon = '';
109
        }
110
111
        if (typeIcon) {
112
            a.classList.add(typeIcon);
113
        }
114
        a.innerText = data['name'];
115
        a.dataset.id = data['id'];
116
        a.dataset.type = data['type'];
117
        a.dataset.name = data['name'];
118
119
        let ulSublist = document.createElement('ul');
120
        ulSublist.id = 'dataset-' + data['id'];
121
122
        li.appendChild(a);
123
124
        if (parseInt(data['favorite']) === 1 && typeINT !== OCA.Analytics.TYPE_SHARED) {
125
            let spanFav = document.createElement('span');
126
            spanFav.id = 'fav-' + data['id'];
127
            spanFav.classList.add('icon', 'icon-starred');
128
            spanFav.style.opacity = '0.5';
129
            spanFav.dataset.testing = 'favI' + data['name'];
130
            li.appendChild(spanFav);
131
        }
132
133
        if (typeINT !== OCA.Analytics.TYPE_SHARED) {
134
            let divUtils = OCA.Analytics.Navigation.buildNavigationUtils(data);
135
            let divMenu = OCA.Analytics.Navigation.buildNavigationMenu(data);
136
            li.appendChild(divUtils);
137
            li.appendChild(divMenu);
138
        }
139
140
        if (typeINT === OCA.Analytics.TYPE_EMPTY_GROUP) {
141
            li.appendChild(ulSublist);
142
            a.addEventListener('click', OCA.Analytics.Navigation.handleGroupClicked);
143
        } else {
144
            a.addEventListener('click', OCA.Analytics.Navigation.handleNavigationClicked);
145
        }
146
147
        let categoryList;
148
        if (parseInt(data['parent']) !== 0 && document.getElementById('dataset-' + data['parent'])) {
149
            categoryList = document.getElementById('dataset-' + data['parent']);
150
        } else {
151
            categoryList = document.getElementById('navigationDatasets');
152
        }
153
        categoryList.appendChild(li);
154
    },
155
156
    buildNavigationUtils: function (data) {
157
        let divUtils = document.createElement('div');
158
        divUtils.classList.add('app-navigation-entry-utils');
159
        let ulUtils = document.createElement('ul');
160
161
        if (document.getElementById('advanced').value === 'true') {
162
            if (data.schedules && parseInt(data.schedules) !== 0) {
163
                let liScheduleButton = document.createElement('li');
164
                liScheduleButton.classList.add('app-navigation-entry-utils-menu-button');
165
                let ScheduleButton = document.createElement('button');
166
                ScheduleButton.classList.add('icon-history', 'toolTip');
167
                ScheduleButton.setAttribute('title', t('analytics', 'scheduled dataload'));
168
                liScheduleButton.appendChild(ScheduleButton);
169
                ulUtils.appendChild(liScheduleButton);
170
            }
171
            if (data.dataloads && parseInt(data.dataloads) !== 0) {
172
                let liScheduleButton = document.createElement('li');
173
                liScheduleButton.classList.add('app-navigation-entry-utils-menu-button');
174
                let ScheduleButton = document.createElement('button');
175
                ScheduleButton.classList.add('icon-category-workflow', 'toolTip');
176
                ScheduleButton.setAttribute('title', t('analytics', 'Dataload'));
177
                liScheduleButton.appendChild(ScheduleButton);
178
                ulUtils.appendChild(liScheduleButton);
179
            }
180
        }
181
182
        let liMenuButton = document.createElement('li');
183
        liMenuButton.classList.add('app-navigation-entry-utils-menu-button');
184
        let button = document.createElement('button');
185
        button.addEventListener('click', OCA.Analytics.Navigation.handleOptionsClicked);
186
        button.dataset.id = data.id;
187
        button.dataset.name = data.name;
188
        button.dataset.type = data.type;
189
        liMenuButton.appendChild(button);
190
        ulUtils.appendChild(liMenuButton);
191
        divUtils.appendChild(ulUtils);
192
193
        return divUtils;
194
    },
195
196
    buildNavigationMenu: function (data) {
197
        // clone the DOM template
198
        let navigationMenu = document.importNode(document.getElementById('templateNavigationMenu').content, true);
199
200
        let menu = navigationMenu.getElementById('navigationMenu');
201
        menu.dataset.id = data.id;
202
        menu.dataset.type = data.type;
203
        menu.dataset.name = data.name;
204
205
        let edit = navigationMenu.getElementById('navigationMenuEdit');
206
        edit.addEventListener('click', OCA.Analytics.Navigation.handleBasicClicked);
207
        edit.children[1].innerText = t('analytics', 'Basic settings');
208
        edit.dataset.testing = 'basic' + data.name;
209
210
        let favorite = navigationMenu.getElementById('navigationMenueFavorite');
211
        favorite.addEventListener('click', OCA.Analytics.Navigation.handleFavoriteClicked);
212
        favorite.dataset.testing = 'fav' + data.name;
213
214
        let advanced = navigationMenu.getElementById('navigationMenuAdvanced');
215
        if (document.getElementById('advanced').value === 'true') {
216
            edit.remove();
217
            advanced.addEventListener('click', OCA.Analytics.Navigation.handleReportClicked);
218
            advanced.children[0].classList.add('icon-category-monitoring');
219
            advanced.children[1].innerText = t('analytics', 'Back to report');
220
            advanced.dataset.testing = 'back' + data.name;
221
        } else {
222
            advanced.addEventListener('click', OCA.Analytics.Navigation.handleAdvancedClicked);
223
            advanced.children[0].classList.add('icon-category-customization');
224
            advanced.children[1].innerText = t('analytics', 'Advanced');
225
            advanced.dataset.testing = 'adv' + data.name;
226
        }
227
228
        if (parseInt(data.favorite) === 1) {
229
            favorite.firstElementChild.classList.replace('icon-star', 'icon-starred');
230
            favorite.children[1].innerHTML = t('analytics', 'Remove from favorites');
231
        } else {
232
            favorite.children[1].innerHTML = t('analytics', 'Add to favorites');
233
        }
234
235
        return navigationMenu;
236
    },
237
238
    handleNavigationClicked: function (evt) {
239
        if (document.querySelector('.app-navigation-entry-menu.open') !== null) {
240
            document.querySelector('.app-navigation-entry-menu.open').classList.remove('open');
241
        }
242
        let activeCategory = document.querySelector('#navigationDatasets .active');
243
        if (evt) {
244
            if (activeCategory) {
245
                activeCategory.classList.remove('active');
246
            }
247
            evt.target.classList.add('active');
248
        }
249
        if (document.getElementById('advanced').value === 'true') {
250
            OCA.Analytics.Sidebar.showSidebar(evt);
251
            evt.stopPropagation();
252
        } else {
253
            document.getElementById('filterVisualisation').innerHTML = '';
254
            OCA.Analytics.Sidebar.hideSidebar();
255
            OCA.Analytics.Backend.getData();
256
        }
257
    },
258
259
    handleOptionsClicked: function (evt) {
260
        let openMenu;
261
        if (document.querySelector('.app-navigation-entry-menu.open') !== null) {
262
            openMenu = document.querySelector('.app-navigation-entry-menu.open').previousElementSibling.firstElementChild.firstElementChild.firstElementChild.dataset.id;
263
            document.querySelector('.app-navigation-entry-menu.open').classList.remove('open');
264
        }
265
        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 261 is false. Are you sure this can never be the case?
Loading history...
266
            evt.target.parentElement.parentElement.parentElement.nextElementSibling.classList.add('open');
267
        }
268
    },
269
270
    handleBasicClicked: function (evt) {
271
        document.querySelector('.app-navigation-entry-menu.open').classList.remove('open');
272
        evt.stopPropagation();
273
        OCA.Analytics.Sidebar.showSidebar(evt);
274
    },
275
276
    handleAdvancedClicked: function (evt) {
277
        document.querySelector('.app-navigation-entry-menu.open').classList.remove('open');
278
        const datasetId = evt.target.closest('div').dataset.id;
279
        window.location = OC.generateUrl('apps/analytics/a/') + '#/r/' + datasetId;
280
        evt.stopPropagation();
281
    },
282
283
    handleFavoriteClicked: function (evt) {
284
        let datasetId = evt.target.closest('div').dataset.id;
285
        let icon = evt.target.parentNode.firstElementChild;
286
        let isFavorite = 'false';
287
288
        if (icon.classList.contains('icon-star')) {
289
            icon.classList.replace('icon-star', 'icon-starred');
290
            evt.target.parentNode.children[1].innerHTML = t('analytics', 'Remove from favorites');
291
            isFavorite = 'true';
292
        } else {
293
            icon.classList.replace('icon-starred', 'icon-star');
294
            evt.target.parentNode.children[1].innerHTML = t('analytics', 'Add to favorites');
295
            document.getElementById('fav-' + datasetId).remove();
296
        }
297
        OCA.Analytics.Backend.favoriteUpdate(datasetId, isFavorite);
298
    },
299
300
    handleReportClicked: function (evt) {
301
        const datasetId = evt.target.closest('div').dataset.id;
302
        window.location = OC.generateUrl('apps/analytics/') + '#/r/' + datasetId;
303
        evt.stopPropagation();
304
    },
305
306
    handleGroupClicked: function (evt) {
307
        if (evt.target.parentNode.classList.contains('open')) {
308
            evt.target.parentNode.classList.remove('open');
309
        } else {
310
            evt.target.parentNode.classList.add('open');
311
        }
312
        evt.stopPropagation();
313
    },
314
};