Projekt

Obecné

Profil

« Předchozí | Další » 

Revize b88dd6bb

Přidáno uživatelem Jan Kohlíček před téměř 7 roky(ů)

refs #6949: rozdělení app.js do více souborů, grafy mají vlastní directive, gulp rozšířen o build-js

Zobrazit rozdíly:

frontend/app.js
1
let app = angular.module('pvpk', ['ngRoute', 'ngResource', 'ngSanitize']);
2

  
3
app.constant('config', {
4
    APP_NAME: 'PVPK',
5
    APP_VERSION: '1.2.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_MAX: 7,
11
});
12

  
13
app.controller('mainController', function ($rootScope, $scope, $location, $window) {
14

  
15
    this.$onInit = function () {
16
        $scope.showLoadingScreen = true;
17
    };
18

  
19
    $window.onload = function () {
20
        let params = $location.search();
21
        if (params.deviceId) {
22
            $rootScope.$emit('activeMarker', {id: params.deviceId});
23
        }
24

  
25
        $scope.$apply(function () {
26
            $scope.showLoadingScreen = false;
27
        });
28
    };
29

  
30
    $rootScope.$on('$locationChangeSuccess', function (event, newUrl, oldUrl) {
31
        let params = $location.search();
32

  
33
        if (newUrl !== oldUrl && $scope.historyUrl) {
34
            if ($scope.historyUrl.q !== $scope.historyUrl.q || $scope.historyUrl.isDirection != params.isDirection) {
35
                $rootScope.$emit('setSearchFromUrl', null);
36
            }
37

  
38
            if ($scope.historyUrl.fromDate !== params.fromDate || $scope.historyUrl.toDate !== params.toDate ||
39
                $scope.historyUrl.fromTime !== params.fromTime || $scope.historyUrl.toTime !== params.toTime) {
40
                $rootScope.$emit('setRangeFromUrl', null);
41
                if (params.deviceId) {
42
                    $rootScope.$emit('infoLocation', {id: params.deviceId, direction: params.direction});
43
                }
44
            } else if (params.deviceId && ($scope.historyUrl.deviceId !== params.deviceId || $scope.historyUrl.direction !== params.direction)) {
45
                $rootScope.$emit('infoLocation', {id: params.deviceId, direction: params.direction});
46
                $rootScope.$emit('activeMarker', {id: params.deviceId});
47
            } else if (!params.deviceId && $scope.historyUrl.deviceId) {
48
                $rootScope.selectDevice = null;
49
                $rootScope.$emit('setDefaultMap', null);
50
            }
51
        } else if (params.deviceId) {
52
            $rootScope.$emit('infoLocation', {id: params.deviceId, direction: params.direction});
53
        }
54

  
55
        $scope.historyUrl = $location.search();
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}
56 13
    });
14
angular.module('pvpk')
15
    .controller('infoController', ['$rootScope', '$scope', '$location', 'config', 'Device', 'Vehicle', function ($rootScope, $scope, $location, config, Device, Vehicle) {
57 16

  
58
    $rootScope.handleErrorResponse = function (response) {
59

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

  
107
    $scope.reloadApp = function () {
108
        $window.location.reload();
109
    }
110
});
111

  
112

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

  
115
    this.$onInit = function () {
116
        $scope.config = config;
117
        $scope.locations = [];
118
        $scope.showSearchLoading = false;
119

  
120
        $rootScope.$emit('setSearchFromUrl', null);
121
    };
122

  
123
    $scope.searchLocations = function () {
124
        let params = $location.search();
125
        params.q = $scope.search.q;
126
        params.isDirection = $scope.search.isDirection ? 1 : null;
127
        $location.search(params);
128

  
129
        if (!$scope.search.q || $scope.search.q.length <= 1) {
130
            $scope.locations = [];
131
            return;
132
        }
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
            });
133 30

  
134
        $scope.showSearchLoading = true;
31
            $rootScope.$emit('setRangeFromUrl', null);
32
        };
135 33

  
136
        Device.query({
137
            address: $scope.search.q,
138
            showDirection: $scope.search.isDirection ? 1 : 0
139
        }, function (data) {
140
            $scope.locations = data;
141
            $scope.showSearchLoading = false;
142
        }, function (response) {
143
            $scope.showSearchLoading = false;
144
            console.log('Error api all Devices');
145
            $rootScope.handleErrorResponse(response);
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
            };
146 43
        });
147
    };
148 44

  
149
    $rootScope.$on('setSearchFromUrl', function (event, args) {
150
        let params = $location.search();
151
        $scope.search = {
152
            q: params.q,
153
            isDirection: params.isDirection ? !!+params.isDirection : false
154
        };
155
        $scope.searchLocations();
156
    });
45
        $rootScope.$on('infoLocation', function (event, args) {
46
            $scope.showInfoLoading = true;
157 47

  
158
    $scope.selectDevice = function (id, direction) {
159
        $rootScope.$emit('activeMarker', {id: id});
160
        $rootScope.$emit('infoLocation', {id: id, direction: direction});
161
    };
48
            var params = $location.search();
49
            params.deviceId = args.id;
50
            params.direction = args.direction;
51
            $location.search(params);
162 52

  
163
});
53
            var range = $scope.getRange();
164 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
            };
165 64

  
166
app.controller('infoController', function ($rootScope, $scope, $location, config, Device, Vehicle) {
65
            Device.get(query, function (data) {
66
                $rootScope.selectDevice = data;
67
                $scope.renderGraph();
68
                $scope.urlExportCsv = $scope.generateUrlExportCsv(query);
167 69

  
168
    this.$onInit = function () {
169
        $rootScope.selectDevice = null;
170
        $scope.showInfoLoading = false;
171
        $scope.vehicles = [];
172
        $scope.filterVehicles = [];
173
        $scope.urlExportCsv = null;
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
            });
174 77

  
175
        Vehicle.query(null, function (data) {
176
            $scope.vehicles = data;
177
        }, function (response) {
178
            $rootScope.graphShow = false;
179
            console.log('Error api all Vehicles');
180
            $rootScope.handleErrorResponse(response);
181 78
        });
182 79

  
183
        $rootScope.$emit('setRangeFromUrl', null);
184
    };
185

  
186
    $rootScope.$on('setRangeFromUrl', function (event, args) {
187
        let params = $location.search();
188
        let defaultRange = $scope.defaultRange();
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;
189 84

  
190
        $scope.range = {
191
            fromDate: moment(params.fromDate, 'YYYY-MM-DD').isValid() ? moment(params.fromDate).toDate() : defaultRange.fromDate.toDate(),
192
            toDate: moment(params.toDate, 'YYYY-MM-DD').isValid() ? moment(params.toDate).toDate() : defaultRange.toDate.toDate(),
193
            fromTime: moment(params.fromTime, 'HH:mm').isValid() ? moment(params.fromTime, 'HH:mm').toDate() : defaultRange.fromTime.toDate(),
194
            toTime: moment(params.toTime, 'HH:mm').isValid() ? moment(params.toTime, 'HH:mm').toDate() : defaultRange.toTime.toDate(),
195
            isTime: params.isTime == 0 ? false : defaultRange.isTime
85
            var paramsUrl = jQuery.param(query);
86
            return config.API_URL + relativeUrl + paramsUrl;
196 87
        };
197 88

  
198
    });
199

  
200
    $rootScope.$on('infoLocation', function (event, args) {
201
        $scope.showInfoLoading = true;
202

  
203
        let params = $location.search();
204
        params.deviceId = args.id;
205
        params.direction = args.direction;
206
        $location.search(params);
207

  
208
        let range = $scope.getRange();
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
            }
209 94

  
210
        let query = {
211
            period: range.isTime ? 'time-period' : 'day-period',
212
            id: args.id,
213
            direction: args.direction,
214
            dateFrom: range.fromDate.format('YYYY-MM-DD'),
215
            dateTo: range.toDate.format('YYYY-MM-DD'),
216
            timeFrom: range.isTime ? range.fromTime.format('HH:mm') : null,
217
            timeTo: range.isTime ? range.toTime.format('HH:mm') : null
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
                });
218 110
        };
219 111

  
220
        Device.get(query, function (data) {
221
            $rootScope.selectDevice = data;
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
        };
222 121

  
223
            $scope.renderGraphAverageSpeed();
224
            $scope.renderGraphNumberVehicles();
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)'];
225 126

  
226
            $scope.urlExportCsv = $scope.generateUrlExportCsv(query);
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
            }));
227 130

  
228
            $scope.showInfoLoading = false;
229
        }, function (response) {
230
            $rootScope.selectDevice = null;
231
            $scope.showInfoLoading = false;
232
            console.log('Error api get Devices');
233
            $rootScope.handleErrorResponse(response);
234
        });
131
            var useVehiclesIds = jQuery.unique($rootScope.selectDevice.traffics.map(function (d) {
132
                return d.typeVehicleId;
133
            }));
235 134

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

  
238
    $scope.generateUrlExportCsv = function (query) {
239
        let relativeUrl = '/devices/:id/:period/csv?'.replace(':id', query.id).replace(':period', query.period);
240
        delete query.id;
241
        delete query.period;
139
            var datasetsNumberVehicles = [];
140
            var datasetsAverageSpeed = [];
242 141

  
243
        let paramsUrl = jQuery.param(query);
244
        return config.API_URL + relativeUrl + paramsUrl;
245
    };
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
                };
246 150

  
247
    $scope.changeRange = function () {
248
        if ($scope.range.fromDate >= $scope.range.toDate || ($scope.range.isTime && $scope.range.fromTime >= $scope.range.toTime)) {
249
            $rootScope.selectDevice.traffics = [];
250
            return;
251
        }
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
                };
252 162

  
253
        let range = $scope.getRange();
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
            }
254 180

  
255
        let params = $location.search();
256
        params.fromDate = range.fromDate.format('YYYY-MM-DD');
257
        params.toDate = range.toDate.format('YYYY-MM-DD');
258
        params.fromTime = range.isTime ? range.fromTime.format('HH:mm') : null;
