Projekt

Obecné

Profil

Stáhnout (23.6 KB) Statistiky
| Větev: | Revize:
1
angular.module('pvpk', ['ngResource', 'ngSanitize']);
2
angular.module('pvpk')
3
    .constant('config', {
4
        APP_NAME: 'PVPK',
5
        APP_VERSION: '1.3.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
        DEFAULT_ZOOM_MIN: 7,
11
        DEFAULT_RANGE_DATE_DAY: {from: -30, to: -1},
12
        DEFAULT_RANGE_TIME_HOUR: {from: 7, to: 16}
13
    });
14
angular.module('pvpk')
15
    .controller('infoController', ['$rootScope', '$scope', '$location', 'config', 'Device', 'Vehicle', function ($rootScope, $scope, $location, config, Device, Vehicle) {
16

    
17
        this.$onInit = function () {
18
            $rootScope.selectDevice = null;
19
            $scope.showInfoLoading = false;
20
            $scope.vehicles = [];
21
            $scope.urlExportCsv = null;
22

    
23
            Vehicle.query(null, function (data) {
24
                $scope.vehicles = data;
25
            }, function (response) {
26
                $rootScope.graphShow = false;
27
                console.log('Error api all Vehicles');
28
                $rootScope.handleErrorResponse(response);
29
            });
30

    
31
            $rootScope.$emit('setRangeFromUrl', null);
32
        };
33

    
34
        $rootScope.$on('setRangeFromUrl', function (event, args) {
35
            var params = $location.search();
36
            $scope.range = {
37
                fromDate: moment(params.fromDate, 'YYYY-MM-DD').isValid() ? moment(params.fromDate).toDate() : moment().add(config.DEFAULT_RANGE_DATE_DAY.from, 'd').toDate(),
38
                toDate: moment(params.toDate, 'YYYY-MM-DD').isValid() ? moment(params.toDate).toDate() : moment().add(config.DEFAULT_RANGE_DATE_DAY.to, 'd').toDate(),
39
                fromTime: moment(params.fromTime, 'HH:mm').isValid() ? moment(params.fromTime, 'HH:mm').toDate() : moment({hour: config.DEFAULT_RANGE_TIME_HOUR.from}).toDate(),
40
                toTime: moment(params.toTime, 'HH:mm').isValid() ? moment(params.toTime, 'HH:mm').toDate() : moment({hour: config.DEFAULT_RANGE_TIME_HOUR.to}).toDate(),
41
                isTime: params.isTime == 0 ? false : true
42
            };
43
        });
44

    
45
        $rootScope.$on('infoLocation', function (event, args) {
46
            $scope.showInfoLoading = true;
47

    
48
            var params = $location.search();
49
            params.deviceId = args.id;
50
            params.direction = args.direction;
51
            $location.search(params);
52

    
53
            var range = $scope.getRange();
54

    
55
            var query = {
56
                period: range.isTime ? 'time-period' : 'day-period',
57
                id: args.id,
58
                direction: args.direction,
59
                dateFrom: range.fromDate.format('YYYY-MM-DD'),
60
                dateTo: range.toDate.format('YYYY-MM-DD'),
61
                timeFrom: range.isTime ? range.fromTime.format('HH:mm') : null,
62
                timeTo: range.isTime ? range.toTime.format('HH:mm') : null
63
            };
64

    
65
            Device.get(query, function (data) {
66
                $rootScope.selectDevice = data;
67
                $scope.renderGraph();
68
                $scope.urlExportCsv = $scope.generateUrlExportCsv(query);
69

    
70
                $scope.showInfoLoading = false;
71
            }, function (response) {
72
                $rootScope.selectDevice = null;
73
                $scope.showInfoLoading = false;
74
                console.log('Error api get Devices');
75
                $rootScope.handleErrorResponse(response);
76
            });
77

    
78
        });
79

    
80
        $scope.generateUrlExportCsv = function (query) {
81
            var relativeUrl = '/devices/:id/:period/csv?'.replace(':id', query.id).replace(':period', query.period);
82
            delete query.id;
83
            delete query.period;
84

    
85
            var paramsUrl = jQuery.param(query);
86
            return config.API_URL + relativeUrl + paramsUrl;
87
        };
88

    
89
        $scope.changeRange = function () {
90
            if ($scope.range.fromDate >= $scope.range.toDate || ($scope.range.isTime && $scope.range.fromTime >= $scope.range.toTime)) {
91
                $rootScope.selectDevice.traffics = [];
92
                return;
93
            }
94

    
95
            var range = $scope.getRange();
96

    
97
            var params = $location.search();
98
            params.fromDate = range.fromDate.format('YYYY-MM-DD');
99
            params.toDate = range.toDate.format('YYYY-MM-DD');
100
            params.fromTime = range.isTime ? range.fromTime.format('HH:mm') : null;
101
            params.toTime = range.isTime ? range.toTime.format('HH:mm') : null;
102
            params.isTime = range.isTime ? null : 0;
103
            $location.search(params);
104

    
105
            if ($rootScope.selectDevice)
106
                $rootScope.$emit('infoLocation', {
107
                    id: $rootScope.selectDevice.id,
108
                    direction: $rootScope.selectDevice.direction
109
                });
110
        };
111

    
112
        $scope.getRange = function () {
113
            return {
114
                fromDate: moment($scope.range.fromDate).isValid() ? moment($scope.range.fromDate) : moment().add(config.DEFAULT_RANGE_DATE_DAY.from, 'd'),
115
                toDate: moment($scope.range.toDate).isValid() ? moment($scope.range.toDate) : moment().add(config.DEFAULT_RANGE_DATE_DAY.to, 'd'),
116
                fromTime: moment($scope.range.fromTime).isValid() ? moment($scope.range.fromTime) : moment({hour: config.DEFAULT_RANGE_TIME_HOUR.from}),
117
                toTime: moment($scope.range.toTime).isValid() ? moment($scope.range.toTime) : moment({hour: config.DEFAULT_RANGE_TIME_HOUR.to}),
118
                isTime: $scope.range.isTime ? true : false
119
            };
120
        };
121

    
122
        $scope.renderGraph = function () {
123
            var color = ['rgba(158, 158, 158, #alpha)', 'rgba(213, 0, 0, #alpha)', 'rgba(0, 123, 255, #alpha)', 'rgba(170, 0, 255, #alpha)',
124
                'rgba(0, 200, 83, #alpha)', 'rgba(255, 214, 0, #alpha)', 'rgba(255, 109, 0, #alpha)',
125
                '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)'];
126

    
127
            var labels = jQuery.unique($rootScope.selectDevice.traffics.map(function (d) {
128
                return $scope.range.isTime ? d.timeFrom : moment(d.date, 'YYYY-MM-DD').format('D.M.YYYY');
129
            }));
130

    
131
            var useVehiclesIds = jQuery.unique($rootScope.selectDevice.traffics.map(function (d) {
132
                return d.typeVehicleId;
133
            }));
134

    
135
            var filterVehicles = jQuery.grep($scope.vehicles, function (n) {
136
                return useVehiclesIds.indexOf(n.id) >= 0;
137
            });
138

    
139
            var datasetsNumberVehicles = [];
140
            var datasetsAverageSpeed = [];
141

    
142
            for (var i = 0, vehicle; vehicle = filterVehicles[i]; i++) {
143
                var datasetNumberVehicles = {
144
                    label: vehicle.name,
145
                    backgroundColor: color[vehicle.id].replace("#alpha", "0.3"),
146
                    borderColor: color[vehicle.id].replace("#alpha", "1"),
147
                    borderWidth: 2,
148
                    data: []
149
                };
150

    
151
                var datasetAverageSpeed = {
152
                    data: [],
153
                    borderWidth: 2,
154
                    label: vehicle.name,
155
                    fill: false,
156
                    //fill: 'start',
157
                    backgroundColor: color[vehicle.id].replace("#alpha", "0.3"),
158
                    borderColor: color[vehicle.id].replace("#alpha", "1"),
159
                    cubicInterpolationMode: 'monotone',
160
                    pointRadius: 0
161
                };
162

    
163
                var l = 0;
164
                for (var j = 0, traffic; traffic = $rootScope.selectDevice.traffics[j]; j++) {
165
                    if (($scope.range.isTime && labels[l] !== traffic.timeFrom) || (!$scope.range.isTime && labels[l] !== moment(traffic.date, 'YYYY-MM-DD').format('D.M.YYYY'))) {
166
                        l++;
167
                        if (datasetNumberVehicles.data.length < l) {
168
                            datasetNumberVehicles.data.push(0);
169
                            datasetAverageSpeed.data.push(null);
170
                        }
171
                    }
172
                    if (traffic.typeVehicleId === vehicle.id) {
173
                        datasetNumberVehicles.data.push($scope.range.isTime ? traffic.numberVehicleAverage : traffic.numberVehicle);
174
                        datasetAverageSpeed.data.push(traffic.speedAverage <= 0 ? null : traffic.speedAverage);
175
                    }
176
                }
177
                datasetsNumberVehicles.push(datasetNumberVehicles);
178
                datasetsAverageSpeed.push(datasetAverageSpeed);
179
            }
180

    
181
            $rootScope.$emit('renderGraphNumberVehicles', {
182
                data: {
183
                    labels: labels,
184
                    datasets: datasetsNumberVehicles
185
                }
186
            });
187

    
188
            $rootScope.$emit('renderGraphAverageSpeed', {
189
                data: {
190
                    labels: labels,
191
                    datasets: datasetsAverageSpeed
192
                }
193
            });
194
        };
195

    
196
        $scope.infoClose = function () {
197
            $rootScope.selectDevice = null;
198

    
199
            var params = $location.search();
200
            params.deviceId = null;
201
            params.direction = null;
202
            $location.search(params);
203

    
204
            $rootScope.$emit('setDefaultMap', null);
205
        };
206
    }]);
