fleetmap-reports 1.0.393 → 1.0.400
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +10 -5
- package/src/activity-report.js +26 -8
- package/src/index.test.js +342 -328
- package/src/refueling-report.js +149 -147
- package/src/speeding-report.js +112 -111
- package/src/tests/index.js +14 -16
- package/src/util/utils.js +151 -153
- package/src/zone-report.js +6 -5
package/src/util/utils.js
CHANGED
|
@@ -1,198 +1,196 @@
|
|
|
1
1
|
const axios = require('axios')
|
|
2
|
-
const turf = require('turf')
|
|
3
|
-
const {getUserPartner} = require(
|
|
4
|
-
const messages = require(
|
|
2
|
+
const turf = require('@turf/helpers')
|
|
3
|
+
const { getUserPartner } = require('fleetmap-partners')
|
|
4
|
+
const messages = require('../../lang')
|
|
5
|
+
const distance = require('@turf/distance')
|
|
5
6
|
|
|
6
7
|
exports.getTranslations = (userData) => {
|
|
7
|
-
|
|
8
|
-
|
|
8
|
+
const lang = userData.user.attributes.lang || (navigator && navigator.language)
|
|
9
|
+
return messages[lang] ? messages[lang] : messages['en-GB']
|
|
9
10
|
}
|
|
10
11
|
|
|
11
|
-
function convertMS(duration, withSeconds) {
|
|
12
|
+
function convertMS (duration, withSeconds) {
|
|
13
|
+
if (!duration || duration < 0) {
|
|
14
|
+
return '00:00'
|
|
15
|
+
}
|
|
12
16
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
let seconds = s % 60;
|
|
20
|
-
s = (s - seconds) / 60;
|
|
21
|
-
let minutes = s % 60;
|
|
22
|
-
let hours = (s - minutes) / 60;
|
|
17
|
+
const ms = duration % 1000
|
|
18
|
+
let s = (duration - ms) / 1000
|
|
19
|
+
let seconds = s % 60
|
|
20
|
+
s = (s - seconds) / 60
|
|
21
|
+
let minutes = s % 60
|
|
22
|
+
let hours = (s - minutes) / 60
|
|
23
23
|
|
|
24
|
+
hours = (hours < 10) ? '0' + hours : hours
|
|
25
|
+
minutes = (minutes < 10) ? '0' + minutes : minutes
|
|
26
|
+
seconds = (seconds < 10) ? '0' + seconds : seconds
|
|
24
27
|
|
|
25
|
-
|
|
26
|
-
minutes = (minutes < 10) ? "0" + minutes : minutes
|
|
27
|
-
seconds = (seconds < 10) ? "0" + seconds : seconds
|
|
28
|
-
|
|
29
|
-
return withSeconds ? hours + ":" + minutes + ":" + seconds : hours + ":" + minutes
|
|
28
|
+
return withSeconds ? hours + ':' + minutes + ':' + seconds : hours + ':' + minutes
|
|
30
29
|
}
|
|
31
30
|
|
|
32
|
-
function coordsDistance(lon1, lat1, lon2, lat2) {
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
function coordsDistance (lon1, lat1, lon2, lat2) {
|
|
32
|
+
const from = turf.point([lon1, lat1])
|
|
33
|
+
const to = turf.point([lon2, lat2])
|
|
35
34
|
|
|
36
|
-
|
|
35
|
+
return distance.default(from, to, {units: 'meters'})
|
|
37
36
|
}
|
|
38
37
|
|
|
39
|
-
function convertPositionToFeature(position) {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
38
|
+
function convertPositionToFeature (position) {
|
|
39
|
+
const point = turf.point([position.longitude, position.latitude])
|
|
40
|
+
point.properties.position = position
|
|
41
|
+
return point
|
|
43
42
|
}
|
|
44
43
|
|
|
45
|
-
function convertToFeature(geofence) {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}
|
|
57
|
-
const str = geofence.area.substring('POLYGON(('.length, geofence.area.length - 2)
|
|
58
|
-
const coord_list = str.split(',')
|
|
59
|
-
for (const i in coord_list) {
|
|
60
|
-
const coord = coord_list[i].trim().split(' ')
|
|
61
|
-
feature.geometry.coordinates[0].push([parseFloat(coord[1]), parseFloat(coord[0])])
|
|
62
|
-
}
|
|
63
|
-
return feature
|
|
44
|
+
function convertToFeature (geofence) {
|
|
45
|
+
if (geofence.area.startsWith('POLYGON')) {
|
|
46
|
+
const feature = {
|
|
47
|
+
type: 'Feature',
|
|
48
|
+
properties: {
|
|
49
|
+
geofence
|
|
50
|
+
},
|
|
51
|
+
geometry: {
|
|
52
|
+
type: 'Polygon',
|
|
53
|
+
coordinates: [[]]
|
|
54
|
+
}
|
|
64
55
|
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
const point = turf.point([parseFloat(coord[1]), parseFloat(coord[0])])
|
|
71
|
-
point.properties.geofence = geofence
|
|
72
|
-
point.properties.distance = coord_list[1].trim()
|
|
73
|
-
console.log(point)
|
|
74
|
-
return point
|
|
56
|
+
const str = geofence.area.substring('POLYGON(('.length, geofence.area.length - 2)
|
|
57
|
+
const coord_list = str.split(',')
|
|
58
|
+
for (const i in coord_list) {
|
|
59
|
+
const coord = coord_list[i].trim().split(' ')
|
|
60
|
+
feature.geometry.coordinates[0].push([parseFloat(coord[1]), parseFloat(coord[0])])
|
|
75
61
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
62
|
+
return feature
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (geofence.area.startsWith('CIRCLE')) {
|
|
66
|
+
const str = geofence.area.substring('CIRCLE ('.length, geofence.area.length - 1)
|
|
67
|
+
const coord_list = str.split(',')
|
|
68
|
+
const coord = coord_list[0].trim().split(' ')
|
|
69
|
+
const point = turf.point([parseFloat(coord[1]), parseFloat(coord[0])])
|
|
70
|
+
point.properties.geofence = geofence
|
|
71
|
+
point.properties.distance = coord_list[1].trim()
|
|
72
|
+
console.log(point)
|
|
73
|
+
return point
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (geofence.area.startsWith('LINESTRING')) {
|
|
77
|
+
const str = geofence.area.substring('LINESTRING ('.length, geofence.area.length - 1)
|
|
78
|
+
const coord_list = str.split(',')
|
|
79
|
+
const coordinates = coord_list.map(c => {
|
|
80
|
+
const coord = c.trim().split(' ')
|
|
81
|
+
return [parseFloat(coord[1]), parseFloat(coord[0])]
|
|
82
|
+
})
|
|
83
|
+
return {
|
|
84
|
+
type: 'Feature',
|
|
85
|
+
properties: {
|
|
86
|
+
geofence
|
|
87
|
+
},
|
|
88
|
+
geometry: {
|
|
89
|
+
type: 'LineString',
|
|
90
|
+
coordinates
|
|
91
|
+
}
|
|
94
92
|
}
|
|
93
|
+
}
|
|
95
94
|
}
|
|
96
95
|
|
|
97
|
-
function getDates(startDate, endDate) {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
96
|
+
function getDates (startDate, endDate) {
|
|
97
|
+
const dates = []
|
|
98
|
+
let currentDate = new Date(startDate.toISOString().split('T')[0] + ' 12:00:00.000 PM')
|
|
99
|
+
const addDays = function (days) {
|
|
100
|
+
const date = new Date(this.valueOf())
|
|
101
|
+
date.setDate(date.getDate() + days)
|
|
102
|
+
return date
|
|
103
|
+
}
|
|
104
|
+
while (currentDate <= endDate) {
|
|
105
|
+
dates.push(currentDate)
|
|
106
|
+
currentDate = addDays.call(currentDate, 1)
|
|
107
|
+
}
|
|
108
|
+
return dates
|
|
110
109
|
}
|
|
111
110
|
|
|
112
|
-
function getImage(url) {
|
|
113
|
-
|
|
111
|
+
function getImage (url) {
|
|
112
|
+
return axios.get(url, { responseType: 'arraybuffer' }).then(d => d.data)
|
|
114
113
|
}
|
|
115
114
|
|
|
116
|
-
async function getImageBase64(url) {
|
|
117
|
-
|
|
118
|
-
|
|
115
|
+
async function getImageBase64 (url) {
|
|
116
|
+
const response = await getImage(url)
|
|
117
|
+
return Buffer.from(response, 'binary').toString('base64')
|
|
119
118
|
}
|
|
120
119
|
|
|
121
|
-
function getLogoUrl(hostname) {
|
|
122
|
-
|
|
123
|
-
|
|
120
|
+
function getLogoUrl (hostname) {
|
|
121
|
+
const path = `/img/logos/${hostname}.png`
|
|
122
|
+
return window ? path : `https://${hostname}${path}`
|
|
124
123
|
}
|
|
125
124
|
|
|
126
|
-
async function getImgFromUrl(hostname) {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
125
|
+
async function getImgFromUrl (hostname) {
|
|
126
|
+
const url = getLogoUrl(hostname)
|
|
127
|
+
try {
|
|
128
|
+
const img = new Image()
|
|
129
|
+
img.src = url
|
|
130
|
+
return img
|
|
131
|
+
} catch (e) {
|
|
132
|
+
return await getImageBase64(url)
|
|
133
|
+
}
|
|
135
134
|
}
|
|
136
135
|
|
|
137
|
-
function isClientSide() { return (typeof window !==
|
|
136
|
+
function isClientSide () { return (typeof window !== 'undefined') }
|
|
138
137
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
}
|
|
138
|
+
function convertToLocaleString (value, lang, timezone) {
|
|
139
|
+
if (isClientSide()) {
|
|
140
|
+
return new Date(value).toLocaleString()
|
|
141
|
+
} else {
|
|
142
|
+
return new Date(value).toLocaleString(lang, {
|
|
143
|
+
timeZone: timezone,
|
|
144
|
+
hour12: false
|
|
145
|
+
})
|
|
146
|
+
}
|
|
149
147
|
}
|
|
150
148
|
|
|
151
|
-
function convertToLocaleDateString(value, lang, timezone){
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
149
|
+
function convertToLocaleDateString (value, lang, timezone) {
|
|
150
|
+
if (isClientSide()) {
|
|
151
|
+
return new Date(value).toLocaleDateString()
|
|
152
|
+
} else {
|
|
153
|
+
return new Date(value).toLocaleDateString(lang, {
|
|
154
|
+
timeZone: timezone,
|
|
155
|
+
hour12: false
|
|
156
|
+
})
|
|
157
|
+
}
|
|
160
158
|
}
|
|
161
159
|
|
|
162
|
-
function convertToLocaleTimeString(value, lang, timezone){
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
160
|
+
function convertToLocaleTimeString (value, lang, timezone) {
|
|
161
|
+
if (isClientSide()) {
|
|
162
|
+
return new Date(value).toLocaleTimeString()
|
|
163
|
+
} else {
|
|
164
|
+
return new Date(value).toLocaleTimeString(lang, {
|
|
165
|
+
timeZone: timezone,
|
|
166
|
+
hour12: false
|
|
167
|
+
})
|
|
168
|
+
}
|
|
171
169
|
}
|
|
172
170
|
|
|
173
|
-
function getTimezoneOffset(timezone){
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
171
|
+
function getTimezoneOffset (timezone) {
|
|
172
|
+
if (isClientSide()) {
|
|
173
|
+
return new Date().getTimezoneOffset()
|
|
174
|
+
} else {
|
|
175
|
+
const utcDate = new Date(new Date().toLocaleString('en-US', { timeZone: 'UTC' }))
|
|
176
|
+
const tzDate = new Date(new Date().toLocaleString('en-US', { timeZone: timezone }))
|
|
177
|
+
return (utcDate.getTime() - tzDate.getTime()) / 6e4
|
|
178
|
+
}
|
|
181
179
|
}
|
|
182
180
|
|
|
183
|
-
function convertFromUTC(value, timezone) {
|
|
184
|
-
|
|
181
|
+
function convertFromUTC (value, timezone) {
|
|
182
|
+
const offset = getTimezoneOffset(timezone)
|
|
185
183
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
184
|
+
const valueDate = new Date(value)
|
|
185
|
+
valueDate.setTime(valueDate.getTime() - (offset * 60 * 1000))
|
|
186
|
+
return valueDate
|
|
189
187
|
}
|
|
190
188
|
|
|
191
|
-
function weekDaySelected(date, weekDays){
|
|
192
|
-
|
|
189
|
+
function weekDaySelected (date, weekDays) {
|
|
190
|
+
return (date.getDay() === 0 && weekDays.sunday) ||
|
|
193
191
|
(date.getDay() === 1 && weekDays.monday) ||
|
|
194
192
|
(date.getDay() === 2 && weekDays.tuesday) ||
|
|
195
|
-
(date.getDay() === 3 && weekDays.wednesday)
|
|
193
|
+
(date.getDay() === 3 && weekDays.wednesday) ||
|
|
196
194
|
(date.getDay() === 4 && weekDays.thursday) ||
|
|
197
195
|
(date.getDay() === 5 && weekDays.friday) ||
|
|
198
196
|
(date.getDay() === 6 && weekDays.saturday)
|
|
@@ -210,8 +208,8 @@ exports.getTimezoneOffset = getTimezoneOffset
|
|
|
210
208
|
exports.convertFromUTC = convertFromUTC
|
|
211
209
|
exports.weekDaySelected = weekDaySelected
|
|
212
210
|
exports.getLogo = (user) => {
|
|
213
|
-
|
|
214
|
-
|
|
211
|
+
const host = window ? window.location.hostname : getUserPartner(user).host
|
|
212
|
+
return getImage(getLogoUrl(host))
|
|
215
213
|
}
|
|
216
214
|
exports.convertToFeature = convertToFeature
|
|
217
215
|
exports.convertPositionToFeature = convertPositionToFeature
|
package/src/zone-report.js
CHANGED
|
@@ -8,8 +8,9 @@ const {getStyle} = require("./reportStyle")
|
|
|
8
8
|
const {getUserPartner} = require("fleetmap-partners")
|
|
9
9
|
const {devicesToProcess} = require("./util/device")
|
|
10
10
|
const traccarHelper = require("./util/traccar")
|
|
11
|
-
const
|
|
12
|
-
const
|
|
11
|
+
const pointToLineDistance = require("@turf/point-to-line-distance")
|
|
12
|
+
const pointOnFeature = require("@turf/point-on-feature")
|
|
13
|
+
const distance = require("@turf/distance")
|
|
13
14
|
|
|
14
15
|
const fileName = 'ZoneReport'
|
|
15
16
|
|
|
@@ -75,7 +76,7 @@ async function createZoneReport(from, to, userData, traccar) {
|
|
|
75
76
|
return reportData
|
|
76
77
|
}
|
|
77
78
|
|
|
78
|
-
async function processDevices(from, to, devices, drivers, geofences, data
|
|
79
|
+
async function processDevices(from, to, devices, drivers, geofences, data) {
|
|
79
80
|
const devicesResult = []
|
|
80
81
|
|
|
81
82
|
for (const d of devices) {
|
|
@@ -160,7 +161,7 @@ function getInAndOutEvents(devices, route, userData) {
|
|
|
160
161
|
routePoints.forEach(p => {
|
|
161
162
|
geofencesFeatures.forEach(g => {
|
|
162
163
|
if(g.geometry.type === 'Polygon') {
|
|
163
|
-
if (
|
|
164
|
+
if (pointOnFeature(p, g)) {
|
|
164
165
|
if (!entryMap.includes(g)) {
|
|
165
166
|
events.push(createEvent('geofenceEnter',d.id,p,g))
|
|
166
167
|
entryMap.push(g)
|
|
@@ -174,7 +175,7 @@ function getInAndOutEvents(devices, route, userData) {
|
|
|
174
175
|
}
|
|
175
176
|
}
|
|
176
177
|
if(g.geometry.type === 'Point') {
|
|
177
|
-
if (
|
|
178
|
+
if (distance(p, g, {units: 'meters'}) < g.properties.distance) {
|
|
178
179
|
if (!entryMap.includes(g)) {
|
|
179
180
|
events.push(createEvent('geofenceEnter',d.id,p,g))
|
|
180
181
|
entryMap.push(g)
|