Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Set up framework for UI filters, add Performer filter #122

Merged
merged 12 commits into from
Dec 7, 2022
1 change: 1 addition & 0 deletions django/src/rdwatch/serializers/site_evaluation.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class SiteEvaluationListSerializer(serializers.Serializer):
count = serializers.IntegerField()
timerange = TimeRangeSerializer()
bbox = BoundingBoxSerializer()
performers = serializers.ListField()
results = SiteEvaluationSerializer(many=True)
next = serializers.CharField()
previous = serializers.CharField()
4 changes: 4 additions & 0 deletions django/src/rdwatch/views/site_evaluation.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ def site_evaluations(request: HttpRequest):
bbox=BoundingBox(Collect("geom")),
)

overview["performers"] = SiteEvaluation.objects.values_list(
"configuration__performer__slug", flat=True
).distinct()
Comment on lines +67 to +69
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note - this adds another field, "performers", to the response of this endpoint. It's a list of every performer in the system, regardless of the filters and/or pagination applied to the site evaluations themselves. I'm torn on if this is correct, or if it should be its own endpoint, but we need some way for the frontend to know every possible performer.


# Pagination
assert api_settings.PAGE_SIZE, "PAGE_SIZE must be set."
limit = int(request.GET.get("limit", api_settings.PAGE_SIZE)) or sys.maxsize
Expand Down
1 change: 1 addition & 0 deletions django/src/rdwatch/views/tile.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ def vector_tile(
order_by="timestamp", # type: ignore
),
),
performer=F("siteeval__configuration__performer__slug"),
)
)
(
Expand Down
136 changes: 136 additions & 0 deletions vue/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions vue/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"@vitejs/plugin-vue": "^3.0.0",
"@vue/test-utils": "^2.0.2",
"autoprefixer": "^10.4.7",
"daisyui": "^2.42.1",
"eslint": "^8.20.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-vue": "^9.2.0",
Expand Down
3 changes: 3 additions & 0 deletions vue/src/client/models/SiteEvaluationList.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export type SiteEvaluationList = {
ymin: number;
ymax: number;
};
performers: Array<any>;
results: Array<{
id: number;
site: string;
Expand All @@ -35,4 +36,6 @@ export type SiteEvaluationList = {
ymax: number;
};
}>;
next: string;
previous: string;
};
5 changes: 4 additions & 1 deletion vue/src/client/services/ApiService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,13 @@ export class ApiService {
* @returns SiteEvaluationList
* @throws ApiError
*/
public static getSiteEvaluations(): CancelablePromise<SiteEvaluationList> {
public static getSiteEvaluations(
query?: Record<string, string>
): CancelablePromise<SiteEvaluationList> {
return __request(OpenAPI, {
method: "GET",
url: "/api/evaluations",
query,
});
}

Expand Down
24 changes: 12 additions & 12 deletions vue/src/components/MapLibre.vue
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ onMounted(() => {
map.value = markRaw(
new Map({
container: mapContainer.value,
style: style(state.timestamp),
style: style(state.timestamp, state.filters),
bounds: [
[state.bbox.xmin, state.bbox.ymin],
[state.bbox.xmax, state.bbox.ymax],
Expand All @@ -51,17 +51,17 @@ onUnmounted(() => {
map.value?.remove();
});

watch(
() => state.timestamp,
(val) => {
const siteFilter = buildSiteFilter(val);
const observationFilter = buildObservationFilter(val);
setFilter("sites-outline", siteFilter);
setFilter("observations-fill", observationFilter);
setFilter("observations-outline", observationFilter);
setFilter("observations-text", observationFilter);
}
);
watch([() => state.timestamp, () => state.filters], () => {
const siteFilter = buildSiteFilter(state.timestamp);
const observationFilter = buildObservationFilter(
state.timestamp,
state.filters
);
setFilter("sites-outline", siteFilter);
setFilter("observations-fill", observationFilter);
setFilter("observations-outline", observationFilter);
setFilter("observations-text", observationFilter);
});

watch(
() => state.bbox,
Expand Down
25 changes: 20 additions & 5 deletions vue/src/components/SideBar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import EvaluationList from "./EvaluationList.vue";
import TimeSlider from "./TimeSlider.vue";
import { state } from "../store";
import { filters } from "./filters";
import { ApiService } from "../client";
import { ref, watch, watchEffect } from "vue";
import type { SiteEvaluationList } from "../client";
Expand All @@ -25,12 +26,23 @@ watch(openedEvaluation, (val) => {
state.bbox = val !== undefined ? val.bbox : evaluations.value.bbox;
}
});

async function filterEvaluations(field: string, value: string) {
const query = {
[field]: value,
};
evaluations.value = await ApiService.getSiteEvaluations(query);
timemin.value = evaluations.value.timerange.min;
state.bbox = evaluations.value.bbox;
state.filters = query;
}
</script>

<template>
<div class="relative">
<div class="fixed h-screen w-80 pt-2 pb-2 pl-2">
<div
v-if="evaluations"
class="relative h-full overflow-hidden rounded-xl bg-white drop-shadow-2xl"
>
<div
Expand All @@ -41,14 +53,17 @@ watch(openedEvaluation, (val) => {
src="../assets/logo.svg"
alt="Resonant GeoData"
/>
<component
:is="filter"
v-for="(filter, i) in filters"
:key="`filter-${i}`"
v-bind="{ evaluations }"
@filter="filterEvaluations"
/>
<TimeSlider :min="timemin" :max="Math.floor(Date.now() / 1000)" />
{{ new Date(state.timestamp * 1000).toLocaleString() }}
</div>
<EvaluationList
v-if="evaluations"
v-model="openedEvaluation"
:evaluations="evaluations"
/>
<EvaluationList v-model="openedEvaluation" :evaluations="evaluations" />
</div>
</div>
</div>
Expand Down
Loading