Skip to content

Display facets with a parent-child relationship as a tree #1214

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

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 2 additions & 44 deletions lxl-web/src/lib/components/find/FacetGroup.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import { page } from '$app/stores';
import type { LocaleCode } from '$lib/i18n/locales';
import type { FacetGroup, Facet, MultiSelectFacet } from '$lib/types/search';
import { ShowLabelsOptions } from '$lib/types/decoratedData';
import {
DEFAULT_FACETS_SHOWN,
DEFAULT_FACET_SORT,
Expand All @@ -12,12 +11,10 @@
import { getMatomoTracker } from '$lib/contexts/matomo';
import { popover } from '$lib/actions/popover';
import FacetRange from './FacetRange.svelte';
import DecoratedData from '../DecoratedData.svelte';
import BiChevronRight from '~icons/bi/chevron-right';
import BiSortDown from '~icons/bi/sort-down';
import BiCheckSquareFill from '~icons/bi/check-square-fill';
import BiSquare from '~icons/bi/square';
import BiInfo from '~icons/bi/info-circle';
import Node from '$lib/components/find/Node.svelte';

const matomoTracker = getMatomoTracker();

Expand Down Expand Up @@ -131,39 +128,7 @@
>
{#each shownFacets as facet (facet.view['@id'])}
<li>
<a
class="facet-link flex items-end justify-between gap-2 no-underline"
href={facet.view['@id']}
>
<span class="overflow-hidden text-ellipsis whitespace-nowrap" title={facet.str}>
{#if 'selected' in facet}
<!-- checkboxes -->
<span class="sr-only"
>{facet.selected ? $page.data.t('search.activeFilter') : ''}</span
>
<div class="mr-1 inline-block h-[13px] w-[13px]" aria-hidden="true">
{#if facet.selected}
<BiCheckSquareFill height="13px" />
{:else}
<BiSquare height="13px" />
{/if}
</div>
{/if}
<span>
<DecoratedData data={facet.object} showLabels={ShowLabelsOptions.Never} />
{#if facet.discriminator}
<span class="text-sm text-secondary">({facet.discriminator})</span>
{/if}
</span>
</span>
{#if facet.totalItems > 0}
<span
class="facet-total mb-px rounded-sm bg-pill/4 px-1 text-sm text-secondary md:text-xs"
aria-label="{facet.totalItems} {$page.data.t('search.hits')}"
>{facet.totalItems.toLocaleString(locale)}</span
>
{/if}
</a>
<Node root={facet} {locale} />
</li>
{/each}
</ol>
Expand Down Expand Up @@ -213,11 +178,4 @@
li[data-dimension='boolFilters'] details[open] .facet-sort {
@apply hidden;
}

.facet-link:hover,
.facet-link:focus {
& .facet-total {
@apply bg-pill/8;
}
}
</style>
82 changes: 82 additions & 0 deletions lxl-web/src/lib/components/find/Node.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
<script lang="ts">
import { ShowLabelsOptions } from '$lib/types/decoratedData';
import Node from '$lib/components/find/Node.svelte';
import DecoratedData from '../DecoratedData.svelte';
import type { Facet } from '$lib/types/search';
import { page } from '$app/stores';
import { slide } from 'svelte/transition';
import BiChevronRight from '~icons/bi/chevron-right';
import BiChevronDown from '~icons/bi/chevron-down';

// Corresponds to a folder
// Implies there are nodes
let { expanded = $bindable(false), root: facet, locale } = $props();

function toggle() {
expanded = !expanded;
}

function isRootNode(f: Facet) {
console.log('Inside node', JSON.stringify(f));
return typeof f._children !== 'undefined';
}
</script>

<span class="flex gap-1">
{#if isRootNode(facet)}
<button class:expanded onclick={toggle}>
<span class="arrow transition-transform">
{#if expanded}
<BiChevronDown class="text-icon" />
{:else}
<BiChevronRight class="text-icon" />
{/if}
</span>
</button>
{/if}
<a
class="facet-link flex w-full items-end justify-between gap-2 no-underline"
href={facet.view['@id']}
>
<span class="overflow-hidden text-ellipsis whitespace-nowrap">
<span>
<DecoratedData data={facet.object} showLabels={ShowLabelsOptions.Never} />
{#if facet.discriminator}
<span class="text-sm text-secondary">({facet.discriminator})</span>
{/if}
</span>
</span>
{#if facet.totalItems > 0}
<span
class="facet-total mb-px rounded-sm bg-pill/4 px-1 text-sm text-secondary md:text-xs"
aria-label="{facet.totalItems} {$page.data.t('search.hits')}"
>
{facet.totalItems.toLocaleString(locale)}
</span>
{/if}
</a>
</span>

{#if expanded}
<ul transition:slide={{ duration: 300 }}>
{#each facet._children as child}
<Node root={child} {locale} />
{/each}
</ul>
{/if}

<style lang="postcss">
ul {
padding: 0.2em 0 0 1em;
margin: 0 0 0 0.5em;
list-style: none;
border-left: 1px solid #eee;
}

.facet-link:hover,
.facet-link:focus {
& .facet-total {
@apply bg-pill/8;
}
}
</style>
4 changes: 3 additions & 1 deletion lxl-web/src/lib/types/search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ export interface Facet {
object: DisplayDecorated;
str: string;
discriminator: string;
_children?: Facet[];
}

export interface MultiSelectFacet extends Facet {
Expand Down Expand Up @@ -110,11 +111,12 @@ interface Slice {
maxItems: number;
}

interface Observation {
export interface Observation {
totalItems: number;
view: Link;
object: FramedData;
_selected?: boolean;
_children?: Observation[];
}

export enum SearchOperators {
Expand Down
26 changes: 15 additions & 11 deletions lxl-web/src/lib/utils/search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ import {
type MultiSelectFacet,
type FacetGroup,
type ApiItemDebugInfo,
type ItemDebugInfo
type ItemDebugInfo,
type Observation
} from '$lib/types/search';

import { LxlLens } from '$lib/types/display';
Expand Down Expand Up @@ -233,19 +234,22 @@ function displayFacetGroups(
dimension: g.dimension,
maxItems: g.maxItems,
...('search' in g && { search: g.search }),
facets: g.observation.map((o) => {
return {
...('_selected' in o && { selected: o._selected }),
totalItems: o.totalItems,
view: replacePath(o.view, usePath),
object: displayUtil.lensAndFormat(o.object, LensType.Chip, locale),
str: toString(displayUtil.lensAndFormat(o.object, LensType.Chip, locale)) || '',
discriminator: getUriSlug(getAtPath(o.object, ['inScheme', JsonLd.ID], '')) || ''
};
})
facets: g.observation.map((o) => mapObservation(o))
};
});

function mapObservation(o: Observation) {
return {
...('_selected' in o && { selected: o._selected }),
totalItems: o.totalItems,
view: replacePath(o.view, usePath),
object: displayUtil.lensAndFormat(o.object, LensType.Chip, locale),
str: toString(displayUtil.lensAndFormat(o.object, LensType.Chip, locale)) || '',
discriminator: getUriSlug(getAtPath(o.object, ['inScheme', JsonLd.ID], '')) || '',
_children: o._children?.map((o) => mapObservation(o))
};
}

result.push(displayBoolFilters(view, displayUtil, locale, translate, usePath));

return result;
Expand Down
Loading