Skip to content

Commit

Permalink
Feat/visualization popups (#24)
Browse files Browse the repository at this point in the history
Add entity popups to the visualizations, when a detail view is enabled.
so the context of the entity is not lost, when the visualization
switches.
  • Loading branch information
stefanprobst authored Jun 28, 2024
2 parents addd7aa + f19e872 commit c7b1d43
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 5 deletions.
8 changes: 7 additions & 1 deletion components/data-graph.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { colors } from "../project.config.json";
const props = defineProps<{
networkData: NetworkEntity;
searchNode: string;
detailNode?: string;
}>();
const graph = new Graph();
Expand Down Expand Up @@ -62,5 +63,10 @@ function getNodeColor(nodeClass: string) {

<template>
<div class="absolute z-10 m-3 flex w-full"></div>
<Network v-if="graph.size > 0" :graph="graph" :search-node="props.searchNode" />
<Network
v-if="graph.size > 0"
:graph="graph"
:search-node="props.searchNode"
:detail-node="props.detailNode"
/>
</template>
35 changes: 34 additions & 1 deletion components/data-map-view.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,17 @@ const route = useRoute();
const t = useTranslations();
const currentView = useGetCurrentView();
const { getUnprefixedId } = useIdPrefix();
const searchFiltersSchema = v.object({
category: v.fallback(v.picklist(categories), "entityName"),
search: v.fallback(v.string(), ""),
});
const detailEntityId = computed(() => {
return route.params.id as string;
});
const searchFilters = computed(() => {
return v.parse(searchFiltersSchema, route.query);
});
Expand All @@ -48,7 +53,7 @@ const { data, isPending, isPlaceholderData } = useGetSearchResults(
: [],
show: ["geometry", "when"],
centroid: true,
system_classes: ["place", "object_location"],
system_classes: ["place"],
limit: 0,
};
}),
Expand Down Expand Up @@ -141,6 +146,34 @@ watch(data, () => {
*/
popover.value = null;
});
watchEffect(() => {
const entity = entities.value.find((feature) => {
const id = getUnprefixedId(feature["@id"]);
return id === detailEntityId.value;
});
if (entity) {
let coordinates = null;
if (entity.geometry.type === "GeometryCollection") {
coordinates = entity.geometry.geometries.find((g) => {
return g.type === "Point";
})?.coordinates as [number, number] | undefined;
}
if (entity.geometry.type === "Point") {
coordinates = entity.geometry.coordinates as unknown as [number, number];
}
popover.value = {
coordinates:
coordinates ??
(turf.center(createFeatureCollection([entity])).geometry.coordinates as [number, number]),
entities: [entity],
};
}
});
</script>

<template>
Expand Down
10 changes: 9 additions & 1 deletion components/data-network-view.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ import { project } from "../config/project.config";
const router = useRouter();
const route = useRoute();
const detailEntityId = computed(() => {
return route.params.id as string;
});
const searchFiltersSchema = z.object({
search: z.string().catch(""),
});
Expand Down Expand Up @@ -104,7 +108,11 @@ const systemClasses = computed(() => {
:system-classes="systemClasses"
@submit="onChangeCategory"
/>
<DataGraph :network-data="entities" :search-node="searchFilters.search" />
<DataGraph
:network-data="entities"
:search-node="searchFilters.search"
:detail-node="detailEntityId"
/>
<Centered v-if="isLoading" class="pointer-events-none">
<LoadingIndicator class="text-neutral-950" size="lg" />
</Centered>
Expand Down
3 changes: 2 additions & 1 deletion components/geo-map-popup.client.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const emit = defineEmits<{
(event: "close"): void;
}>();
const { map } = useGeoMap();
const geoMapContext = useGeoMap();
const elementRef = ref<HTMLElement | null>(null);
Expand All @@ -24,6 +24,7 @@ const context: Context = {
onMounted(async () => {
await nextTick();
const { map } = geoMapContext;
assert(elementRef.value != null);
assert(map != null);
Expand Down
44 changes: 44 additions & 0 deletions components/network.client.vue
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ interface State {
const props = defineProps<{
graph: Graph;
searchNode?: string;
detailNode?: string;
}>();
interface NetworkContext {
Expand All @@ -41,6 +42,7 @@ circular.assign(context.graph);
const locale = useLocale();
const router = useRouter();
let hoverTimeOut: ReturnType<typeof setTimeout>;
const state = ref<State>({});
Expand Down Expand Up @@ -91,6 +93,48 @@ watch(
{ immediate: true },
);
watch(
() => {
return props.detailNode;
},
(detailNode) => {
context.graph.nodes().forEach((el) => {
context.graph.removeNodeAttribute(el, "highlighted");
});
if (detailNode) {
const results = context.graph
.nodes()
.map((n) => {
return { id: n, label: context.graph.getNodeAttribute(n, "id") as string };
})
.filter(({ id }) => {
return id === detailNode;
});
if (results.length === 1) {
state.value.selectedNodes = results;
state.value.selectedNodes.forEach((el) => {
context.graph.setNodeAttribute(el.id, "highlighted", true);
});
}
}
// If the query is empty, then we reset the selectedNode
else {
state.value.selectedNodes = undefined;
}
// Refresh rendering
// You can directly call `renderer.refresh()`, but if you need performances
// you can provide some options to the refresh method.
// In this case, we don't touch the graph data so we can skip its reindexation
context.renderer?.refresh({
skipIndexation: true,
});
},
{ immediate: true },
);
const currentView = useGetCurrentView();
onMounted(async () => {
Expand Down
2 changes: 1 addition & 1 deletion layouts/visualization.vue
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ const currentView = useGetCurrentView();
<template v-if="env.public.NUXT_PUBLIC_DATABASE !== 'disabled'">
<ErrorBoundary>
<DataMapView v-if="currentView === 'map'" />
<DataNetworkView v-else />
<DataNetworkView v-if="currentView === 'network'" />
</ErrorBoundary>
</template>
<template v-else>
Expand Down

0 comments on commit c7b1d43

Please sign in to comment.