From 99e21bc8e800f941168de577d23cdc426f7e5e28 Mon Sep 17 00:00:00 2001 From: Ricco Xie Date: Wed, 8 Mar 2023 16:10:14 +0800 Subject: [PATCH] feat: multiple setting config component completed. add DistinctAttribute & SortableAttributes & SearchableAttributes & DisplayedAttributes components. adjust config refetch interval. add logic for empty config mutation to reset. apply config tabs ghost styles. --- package.json | 2 +- pnpm-lock.yaml | 8 +- .../config/detail/displayedAttributes.tsx | 72 ++++++++++ .../config/detail/distinctAttribute.tsx | 131 ++++++++++++++++++ .../config/detail/filterableAttributes.tsx | 9 +- .../config/detail/searchableAttributes.tsx | 81 +++++++++++ .../config/detail/sortableAttributes.tsx | 76 ++++++++++ src/components/Settings/config/index.tsx | 32 ++++- 8 files changed, 401 insertions(+), 10 deletions(-) create mode 100644 src/components/Settings/config/detail/displayedAttributes.tsx create mode 100644 src/components/Settings/config/detail/distinctAttribute.tsx create mode 100644 src/components/Settings/config/detail/searchableAttributes.tsx create mode 100644 src/components/Settings/config/detail/sortableAttributes.tsx diff --git a/package.json b/package.json index ce01c1a..03fe088 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "@mantine/hooks": "^6.0.0", "@mantine/modals": "^6.0.0", "@monaco-editor/react": "^4.4.6", - "@sira-ui/tailwind": "^0.8.0", + "@sira-ui/tailwind": "^0.9.0", "@tabler/icons-react": "^2.8.0", "@tanstack/react-query": "^4.26.1", "@tanstack/react-query-devtools": "^4.26.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d9a33de..e15fac0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,7 +8,7 @@ specifiers: '@mantine/hooks': ^6.0.0 '@mantine/modals': ^6.0.0 '@monaco-editor/react': ^4.4.6 - '@sira-ui/tailwind': ^0.8.0 + '@sira-ui/tailwind': ^0.9.0 '@tabler/icons-react': ^2.8.0 '@tanstack/react-query': ^4.26.1 '@tanstack/react-query-devtools': ^4.26.1 @@ -55,7 +55,7 @@ dependencies: '@mantine/hooks': 6.0.0_react@18.2.0 '@mantine/modals': 6.0.0_uziugpv5zwkk3pqsn64qbjkxrm '@monaco-editor/react': 4.4.6_waewrrayshn643ztij6zbniufy - '@sira-ui/tailwind': 0.8.0_tailwindcss@3.2.7 + '@sira-ui/tailwind': 0.9.0_tailwindcss@3.2.7 '@tabler/icons-react': 2.8.0_react@18.2.0 '@tanstack/react-query': 4.26.1_biqbaboplfbrettd7655fr4n2y '@tanstack/react-query-devtools': 4.26.1_brdhmlf72zuns3lsk66phyptty @@ -1197,8 +1197,8 @@ packages: chroma-js: 2.4.2 dev: false - /@sira-ui/tailwind/0.8.0_tailwindcss@3.2.7: - resolution: {integrity: sha512-lKPa71QXorKuA5At2pI6Iw6m+pPfiHi9YeSsheS3Qdy7zHG9U8aa1YpPWPvFvP/F2ABFu56E7rIZ0H3bh+dvMw==} + /@sira-ui/tailwind/0.9.0_tailwindcss@3.2.7: + resolution: {integrity: sha512-ZowG1UiOJ9H1eLmMIEvs7BHeCuejzRXSFlkZ48VswFrHfHsEm23t1/vMRxeGxqpOV4gfm6ilm0ozGO0lw6y3Jw==} peerDependencies: tailwindcss: ^3 dependencies: diff --git a/src/components/Settings/config/detail/displayedAttributes.tsx b/src/components/Settings/config/detail/displayedAttributes.tsx new file mode 100644 index 0000000..e5e8471 --- /dev/null +++ b/src/components/Settings/config/detail/displayedAttributes.tsx @@ -0,0 +1,72 @@ +import { useMutation, useQuery } from '@tanstack/react-query'; +import clsx from 'clsx'; +import { DisplayedAttributes as TDisplayedAttributes } from 'meilisearch'; +import { FC, useEffect, useMemo } from 'react'; +import { IndexSettingConfigComponentProps } from '../..'; +import { ArrayInput } from './arrayInput'; +import _ from 'lodash'; + +export const DisplayedAttributes: FC = ({ + client, + className, + host, + toggleLoading, +}) => { + const query = useQuery({ + queryKey: ['getDisplayedAttributes', host, client.uid], + refetchInterval: 4500, + async queryFn(ctx) { + return await client.getDisplayedAttributes(); + }, + }); + + const mutation = useMutation({ + mutationKey: ['updateDisplayedAttributes', host, client.uid], + async mutationFn(variables: TDisplayedAttributes) { + console.debug('🚀 ~ file: displayedAttributes.tsx:19 ~ mutationFn ~ variables:', variables); + if (_.isEmpty(variables)) { + // empty to reset + return await client.resetDisplayedAttributes(); + } + return await client.updateDisplayedAttributes(variables); + }, + }); + + useEffect(() => { + const isLoading = query.isLoading || query.isFetching || mutation.isLoading; + toggleLoading(isLoading); + }, [mutation.isLoading, query.isFetching, query.isLoading, toggleLoading]); + + return useMemo( + () => ( +
+

