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

Add search function for milestone components #87

Merged
merged 12 commits into from
Sep 25, 2024
75 changes: 63 additions & 12 deletions frontend/src/lib/components/DataDisplay/GalleryDisplay.svelte
Original file line number Diff line number Diff line change
@@ -1,21 +1,33 @@
<script lang="ts">
import { Gallery, Heading, Search } from 'flowbite-svelte';

export let filterData = (data, col, searchTerm) => {
if (searchTerm === '') {
return data;
} else {
return data.filter((item) => item[col].toLowerCase().includes(searchTerm.toLowerCase()));
}
};
import { Button, Dropdown, DropdownItem, Gallery, Heading, Search } from 'flowbite-svelte';
import { ChevronDownOutline } from 'flowbite-svelte-icons';
import { tick } from 'svelte';

export let data;
export let header: string | null = null;
export let itemComponent;
export let withSearch = true;
export let searchableCol = '';
export let componentProps;
export let searchPlaceHolder = 'Durchsuchen';

export let searchData = [
{
label: 'Alle',
placeholder: 'Durchsuchen',
filterFunction: (data: any[], col: any, searchTerm: string): any[] => {
if (searchTerm === '') {
return data;
} else {
return data.filter((item) => item[col].toLowerCase().includes(searchTerm.toLowerCase()));
}
}
}
];

let searchCategory: string = searchData[0].label;
let searchPlaceHolder: string = searchData[0].placeholder;
let filterData = searchData[0].filterFunction;
let dropdownOpen: boolean = false;

// dynamic statements
let searchTerm = '';
Expand All @@ -41,8 +53,47 @@
{/if}

{#if withSearch}
<form class="m-2 w-full p-4">
<Search size="md" placeholder={searchPlaceHolder} bind:value={searchTerm} />
<form class="m-2 flex w-full rounded p-4">
{#if searchData.length > 1}
<!-- after example: https://flowbite-svelte.com/docs/forms/search-input#Search_with_dropdown -->
<div class="relative">
<Button
class="h-full whitespace-nowrap rounded-e-none border border-e-0 border-primary-700"
>
{searchCategory}
<ChevronDownOutline class="ms-2.5 h-2.5 w-2.5" />
</Button>
<Dropdown classContainer="flex w-auto" bind:open={dropdownOpen}>
{#each searchData as { label, placeholder, filterFunction }}
<DropdownItem
on:click={async () => {
searchCategory = label;
searchPlaceHolder = placeholder;
filterData = filterFunction;
dropdownOpen = false;
await tick();
}}
class={searchCategory === label ? 'underline' : ''}
>
{label}
</DropdownItem>
{/each}
</Dropdown>
</div>
<Search
class="rounded-e rounded-s-none py-2.5"
size="md"
placeholder={searchPlaceHolder}
bind:value={searchTerm}
/>
{:else}
<Search
size="md"
class="rounded py-2.5"
placeholder={searchPlaceHolder}
bind:value={searchTerm}
/>
{/if}
</form>
{/if}

Expand Down
22 changes: 3 additions & 19 deletions frontend/src/lib/components/MilestoneGroup.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,10 @@
import Breadcrumbs from '$lib/components/Breadcrumbs.svelte';
import CardDisplay from '$lib/components/DataDisplay/CardDisplay.svelte';
import GalleryDisplay from '$lib/components/DataDisplay/GalleryDisplay.svelte';

export let breadcrumbdata: any[] = [];
export let milestonedata: any[] = [];

function filterData(data: object[], dummy: any, key: string): object[] {
if (key === '') {
return data;
} else {
return data.filter((item) => {
// button label contains info about completion status => use for search
if (key === completeKey) {
return item.progress === 1;
} else if (key === incompleteKey) {
return item.progress < 1;
} else {
return item.header.toLowerCase().includes(key.toLowerCase());
}
});
}
}
export let searchData: any[] = [];

// FIXME:styling has no business being here... not sure where to put it though given thatparts of it are data dependent
export function createStyle(data) {
Expand Down Expand Up @@ -54,9 +39,8 @@
itemComponent={CardDisplay}
searchableCol={'header'}
componentProps={createStyle(milestonedata)}
searchPlaceHolder={`Nach Status (${completeKey}/${incompleteKey}) oder Titel durchsuchen`}
withSearch={true}
{filterData}
{searchData}
/>
</div>
</div>
23 changes: 4 additions & 19 deletions frontend/src/lib/components/MilestoneOverview.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,6 @@
import GalleryDisplay from '$lib/components/DataDisplay/GalleryDisplay.svelte';
import { CheckCircleSolid, ExclamationCircleSolid } from 'flowbite-svelte-icons';

function filterData(data: object[], dummy: any, key: string): object[] {
if (key === '') {
return data;
} else {
return data.filter((item) => {
// button label contains info about completion status => use for search
if (key === completeKey) {
return item.complete === true;
} else if (key === incompleteKey) {
return item.complete === false;
} else {
return item.header.toLowerCase().includes(key.toLowerCase());
}
});
}
}

// FIXME: this must go eventually. Either must happen in the backend or there
// should be in a refactored version of the card component
function convertData(data: object[]): object[] {
Expand All @@ -30,6 +13,8 @@
header: item.title,
href: `${base}/milestone`, // hardcoded link for the moment
complete: item.answer !== null,
summary: item.desc,
answer: item.answer,
auxilliary: item.answer !== null ? CheckCircleSolid : ExclamationCircleSolid
};
});
Expand All @@ -38,6 +23,7 @@
const completeKey = 'fertig';
const incompleteKey = 'unfertig';
export let breadcrumbdata: object[] = [];
export let searchData: any[];
export let data: object[] = [];
const rawdata = convertData(data).sort((a, b) => a.complete - b.complete); // FIXME: the convert step should not be here and will be handeled backend-side
</script>
Expand All @@ -60,9 +46,8 @@
}
};
})}
searchPlaceHolder={`Nach Status (${completeKey}/${incompleteKey}) oder Titel durchsuchen`}
withSearch={true}
{filterData}
{searchData}
/>
</div>
</div>
Loading