259
        params.toTime = range.isTime ? range.toTime.format('HH:mm') : null;
260
        params.isTime = range.isTime ? null : 0;
261
        $location.search(params);
181
            $rootScope.$emit('renderGraphNumberVehicles', {
182
                data: {
183
                    labels: labels,
184
                    datasets: datasetsNumberVehicles
185
                }
186
            });
262 187

  
263
        if ($rootScope.selectDevice)
264
            $rootScope.$emit('infoLocation', {
265
                id: $rootScope.selectDevice.id,
266
                direction: $rootScope.selectDevice.direction
188
            $rootScope.$emit('renderGraphAverageSpeed', {
189
                data: {
190
                    labels: labels,
191
                    datasets: datasetsAverageSpeed
192
                }
267 193
            });
268
    };
194
        };
269 195

  
270
    $scope.getRange = function () {
271
        let defaultRange = $scope.defaultRange();
196
        $scope.infoClose = function () {
197
            $rootScope.selectDevice = null;
272 198

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

  
282
    $scope.defaultRange = function () {
283
        return {
284
            fromDate: moment().day(-30),
285
            toDate: moment().day(-1),
286
            fromTime: moment({hour: 7}),
287
            toTime: moment({hour: 16}),
288
            isTime: true
199
            var params = $location.search();
200
            params.deviceId = null;
201
            params.direction = null;
202
            $location.search(params);
203

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

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

  
294
        let t = $rootScope.selectDevice.traffics.reduce(function (l, r) {
295
            let key = $scope.range.isTime ? r.timeFrom : r.date;
296
            if (typeof l[key] === 'undefined') {
297
                l[key] = {
298
                    numberVehicle: 0,
299
                    speedSum: 0
300
                };
301
            }
211
        this.$onInit = function () {
212
            $scope.showLoadingScreen = true;
213
        };
302 214

  
303
            if (r.speedAverage > 0) {
304
                l[key].numberVehicle += r.numberVehicle;
305
                l[key].speedSum += r.speedAverage * r.numberVehicle;
215
        $window.onload = function () {
216
            var params = $location.search();
217
            if (params.deviceId) {
218
                $rootScope.$emit('activeMarker', {id: params.deviceId});
306 219
            }
307
            return l;
308
        }, {});
309

  
310
        let labels = jQuery.unique($rootScope.selectDevice.traffics.map(function (d) {
311
            return $scope.range.isTime ? d.timeFrom : moment(d.date, 'YYYY-MM-DD').format('D.M.YYYY');
312
        }));
313
        let data = Object.values(t).map(function (d) {
314
            return Math.round(d.speedSum / d.numberVehicle);
315
        });
316 220

  
317
        let canvasGraphAverageSpeed = document.getElementById('graphAverageSpeed').getContext('2d');
221
            $scope.$apply(function () {
222
                $scope.showLoadingScreen = false;
223
            });
224
        };
225

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

  
319
        if ($scope.graphAverageSpeed)
320
            $scope.graphAverageSpeed.destroy();
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
                }
321 233

  
322
        $scope.graphAverageSpeed = new Chart(canvasGraphAverageSpeed, {
323
            type: 'line',
324
            data: {
325
                labels: labels,
326
                datasets: [{
327
                    data: data,
328
                    borderWidth: 2,
329
                    label: "Rychlost",
330
                    fill: 'start',
331
                    backgroundColor: 'rgba(0, 123, 255, 0.3)',
332
                    borderColor: 'rgba(0, 123, 255,1)',
333
                    cubicInterpolationMode: 'monotone',
334
                    pointRadius: 0
335
                }]
336
            },
337
            options: {
338
                responsive: true,
339
                pointDot: false,
340
                legend: {
341
                    display: false
342
                },
343
                scales: {
344
                    xAxes: [{
345
                        ticks: {
346
                            autoSkip: true,
347
                            maxTicksLimit: 15
348
                        }
349
                    }],
350
                    yAxes: [{
351
                        scaleLabel: {
352
                            display: true,
353
                            labelString: 'km/h'
354
                        },
355
                        ticks: {
356
                            beginAtZero: true,
357
                            max: Math.max(Math.round((Math.max.apply(null, data) + 10) / 10) * 10, 70)
358
                        }
359
                    }]
360
                },
361
                tooltips: {
362
                    mode: 'index',
363
                    intersect: false,
364
                    callbacks: {
365
                        label: function (tooltipItems) {
366
                            return tooltipItems.yLabel + ' km/h';
367
                        }
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});
368 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);
369 246
                }
247
            } else if (params.deviceId) {
248
                $rootScope.$emit('infoLocation', {id: params.deviceId, direction: params.direction});
370 249
            }
371
        });
372
    };
373

  
374 250

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

  
380

  
381
        let labels = jQuery.unique($rootScope.selectDevice.traffics.map(function (d) {
382
            return $scope.range.isTime ? d.timeFrom : moment(d.date, 'YYYY-MM-DD').format('D.M.YYYY');
383
        }));
384

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

  
389
        $scope.filterVehicles = jQuery.grep($scope.vehicles, function (n) {
390
            return useVehiclesIds.indexOf(n.id) >= 0;
251
            $scope.historyUrl = $location.search();
391 252
        });
392 253

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

  
403
            let l = 0;
404
            for (let j = 0, traffic; traffic = $rootScope.selectDevice.traffics[j]; j++) {
405
                if (($scope.range.isTime && labels[l] !== traffic.timeFrom) || (!$scope.range.isTime && labels[l] !== moment(traffic.date, 'YYYY-MM-DD').format('D.M.YYYY'))) {
406
                    l++;
407
                    if (dataset.data.length < l) {
408
                        dataset.data.push(0);
409
                    }
410
                }
411
                if (traffic.typeVehicleId === vehicle.id) {
412
                    dataset.data.push($scope.range.isTime ? traffic.numberVehicleAverage : traffic.numberVehicle);
413
                }
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;
414 300
            }
415
            datasets.push(dataset);
301
        };
302

  
303
        $scope.reloadApp = function () {
304
            $window.location.reload();
416 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
            });
417 325

  
418
        let canvasGraphNumberVehicles = document.getElementById('graphNumberVehicles').getContext('2d');
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
        };
419 335

  
420
        if ($scope.graphNumberVehicles)
421
            $scope.graphNumberVehicles.destroy();
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
        };
422 358

  
423
        $scope.graphNumberVehicles = new Chart(canvasGraphNumberVehicles, {
424
            type: 'bar',
425
            data: {
426
                labels: labels,
427
                datasets: datasets
428
            },
429
            options: {
430
                responsive: true,
431
                onResize: function (chart, size) {
432
                    chart.options.legend.display = size.height > 240;
433
                    chart.update();
434
                },
435
                legend: {
436
                    position: 'bottom',
437
                },
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
                tooltips: {
455
                    mode: 'index',
456
                    intersect: false
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();
457 367
                }
458 368
            }
459 369
        });
460
    };
461 370

  
462
    $scope.infoClose = function () {
463
        $rootScope.selectDevice = null;
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) {
464 385

  
465
        let params = $location.search();
466
        params.deviceId = null;
467
        params.direction = null;
468
        $location.search(params);
386
        this.$onInit = function () {
387
            $scope.config = config;
388
            $scope.locations = [];
389
            $scope.showSearchLoading = false;
469 390

  
470
        $rootScope.$emit('setDefaultMap', null);
471
    };
472
});
391
            $rootScope.$emit('setSearchFromUrl', null);
392
        };
473 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);
474 399

  
475
app.controller('mapController', function ($rootScope, $scope, config, Device) {
400
            if (!$scope.search.q || $scope.search.q.length <= 1) {
401
                $scope.locations = [];
402
                return;
403
            }
476 404

  
477
    this.$onInit = function () {
478
        $scope.markers = [];
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
        };
479 419

  
480
        $scope.map = new google.maps.Map(document.getElementById('map'), {
481
            center: {lat: config.DEFAULT_POSITION.LAT, lng: config.DEFAULT_POSITION.LNG},
482
            zoom: config.DEFAULT_ZOOM,
483
            minZoom: config.DEFAULT_ZOOM_MAX,
484
            zoomControl: true,
485
            mapTypeControl: false,
486
            scaleControl: false,
487
            streetViewControl: false,
488
            rotateControl: false,
489
            fullscreenControl: false,
490
            mapTypeId: google.maps.MapTypeId.ROADMAP
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();
491 427
        });
492 428

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

  
503
    $scope.createMarker = function (lctn) {
504
        if (lctn.lat && lctn.lng) {
505
            let marker = new google.maps.Marker({
506
                map: $scope.map,
507
                position: {lat: lctn.lat, lng: lctn.lng},
508
                title: lctn.name,
509
                infoWindow: new google.maps.InfoWindow({
510
                    content: '<h6 class="mb-1">' + lctn.name + '</h6>'
511
                    + '<address>' + lctn.street + ', ' + lctn.town + '</address>'
512
                }),
513
                id: lctn.id
514
            });
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
                });
515 484

  
516
            marker.addListener('click', function () {
517
                $scope.closeInfoWindows();
518
                marker.infoWindow.open($scope.map, marker);
519
                $rootScope.$emit('infoLocation', {id: lctn.id});
520 485
            });
521 486

  
522
            $scope.markers.push(marker);
523
        }
524
    };
525

  
526
    $rootScope.$on('activeMarker', function (event, args) {
527
        let id = args.id;
528
        for (let i = 0, marker; marker = $scope.markers[i]; i++) {
529
            if (marker.id && marker.id === id && marker.infoWindow) {
530
                $scope.map.setCenter(marker.getPosition());
531
                $scope.map.setZoom(12);
532
                marker.infoWindow.open($scope.map, marker);
533
            } else {
534
                marker.infoWindow.close();
535
            }
536
        }
487
        }]
537 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
                });