Displayed Attributes

+ +

+ The attributes added to the displayedAttributes list appear in search results. displayedAttributes only + affects the search endpoints. It has no impact on the GET documents endpoint. +
+ By default, the displayedAttributes array is equal to all fields in your dataset. This behavior is + represented by the value ["*"]. +

+ + Learn more + +
+ { + mutation.mutate(value); + }} + /> +
+ ), + [className, mutation, query.data] + ); +}; diff --git a/src/components/Settings/config/detail/distinctAttribute.tsx b/src/components/Settings/config/detail/distinctAttribute.tsx new file mode 100644 index 0000000..f5ded22 --- /dev/null +++ b/src/components/Settings/config/detail/distinctAttribute.tsx @@ -0,0 +1,131 @@ +import { useMutation, useQuery } from '@tanstack/react-query'; +import clsx from 'clsx'; +import { DistinctAttribute as TDistinctAttribute } from 'meilisearch'; +import { FC, useCallback, useEffect, useMemo, useState } from 'react'; +import { IndexSettingConfigComponentProps } from '../..'; +import { IconAlertTriangleFilled } from '@tabler/icons-react'; +import { Controller, useForm } from 'react-hook-form'; +import _ from 'lodash'; + +export const DistinctAttribute: FC = ({ client, className, host, toggleLoading }) => { + const query = useQuery({ + queryKey: ['getDistinctAttribute', host, client.uid], + refetchInterval: 4500, + async queryFn(ctx) { + return await client.getDistinctAttribute(); + }, + }); + + const mutation = useMutation({ + mutationKey: ['updateDistinctAttribute', host, client.uid], + async mutationFn(variables: TDistinctAttribute) { + console.debug('🚀 ~ file: distinctAttributes.tsx:19 ~ mutationFn ~ variables:', variables); + if (_.isEmpty(variables)) { + // empty to reset + return await client.resetDistinctAttribute(); + } + return await client.updateDistinctAttribute(variables); + }, + }); + + useEffect(() => { + const isLoading = query.isLoading || query.isFetching || mutation.isLoading; + toggleLoading(isLoading); + }, [mutation.isLoading, query.isFetching, query.isLoading, toggleLoading]); + + const [isEditing, setIsEditing] = useState(false); + const form = useForm({ defaultValues: { input: '' } }); + + const onCompleteInput = useCallback(() => { + // close input + setIsEditing(false); + form.reset(); + }, [form]); + + const startEdit = useCallback(() => { + form.setValue('input', query.data || ''); + setIsEditing(true); + }, [form, query.data]); + + const onSubmit = form.handleSubmit(async ({ input }) => { + mutation.mutate(input); + onCompleteInput(); + }); + + return useMemo( + () => ( +
+

Distinct Attribute

+ +

The distinct attribute is a field whose value will always be unique in the returned documents.

+ + Learn more + +
+ + + + +

+ Updating distinct attributes will re-index all documents in the index, which can take some time. We + recommend updating your index settings first and then adding documents as this reduces RAM consumption. +

+
+ +
+ ( + + + + )} + /> +
+ + + +
+ +
+ ), + [className, form.control, isEditing, onCompleteInput, onSubmit, query.data, startEdit] + ); +}; diff --git a/src/components/Settings/config/detail/filterableAttributes.tsx b/src/components/Settings/config/detail/filterableAttributes.tsx index ec24ecd..84b0638 100644 --- a/src/components/Settings/config/detail/filterableAttributes.tsx +++ b/src/components/Settings/config/detail/filterableAttributes.tsx @@ -5,6 +5,7 @@ import { FC, useEffect, useMemo } from 'react'; import { IndexSettingConfigComponentProps } from '../..'; import { ArrayInput } from './arrayInput'; import { IconAlertTriangleFilled } from '@tabler/icons-react'; +import _ from 'lodash'; export const FilterableAttributes: FC = ({ client, @@ -14,7 +15,7 @@ export const FilterableAttributes: FC = ({ }) => { const query = useQuery({ queryKey: ['getFilterableAttributes', host, client.uid], - refetchInterval: 3000, + refetchInterval: 4500, async queryFn(ctx) { return await client.getFilterableAttributes(); }, @@ -24,6 +25,10 @@ export const FilterableAttributes: FC = ({ mutationKey: ['updateFilterableAttributes', host, client.uid], async mutationFn(variables: TFilterableAttributes) { console.debug('🚀 ~ file: filterableAttributes.tsx:19 ~ mutationFn ~ variables:', variables); + if (_.isEmpty(variables)) { + // empty to reset + return await client.resetFilterableAttributes(); + } return await client.updateFilterableAttributes(variables); }, }); @@ -42,6 +47,8 @@ export const FilterableAttributes: FC = ({ Learn more diff --git a/src/components/Settings/config/detail/searchableAttributes.tsx b/src/components/Settings/config/detail/searchableAttributes.tsx new file mode 100644 index 0000000..e5de108 --- /dev/null +++ b/src/components/Settings/config/detail/searchableAttributes.tsx @@ -0,0 +1,81 @@ +import { useMutation, useQuery } from '@tanstack/react-query'; +import clsx from 'clsx'; +import { SearchableAttributes as TSearchableAttributes } from 'meilisearch'; +import { FC, useEffect, useMemo } from 'react'; +import { IndexSettingConfigComponentProps } from '../..'; +import { ArrayInput } from './arrayInput'; +import { IconAlertTriangleFilled } from '@tabler/icons-react'; +import _ from 'lodash'; + +export const SearchableAttributes: FC = ({ + client, + className, + host, + toggleLoading, +}) => { + const query = useQuery({ + queryKey: ['getSearchableAttributes', host, client.uid], + refetchInterval: 4500, + async queryFn(ctx) { + return await client.getSearchableAttributes(); + }, + }); + + const mutation = useMutation({ + mutationKey: ['updateSearchableAttributes', host, client.uid], + async mutationFn(variables: TSearchableAttributes) { + console.debug('🚀 ~ file: searchableAttributes.tsx:19 ~ mutationFn ~ variables:', variables); + if (_.isEmpty(variables)) { + // empty to reset + return await client.resetSearchableAttributes(); + } + return await client.updateSearchableAttributes(variables); + }, + }); + + useEffect(() => { + const isLoading = query.isLoading || query.isFetching || mutation.isLoading; + toggleLoading(isLoading); + }, [mutation.isLoading, query.isFetching, query.isLoading, toggleLoading]); + + return useMemo( + () => ( +
+

Searchable Attributes

+ +

+ The values associated with attributes in the searchableAttributes list are searched for matching query + words. The order of the list also determines the attribute ranking order.
By default, the + searchableAttributes array is equal to all fields in your dataset. This behavior is represented by the value + ["*"]. +

+ + Learn more + +
+ + + + +

+ Updating searchable attributes will re-index all documents in the index, which can take some time. We + recommend updating your index settings first and then adding documents as this reduces RAM consumption. +

+
+ { + mutation.mutate(value); + }} + /> +
+ ), + [className, mutation, query.data] + ); +}; diff --git a/src/components/Settings/config/detail/sortableAttributes.tsx b/src/components/Settings/config/detail/sortableAttributes.tsx new file mode 100644 index 0000000..5c477d4 --- /dev/null +++ b/src/components/Settings/config/detail/sortableAttributes.tsx @@ -0,0 +1,76 @@ +import { useMutation, useQuery } from '@tanstack/react-query'; +import clsx from 'clsx'; +import { SortableAttributes as TSortableAttributes } from 'meilisearch'; +import { FC, useEffect, useMemo } from 'react'; +import { IndexSettingConfigComponentProps } from '../..'; +import { ArrayInput } from './arrayInput'; +import { IconAlertTriangleFilled } from '@tabler/icons-react'; +import _ from 'lodash'; + +export const SortableAttributes: FC = ({ + client, + className, + host, + toggleLoading, +}) => { + const query = useQuery({ + queryKey: ['getSortableAttributes', host, client.uid], + refetchInterval: 4500, + async queryFn(ctx) { + return await client.getSortableAttributes(); + }, + }); + + const mutation = useMutation({ + mutationKey: ['updateSortableAttributes', host, client.uid], + async mutationFn(variables: TSortableAttributes) { + console.debug('🚀 ~ file: sortableAttributes.tsx:19 ~ mutationFn ~ variables:', variables); + if (_.isEmpty(variables)) { + // empty to reset + return await client.resetSortableAttributes(); + } + return await client.updateSortableAttributes(variables); + }, + }); + + useEffect(() => { + const isLoading = query.isLoading || query.isFetching || mutation.isLoading; + toggleLoading(isLoading); + }, [mutation.isLoading, query.isFetching, query.isLoading, toggleLoading]); + + return useMemo( + () => ( +
+

Sortable Attributes

+ +

Attributes that can be used when sorting search results using the sort search parameter.

+ + Learn more + +
+ + + + +

+ Updating sortable attributes will re-index all documents in the index, which can take some time. We + recommend updating your index settings first and then adding documents as this reduces RAM consumption. +

+
+ { + mutation.mutate(value); + }} + /> +
+ ), + [className, mutation, query.data] + ); +}; diff --git a/src/components/Settings/config/index.tsx b/src/components/Settings/config/index.tsx index 489cd80..5840004 100644 --- a/src/components/Settings/config/index.tsx +++ b/src/components/Settings/config/index.tsx @@ -1,12 +1,16 @@ -import { FC, useCallback, useMemo, useState } from 'react'; +import { FC, useMemo, useState } from 'react'; import { IndexSettingComponentProps } from '..'; import clsx from 'clsx'; import { Editor } from './editor'; import { FilterableAttributes } from './detail/filterableAttributes'; +import { DistinctAttribute } from './detail/distinctAttribute'; +import { SortableAttributes } from './detail/sortableAttributes'; +import { SearchableAttributes } from './detail/searchableAttributes'; +import { DisplayedAttributes } from './detail/displayedAttributes'; const tabs = [ 'Filterable Attributes', - 'Distinct Attributes', + 'Distinct Attribute', 'Sortable Attributes', 'Searchable Attributes', 'Displayed Attributes', @@ -47,9 +51,13 @@ export const IndexConfiguration: FC = ({ host, clien
-
+
{tabs.map((tab, i) => ( -
setSelectTab(i)}> +
setSelectTab(i)} + > {tab}
))} @@ -59,6 +67,22 @@ export const IndexConfiguration: FC = ({ host, clien className={clsx(selectTab !== 0 && 'hidden', 'flex-1 flex flex-col gap-2 p-2')} {...{ client, host, toggleLoading }} /> + + + +