From 5d1bb36be3bd574977f1e5df71c98e337e92b194 Mon Sep 17 00:00:00 2001 From: Laura Hausmann Date: Sat, 18 Nov 2023 20:32:39 +0100 Subject: [PATCH] [client] Improve postgres FTS filter menu and guide --- locales/en-US.yml | 11 +++- .../server/api/common/generate-fts-query.ts | 1 - packages/client/src/components/MkDialog.vue | 55 +++++++++++-------- packages/client/src/pages/search-filters.vue | 31 +++++++++-- 4 files changed, 66 insertions(+), 32 deletions(-) diff --git a/locales/en-US.yml b/locales/en-US.yml index 7c0501c2f..405fbad6d 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -1494,14 +1494,17 @@ _filters: word: "word" phrase: "literal phrase that contains (arbitrary) characters" attachmentType: "Filter by attachment type(s)" + matchOptions: "Change case sensitivity and/or enable whole word matching" info: "Nomenclature" - info1: "Text in brackets signifies available optional filter parameters. Filter aliases or parameter options are signified by a pipe character." + info1: "Text in brackets signifies available optional filter parameters. Parameter options are signified by a pipe character." info2: "A dash enclosed in brackets denotes the ability to invert/negate a filter with the dash character." + infoEnd: "Filter aliases" + infoEnd1: "For convenience and typo-prevention, some filters have aliases, which are listed below." fromUser: "From user" replyTo: "Replying to" mentioning: "Mentioning" - withFile: "With file" - fromDomain: "From domain" + withFile: "Has attachment" + fromDomain: "Specific instance only" notesBefore: "Posts before" notesAfter: "Posts after" followingOnly: "Following only" @@ -1509,6 +1512,8 @@ _filters: repliesOnly: "Replies only" excludeReplies: "Exclude replies" excludeRenotes: "Exclude boosts" + caseSensitive: "Case sensitive" + matchWords: "Match whole words" _tutorial: title: "How to use Iceshrimp" step1_1: "Welcome!" diff --git a/packages/backend/src/server/api/common/generate-fts-query.ts b/packages/backend/src/server/api/common/generate-fts-query.ts index 43644e202..6c67d31e7 100644 --- a/packages/backend/src/server/api/common/generate-fts-query.ts +++ b/packages/backend/src/server/api/common/generate-fts-query.ts @@ -26,7 +26,6 @@ const filters = { } as Record, search: string, id: number) => any> //TODO: editing the query should be possible, clicking search again resets it (it should be a twitter-like top of the page kind of deal) -//TODO: UI and guide are missing for search|match: and case: filters export function generateFtsQuery(query: SelectQueryBuilder, q: string): void { const components = q.trim().split(" "); diff --git a/packages/client/src/components/MkDialog.vue b/packages/client/src/components/MkDialog.vue index a1175001d..189426c36 100644 --- a/packages/client/src/components/MkDialog.vue +++ b/packages/client/src/components/MkDialog.vue @@ -391,13 +391,29 @@ async function openSearchFilters(ev) { }); }, }, + null, + { + icon: "ph-eye ph-bold ph-lg", + text: i18n.ts._filters.followingOnly, + action: () => { + appendSearchFilter("filter:following"); + }, + }, + { + icon: "ph-users-three ph-bold ph-lg", + text: i18n.ts._filters.followersOnly, + action: () => { + appendSearchFilter("filter:followers"); + }, + }, { icon: "ph-link ph-bold ph-lg", text: i18n.ts._filters.fromDomain, action: () => { - appendSearchFilter("domain:", false); + appendSearchFilter("instance:", false); }, }, + null, { type: "parent", text: i18n.ts._filters.withFile, @@ -459,28 +475,6 @@ async function openSearchFilters(ev) { }, }, null, - { - icon: "ph-eye ph-bold ph-lg", - text: i18n.ts._filters.followingOnly, - action: () => { - appendSearchFilter("filter:following"); - }, - }, - { - icon: "ph-users-three ph-bold ph-lg", - text: i18n.ts._filters.followersOnly, - action: () => { - appendSearchFilter("filter:followers"); - }, - }, - { - icon: "ph-arrow-u-up-left ph-bold ph-lg", - text: i18n.ts._filters.repliesOnly, - action: () => { - appendSearchFilter("filter:replies"); - }, - }, - null, { icon: "ph-arrow-u-up-left ph-bold ph-lg", text: i18n.ts._filters.excludeReplies, @@ -496,6 +490,21 @@ async function openSearchFilters(ev) { }, }, null, + { + icon: "ph-text-aa ph-bold ph-lg", + text: i18n.ts._filters.caseSensitive, + action: () => { + appendSearchFilter("case:sensitive"); + }, + }, + { + icon: "ph-brackets-angle ph-bold ph-lg", + text: i18n.ts._filters.matchWords, + action: () => { + appendSearchFilter("match:words"); + }, + }, + null, { icon: "ph-question ph-bold ph-lg", text: i18n.ts._filters._dialog.learnMore, diff --git a/packages/client/src/pages/search-filters.vue b/packages/client/src/pages/search-filters.vue index b69e4c7ce..346548c18 100644 --- a/packages/client/src/pages/search-filters.vue +++ b/packages/client/src/pages/search-filters.vue @@ -18,19 +18,27 @@

(one OR of OR multiple OR words)

+
+
{{ i18n.ts._filters._dialog.matchOptions }}
+
+

case:sensitive

+

match:word[s]

+
+
{{ i18n.ts._filters._dialog.userDomain }}

[-]from:[@]user[@host.tld]

[-]mention:[@]user[@host.tld]

-

[-]reply|to:[@]user[@host.tld]

-

[-]domain|host:host.tld

+

[-]reply:[@]user[@host.tld]

+

[-]instance:domain.tld

{{ i18n.ts._filters._dialog.miscFilters }}
-

[-]filter:followers|following|replies|reply|renote[s]|boost[s]

+

[-]filter:followers|following

+

[-]filter:replies|renote[s]|boost[s]

@@ -43,8 +51,21 @@
{{ i18n.ts._filters._dialog.postDate }}

{{ i18n.ts._filters._dialog.exclusivity }}

-

before|until:yyyy-mm-dd

-

after|since:yyyy-mm-dd

+

before:yyyy-mm-dd

+

after:yyyy-mm-dd

+
+
+
+
{{ i18n.ts._filters._dialog.infoEnd }}
+
+

{{ i18n.ts._filters._dialog.infoEnd1 }}

+

filter:reply = filter:replies

+

search:word[s] = match:word[s]

+

domain: = host: = instance:

+

until: = before:

+

since: = after:

+

host: = domain:

+

to: = reply: