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