diff --git a/web/app/components/app/chat/answer/index.tsx b/web/app/components/app/chat/answer/index.tsx index ae3fd18429..124f32b913 100644 --- a/web/app/components/app/chat/answer/index.tsx +++ b/web/app/components/app/chat/answer/index.tsx @@ -1,6 +1,6 @@ 'use client' import type { FC, ReactNode } from 'react' -import React, { useEffect, useRef, useState } from 'react' +import React, { useState } from 'react' import { useTranslation } from 'react-i18next' import { UserCircleIcon } from '@heroicons/react/24/solid' import cn from 'classnames' @@ -27,7 +27,6 @@ import type { Emoji } from '@/app/components/tools/types' import type { VisionFile } from '@/types/app' import ImageGallery from '@/app/components/base/image-gallery' import Log from '@/app/components/app/chat/log' -import PromptLogModal from '@/app/components/base/prompt-log-modal' const IconWrapper: FC<{ children: React.ReactNode | string }> = ({ children }) => { return
@@ -234,23 +233,9 @@ const Answer: FC = ({
) - const [showPromptLogModal, setShowPromptLogModal] = useState(false) - const [width, setWidth] = useState(0) - - const ref = useRef(null) - - const adjustModalWidth = () => { - if (ref.current) - setWidth(document.body.clientWidth - (ref.current?.clientWidth + 56 + 16)) - } - - useEffect(() => { - adjustModalWidth() - }, []) - return ( // data-id for debug the item message is right -
+
{ answerIcon || ( @@ -336,7 +321,7 @@ const Answer: FC = ({ {((isShowPromptLog && !isResponding) || (!item.isOpeningStatement && isShowTextToSpeech)) && (
{isShowPromptLog && !isResponding && ( - + )} {!item.isOpeningStatement && isShowTextToSpeech && ( <> @@ -386,13 +371,6 @@ const Answer: FC = ({ {!feedbackDisabled && renderFeedbackRating(feedback?.rating, !isHideFeedbackEdit, displayScene !== 'console')}
- {showPromptLogModal && ( - setShowPromptLogModal(false)} - /> - )} {more && }
diff --git a/web/app/components/app/chat/log/index.tsx b/web/app/components/app/chat/log/index.tsx index cb7e6520de..68a36813f6 100644 --- a/web/app/components/app/chat/log/index.tsx +++ b/web/app/components/app/chat/log/index.tsx @@ -1,43 +1,32 @@ -import type { Dispatch, FC, ReactNode, SetStateAction } from 'react' +import type { FC } from 'react' import { useTranslation } from 'react-i18next' import { File02 } from '@/app/components/base/icons/src/vender/line/files' - -export type LogData = { - role: string - text: string -} +import type { IChatItem } from '@/app/components/app/chat/type' +import { useStore as useAppStore } from '@/app/components/app/store' type LogProps = { - runID?: string - setShowModal: Dispatch> - children?: (v: Dispatch>) => ReactNode + logItem: IChatItem } const Log: FC = ({ - children, - runID, - setShowModal, + logItem, }) => { const { t } = useTranslation() + const { setCurrentLogItem, setShowPromptLogModal } = useAppStore() + const { workflow_run_id: runID } = logItem return ( - <> - { - children - ? children(setShowModal) - : ( -
{ - e.stopPropagation() - setShowModal(true) - }} - > - -
{runID ? t('appLog.viewLog') : t('appLog.promptLog')}
-
- ) - } - +
{ + e.stopPropagation() + e.nativeEvent.stopImmediatePropagation() + setCurrentLogItem(logItem) + setShowPromptLogModal(true) + }} + > + +
{runID ? t('appLog.viewLog') : t('appLog.promptLog')}
+
) } diff --git a/web/app/components/app/log/list.tsx b/web/app/components/app/log/list.tsx index 49ad61fe32..1db85f9859 100644 --- a/web/app/components/app/log/list.tsx +++ b/web/app/components/app/log/list.tsx @@ -1,6 +1,6 @@ 'use client' import type { FC } from 'react' -import React, { useEffect, useState } from 'react' +import React, { useEffect, useRef, useState } from 'react' import useSWR from 'swr' import { HandThumbDownIcon, @@ -35,6 +35,8 @@ import ModelName from '@/app/components/header/account-setting/model-provider-pa import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints' import TextGeneration from '@/app/components/app/text-generate/item' import { addFileInfos, sortAgentSorts } from '@/app/components/tools/utils' +import PromptLogModal from '@/app/components/base/prompt-log-modal' +import { useStore as useAppStore } from '@/app/components/app/store' type IConversationList = { logs?: ChatConversationsResponse | CompletionConversationsResponse @@ -141,6 +143,7 @@ type IDetailPanel = { function DetailPanel({ detail, onFeedback }: IDetailPanel) { const { onClose, appDetail } = useContext(DrawerContext) + const { currentLogItem, setCurrentLogItem, showPromptLogModal, setShowPromptLogModal } = useAppStore() const { t } = useTranslation() const [items, setItems] = React.useState([]) const [hasMore, setHasMore] = useState(true) @@ -228,144 +231,168 @@ function DetailPanel - {/* Panel Header */} -
-
-
{isChatMode ? t('appLog.detail.conversationId') : t('appLog.detail.time')}
-
{isChatMode ? detail.id?.split('-').slice(-1)[0] : dayjs.unix(detail.created_at).format(t('appLog.dateTimeFormat') as string)}
-
-
-
- - + const [width, setWidth] = useState(0) + const ref = useRef(null) + + const adjustModalWidth = () => { + if (ref.current) + setWidth(document.body.clientWidth - (ref.current?.clientWidth + 16) - 8) + } + + useEffect(() => { + adjustModalWidth() + }, []) + + return ( +
+ {/* Panel Header */} +
+
+
{isChatMode ? t('appLog.detail.conversationId') : t('appLog.detail.time')}
+
{isChatMode ? detail.id?.split('-').slice(-1)[0] : dayjs.unix(detail.created_at).format(t('appLog.dateTimeFormat') as string)}
- - {targetTone} - - } - htmlContent={
-
- Tone of responses -
{targetTone}
-
- {['temperature', 'top_p', 'presence_penalty', 'max_tokens', 'stop'].map((param: string, index: number) => { - return
- {PARAM_MAP[param as keyof typeof PARAM_MAP]} - {getParamValue(param)} +
+
+ + +
+ + {targetTone} + + } + htmlContent={
+
+ Tone of responses +
{targetTone}
- })} -
} - /> -
- + {['temperature', 'top_p', 'presence_penalty', 'max_tokens', 'stop'].map((param: string, index: number) => { + return
+ {PARAM_MAP[param as keyof typeof PARAM_MAP]} + {getParamValue(param)} +
+ })} +
} + /> +
+ +
-
-
- {/* Panel Body */} - {(varList.length > 0 || (!isChatMode && message_files.length > 0)) && ( -
-
- )} - - {!isChatMode - ?
-
-
{t('appLog.table.header.output')}
-
+ {/* Panel Body */} + {(varList.length > 0 || (!isChatMode && message_files.length > 0)) && ( +
+
- { }} - isInstalledApp={false} - supportFeedback - feedback={detail.message.feedbacks.find((item: any) => item.from_source === 'admin')} - onFeedback={feedback => onFeedback(detail.message.id, feedback)} - supportAnnotation - isShowTextToSpeech - appId={appDetail?.id} - varList={varList} - /> -
- : items.length < 8 - ?
- +
+
{t('appLog.table.header.output')}
+
+
+ { }} + isInstalledApp={false} + supportFeedback + feedback={detail.message.feedbacks.find((item: any) => item.from_source === 'admin')} + onFeedback={feedback => onFeedback(detail.message.id, feedback)} supportAnnotation isShowTextToSpeech appId={appDetail?.id} - onChatListChange={setItems} + varList={varList} />
- :
- {/* Put the scroll bar always on the bottom */} - {t('appLog.detail.loading')}...
} - // endMessage={
Nothing more to show
} - // below props only if you need pull down functionality - refreshFunction={fetchData} - pullDownToRefresh - pullDownToRefreshThreshold={50} - // pullDownToRefreshContent={ - //
Pull down to refresh
- // } - // releaseToRefreshContent={ - //
Release to refresh
- // } - // To put endMessage and loader to the top. - style={{ display: 'flex', flexDirection: 'column-reverse' }} - inverse={true} - > + : items.length < 8 + ?
- -
- } -
) +
+ :
+ {/* Put the scroll bar always on the bottom */} + {t('appLog.detail.loading')}...
} + // endMessage={
Nothing more to show
} + // below props only if you need pull down functionality + refreshFunction={fetchData} + pullDownToRefresh + pullDownToRefreshThreshold={50} + // pullDownToRefreshContent={ + //
Pull down to refresh
+ // } + // releaseToRefreshContent={ + //
Release to refresh
+ // } + // To put endMessage and loader to the top. + style={{ display: 'flex', flexDirection: 'column-reverse' }} + inverse={true} + > + + +
+ } + {showPromptLogModal && ( + { + setCurrentLogItem() + setShowPromptLogModal(false) + }} + /> + )} +
+ ) } /** diff --git a/web/app/components/app/store.ts b/web/app/components/app/store.ts index 4d2a501bd3..1c813ecb11 100644 --- a/web/app/components/app/store.ts +++ b/web/app/components/app/store.ts @@ -1,14 +1,21 @@ import { create } from 'zustand' import type { App } from '@/types/app' +import type { IChatItem } from '@/app/components/app/chat/type' type State = { appDetail?: App appSidebarExpand: string + currentLogItem?: IChatItem + showPromptLogModal: boolean + showMessageLogModal: boolean } type Action = { setAppDetail: (appDetail?: App) => void setAppSiderbarExpand: (state: string) => void + setCurrentLogItem: (item?: IChatItem) => void + setShowPromptLogModal: (showPromptLogModal: boolean) => void + setShowMessageLogModal: (showMessageLogModal: boolean) => void } export const useStore = create(set => ({ @@ -16,4 +23,10 @@ export const useStore = create(set => ({ setAppDetail: appDetail => set(() => ({ appDetail })), appSidebarExpand: '', setAppSiderbarExpand: appSidebarExpand => set(() => ({ appSidebarExpand })), + currentLogItem: undefined, + setCurrentLogItem: currentLogItem => set(() => ({ currentLogItem })), + showPromptLogModal: false, + setShowPromptLogModal: showPromptLogModal => set(() => ({ showPromptLogModal })), + showMessageLogModal: false, + setShowMessageLogModal: showMessageLogModal => set(() => ({ showMessageLogModal })), })) diff --git a/web/app/components/base/chat/chat/answer/index.tsx b/web/app/components/base/chat/chat/answer/index.tsx index d50a978654..e64a9ae3ed 100644 --- a/web/app/components/base/chat/chat/answer/index.tsx +++ b/web/app/components/base/chat/chat/answer/index.tsx @@ -2,7 +2,7 @@ import type { FC, ReactNode, } from 'react' -import { memo, useEffect, useRef, useState } from 'react' +import { memo } from 'react' import { useTranslation } from 'react-i18next' import type { ChatConfig, @@ -18,7 +18,6 @@ import LoadingAnim from '@/app/components/app/chat/loading-anim' import Citation from '@/app/components/app/chat/citation' import { EditTitle } from '@/app/components/app/annotation/edit-annotation-modal/edit-item' import type { Emoji } from '@/app/components/tools/types' -import PromptLogModal from '@/app/components/base/prompt-log-modal' type AnswerProps = { item: ChatItem @@ -50,22 +49,8 @@ const Answer: FC = ({ } = item const hasAgentThoughts = !!agent_thoughts?.length - const [showPromptLogModal, setShowPromptLogModal] = useState(false) - const [width, setWidth] = useState(0) - - const ref = useRef(null) - - const adjustModalWidth = () => { - if (ref.current) - setWidth(document.body.clientWidth - (ref.current?.clientWidth + 56 + 16)) - } - - useEffect(() => { - adjustModalWidth() - }, []) - return ( -
+
{ answerIcon || ( @@ -93,7 +78,6 @@ const Answer: FC = ({ question={question} index={index} showPromptLog={showPromptLog} - setShowPromptLogModal={setShowPromptLogModal} /> ) } @@ -136,13 +120,6 @@ const Answer: FC = ({
- {showPromptLogModal && ( - setShowPromptLogModal(false)} - /> - )}
) } diff --git a/web/app/components/base/chat/chat/answer/operation.tsx b/web/app/components/base/chat/chat/answer/operation.tsx index e824b051e8..2a56c69d33 100644 --- a/web/app/components/base/chat/chat/answer/operation.tsx +++ b/web/app/components/base/chat/chat/answer/operation.tsx @@ -1,4 +1,4 @@ -import type { Dispatch, FC, SetStateAction } from 'react' +import type { FC } from 'react' import { memo, useMemo, @@ -24,14 +24,12 @@ type OperationProps = { question: string index: number showPromptLog?: boolean - setShowPromptLogModal: Dispatch> } const Operation: FC = ({ item, question, index, showPromptLog, - setShowPromptLogModal, }) => { const { t } = useTranslation() const { @@ -79,7 +77,7 @@ const Operation: FC = ({
{showPromptLog && ( - + )} {(!isOpeningStatement && config?.text_to_speech?.enabled) && ( <> diff --git a/web/app/components/base/chat/chat/index.tsx b/web/app/components/base/chat/chat/index.tsx index 8792eff759..7313437ffb 100644 --- a/web/app/components/base/chat/chat/index.tsx +++ b/web/app/components/base/chat/chat/index.tsx @@ -6,6 +6,7 @@ import { memo, useEffect, useRef, + useState, } from 'react' import { useTranslation } from 'react-i18next' import { useThrottleEffect } from 'ahooks' @@ -24,6 +25,8 @@ import { ChatContextProvider } from './context' import type { Emoji } from '@/app/components/tools/types' import Button from '@/app/components/base/button' import { StopCircle } from '@/app/components/base/icons/src/vender/solid/mediaAndDevices' +import PromptLogModal from '@/app/components/base/prompt-log-modal' +import { useStore as useAppStore } from '@/app/components/app/store' export type ChatProps = { chatList: ChatItem[] @@ -72,6 +75,8 @@ const Chat: FC = ({ onFeedback, }) => { const { t } = useTranslation() + const { currentLogItem, setCurrentLogItem, showPromptLogModal, setShowPromptLogModal } = useAppStore() + const [width, setWidth] = useState(0) const chatContainerRef = useRef(null) const chatContainerInnerRef = useRef(null) const chatFooterRef = useRef(null) @@ -83,6 +88,9 @@ const Chat: FC = ({ } const handleWindowResize = () => { + if (chatContainerRef.current) + setWidth(document.body.clientWidth - (chatContainerRef.current?.clientWidth + 16) - 8) + if (chatContainerRef.current && chatFooterRef.current) chatFooterRef.current.style.width = `${chatContainerRef.current.clientWidth}px` @@ -215,6 +223,16 @@ const Chat: FC = ({ }
+ {showPromptLogModal && ( + { + setCurrentLogItem() + setShowPromptLogModal(false) + }} + /> + )}
) diff --git a/web/app/components/base/prompt-log-modal/index.tsx b/web/app/components/base/prompt-log-modal/index.tsx index f0e5b27dde..49585468fe 100644 --- a/web/app/components/base/prompt-log-modal/index.tsx +++ b/web/app/components/base/prompt-log-modal/index.tsx @@ -4,15 +4,15 @@ import { useClickAway } from 'ahooks' import Card from './card' import { CopyFeedbackNew } from '@/app/components/base/copy-feedback' import { XClose } from '@/app/components/base/icons/src/vender/line/general' -import type { VisionFile } from '@/types/app' +import type { IChatItem } from '@/app/components/app/chat/type' type PromptLogModalProps = { - log: { role: string; text: string; files?: VisionFile[] }[] + currentLogItem?: IChatItem width: number onCancel: () => void } const PromptLogModal: FC = ({ - log, + currentLogItem, width, onCancel, }) => { @@ -20,17 +20,15 @@ const PromptLogModal: FC = ({ const [mounted, setMounted] = useState(false) useClickAway(() => { - if (mounted) { - console.log(111) + if (mounted) onCancel() - } }, ref) useEffect(() => { setMounted(true) }, []) - if (!log) + if (!currentLogItem || !currentLogItem.log) return null return ( @@ -43,9 +41,9 @@ const PromptLogModal: FC = ({
PROMPT LOG
{ - log?.length === 1 && ( + currentLogItem.log?.length === 1 && ( <> - +
) @@ -59,7 +57,7 @@ const PromptLogModal: FC = ({
- +
) diff --git a/web/app/components/share/chatbot/index.tsx b/web/app/components/share/chatbot/index.tsx index d31c6d691c..cc6577487a 100644 --- a/web/app/components/share/chatbot/index.tsx +++ b/web/app/components/share/chatbot/index.tsx @@ -729,7 +729,7 @@ const Main: FC = ({ title={siteInfo.title} icon='' customerIcon={difyIcon} - icon_background={siteInfo.icon_background} + icon_background={siteInfo.icon_background || ''} isEmbedScene={true} isMobile={isMobile} onCreateNewChat={() => handleConversationIdChange('-1')}