207

    
208
angular.module('pvpk')
209
    .controller('mainController', ['$rootScope', '$scope', '$location', '$window', function ($rootScope, $scope, $location, $window) {
210

    
211
        this.$onInit = function () {
212
            $scope.showLoadingScreen = true;
213
        };
214

    
215
        $window.onload = function () {
216
            var params = $location.search();
217
            if (params.deviceId) {
218
                $rootScope.$emit('activeMarker', {id: params.deviceId});
219
            }
220

    
221
            $scope.$apply(function () {
222
                $scope.showLoadingScreen = false;
223
            });
224
        };
225

    
226
        $rootScope.$on('$locationChangeSuccess', function (event, newUrl, oldUrl) {
227
            var params = $location.search();
228

    
229
            if (newUrl !== oldUrl && $scope.historyUrl) {
230
                if ($scope.historyUrl.q !== $scope.historyUrl.q || $scope.historyUrl.isDirection != params.isDirection) {
231
                    $rootScope.$emit('setSearchFromUrl', null);
232
                }
233

    
234
                if ($scope.historyUrl.fromDate !== params.fromDate || $scope.historyUrl.toDate !== params.toDate ||
235
                    $scope.historyUrl.fromTime !== params.fromTime || $scope.historyUrl.toTime !== params.toTime) {
236
                    $rootScope.$emit('setRangeFromUrl', null);
237
                    if (params.deviceId) {
238
                        $rootScope.$emit('infoLocation', {id: params.deviceId, direction: params.direction});
239
                    }
240
                } else if (params.deviceId && ($scope.historyUrl.deviceId !== params.deviceId || $scope.historyUrl.direction !== params.direction)) {
241
                    $rootScope.$emit('infoLocation', {id: params.deviceId, direction: params.direction});
242
                    $rootScope.$emit('activeMarker', {id: params.deviceId});
243
                } else if (!params.deviceId && $scope.historyUrl.deviceId) {
244
                    $rootScope.selectDevice = null;
245
                    $rootScope.$emit('setDefaultMap', null);
246
                }
247
            } else if (params.deviceId) {
248
                $rootScope.$emit('infoLocation', {id: params.deviceId, direction: params.direction});
249
            }
250

    
251
            $scope.historyUrl = $location.search();
252
        });
253

    
254
        $rootScope.handleErrorResponse = function (response) {
255

    
256
            var modalError = jQuery('#modalError');
257
            switch (response.status) {
258
                case 400:
259
                    console.log('API ERROR 400');
260
                    $scope.modalError = {
261
                        title: 'Neplatný požadavek',
262
                        body: 'Požadavek nemůže být vyřízen, poněvadž byl syntakticky nesprávně zapsán.',
263
                        button: 'OK'
264
                    };
265
                    modalError.modal('show');
266
                    break;
267
                case 401:
268
                    $scope.modalError = {
269
                        title: 'Platnost webové aplikace vypršela',
270
                        body: 'Pro obnovení platnosti stačí stisknout tlačítko <strong>Obnovit</strong>.',
271
                        button: 'Obnovit',
272
                        clickButton: $scope.reloadApp
273
                    };
274
                    modalError.modal({backdrop: 'static', keyboard: false});
275
                    break;
276
                case 404:
277
                    console.log('API ERROR 404');
278
                    $scope.modalError = {title: 'Nenalezen', body: 'Záznam nebyl nalezen.', button: 'OK'};
279
                    modalError.modal('show');
280
                    break;
281
                case 500:
282
                    console.log('API ERROR 500');
283
                    $scope.modalError = {title: 'Chyba', body: 'Chyba serveru. Zopakujte akci později.', button: 'OK'};
284
                    modalError.modal('show');
285
                    break;
286
                case -1:
287
                    console.log('API NOT CONNECTED');
288
                    $scope.modalError = {
289
                        title: 'Připojení k internetu',
290
                        body: 'Nejste připojeni k internetu. Zkontrolujte připojení.',
291
                        button: 'OK'
292
                    };
293
                    modalError.modal('show');
294
                    break;
295
                default:
296
                    console.log('API UNKNOWN ERROR');
297
                    $scope.modalError = {title: 'Neočekávaná chyba', body: 'Nastala neočekávaná chyba.', button: 'OK'};
298
                    modalError.modal('show');
299
                    break;
300
            }
301
        };
302

    
303
        $scope.reloadApp = function () {
304
            $window.location.reload();
305
        }
306
    }]);
