mirror of
https://github.com/langgenius/dify.git
synced 2024-11-16 11:42:29 +08:00
fix: webapp variable input & app unavailable status (#2405)
This commit is contained in:
parent
843280f82b
commit
d8de2017b5
|
@ -0,0 +1,46 @@
|
||||||
|
import type { FC } from 'react'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import { memo } from 'react'
|
||||||
|
|
||||||
|
type InputProps = {
|
||||||
|
form: any
|
||||||
|
value: string
|
||||||
|
onChange: (variable: string, value: string) => void
|
||||||
|
}
|
||||||
|
const FormInput: FC<InputProps> = ({
|
||||||
|
form,
|
||||||
|
value,
|
||||||
|
onChange,
|
||||||
|
}) => {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
const {
|
||||||
|
type,
|
||||||
|
label,
|
||||||
|
required,
|
||||||
|
max_length,
|
||||||
|
variable,
|
||||||
|
} = form
|
||||||
|
|
||||||
|
if (type === 'paragraph') {
|
||||||
|
return (
|
||||||
|
<textarea
|
||||||
|
value={value}
|
||||||
|
className='grow h-[104px] rounded-lg bg-gray-100 px-2.5 py-2 outline-none appearance-none resize-none'
|
||||||
|
onChange={e => onChange(variable, e.target.value)}
|
||||||
|
placeholder={`${label}${!required ? `(${t('appDebug.variableTable.optional')})` : ''}`}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<input
|
||||||
|
className='grow h-9 rounded-lg bg-gray-100 px-2.5 outline-none appearance-none'
|
||||||
|
value={value || ''}
|
||||||
|
maxLength={max_length}
|
||||||
|
onChange={e => onChange(variable, e.target.value)}
|
||||||
|
placeholder={`${label}${!required ? `(${t('appDebug.variableTable.optional')})` : ''}`}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default memo(FormInput)
|
|
@ -1,5 +1,7 @@
|
||||||
|
import { useCallback } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { useChatWithHistoryContext } from '../context'
|
import { useChatWithHistoryContext } from '../context'
|
||||||
|
import Input from './form-input'
|
||||||
import { PortalSelect } from '@/app/components/base/select'
|
import { PortalSelect } from '@/app/components/base/select'
|
||||||
|
|
||||||
const Form = () => {
|
const Form = () => {
|
||||||
|
@ -11,43 +13,31 @@ const Form = () => {
|
||||||
isMobile,
|
isMobile,
|
||||||
} = useChatWithHistoryContext()
|
} = useChatWithHistoryContext()
|
||||||
|
|
||||||
const handleFormChange = (variable: string, value: string) => {
|
const handleFormChange = useCallback((variable: string, value: string) => {
|
||||||
handleNewConversationInputsChange({
|
handleNewConversationInputsChange({
|
||||||
...newConversationInputs,
|
...newConversationInputs,
|
||||||
[variable]: value,
|
[variable]: value,
|
||||||
})
|
})
|
||||||
}
|
}, [newConversationInputs, handleNewConversationInputsChange])
|
||||||
|
|
||||||
const renderField = (form: any) => {
|
const renderField = (form: any) => {
|
||||||
const {
|
const {
|
||||||
label,
|
label,
|
||||||
required,
|
required,
|
||||||
max_length,
|
|
||||||
variable,
|
variable,
|
||||||
options,
|
options,
|
||||||
} = form
|
} = form
|
||||||
|
|
||||||
if (form.type === 'text-input') {
|
if (form.type === 'text-input' || form.type === 'paragraph') {
|
||||||
return (
|
return (
|
||||||
<input
|
<Input
|
||||||
className='grow h-9 rounded-lg bg-gray-100 px-2.5 outline-none appearance-none'
|
form={form}
|
||||||
value={newConversationInputs[variable] || ''}
|
|
||||||
maxLength={max_length}
|
|
||||||
onChange={e => handleFormChange(variable, e.target.value)}
|
|
||||||
placeholder={`${label}${!required ? `(${t('appDebug.variableTable.optional')})` : ''}`}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
if (form.type === 'paragraph') {
|
|
||||||
return (
|
|
||||||
<textarea
|
|
||||||
value={newConversationInputs[variable]}
|
value={newConversationInputs[variable]}
|
||||||
className='grow h-[104px] rounded-lg bg-gray-100 px-2.5 py-2 outline-none appearance-none resize-none'
|
onChange={handleFormChange}
|
||||||
onChange={e => handleFormChange(variable, e.target.value)}
|
|
||||||
placeholder={`${label}${!required ? `(${t('appDebug.variableTable.optional')})` : ''}`}
|
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PortalSelect
|
<PortalSelect
|
||||||
popupClassName='w-[200px]'
|
popupClassName='w-[200px]'
|
||||||
|
|
|
@ -16,6 +16,7 @@ import type {
|
||||||
} from '@/models/share'
|
} from '@/models/share'
|
||||||
|
|
||||||
export type ChatWithHistoryContextValue = {
|
export type ChatWithHistoryContextValue = {
|
||||||
|
appInfoError?: any
|
||||||
appInfoLoading?: boolean
|
appInfoLoading?: boolean
|
||||||
appMeta?: AppMeta
|
appMeta?: AppMeta
|
||||||
appData?: AppData
|
appData?: AppData
|
||||||
|
|
|
@ -40,7 +40,7 @@ import { changeLanguage } from '@/i18n/i18next-config'
|
||||||
|
|
||||||
export const useChatWithHistory = (installedAppInfo?: InstalledApp) => {
|
export const useChatWithHistory = (installedAppInfo?: InstalledApp) => {
|
||||||
const isInstalledApp = useMemo(() => !!installedAppInfo, [installedAppInfo])
|
const isInstalledApp = useMemo(() => !!installedAppInfo, [installedAppInfo])
|
||||||
const { data: appInfo, isLoading: appInfoLoading } = useSWR(installedAppInfo ? null : 'appInfo', fetchAppInfo)
|
const { data: appInfo, isLoading: appInfoLoading, error: appInfoError } = useSWR(installedAppInfo ? null : 'appInfo', fetchAppInfo)
|
||||||
|
|
||||||
const appData = useMemo(() => {
|
const appData = useMemo(() => {
|
||||||
if (isInstalledApp) {
|
if (isInstalledApp) {
|
||||||
|
@ -350,6 +350,7 @@ export const useChatWithHistory = (installedAppInfo?: InstalledApp) => {
|
||||||
}, [isInstalledApp, appId, t, notify])
|
}, [isInstalledApp, appId, t, notify])
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
appInfoError,
|
||||||
appInfoLoading,
|
appInfoLoading,
|
||||||
isInstalledApp,
|
isInstalledApp,
|
||||||
appId,
|
appId,
|
||||||
|
|
|
@ -17,6 +17,7 @@ import type { InstalledApp } from '@/models/explore'
|
||||||
import Loading from '@/app/components/base/loading'
|
import Loading from '@/app/components/base/loading'
|
||||||
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
|
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
|
||||||
import { checkOrSetAccessToken } from '@/app/components/share/utils'
|
import { checkOrSetAccessToken } from '@/app/components/share/utils'
|
||||||
|
import AppUnavailable from '@/app/components/base/app-unavailable'
|
||||||
|
|
||||||
type ChatWithHistoryProps = {
|
type ChatWithHistoryProps = {
|
||||||
className?: string
|
className?: string
|
||||||
|
@ -25,6 +26,7 @@ const ChatWithHistory: FC<ChatWithHistoryProps> = ({
|
||||||
className,
|
className,
|
||||||
}) => {
|
}) => {
|
||||||
const {
|
const {
|
||||||
|
appInfoError,
|
||||||
appData,
|
appData,
|
||||||
appInfoLoading,
|
appInfoLoading,
|
||||||
appPrevChatList,
|
appPrevChatList,
|
||||||
|
@ -53,6 +55,12 @@ const ChatWithHistory: FC<ChatWithHistoryProps> = ({
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (appInfoError) {
|
||||||
|
return (
|
||||||
|
<AppUnavailable />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`h-full flex bg-white ${className} ${isMobile && 'flex-col'}`}>
|
<div className={`h-full flex bg-white ${className} ${isMobile && 'flex-col'}`}>
|
||||||
{
|
{
|
||||||
|
@ -100,6 +108,7 @@ const ChatWithHistoryWrap: FC<ChatWithHistoryWrapProps> = ({
|
||||||
const isMobile = media === MediaType.mobile
|
const isMobile = media === MediaType.mobile
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
appInfoError,
|
||||||
appInfoLoading,
|
appInfoLoading,
|
||||||
appData,
|
appData,
|
||||||
appParams,
|
appParams,
|
||||||
|
@ -132,6 +141,7 @@ const ChatWithHistoryWrap: FC<ChatWithHistoryWrapProps> = ({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ChatWithHistoryContext.Provider value={{
|
<ChatWithHistoryContext.Provider value={{
|
||||||
|
appInfoError,
|
||||||
appInfoLoading,
|
appInfoLoading,
|
||||||
appData,
|
appData,
|
||||||
appParams,
|
appParams,
|
||||||
|
@ -172,15 +182,32 @@ const ChatWithHistoryWrapWithCheckToken: FC<ChatWithHistoryWrapProps> = ({
|
||||||
className,
|
className,
|
||||||
}) => {
|
}) => {
|
||||||
const [inited, setInited] = useState(false)
|
const [inited, setInited] = useState(false)
|
||||||
|
const [appUnavailable, setAppUnavailable] = useState<boolean>(false)
|
||||||
|
const [isUnknwonReason, setIsUnknwonReason] = useState<boolean>(false)
|
||||||
|
|
||||||
useAsyncEffect(async () => {
|
useAsyncEffect(async () => {
|
||||||
if (!inited) {
|
if (!inited) {
|
||||||
if (!installedAppInfo)
|
if (!installedAppInfo) {
|
||||||
await checkOrSetAccessToken()
|
try {
|
||||||
|
await checkOrSetAccessToken()
|
||||||
|
}
|
||||||
|
catch (e: any) {
|
||||||
|
if (e.status === 404) {
|
||||||
|
setAppUnavailable(true)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
setIsUnknwonReason(true)
|
||||||
|
setAppUnavailable(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
setInited(true)
|
setInited(true)
|
||||||
}
|
}
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
|
if (appUnavailable)
|
||||||
|
return <AppUnavailable isUnknwonReason={isUnknwonReason} />
|
||||||
|
|
||||||
if (!inited)
|
if (!inited)
|
||||||
return null
|
return null
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user