mirror of
https://github.com/immich-app/immich.git
synced 2025-03-11 02:23:09 -05:00
feat(web): metadata search
This commit is contained in:
parent
1b141d5ca9
commit
1d0df97c13
3 changed files with 96 additions and 1 deletions
|
@ -0,0 +1,19 @@
|
|||
<script lang="ts">
|
||||
interface Props {
|
||||
value: string;
|
||||
description: string;
|
||||
example: string;
|
||||
}
|
||||
|
||||
let { value, description, example }: Props = $props();
|
||||
</script>
|
||||
|
||||
<div class="flex justify-between bg-gray-100 p-2 w-full rounded-lg">
|
||||
<div class="">
|
||||
<p class="font-semibold text-[10px] text-primary">{description.toUpperCase()}</p>
|
||||
<code class="italic text-[12px]">{example}</code>
|
||||
</div>
|
||||
<code class="bg-immich-primary/15 px-2 rounded-lg flex place-items-center place-content-center font-bold"
|
||||
>{value}</code
|
||||
>
|
||||
</div>
|
|
@ -32,6 +32,7 @@
|
|||
let showFilter = $state(false);
|
||||
let isSearchSuggestions = $state(false);
|
||||
let selectedId: string | undefined = $state();
|
||||
let showMetadataSuggestions = $state(false);
|
||||
|
||||
const listboxId = generateId();
|
||||
|
||||
|
@ -128,6 +129,15 @@
|
|||
const onInput = () => {
|
||||
openDropdown();
|
||||
searchHistoryBox?.clearSelection();
|
||||
|
||||
const hasMetadataShortcut = value.startsWith('m:');
|
||||
|
||||
if (hasMetadataShortcut) {
|
||||
showMetadataSuggestions = true;
|
||||
isSearchSuggestions = true;
|
||||
} else {
|
||||
showMetadataSuggestions = false;
|
||||
}
|
||||
};
|
||||
|
||||
const openDropdown = () => {
|
||||
|
@ -204,6 +214,7 @@
|
|||
id={listboxId}
|
||||
searchQuery={value}
|
||||
isOpen={showSuggestions}
|
||||
{showMetadataSuggestions}
|
||||
onClearAllSearchTerms={clearAllSearchTerms}
|
||||
onClearSearchTerm={(searchTerm) => clearSearchTerm(searchTerm)}
|
||||
onSelectSearchTerm={(searchTerm) => handlePromiseError(onHistoryTermClick(searchTerm))}
|
||||
|
|
|
@ -2,15 +2,17 @@
|
|||
import Icon from '$lib/components/elements/icon.svelte';
|
||||
import { savedSearchTerms } from '$lib/stores/search.store';
|
||||
import { mdiMagnify, mdiClose } from '@mdi/js';
|
||||
import { fly } from 'svelte/transition';
|
||||
import { fade, fly } from 'svelte/transition';
|
||||
import { t } from 'svelte-i18n';
|
||||
import CircleIconButton from '$lib/components/elements/buttons/circle-icon-button.svelte';
|
||||
import MetadataSuggestionTip from '$lib/components/shared-components/search-bar/metadata-suggestion-tip.svelte';
|
||||
|
||||
interface Props {
|
||||
id: string;
|
||||
searchQuery?: string;
|
||||
isSearchSuggestions?: boolean;
|
||||
isOpen?: boolean;
|
||||
showMetadataSuggestions?: boolean;
|
||||
onSelectSearchTerm: (searchTerm: string) => void;
|
||||
onClearSearchTerm: (searchTerm: string) => void;
|
||||
onClearAllSearchTerms: () => void;
|
||||
|
@ -22,6 +24,7 @@
|
|||
searchQuery = '',
|
||||
isSearchSuggestions = $bindable(false),
|
||||
isOpen = false,
|
||||
showMetadataSuggestions = false,
|
||||
onSelectSearchTerm,
|
||||
onClearSearchTerm,
|
||||
onClearAllSearchTerms,
|
||||
|
@ -89,6 +92,57 @@
|
|||
}
|
||||
return `${id}-${index}`;
|
||||
};
|
||||
|
||||
type MetadataSuggestion = {
|
||||
value: string;
|
||||
description: string;
|
||||
example: string;
|
||||
};
|
||||
|
||||
let metadataExample: Array<MetadataSuggestion> = [
|
||||
{ value: 'm:name:', description: 'File Name', example: 'm:name:img123.jpg' },
|
||||
{ value: 'm:ctx', description: 'Context', example: 'm:ctx:sunrise on the beach' },
|
||||
{
|
||||
value: 'm:desc:',
|
||||
description: 'Description',
|
||||
example: 'm:desc:a table full of cats',
|
||||
},
|
||||
{
|
||||
value: 'm:orien:',
|
||||
description: 'Orientation',
|
||||
example: 'm:orientation:landscape',
|
||||
},
|
||||
{
|
||||
value: 'm:width:',
|
||||
description: 'Media width',
|
||||
example: 'm:width:1920',
|
||||
},
|
||||
{
|
||||
value: 'm:height:',
|
||||
description: 'Media height',
|
||||
example: 'm:height:1080',
|
||||
},
|
||||
{
|
||||
value: 'm:size:',
|
||||
description: 'File size',
|
||||
example: 'm:size:1MB, m:size:1GB',
|
||||
},
|
||||
{
|
||||
value: 'm:date-from:',
|
||||
description: 'Date from',
|
||||
example: 'm:date-from:2020-01-01',
|
||||
},
|
||||
{
|
||||
value: 'm:date-to:',
|
||||
description: 'Date to',
|
||||
example: 'm:date-to:2024-12-31',
|
||||
},
|
||||
{
|
||||
value: 'm:rating:',
|
||||
description: 'Rating',
|
||||
example: 'm:rating:5',
|
||||
},
|
||||
];
|
||||
</script>
|
||||
|
||||
<div role="listbox" {id} aria-label={$t('recent_searches')} bind:this={element}>
|
||||
|
@ -97,6 +151,17 @@
|
|||
transition:fly={{ y: 25, duration: 150 }}
|
||||
class="absolute w-full rounded-b-3xl border-2 border-t-0 border-gray-200 bg-white pb-5 shadow-2xl transition-all dark:border-gray-700 dark:bg-immich-dark-gray dark:text-gray-300"
|
||||
>
|
||||
{#if showMetadataSuggestions}
|
||||
<div in:fly={{ x: -50 }} class="flex items-center justify-between px-5 pt-5 text-xs">
|
||||
<p class="py-2" aria-hidden={true}>{'searchable metadata'.toUpperCase()}</p>
|
||||
</div>
|
||||
<div in:fly={{ x: 50 }} class="px-5 grid grid-rows-3 grid-cols-2 gap-1 justify-items-start text-xs mt-1">
|
||||
{#each metadataExample as example}
|
||||
<MetadataSuggestionTip value={example.value} description={example.description} example={example.example} />
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div class="flex items-center justify-between px-5 pt-5 text-xs">
|
||||
<p class="py-2" aria-hidden={true}>{$t('recent_searches').toUpperCase()}</p>
|
||||
{#if showClearAll}
|
||||
|
|
Loading…
Add table
Reference in a new issue