307
angular.module('pvpk')
308
    .controller('mapController', ['$rootScope', '$scope', 'config', 'Device', function ($rootScope, $scope, config, Device) {
309

    
310
        this.$onInit = function () {
311
            $scope.markers = [];
312

    
313
            $scope.map = new google.maps.Map(document.getElementById('map'), {
314
                center: config.DEFAULT_POSITION,
315
                zoom: config.DEFAULT_ZOOM,
316
                minZoom: config.DEFAULT_ZOOM_MIN,
317
                zoomControl: true,
318
                mapTypeControl: false,
319
                scaleControl: false,
320
                streetViewControl: false,
321
                rotateControl: false,
322
                fullscreenControl: false,
323
                mapTypeId: google.maps.MapTypeId.ROADMAP
324
            });
325

    
326
            Device.query({showDirection: 0}, function (data) {
327
                for (var i = 0, lctn; lctn = data[i]; i++) {
328
                    $scope.createMarker(lctn);
329
                }
330
            }, function (response) {
331
                console.log('Error api all Devices');
332
                $rootScope.handleErrorResponse(response);
333
            });
334
        };
335

    
336
        $scope.createMarker = function (lctn) {
337
            if (lctn.lat && lctn.lng) {
338
                var marker = new google.maps.Marker({
339
                    map: $scope.map,
340
                    position: {lat: lctn.lat, lng: lctn.lng},
341
                    title: lctn.name,
342
                    infoWindow: new google.maps.InfoWindow({
343
                        content: '<h6 class="mb-1">' + lctn.name + '</h6>'
344
                        + '<address>' + lctn.street + ', ' + lctn.town + '</address>'
345
                    }),
346
                    id: lctn.id
347
                });
348

    
349
                marker.addListener('click', function () {
350
                    $scope.closeInfoWindows();
351
                    marker.infoWindow.open($scope.map, marker);
352
                    $rootScope.$emit('infoLocation', {id: lctn.id});
353
                });
354

    
355
                $scope.markers.push(marker);
356
            }
357
        };
358

    
359
        $rootScope.$on('activeMarker', function (event, args) {
360
            for (var i = 0, marker; marker = $scope.markers[i]; i++) {
361
                if (marker.id && marker.id === args.id && marker.infoWindow) {
362
                    $scope.map.setCenter(marker.getPosition());
363
                    $scope.map.setZoom(12);
364
                    marker.infoWindow.open($scope.map, marker);
365
                } else {
366
                    marker.infoWindow.close();
367
                }
368
            }
369
        });
370

    
371
        $rootScope.$on('setDefaultMap', function (event, args) {
372
            $scope.map.setCenter(config.DEFAULT_POSITION);
373
            $scope.map.setZoom(config.DEFAULT_ZOOM);
374
            $scope.closeInfoWindows();
375
        });
376

    
377
        $scope.closeInfoWindows = function () {
378
            for (var i = 0, marker; marker = $scope.markers[i]; i++) {
379
                marker.infoWindow.close();
380
            }
381
        };
382
    }]);