538 534

  
539
    $rootScope.$on('setDefaultMap', function (event, args) {
540
        $scope.map.setCenter({lat: config.DEFAULT_POSITION.LAT, lng: config.DEFAULT_POSITION.LNG});
541
        $scope.map.setZoom(config.DEFAULT_ZOOM);
542
        $scope.closeInfoWindows();
543
    });
535
            });
544 536

  
545
    $scope.closeInfoWindows = function () {
546
        for (let i = 0, marker; marker = $scope.markers[i]; i++) {
547
            marker.infoWindow.close();
548
        }
549
    };
550
});
551

  
552

  
553
app.factory('Device', function ($resource, config) {
554
    return $resource(config.API_URL + '/devices/:id', {id: '@id', period: '@period'}, {
555
        'get': {
556
            url: config.API_URL + '/devices/:id/:period',
557
            method: 'GET',
558
            headers: {
559
                'Content-Type': 'application/json',
560
                'Accept': 'application/json',
561
                'jwt': config.API_TOKEN
562
            }
563
        },
564
        'query': {
565
            url: config.API_URL + '/devices',
566
            method: 'GET',
567
            isArray: true,
568
            headers: {
569
                'Content-Type': 'application/json',
570
                'Accept': 'application/json',
571
                'jwt': config.API_TOKEN
572
            }
573
        }
537
        }]
574 538
    });
575
});
576

  
577
app.factory('Vehicle', function ($resource, config) {
578
    return $resource(config.API_URL + '/vehicles', null, {
579
        'query': {
580
            url: config.API_URL + '/vehicles',
581
            method: 'GET',
582
            isArray: true,
583
            headers: {
584
                'Content-Type': 'application/json',
585
                'Accept': 'application/json',
586
                'jwt': config.API_TOKEN
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
                }
587 560
            }
588
        }
589
    });
590
});
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
    }]);
