Support filtering points by deviceId on the UI.
Also, display the broadcasting device when clicking on a point on the map.
This commit is contained in:
parent
70ba053016
commit
87f1da7688
5 changed files with 66 additions and 4 deletions
frontend/src
|
@ -28,6 +28,7 @@
|
|||
</div>
|
||||
|
||||
<PointInfo :point="selectedPoint"
|
||||
:device="devicesById[selectedPoint?.deviceId]"
|
||||
ref="popup"
|
||||
@remove="onRemove"
|
||||
@edit="editPoint"
|
||||
|
@ -36,6 +37,7 @@
|
|||
<div class="controls">
|
||||
<div class="form-container" v-if="showControls">
|
||||
<FilterForm :value="locationQuery"
|
||||
:devices="devices"
|
||||
:disabled="loading"
|
||||
:has-next-page="hasNextPage"
|
||||
:has-prev-page="hasPrevPage"
|
||||
|
@ -101,6 +103,7 @@ import Routes from '../mixins/Routes.vue';
|
|||
import Timeline from './Timeline.vue';
|
||||
import TimelineMetricsConfiguration from '../models/TimelineMetricsConfiguration';
|
||||
import URLQueryHandler from '../mixins/URLQueryHandler.vue';
|
||||
import UserDevice from '../models/UserDevice';
|
||||
|
||||
useGeographic()
|
||||
|
||||
|
@ -125,6 +128,7 @@ export default {
|
|||
|
||||
data() {
|
||||
return {
|
||||
devices: [] as UserDevice[],
|
||||
loading: false,
|
||||
map: null as Optional<Map>,
|
||||
mapView: null as Optional<View>,
|
||||
|
@ -143,6 +147,13 @@ export default {
|
|||
},
|
||||
|
||||
computed: {
|
||||
devicesById(): Record<string, string> {
|
||||
return this.devices.reduce((acc: Record<string, string>, device: any) => {
|
||||
acc[device.id] = device
|
||||
return acc
|
||||
}, {})
|
||||
},
|
||||
|
||||
groupedGPSPoints(): GPSPoint[] {
|
||||
// Reference refreshPoints to force reactivity
|
||||
this.refreshPoints;
|
||||
|
@ -450,8 +461,12 @@ export default {
|
|||
},
|
||||
|
||||
async mounted() {
|
||||
this.initQuery()
|
||||
this.gpsPoints = await this.fetch()
|
||||
this.initQuery();
|
||||
[this.gpsPoints, this.devices] = await Promise.all([
|
||||
this.fetch(),
|
||||
this.getMyDevices(),
|
||||
])
|
||||
|
||||
this.map = this.createMap()
|
||||
},
|
||||
}
|
||||
|
|
|
@ -50,6 +50,11 @@
|
|||
</span>
|
||||
</p>
|
||||
|
||||
<p class="device" v-if="device">
|
||||
<font-awesome-icon icon="fas fa-mobile-alt" />
|
||||
{{ device.name }}
|
||||
</p>
|
||||
|
||||
<p class="locality" v-if="point.locality">{{ point.locality }}</p>
|
||||
<p class="postal-code" v-if="point.postalCode">{{ point.postalCode }}</p>
|
||||
<p class="country" v-if="country">
|
||||
|
@ -77,11 +82,15 @@ import { getCountryData, getEmojiFlag } from 'countries-list';
|
|||
|
||||
import Dates from '../mixins/Dates.vue';
|
||||
import GPSPoint from '../models/GPSPoint';
|
||||
import UserDevice from '../models/UserDevice';
|
||||
|
||||
export default {
|
||||
emit: ['close', 'edit', 'remove'],
|
||||
mixins: [Dates],
|
||||
props: {
|
||||
device: {
|
||||
type: [UserDevice, null],
|
||||
},
|
||||
point: {
|
||||
type: [GPSPoint, null],
|
||||
},
|
||||
|
@ -271,6 +280,12 @@ export default {
|
|||
}
|
||||
}
|
||||
|
||||
.device {
|
||||
font-size: 0.9em;
|
||||
font-weight: bold;
|
||||
letter-spacing: 0.05em;
|
||||
}
|
||||
|
||||
.timestamp {
|
||||
color: var(--color-heading);
|
||||
font-weight: bold;
|
||||
|
|
|
@ -138,6 +138,17 @@
|
|||
min="0" />
|
||||
</div>
|
||||
|
||||
<div class="device-container">
|
||||
<label for="device">Device</label>
|
||||
<select id="device"
|
||||
name="device"
|
||||
v-model="newFilter.deviceId"
|
||||
:disabled="disabled">
|
||||
<option value="">All</option>
|
||||
<option v-for="device in devices" :key="device.id" :value="device.id">{{ device.name }}</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="footer">
|
||||
<button type="submit" :disabled="disabled || !changed">
|
||||
<font-awesome-icon icon="fas fa-check" /> Apply
|
||||
|
@ -149,6 +160,8 @@
|
|||
<script lang="ts">
|
||||
import _ from 'lodash'
|
||||
|
||||
import UserDevice from '../../models/UserDevice'
|
||||
|
||||
export default {
|
||||
emit: [
|
||||
'next-page',
|
||||
|
@ -157,8 +170,13 @@ export default {
|
|||
'refresh',
|
||||
'set-resolution',
|
||||
],
|
||||
|
||||
props: {
|
||||
value: Object,
|
||||
devices: {
|
||||
type: Array as () => UserDevice[],
|
||||
default: () => [],
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
|
|
|
@ -10,7 +10,7 @@ export default {
|
|||
await this.request(`/devices`) as {
|
||||
devices: UserDevice[]
|
||||
}
|
||||
).devices;
|
||||
).devices.map((device) => new UserDevice(device));
|
||||
},
|
||||
|
||||
async registerDevice(name: string): Promise<UserDevice> {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
class LocationQuery {
|
||||
public limit: number = 250;
|
||||
public offset: number | null = null;
|
||||
public deviceId: string | null = null;
|
||||
public startDate: Date | null = null;
|
||||
public endDate: Date | null = null;
|
||||
public minId: number | null = null;
|
||||
|
@ -10,9 +11,22 @@ class LocationQuery {
|
|||
public postalCode: string | null = null;
|
||||
public order: string = 'asc';
|
||||
|
||||
constructor(public data: any) {
|
||||
constructor(data: {
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
deviceId?: string;
|
||||
startDate?: Date;
|
||||
endDate?: Date;
|
||||
minId?: number;
|
||||
maxId?: number;
|
||||
country?: string;
|
||||
locality?: string;
|
||||
postalCode?: string;
|
||||
order?: string;
|
||||
}) {
|
||||
this.limit = data.limit || this.limit;
|
||||
this.offset = data.offset || this.offset;
|
||||
this.deviceId = data.deviceId || this.deviceId;
|
||||
this.startDate = data.startDate || this.startDate;
|
||||
this.endDate = data.endDate || this.endDate;
|
||||
this.minId = data.minId || this.minId;
|
||||
|
|
Loading…
Add table
Reference in a new issue