383
angular.module('pvpk')
384
    .controller('searchController', ['$rootScope', '$scope', '$location', 'config', 'Device', function ($rootScope, $scope, $location, config, Device) {
385

    
386
        this.$onInit = function () {
387
            $scope.config = config;
388
            $scope.locations = [];
389
            $scope.showSearchLoading = false;
390

    
391
            $rootScope.$emit('setSearchFromUrl', null);
392
        };
393

    
394
        $scope.searchLocations = function () {
395
            var params = $location.search();
396
            params.q = $scope.search.q;
397
            params.isDirection = $scope.search.isDirection ? 1 : null;
398
            $location.search(params);
399

    
400
            if (!$scope.search.q || $scope.search.q.length <= 1) {
401
                $scope.locations = [];
402
                return;
403
            }
404

    
405
            $scope.showSearchLoading = true;
406

    
407
            Device.query({
408
                address: $scope.search.q,
409
                showDirection: $scope.search.isDirection ? 1 : 0
410
            }, function (data) {
411
                $scope.locations = data;
412
                $scope.showSearchLoading = false;
413
            }, function (response) {
414
                $scope.showSearchLoading = false;
415
                console.log('Error api all Devices');
416
                $rootScope.handleErrorResponse(response);
417
            });
418
        };
419

    
420
        $rootScope.$on('setSearchFromUrl', function (event, args) {
421
            var params = $location.search();
422
            $scope.search = {
423
                q: params.q,
424
                isDirection: params.isDirection ? !!+params.isDirection : false
425
            };
426
            $scope.searchLocations();
427
        });
428

    
429
        $scope.selectDevice = function (id, direction) {
430
            $rootScope.$emit('activeMarker', {id: id});
431
            $rootScope.$emit('infoLocation', {id: id, direction: direction});
432
        };
433

    
434
    }]);
