Revize b88dd6bb
Přidáno uživatelem Jan Kohlíček před téměř 7 roky(ů)
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 |
}), |
Také k dispozici: Unified diff
refs #6949: rozdělení app.js do více souborů, grafy mají vlastní directive, gulp rozšířen o build-js