Passed
Push — master ( 14e493...9c2d3e )
by Marcel
02:30
created

js/advanced.js   C

Complexity

Total Complexity 57
Complexity/F 1.58

Size

Lines of Code 417
Function Count 36

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 283
dl 0
loc 417
rs 5.04
c 0
b 0
f 0
wmc 57
mnd 21
bc 21
fnc 36
bpm 0.5833
cpm 1.5833
noi 2

How to fix   Complexity   

Complexity

Complex classes like js/advanced.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
/**
16
 * @namespace OCA.Analytics.Advanced
17
 */
18
OCA.Analytics.Advanced = {};
19
20
/**
21
 * @namespace OCA.Analytics.Advanced.Dataload
22
 */
23
OCA.Analytics.Advanced.Dataload = {
24
    datasourceTemplates: [],
25
    dataloadArray: [],
26
27
    tabContainerDataload: function () {
28
        const datasetId = document.getElementById('app-sidebar').dataset.id;
29
30
        OCA.Analytics.Sidebar.resetView();
31
        document.getElementById('tabHeaderDataload').classList.add('selected');
32
        document.getElementById('tabContainerDataload').classList.remove('hidden');
33
        document.getElementById('tabContainerDataload').innerHTML = '<div style="text-align:center; word-wrap:break-word;" class="get-metadata"><p><img src="' + OC.imagePath('core', 'loading.gif') + '"><br><br></p><p>' + t('analytics', 'Reading data') + '</p></div>';
34
35
        $.ajax({
36
            type: 'GET',
37
            url: OC.generateUrl('apps/analytics/dataload/') + datasetId,
38
            success: function (data) {
39
                let table;
40
                table = document.getElementById('templateDataload').cloneNode(true);
41
                table.id = 'tableDataload';
42
                document.getElementById('tabContainerDataload').innerHTML = '';
43
                document.getElementById('tabContainerDataload').appendChild(table);
44
                document.getElementById('createDataloadButton').addEventListener('click', OCA.Analytics.Advanced.Dataload.handleDataloadCreateButton);
45
                document.getElementById('dataloadList').innerHTML = '';
46
                for (let dataload of data['dataloads']) {
47
                    const li = OCA.Analytics.Advanced.Dataload.buildDataloadRow(dataload);
48
                    document.getElementById('dataloadList').appendChild(li);
49
                }
50
                for (let key in data['datasources']) {
51
                    let value = data['datasources'][key];
52
                    let option = document.createElement('option');
53
                    option.value = key;
54
                    option.innerText = value;
55
                    document.getElementById('dataloadType').appendChild(option);
56
                }
57
58
                OCA.Analytics.Advanced.Dataload.datasourceTemplates = data['templates'];
59
                OCA.Analytics.Advanced.Dataload.dataloadArray = data['dataloads'];
60
            }
61
        });
62
    },
63
64
    handleDataloadCreateButton: function () {
65
        OCA.Analytics.Advanced.Dataload.createDataload();
66
    },
67
68
    handleDataloadUpdateButton: function () {
69
        OCA.Analytics.Advanced.Dataload.updateDataload();
70
    },
71
72
    handleDataloadDeleteButton: function () {
73
        OC.dialogs.confirm(
74
            t('analytics', 'Are you sure?'),
75
            t('analytics', 'Delete Dataload'),
76
            function (e) {
77
                if (e === true) {
78
                    OCA.Analytics.Advanced.Dataload.deleteDataload();
79
                }
80
            },
81
            true
82
        );
83
    },
84
85
    handleDataloadEditClick: function (evt) {
86
        OCA.Analytics.Advanced.Dataload.bildDataloadDetails(evt);
87
    },
88
89
    handleDataloadExecuteButton: function () {
90
        OCA.Analytics.Advanced.Dataload.executeDataload();
91
    },
92
93
    buildDataloadRow: function (dataload) {
94
95
        let item = document.createElement('div');
96
        item.classList.add('dataloadItem');
97
98
        let typeINT = parseInt(dataload.datasource);
99
        let typeIcon;
100
        if (typeINT === OCA.Analytics.TYPE_INTERNAL_FILE) {
101
            typeIcon = 'icon-file';
102
        } else if (typeINT === OCA.Analytics.TYPE_INTERNAL_DB) {
103
            typeIcon = 'icon-projects';
104
        } else if (typeINT === OCA.Analytics.TYPE_GIT || typeINT === OCA.Analytics.TYPE_EXTERNAL_FILE) {
105
            typeIcon = 'icon-external';
106
        } else {
107
            typeIcon = 'icon-external';
108
        }
109
        let a = document.createElement('a');
110
        //a.setAttribute('href', '#');
111
        a.classList.add(typeIcon);
112
        a.innerText = dataload.name;
113
        a.dataset.id = dataload.id;
114
        a.dataset.datasourceId = dataload.datasource;
115
        a.addEventListener('click', OCA.Analytics.Advanced.Dataload.handleDataloadEditClick);
116
        item.appendChild(a);
117
        return item;
118
    },
119
120
    bildDataloadDetails: function (evt) {
121
        let dataload = OCA.Analytics.Advanced.Dataload.dataloadArray.find(x => x.id === parseInt(evt.target.dataset.id));
122
        if (!dataload) dataload = OCA.Analytics.Advanced.Dataload.dataloadArray.find(x => x.id === evt.target.dataset.id);
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
123
        let template = OCA.Analytics.Advanced.Dataload.datasourceTemplates[evt.target.dataset.datasourceId];
124
125
        document.getElementById('dataloadDetail').dataset.id = dataload.id;
126
        document.getElementById('dataloadName').value = dataload.name;
127
        document.getElementById('dataloadDetailHeader').hidden = false;
128
        document.getElementById('dataloadDetailButtons').hidden = false;
129
        document.getElementById('dataloadUpdateButton').addEventListener('click', OCA.Analytics.Advanced.Dataload.handleDataloadUpdateButton);
130
        document.getElementById('dataloadDeleteButton').addEventListener('click', OCA.Analytics.Advanced.Dataload.handleDataloadDeleteButton);
131
        document.getElementById('dataloadSchedule').value = dataload.schedule;
132
        document.getElementById('dataloadSchedule').addEventListener('change', OCA.Analytics.Advanced.Dataload.updateDataload);
133
        document.getElementById('dataloadOCC').innerText = 'occ analytics:load ' + dataload.id;
134
135
        let item = document.getElementById('dataloadDetailItems');
136
        item.innerHTML = '';
137
138
        for (let option of template) {
139
            let tablerow = document.createElement('div');
140
            //tablerow.style.display = 'table-row';
141
            let label = document.createElement('div');
142
            label.style.display = 'inline-flex';
143
            label.classList.add('input250');
144
            label.innerText = option.name;
145
146
            let input;
147
            if (option.type && option.type === 'tf') {
148
                input = OCA.Analytics.Advanced.Dataload.buildDataloadDetailSelect(option, dataload);
149
            } else {
150
                input = OCA.Analytics.Advanced.Dataload.buildDataloadDetailInput(option, dataload);
151
            }
152
            item.appendChild(tablerow);
153
            tablerow.appendChild(label);
154
            tablerow.appendChild(input);
155
        }
156
157
        document.getElementById('dataloadRun').hidden = false;
158
        document.getElementById('dataloadExecuteButton').addEventListener('click', OCA.Analytics.Advanced.Dataload.handleDataloadExecuteButton);
159
        //scheduleButton.addEventListener('click', OCA.Analytics.Advanced.Dataload.handleDataloadExecuteButton);
160
        //useButton.addEventListener('click', OCA.Analytics.Advanced.Dataload.handleDataloadExecuteButton);
161
162
    },
163
164
    buildDataloadDetailInput: function (option, dataload) {
165
        let input = document.createElement('input');
166
        input.style.display = 'inline-flex';
167
        input.classList.add('input250');
168
        input.placeholder = option.placeholder;
169
        input.id = option.id;
170
        let fieldValues = JSON.parse(dataload.option);
171
        if (option.id in fieldValues) {
172
            input.value = fieldValues[option.id];
173
        }
174
        return input;
175
    },
176
177
    buildDataloadDetailSelect: function (datasourceOptions, dataload) {
0 ignored issues
show
Unused Code introduced by
The parameter dataload 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...
178
        let input = document.createElement('select');
179
        input.style.display = 'inline-flex';
180
        input.classList.add('input250');
181
        input.id = datasourceOptions.id;
182
183
        let selectOptions = datasourceOptions.placeholder.split("/")
184
        for (let selectOption of selectOptions) {
185
            let option = document.createElement('option');
186
            option.value = selectOption;
187
            option.innerText = selectOption;
188
            input.appendChild(option);
189
        }
190
        return input;
191
    },
192
193
    createDataload: function () {
194
        const datasetId = parseInt(document.getElementById('app-sidebar').dataset.id);
195
196
        $.ajax({
197
            type: 'POST',
198
            url: OC.generateUrl('apps/analytics/dataload'),
199
            data: {
200
                'datasetId': datasetId,
201
                'datasourceId': document.getElementById('dataloadType').value,
202
            },
203
            success: function () {
204
                document.querySelector('.tabHeader.selected').click();
205
            }
206
        });
207
    },
208
209
    updateDataload: function () {
210
        const dataloadId = document.getElementById('dataloadDetail').dataset.id;
211
        let option = {};
212
213
        let inputFields = document.querySelectorAll('#dataloadDetailItems input, #dataloadDetailItems select');
214
        for (let inputField of inputFields) {
215
            option[inputField.id] = inputField.value;
216
        }
217
        option = JSON.stringify(option);
218
219
        $.ajax({
220
            type: 'PUT',
221
            url: OC.generateUrl('apps/analytics/dataload/') + dataloadId,
222
            data: {
223
                'name': document.getElementById('dataloadName').value,
224
                'schedule': document.getElementById('dataloadSchedule').value,
225
                'option': option,
226
            },
227
            success: function () {
228
                OCA.Analytics.UI.notification('success', t('analytics', 'Dataload saved'));
229
                OCA.Analytics.Advanced.Dataload.dataloadArray.find(x => x.id === parseInt(dataloadId)).schedule = document.getElementById('dataloadSchedule').value;
230
                OCA.Analytics.Advanced.Dataload.dataloadArray.find(x => x.id === parseInt(dataloadId)).name = document.getElementById('dataloadName').value;
231
            }
232
        });
233
    },
234
235
    deleteDataload: function () {
236
        const dataloadId = document.getElementById('dataloadDetail').dataset.id;
237
        $.ajax({
238
            type: 'DELETE',
239
            url: OC.generateUrl('apps/analytics/dataload/') + dataloadId,
240
            success: function () {
241
                document.querySelector('.tabHeader.selected').click();
242
            }
243
        });
244
    },
245
246
    executeDataload: function () {
247
        const dataloadId = document.getElementById('dataloadDetail').dataset.id;
248
        let mode;
249
        if (document.getElementById('testrunCheckbox').checked) {
250
            mode = 'simulate';
251
        } else {
252
            mode = 'execute';
253
        }
254
255
        $.ajax({
256
            type: 'POST',
257
            url: OC.generateUrl('apps/analytics/dataload/') + mode,
258
            data: {
259
                'dataloadId': dataloadId,
260
            },
261
            success: function (data) {
262
                if (mode === 'simulate') {
263
                    OC.dialogs.message(
264
                        JSON.stringify(data.data),
265
                        t('analytics', 'Datasource simulation'),
266
                        'info',
267
                        OC.dialogs.OK_BUTTON,
268
                        function () {
269
                        },
270
                        true,
271
                        true
272
                    );
273
                } else {
274
                    if (data.error === 0) {
275
                        OCA.Analytics.UI.notification('success', data.insert + t('analytics', ' records inserted, ') + data.update + t('analytics', ' records updated'));
276
                        //document.querySelector('#navigationDatasets [data-id="' + datasetId + '"]').click();
277
                    } else {
278
                        OCA.Analytics.UI.notification('error', data.error);
279
                    }
280
                }
281
            }
282
        });
283
    },
284
285
};
286
287
OCA.Analytics.Advanced.Threshold = {
288
289
    tabContainerThreshold: function () {
290
        const datasetId = document.getElementById('app-sidebar').dataset.id;
291
292
        OCA.Analytics.Sidebar.resetView();
293
        document.getElementById('tabHeaderThreshold').classList.add('selected');
294
        document.getElementById('tabContainerThreshold').classList.remove('hidden');
295
        document.getElementById('tabContainerThreshold').innerHTML = '<div style="text-align:center; word-wrap:break-word;" class="get-metadata"><p><img src="' + OC.imagePath('core', 'loading.gif') + '"><br><br></p><p>' + t('analytics', 'Reading data') + '</p></div>';
296
297
        $.ajax({
298
            type: 'GET',
299
            url: OC.generateUrl('apps/analytics/dataset/') + datasetId,
300
            success: function (data) {
301
                let table;
302
                table = document.getElementById('templateThreshold').cloneNode(true);
303
                table.id = 'tableThreshold';
304
                document.getElementById('tabContainerThreshold').innerHTML = '';
305
                document.getElementById('tabContainerThreshold').appendChild(table);
306
                document.getElementById('sidebarThresholdTextDimension1').innerText = data.dimension1 || t('analytics', 'Column 1');
307
                document.getElementById('sidebarThresholdTextValue').innerText = data.value || t('analytics', 'Column 3');
308
                document.getElementById('createThresholdButton').addEventListener('click', OCA.Analytics.Advanced.Threshold.handleThresholdCreateButton);
309
                if (parseInt(data.type) !== OCA.Analytics.TYPE_INTERNAL_DB) {
310
                    document.getElementById('sidebarThresholdSeverity').remove(0);
311
                }
312
            }
313
        });
314
315
        $.ajax({
316
            type: 'GET',
317
            url: OC.generateUrl('apps/analytics/threshold/') + datasetId,
318
            success: function (data) {
319
                if (data !== false) {
320
                    document.getElementById('sidebarThresholdList').innerHTML = '';
321
                    for (let threshold of data) {
322
                        const li = OCA.Analytics.Advanced.Threshold.buildThresholdRow(threshold);
323
                        document.getElementById('sidebarThresholdList').appendChild(li);
324
                    }
325
                }
326
            }
327
        });
328
    },
329
330
    handleThresholdCreateButton: function () {
331
        OCA.Analytics.Advanced.Threshold.createThreashold();
332
    },
333
334
    handleThresholdDeleteButton: function (evt) {
335
        const thresholdId = evt.target.dataset.id;
336
        OCA.Analytics.Advanced.Threshold.deleteThreshold(thresholdId);
337
    },
338
339
    buildThresholdRow: function (data) {
340
341
        let bulletColor, bullet;
342
        data.severity = parseInt(data.severity);
343
        if (data.severity === 2) {
344
            bulletColor = 'red';
345
        } else if (data.severity === 3) {
346
            bulletColor = 'orange';
347
        } else {
348
            bulletColor = 'green';
349
        }
350
351
        if (data.severity === 1) {
352
            bullet = document.createElement('img');
353
            bullet.src = OC.imagePath('notifications', 'notifications-dark.svg');
354
            bullet.classList.add('thresholdBullet');
355
        } else {
356
            bullet = document.createElement('div');
357
            bullet.style.backgroundColor = bulletColor;
358
            bullet.classList.add('thresholdBullet');
359
        }
360
361
        let item = document.createElement('div');
362
        item.classList.add('thresholdItem');
363
364
        let text = document.createElement('div');
365
        text.classList.add('thresholdText');
366
        text.innerText = data.dimension1 + ' ' + data.option + ' ' + data.value;
367
368
        let tDelete = document.createElement('div');
369
        tDelete.classList.add('icon-close');
370
        tDelete.dataset.id = data.id;
371
        tDelete.addEventListener('click', OCA.Analytics.Advanced.Threshold.handleThresholdDeleteButton);
372
373
        item.appendChild(bullet);
374
        item.appendChild(text);
375
        item.appendChild(tDelete);
376
        return item;
377
    },
378
379
    createThreashold: function () {
380
        const datasetId = parseInt(document.getElementById('app-sidebar').dataset.id);
381
        const url = OC.generateUrl('apps/analytics/threshold');
382
383
        $.ajax({
384
            type: 'POST',
385
            url: url,
386
            data: {
387
                'datasetId': datasetId,
388
                'dimension1': document.getElementById('sidebarThresholdDimension1').value,
389
                'option': document.getElementById('sidebarThresholdOption').value,
390
                'value': document.getElementById('sidebarThresholdValue').value,
391
                'severity': document.getElementById('sidebarThresholdSeverity').value,
392
            },
393
            success: function () {
394
                document.querySelector('.tabHeader.selected').click();
395
            }
396
        });
397
    },
398
399
    deleteThreshold: function (thresholdId) {
400
401
        $.ajax({
402
            type: 'DELETE',
403
            url: OC.generateUrl('apps/analytics/threshold/') + thresholdId,
404
            success: function () {
405
                document.querySelector('.tabHeader.selected').click();
406
            }
407
        });
408
    },
409
410
};
411
412
document.addEventListener('DOMContentLoaded', function () {
413
    OCA.Analytics.Sidebar.registerSidebarTab({
414
        id: 'tabHeaderDataload',
415
        class: 'tabContainerDataload',
416
        tabindex: '2',
417
        name: t('analytics', 'Dataload'),
418
        action: OCA.Analytics.Advanced.Dataload.tabContainerDataload,
419
    });
420
421
    OCA.Analytics.Sidebar.registerSidebarTab({
422
        id: 'tabHeaderThreshold',
423
        class: 'tabContainerThreshold',
424
        tabindex: '3',
425
        name: t('analytics', 'Thresholds'),
426
        action: OCA.Analytics.Advanced.Threshold.tabContainerThreshold,
427
    });
428
429
});