435
angular.module('pvpk')
436
    .component('graphAverageSpeed', {
437
        template: '<div><canvas id="graphAverageSpeed" class="graphSize mb-5"></canvas></div>',
438
        controller: ['$rootScope', '$scope', function ($rootScope, $scope) {
439

    
440
            $rootScope.$on('renderGraphAverageSpeed', function (event, args) {
441
                var canvas = document.getElementById('graphAverageSpeed').getContext('2d');
442

    
443
                if ($scope.graphLine)
444
                    $scope.graphLine.destroy();
445

    
446
                $scope.graphLine = new Chart(canvas, {
447
                    type: 'line',
448
                    data: args.data,
449
                    options: {
450
                        responsive: true,
451
                        pointDot: false,
452
                        legend: {
453
                            position: 'bottom'
454
                        },
455
                        scales: {
456
                            xAxes: [{
457
                                ticks: {
458
                                    autoSkip: true,
459
                                    maxTicksLimit: 15
460
                                }
461
                            }],
462
                            yAxes: [{
463
                                scaleLabel: {
464
                                    display: true,
465
                                    labelString: 'km/h'
466
                                },
467
                                ticks: {
468
                                    beginAtZero: true,
469
                                    suggestedMax: 70
470
                                }
471
                            }]
472
                        },
473
                        tooltips: {
474
                            mode: 'index',
475
                            intersect: false,
476
                            callbacks: {
477
                                label: function (tooltipItems) {
478
                                    return tooltipItems.yLabel + ' km/h';
479
                                }
480
                            }
481
                        }
482
                    }
483
                });
484

    
485
            });
486

    
487
        }]
488
    });