frontend/app.min.js
1
angular.module("pvpk",["ngResource","ngSanitize"]),angular.module("pvpk").constant("config",{APP_NAME:"PVPK",APP_VERSION:"1.3.0",API_URL:API_URL,API_TOKEN:API_TOKEN,DEFAULT_POSITION:{lat:49.53,lng:13.3},DEFAULT_ZOOM:10,DEFAULT_ZOOM_MIN:7,DEFAULT_RANGE_DATE_DAY:{from:-30,to:-1},DEFAULT_RANGE_TIME_HOUR:{from:7,to:16}}),angular.module("pvpk").controller("infoController",["$rootScope","$scope","$location","config","Device","Vehicle",function(u,h,r,i,n,e){this.$onInit=function(){u.selectDevice=null,h.showInfoLoading=!1,h.vehicles=[],h.urlExportCsv=null,e.query(null,function(e){h.vehicles=e},function(e){u.graphShow=!1,console.log("Error api all Vehicles"),u.handleErrorResponse(e)}),u.$emit("setRangeFromUrl",null)},u.$on("setRangeFromUrl",function(e,o){var t=r.search();h.range={fromDate:moment(t.fromDate,"YYYY-MM-DD").isValid()?moment(t.fromDate).toDate():moment().add(i.DEFAULT_RANGE_DATE_DAY.from,"d").toDate(),toDate:moment(t.toDate,"YYYY-MM-DD").isValid()?moment(t.toDate).toDate():moment().add(i.DEFAULT_RANGE_DATE_DAY.to,"d").toDate(),fromTime:moment(t.fromTime,"HH:mm").isValid()?moment(t.fromTime,"HH:mm").toDate():moment({hour:i.DEFAULT_RANGE_TIME_HOUR.from}).toDate(),toTime:moment(t.toTime,"HH:mm").isValid()?moment(t.toTime,"HH:mm").toDate():moment({hour:i.DEFAULT_RANGE_TIME_HOUR.to}).toDate(),isTime:0!=t.isTime}}),u.$on("infoLocation",function(e,o){h.showInfoLoading=!0;var t=r.search();t.deviceId=o.id,t.direction=o.direction,r.search(t);var i=h.getRange(),a={period:i.isTime?"time-period":"day-period",id:o.id,direction:o.direction,dateFrom:i.fromDate.format("YYYY-MM-DD"),dateTo:i.toDate.format("YYYY-MM-DD"),timeFrom:i.isTime?i.fromTime.format("HH:mm"):null,timeTo:i.isTime?i.toTime.format("HH:mm"):null};n.get(a,function(e){u.selectDevice=e,h.renderGraph(),h.urlExportCsv=h.generateUrlExportCsv(a),h.showInfoLoading=!1},function(e){u.selectDevice=null,h.showInfoLoading=!1,console.log("Error api get Devices"),u.handleErrorResponse(e)})}),h.generateUrlExportCsv=function(e){var o="/devices/:id/:period/csv?".replace(":id",e.id).replace(":period",e.period);delete e.id,delete e.period;var t=jQuery.param(e);return i.API_URL+o+t},h.changeRange=function(){if(h.range.fromDate>=h.range.toDate||h.range.isTime&&h.range.fromTime>=h.range.toTime)u.selectDevice.traffics=[];else{var e=h.getRange(),o=r.search();o.fromDate=e.fromDate.format("YYYY-MM-DD"),o.toDate=e.toDate.format("YYYY-MM-DD"),o.fromTime=e.isTime?e.fromTime.format("HH:mm"):null,o.toTime=e.isTime?e.toTime.format("HH:mm"):null,o.isTime=e.isTime?null:0,r.search(o),u.selectDevice&&u.$emit("infoLocation",{id:u.selectDevice.id,direction:u.selectDevice.direction})}},h.getRange=function(){return{fromDate:moment(h.range.fromDate).isValid()?moment(h.range.fromDate):moment().add(i.DEFAULT_RANGE_DATE_DAY.from,"d"),toDate:moment(h.range.toDate).isValid()?moment(h.range.toDate):moment().add(i.DEFAULT_RANGE_DATE_DAY.to,"d"),fromTime:moment(h.range.fromTime).isValid()?moment(h.range.fromTime):moment({hour:i.DEFAULT_RANGE_TIME_HOUR.from}),toTime:moment(h.range.toTime).isValid()?moment(h.range.toTime):moment({hour:i.DEFAULT_RANGE_TIME_HOUR.to}),isTime:!!h.range.isTime}},h.renderGraph=function(){for(var e,o=["rgba(158, 158, 158, #alpha)","rgba(213, 0, 0, #alpha)","rgba(0, 123, 255, #alpha)","rgba(170, 0, 255, #alpha)","rgba(0, 200, 83, #alpha)","rgba(255, 214, 0, #alpha)","rgba(255, 109, 0, #alpha)","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)"],t=jQuery.unique(u.selectDevice.traffics.map(function(e){return h.range.isTime?e.timeFrom:moment(e.date,"YYYY-MM-DD").format("D.M.YYYY")})),i=jQuery.unique(u.selectDevice.traffics.map(function(e){return e.typeVehicleId})),a=jQuery.grep(h.vehicles,function(e){return 0<=i.indexOf(e.id)}),r=[],n=[],l=0;e=a[l];l++){for(var c,s={label:e.name,backgroundColor:o[e.id].replace("#alpha","0.3"),borderColor:o[e.id].replace("#alpha","1"),borderWidth:2,data:[]},m={data:[],borderWidth:2,label:e.name,fill:!1,backgroundColor:o[e.id].replace("#alpha","0.3"),borderColor:o[e.id].replace("#alpha","1"),cubicInterpolationMode:"monotone",pointRadius:0},d=0,p=0;c=u.selectDevice.traffics[p];p++)(h.range.isTime&&t[d]!==c.timeFrom||!h.range.isTime&&t[d]!==moment(c.date,"YYYY-MM-DD").format("D.M.YYYY"))&&(d++,s.data.length<d&&(s.data.push(0),m.data.push(null))),c.typeVehicleId===e.id&&(s.data.push(h.range.isTime?c.numberVehicleAverage:c.numberVehicle),m.data.push(c.speedAverage<=0?null:c.speedAverage));r.push(s),n.push(m)}u.$emit("renderGraphNumberVehicles",{data:{labels:t,datasets:r}}),u.$emit("renderGraphAverageSpeed",{data:{labels:t,datasets:n}})},h.infoClose=function(){u.selectDevice=null;var e=r.search();e.deviceId=null,e.direction=null,r.search(e),u.$emit("setDefaultMap",null)}}]),angular.module("pvpk").controller("mainController",["$rootScope","$scope","$location","$window",function(a,r,n,e){this.$onInit=function(){r.showLoadingScreen=!0},e.onload=function(){var e=n.search();e.deviceId&&a.$emit("activeMarker",{id:e.deviceId}),r.$apply(function(){r.showLoadingScreen=!1})},a.$on("$locationChangeSuccess",function(e,o,t){var i=n.search();o!==t&&r.historyUrl?(r.historyUrl.q==r.historyUrl.q&&r.historyUrl.isDirection==i.isDirection||a.$emit("setSearchFromUrl",null),r.historyUrl.fromDate!==i.fromDate||r.historyUrl.toDate!==i.toDate||r.historyUrl.fromTime!==i.fromTime||r.historyUrl.toTime!==i.toTime?(a.$emit("setRangeFromUrl",null),i.deviceId&&a.$emit("infoLocation",{id:i.deviceId,direction:i.direction})):!i.deviceId||r.historyUrl.deviceId===i.deviceId&&r.historyUrl.direction===i.direction?!i.deviceId&&r.historyUrl.deviceId&&(a.selectDevice=null,a.$emit("setDefaultMap",null)):(a.$emit("infoLocation",{id:i.deviceId,direction:i.direction}),a.$emit("activeMarker",{id:i.deviceId}))):i.deviceId&&a.$emit("infoLocation",{id:i.deviceId,direction:i.direction}),r.historyUrl=n.search()}),a.handleErrorResponse=function(e){var o=jQuery("#modalError");switch(e.status){case 400:console.log("API ERROR 400"),r.modalError={title:"Neplatný požadavek",body:"Požadavek nemůže být vyřízen, poněvadž byl syntakticky nesprávně zapsán.",button:"OK"},o.modal("show");break;case 401:r.modalError={title:"Platnost webové aplikace vypršela",body:"Pro obnovení platnosti stačí stisknout tlačítko <strong>Obnovit</strong>.",button:"Obnovit",clickButton:r.reloadApp},o.modal({backdrop:"static",keyboard:!1});break;case 404:console.log("API ERROR 404"),r.modalError={title:"Nenalezen",body:"Záznam nebyl nalezen.",button:"OK"},o.modal("show");break;case 500:console.log("API ERROR 500"),r.modalError={title:"Chyba",body:"Chyba serveru. Zopakujte akci později.",button:"OK"},o.modal("show");break;case-1:console.log("API NOT CONNECTED"),r.modalError={title:"Připojení k internetu",body:"Nejste připojeni k internetu. Zkontrolujte připojení.",button:"OK"},o.modal("show");break;default:console.log("API UNKNOWN ERROR"),r.modalError={title:"Neočekávaná chyba",body:"Nastala neočekávaná chyba.",button:"OK"},o.modal("show")}},r.reloadApp=function(){e.location.reload()}}]),angular.module("pvpk").controller("mapController",["$rootScope","$scope","config","Device",function(t,a,i,e){this.$onInit=function(){a.markers=[],a.map=new google.maps.Map(document.getElementById("map"),{center:i.DEFAULT_POSITION,zoom:i.DEFAULT_ZOOM,minZoom:i.DEFAULT_ZOOM_MIN,zoomControl:!0,mapTypeControl:!1,scaleControl:!1,streetViewControl:!1,rotateControl:!1,fullscreenControl:!1,mapTypeId:google.maps.MapTypeId.ROADMAP}),e.query({showDirection:0},function(e){for(var o,t=0;o=e[t];t++)a.createMarker(o)},function(e){console.log("Error api all Devices"),t.handleErrorResponse(e)})},a.createMarker=function(e){if(e.lat&&e.lng){var o=new google.maps.Marker({map:a.map,position:{lat:e.lat,lng:e.lng},title:e.name,infoWindow:new google.maps.InfoWindow({content:'<h6 class="mb-1">'+e.name+"</h6><address>"+e.street+", "+e.town+"</address>"}),id:e.id});o.addListener("click",function(){a.closeInfoWindows(),o.infoWindow.open(a.map,o),t.$emit("infoLocation",{id:e.id})}),a.markers.push(o)}},t.$on("activeMarker",function(e,o){for(var t,i=0;t=a.markers[i];i++)t.id&&t.id===o.id&&t.infoWindow?(a.map.setCenter(t.getPosition()),a.map.setZoom(12),t.infoWindow.open(a.map,t)):t.infoWindow.close()}),t.$on("setDefaultMap",function(e,o){a.map.setCenter(i.DEFAULT_POSITION),a.map.setZoom(i.DEFAULT_ZOOM),a.closeInfoWindows()}),a.closeInfoWindows=function(){for(var e,o=0;e=a.markers[o];o++)e.infoWindow.close()}}]),angular.module("pvpk").controller("searchController",["$rootScope","$scope","$location","config","Device",function(t,i,a,e,o){this.$onInit=function(){i.config=e,i.locations=[],i.showSearchLoading=!1,t.$emit("setSearchFromUrl",null)},i.searchLocations=function(){var e=a.search();e.q=i.search.q,e.isDirection=i.search.isDirection?1:null,a.search(e),!i.search.q||i.search.q.length<=1?i.locations=[]:(i.showSearchLoading=!0,o.query({address:i.search.q,showDirection:i.search.isDirection?1:0},function(e){i.locations=e,i.showSearchLoading=!1},function(e){i.showSearchLoading=!1,console.log("Error api all Devices"),t.handleErrorResponse(e)}))},t.$on("setSearchFromUrl",function(e,o){var t=a.search();i.search={q:t.q,isDirection:!!t.isDirection&&!!+t.isDirection},i.searchLocations()}),i.selectDevice=function(e,o){t.$emit("activeMarker",{id:e}),t.$emit("infoLocation",{id:e,direction:o})}}]),angular.module("pvpk").component("graphAverageSpeed",{template:'<div><canvas id="graphAverageSpeed" class="graphSize mb-5"></canvas></div>',controller:["$rootScope","$scope",function(e,i){e.$on("renderGraphAverageSpeed",function(e,o){var t=document.getElementById("graphAverageSpeed").getContext("2d");i.graphLine&&i.graphLine.destroy(),i.graphLine=new Chart(t,{type:"line",data:o.data,options:{responsive:!0,pointDot:!1,legend:{position:"bottom"},scales:{xAxes:[{ticks:{autoSkip:!0,maxTicksLimit:15}}],yAxes:[{scaleLabel:{display:!0,labelString:"km/h"},ticks:{beginAtZero:!0,suggestedMax:70}}]},tooltips:{mode:"index",intersect:!1,callbacks:{label:function(e){return e.yLabel+" km/h"}}}}})})}]}),angular.module("pvpk").component("graphNumberVehicles",{template:'<div><canvas id="graphNumberVehicles" class="graphSize mb-5"></canvas></div>',controller:["$rootScope","$scope",function(e,i){e.$on("renderGraphNumberVehicles",function(e,o){var t=document.getElementById("graphNumberVehicles").getContext("2d");i.graphNumberVehicles&&i.graphNumberVehicles.destroy(),i.graphNumberVehicles=new Chart(t,{type:"bar",data:o.data,options:{responsive:!0,onResize:function(e,o){e.options.legend.display=240<o.height,e.update()},legend:{position:"bottom"},scales:{xAxes:[{stacked:!0,ticks:{autoSkip:!0,maxTicksLimit:15}}],yAxes:[{scaleLabel:{display:!0,labelString:"počet vozidel"},stacked:!0}]},tooltips:{mode:"index",intersect:!1}}})})}]}),angular.module("pvpk").factory("Device",["$resource","config",function(e,o){return e(o.API_URL+"/devices/:id",{id:"@id",period:"@period"},{get:{url:o.API_URL+"/devices/:id/:period",method:"GET",headers:{"Content-Type":"application/json",Accept:"application/json",jwt:o.API_TOKEN}},query:{url:o.API_URL+"/devices",method:"GET",isArray:!0,headers:{"Content-Type":"application/json",Accept:"application/json",jwt:o.API_TOKEN}}})}]),angular.module("pvpk").factory("Vehicle",["$resource","config",function(e,o){return e(o.API_URL+"/vehicles",null,{query:{url:o.API_URL+"/vehicles",method:"GET",isArray:!0,headers:{"Content-Type":"application/json",Accept:"application/json",jwt:o.API_TOKEN}}})}]);
2
//# sourceMappingURL=app.min.js.map
frontend/app.min.js.map
1
{"version":3,"sources":["app.module.js","app.config.js","infoController.js","mainController.js","mapController.js","searchController.js","graphAverageSpeed.js","graphNumberVehicles.js","DeviceService.js","VehicleService.js"],"names":["angular","module","constant","APP_NAME","APP_VERSION","API_URL","API_TOKEN","DEFAULT_POSITION","lat","lng","DEFAULT_ZOOM","DEFAULT_ZOOM_MIN","DEFAULT_RANGE_DATE_DAY","from","to","DEFAULT_RANGE_TIME_HOUR","controller","$rootScope","$scope","$location","config","Device","Vehicle","this","$onInit","selectDevice","showInfoLoading","vehicles","urlExportCsv","query","data","response","graphShow","console","log","handleErrorResponse","$emit","$on","event","args","params","search","range","fromDate","moment","isValid","toDate","add","fromTime","hour","toTime","isTime","deviceId","id","direction","getRange","period","dateFrom","format","dateTo","timeFrom","timeTo","get","renderGraph","generateUrlExportCsv","relativeUrl","replace","paramsUrl","jQuery","param","changeRange","traffics","vehicle","color","labels","unique","map","d","date","useVehiclesIds","typeVehicleId","filterVehicles","grep","n","indexOf","datasetsNumberVehicles","datasetsAverageSpeed","i","traffic","datasetNumberVehicles","label","name","backgroundColor","borderColor","borderWidth","datasetAverageSpeed","fill","cubicInterpolationMode","pointRadius","l","j","length","push","numberVehicleAverage","numberVehicle","speedAverage","datasets","infoClose","$window","showLoadingScreen","onload","$apply","newUrl","oldUrl","historyUrl","q","isDirection","modalError","status","title","body","button","modal","clickButton","reloadApp","backdrop","keyboard","location","reload","markers","google","maps","Map","document","getElementById","center","zoom","minZoom","zoomControl","mapTypeControl","scaleControl","streetViewControl","rotateControl","fullscreenControl","mapTypeId","MapTypeId","ROADMAP","showDirection","lctn","createMarker","marker","Marker","position","infoWindow","InfoWindow","content","street","town","addListener","closeInfoWindows","open","setCenter","getPosition","setZoom","close","locations","showSearchLoading","searchLocations","address","component","template","canvas","getContext","graphLine","destroy","Chart","type","options","responsive","pointDot","legend","scales","xAxes","ticks","autoSkip","maxTicksLimit","yAxes","scaleLabel","display","labelString","beginAtZero","suggestedMax","tooltips","mode","intersect","callbacks","tooltipItems","yLabel","canvasGraphNumberVehicles","graphNumberVehicles","onResize","chart","size","height","update","stacked","factory","$resource","url","method","headers","Content-Type","Accept","jwt","isArray"],"mappings":"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","file":"app.min.js","sourcesContent":["angular.module('pvpk', ['ngResource', 'ngSanitize']);","angular.module('pvpk')\r\n    .constant('config', {\r\n        APP_NAME: 'PVPK',\r\n        APP_VERSION: '1.3.0',\r\n        API_URL: API_URL,\r\n        API_TOKEN: API_TOKEN,\r\n        DEFAULT_POSITION: {lat: 49.53, lng: 13.3},\r\n        DEFAULT_ZOOM: 10,\r\n        DEFAULT_ZOOM_MIN: 7,\r\n        DEFAULT_RANGE_DATE_DAY: {from: -30, to: -1},\r\n        DEFAULT_RANGE_TIME_HOUR: {from: 7, to: 16}\r\n    });","angular.module('pvpk')\r\n    .controller('infoController', ['$rootScope', '$scope', '$location', 'config', 'Device', 'Vehicle', function ($rootScope, $scope, $location, config, Device, Vehicle) {\r\n\r\n        this.$onInit = function () {\r\n            $rootScope.selectDevice = null;\r\n            $scope.showInfoLoading = false;\r\n            $scope.vehicles = [];\r\n            $scope.urlExportCsv = null;\r\n\r\n            Vehicle.query(null, function (data) {\r\n                $scope.vehicles = data;\r\n            }, function (response) {\r\n                $rootScope.graphShow = false;\r\n                console.log('Error api all Vehicles');\r\n                $rootScope.handleErrorResponse(response);\r\n            });\r\n\r\n            $rootScope.$emit('setRangeFromUrl', null);\r\n        };\r\n\r\n        $rootScope.$on('setRangeFromUrl', function (event, args) {\r\n            var params = $location.search();\r\n            $scope.range = {\r\n                fromDate: moment(params.fromDate, 'YYYY-MM-DD').isValid() ? moment(params.fromDate).toDate() : moment().add(config.DEFAULT_RANGE_DATE_DAY.from, 'd').toDate(),\r\n                toDate: moment(params.toDate, 'YYYY-MM-DD').isValid() ? moment(params.toDate).toDate() : moment().add(config.DEFAULT_RANGE_DATE_DAY.to, 'd').toDate(),\r\n                fromTime: moment(params.fromTime, 'HH:mm').isValid() ? moment(params.fromTime, 'HH:mm').toDate() : moment({hour: config.DEFAULT_RANGE_TIME_HOUR.from}).toDate(),\r\n                toTime: moment(params.toTime, 'HH:mm').isValid() ? moment(params.toTime, 'HH:mm').toDate() : moment({hour: config.DEFAULT_RANGE_TIME_HOUR.to}).toDate(),\r\n                isTime: params.isTime == 0 ? false : true\r\n            };\r\n        });\r\n\r\n        $rootScope.$on('infoLocation', function (event, args) {\r\n            $scope.showInfoLoading = true;\r\n\r\n            var params = $location.search();\r\n            params.deviceId = args.id;\r\n            params.direction = args.direction;\r\n            $location.search(params);\r\n\r\n            var range = $scope.getRange();\r\n\r\n            var query = {\r\n                period: range.isTime ? 'time-period' : 'day-period',\r\n                id: args.id,\r\n                direction: args.direction,\r\n                dateFrom: range.fromDate.format('YYYY-MM-DD'),\r\n                dateTo: range.toDate.format('YYYY-MM-DD'),\r\n                timeFrom: range.isTime ? range.fromTime.format('HH:mm') : null,\r\n                timeTo: range.isTime ? range.toTime.format('HH:mm') : null\r\n            };\r\n\r\n            Device.get(query, function (data) {\r\n                $rootScope.selectDevice = data;\r\n                $scope.renderGraph();\r\n                $scope.urlExportCsv = $scope.generateUrlExportCsv(query);\r\n\r\n                $scope.showInfoLoading = false;\r\n            }, function (response) {\r\n                $rootScope.selectDevice = null;\r\n                $scope.showInfoLoading = false;\r\n                console.log('Error api get Devices');\r\n                $rootScope.handleErrorResponse(response);\r\n            });\r\n\r\n        });\r\n\r\n        $scope.generateUrlExportCsv = function (query) {\r\n            var relativeUrl = '/devices/:id/:period/csv?'.replace(':id', query.id).replace(':period', query.period);\r\n            delete query.id;\r\n            delete query.period;\r\n\r\n            var paramsUrl = jQuery.param(query);\r\n            return config.API_URL + relativeUrl + paramsUrl;\r\n        };\r\n\r\n        $scope.changeRange = function () {\r\n            if ($scope.range.fromDate >= $scope.range.toDate || ($scope.range.isTime && $scope.range.fromTime >= $scope.range.toTime)) {\r\n                $rootScope.selectDevice.traffics = [];\r\n                return;\r\n            }\r\n\r\n            var range = $scope.getRange();\r\n\r\n            var params = $location.search();\r\n            params.fromDate = range.fromDate.format('YYYY-MM-DD');\r\n            params.toDate = range.toDate.format('YYYY-MM-DD');\r\n            params.fromTime = range.isTime ? range.fromTime.format('HH:mm') : null;\r\n            params.toTime = range.isTime ? range.toTime.format('HH:mm') : null;\r\n            params.isTime = range.isTime ? null : 0;\r\n            $location.search(params);\r\n\r\n            if ($rootScope.selectDevice)\r\n                $rootScope.$emit('infoLocation', {\r\n                    id: $rootScope.selectDevice.id,\r\n                    direction: $rootScope.selectDevice.direction\r\n                });\r\n        };\r\n\r\n        $scope.getRange = function () {\r\n            return {\r\n                fromDate: moment($scope.range.fromDate).isValid() ? moment($scope.range.fromDate) : moment().add(config.DEFAULT_RANGE_DATE_DAY.from, 'd'),\r\n                toDate: moment($scope.range.toDate).isValid() ? moment($scope.range.toDate) : moment().add(config.DEFAULT_RANGE_DATE_DAY.to, 'd'),\r\n                fromTime: moment($scope.range.fromTime).isValid() ? moment($scope.range.fromTime) : moment({hour: config.DEFAULT_RANGE_TIME_HOUR.from}),\r\n                toTime: moment($scope.range.toTime).isValid() ? moment($scope.range.toTime) : moment({hour: config.DEFAULT_RANGE_TIME_HOUR.to}),\r\n                isTime: $scope.range.isTime ? true : false\r\n            };\r\n        };\r\n\r\n        $scope.renderGraph = function () {\r\n            var color = ['rgba(158, 158, 158, #alpha)', 'rgba(213, 0, 0, #alpha)', 'rgba(0, 123, 255, #alpha)', 'rgba(170, 0, 255, #alpha)',\r\n                'rgba(0, 200, 83, #alpha)', 'rgba(255, 214, 0, #alpha)', 'rgba(255, 109, 0, #alpha)',\r\n                '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)'];\r\n\r\n            var labels = jQuery.unique($rootScope.selectDevice.traffics.map(function (d) {\r\n                return $scope.range.isTime ? d.timeFrom : moment(d.date, 'YYYY-MM-DD').format('D.M.YYYY');\r\n            }));\r\n\r\n            var useVehiclesIds = jQuery.unique($rootScope.selectDevice.traffics.map(function (d) {\r\n                return d.typeVehicleId;\r\n            }));\r\n\r\n            var filterVehicles = jQuery.grep($scope.vehicles, function (n) {\r\n                return useVehiclesIds.indexOf(n.id) >= 0;\r\n            });\r\n\r\n            var datasetsNumberVehicles = [];\r\n            var datasetsAverageSpeed = [];\r\n\r\n            for (var i = 0, vehicle; vehicle = filterVehicles[i]; i++) {\r\n                var datasetNumberVehicles = {\r\n                    label: vehicle.name,\r\n                    backgroundColor: color[vehicle.id].replace(\"#alpha\", \"0.3\"),\r\n                    borderColor: color[vehicle.id].replace(\"#alpha\", \"1\"),\r\n                    borderWidth: 2,\r\n                    data: []\r\n                };\r\n\r\n                var datasetAverageSpeed = {\r\n                    data: [],\r\n                    borderWidth: 2,\r\n                    label: vehicle.name,\r\n                    fill: false,\r\n                    //fill: 'start',\r\n                    backgroundColor: color[vehicle.id].replace(\"#alpha\", \"0.3\"),\r\n                    borderColor: color[vehicle.id].replace(\"#alpha\", \"1\"),\r\n                    cubicInterpolationMode: 'monotone',\r\n                    pointRadius: 0\r\n                };\r\n\r\n                var l = 0;\r\n                for (var j = 0, traffic; traffic = $rootScope.selectDevice.traffics[j]; j++) {\r\n                    if (($scope.range.isTime && labels[l] !== traffic.timeFrom) || (!$scope.range.isTime && labels[l] !== moment(traffic.date, 'YYYY-MM-DD').format('D.M.YYYY'))) {\r\n                        l++;\r\n                        if (datasetNumberVehicles.data.length < l) {\r\n                            datasetNumberVehicles.data.push(0);\r\n                            datasetAverageSpeed.data.push(null);\r\n                        }\r\n                    }\r\n                    if (traffic.typeVehicleId === vehicle.id) {\r\n                        datasetNumberVehicles.data.push($scope.range.isTime ? traffic.numberVehicleAverage : traffic.numberVehicle);\r\n                        datasetAverageSpeed.data.push(traffic.speedAverage <= 0 ? null : traffic.speedAverage);\r\n                    }\r\n                }\r\n                datasetsNumberVehicles.push(datasetNumberVehicles);\r\n                datasetsAverageSpeed.push(datasetAverageSpeed);\r\n            }\r\n\r\n            $rootScope.$emit('renderGraphNumberVehicles', {\r\n                data: {\r\n                    labels: labels,\r\n                    datasets: datasetsNumberVehicles\r\n                }\r\n            });\r\n\r\n            $rootScope.$emit('renderGraphAverageSpeed', {\r\n                data: {\r\n                    labels: labels,\r\n                    datasets: datasetsAverageSpeed\r\n                }\r\n            });\r\n        };\r\n\r\n        $scope.infoClose = function () {\r\n            $rootScope.selectDevice = null;\r\n\r\n            var params = $location.search();\r\n            params.deviceId = null;\r\n            params.direction = null;\r\n            $location.search(params);\r\n\r\n            $rootScope.$emit('setDefaultMap', null);\r\n        };\r\n    }]);\r\n","angular.module('pvpk')\r\n    .controller('mainController', ['$rootScope', '$scope', '$location', '$window', function ($rootScope, $scope, $location, $window) {\r\n\r\n        this.$onInit = function () {\r\n            $scope.showLoadingScreen = true;\r\n        };\r\n\r\n        $window.onload = function () {\r\n            var params = $location.search();\r\n            if (params.deviceId) {\r\n                $rootScope.$emit('activeMarker', {id: params.deviceId});\r\n            }\r\n\r\n            $scope.$apply(function () {\r\n                $scope.showLoadingScreen = false;\r\n            });\r\n        };\r\n\r\n        $rootScope.$on('$locationChangeSuccess', function (event, newUrl, oldUrl) {\r\n            var params = $location.search();\r\n\r\n            if (newUrl !== oldUrl && $scope.historyUrl) {\r\n                if ($scope.historyUrl.q !== $scope.historyUrl.q || $scope.historyUrl.isDirection != params.isDirection) {\r\n                    $rootScope.$emit('setSearchFromUrl', null);\r\n                }\r\n\r\n                if ($scope.historyUrl.fromDate !== params.fromDate || $scope.historyUrl.toDate !== params.toDate ||\r\n                    $scope.historyUrl.fromTime !== params.fromTime || $scope.historyUrl.toTime !== params.toTime) {\r\n                    $rootScope.$emit('setRangeFromUrl', null);\r\n                    if (params.deviceId) {\r\n                        $rootScope.$emit('infoLocation', {id: params.deviceId, direction: params.direction});\r\n                    }\r\n                } else if (params.deviceId && ($scope.historyUrl.deviceId !== params.deviceId || $scope.historyUrl.direction !== params.direction)) {\r\n                    $rootScope.$emit('infoLocation', {id: params.deviceId, direction: params.direction});\r\n                    $rootScope.$emit('activeMarker', {id: params.deviceId});\r\n                } else if (!params.deviceId && $scope.historyUrl.deviceId) {\r\n                    $rootScope.selectDevice = null;\r\n                    $rootScope.$emit('setDefaultMap', null);\r\n                }\r\n            } else if (params.deviceId) {\r\n                $rootScope.$emit('infoLocation', {id: params.deviceId, direction: params.direction});\r\n            }\r\n\r\n            $scope.historyUrl = $location.search();\r\n        });\r\n\r\n        $rootScope.handleErrorResponse = function (response) {\r\n\r\n            var modalError = jQuery('#modalError');\r\n            switch (response.status) {\r\n                case 400:\r\n                    console.log('API ERROR 400');\r\n                    $scope.modalError = {\r\n                        title: 'Neplatný požadavek',\r\n                        body: 'Požadavek nemůže být vyřízen, poněvadž byl syntakticky nesprávně zapsán.',\r\n                        button: 'OK'\r\n                    };\r\n                    modalError.modal('show');\r\n                    break;\r\n                case 401:\r\n                    $scope.modalError = {\r\n                        title: 'Platnost webové aplikace vypršela',\r\n                        body: 'Pro obnovení platnosti stačí stisknout tlačítko <strong>Obnovit</strong>.',\r\n                        button: 'Obnovit',\r\n                        clickButton: $scope.reloadApp\r\n                    };\r\n                    modalError.modal({backdrop: 'static', keyboard: false});\r\n                    break;\r\n                case 404:\r\n                    console.log('API ERROR 404');\r\n                    $scope.modalError = {title: 'Nenalezen', body: 'Záznam nebyl nalezen.', button: 'OK'};\r\n                    modalError.modal('show');\r\n                    break;\r\n                case 500:\r\n                    console.log('API ERROR 500');\r\n                    $scope.modalError = {title: 'Chyba', body: 'Chyba serveru. Zopakujte akci později.', button: 'OK'};\r\n                    modalError.modal('show');\r\n                    break;\r\n                case -1:\r\n                    console.log('API NOT CONNECTED');\r\n                    $scope.modalError = {\r\n                        title: 'Připojení k internetu',\r\n                        body: 'Nejste připojeni k internetu. Zkontrolujte připojení.',\r\n                        button: 'OK'\r\n                    };\r\n                    modalError.modal('show');\r\n                    break;\r\n                default:\r\n                    console.log('API UNKNOWN ERROR');\r\n                    $scope.modalError = {title: 'Neočekávaná chyba', body: 'Nastala neočekávaná chyba.', button: 'OK'};\r\n                    modalError.modal('show');\r\n                    break;\r\n            }\r\n        };\r\n\r\n        $scope.reloadApp = function () {\r\n            $window.location.reload();\r\n        }\r\n    }]);","angular.module('pvpk')\r\n    .controller('mapController', ['$rootScope', '$scope', 'config', 'Device', function ($rootScope, $scope, config, Device) {\r\n\r\n        this.$onInit = function () {\r\n            $scope.markers = [];\r\n\r\n            $scope.map = new google.maps.Map(document.getElementById('map'), {\r\n                center: config.DEFAULT_POSITION,\r\n                zoom: config.DEFAULT_ZOOM,\r\n                minZoom: config.DEFAULT_ZOOM_MIN,\r\n                zoomControl: true,\r\n                mapTypeControl: false,\r\n                scaleControl: false,\r\n                streetViewControl: false,\r\n                rotateControl: false,\r\n                fullscreenControl: false,\r\n                mapTypeId: google.maps.MapTypeId.ROADMAP\r\n            });\r\n\r\n            Device.query({showDirection: 0}, function (data) {\r\n                for (var i = 0, lctn; lctn = data[i]; i++) {\r\n                    $scope.createMarker(lctn);\r\n                }\r\n            }, function (response) {\r\n                console.log('Error api all Devices');\r\n                $rootScope.handleErrorResponse(response);\r\n            });\r\n        };\r\n\r\n        $scope.createMarker = function (lctn) {\r\n            if (lctn.lat && lctn.lng) {\r\n                var marker = new google.maps.Marker({\r\n                    map: $scope.map,\r\n                    position: {lat: lctn.lat, lng: lctn.lng},\r\n                    title: lctn.name,\r\n                    infoWindow: new google.maps.InfoWindow({\r\n                        content: '<h6 class=\"mb-1\">' + lctn.name + '</h6>'\r\n                        + '<address>' + lctn.street + ', ' + lctn.town + '</address>'\r\n                    }),\r\n                    id: lctn.id\r\n                });\r\n\r\n                marker.addListener('click', function () {\r\n                    $scope.closeInfoWindows();\r\n                    marker.infoWindow.open($scope.map, marker);\r\n                    $rootScope.$emit('infoLocation', {id: lctn.id});\r\n                });\r\n\r\n                $scope.markers.push(marker);\r\n            }\r\n        };\r\n\r\n        $rootScope.$on('activeMarker', function (event, args) {\r\n            for (var i = 0, marker; marker = $scope.markers[i]; i++) {\r\n                if (marker.id && marker.id === args.id && marker.infoWindow) {\r\n                    $scope.map.setCenter(marker.getPosition());\r\n                    $scope.map.setZoom(12);\r\n                    marker.infoWindow.open($scope.map, marker);\r\n                } else {\r\n                    marker.infoWindow.close();\r\n                }\r\n            }\r\n        });\r\n\r\n        $rootScope.$on('setDefaultMap', function (event, args) {\r\n            $scope.map.setCenter(config.DEFAULT_POSITION);\r\n            $scope.map.setZoom(config.DEFAULT_ZOOM);\r\n            $scope.closeInfoWindows();\r\n        });\r\n\r\n        $scope.closeInfoWindows = function () {\r\n            for (var i = 0, marker; marker = $scope.markers[i]; i++) {\r\n                marker.infoWindow.close();\r\n            }\r\n        };\r\n    }]);","angular.module('pvpk')\r\n    .controller('searchController', ['$rootScope', '$scope', '$location', 'config', 'Device', function ($rootScope, $scope, $location, config, Device) {\r\n\r\n        this.$onInit = function () {\r\n            $scope.config = config;\r\n            $scope.locations = [];\r\n            $scope.showSearchLoading = false;\r\n\r\n            $rootScope.$emit('setSearchFromUrl', null);\r\n        };\r\n\r\n        $scope.searchLocations = function () {\r\n            var params = $location.search();\r\n            params.q = $scope.search.q;\r\n            params.isDirection = $scope.search.isDirection ? 1 : null;\r\n            $location.search(params);\r\n\r\n            if (!$scope.search.q || $scope.search.q.length <= 1) {\r\n                $scope.locations = [];\r\n                return;\r\n            }\r\n\r\n            $scope.showSearchLoading = true;\r\n\r\n            Device.query({\r\n                address: $scope.search.q,\r\n                showDirection: $scope.search.isDirection ? 1 : 0\r\n            }, function (data) {\r\n                $scope.locations = data;\r\n                $scope.showSearchLoading = false;\r\n            }, function (response) {\r\n                $scope.showSearchLoading = false;\r\n                console.log('Error api all Devices');\r\n                $rootScope.handleErrorResponse(response);\r\n            });\r\n        };\r\n\r\n        $rootScope.$on('setSearchFromUrl', function (event, args) {\r\n            var params = $location.search();\r\n            $scope.search = {\r\n                q: params.q,\r\n                isDirection: params.isDirection ? !!+params.isDirection : false\r\n            };\r\n            $scope.searchLocations();\r\n        });\r\n\r\n        $scope.selectDevice = function (id, direction) {\r\n            $rootScope.$emit('activeMarker', {id: id});\r\n            $rootScope.$emit('infoLocation', {id: id, direction: direction});\r\n        };\r\n\r\n    }]);","angular.module('pvpk')\r\n    .component('graphAverageSpeed', {\r\n        template: '<div><canvas id=\"graphAverageSpeed\" class=\"graphSize mb-5\"></canvas></div>',\r\n        controller: ['$rootScope', '$scope', function ($rootScope, $scope) {\r\n\r\n            $rootScope.$on('renderGraphAverageSpeed', function (event, args) {\r\n                var canvas = document.getElementById('graphAverageSpeed').getContext('2d');\r\n\r\n                if ($scope.graphLine)\r\n                    $scope.graphLine.destroy();\r\n\r\n                $scope.graphLine = new Chart(canvas, {\r\n                    type: 'line',\r\n                    data: args.data,\r\n                    options: {\r\n                        responsive: true,\r\n                        pointDot: false,\r\n                        legend: {\r\n                            position: 'bottom'\r\n                        },\r\n                        scales: {\r\n                            xAxes: [{\r\n                                ticks: {\r\n                                    autoSkip: true,\r\n                                    maxTicksLimit: 15\r\n                                }\r\n                            }],\r\n                            yAxes: [{\r\n                                scaleLabel: {\r\n                                    display: true,\r\n                                    labelString: 'km/h'\r\n                                },\r\n                                ticks: {\r\n                                    beginAtZero: true,\r\n                                    suggestedMax: 70\r\n                                }\r\n                            }]\r\n                        },\r\n                        tooltips: {\r\n                            mode: 'index',\r\n                            intersect: false,\r\n                            callbacks: {\r\n                                label: function (tooltipItems) {\r\n                                    return tooltipItems.yLabel + ' km/h';\r\n                                }\r\n                            }\r\n                        }\r\n                    }\r\n                });\r\n\r\n            });\r\n\r\n        }]\r\n    });","angular.module('pvpk')\r\n    .component('graphNumberVehicles', {\r\n        template: '<div><canvas id=\"graphNumberVehicles\" class=\"graphSize mb-5\"></canvas></div>',\r\n        controller: ['$rootScope', '$scope', function ($rootScope, $scope) {\r\n\r\n            $rootScope.$on('renderGraphNumberVehicles', function (event, args) {\r\n                var canvasGraphNumberVehicles = document.getElementById('graphNumberVehicles').getContext('2d');\r\n\r\n                if ($scope.graphNumberVehicles)\r\n                    $scope.graphNumberVehicles.destroy();\r\n\r\n                $scope.graphNumberVehicles = new Chart(canvasGraphNumberVehicles, {\r\n                    type: 'bar',\r\n                    data: args.data,\r\n                    options: {\r\n                        responsive: true,\r\n                        onResize: function (chart, size) {\r\n                            chart.options.legend.display = size.height > 240;\r\n                            chart.update();\r\n                        },\r\n                        legend: {\r\n                            position: 'bottom'\r\n                        },\r\n                        scales: {\r\n                            xAxes: [{\r\n                                stacked: true,\r\n                                ticks: {\r\n                                    autoSkip: true,\r\n                                    maxTicksLimit: 15\r\n                                }\r\n                            }],\r\n                            yAxes: [{\r\n                                scaleLabel: {\r\n                                    display: true,\r\n                                    labelString: \"počet vozidel\"\r\n                                },\r\n                                stacked: true\r\n                            }]\r\n                        },\r\n                        tooltips: {\r\n                            mode: 'index',\r\n                            intersect: false\r\n                        }\r\n                    }\r\n                });\r\n\r\n            });\r\n\r\n        }]\r\n    });","angular.module('pvpk')\r\n    .factory('Device', ['$resource', 'config', function ($resource, config) {\r\n        return $resource(config.API_URL + '/devices/:id', {id: '@id', period: '@period'}, {\r\n            'get': {\r\n                url: config.API_URL + '/devices/:id/:period',\r\n                method: 'GET',\r\n                headers: {\r\n                    'Content-Type': 'application/json',\r\n                    'Accept': 'application/json',\r\n                    'jwt': config.API_TOKEN\r\n                }\r\n            },\r\n            'query': {\r\n                url: config.API_URL + '/devices',\r\n                method: 'GET',\r\n                isArray: true,\r\n                headers: {\r\n                    'Content-Type': 'application/json',\r\n                    'Accept': 'application/json',\r\n                    'jwt': config.API_TOKEN\r\n                }\r\n            }\r\n        });\r\n    }]);","angular.module('pvpk')\r\n    .factory('Vehicle', ['$resource', 'config', function ($resource, config) {\r\n        return $resource(config.API_URL + '/vehicles', null, {\r\n            'query': {\r\n                url: config.API_URL + '/vehicles',\r\n                method: 'GET',\r\n                isArray: true,\r\n                headers: {\r\n                    'Content-Type': 'application/json',\r\n                    'Accept': 'application/json',\r\n                    'jwt': config.API_TOKEN\r\n                }\r\n            }\r\n        });\r\n    }]);"]}
frontend/app/app.config.js
1
angular.module('pvpk')
2
    .constant('config', {
3
        APP_NAME: 'PVPK',
4
        APP_VERSION: '1.3.0',
5
        API_URL: API_URL,
6
        API_TOKEN: API_TOKEN,
7
        DEFAULT_POSITION: {lat: 49.53, lng: 13.3},
8
        DEFAULT_ZOOM: 10,
9
        DEFAULT_ZOOM_MIN: 7,
10
        DEFAULT_RANGE_DATE_DAY: {from: -30, to: -1},
11
        DEFAULT_RANGE_TIME_HOUR: {from: 7, to: 16}
12
    });
