From ad27fd7996b98e7ab7b69d507bb378656bde59f7 Mon Sep 17 00:00:00 2001 From: Ricco Xie Date: Thu, 9 Mar 2023 17:11:04 +0800 Subject: [PATCH] feat: add RankingRules & StopWords components. add moveable property into ArrayInput component. fix config edit type switch tabs height. --- .../Settings/config/detail/arrayInput.tsx | 54 +++++++++++++- .../Settings/config/detail/rankingRules.tsx | 65 +++++++++++++++++ .../Settings/config/detail/stopWords.tsx | 73 +++++++++++++++++++ src/components/Settings/config/index.tsx | 14 +++- src/utils/array.ts | 17 +++++ 5 files changed, 218 insertions(+), 5 deletions(-) create mode 100644 src/components/Settings/config/detail/rankingRules.tsx create mode 100644 src/components/Settings/config/detail/stopWords.tsx create mode 100644 src/utils/array.ts diff --git a/src/components/Settings/config/detail/arrayInput.tsx b/src/components/Settings/config/detail/arrayInput.tsx index 28f5005..3f183c4 100644 --- a/src/components/Settings/config/detail/arrayInput.tsx +++ b/src/components/Settings/config/detail/arrayInput.tsx @@ -1,18 +1,21 @@ import clsx from 'clsx'; import { useForm } from 'react-hook-form'; -import { IconPlus, IconCircleMinus } from '@tabler/icons-react'; +import { IconPlus, IconCircleMinus, IconArrowUp, IconArrowDown } from '@tabler/icons-react'; import { PropsWithoutRef, useCallback, useMemo, useState } from 'react'; import { openConfirmModal } from '@mantine/modals'; import _ from 'lodash'; +import { arrayMove } from '@/src/utils/array'; export function ArrayInput({ defaultValue, onMutation, className, + moveable = false, }: PropsWithoutRef<{ className?: string; defaultValue: V[]; onMutation: (value: V[]) => void; + moveable?: boolean; }>) { const [array, setArray] = useState(defaultValue); const [isAdding, setIsAdding] = useState(false); @@ -34,6 +37,30 @@ export function ArrayInput({ onCompleteInput(); }); + const onClickItemUp = useCallback( + (index: number) => { + console.debug('🚀 ~ file: ArrayInput onClickItemUp', index); + if (!moveable || index <= 0) return; + + const updated = arrayMove(array, index, index - 1); + setArray(updated); + onMutation(updated); + }, + [array, moveable, onMutation] + ); + + const onClickItemDown = useCallback( + (index: number) => { + console.debug('🚀 ~ file: ArrayInput onClickItemDown', index); + if (!moveable || index >= array.length - 1) return; + + const updated = arrayMove(array, index, index + 1); + setArray(updated); + onMutation(updated); + }, + [array, moveable, onMutation] + ); + const onClickItemDel = useCallback( (index: number) => { console.debug('🚀 ~ file: ArrayInput onClickItemDel', index); @@ -63,7 +90,16 @@ export function ArrayInput({ className="w-full flex justify-center items-center p-2 bg-primary-200 text-primary-1000 rounded-xl" >

{item}

- + + @@ -94,6 +130,18 @@ export function ArrayInput({ ), - [addForm, array, className, defaultValue, isAdding, onClickItemDel, onCompleteInput, onSubmit] + [ + addForm, + array, + className, + defaultValue, + isAdding, + moveable, + onClickItemDel, + onClickItemDown, + onClickItemUp, + onCompleteInput, + onSubmit, + ] ); } diff --git a/src/components/Settings/config/detail/rankingRules.tsx b/src/components/Settings/config/detail/rankingRules.tsx new file mode 100644 index 0000000..f327500 --- /dev/null +++ b/src/components/Settings/config/detail/rankingRules.tsx @@ -0,0 +1,65 @@ +import { useMutation, useQuery } from '@tanstack/react-query'; +import clsx from 'clsx'; +import { RankingRules as TRankingRules } from 'meilisearch'; +import { FC, useEffect, useMemo } from 'react'; +import { IndexSettingConfigComponentProps } from '../..'; +import { ArrayInput } from './arrayInput'; +import _ from 'lodash'; + +export const RankingRules: FC = ({ client, className, host, toggleLoading }) => { + const query = useQuery({ + queryKey: ['getRankingRules', host, client.uid], + refetchInterval: 4500, + async queryFn(ctx) { + return await client.getRankingRules(); + }, + }); + + const mutation = useMutation({ + mutationKey: ['updateRankingRules', host, client.uid], + async mutationFn(variables: TRankingRules) { + console.debug('🚀 ~ file: rankingRules.tsx:19 ~ mutationFn ~ variables:', variables); + if (_.isEmpty(variables)) { + // empty to reset + return await client.resetRankingRules(); + } + return await client.updateRankingRules(variables); + }, + }); + + useEffect(() => { + const isLoading = query.isLoading || query.isFetching || mutation.isLoading; + toggleLoading(isLoading); + }, [mutation.isLoading, query.isFetching, query.isLoading, toggleLoading]); + + return useMemo( + () => ( +
+

Ranking Rules

+ +

+ Ranking rules are built-in rules that rank search results according to certain criteria. They are applied in + the same order in which they appear in the rankingRules array. +

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

Displayed Attributes

+ +

Words added to the stopWords list are ignored in future search queries.

+
+ + + + +

+ Updating stop words 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. +

+
+ + + + +

+ Stop words are strongly related to the language used in your dataset. For example, most datasets containing + English documents will have countless occurrences of 'the' and 'of'. Italian datasets, instead, will benefit + from ignoring words like 'a', 'la', or 'il'. +

+
+ { + mutation.mutate(value); + }} + /> +
+ ), + [className, mutation, query.data] + ); +}; diff --git a/src/components/Settings/config/index.tsx b/src/components/Settings/config/index.tsx index 5840004..dda7e7c 100644 --- a/src/components/Settings/config/index.tsx +++ b/src/components/Settings/config/index.tsx @@ -7,6 +7,8 @@ import { DistinctAttribute } from './detail/distinctAttribute'; import { SortableAttributes } from './detail/sortableAttributes'; import { SearchableAttributes } from './detail/searchableAttributes'; import { DisplayedAttributes } from './detail/displayedAttributes'; +import { RankingRules } from './detail/rankingRules'; +import { StopWords } from './detail/stopWords'; const tabs = [ 'Filterable Attributes', @@ -37,13 +39,13 @@ export const IndexConfiguration: FC = ({ host, clien
setInputType('visualization')} > Visualization
setInputType('json')} > JSON @@ -83,6 +85,14 @@ export const IndexConfiguration: FC = ({ host, clien className={clsx(selectTab !== 4 && 'hidden', 'flex-1 flex flex-col gap-2 p-2')} {...{ client, host, toggleLoading }} /> + +
diff --git a/src/utils/array.ts b/src/utils/array.ts new file mode 100644 index 0000000..1851187 --- /dev/null +++ b/src/utils/array.ts @@ -0,0 +1,17 @@ +export const arrayMove = (arr: T[], old_index: number, new_index: number): T[] => { + while (old_index < 0) { + old_index += arr.length; + } + while (new_index < 0) { + new_index += arr.length; + } + if (new_index >= arr.length) { + var k = new_index - arr.length + 1; + while (k--) { + // @ts-ignore + arr.push(undefined); + } + } + arr.splice(new_index, 0, arr.splice(old_index, 1)[0]); + return arr; +};