Skip to content

Commit

Permalink
Feat hiarchy second try (#82)
Browse files Browse the repository at this point in the history
resolves #81, resolves #52

---------

Co-authored-by: Robin Kaggl <[email protected]>
  • Loading branch information
kaggl and Robin Kaggl authored Mar 13, 2024
1 parent eb5d4fa commit 8a2ffa5
Show file tree
Hide file tree
Showing 22 changed files with 835 additions and 90 deletions.
3 changes: 1 addition & 2 deletions .vscode/extensions.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
"esbenp.prettier-vscode",
"mikestead.dotenv",
"stylelint.vscode-stylelint",
"vue.volar",
"vue.vscode-typescript-vue-plugin"
"vue.volar"
]
}
12 changes: 3 additions & 9 deletions components/app-header.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const links = computed(() => {
return {
home: { href: { path: localePath("/") }, label: t("pages.home.label") },
search: { href: { path: localePath("/search/persons") }, label: t("pages.search.label") },
hierarchy: { href: { path: localePath("/hierarchy") }, label: t("pages.hierarchy.label") },
documentation: {
href: { path: localePath("/documentation/project") },
label: t("pages.documentation.label"),
Expand Down Expand Up @@ -52,14 +53,7 @@ const links = computed(() => {
<span class="sr-only">Open/Close Menu</span>
</MenuButton>
</ClientOnly>
<Transition
enter-active-class="transition duration-100 ease-out"
enter-from-class="transform scale-95 -translate-y-8 opacity-0"
enter-to-class="transform scale-100 translate-y-0 opacity-100"
leave-active-class="transition duration-75 ease-in"
leave-from-class="transform scale-100 opacity-100"
leave-to-class="transform scale-95 opacity-0"
>
<MenuTransition>
<MenuItems
as="div"
class="absolute right-0 z-50 mt-1 flex w-56 flex-col divide-y rounded bg-gray-50 shadow-lg ring"
Expand All @@ -77,7 +71,7 @@ const links = computed(() => {
<LocaleSwitch no-select />
</MenuItem>
</MenuItems>
</Transition>
</MenuTransition>
</Menu>
</div>
</div>
Expand Down
89 changes: 89 additions & 0 deletions components/autocomplete.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<script lang="ts" setup>
import {
Combobox,
ComboboxButton,
ComboboxInput,
ComboboxOption,
ComboboxOptions,
} from "@headlessui/vue";
import { useQuery } from "@tanstack/vue-query";
import { Search } from "lucide-vue-next";
import type { ModelRef } from "vue";
import type { HierarchyNode } from "@/lib/types";
const query = ref(
useQuery({
queryKey: ["autocomplete"],
queryFn: async () => {
const data = await fetch(
"https://viecpro.acdh-dev.oeaw.ac.at/visualisations/entityautocomplete/",
);
const ret = await data.json();
return ret.context as Array<HierarchyNode>;
},
}),
);
const selection: ModelRef<HierarchyNode | null> = defineModel({
default: null,
});
const input = ref("");
const filtered = computed(() => {
if (!query.value.data) return null;
return input.value === ""
? query.value.data
: query.value.data.filter((entity) => {
return entity.label.toLowerCase().includes(input.value.toLowerCase());
});
});
defineEmits(["change", "input"]);
</script>

<template>
<Combobox
v-model="selection"
as="div"
class="relative"
@update:model-value="$emit('change', selection)"
>
<div
v-if="!query.isFetching"
class="relative m-2 flex cursor-default overflow-hidden rounded border bg-white text-left shadow-lg"
>
<ComboboxInput
class="w-96 truncate p-2"
:display-value="(entity) => (entity as HierarchyNode)?.label"
@change="
$emit('input', $event.target.value);
input = $event.target.value;
"
/>
<ComboboxButton class="inset-y-0 right-0 flex items-center px-3 text-gray-500">
<Search class="h-5 w-5" />
</ComboboxButton>
</div>
<div v-else class="m-2 h-11 w-96 animate-pulse rounded bg-gray-300 shadow-lg" />
<MenuTransition>
<ComboboxOptions
v-if="filtered"
as="div"
class="absolute ml-2 flex flex-col divide-y overflow-auto rounded border bg-white text-base shadow"
>
<ComboboxOption
v-for="entity in filtered.slice(0, 10)"
:key="entity.pk"
:value="entity"
as="div"
class="cursor-pointer p-2 ui-active:bg-primary-300"
>
{{ entity.label }}
</ComboboxOption>
</ComboboxOptions>
</MenuTransition>
</Combobox>
</template>
2 changes: 1 addition & 1 deletion components/detail-disclosure.vue
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ const all = props.rels.length;
class="grid grid-cols-[1fr_auto] items-center gap-1"
:class="linkTo && 'rounded transition hover:bg-slate-200 active:bg-slate-300 p-1 -ml-1'"
>
<div class="grid items-center gap-2" :class="gridClass">
<div class="grid items-center gap-2 hyphens-auto" :class="gridClass">
<template v-for="header in headers" :key="hit + header">
<span v-if="typeof header === 'string'">
{{ get(hit, header) }}
Expand Down
11 changes: 2 additions & 9 deletions components/download-menu.vue
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,7 @@ defineProps<{
<span class="sr-only">Open/Close Menu</span>
</MenuButton>
</ClientOnly>
<Transition
enter-active-class="transition duration-100 ease-out"
enter-from-class="transform scale-95 -translate-y-8 opacity-0"
enter-to-class="transform scale-100 translate-y-0 opacity-100"
leave-active-class="transition duration-75 ease-in"
leave-from-class="transform scale-100 opacity-100"
leave-to-class="transform scale-95 opacity-0"
>
<MenuTransition>
<MenuItems
as="div"
class="absolute right-0 mt-1 flex gap-2 divide-y rounded border bg-gray-50 p-2 shadow-lg"
Expand Down Expand Up @@ -78,6 +71,6 @@ defineProps<{
<DownloadResultsButtons :collection="collection" :all="all" :query="query" />
</MenuItem>
</MenuItems>
</Transition>
</MenuTransition>
</Menu>
</template>
4 changes: 2 additions & 2 deletions components/facet-disclosures.vue
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ const route = useRoute();
const facetObject: Record<string, Array<string>> = getFacetObjectFromURL(true);
const facetChange = async (facets: Array<string>, field: string) => {
const facetChange = (facets: Array<string>, field: string) => {
facetObject[field] = facets;
await router.push({
void router.push({
query: {
...route.query,
page: 1,
Expand Down
47 changes: 47 additions & 0 deletions components/generic-listbox.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<script lang="ts" setup>
import { Listbox, ListboxButton, ListboxOption, ListboxOptions } from "@headlessui/vue";
import { ChevronsUpDown } from "lucide-vue-next";
import type { ModelRef } from "vue";
const model: ModelRef<{ label: string; value: string } | null> = defineModel({
default: null,
});
defineProps<{
items: Array<{ label: string; value: string }>;
}>();
defineEmits(["change"]);
</script>

<template>
<Listbox
v-model="model"
as="div"
class="relative"
@update:model-value="(to) => $emit('change', to)"
>
<ListboxButton
class="flex h-11 w-full items-center justify-between gap-2 rounded border bg-white p-2 shadow-lg"
as="button"
>
<span>{{ model?.label || model }}</span>
<ChevronsUpDown class="h-5 w-5 text-gray-500" />
</ListboxButton>
<MenuTransition>
<ListboxOptions
v-if="items.length != 0"
as="div"
class="absolute mt-2 flex w-full flex-col divide-y rounded border bg-white shadow-xl"
>
<ListboxOption
v-for="item in items"
:key="item.value"
class="cursor-pointer list-none p-2 first-of-type:rounded-t last-of-type:rounded-b ui-selected:bg-primary-300 ui-active:bg-primary-300"
:value="item"
>
<span>{{ item.label }}</span>
</ListboxOption>
</ListboxOptions>
</MenuTransition>
</Listbox>
</template>
75 changes: 75 additions & 0 deletions components/hierarchy-wrapper.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<script lang="ts" setup>
import { hierarchy } from "d3";
import type { TreeEntity } from "@/lib/get-tree-data";
import { Tree } from "@/lib/tree";
const router = useRouter();
const locale = useLocale();
const props = defineProps<{
data: TreeEntity;
width: number;
}>();
const hierarchyRef = ref<SVGElement | null>(null);
onMounted(() => {
updateTree(props.data, props.width);
});
watch(
() => [props.data, props.width],
([to, newWidth]) => {
updateTree(to as TreeEntity, newWidth as number);
},
{ deep: true },
);
interface Node {
data: {
children: Array<Node>;
name: string;
meta: {
end: string;
entity_type: string;
label: string;
pk: number;
rel_end: string;
rel_start: string;
start: string;
url: string;
};
};
depth: number;
height: number;
parent?: Node;
}
function updateTree(data: TreeEntity, width: number) {
const options = {
label: (d: Node) => d.data.meta.label,
link: (d: Node) =>
`/${locale.value}/hierarchy?id=${d.data.meta.pk}&model=${d.data.meta.entity_type}&label=${d.data.meta.label}`,
width,
r: 7,
fontSize: "medium",
padding: 2,
};
hierarchyRef.value = Tree(hierarchy(data), options);
}
</script>

<template>
<!-- eslint-disable vuejs-accessibility/no-static-element-interactions -->
<!-- eslint-disable vuejs-accessibility/click-events-have-key-events -->
<div
class="w-full"
@click.prevent="
(event) =>
event.target?.parentNode?.href ? router.push(event.target.parentNode.href.baseVal) : null
"
v-html="hierarchyRef?.outerHTML"
/>
</template>
11 changes: 2 additions & 9 deletions components/info-menu.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,12 @@ import { Menu, MenuButton, MenuItem, MenuItems } from "@headlessui/vue";
<slot name="button" />
</MenuButton>
</ClientOnly>
<Transition
enter-active-class="transition duration-100 ease-out"
enter-from-class="transform scale-95 -translate-y-8 opacity-0"
enter-to-class="transform scale-100 translate-y-0 opacity-100"
leave-active-class="transition duration-75 ease-in"
leave-from-class="transform scale-100 opacity-100"
leave-to-class="transform scale-95 opacity-0"
>
<MenuTransition>
<MenuItems as="div" class="absolute right-0 rounded border bg-gray-50 p-2 shadow-lg">
<MenuItem>
<slot name="content" />
</MenuItem>
</MenuItems>
</Transition>
</MenuTransition>
</Menu>
</template>
11 changes: 2 additions & 9 deletions components/locale-switch.vue
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,7 @@ defineProps<{
{{ locale.toUpperCase() }}
</MenuButton>
</ClientOnly>
<Transition
enter-active-class="transition duration-100 ease-out"
enter-from-class="transform scale-95 -translate-y-8 opacity-0"
enter-to-class="transform scale-100 translate-y-0 opacity-100"
leave-active-class="transition duration-75 ease-in"
leave-from-class="transform scale-100 opacity-100"
leave-to-class="transform scale-95 opacity-0"
>
<MenuTransition>
<MenuItems
class="fixed z-50 ml-4 mt-4 flex -translate-x-4 flex-col rounded bg-white shadow-lg"
>
Expand All @@ -43,7 +36,7 @@ defineProps<{
{{ loc.code.toUpperCase() }}
</MenuItem>
</MenuItems>
</Transition>
</MenuTransition>
</Menu>
</div>
<div v-else class="flex w-full divide-x">
Expand Down
12 changes: 12 additions & 0 deletions components/menu-transition.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<template>
<Transition
enter-active-class="transition duration-100 ease-out"
enter-from-class="transform scale-95 -translate-y-8 opacity-0"
enter-to-class="transform scale-100 translate-y-0 opacity-100"
leave-active-class="transition duration-75 ease-in"
leave-from-class="transform scale-100 opacity-100"
leave-to-class="transform scale-95 opacity-0"
>
<slot />
</Transition>
</template>
4 changes: 2 additions & 2 deletions components/search-table.vue
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ const limitNum = computed(() => {
});
const comQuery = computed(() => {
const query = route.query;
const { query } = route;
return {
q: String(query.q ?? ""),
query_by: props.queryBy,
Expand Down Expand Up @@ -183,7 +183,7 @@ const getDetailLink = (id: string, entity?: string) => {
<div
v-for="hit in data.hits"
:key="String(hit.document.id)"
class="border-b py-1 md:border-t"
class="hyphens-auto border-b py-1 md:border-t"
>
<component
:is="customCols ? 'div' : NuxtLink"
Expand Down
Loading

0 comments on commit 8a2ffa5

Please sign in to comment.