frontend/app/app.module.js
1
angular.module('pvpk', ['ngResource', 'ngSanitize']);
frontend/app/controllers/infoController.js
1
angular.module('pvpk')
2
    .controller('infoController', ['$rootScope', '$scope', '$location', 'config', 'Device', 'Vehicle', function ($rootScope, $scope, $location, config, Device, Vehicle) {
3

  
4
        this.$onInit = function () {
5
            $rootScope.selectDevice = null;
6
            $scope.showInfoLoading = false;
7
            $scope.vehicles = [];
8
            $scope.urlExportCsv = null;
9

  
10
            Vehicle.query(null, function (data) {
11
                $scope.vehicles = data;
12
            }, function (response) {
13
                $rootScope.graphShow = false;
14
                console.log('Error api all Vehicles');
15
                $rootScope.handleErrorResponse(response);
16
            });
17

  
18
            $rootScope.$emit('setRangeFromUrl', null);
19
        };
20

  
21
        $rootScope.$on('setRangeFromUrl', function (event, args) {
22
            var params = $location.search();
23
            $scope.range = {
24
                fromDate: moment(params.fromDate, 'YYYY-MM-DD').isValid() ? moment(params.fromDate).toDate() : moment().add(config.DEFAULT_RANGE_DATE_DAY.from, 'd').toDate(),
25
                toDate: moment(params.toDate, 'YYYY-MM-DD').isValid() ? moment(params.toDate).toDate() : moment().add(config.DEFAULT_RANGE_DATE_DAY.to, 'd').toDate(),
26
                fromTime: moment(params.fromTime, 'HH:mm').isValid() ? moment(params.fromTime, 'HH:mm').toDate() : moment({hour: config.DEFAULT_RANGE_TIME_HOUR.from}).toDate(),
27
                toTime: moment(params.toTime, 'HH:mm').isValid() ? moment(params.toTime, 'HH:mm').toDate() : moment({hour: config.DEFAULT_RANGE_TIME_HOUR.to}).toDate(),
28
                isTime: params.isTime == 0 ? false : true
29
            };
30
        });
31

  
32
        $rootScope.$on('infoLocation', function (event, args) {
33
            $scope.showInfoLoading = true;
34

  
35
            var params = $location.search();
36
            params.deviceId = args.id;
37
            params.direction = args.direction;
38
            $location.search(params);
39

  
40
            var range = $scope.getRange();
41

  
42
            var query = {
43
                period: range.isTime ? 'time-period' : 'day-period',
44
                id: args.id,
45
                direction: args.direction,
46
                dateFrom: range.fromDate.format('YYYY-MM-DD'),
47
                dateTo: range.toDate.format('YYYY-MM-DD'),
48
                timeFrom: range.isTime ? range.fromTime.format('HH:mm') : null,
49
                timeTo: range.isTime ? range.toTime.format('HH:mm') : null
50
            };
51

  
52
            Device.get(query, function (data) {
53
                $rootScope.selectDevice = data;
54
                $scope.renderGraph();
55
                $scope.urlExportCsv = $scope.generateUrlExportCsv(query);
56

  
57
                $scope.showInfoLoading = false;
58
            }, function (response) {
59
                $rootScope.selectDevice = null;
60
                $scope.showInfoLoading = false;
61
                console.log('Error api get Devices');
62
                $rootScope.handleErrorResponse(response);
63
            });
64

  
65
        });
66

  
67
        $scope.generateUrlExportCsv = function (query) {
68
            var relativeUrl = '/devices/:id/:period/csv?'.replace(':id', query.id).replace(':period', query.period);
69
            delete query.id;
70
            delete query.period;
71

  
72
            var paramsUrl = jQuery.param(query);
73
            return config.API_URL + relativeUrl + paramsUrl;
74
        };
75

  
76
        $scope.changeRange = function () {
77
            if ($scope.range.fromDate >= $scope.range.toDate || ($scope.range.isTime && $scope.range.fromTime >= $scope.range.toTime)) {
78
                $rootScope.selectDevice.traffics = [];
79
                return;
80
            }
81

  
82
            var range = $scope.getRange();
83

  
84
            var params = $location.search();
85
            params.fromDate = range.fromDate.format('YYYY-MM-DD');
86
            params.toDate = range.toDate.format('YYYY-MM-DD');
87
            params.fromTime = range.isTime ? range.fromTime.format('HH:mm') : null;
88
            params.toTime = range.isTime ? range.toTime.format('HH:mm') : null;
89
            params.isTime = range.isTime ? null : 0;
90
            $location.search(params);
91

  
92
            if ($rootScope.selectDevice)
93
                $rootScope.$emit('infoLocation', {
94
                    id: $rootScope.selectDevice.id,
95
                    direction: $rootScope.selectDevice.direction
96
                });
97
        };
98

  
99
        $scope.getRange = function () {
100
            return {
101
                fromDate: moment($scope.range.fromDate).isValid() ? moment($scope.range.fromDate) : moment().add(config.DEFAULT_RANGE_DATE_DAY.from, 'd'),
102
                toDate: moment($scope.range.toDate).isValid() ? moment($scope.range.toDate) : moment().add(config.DEFAULT_RANGE_DATE_DAY.to, 'd'),
103
                fromTime: moment($scope.range.fromTime).isValid() ? moment($scope.range.fromTime) : moment({hour: config.DEFAULT_RANGE_TIME_HOUR.from}),
104
                toTime: moment($scope.range.toTime).isValid() ? moment($scope.range.toTime) : moment({hour: config.DEFAULT_RANGE_TIME_HOUR.to}),
105
                isTime: $scope.range.isTime ? true : false
106
            };
107
        };
108

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

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

  
118
            var useVehiclesIds = jQuery.unique($rootScope.selectDevice.traffics.map(function (d) {
119
                return d.typeVehicleId;
120
            }));
121

  
122
            var filterVehicles = jQuery.grep($scope.vehicles, function (n) {
123
                return useVehiclesIds.indexOf(n.id) >= 0;
124
            });
125

  
126
            var datasetsNumberVehicles = [];
127
            var datasetsAverageSpeed = [];
128

  
129
            for (var i = 0, vehicle; vehicle = filterVehicles[i]; i++) {
130
                var datasetNumberVehicles = {
131
                    label: vehicle.name,
132
                    backgroundColor: color[vehicle.id].replace("#alpha", "0.3"),
133
                    borderColor: color[vehicle.id].replace("#alpha", "1"),
134
                    borderWidth: 2,
135
                    data: []
136
                };
137

  
138
                var datasetAverageSpeed = {
139
                    data: [],
140
                    borderWidth: 2,
141
                    label: vehicle.name,
142
                    fill: false,
143
                    //fill: 'start',
144
                    backgroundColor: color[vehicle.id].replace("#alpha", "0.3"),
145
                    borderColor: color[vehicle.id].replace("#alpha", "1"),
146
                    cubicInterpolationMode: 'monotone',
147
                    pointRadius: 0
148
                };
149

  
150
                var l = 0;
151
                for (var j = 0, traffic; traffic = $rootScope.selectDevice.traffics[j]; j++) {
152
                    if (($scope.range.isTime && labels[l] !== traffic.timeFrom) || (!$scope.range.isTime && labels[l] !== moment(traffic.date, 'YYYY-MM-DD').format('D.M.YYYY'))) {
153
                        l++;
154
                        if (datasetNumberVehicles.data.length < l) {
155
                            datasetNumberVehicles.data.push(0);
156
                            datasetAverageSpeed.data.push(null);
157
                        }
158
                    }
159
                    if (traffic.typeVehicleId === vehicle.id) {
160
                        datasetNumberVehicles.data.push($scope.range.isTime ? traffic.numberVehicleAverage : traffic.numberVehicle);
161
                        datasetAverageSpeed.data.push(traffic.speedAverage <= 0 ? null : traffic.speedAverage);
162
                    }
163
                }
164
                datasetsNumberVehicles.push(datasetNumberVehicles);
165
                datasetsAverageSpeed.push(datasetAverageSpeed);
166
            }
167

  
168
            $rootScope.$emit('renderGraphNumberVehicles', {
169
                data: {
170
                    labels: labels,
171
                    datasets: datasetsNumberVehicles
172
                }
173
            });
174

  
175
            $rootScope.$emit('renderGraphAverageSpeed', {
176
                data: {
177
                    labels: labels,
178
                    datasets: datasetsAverageSpeed
179
                }
180
            });
181
        };
182

  
183
        $scope.infoClose = function () {
184
            $rootScope.selectDevice = null;
185

  
186
            var params = $location.search();
187
            params.deviceId = null;
188
            params.direction = null;
189
            $location.search(params);
190

  
191
            $rootScope.$emit('setDefaultMap', null);
192
        };
193
    }]);