489
angular.module('pvpk')
490
    .component('graphNumberVehicles', {
491
        template: '<div><canvas id="graphNumberVehicles" class="graphSize mb-5"></canvas></div>',
492
        controller: ['$rootScope', '$scope', function ($rootScope, $scope) {
493

    
494
            $rootScope.$on('renderGraphNumberVehicles', function (event, args) {
495
                var canvasGraphNumberVehicles = document.getElementById('graphNumberVehicles').getContext('2d');
496

    
497
                if ($scope.graphNumberVehicles)
498
                    $scope.graphNumberVehicles.destroy();
499

    
500
                $scope.graphNumberVehicles = new Chart(canvasGraphNumberVehicles, {
501
                    type: 'bar',
502
                    data: args.data,
503
                    options: {
504
                        responsive: true,
505
                        onResize: function (chart, size) {
506
                            chart.options.legend.display = size.height > 240;
507
                            chart.update();
508
                        },
509
                        legend: {
510
                            position: 'bottom'
511
                        },
512
                        scales: {
513
                            xAxes: [{
514
                                stacked: true,
515
                                ticks: {
516
                                    autoSkip: true,
517
                                    maxTicksLimit: 15
518
                                }
519
                            }],
520
                            yAxes: [{
521
                                scaleLabel: {
522
                                    display: true,
523
                                    labelString: "počet vozidel"
524
                                },
525
                                stacked: true
526
                            }]
527
                        },
528
                        tooltips: {
529
                            mode: 'index',
530
                            intersect: false
531
                        }
532
                    }
533
                });
534

    
535
            });
536

    
537
        }]
538
    });
539
angular.module('pvpk')
540
    .factory('Device', ['$resource', 'config', function ($resource, config) {
541
        return $resource(config.API_URL + '/devices/:id', {id: '@id', period: '@period'}, {
542
            'get': {
543
                url: config.API_URL + '/devices/:id/:period',
544
                method: 'GET',
545
                headers: {
546
                    'Content-Type': 'application/json',
547
                    'Accept': 'application/json',
548
                    'jwt': config.API_TOKEN
549
                }
550
            },
551
            'query': {
552
                url: config.API_URL + '/devices',
553
                method: 'GET',
554
                isArray: true,
555
                headers: {
556
                    'Content-Type': 'application/json',
557
                    'Accept': 'application/json',
558
                    'jwt': config.API_TOKEN
559
                }
560
            }
561
        });
562
    }]);
563
angular.module('pvpk')
564
    .factory('Vehicle', ['$resource', 'config', function ($resource, config) {
565
        return $resource(config.API_URL + '/vehicles', null, {
566
            'query': {
567
                url: config.API_URL + '/vehicles',
568
                method: 'GET',
569
                isArray: true,
570
                headers: {
571
                    'Content-Type': 'application/json',
572
                    'Accept': 'application/json',
573
                    'jwt': config.API_TOKEN
574
                }
575
            }
576
        });
577
    }]);
(2-2/8)