Projekt

Obecné

Profil

Stáhnout (19.7 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
            }
70
        }
71

    
72
        $scope.historyUrl = $location.search();
73
    });
74

    
75
    $rootScope.handleErrorResponse = function (response) {
76

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

    
124
    $scope.reloadApp = function () {
125
        $window.location.reload();
126
    }
127
});
128

    
129

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

    
132
    this.$onInit = function () {
133
        $scope.locations = [];
134
        $scope.showSearchLoading = false;
135

    
136
        $rootScope.$emit('setSearchFromUrl', null);
137
    };
138

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

    
145
        $scope.showSearchLoading = true;
146

    
147
        let params = $location.search();
148
        params.q = $scope.search.q;
149
        params.isDirection = $scope.search.isDirection ? 1 : 0;
150
        $location.search(params);
151

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

    
165
    $rootScope.$on('setSearchFromUrl', function (event, args) {
166
        let params = $location.search();
167

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

    
175
    $scope.selectDevice = function (id, direction) {
176
        $rootScope.$emit('activeMarker', {id: id});
177
        $rootScope.$emit('infoLocation', {id: id, direction: direction});
178
    };
179

    
180
});
181

    
182

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

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

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

    
200
        $rootScope.$emit('setRangeFromUrl', null);
201
    };
202

    
203
    $rootScope.$on('setRangeFromUrl', function (event, args) {
204
        let params = $location.search();
205
        let defaultRange = $scope.defaultRange();
206

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

    
214
    });
215

    
216
    $rootScope.$on('infoLocation', function (event, args) {
217
        $scope.showInfoLoading = true;
218

    
219
        let params = $location.search();
220
        params.deviceId = args.id;
221
        params.direction = args.direction;
222
        $location.search(params);
223

    
224
        let range = $scope.getRange();
225

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

    
236
            $scope.typeVehicle = null;
237
            $scope.renderGraphAverageSpeed();
238
            $scope.renderGraphNumberVehicles();
239

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

    
248
    });
249

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

    
256
        let range = $scope.getRange();
257

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

    
265
        if ($rootScope.selectDevice)
266
            $rootScope.$emit('infoLocation', {
267
                id: $rootScope.selectDevice.id,
268
                direction: $rootScope.selectDevice.direction
269
            });
270
    };
271

    
272
    $scope.getRange = function () {
273
        let defaultRange = $scope.defaultRange();
274

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

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

    
292

    
293
    $scope.renderGraphAverageSpeed = function () {
294

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

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

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

    
318

    
319
        let canvasGraphAverageSpeed = document.getElementById('graphAverageSpeed').getContext('2d');
320

    
321
        if ($scope.graphAverageSpeed)
322
            $scope.graphAverageSpeed.destroy();
323

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

    
372

    
373
    $scope.renderGraphNumberVehicles = function () {
374
        let color = ['rgba(158, 158, 158, #alpha)', 'rgba(213, 0, 0, #alpha)', 'rgba(0, 123, 255, #alpha)', 'rgba(170, 0, 255, #alpha)',
375
            'rgba(0, 200, 83, #alpha)', 'rgba(255, 214, 0, #alpha)', 'rgba(255, 109, 0, #alpha)',
376
            '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)'];
377

    
378

    
379
        let labels = jQuery.unique($rootScope.selectDevice.traffics.map(function (d) {
380
            return d.timeFrom;
381
        }));
382

    
383
        let useVehiclesIds = jQuery.unique($rootScope.selectDevice.traffics.map(function (d) {
384
            return d.typeVehicleId;
385
        }));
386

    
387
        $scope.filterVehicles = jQuery.grep($scope.vehicles, function (n) {
388
            return useVehiclesIds.indexOf(n.id) >= 0;
389
        });
390

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

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

    
418
        let canvasGraphNumberVehicles = document.getElementById('graphNumberVehicles').getContext('2d');
419

    
420
        if ($scope.graphNumberVehicles)
421
            $scope.graphNumberVehicles.destroy();
422

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

    
455

    
456
    $scope.infoClose = function () {
457
        $rootScope.selectDevice = null;
458

    
459
        let params = $location.search();
460
        params.deviceId = null;
461
        params.direction = null;
462
        $location.search(params);
463

    
464
        $rootScope.$emit('setDefaultMap', null);
465
    };
466
});
467

    
468

    
469
app.controller('mapController', function ($rootScope, $scope, config, Device) {
470

    
471
    this.$onInit = function () {
472

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

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

    
504

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

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

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

    
543

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

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