frontend/app/controllers/mainController.js
1
angular.module('pvpk')
2
    .controller('mainController', ['$rootScope', '$scope', '$location', '$window', function ($rootScope, $scope, $location, $window) {
3

  
4
        this.$onInit = function () {
5
            $scope.showLoadingScreen = true;
6
        };
7

  
8
        $window.onload = function () {
9
            var params = $location.search();
10
            if (params.deviceId) {
11
                $rootScope.$emit('activeMarker', {id: params.deviceId});
12
            }
13

  
14
            $scope.$apply(function () {
15
                $scope.showLoadingScreen = false;
16
            });
17
        };
18

  
19
        $rootScope.$on('$locationChangeSuccess', function (event, newUrl, oldUrl) {
20
            var params = $location.search();
21

  
22
            if (newUrl !== oldUrl && $scope.historyUrl) {
23
                if ($scope.historyUrl.q !== $scope.historyUrl.q || $scope.historyUrl.isDirection != params.isDirection) {
24
                    $rootScope.$emit('setSearchFromUrl', null);
25
                }
26

  
27
                if ($scope.historyUrl.fromDate !== params.fromDate || $scope.historyUrl.toDate !== params.toDate ||
28
                    $scope.historyUrl.fromTime !== params.fromTime || $scope.historyUrl.toTime !== params.toTime) {
29
                    $rootScope.$emit('setRangeFromUrl', null);
30
                    if (params.deviceId) {
31
                        $rootScope.$emit('infoLocation', {id: params.deviceId, direction: params.direction});
32
                    }
33
                } else if (params.deviceId && ($scope.historyUrl.deviceId !== params.deviceId || $scope.historyUrl.direction !== params.direction)) {
34
                    $rootScope.$emit('infoLocation', {id: params.deviceId, direction: params.direction});
35
                    $rootScope.$emit('activeMarker', {id: params.deviceId});
36
                } else if (!params.deviceId && $scope.historyUrl.deviceId) {
37
                    $rootScope.selectDevice = null;
38
                    $rootScope.$emit('setDefaultMap', null);
39
                }
40
            } else if (params.deviceId) {
41
                $rootScope.$emit('infoLocation', {id: params.deviceId, direction: params.direction});
42
            }
43

  
44
            $scope.historyUrl = $location.search();
45
        });
46

  
47
        $rootScope.handleErrorResponse = function (response) {
48

  
49
            var modalError = jQuery('#modalError');
50
            switch (response.status) {
51
                case 400:
52
                    console.log('API ERROR 400');
53
                    $scope.modalError = {
54
                        title: 'Neplatný požadavek',
55
                        body: 'Požadavek nemůže být vyřízen, poněvadž byl syntakticky nesprávně zapsán.',
56
                        button: 'OK'
57
                    };
58
                    modalError.modal('show');
59
                    break;
60
                case 401:
61
                    $scope.modalError = {
62
                        title: 'Platnost webové aplikace vypršela',
63
                        body: 'Pro obnovení platnosti stačí stisknout tlačítko <strong>Obnovit</strong>.',
64
                        button: 'Obnovit',
65
                        clickButton: $scope.reloadApp
66
                    };
67
                    modalError.modal({backdrop: 'static', keyboard: false});
68
                    break;
69
                case 404:
70
                    console.log('API ERROR 404');
71
                    $scope.modalError = {title: 'Nenalezen', body: 'Záznam nebyl nalezen.', button: 'OK'};
72
                    modalError.modal('show');
73
                    break;
74
                case 500:
75
                    console.log('API ERROR 500');
76
                    $scope.modalError = {title: 'Chyba', body: 'Chyba serveru. Zopakujte akci později.', button: 'OK'};
77
                    modalError.modal('show');
78
                    break;
79
                case -1:
80
                    console.log('API NOT CONNECTED');
81
                    $scope.modalError = {
82
                        title: 'Připojení k internetu',
83
                        body: 'Nejste připojeni k internetu. Zkontrolujte připojení.',
84
                        button: 'OK'
85
                    };
86
                    modalError.modal('show');
87
                    break;
88
                default:
89
                    console.log('API UNKNOWN ERROR');
90
                    $scope.modalError = {title: 'Neočekávaná chyba', body: 'Nastala neočekávaná chyba.', button: 'OK'};
91
                    modalError.modal('show');
92
                    break;
93
            }
94
        };
95

  
96
        $scope.reloadApp = function () {
97
            $window.location.reload();
98
        }
99
    }]);
