mirror of
https://github.com/owntracks/frontend.git
synced 2026-02-25 21:53:49 +00:00
Compare commits
6 Commits
v2.0.0-bet
...
v2.0.0-bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bc3670df99 | ||
|
|
95613753a9 | ||
|
|
cfa3052a0a | ||
|
|
0bd84f4de5 | ||
|
|
85e51643bf | ||
|
|
6cbdf30580 |
@@ -7,6 +7,12 @@ module.exports = {
|
||||
rules: {
|
||||
"no-console": process.env.NODE_ENV === "production" ? "error" : "warn",
|
||||
"no-debugger": process.env.NODE_ENV === "production" ? "error" : "warn",
|
||||
"max-len": [
|
||||
"error",
|
||||
{
|
||||
ignoreUrls: true,
|
||||
},
|
||||
],
|
||||
"prettier/prettier": [
|
||||
"error",
|
||||
{
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# Changelog
|
||||
|
||||
## 2.0.0-beta.8 (2020-01-26)
|
||||
|
||||
- Add friendly device name and face images to location history popups
|
||||
- Add missing `alt`/`title` to device face image
|
||||
- Fix all JSDoc `@return` directives to `@returns`
|
||||
- Use computed prop for device name in location popup
|
||||
- Enable ESLint `max-len` rule
|
||||
|
||||
## 2.0.0-beta.7 (2020-01-24)
|
||||
|
||||
This release doesn't really affect end-users but greatly improves the development experience.
|
||||
|
||||
@@ -6,7 +6,7 @@ COPY . ./
|
||||
RUN yarn build
|
||||
|
||||
FROM nginx:1.17-alpine
|
||||
LABEL version="2.0.0-beta.7"
|
||||
LABEL version="2.0.0-beta.8"
|
||||
LABEL description="OwnTracks UI"
|
||||
LABEL maintainer="Linus Groh <mail@linusgroh.de>"
|
||||
ENV LISTEN_PORT=80 \
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "owntracks-ui",
|
||||
"version": "2.0.0-beta.7",
|
||||
"version": "2.0.0-beta.8",
|
||||
"author": {
|
||||
"name": "Linus Groh",
|
||||
"email": "mail@linusgroh.de"
|
||||
|
||||
22
src/api.js
22
src/api.js
@@ -18,7 +18,7 @@ import { getApiUrl } from "@/util";
|
||||
*
|
||||
* @param {String} path API resource path
|
||||
* @param {QueryParams} [params] Query parameters
|
||||
* @return {Promise} Promise returned by the fetch function
|
||||
* @returns {Promise} Promise returned by the fetch function
|
||||
*/
|
||||
const fetchApi = (path, params = {}) => {
|
||||
const url = getApiUrl(path);
|
||||
@@ -30,7 +30,7 @@ const fetchApi = (path, params = {}) => {
|
||||
/**
|
||||
* Get the recorder's version.
|
||||
*
|
||||
* @return {String} Version
|
||||
* @returns {String} Version
|
||||
*/
|
||||
export const getVersion = async () => {
|
||||
const response = await fetchApi("/api/0/version");
|
||||
@@ -42,7 +42,7 @@ export const getVersion = async () => {
|
||||
/**
|
||||
* Get all users.
|
||||
*
|
||||
* @return {Array.<User>} Array of usernames
|
||||
* @returns {Array.<User>} Array of usernames
|
||||
*/
|
||||
export const getUsers = async () => {
|
||||
const response = await fetchApi("/api/0/list");
|
||||
@@ -55,7 +55,8 @@ export const getUsers = async () => {
|
||||
* Get all devices for the provided users.
|
||||
*
|
||||
* @param {Array.<User>} users Array of usernames
|
||||
* @return {Object.<User, Array.<Device>>} Object mapping each username to an array of device names
|
||||
* @returns {Object.<User, Array.<Device>>}
|
||||
* Object mapping each username to an array of device names
|
||||
*/
|
||||
export const getDevices = async users => {
|
||||
const devices = {};
|
||||
@@ -75,7 +76,7 @@ export const getDevices = async users => {
|
||||
*
|
||||
* @param {User} [user] Get last locations of all devices from this user
|
||||
* @param {Device} [device] Get last location of specific device
|
||||
* @return {Array.<LastLocation>} Array of last location objects
|
||||
* @returns {Array.<LastLocation>} Array of last location objects
|
||||
*/
|
||||
export const getLastLocations = async (user, device) => {
|
||||
const params = {};
|
||||
@@ -97,7 +98,7 @@ export const getLastLocations = async (user, device) => {
|
||||
* @param {Device} device Device name
|
||||
* @param {String} start Start date and time in UTC
|
||||
* @param {String} end End date and time in UTC
|
||||
* @return {LocationHistory} Array of location history objects
|
||||
* @returns {LocationHistory} Array of location history objects
|
||||
*/
|
||||
export const getUserDeviceLocationHistory = async (
|
||||
user,
|
||||
@@ -119,10 +120,12 @@ export const getUserDeviceLocationHistory = async (
|
||||
/**
|
||||
* Get the location history of multiple devices.
|
||||
*
|
||||
* @param {Object.<User, Array.<Device>>} devices Devices of which the history should be fetched
|
||||
* @param {Object.<User, Array.<Device>>} devices
|
||||
* Devices of which the history should be fetched
|
||||
* @param {String} start Start date and time in UTC
|
||||
* @param {String} end End date and time in UTC
|
||||
* @return {Object.<User, Object.<Device, LocationHistory>>} Array of location history objects
|
||||
* @returns {Object.<User, Object.<Device, LocationHistory>>}
|
||||
* Array of location history objects
|
||||
*/
|
||||
export const getLocationHistory = async (devices, start, end) => {
|
||||
const locationHistory = {};
|
||||
@@ -145,7 +148,8 @@ export const getLocationHistory = async (devices, start, end) => {
|
||||
};
|
||||
|
||||
/**
|
||||
* Connect to the WebSocket API, reconnect when necessary and handle received messages.
|
||||
* Connect to the WebSocket API, reconnect when necessary and handle received
|
||||
* messages.
|
||||
*
|
||||
* @param {webSocketLocationCallback} [callback] Callback for location messages
|
||||
*/
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
<template>
|
||||
<LPopup>
|
||||
<div v-if="name" class="device">{{ name }}</div>
|
||||
<div v-else class="device">{{ user }}/{{ device }}</div>
|
||||
<div class="device">{{ deviceName }}</div>
|
||||
<div class="wrapper">
|
||||
<img v-if="face" :src="faceImageDataURI" alt="" />
|
||||
<img
|
||||
v-if="face"
|
||||
:src="faceImageDataURI"
|
||||
:alt="$t('Image of {deviceName}', { deviceName })"
|
||||
:title="$t('Image of {deviceName}', { deviceName })"
|
||||
/>
|
||||
<ul class="info-list">
|
||||
<li :title="$t('Timestamp')">
|
||||
<ClockIcon size="1x" aria-hidden="true" role="img" />
|
||||
@@ -122,13 +126,23 @@ export default {
|
||||
},
|
||||
computed: {
|
||||
/**
|
||||
* Return the face image as a data URI string which can be used for an image's src attribute
|
||||
* Return the face image as a data URI string which can be used for an
|
||||
* image's src attribute.
|
||||
*
|
||||
* @return {String} base64-encoded face image data URI
|
||||
* @returns {String} base64-encoded face image data URI
|
||||
*/
|
||||
faceImageDataURI() {
|
||||
return `data:image/png;base64,${this.face}`;
|
||||
},
|
||||
/**
|
||||
* Return the device name for displaying with <user identifier>/<device
|
||||
* identifier> as fallback.
|
||||
*
|
||||
* @returns {String} device name for displaying
|
||||
*/
|
||||
deviceName() {
|
||||
return this.name ? this.name : `${this.user}/${this.device}`;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
"OwnTracks documentation": "OwnTracks Dokumentation",
|
||||
"OwnTracks on Twitter": "OwnTracks auf Twitter",
|
||||
"Loading data, please wait...": "Daten werden geladen, bitte warten...",
|
||||
"Image of {deviceName}": "Bild von {deviceName}",
|
||||
"Timestamp": "Zeitstempel",
|
||||
"Location": "Standort",
|
||||
"Address": "Adresse",
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
"OwnTracks documentation": "OwnTracks documentation",
|
||||
"OwnTracks on Twitter": "OwnTracks on Twitter",
|
||||
"Loading data, please wait...": "Loading data, please wait...",
|
||||
"Image of {deviceName}": "Image of {deviceName}",
|
||||
"Timestamp": "Timestamp",
|
||||
"Location": "Location",
|
||||
"Address": "Address",
|
||||
|
||||
@@ -12,8 +12,9 @@ import { distanceBetweenCoordinates } from "@/util";
|
||||
* array of all coordinates.
|
||||
*
|
||||
* @param {State} state
|
||||
* @param {MultiLocationHistory} state.locationHistory Location history of selected users and devices
|
||||
* @return {Array.<L.LatLng>} All coordinates
|
||||
* @param {MultiLocationHistory} state.locationHistory
|
||||
* Location history of selected users and devices
|
||||
* @returns {Array.<L.LatLng>} All coordinates
|
||||
*/
|
||||
const locationHistoryLatLngs = state => {
|
||||
const latLngs = [];
|
||||
@@ -33,8 +34,9 @@ const locationHistoryLatLngs = state => {
|
||||
* coordinates does not exceed `config.map.maxPointDistance`.
|
||||
*
|
||||
* @param {State} state
|
||||
* @param {MultiLocationHistory} state.locationHistory Location history of selected users and devices
|
||||
* @return {Array.<Array.<L.LatLng>>} Groups of coherent coordinates
|
||||
* @param {MultiLocationHistory} state.locationHistory
|
||||
* Location history of selected users and devices
|
||||
* @returns {Array.<Array.<L.LatLng>>} Groups of coherent coordinates
|
||||
*/
|
||||
const locationHistoryLatLngGroups = state => {
|
||||
const groups = [];
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
/* eslint max-len: 0 */
|
||||
|
||||
/**
|
||||
* A coordinate with latitude and longitude.
|
||||
*
|
||||
|
||||
@@ -10,7 +10,7 @@ import { DATE_TIME_FORMAT, EARTH_RADIUS_IN_KM } from "@/constants";
|
||||
* base URL configuration into account.
|
||||
*
|
||||
* @param {String} path Path to the API resource
|
||||
* @return {URL} Final API URL
|
||||
* @returns {URL} Final API URL
|
||||
*/
|
||||
export const getApiUrl = path => {
|
||||
const normalizedBaseUrl = config.api.baseUrl.endsWith("/")
|
||||
@@ -24,7 +24,7 @@ export const getApiUrl = path => {
|
||||
* Check if the given string is an ISO 8601 YYYY-MM-DDTHH:MM:SS datetime.
|
||||
*
|
||||
* @param {String} s Input value to be tested
|
||||
* @return {Boolean} Whether the input matches the expected format
|
||||
* @returns {Boolean} Whether the input matches the expected format
|
||||
*/
|
||||
export const isIsoDateTime = s => moment(s, DATE_TIME_FORMAT, true).isValid();
|
||||
|
||||
@@ -32,7 +32,7 @@ export const isIsoDateTime = s => moment(s, DATE_TIME_FORMAT, true).isValid();
|
||||
* Convert degrees to radians.
|
||||
*
|
||||
* @param {Number} degrees Angle in degrees
|
||||
* @return {Number} Angle in radians
|
||||
* @returns {Number} Angle in radians
|
||||
*/
|
||||
export const degreesToRadians = degrees => (degrees * Math.PI) / 180;
|
||||
|
||||
@@ -44,7 +44,7 @@ export const degreesToRadians = degrees => (degrees * Math.PI) / 180;
|
||||
*
|
||||
* @param {Coordinate} c1 First coordinate
|
||||
* @param {Coordinate} c2 Second coordinate
|
||||
* @return {Number} Distance in meters
|
||||
* @returns {Number} Distance in meters
|
||||
*/
|
||||
export const distanceBetweenCoordinates = (c1, c2) => {
|
||||
const r = EARTH_RADIUS_IN_KM * 1000;
|
||||
|
||||
@@ -66,7 +66,11 @@
|
||||
<template v-for="(userDevices, user) in locationHistory">
|
||||
<template v-for="(deviceLocations, device) in userDevices">
|
||||
<LCircleMarker
|
||||
v-for="(l, n) in deviceLocations"
|
||||
v-for="(l, n) in deviceLocationsWithNameAndFace(
|
||||
user,
|
||||
device,
|
||||
deviceLocations
|
||||
)"
|
||||
:key="`${user}-${device}-${n}`"
|
||||
:lat-lng="[l.lat, l.lon]"
|
||||
v-bind="circleMarker"
|
||||
@@ -74,6 +78,8 @@
|
||||
<LDeviceLocationPopup
|
||||
:user="user"
|
||||
:device="device"
|
||||
:name="l.name"
|
||||
:face="l.face"
|
||||
:timestamp="l.tst"
|
||||
:lat="l.lat"
|
||||
:lon="l.lon"
|
||||
@@ -202,6 +208,29 @@ export default {
|
||||
});
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Find a the last location object for a user/device combination from the
|
||||
* local cache and backfill name and face attributes to each item from the
|
||||
* passed array of location objects.
|
||||
*
|
||||
* @param {User} user Username
|
||||
* @param {Device} device Device name
|
||||
* @param {LocationHistory} deviceLocations Device name
|
||||
* @returns {LocationHistory} Updated location history
|
||||
*/
|
||||
deviceLocationsWithNameAndFace(user, device, deviceLocations) {
|
||||
const lastLocation = this.lastLocations.find(
|
||||
l => l.username === user && l.device === device
|
||||
);
|
||||
if (!lastLocation) {
|
||||
return deviceLocations;
|
||||
}
|
||||
return deviceLocations.map(l => ({
|
||||
...l,
|
||||
name: lastLocation.name,
|
||||
face: lastLocation.face,
|
||||
}));
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user