Skip to content

Commit

Permalink
Merge pull request #4 from gdi-be/search
Browse files Browse the repository at this point in the history
Introduces `MetadataSearchField`
  • Loading branch information
KaiVolland authored Dec 17, 2024
2 parents 42c4de8 + 07833df commit cc536da
Show file tree
Hide file tree
Showing 10 changed files with 188 additions and 76 deletions.
Binary file modified bun.lockb
Binary file not shown.
24 changes: 12 additions & 12 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
"mdsvex": "^0.12.3",
"prettier": "^3.3.3",
"prettier-plugin-svelte": "^3.2.8",
"smui-theme": "^8.0.0-beta.0",
"smui-theme": "^8.0.0-beta.2",
"svelte": "^5.5.3",
"svelte-adapter-bun": "^0.5.2",
"svelte-check": "^4.1.1",
Expand All @@ -40,17 +40,17 @@
"vite": "^5.4.11"
},
"dependencies": {
"@smui-extra/autocomplete": "^8.0.0-beta.0",
"@smui-extra/chip-input": "^8.0.0-beta.0",
"@smui/button": "^8.0.0-beta.0",
"@smui/card": "^8.0.0-beta.0",
"@smui/dialog": "^8.0.0-beta.0",
"@smui/form-field": "^8.0.0-beta.0",
"@smui/icon-button": "^8.0.0-beta.0",
"@smui/select": "^8.0.0-beta.0",
"@smui/switch": "^8.0.0-beta.0",
"@smui/textfield": "^8.0.0-beta.0",
"@smui/tooltip": "^8.0.0-beta.0",
"@smui-extra/autocomplete": "^8.0.0-beta.2",
"@smui-extra/chip-input": "^8.0.0-beta.2",
"@smui/button": "^8.0.0-beta.2",
"@smui/card": "^8.0.0-beta.2",
"@smui/dialog": "^8.0.0-beta.2",
"@smui/form-field": "^8.0.0-beta.2",
"@smui/icon-button": "^8.0.0-beta.2",
"@smui/select": "^8.0.0-beta.2",
"@smui/switch": "^8.0.0-beta.2",
"@smui/textfield": "^8.0.0-beta.2",
"@smui/tooltip": "^8.0.0-beta.2",
"cookie": "^1.0.1",
"jsonwebtoken": "^9.0.2",
"loggisch": "^0.0.1",
Expand Down
47 changes: 39 additions & 8 deletions src/lib/api/metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,21 +75,45 @@ export const getMetadataCollectionByMetadataId = async (metadataId: string, toke
return await response.json();
}

export const searchForMetadata = async (token: string, searchTerm: string, pagingOpts = defaultPage): Promise<SearchResponse<IsoMetadata>> => {
if (!token) {
log.error("No token provided.");
return Promise.reject(new Error("No token provided."));
}

const url: URL = new URL(`${env.BACKEND_URL}/metadata/iso/search`);
url.searchParams.append('searchTerm', searchTerm);

if (pagingOpts) {
const offset = pagingOpts.page * pagingOpts.size;
const limit = pagingOpts.size;
url.searchParams.append('offset', offset.toString());
url.searchParams.append('limit', limit.toString());
}

const response = await fetch(url, {
headers: new Headers({
Authorization: `Bearer ${token}`,
'accept': 'application/json'
})
});

if (!response.ok) {
throw new Error(`HTTP error status: ${response.status}`);
}

const data = await response.json();

return data;
}

export type UpdateProps = {
metadataId: string;
metadataType: MetadataType;
key: string;
value: unknown;
token: string;
}

export type CreateProps = {
token: string;
title: string;
metadataProfile: MetadataProfile;
cloneMetadataId?: MetadataId;
}

export const updateDataValue = async ({
metadataId,
metadataType,
Expand Down Expand Up @@ -125,6 +149,13 @@ export const updateDataValue = async ({
return await response.json();
}

export type CreateProps = {
token: string;
title: string;
metadataProfile: MetadataProfile;
cloneMetadataId?: MetadataId;
}

export const createMetadataCollection = async ({
token,
title,
Expand Down
2 changes: 1 addition & 1 deletion src/lib/components/Form/Inputs/AutoCompleteInput.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,5 @@
{label}
bind:value
options={options}
getOptionLabel={(option: Option) => option?.label}
getOptionLabel={(option: Option) => option?.label as string || ''}
/>
8 changes: 4 additions & 4 deletions src/lib/components/Form/Inputs/BooleanInput.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@
} = config;
</script>

<FormField
bind:value
>
<Switch/>
<FormField>
<Switch
bind:checked={value}
/>
{#snippet label()}
{inputLabel}
{/snippet}
Expand Down
1 change: 0 additions & 1 deletion src/lib/components/Form/Inputs/DateInput.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
{label}
id={key}
input$name={key}
name={key}
bind:value
>
{#snippet leadingIcon()}
Expand Down
56 changes: 40 additions & 16 deletions src/lib/components/MetadataSearchField.svelte
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
<script lang="ts">
import Autocomplete from "@smui-extra/autocomplete";
import { Text } from "@smui/list";
import type { MetadataId } from "$lib/models/metadata";
import type { IsoMetadata } from "$lib/models/metadata";
import { type Option } from "$lib/models/form";
export type MetadataSearchFieldProps = {
value: MetadataId | undefined;
value: Option | undefined;
label?: string;
};
Expand All @@ -14,32 +14,45 @@
label = 'Suche nach Metadaten'
}: MetadataSearchFieldProps = $props();
let text = $state('');
async function searchItems(input: string) {
if (input === '') {
return [];
}
// TODO: implement search
return [{
key: 'a10f5c2b-0a31-3a9a-99b0-db903996b5c5',
label: 'Straßenparkplätze'
}, {
key: '886873a2-813e-33a6-bad4-f80364f94e24',
label: 'Gebäudegeschosse'
}, {
key: 'c54eebcb-9eae-3b60-b112-bcb291eeddc7',
label: 'Pflegeeinrichtungen'
}]
const url = new URL('/metadata/search', window.location.origin);
url.searchParams.append('query', input);
const response = await fetch(url);
if (response.ok) {
const data = await response.json();
return data.map((isoMetadata: IsoMetadata) => ({
key: isoMetadata.metadataId,
label: isoMetadata.title
}));
}
return [];
}
const splitLabel = (l: string) => {
const regex = new RegExp(`(${text})`, 'gi');
const parts = l.split(regex);
return parts;
};
</script>

<Autocomplete
class="metadata-search-field"
search={searchItems}
bind:value
bind:text
getOptionLabel={(option: Option) => {
if (!option) return '';
return option.label;
return option.label as string || '';
}}
showMenuWithNoInput={false}
{label}
Expand All @@ -51,9 +64,20 @@
{#snippet noMatches()}
<Text>No results found</Text>
{/snippet}
</Autocomplete>

<style lang="scss">
{#snippet match(item)}
<Text>
{#each splitLabel(item.label) as part}
{#if part.toLowerCase() === text.toLowerCase()}
<strong>{part}</strong>
{:else}
{part}
{/if}
{/each}
</Text>
{/snippet}

</Autocomplete>

<style lang="scss">
</style>
22 changes: 19 additions & 3 deletions src/routes/metadata/+page.svelte
Original file line number Diff line number Diff line change
@@ -1,20 +1,30 @@
<script lang="ts">
import { goto } from "$app/navigation";
import MetadataCard from "../../lib/components/MetadataCard.svelte";
import Pagination from "../../lib/components/Pagination.svelte";
import MetadataCard from "$lib/components/MetadataCard.svelte";
import MetadataSearchField from "$lib/components/MetadataSearchField.svelte";
import Pagination from "$lib/components/Pagination.svelte";
import { Icon } from "@smui/button";
import Card, { PrimaryAction } from '@smui/card';
import type { Option } from "$lib/models/form.js";
let { data } = $props();
const metadata = $derived(data.metadata.content);
const pageable = $derived(data.metadata);
let searchValue = $state<Option>()
$effect(() => {
if (searchValue) {
goto(`/metadata/${searchValue.key}`);
}
});
</script>

<div class="metadata-overview">
<div class="metadata-toolbar">
<h1>Metadaten</h1>
<MetadataSearchField bind:value={searchValue}/>
</div>
<div class="metadata-list">
<Card class="create-card">
Expand Down Expand Up @@ -47,6 +57,12 @@
flex: 0 0 auto;
}
.metadata-toolbar {
:global(.metadata-search-field .mdc-text-field) {
width: 600px;
}
}
.metadata-list {
flex: 1;
padding: 1em;
Expand Down
79 changes: 48 additions & 31 deletions src/routes/metadata/create/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@
type MetadataProfile
} from "$lib/models/metadata";
import Button from "@smui/button";
import Select, { Option } from "@smui/select";
import Select, { Option as SelectOption } from "@smui/select";
import Textfield from "@smui/textfield";
import log from "loggisch";
import MetadataSearchField from "$lib/components/MetadataSearchField.svelte";
import type { Option } from "$lib/models/form";
import Card, { Content } from "@smui/card";
let title = $state<string>('');
let metadataProfile = $state<MetadataProfile>('ISO');
Expand Down Expand Up @@ -38,50 +40,65 @@
goto(`/metadata/${metadataId}`);
} else {
log.error('No metadataId in response');
console.log(metadataId);
}
}
};
</script>

<div>
<h1>Neuerfassung</h1>
<Textfield
bind:value={title}
label="Titel"
required
/>
<Select
bind:value={metadataProfile}
label="Vorlage"
required
>
<Option value="ISO">ISO</Option>
<Option value="INSPIRE_HARMONISED">Inspire (harmonisiert)</Option>
<Option value="INSPIRE_IDENTIFIED">Inspire (identified)</Option>
</Select>
<MetadataSearchField
bind:value={cloneMetadataId}
label="Metadaten kopieren"
/>
<Button
variant="raised"
onclick={onCreateClick}
disabled={!allFieldsValid}
>
Metadaten anlegen
</Button>
<div class="create-metadata">
<Card>
<Content>
<h1>Neuerfassung</h1>
<Textfield
bind:value={title}
label="Titel"
required
/>
<Select
bind:value={metadataProfile}
label="Vorlage"
required
>
<SelectOption value="ISO">ISO</SelectOption>
<SelectOption value="INSPIRE_HARMONISED">Inspire (harmonisiert)</SelectOption>
<SelectOption value="INSPIRE_IDENTIFIED">Inspire (identified)</SelectOption>
</Select>
<MetadataSearchField
bind:value={cloneMetadataId}
label="Metadaten kopieren"
/>
<Button
variant="raised"
onclick={onCreateClick}
disabled={!allFieldsValid}
>
Metadaten anlegen
</Button>
</Content>
</Card>
</div>

<style lang="scss">
div {
.create-metadata {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100%;
text-align: center;
gap: 1em
gap: 1em;
:global(.smui-card__content) {
display: flex;
flex-direction: column;
align-items: center;
gap: 1em;
}
:global(.mdc-text-field),
:global(.mdc-select) {
width: 25em;
}
}
</style>
Loading

0 comments on commit cc536da

Please sign in to comment.