frontend/app/controllers/mapController.js
1
angular.module('pvpk')
2
    .controller('mapController', ['$rootScope', '$scope', 'config', 'Device', function ($rootScope, $scope, config, Device) {
3

  
4
        this.$onInit = function () {
5
            $scope.markers = [];
6

  
7
            $scope.map = new google.maps.Map(document.getElementById('map'), {
8
                center: config.DEFAULT_POSITION,
9
                zoom: config.DEFAULT_ZOOM,
10
                minZoom: config.DEFAULT_ZOOM_MIN,
11
                zoomControl: true,
12
                mapTypeControl: false,
13
                scaleControl: false,
14
                streetViewControl: false,
15
                rotateControl: false,
16
                fullscreenControl: false,
17
                mapTypeId: google.maps.MapTypeId.ROADMAP
18
            });
19

  
20
            Device.query({showDirection: 0}, function (data) {
21
                for (var i = 0, lctn; lctn = data[i]; i++) {
22
                    $scope.createMarker(lctn);
23
                }
24
            }, function (response) {
25
                console.log('Error api all Devices');
26
                $rootScope.handleErrorResponse(response);
27
            });
28
        };
29

  
30
        $scope.createMarker = function (lctn) {
31
            if (lctn.lat && lctn.lng) {
32
                var marker = new google.maps.Marker({
33
                    map: $scope.map,
34
                    position: {lat: lctn.lat, lng: lctn.lng},
35
                    title: lctn.name,
36
                    infoWindow: new google.maps.InfoWindow({
37
                        content: '<h6 class="mb-1">' + lctn.name + '</h6>'
38
                        + '<address>' + lctn.street + ', ' + lctn.town + '</address>'
39
                    }),
... Rozdílový soubor je zkrácen, protože jeho délka přesahuje max. limit.

Také k dispozici: Unified diff