From 65bc4e0fc091ed643f4ca49e484715c1059dbd35 Mon Sep 17 00:00:00 2001 From: faye1225 <56664035+faye1225@users.noreply.github.com> Date: Wed, 17 Jul 2024 20:24:31 +0800 Subject: [PATCH] Fix issues related to search apps, notification duration, and loading icon on the explore page (#6374) --- .../app/configuration/debug/index.tsx | 6 +- .../components/app/configuration/index.tsx | 10 +-- .../components/base/chat/chat/chat-input.tsx | 2 +- web/app/components/base/toast/index.tsx | 5 +- .../settings/permission-selector/index.tsx | 2 + web/app/components/explore/app-list/index.tsx | 62 ++++++++++++++----- 6 files changed, 59 insertions(+), 28 deletions(-) diff --git a/web/app/components/app/configuration/debug/index.tsx b/web/app/components/app/configuration/debug/index.tsx index ff476246fe..45e2ae720b 100644 --- a/web/app/components/app/configuration/debug/index.tsx +++ b/web/app/components/app/configuration/debug/index.tsx @@ -136,7 +136,7 @@ const Debug: FC = ({ const { notify } = useContext(ToastContext) const logError = useCallback((message: string) => { - notify({ type: 'error', message, duration: 3000 }) + notify({ type: 'error', message }) }, [notify]) const [completionFiles, setCompletionFiles] = useState([]) @@ -144,11 +144,11 @@ const Debug: FC = ({ if (isAdvancedMode && mode !== AppType.completion) { if (modelModeType === ModelModeType.completion) { if (!hasSetBlockStatus.history) { - notify({ type: 'error', message: t('appDebug.otherError.historyNoBeEmpty'), duration: 3000 }) + notify({ type: 'error', message: t('appDebug.otherError.historyNoBeEmpty') }) return false } if (!hasSetBlockStatus.query) { - notify({ type: 'error', message: t('appDebug.otherError.queryNoBeEmpty'), duration: 3000 }) + notify({ type: 'error', message: t('appDebug.otherError.queryNoBeEmpty') }) return false } } diff --git a/web/app/components/app/configuration/index.tsx b/web/app/components/app/configuration/index.tsx index 3b61a0b7fe..030d0ef526 100644 --- a/web/app/components/app/configuration/index.tsx +++ b/web/app/components/app/configuration/index.tsx @@ -555,23 +555,23 @@ const Configuration: FC = () => { const promptVariables = modelConfig.configs.prompt_variables if (promptEmpty) { - notify({ type: 'error', message: t('appDebug.otherError.promptNoBeEmpty'), duration: 3000 }) + notify({ type: 'error', message: t('appDebug.otherError.promptNoBeEmpty') }) return } if (isAdvancedMode && mode !== AppType.completion) { if (modelModeType === ModelModeType.completion) { if (!hasSetBlockStatus.history) { - notify({ type: 'error', message: t('appDebug.otherError.historyNoBeEmpty'), duration: 3000 }) + notify({ type: 'error', message: t('appDebug.otherError.historyNoBeEmpty') }) return } if (!hasSetBlockStatus.query) { - notify({ type: 'error', message: t('appDebug.otherError.queryNoBeEmpty'), duration: 3000 }) + notify({ type: 'error', message: t('appDebug.otherError.queryNoBeEmpty') }) return } } } if (contextVarEmpty) { - notify({ type: 'error', message: t('appDebug.feature.dataSet.queryVariable.contextVarNotEmpty'), duration: 3000 }) + notify({ type: 'error', message: t('appDebug.feature.dataSet.queryVariable.contextVarNotEmpty') }) return } const postDatasets = dataSets.map(({ id }) => ({ @@ -638,7 +638,7 @@ const Configuration: FC = () => { modelConfig: newModelConfig, completionParams, }) - notify({ type: 'success', message: t('common.api.success'), duration: 3000 }) + notify({ type: 'success', message: t('common.api.success') }) setCanReturnToSimpleMode(false) return true diff --git a/web/app/components/base/chat/chat/chat-input.tsx b/web/app/components/base/chat/chat/chat-input.tsx index e5a99be065..6d15010f85 100644 --- a/web/app/components/base/chat/chat/chat-input.tsx +++ b/web/app/components/base/chat/chat/chat-input.tsx @@ -106,7 +106,7 @@ const ChatInput: FC = ({ } const logError = (message: string) => { - notify({ type: 'error', message, duration: 3000 }) + notify({ type: 'error', message }) } const handleVoiceInputShow = () => { (Recorder as any).getPermission().then(() => { diff --git a/web/app/components/base/toast/index.tsx b/web/app/components/base/toast/index.tsx index 06069f57e8..903b6d29a7 100644 --- a/web/app/components/base/toast/index.tsx +++ b/web/app/components/base/toast/index.tsx @@ -22,7 +22,6 @@ export type IToastProps = { type IToastContext = { notify: (props: IToastProps) => void } -const defaultDuring = 3000 export const ToastContext = createContext({} as IToastContext) export const useToastContext = () => useContext(ToastContext) @@ -89,10 +88,10 @@ export const ToastProvider = ({ const placeholder: IToastProps = { type: 'info', message: 'Toast message', - duration: 3000, + duration: 6000, } const [params, setParams] = React.useState(placeholder) - + const defaultDuring = params.type === 'success' ? 3000 : 6000 const [mounted, setMounted] = useState(false) useEffect(() => { diff --git a/web/app/components/datasets/settings/permission-selector/index.tsx b/web/app/components/datasets/settings/permission-selector/index.tsx index 2405f9512b..910dfc5347 100644 --- a/web/app/components/datasets/settings/permission-selector/index.tsx +++ b/web/app/components/datasets/settings/permission-selector/index.tsx @@ -51,9 +51,11 @@ const PermissionSelector = ({ disabled, permission, value, memberList, onChange, ...memberList.filter(member => member.id !== userProfile.id).filter(member => value.includes(member.id)), ].map(member => member.name).join(', ') }, [userProfile, value, memberList]) + const showMe = useMemo(() => { return userProfile.name.includes(searchKeywords) || userProfile.email.includes(searchKeywords) }, [searchKeywords, userProfile]) + const filteredMemberList = useMemo(() => { return memberList.filter(member => (member.name.includes(searchKeywords) || member.email.includes(searchKeywords)) && member.id !== userProfile.id && ['owner', 'admin', 'editor', 'dataset_operator'].includes(member.role)) }, [memberList, searchKeywords, userProfile]) diff --git a/web/app/components/explore/app-list/index.tsx b/web/app/components/explore/app-list/index.tsx index b465893410..4f2926677d 100644 --- a/web/app/components/explore/app-list/index.tsx +++ b/web/app/components/explore/app-list/index.tsx @@ -5,6 +5,7 @@ import { useRouter } from 'next/navigation' import { useTranslation } from 'react-i18next' import { useContext } from 'use-context-selector' import useSWR from 'swr' +import { useDebounceFn } from 'ahooks' import Toast from '../../base/toast' import s from './style.module.css' import cn from '@/utils/classnames' @@ -22,6 +23,7 @@ import Loading from '@/app/components/base/loading' import { NEED_REFRESH_APP_LIST_KEY } from '@/config' import { useAppContext } from '@/context/app-context' import { getRedirection } from '@/utils/app-redirection' +import SearchInput from '@/app/components/base/search-input' type AppsProps = { pageType?: PageType @@ -43,6 +45,18 @@ const Apps = ({ const { hasEditPermission } = useContext(ExploreContext) const allCategoriesEn = t('explore.apps.allCategories', { lng: 'en' }) + const [keywords, setKeywords] = useState('') + const [searchKeywords, setSearchKeywords] = useState('') + + const { run: handleSearch } = useDebounceFn(() => { + setSearchKeywords(keywords) + }, { wait: 500 }) + + const handleKeywordsChange = (value: string) => { + setKeywords(value) + handleSearch() + } + const [currentType, setCurrentType] = useState('') const [currCategory, setCurrCategory] = useTabSearchParams({ defaultTab: allCategoriesEn, @@ -89,6 +103,17 @@ const Apps = ({ } }, [currentType, currCategory, allCategoriesEn, allList]) + const searchFilteredList = useMemo(() => { + if (!searchKeywords || !filteredList || filteredList.length === 0) + return filteredList + + const lowerCaseSearchKeywords = searchKeywords.toLowerCase() + + return filteredList.filter(item => + item.app && item.app.name && item.app.name.toLowerCase().includes(lowerCaseSearchKeywords), + ) + }, [searchKeywords, filteredList]) + const [currApp, setCurrApp] = React.useState(null) const [isShowCreateModal, setIsShowCreateModal] = React.useState(false) const onCreate: CreateAppModalProps['onConfirm'] = async ({ @@ -123,7 +148,7 @@ const Apps = ({ } } - if (!categories) { + if (!categories || categories.length === 0) { return (
@@ -143,25 +168,30 @@ const Apps = ({
)}
- {pageType !== PageType.EXPLORE && ( - <> - -
- - )} - + <> + {pageType !== PageType.EXPLORE && ( + <> + +
+ + )} + + + +
+