Files
frontend/static/main.js
2019-03-01 22:26:10 +01:00

219 lines
7.7 KiB
JavaScript

(() => {
const { LMap, LTileLayer, LMarker, LCircleMarker, LCircle, LPolyline } = Vue2Leaflet;
const config = deepmerge(window.defaultConfig, window.config);
new Vue({
el: '#app',
components: { vuejsDatepicker, LMap, LTileLayer, LMarker, LCircleMarker, LPolyline, LCircle },
data: {
users: [],
devices: {},
lastLocations: [],
locationHistory: {},
showLastLocations: true,
showLocationHistoryPoints: false,
showLocationHistoryLine: false,
showLocationHeatmap: false,
selectedUser: '',
selectedDevice: '',
startDate: config.startDate,
endDate: config.endDate,
showDownloadModal: false,
showInformationModal: false,
map: {
center: config.map.center,
zoom: config.map.zoom,
maxNativeZoom: config.map.maxNativeZoom,
maxZoom: config.map.maxZoom,
url: config.map.url,
attribution: config.map.attribution,
polyline: {
color: config.accentColor,
fillColor: 'transparent',
},
circle: {
color: config.accentColor,
fillColor: config.accentColor,
fillOpacity: 0.2,
},
circleMarker: {
radius: 4,
color: config.accentColor,
fillColor: '#fff',
fillOpacity: 1,
},
heatmap: {
max: config.map.heatmap.max,
radius: config.map.heatmap.radius,
blur: config.map.heatmap.radius,
gradient: config.map.heatmap.gradient,
},
},
information: {
ownTracks: {
version: '',
documentationUrl: 'https://owntracks.org/booklet/',
sourceCodeUrl: 'https://github.com/owntracks/recorder',
twitterUrl: 'https://twitter.com/OwnTracks',
},
ownTracksUi: {
sourceCodeUrl: 'https://github.com/linusg/owntracks-ui',
},
}
},
watch: {
selectedUser: async function () {
this.selectedDevice = '';
this.lastLocations = await this.getLastLocations();
this.locationHistory = await this.getLocationHistory();
},
selectedDevice: async function () {
this.lastLocations = await this.getLastLocations();
this.locationHistory = await this.getLocationHistory();
},
startDate: async function () {
this.locationHistory = await this.getLocationHistory();
},
endDate: async function () {
this.locationHistory = await this.getLocationHistory();
},
},
computed: {
locationHistoryLatLngs() {
const latLngs = [];
Object.keys(this.locationHistory).forEach((user) => {
Object.keys(this.locationHistory[user]).forEach((device) => {
this.locationHistory[user][device].forEach((l) => {
latLngs.push(L.latLng(l.lat, l.lon));
});
});
});
return latLngs;
},
startDateDisabledDates() {
return {
customPredictor: (date) => (date > this.endDate) || (date > new Date())
};
},
endDateDisabledDates() {
return {
customPredictor: (date) => (date < this.startDate) || (date > new Date())
};
},
},
methods: {
init: async function () {
const root = document.documentElement;
root.style.setProperty('--color-accent', config.accentColor);
this.users = await this.getUsers();
this.devices = await this.getDevices();
this.lastLocations = await this.getLastLocations();
this.locationHistory = await this.getLocationHistory();
this.centerView();
await this.connectWebsocket();
this.information.ownTracks.version = await this.getVersion();
},
connectWebsocket: async function () {
const wsUrl = `${document.location.protocol.replace('http', 'ws')}//${document.location.host}/ws/last`;
const ws = new WebSocket(wsUrl);
console.log(`[WS] Connecting to ${wsUrl}...`);
ws.onopen = (e) => {
console.log('[WS] Connected');
ws.send('LAST');
};
ws.onclose = () => {
console.log('[WS] Disconnected. Reconnecting in one second...')
setTimeout(this.connectWebsocket, 1000);
};
ws.onmessage = async (msg) => {
if (msg.data) {
try {
const data = JSON.parse(msg.data);
if (data._type === 'location') {
console.log('[WS] Location update received');
this.lastLocations = await this.getLastLocations();
this.locationHistory = await this.getLocationHistory();
}
} catch (err) {}
} else {
console.log('[WS] Ping');
}
};
},
getVersion: async function () {
const response = await fetch('/api/0/version');
const json = await response.json();
const version = json.version;
return version;
},
getUsers: async function () {
const response = await fetch('/api/0/list');
const json = await response.json();
const users = json.results;
return users;
},
getDevices: async function () {
const devices = {};
await Promise.all(this.users.map(async (user) => {
const response = await fetch(`/api/0/list?user=${user}`);
const json = await response.json();
const userDevices = json.results;
devices[user] = userDevices;
}));
return devices;
},
getLastLocations: async function () {
let url = '/api/0/last';
if (this.selectedUser !== '') {
url += `?&user=${this.selectedUser}`;
if (this.selectedDevice !== '') {
url += `&device=${this.selectedDevice}`;
}
}
const response = await fetch(url);
const json = await response.json();
return json;
},
getLocationHistory: async function () {
let users;
let devices;
if (this.selectedUser === '') {
users = this.users;
devices = { ...this.devices };
} else {
users = [this.selectedUser];
if (this.selectedDevice === '') {
devices = { [this.selectedUser]: this.devices[this.selectedUser] };
} else {
devices = { [this.selectedUser]: [this.selectedDevice] };
}
}
const locations = {};
await Promise.all(users.map(async (user) => {
locations[user] = {};
await Promise.all(devices[user].map(async (device) => {
const startDateString = `${this.startDate.toISOString().split('T')[0]}T00:00:00`;
const endDateString = `${this.endDate.toISOString().split('T')[0]}T23:59:59`;
const url = `/api/0/locations?from=${startDateString}&to=${endDateString}&format=json&user=${user}&device=${device}`;
const response = await fetch(url);
const json = await response.json();
const userDeviceLocations = json.data;
locations[user][device] = userDeviceLocations;
}));
}));
return locations;
},
centerView() {
if ((this.showLocationHistoryPoints || this.showLocationHistoryLine || this.showLocationHeatmap) && this.locationHistoryLatLngs.length > 0) {
this.$refs.map.mapObject.fitBounds(new L.LatLngBounds(this.locationHistoryLatLngs));
} else if (this.showLastLocations && this.lastLocations.length > 0) {
const locations = this.lastLocations.map((l) => L.latLng(l.lat, l.lon));
this.$refs.map.mapObject.fitBounds(new L.LatLngBounds(locations), {maxZoom: this.map.maxNativeZoom});
}
},
},
mounted() {
this.init();
},
});
})();