Passed
Push — master ( 6ae27f...139ca0 )
by Marcel
03:14
created

js/advanced.js   D

Complexity

Total Complexity 58
Complexity/F 1.61

Size

Lines of Code 421
Function Count 36

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
wmc 58
eloc 286
mnd 22
bc 22
fnc 36
dl 0
loc 421
rs 4.5599
bpm 0.6111
cpm 1.6111
noi 1
c 0
b 0
f 0

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