mirror of
https://github.com/immich-app/immich.git
synced 2025-07-31 15:08:44 -04:00
feat: adds option to search only for untagged assets (#19730)
Co-authored-by: SkwalExe <skwal@skwal.net>
This commit is contained in:
parent
818bdde317
commit
f778adea92
@ -1886,6 +1886,7 @@
|
|||||||
"unselect_all_in": "Unselect all in {group}",
|
"unselect_all_in": "Unselect all in {group}",
|
||||||
"unstack": "Un-stack",
|
"unstack": "Un-stack",
|
||||||
"unstacked_assets_count": "Un-stacked {count, plural, one {# asset} other {# assets}}",
|
"unstacked_assets_count": "Un-stacked {count, plural, one {# asset} other {# assets}}",
|
||||||
|
"untagged": "Untagged",
|
||||||
"up_next": "Up next",
|
"up_next": "Up next",
|
||||||
"updated_at": "Updated",
|
"updated_at": "Updated",
|
||||||
"updated_password": "Updated password",
|
"updated_password": "Updated password",
|
||||||
|
@ -241,7 +241,7 @@ class MetadataSearchDto {
|
|||||||
|
|
||||||
String? state;
|
String? state;
|
||||||
|
|
||||||
List<String> tagIds;
|
List<String>? tagIds;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Please note: This property should have been non-nullable! Since the specification file
|
/// Please note: This property should have been non-nullable! Since the specification file
|
||||||
@ -425,7 +425,7 @@ class MetadataSearchDto {
|
|||||||
(rating == null ? 0 : rating!.hashCode) +
|
(rating == null ? 0 : rating!.hashCode) +
|
||||||
(size == null ? 0 : size!.hashCode) +
|
(size == null ? 0 : size!.hashCode) +
|
||||||
(state == null ? 0 : state!.hashCode) +
|
(state == null ? 0 : state!.hashCode) +
|
||||||
(tagIds.hashCode) +
|
(tagIds == null ? 0 : tagIds!.hashCode) +
|
||||||
(takenAfter == null ? 0 : takenAfter!.hashCode) +
|
(takenAfter == null ? 0 : takenAfter!.hashCode) +
|
||||||
(takenBefore == null ? 0 : takenBefore!.hashCode) +
|
(takenBefore == null ? 0 : takenBefore!.hashCode) +
|
||||||
(thumbnailPath == null ? 0 : thumbnailPath!.hashCode) +
|
(thumbnailPath == null ? 0 : thumbnailPath!.hashCode) +
|
||||||
@ -578,7 +578,11 @@ class MetadataSearchDto {
|
|||||||
} else {
|
} else {
|
||||||
// json[r'state'] = null;
|
// json[r'state'] = null;
|
||||||
}
|
}
|
||||||
|
if (this.tagIds != null) {
|
||||||
json[r'tagIds'] = this.tagIds;
|
json[r'tagIds'] = this.tagIds;
|
||||||
|
} else {
|
||||||
|
// json[r'tagIds'] = null;
|
||||||
|
}
|
||||||
if (this.takenAfter != null) {
|
if (this.takenAfter != null) {
|
||||||
json[r'takenAfter'] = this.takenAfter!.toUtc().toIso8601String();
|
json[r'takenAfter'] = this.takenAfter!.toUtc().toIso8601String();
|
||||||
} else {
|
} else {
|
||||||
|
8
mobile/openapi/lib/model/random_search_dto.dart
generated
8
mobile/openapi/lib/model/random_search_dto.dart
generated
@ -155,7 +155,7 @@ class RandomSearchDto {
|
|||||||
|
|
||||||
String? state;
|
String? state;
|
||||||
|
|
||||||
List<String> tagIds;
|
List<String>? tagIds;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Please note: This property should have been non-nullable! Since the specification file
|
/// Please note: This property should have been non-nullable! Since the specification file
|
||||||
@ -310,7 +310,7 @@ class RandomSearchDto {
|
|||||||
(rating == null ? 0 : rating!.hashCode) +
|
(rating == null ? 0 : rating!.hashCode) +
|
||||||
(size == null ? 0 : size!.hashCode) +
|
(size == null ? 0 : size!.hashCode) +
|
||||||
(state == null ? 0 : state!.hashCode) +
|
(state == null ? 0 : state!.hashCode) +
|
||||||
(tagIds.hashCode) +
|
(tagIds == null ? 0 : tagIds!.hashCode) +
|
||||||
(takenAfter == null ? 0 : takenAfter!.hashCode) +
|
(takenAfter == null ? 0 : takenAfter!.hashCode) +
|
||||||
(takenBefore == null ? 0 : takenBefore!.hashCode) +
|
(takenBefore == null ? 0 : takenBefore!.hashCode) +
|
||||||
(trashedAfter == null ? 0 : trashedAfter!.hashCode) +
|
(trashedAfter == null ? 0 : trashedAfter!.hashCode) +
|
||||||
@ -416,7 +416,11 @@ class RandomSearchDto {
|
|||||||
} else {
|
} else {
|
||||||
// json[r'state'] = null;
|
// json[r'state'] = null;
|
||||||
}
|
}
|
||||||
|
if (this.tagIds != null) {
|
||||||
json[r'tagIds'] = this.tagIds;
|
json[r'tagIds'] = this.tagIds;
|
||||||
|
} else {
|
||||||
|
// json[r'tagIds'] = null;
|
||||||
|
}
|
||||||
if (this.takenAfter != null) {
|
if (this.takenAfter != null) {
|
||||||
json[r'takenAfter'] = this.takenAfter!.toUtc().toIso8601String();
|
json[r'takenAfter'] = this.takenAfter!.toUtc().toIso8601String();
|
||||||
} else {
|
} else {
|
||||||
|
8
mobile/openapi/lib/model/smart_search_dto.dart
generated
8
mobile/openapi/lib/model/smart_search_dto.dart
generated
@ -175,7 +175,7 @@ class SmartSearchDto {
|
|||||||
|
|
||||||
String? state;
|
String? state;
|
||||||
|
|
||||||
List<String> tagIds;
|
List<String>? tagIds;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Please note: This property should have been non-nullable! Since the specification file
|
/// Please note: This property should have been non-nullable! Since the specification file
|
||||||
@ -318,7 +318,7 @@ class SmartSearchDto {
|
|||||||
(rating == null ? 0 : rating!.hashCode) +
|
(rating == null ? 0 : rating!.hashCode) +
|
||||||
(size == null ? 0 : size!.hashCode) +
|
(size == null ? 0 : size!.hashCode) +
|
||||||
(state == null ? 0 : state!.hashCode) +
|
(state == null ? 0 : state!.hashCode) +
|
||||||
(tagIds.hashCode) +
|
(tagIds == null ? 0 : tagIds!.hashCode) +
|
||||||
(takenAfter == null ? 0 : takenAfter!.hashCode) +
|
(takenAfter == null ? 0 : takenAfter!.hashCode) +
|
||||||
(takenBefore == null ? 0 : takenBefore!.hashCode) +
|
(takenBefore == null ? 0 : takenBefore!.hashCode) +
|
||||||
(trashedAfter == null ? 0 : trashedAfter!.hashCode) +
|
(trashedAfter == null ? 0 : trashedAfter!.hashCode) +
|
||||||
@ -433,7 +433,11 @@ class SmartSearchDto {
|
|||||||
} else {
|
} else {
|
||||||
// json[r'state'] = null;
|
// json[r'state'] = null;
|
||||||
}
|
}
|
||||||
|
if (this.tagIds != null) {
|
||||||
json[r'tagIds'] = this.tagIds;
|
json[r'tagIds'] = this.tagIds;
|
||||||
|
} else {
|
||||||
|
// json[r'tagIds'] = null;
|
||||||
|
}
|
||||||
if (this.takenAfter != null) {
|
if (this.takenAfter != null) {
|
||||||
json[r'takenAfter'] = this.takenAfter!.toUtc().toIso8601String();
|
json[r'takenAfter'] = this.takenAfter!.toUtc().toIso8601String();
|
||||||
} else {
|
} else {
|
||||||
|
@ -149,7 +149,7 @@ class StatisticsSearchDto {
|
|||||||
|
|
||||||
String? state;
|
String? state;
|
||||||
|
|
||||||
List<String> tagIds;
|
List<String>? tagIds;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Please note: This property should have been non-nullable! Since the specification file
|
/// Please note: This property should have been non-nullable! Since the specification file
|
||||||
@ -268,7 +268,7 @@ class StatisticsSearchDto {
|
|||||||
(personIds.hashCode) +
|
(personIds.hashCode) +
|
||||||
(rating == null ? 0 : rating!.hashCode) +
|
(rating == null ? 0 : rating!.hashCode) +
|
||||||
(state == null ? 0 : state!.hashCode) +
|
(state == null ? 0 : state!.hashCode) +
|
||||||
(tagIds.hashCode) +
|
(tagIds == null ? 0 : tagIds!.hashCode) +
|
||||||
(takenAfter == null ? 0 : takenAfter!.hashCode) +
|
(takenAfter == null ? 0 : takenAfter!.hashCode) +
|
||||||
(takenBefore == null ? 0 : takenBefore!.hashCode) +
|
(takenBefore == null ? 0 : takenBefore!.hashCode) +
|
||||||
(trashedAfter == null ? 0 : trashedAfter!.hashCode) +
|
(trashedAfter == null ? 0 : trashedAfter!.hashCode) +
|
||||||
@ -370,7 +370,11 @@ class StatisticsSearchDto {
|
|||||||
} else {
|
} else {
|
||||||
// json[r'state'] = null;
|
// json[r'state'] = null;
|
||||||
}
|
}
|
||||||
|
if (this.tagIds != null) {
|
||||||
json[r'tagIds'] = this.tagIds;
|
json[r'tagIds'] = this.tagIds;
|
||||||
|
} else {
|
||||||
|
// json[r'tagIds'] = null;
|
||||||
|
}
|
||||||
if (this.takenAfter != null) {
|
if (this.takenAfter != null) {
|
||||||
json[r'takenAfter'] = this.takenAfter!.toUtc().toIso8601String();
|
json[r'takenAfter'] = this.takenAfter!.toUtc().toIso8601String();
|
||||||
} else {
|
} else {
|
||||||
|
@ -11203,6 +11203,7 @@
|
|||||||
"format": "uuid",
|
"format": "uuid",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"nullable": true,
|
||||||
"type": "array"
|
"type": "array"
|
||||||
},
|
},
|
||||||
"takenAfter": {
|
"takenAfter": {
|
||||||
@ -12092,6 +12093,7 @@
|
|||||||
"format": "uuid",
|
"format": "uuid",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"nullable": true,
|
||||||
"type": "array"
|
"type": "array"
|
||||||
},
|
},
|
||||||
"takenAfter": {
|
"takenAfter": {
|
||||||
@ -13157,6 +13159,7 @@
|
|||||||
"format": "uuid",
|
"format": "uuid",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"nullable": true,
|
||||||
"type": "array"
|
"type": "array"
|
||||||
},
|
},
|
||||||
"takenAfter": {
|
"takenAfter": {
|
||||||
@ -13348,6 +13351,7 @@
|
|||||||
"format": "uuid",
|
"format": "uuid",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"nullable": true,
|
||||||
"type": "array"
|
"type": "array"
|
||||||
},
|
},
|
||||||
"takenAfter": {
|
"takenAfter": {
|
||||||
|
@ -889,7 +889,7 @@ export type MetadataSearchDto = {
|
|||||||
rating?: number;
|
rating?: number;
|
||||||
size?: number;
|
size?: number;
|
||||||
state?: string | null;
|
state?: string | null;
|
||||||
tagIds?: string[];
|
tagIds?: string[] | null;
|
||||||
takenAfter?: string;
|
takenAfter?: string;
|
||||||
takenBefore?: string;
|
takenBefore?: string;
|
||||||
thumbnailPath?: string;
|
thumbnailPath?: string;
|
||||||
@ -956,7 +956,7 @@ export type RandomSearchDto = {
|
|||||||
rating?: number;
|
rating?: number;
|
||||||
size?: number;
|
size?: number;
|
||||||
state?: string | null;
|
state?: string | null;
|
||||||
tagIds?: string[];
|
tagIds?: string[] | null;
|
||||||
takenAfter?: string;
|
takenAfter?: string;
|
||||||
takenBefore?: string;
|
takenBefore?: string;
|
||||||
trashedAfter?: string;
|
trashedAfter?: string;
|
||||||
@ -993,7 +993,7 @@ export type SmartSearchDto = {
|
|||||||
rating?: number;
|
rating?: number;
|
||||||
size?: number;
|
size?: number;
|
||||||
state?: string | null;
|
state?: string | null;
|
||||||
tagIds?: string[];
|
tagIds?: string[] | null;
|
||||||
takenAfter?: string;
|
takenAfter?: string;
|
||||||
takenBefore?: string;
|
takenBefore?: string;
|
||||||
trashedAfter?: string;
|
trashedAfter?: string;
|
||||||
@ -1025,7 +1025,7 @@ export type StatisticsSearchDto = {
|
|||||||
personIds?: string[];
|
personIds?: string[];
|
||||||
rating?: number;
|
rating?: number;
|
||||||
state?: string | null;
|
state?: string | null;
|
||||||
tagIds?: string[];
|
tagIds?: string[] | null;
|
||||||
takenAfter?: string;
|
takenAfter?: string;
|
||||||
takenBefore?: string;
|
takenBefore?: string;
|
||||||
trashedAfter?: string;
|
trashedAfter?: string;
|
||||||
|
@ -92,8 +92,8 @@ class BaseSearchDto {
|
|||||||
@ValidateUUID({ each: true, optional: true })
|
@ValidateUUID({ each: true, optional: true })
|
||||||
personIds?: string[];
|
personIds?: string[];
|
||||||
|
|
||||||
@ValidateUUID({ each: true, optional: true })
|
@ValidateUUID({ each: true, optional: true, nullable: true })
|
||||||
tagIds?: string[];
|
tagIds?: string[] | null;
|
||||||
|
|
||||||
@ValidateUUID({ each: true, optional: true })
|
@ValidateUUID({ each: true, optional: true })
|
||||||
albumIds?: string[];
|
albumIds?: string[];
|
||||||
|
@ -89,7 +89,7 @@ export interface SearchPeopleOptions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface SearchTagOptions {
|
export interface SearchTagOptions {
|
||||||
tagIds?: string[];
|
tagIds?: string[] | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SearchAlbumOptions {
|
export interface SearchAlbumOptions {
|
||||||
|
@ -307,6 +307,9 @@ export function searchAssetBuilder(kysely: Kysely<DB>, options: AssetSearchBuild
|
|||||||
.where('assets.visibility', '=', visibility)
|
.where('assets.visibility', '=', visibility)
|
||||||
.$if(!!options.albumIds && options.albumIds.length > 0, (qb) => inAlbums(qb, options.albumIds!))
|
.$if(!!options.albumIds && options.albumIds.length > 0, (qb) => inAlbums(qb, options.albumIds!))
|
||||||
.$if(!!options.tagIds && options.tagIds.length > 0, (qb) => hasTags(qb, options.tagIds!))
|
.$if(!!options.tagIds && options.tagIds.length > 0, (qb) => hasTags(qb, options.tagIds!))
|
||||||
|
.$if(options.tagIds === null, (qb) =>
|
||||||
|
qb.where((eb) => eb.not(eb.exists((eb) => eb.selectFrom('tag_asset').whereRef('assetsId', '=', 'assets.id')))),
|
||||||
|
)
|
||||||
.$if(!!options.personIds && options.personIds.length > 0, (qb) => hasPeople(qb, options.personIds!))
|
.$if(!!options.personIds && options.personIds.length > 0, (qb) => hasPeople(qb, options.personIds!))
|
||||||
.$if(!!options.createdBefore, (qb) => qb.where('assets.createdAt', '<=', options.createdBefore!))
|
.$if(!!options.createdBefore, (qb) => qb.where('assets.createdAt', '<=', options.createdBefore!))
|
||||||
.$if(!!options.createdAfter, (qb) => qb.where('assets.createdAt', '>=', options.createdAfter!))
|
.$if(!!options.createdAfter, (qb) => qb.where('assets.createdAt', '>=', options.createdAfter!))
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
label: string;
|
label: string;
|
||||||
|
disabled?: boolean;
|
||||||
hideLabel?: boolean;
|
hideLabel?: boolean;
|
||||||
options?: ComboBoxOption[];
|
options?: ComboBoxOption[];
|
||||||
selectedOption?: ComboBoxOption | undefined;
|
selectedOption?: ComboBoxOption | undefined;
|
||||||
@ -52,6 +53,7 @@
|
|||||||
let {
|
let {
|
||||||
label,
|
label,
|
||||||
hideLabel = false,
|
hideLabel = false,
|
||||||
|
disabled = false,
|
||||||
options = [],
|
options = [],
|
||||||
selectedOption = $bindable(),
|
selectedOption = $bindable(),
|
||||||
placeholder = '',
|
placeholder = '',
|
||||||
@ -275,6 +277,7 @@
|
|||||||
|
|
||||||
<input
|
<input
|
||||||
{placeholder}
|
{placeholder}
|
||||||
|
{disabled}
|
||||||
aria-activedescendant={selectedIndex || selectedIndex === 0 ? `${listboxId}-${selectedIndex}` : ''}
|
aria-activedescendant={selectedIndex || selectedIndex === 0 ? `${listboxId}-${selectedIndex}` : ''}
|
||||||
aria-autocomplete="list"
|
aria-autocomplete="list"
|
||||||
aria-controls={listboxId}
|
aria-controls={listboxId}
|
||||||
|
@ -3,13 +3,14 @@
|
|||||||
import Combobox, { type ComboBoxOption } from '$lib/components/shared-components/combobox.svelte';
|
import Combobox, { type ComboBoxOption } from '$lib/components/shared-components/combobox.svelte';
|
||||||
import { preferences } from '$lib/stores/user.store';
|
import { preferences } from '$lib/stores/user.store';
|
||||||
import { getAllTags, type TagResponseDto } from '@immich/sdk';
|
import { getAllTags, type TagResponseDto } from '@immich/sdk';
|
||||||
|
import { Checkbox, Label } from '@immich/ui';
|
||||||
import { mdiClose } from '@mdi/js';
|
import { mdiClose } from '@mdi/js';
|
||||||
import { onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
import { t } from 'svelte-i18n';
|
import { t } from 'svelte-i18n';
|
||||||
import { SvelteSet } from 'svelte/reactivity';
|
import { SvelteSet } from 'svelte/reactivity';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
selectedTags: SvelteSet<string>;
|
selectedTags: SvelteSet<string> | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
let { selectedTags = $bindable() }: Props = $props();
|
let { selectedTags = $bindable() }: Props = $props();
|
||||||
@ -23,7 +24,7 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
const handleSelect = (option?: ComboBoxOption) => {
|
const handleSelect = (option?: ComboBoxOption) => {
|
||||||
if (!option || !option.id) {
|
if (!option || !option.id || selectedTags === null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,6 +33,10 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleRemove = (tag: string) => {
|
const handleRemove = (tag: string) => {
|
||||||
|
if (selectedTags === null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
selectedTags.delete(tag);
|
selectedTags.delete(tag);
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
@ -41,6 +46,7 @@
|
|||||||
<form autocomplete="off" id="create-tag-form">
|
<form autocomplete="off" id="create-tag-form">
|
||||||
<div class="my-4 flex flex-col gap-2">
|
<div class="my-4 flex flex-col gap-2">
|
||||||
<Combobox
|
<Combobox
|
||||||
|
disabled={selectedTags === null}
|
||||||
onSelect={handleSelect}
|
onSelect={handleSelect}
|
||||||
label={$t('tags').toUpperCase()}
|
label={$t('tags').toUpperCase()}
|
||||||
defaultFirstOption
|
defaultFirstOption
|
||||||
@ -49,10 +55,21 @@
|
|||||||
placeholder={$t('search_tags')}
|
placeholder={$t('search_tags')}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<Checkbox
|
||||||
|
id="untagged-checkbox"
|
||||||
|
size="tiny"
|
||||||
|
checked={selectedTags === null}
|
||||||
|
onCheckedChange={(checked) => {
|
||||||
|
selectedTags = checked ? null : new SvelteSet();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Label label={$t('untagged')} for="untagged-checkbox" />
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<section class="flex flex-wrap pt-2 gap-1">
|
<section class="flex flex-wrap pt-2 gap-1">
|
||||||
{#each selectedTags as tagId (tagId)}
|
{#each selectedTags ?? [] as tagId (tagId)}
|
||||||
{@const tag = tagMap[tagId]}
|
{@const tag = tagMap[tagId]}
|
||||||
{#if tag}
|
{#if tag}
|
||||||
<div class="flex group transition-all">
|
<div class="flex group transition-all">
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
query: string;
|
query: string;
|
||||||
queryType: 'smart' | 'metadata' | 'description';
|
queryType: 'smart' | 'metadata' | 'description';
|
||||||
personIds: SvelteSet<string>;
|
personIds: SvelteSet<string>;
|
||||||
tagIds: SvelteSet<string>;
|
tagIds: SvelteSet<string> | null;
|
||||||
location: SearchLocationFilter;
|
location: SearchLocationFilter;
|
||||||
camera: SearchCameraFilter;
|
camera: SearchCameraFilter;
|
||||||
date: SearchDateFilter;
|
date: SearchDateFilter;
|
||||||
@ -68,7 +68,12 @@
|
|||||||
query: 'query' in searchQuery ? searchQuery.query : searchQuery.originalFileName || '',
|
query: 'query' in searchQuery ? searchQuery.query : searchQuery.originalFileName || '',
|
||||||
queryType: defaultQueryType(),
|
queryType: defaultQueryType(),
|
||||||
personIds: new SvelteSet('personIds' in searchQuery ? searchQuery.personIds : []),
|
personIds: new SvelteSet('personIds' in searchQuery ? searchQuery.personIds : []),
|
||||||
tagIds: new SvelteSet('tagIds' in searchQuery ? searchQuery.tagIds : []),
|
tagIds:
|
||||||
|
'tagIds' in searchQuery
|
||||||
|
? searchQuery.tagIds === null
|
||||||
|
? null
|
||||||
|
: new SvelteSet(searchQuery.tagIds)
|
||||||
|
: new SvelteSet(),
|
||||||
location: {
|
location: {
|
||||||
country: withNullAsUndefined(searchQuery.country),
|
country: withNullAsUndefined(searchQuery.country),
|
||||||
state: withNullAsUndefined(searchQuery.state),
|
state: withNullAsUndefined(searchQuery.state),
|
||||||
@ -140,7 +145,7 @@
|
|||||||
isFavorite: filter.display.isFavorite || undefined,
|
isFavorite: filter.display.isFavorite || undefined,
|
||||||
isNotInAlbum: filter.display.isNotInAlbum || undefined,
|
isNotInAlbum: filter.display.isNotInAlbum || undefined,
|
||||||
personIds: filter.personIds.size > 0 ? [...filter.personIds] : undefined,
|
personIds: filter.personIds.size > 0 ? [...filter.personIds] : undefined,
|
||||||
tagIds: filter.tagIds.size > 0 ? [...filter.tagIds] : undefined,
|
tagIds: filter.tagIds === null ? null : filter.tagIds.size > 0 ? [...filter.tagIds] : undefined,
|
||||||
type,
|
type,
|
||||||
rating: filter.rating,
|
rating: filter.rating,
|
||||||
};
|
};
|
||||||
|
@ -233,7 +233,10 @@
|
|||||||
return personNames.join(', ');
|
return personNames.join(', ');
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getTagNames(tagIds: string[]) {
|
async function getTagNames(tagIds: string[] | null) {
|
||||||
|
if (tagIds === null) {
|
||||||
|
return $t('untagged');
|
||||||
|
}
|
||||||
const tagNames = await Promise.all(
|
const tagNames = await Promise.all(
|
||||||
tagIds.map(async (tagId) => {
|
tagIds.map(async (tagId) => {
|
||||||
const tag = await getTagById({ id: tagId });
|
const tag = await getTagById({ id: tagId });
|
||||||
@ -343,7 +346,7 @@
|
|||||||
{#await getPersonName(value) then personName}
|
{#await getPersonName(value) then personName}
|
||||||
{personName}
|
{personName}
|
||||||
{/await}
|
{/await}
|
||||||
{:else if searchKey === 'tagIds' && Array.isArray(value)}
|
{:else if searchKey === 'tagIds' && (Array.isArray(value) || value === null)}
|
||||||
{#await getTagNames(value) then tagNames}
|
{#await getTagNames(value) then tagNames}
|
||||||
{tagNames}
|
{tagNames}
|
||||||
{/await}
|
{/await}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user