Projekt

Obecné

Profil

Stáhnout (19.8 KB) Statistiky
| Větev: | Revize:
1
let app = angular.module('pvpk', ['ngRoute', 'ngResource', 'ngSanitize']);
2

    
3
app.constant('config', {
4
    APP_NAME: 'PVPK',
5
    APP_VERSION: 1.0,
6
    API_URL: API_URL,
7
    API_TOKEN: API_TOKEN,
8
    DEFAULT_POSITION: {LAT: 49.53, LNG: 13.3},
9
    DEFAULT_ZOOM: 10
10
});
11

    
12
//PRIPRAVA PRO REFAKTORING
13
// app.config(function($stateProvider, $locationProvider) {
14
//     // $stateProvider
15
//     // .state('report',{
16
//     //     views: {
17
//     //         'search': {
18
//     //             templateUrl: 'report-filters.html',
19
//     //             controller: searchController
20
//     //         },
21
//     //         'graph': {
22
//     //             templateUrl: 'report-table.html',
23
//     //             controller: graphController
24
//     //         },
25
//     //         'map': {
26
//     //             templateUrl: 'report-graph.html',
27
//     //             controller: mapController
28
//     //         }
29
//     //     }
30
//     // });
31
//    $locationProvider.html5Mode(true);
32
// });
33

    
34

    
35
app.controller('mainController', function ($rootScope, $scope, $location, $window) {
36

    
37
    this.$onInit = function () {
38

    
39
    };
40

    
41
    $window.onload = function () {
42
        let params = $location.search();
43
        if (params.deviceId) {
44
            $rootScope.$emit('infoLocation', {id: params.deviceId, direction: params.direction});
45
            $rootScope.$emit('activeMarker', {id: params.deviceId});
46
        }
47

    
48
        $scope.showLoadingScreen = false;
49
    };
50

    
51
    $rootScope.$on('$locationChangeSuccess', function (event, newUrl, oldUrl) {
52

    
53
        if (newUrl !== oldUrl && $scope.historyUrl) {
54
            let params = $location.search();
55

    
56
            if ($scope.historyUrl.q !== $scope.historyUrl.q || $scope.historyUrl.isDirection != params.isDirection) {
57
                $rootScope.$emit('setSearchFromUrl', null);
58
            }
59

    
60
            if ($scope.historyUrl.fromDate !== params.fromDate || $scope.historyUrl.toDate !== params.toDate ||
61
                $scope.historyUrl.fromTime !== params.fromTime || $scope.historyUrl.toTime !== params.toTime) {
62
                $rootScope.$emit('setRangeFromUrl', null);
63
                if (params.deviceId) {
64
                    $rootScope.$emit('infoLocation', {id: params.deviceId, direction: params.direction});
65
                }
66
            } else if (params.deviceId && ($scope.historyUrl.deviceId !== params.deviceId || $scope.historyUrl.direction !== params.direction)) {
67
                $rootScope.$emit('infoLocation', {id: params.deviceId, direction: params.direction});
68
                $rootScope.$emit('activeMarker', {id: params.deviceId});
69
            }else if(!params.deviceId && $scope.historyUrl.deviceId){
70
                $rootScope.selectDevice = null;
71
                $rootScope.$emit('setDefaultMap', null);
72
            }
73
        }
74

    
75
        $scope.historyUrl = $location.search();
76
    });
77

    
78
    $rootScope.handleErrorResponse = function (response) {
79

    
80
        let modalError = jQuery('#modalError');
81
        switch (response.status) {
82
            case 400:
83
                console.log('API ERROR 400');
84
                $scope.modalError = {
85
                    title: 'Neplatný požadavek',
86
                    body: 'Požadavek nemůže být vyřízen, poněvadž byl syntakticky nesprávně zapsán.',
87
                    button: 'OK'
88
                };
89
                modalError.modal('show');
90
                break;
91
            case 401:
92
                $scope.modalError = {
93
                    title: 'Platnost webové aplikace vypršela',
94
                    body: 'Pro obnovení platnosti stačí stisknout tlačítko <strong>Obnovit</strong>.',
95
                    button: 'Obnovit',
96
                    clickButton: $scope.reloadApp
97
                };
98
                modalError.modal({backdrop: 'static', keyboard: false});
99
                break;
100
            case 404:
101
                console.log('API ERROR 404');
102
                $scope.modalError = {title: 'Nenalezen', body: 'Záznam nebyl nalezen.', button: 'OK'};
103
                modalError.modal('show');
104
                break;
105
            case 500:
106
                console.log('API ERROR 500');
107
                $scope.modalError = {title: 'Chyba', body: 'Chyba serveru. Zopakujte akci později.', button: 'OK'};
108
                modalError.modal('show');
109
                break;
110
            case -1:
111
                console.log('API NOT CONNECTED');
112
                $scope.modalError = {
113
                    title: 'Připojení k internetu',
114
                    body: 'Nejste připojeni k internetu. Zkontrolujte připojení.',
115
                    button: 'OK'
116
                };
117
                modalError.modal('show');
118
                break;
119
            default:
120
                console.log('API UNKNOWN ERROR');
121
                $scope.modalError = {title: 'Neočekávaná chyba', body: 'Nastala neočekávaná chyba.', button: 'OK'};
122
                modalError.modal('show');
123
                break;
124
        }
125
    };
126

    
127
    $scope.reloadApp = function () {
128
        $window.location.reload();
129
    }
130
});
131

    
132

    
133
app.controller('searchController', function ($rootScope, $scope, $location, config, Device) {
134

    
135
    this.$onInit = function () {
136
        $scope.locations = [];
137
        $scope.showSearchLoading = false;
138

    
139
        $rootScope.$emit('setSearchFromUrl', null);
140
    };
141

    
142
    $scope.searchLocations = function () {
143
        if (!$scope.search.q || $scope.search.q.length <= 1) {
144
            $scope.locations = [];
145
            return;
146
        }
147

    
148
        $scope.showSearchLoading = true;
149

    
150
        let params = $location.search();
151
        params.q = $scope.search.q;
152
        params.isDirection = $scope.search.isDirection ? 1 : 0;
153
        $location.search(params);
154

    
155
        Device.query({
156
            address: $scope.search.q,
157
            showDirection: $scope.search.isDirection ? 1 : 0
158
        }, function (data) {
159
            $scope.locations = data;
160
            $scope.showSearchLoading = false;
161
        }, function (response) {
162
            $scope.showSearchLoading = false;
163
            console.log('Error api all Devices');
164
            $rootScope.handleErrorResponse(response);
165
        });
166
    };
167

    
168
    $rootScope.$on('setSearchFromUrl', function (event, args) {
169
        let params = $location.search();
170

    
171
        $scope.search = {
172
            q: params.q,
173
            isDirection: params.isDirection ? !!+params.isDirection : false
174
        };
175
        $scope.searchLocations();
176
    });
177

    
178
    $scope.selectDevice = function (id, direction) {
179
        $rootScope.$emit('activeMarker', {id: id});
180
        $rootScope.$emit('infoLocation', {id: id, direction: direction});
181
    };
182

    
183
});
184

    
185

    
186
app.controller('infoController', function ($rootScope, $scope, $location, config, Device, Vehicle) {
187

    
188
    this.$onInit = function () {
189
        $rootScope.selectDevice = null;
190
        $scope.showInfoLoading = false;
191
        $scope.vehicles = [];
192
        $scope.typeVehicle = null;
193
        $scope.filterVehicles = [];
194

    
195
        Vehicle.query(null, function (data) {
196
            $scope.vehicles = data;
197
        }, function (response) {
198
            $rootScope.graphShow = false;
199
            console.log('Error api all Vehicles');
200
            $rootScope.handleErrorResponse(response);
201
        });
202

    
203
        $rootScope.$emit('setRangeFromUrl', null);
204
    };
205

    
206
    $rootScope.$on('setRangeFromUrl', function (event, args) {
207
        let params = $location.search();
208
        let defaultRange = $scope.defaultRange();
209

    
210
        $scope.range = {
211
            fromDate: moment(params.fromDate, 'YYYY-MM-DD').isValid() ? moment(params.fromDate).toDate() : defaultRange.fromDate.toDate(),
212
            toDate: moment(params.toDate, 'YYYY-MM-DD').isValid() ? moment(params.toDate).toDate() : defaultRange.toDate.toDate(),
213
            fromTime: moment(params.fromTime, 'HH:mm').isValid() ? moment(params.fromTime, 'HH:mm').toDate() : defaultRange.fromTime.toDate(),
214
            toTime: moment(params.toTime, 'HH:mm').isValid() ? moment(params.toTime, 'HH:mm').toDate() : defaultRange.toTime.toDate()
215
        };
216

    
217
    });
218

    
219
    $rootScope.$on('infoLocation', function (event, args) {
220
        $scope.showInfoLoading = true;
221

    
222
        let params = $location.search();
223
        params.deviceId = args.id;
224
        params.direction = args.direction;
225
        $location.search(params);
226

    
227
        let range = $scope.getRange();
228

    
229
        Device.get({
230
            id: args.id,
231
            direction: args.direction,
232
            dateFrom: range.fromDate.format('YYYY-MM-DD'),
233
            dateTo: range.toDate.format('YYYY-MM-DD'),
234
            timeFrom: range.fromTime.format('HH:mm'),
235
            timeTo: range.toTime.format('HH:mm'),
236
        }, function (data) {
237
            $rootScope.selectDevice = data;
238

    
239
            $scope.typeVehicle = null;
240
            $scope.renderGraphAverageSpeed();
241
            $scope.renderGraphNumberVehicles();
242

    
243
            $scope.showInfoLoading = false;
244
        }, function (response) {
245
            $rootScope.selectDevice = null;
246
            $scope.showInfoLoading = false;
247
            console.log('Error api get Devices');
248
            $rootScope.handleErrorResponse(response);
249
        });
250

    
251
    });
252

    
253
    $scope.changeRange = function () {
254
        if ($scope.range.fromDate >= $scope.range.toDate || $scope.range.fromTime >= $scope.range.toTime) {
255
            $rootScope.selectDevice.traffics = [];
256
            return;
257
        }
258

    
259
        let range = $scope.getRange();
260

    
261
        let params = $location.search();
262
        params.fromDate = range.fromDate.format('YYYY-MM-DD');
263
        params.toDate = range.toDate.format('YYYY-MM-DD');
264
        params.fromTime = range.fromTime.format('HH:mm');
265
        params.toTime = range.toTime.format('HH:mm');
266
        $location.search(params);
267

    
268
        if ($rootScope.selectDevice)
269
            $rootScope.$emit('infoLocation', {
270
                id: $rootScope.selectDevice.id,
271
                direction: $rootScope.selectDevice.direction
272
            });
273
    };
274

    
275
    $scope.getRange = function () {
276
        let defaultRange = $scope.defaultRange();
277

    
278
        return {
279
            fromDate: moment($scope.range.fromDate).isValid() ? moment($scope.range.fromDate) : defaultRange.fromDate,
280
            toDate: moment($scope.range.toDate).isValid() ? moment($scope.range.toDate) : defaultRange.toDate,
281
            fromTime: moment($scope.range.fromTime).isValid() ? moment($scope.range.fromTime) : defaultRange.fromTime,
282
            toTime: moment($scope.range.toTime).isValid() ? moment($scope.range.toTime) : defaultRange.toTime
283
        };
284
    };
285

    
286
    $scope.defaultRange = function () {
287
        return {
288
            fromDate: moment().day(-30),
289
            toDate: moment().day(-1),
290
            fromTime: moment({hour: 7}),
291
            toTime: moment({hour: 16})
292
        };
293
    };
294

    
295

    
296
    $scope.renderGraphAverageSpeed = function () {
297

    
298
        let t = $rootScope.selectDevice.traffics.reduce(function (l, r) {
299
            let key = r.timeFrom;
300
            if (typeof l[key] === 'undefined') {
301
                l[key] = {
302
                    numberVehicle: 0,
303
                    speedSum: 0
304
                };
305
            }
306

    
307
            if (r.speedAverage > 0) {
308
                l[key].numberVehicle += r.numberVehicle;
309
                l[key].speedSum += r.speedAverage * r.numberVehicle;
310
            }
311
            return l;
312
        }, {});
313

    
314
        let labels = jQuery.unique($rootScope.selectDevice.traffics.map(function (d) {
315
            return d.timeFrom;
316
        }));
317
        let data = Object.values(t).map(function (d) {
318
            return Math.round(d.speedSum / d.numberVehicle);
319
        });
320

    
321

    
322
        let canvasGraphAverageSpeed = document.getElementById('graphAverageSpeed').getContext('2d');
323

    
324
        if ($scope.graphAverageSpeed)
325
            $scope.graphAverageSpeed.destroy();
326

    
327
        $scope.graphAverageSpeed = new Chart(canvasGraphAverageSpeed, {
328
            type: 'line',
329
            data: {
330
                labels: labels,
331
                datasets: [{
332
                    data: data,
333
                    borderWidth: 2,
334
                    label: "Rychlost",
335
                    fill: 'start',
336
                    backgroundColor: 'rgba(0, 123, 255, 0.3)',
337
                    borderColor: 'rgba(0, 123, 255,1)',
338
                    cubicInterpolationMode: 'monotone',
339
                    radius: 0
340
                }]
341
            },
342
            options: {
343
                responsive: true,
344
                pointDot: false,
345
                scales: {
346
                    xAxes: [{
347
                        ticks: {
348
                            autoSkip: true,
349
                            maxTicksLimit: 15
350
                        }
351
                    }],
352
                    yAxes: [{
353
                        scaleLabel: {
354
                            display: true,
355
                            labelString: 'km/h'
356
                        },
357
                        ticks: {
358
                            beginAtZero: true
359
                        }
360
                    }]
361
                },
362
                tooltips: {
363
                    enabled: true,
364
                    mode: 'single',
365
                    callbacks: {
366
                        label: function (tooltipItems) {
367
                            return tooltipItems.yLabel + ' km/h';
368
                        }
369
                    }
370
                }
371
            }
372
        });
373
    };
374

    
375

    
376
    $scope.renderGraphNumberVehicles = function () {
377
        let color = ['rgba(158, 158, 158, #alpha)', 'rgba(213, 0, 0, #alpha)', 'rgba(0, 123, 255, #alpha)', 'rgba(170, 0, 255, #alpha)',
378
            'rgba(0, 200, 83, #alpha)', 'rgba(255, 214, 0, #alpha)', 'rgba(255, 109, 0, #alpha)',
379
            'rgba(174, 234, 0, #alpha)', 'rgba(98, 0, 234, #alpha)', 'rgba(255, 171, 0, #alpha)', 'rgba(100, 221, 23, #alpha)', 'rgba(0, 184, 212, #alpha)'];
380

    
381

    
382
        let labels = jQuery.unique($rootScope.selectDevice.traffics.map(function (d) {
383
            return d.timeFrom;
384
        }));
385

    
386
        let useVehiclesIds = jQuery.unique($rootScope.selectDevice.traffics.map(function (d) {
387
            return d.typeVehicleId;
388
        }));
389

    
390
        $scope.filterVehicles = jQuery.grep($scope.vehicles, function (n) {
391
            return useVehiclesIds.indexOf(n.id) >= 0;
392
        });
393

    
394
        let datasets = [];
395
        for (let i = 0, vehicle; vehicle = $scope.filterVehicles[i]; i++) {
396
            if ($scope.typeVehicle == null || $scope.typeVehicle === vehicle.id) {
397
                let dataset = {
398
                    label: vehicle.name,
399
                    backgroundColor: color[vehicle.id].replace("#alpha", "0.3"),
400
                    borderColor: color[vehicle.id].replace("#alpha", "1"),
401
                    borderWidth: 2,
402
                    data: []
403
                };
404

    
405
                let l = 0;
406
                for (let j = 0, traffic; traffic = $rootScope.selectDevice.traffics[j]; j++) {
407
                    if (labels[l] !== traffic.timeFrom) {
408
                        l++;
409
                        if (dataset.data.length < l) {
410
                            dataset.data.push(0);
411
                        }
412
                    }
413
                    if (traffic.typeVehicleId === vehicle.id) {
414
                        dataset.data.push(traffic.numberVehicleAverage);
415
                    }
416
                }
417
                datasets.push(dataset);
418
            }
419
        }
420

    
421
        let canvasGraphNumberVehicles = document.getElementById('graphNumberVehicles').getContext('2d');
422

    
423
        if ($scope.graphNumberVehicles)
424
            $scope.graphNumberVehicles.destroy();
425

    
426
        $scope.graphNumberVehicles = new Chart(canvasGraphNumberVehicles, {
427
            type: 'bar',
428
            data: {
429
                labels: labels,
430
                datasets: datasets
431
            },
432
            options: {
433
                tooltips: {
434
                    mode: 'index',
435
                    intersect: false
436
                },
437
                responsive: true,
438
                scales: {
439
                    xAxes: [{
440
                        stacked: true,
441
                        ticks: {
442
                            autoSkip: true,
443
                            maxTicksLimit: 15
444
                        }
445
                    }],
446
                    yAxes: [{
447
                        scaleLabel: {
448
                            display: true,
449
                            labelString: "počet vozidel"
450
                        },
451
                        stacked: true
452
                    }]
453
                }
454
            }
455
        });
456
    };
457

    
458

    
459
    $scope.infoClose = function () {
460
        $rootScope.selectDevice = null;
461

    
462
        let params = $location.search();
463
        params.deviceId = null;
464
        params.direction = null;
465
        $location.search(params);
466

    
467
        $rootScope.$emit('setDefaultMap', null);
468
    };
469
});
470

    
471

    
472
app.controller('mapController', function ($rootScope, $scope, config, Device) {
473

    
474
    this.$onInit = function () {
475

    
476
        $scope.map = new GMaps({
477
            div: '#map',
478
            zoomControl: true,
479
            mapTypeControl: false,
480
            scaleControl: false,
481
            streetViewControl: false,
482
            rotateControl: false,
483
            fullscreenControl: false,
484
            mapTypeId: 'roadmap',
485
            zoom: config.DEFAULT_ZOOM,
486
            lat: config.DEFAULT_POSITION.LAT,
487
            lng: config.DEFAULT_POSITION.LNG,
488
            // styles: [
489
            //     {
490
            //         featureType: "poi",
491
            //         elementType: "labels",
492
            //         stylers: [{ visibility: "off" }]
493
            //     }
494
            // ]
495
        });
496

    
497
        Device.query({showDirection: 0}, function (data) {
498
            for (let i = 0, lctn; lctn = data[i]; i++) {
499
                $scope.createMarker(lctn);
500
            }
501
        }, function (response) {
502
            console.log('Error api all Devices');
503
            $rootScope.handleErrorResponse(response);
504
        });
505
    };
506

    
507

    
508
    $scope.createMarker = function (lctn) {
509
        if (lctn.lat && lctn.lng) {
510
            $scope.map.addMarker({
511
                lat: lctn.lat,
512
                lng: lctn.lng,
513
                title: lctn.name,
514
                click: function () {
515
                    $rootScope.$emit('infoLocation', {id: lctn.id});
516
                },
517
                infoWindow: {
518
                    content: '<h6 class="mb-1">' + lctn.name + '</h6>'
519
                    + '<address>' + lctn.street + ', ' + lctn.town + '</address>'
520
                },
521
                id: lctn.id
522
            });
523
        }
524
    };
525

    
526
    $rootScope.$on('activeMarker', function (event, args) {
527
        let id = args.id;
528
        for (let i = 0, marker; marker = $scope.map.markers[i]; i++) {
529
            if (marker.id && marker.id === id && marker.infoWindow) {
530
                $scope.map.setCenter(marker.position.lat(), marker.position.lng());
531
                $scope.map.setZoom(12);
532
                $scope.map.hideInfoWindows();
533
                marker.infoWindow.open($scope.map, marker);
534
                return;
535
            }
536
        }
537
    });
538

    
539
    $rootScope.$on('setDefaultMap', function (event, args) {
540
        $scope.map.setCenter(config.DEFAULT_POSITION.LAT, config.DEFAULT_POSITION.LNG);
541
        $scope.map.setZoom(config.DEFAULT_ZOOM);
542
        $scope.map.hideInfoWindows();
543
    });
544
});
545

    
546

    
547
app.factory('Device', function ($resource, config) {
548
    return $resource(config.API_URL + '/devices/:id', {id: '@id'}, {
549
        'get': {
550
            url: config.API_URL + '/devices/:id/time-period',
551
            method: 'GET',
552
            headers: {
553
                'Content-Type': 'application/json',
554
                'Accept': 'application/json',
555
                'jwt': config.API_TOKEN
556
            }
557
        },
558
        'query': {
559
            url: config.API_URL + '/devices',
560
            method: 'GET',
561
            isArray: true,
562
            headers: {
563
                'Content-Type': 'application/json',
564
                'Accept': 'application/json',
565
                'jwt': config.API_TOKEN
566
            }
567
        }
568
    });
569
});
570

    
571
app.factory('Vehicle', function ($resource, config) {
572
    return $resource(config.API_URL + '/vehicles', null, {
573
        'query': {
574
            url: config.API_URL + '/vehicles',
575
            method: 'GET',
576
            isArray: true,
577
            headers: {
578
                'Content-Type': 'application/json',
579
                'Accept': 'application/json',
580
                'jwt': config.API_TOKEN
581
            }
582
        }
583
    });
584
});
(1-1/3)