Added support for filtering directly by point IDs

This commit is contained in:
Fabio Manganiello 2025-04-08 02:33:06 +02:00
parent d9e891a821
commit c8200bfcbf
Signed by: blacklight
GPG key ID: D90FBA7F76362774
3 changed files with 48 additions and 0 deletions
frontend/src
components/filter
models
src/requests

View file

@ -241,6 +241,26 @@
v-model="newFilter.description"
:disabled="disabled" />
</div>
<div class="container ids-container">
<label for="ids">
<p class="title">
<font-awesome-icon icon="fas fa-tag" />
Point IDs
</p>
<p class="help">
Comma-separated list of point IDs to filter by
</p>
</label>
<input type="text"
id="ids"
name="ids"
placeholder="Filter by point IDs"
v-model="newFilter.ids"
:disabled="disabled" />
</div>
</main>
<footer>
@ -516,6 +536,10 @@ $footer-height: 3.5em;
width: 50%;
}
.title {
text-align: center;
}
label {
margin-bottom: 0.25em;
@include until(tablet) {

View file

@ -6,6 +6,7 @@ class LocationQuery {
public deviceId: Optional<string> = null;
public startDate: Optional<Date> = null;
public endDate: Optional<Date> = null;
public ids: Optional<number[]> = null;
public minId: Optional<number> = null;
public maxId: Optional<number> = null;
public minLatitude: Optional<number> = null;
@ -25,6 +26,7 @@ class LocationQuery {
deviceId?: Optional<string>;
startDate?: Optional<Date>;
endDate?: Optional<Date>;
ids?: Optional<number[] | string>;
minId?: Optional<number>;
maxId?: Optional<number>;
minLatitude?: Optional<number>;
@ -43,6 +45,7 @@ class LocationQuery {
this.deviceId = data.deviceId || this.deviceId;
this.startDate = data.startDate || this.startDate;
this.endDate = data.endDate || this.endDate;
this.ids = data.ids ? (Array.isArray(data.ids) ? data.ids : data.ids.split(/\s*,\s*/).map(Number)) : this.ids;
this.minId = data.minId || this.minId;
this.maxId = data.maxId || this.maxId;
this.minLatitude = data.minLatitude || this.minLatitude;

View file

@ -13,6 +13,7 @@ class LocationRequest {
offset: Optional<number> = null;
startDate: Optional<Date> = null;
endDate: Optional<Date> = null;
ids: Optional<number[]> = null;
minId: Optional<number> = null;
maxId: Optional<number> = null;
minLatitude: Optional<number> = null;
@ -33,6 +34,7 @@ class LocationRequest {
offset?: number;
startDate?: Date;
endDate?: Date;
ids?: number[] | string;
minId?: number;
maxId?: number;
minLatitude?: number;
@ -64,6 +66,15 @@ class LocationRequest {
this.description = req.description;
this.orderBy = req.orderBy || this.orderBy;
this.order = (req.order || this.order).toUpperCase() as Order;
const ids = typeof req.ids === 'string' ? req.ids.split(/\s*,\s*/) : req.ids;
this.ids = (ids || []).map((id: any) => {
const numId = parseInt(id);
if (isNaN(numId)) {
throw new ValidationError(`Invalid value for ids: ${id}`);
}
return numId;
});
}
private initNumber(key: string, req: any, parser: (s: string) => number = parseInt): void {
@ -89,6 +100,16 @@ class LocationRequest {
let queryMap: any = {};
const where: any = {};
if (this.ids?.length) {
queryMap.where = {
[db.locationTableColumns.id || 'id']: {[Op.in]: this.ids},
};
queryMap.order = [[db.locationTableColumns.timestamp || 'timestamp', this.order.toUpperCase()]];
// If we have ids, we don't need any other filters
return queryMap;
}
if (this.limit != null) {
queryMap.limit = this.limit;
}