Skip to content

Commit

Permalink
Feat/disable map visualization (#25)
Browse files Browse the repository at this point in the history
when an entity is not displayed on the map or the network disable the
mode-switcher so you can not switch to the view.
navigate to the visualizations (datalist, map and network) via query
params (mode and selection)
  • Loading branch information
stefanprobst authored Aug 7, 2024
2 parents c19dd0c + c54e080 commit 49c94c4
Show file tree
Hide file tree
Showing 30 changed files with 731 additions and 337 deletions.
22 changes: 16 additions & 6 deletions components/app-header.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,26 @@ const defaultLinks = computed<
if (!project.map.startPage) {
return {
home: { href: { path: "/" }, label: t("AppHeader.links.home") },
data: { href: { path: "/data" }, label: t("AppHeader.links.data") },
map: { href: { path: "/map" }, label: t("AppHeader.links.map") },
network: { href: { path: "/network" }, label: t("AppHeader.links.network") },
data: {
href: { path: "/visualization", query: { mode: "table" } },
label: t("AppHeader.links.data"),
},
map: {
href: { path: "/visualization", query: { mode: "map" } },
label: t("AppHeader.links.map"),
},
network: {
href: { path: "/visualization", query: { mode: "network" } },
label: t("AppHeader.links.network"),
},
team: { href: { path: "/team" }, label: t("AppHeader.links.team") },
};
}
return {
home: { href: { path: "/" }, label: t("AppHeader.links.home") },
data: { href: { path: "/data" }, label: t("AppHeader.links.data") },
network: { href: { path: "/network" }, label: t("AppHeader.links.network") },
home: {
href: { path: "/", query: { mode: "map" } },
label: t("AppHeader.links.home"),
},
team: { href: { path: "/team" }, label: t("AppHeader.links.team") },
};
});
Expand Down
22 changes: 20 additions & 2 deletions components/custom-primary-details-feature.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const t = useTranslations();
const { getUnprefixedId } = useIdPrefix();
const props = defineProps<{ entity: EntityFeature }>();
const route = useRoute();
const { data } = useGetBySystemClass(
computed(() => {
Expand Down Expand Up @@ -80,13 +81,27 @@ const handledRelations: Array<RelationType> = [
onMounted(() => {
emit("handledRelations", handledRelations);
});
function getPath() {
if (route.path.includes("visualization")) {
return "visualization";
}
return "";
}
const currentMode = computed(() => {
return route.query.mode;
});
</script>

<template>
<div class="flex justify-between">
<NavLink
v-if="previousFeature"
:href="{ path: `/entities/${getUnprefixedId(previousFeature['@id'])}` }"
:href="{
path: `/${getPath()}`,
query: { mode: currentMode, selection: getUnprefixedId(previousFeature['@id']) },
}"
class="flex items-center underline decoration-dotted transition hover:no-underline focus-visible:no-underline"
>
<ChevronLeftIcon class="size-4" />
Expand All @@ -95,7 +110,10 @@ onMounted(() => {
</NavLink>
<NavLink
v-if="nextFeature"
:href="{ path: `/entities/${getUnprefixedId(nextFeature['@id'])}` }"
:href="{
path: `/${getPath()}`,
query: { mode: currentMode, selection: getUnprefixedId(nextFeature['@id']) },
}"
class="flex items-center underline decoration-dotted transition hover:no-underline focus-visible:no-underline"
>
<span>{{ nextFeature.properties.title }}</span>
Expand Down
80 changes: 51 additions & 29 deletions components/data-map-view.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,26 +15,38 @@ const router = useRouter();
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 entitySelectionSchema = v.object({
selection: v.fallback(v.array(v.string()), []),
});
const searchFilters = computed(() => {
return v.parse(searchFiltersSchema, route.query);
});
type EntitySelection = v.InferOutput<typeof entitySelectionSchema>;
type SearchFilters = v.InferOutput<typeof searchFiltersSchema>;
function setEntitySelection(query: Partial<EntitySelection>) {
void router.push({ query: { mode: route.query.mode, ...query } });
}
function onChangeEntitySelection(values: EntityFeature) {
const temp: EntitySelection = {
selection: [getUnprefixedId(values["@id"])],
};
setEntitySelection(temp);
}
function setSearchFilters(query: Partial<SearchFilters>) {
void router.push({ query });
void router.push({ query: { mode: route.query.mode, ...query } });
}
function onChangeSearchFilters(values: SearchFormData) {
Expand Down Expand Up @@ -83,6 +95,13 @@ function togglePolygons() {
show.value = !show.value;
}
const selection = computed(() => {
return route.query.selection;
});
const mode = computed(() => {
return route.query.mode;
});
/**
* Reduce size of geojson payload, which has an impact on performance,
* because `maplibre-gl` will serialize geojson features when sending them to the webworker.
Expand Down Expand Up @@ -148,30 +167,32 @@ watch(data, () => {
});
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];
if (mode.value && selection.value) {
const entity = entities.value.find((feature) => {
const id = getUnprefixedId(feature["@id"]);
return id === selection.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],
};
}
popover.value = {
coordinates:
coordinates ??
(turf.center(createFeatureCollection([entity])).geometry.coordinates as [number, number]),
entities: [entity],
};
}
});
</script>
Expand Down Expand Up @@ -248,8 +269,9 @@ watchEffect(() => {
>
<strong class="font-medium">
<NavLink
class="flex items-center gap-1 underline decoration-dotted hover:no-underline"
:href="{ path: `/entities/${entity.properties._id}/${currentView}` }"
href="#"
class="flex cursor-pointer items-center gap-1 underline decoration-dotted hover:no-underline"
@click="onChangeEntitySelection(entity)"
>
<Component :is="getEntityIcon(entity.systemClass)" class="size-3.5 shrink-0" />
{{ entity.properties.title }}
Expand Down
22 changes: 5 additions & 17 deletions components/data-network-view.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const router = useRouter();
const route = useRoute();
const detailEntityId = computed(() => {
return route.params.id as string;
return route.query.selection as string;
});
const searchFiltersSchema = z.object({
Expand All @@ -22,7 +22,7 @@ const searchFilters = computed(() => {
});
function onChangeSearchFilters(values: SearchFormData) {
const query = { ...searchFilters.value, ...values };
const query = { mode: route.query.mode, ...searchFilters.value, ...values };
if (values.search === "") {
// @ts-expect-error Fix me later please
Expand All @@ -33,27 +33,15 @@ function onChangeSearchFilters(values: SearchFormData) {
}
function onChangeCategory(values: CategoryFormData) {
void router.push({ query: { ...searchFilters.value, ...values } });
void router.push({ query: { mode: route.query.mode, ...searchFilters.value, ...values } });
}
const { data, isPending, isPlaceholderData } = useGetNetworkData(
// @ts-expect-error Includes custom, per-instance system classes.
computed(() => {
return {
exclude_system_classes: [
// TO-DO: Currently there is an issue: filtering by case study and system_class type will return no results
"type",
"object_location",
"reference_system",
"file",
"source_translation",
"source",
"bibliography",
"external_reference",
"administrative_unit",
"edition",
"type_tools",
],
// TO-DO: Currently there is an issue: filtering by case study and system_class type will return no results
exclude_system_classes: project.network.exclude,
};
}),
);
Expand Down
6 changes: 4 additions & 2 deletions components/data-view.vue
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,9 @@ const sortingState = computed(() => {
type SearchFilters = v.InferOutput<typeof searchFiltersSchema>;
function setSearchFilters(query: Partial<SearchFilters>) {
void router.push({ query });
void router.push({
query: { mode: route.query.mode, selection: route.query.selection, ...query },
});
document.body.scrollTo(0, 0);
}
Expand Down Expand Up @@ -106,7 +108,7 @@ const entities = computed(() => {
</script>

<template>
<div class="relative grid grid-rows-[auto_1fr] gap-4">
<div class="container relative grid grid-rows-[auto_1fr] gap-4 p-8">
<SearchForm
:filter="searchFilters.category"
:search="searchFilters.search"
Expand Down
28 changes: 26 additions & 2 deletions components/entity-details.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { useIdPrefix } from "@/composables/use-id-prefix";
const { getUnprefixedId } = useIdPrefix();
const t = useTranslations();
const route = useRoute();
const props = defineProps<{
relations: EntityFeature["relations"];
Expand Down Expand Up @@ -33,6 +34,17 @@ const relationsByType = computed(() => {
},
);
});
function getPath() {
if (route.path.includes("visualization")) {
return "visualization";
}
return "";
}
const currentMode = computed(() => {
return route.query.mode;
});
</script>

<template>
Expand All @@ -54,7 +66,13 @@ const relationsByType = computed(() => {
<NavLink
v-if="relation.relationTo"
class="underline decoration-dotted hover:no-underline"
:href="{ path: `/entities/${getUnprefixedId(relation.relationTo)}` }"
:href="{
path: `/${getPath()}`,
query: {
mode: currentMode,
selection: getUnprefixedId(relation.relationTo),
},
}"
>
{{ relation.label }}
</NavLink>
Expand All @@ -68,7 +86,13 @@ const relationsByType = computed(() => {
<NavLink
v-if="relation.relationTo"
class="underline decoration-dotted hover:no-underline"
:href="{ path: `/entities/${getUnprefixedId(relation.relationTo)}` }"
:href="{
path: `/${getPath()}`,
query: {
mode: currentMode,
selection: getUnprefixedId(relation.relationTo),
},
}"
>
{{ relation.label }}
</NavLink>
Expand Down
17 changes: 16 additions & 1 deletion components/entity-preview-link.vue
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<script setup lang="ts">
const route = useRoute();
const props = defineProps<{ id: number; entity?: EntityFeature; label?: string }>();
const previewEntity = computed(() => {
Expand All @@ -21,14 +22,28 @@ const { data, isPending, isPlaceholderData } = props.entity
const isLoading = computed(() => {
return isPending || isPlaceholderData;
});
function getPath() {
if (route.path.includes("visualization")) {
return "visualization";
}
return "";
}
const currentMode = computed(() => {
return route.query.mode;
});
</script>

<template v-if="entity || id">
<HoverCard :close-delay="150" :open-delay="150">
<HoverCardTrigger as-child>
<NavLink
class="underline decoration-dotted transition hover:no-underline focus-visible:no-underline"
:href="{ path: `/entities/${id}` }"
:href="{
path: `/${getPath()}`,
query: { mode: currentMode, selection: id },
}"
>
<template v-if="label">
{{ label }}
Expand Down
Loading

0 comments on commit 49c94c4

Please sign in to comment.