diff --git a/web/app/components/app/app-publisher/index.tsx b/web/app/components/app/app-publisher/index.tsx index a2a4433cfa..fa7b9ed344 100644 --- a/web/app/components/app/app-publisher/index.tsx +++ b/web/app/components/app/app-publisher/index.tsx @@ -5,55 +5,68 @@ import { } from 'react' import { useTranslation } from 'react-i18next' import dayjs from 'dayjs' +import classNames from 'classnames' +import type { ModelAndParameter } from '../configuration/debug/types' import SuggestedAction from './suggested-action' +import PublishWithMultipleModel from './publish-with-multiple-model' import Button from '@/app/components/base/button' import { PortalToFollowElem, PortalToFollowElemContent, PortalToFollowElemTrigger, } from '@/app/components/base/portal-to-follow-elem' +import EmbeddedModal from '@/app/components/app/overview/embedded' import { useStore as useAppStore } from '@/app/components/app/store' +import { useGetLanguage } from '@/context/i18n' import { ChevronDown } from '@/app/components/base/icons/src/vender/line/arrows' import { PlayCircle } from '@/app/components/base/icons/src/vender/line/mediaAndDevices' import { CodeBrowser } from '@/app/components/base/icons/src/vender/line/development' import { LeftIndent02 } from '@/app/components/base/icons/src/vender/line/editor' import { FileText } from '@/app/components/base/icons/src/vender/line/files' -import { useGetLanguage } from '@/context/i18n' export type AppPublisherProps = { disabled?: boolean + publishDisabled?: boolean publishedAt?: number /** only needed in workflow / chatflow mode */ draftUpdatedAt?: number - onPublish?: () => Promise | void - onRestore?: () => Promise | void + debugWithMultipleModel?: boolean + multipleModelConfigs?: ModelAndParameter[] + /** modelAndParameter is passed when debugWithMultipleModel is true */ + onPublish?: (modelAndParameter?: ModelAndParameter) => Promise | any + onRestore?: () => Promise | any onToggle?: (state: boolean) => void + crossAxisOffset?: number } const AppPublisher = ({ disabled = false, + publishDisabled = false, publishedAt, draftUpdatedAt, + debugWithMultipleModel = false, + multipleModelConfigs = [], onPublish, onRestore, onToggle, + crossAxisOffset = 0, }: AppPublisherProps) => { const { t } = useTranslation() const [published, setPublished] = useState(false) const [open, setOpen] = useState(false) const appDetail = useAppStore(state => state.appDetail) - const { app_base_url: appBaseURL, access_token } = appDetail?.site ?? {} + const { app_base_url: appBaseURL = '', access_token: accessToken = '' } = appDetail?.site ?? {} const appMode = (appDetail?.mode !== 'completion' && appDetail?.mode !== 'workflow') ? 'chat' : appDetail.mode - const appURL = `${appBaseURL}/${appMode}/${access_token}` + const appURL = `${appBaseURL}/${appMode}/${accessToken}` const language = useGetLanguage() const formatTimeFromNow = useCallback((time: number) => { return dayjs(time).locale(language === 'zh_Hans' ? 'zh-cn' : language.replace('_', '-')).fromNow() }, [language]) - const handlePublish = async () => { + const handlePublish = async (modelAndParameter?: ModelAndParameter) => { try { - await onPublish?.() + await onPublish?.(modelAndParameter) setPublished(true) } catch (e) { @@ -70,22 +83,22 @@ const AppPublisher = ({ }, [onRestore]) const handleTrigger = useCallback(() => { + const state = !open + if (disabled) { setOpen(false) return } - onToggle?.(!open) + onToggle?.(state) + setOpen(state) - if (open) { - setOpen(false) - } - else { - setOpen(true) + if (state) setPublished(false) - } }, [disabled, onToggle, open]) + const [embeddingModalOpen, setEmbeddingModalOpen] = useState(false) + return ( @@ -137,35 +150,68 @@ const AppPublisher = ({ {t('workflow.common.autoSaved')} ยท {Boolean(draftUpdatedAt) && formatTimeFromNow(draftUpdatedAt!)} )} - + {debugWithMultipleModel + ? ( + handlePublish(item)} + // textGenerationModelList={textGenerationModelList} + /> + ) + : ( + + ) + }
}>{t('workflow.common.runApp')} - {appMode === 'chat' + {appDetail?.mode === 'workflow' ? ( - }>{t('workflow.common.embedIntoSite')} + } + > + {t('workflow.common.batchRunApp')} + ) : ( - }>{t('workflow.common.batchRunApp')} + { + setEmbeddingModalOpen(true) + handleTrigger() + }} + disabled={!publishedAt} + icon={} + > + {t('workflow.common.embedIntoSite')} + )} }>{t('workflow.common.accessAPIReference')}
+ setEmbeddingModalOpen(false)} + appBaseUrl={appBaseURL} + accessToken={accessToken} + className='z-50' + />
) } diff --git a/web/app/components/app/configuration/debug/debug-with-multiple-model/publish-with-multiple-model.tsx b/web/app/components/app/app-publisher/publish-with-multiple-model.tsx similarity index 72% rename from web/app/components/app/configuration/debug/debug-with-multiple-model/publish-with-multiple-model.tsx rename to web/app/components/app/app-publisher/publish-with-multiple-model.tsx index be544bd362..3396aab5d6 100644 --- a/web/app/components/app/configuration/debug/debug-with-multiple-model/publish-with-multiple-model.tsx +++ b/web/app/components/app/app-publisher/publish-with-multiple-model.tsx @@ -1,7 +1,8 @@ import type { FC } from 'react' import { useState } from 'react' import { useTranslation } from 'react-i18next' -import type { ModelAndParameter } from '../types' +import type { ModelAndParameter } from '../configuration/debug/types' +import ModelIcon from '../../header/account-setting/model-provider-page/model-icon' import Button from '@/app/components/base/button' import { PortalToFollowElem, @@ -10,15 +11,17 @@ import { } from '@/app/components/base/portal-to-follow-elem' import { ChevronDown } from '@/app/components/base/icons/src/vender/line/arrows' import { useProviderContext } from '@/context/provider-context' -import type { ModelItem } from '@/app/components/header/account-setting/model-provider-page/declarations' +import type { Model, ModelItem } from '@/app/components/header/account-setting/model-provider-page/declarations' import { useLanguage } from '@/app/components/header/account-setting/model-provider-page/hooks' type PublishWithMultipleModelProps = { multipleModelConfigs: ModelAndParameter[] + // textGenerationModelList?: Model[] onSelect: (v: ModelAndParameter) => void } const PublishWithMultipleModel: FC = ({ multipleModelConfigs, + // textGenerationModelList = [], onSelect, }) => { const { t } = useTranslation() @@ -26,7 +29,7 @@ const PublishWithMultipleModel: FC = ({ const { textGenerationModelList } = useProviderContext() const [open, setOpen] = useState(false) - const validModelConfigs: (ModelAndParameter & { modelItem: ModelItem })[] = [] + const validModelConfigs: (ModelAndParameter & { modelItem: ModelItem; providerItem: Model })[] = [] multipleModelConfigs.forEach((item) => { const provider = textGenerationModelList.find(model => model.provider === item.provider) @@ -40,6 +43,7 @@ const PublishWithMultipleModel: FC = ({ model: item.model, provider: item.provider, modelItem: model, + providerItem: provider, parameters: item.parameters, }) } @@ -62,18 +66,18 @@ const PublishWithMultipleModel: FC = ({ onOpenChange={setOpen} placement='bottom-end' > - + - -
+ +
{t('appDebug.publishAs')}
@@ -81,10 +85,11 @@ const PublishWithMultipleModel: FC = ({ validModelConfigs.map((item, index) => (
handleSelect(item)} > - #{index + 1} + #{index + 1} +
& { icon?: React.ReactNode link?: string disabled?: boolean }> -const SuggestedAction = ({ icon, link, disabled, children }: SuggestedActionProps) => ( - +const SuggestedAction = ({ icon, link, disabled, children, className, ...props }: SuggestedActionProps) => ( +
{icon}
{children}
diff --git a/web/app/components/app/configuration/index.tsx b/web/app/components/app/configuration/index.tsx index 07c4882fd2..fc37de33a2 100644 --- a/web/app/components/app/configuration/index.tsx +++ b/web/app/components/app/configuration/index.tsx @@ -1,16 +1,16 @@ 'use client' import type { FC } from 'react' -import React, { useEffect, useRef, useState } from 'react' +import React, { useEffect, useMemo, useRef, useState } from 'react' import { useTranslation } from 'react-i18next' import { useContext } from 'use-context-selector' import { usePathname } from 'next/navigation' import produce from 'immer' import { useBoolean, useGetState } from 'ahooks' -import cn from 'classnames' import { clone, isEqual } from 'lodash-es' import { CodeBracketIcon } from '@heroicons/react/20/solid' import Button from '../../base/button' import Loading from '../../base/loading' +import AppPublisher from '../app-publisher' import AgentSettingButton from './config/agent-setting-button' import useAdvancedPromptConfig from './hooks/use-advanced-prompt-config' import EditHistoryModal from './config-prompt/conversation-histroy/edit-modal' @@ -19,7 +19,6 @@ import { useFormattingChangedDispatcher, } from './debug/hooks' import type { ModelAndParameter } from './debug/types' -import PublishWithMultipleModel from './debug/debug-with-multiple-model/publish-with-multiple-model' import type { AnnotationReplyConfig, DatasetConfigs, @@ -66,7 +65,7 @@ type PublichConfig = { const Configuration: FC = () => { const { t } = useTranslation() const { notify } = useContext(ToastContext) - const { setAppSiderbarExpand } = useAppStore() + const { appDetail, setAppSiderbarExpand } = useAppStore() const [formattingChanged, setFormattingChanged] = useState(false) const { setShowAccountSettingModal } = useModalContext() const [hasFetchedDetail, setHasFetchedDetail] = useState(false) @@ -77,6 +76,7 @@ const Configuration: FC = () => { const [mode, setMode] = useState('') const [publishedConfig, setPublishedConfig] = useState(null) + const modalConfig = useMemo(() => appDetail?.model_config || {} as BackendModelConfig, [appDetail]) const [conversationId, setConversationId] = useState('') const media = useBreakpoints() @@ -130,7 +130,7 @@ const Configuration: FC = () => { const [inputs, setInputs] = useState({}) const [query, setQuery] = useState('') const [completionParams, doSetCompletionParams] = useState({}) - const [tempStop, setTempStop, getTempStop] = useGetState([]) + const [_, setTempStop, getTempStop] = useGetState([]) const setCompletionParams = (value: FormValue) => { const params = { ...value } @@ -508,6 +508,7 @@ const Configuration: FC = () => { setHasFetchedDetail(true) }) })() + // eslint-disable-next-line react-hooks/exhaustive-deps }, [appId]) const promptEmpty = (() => { @@ -541,7 +542,7 @@ const Configuration: FC = () => { else { return promptEmpty } })() const contextVarEmpty = mode === AppType.completion && dataSets.length > 0 && !hasSetContextVar - const handlePublish = async (isSilence?: boolean, modelAndParameter?: ModelAndParameter) => { + const onPublish = async (modelAndParameter?: ModelAndParameter) => { const modelId = modelAndParameter?.model || modelConfig.model_id const promptTemplate = modelConfig.configs.prompt_template const promptVariables = modelConfig.configs.prompt_variables @@ -630,17 +631,16 @@ const Configuration: FC = () => { modelConfig: newModelConfig, completionParams, }) - if (!isSilence) - notify({ type: 'success', message: t('common.api.success'), duration: 3000 }) + notify({ type: 'success', message: t('common.api.success'), duration: 3000 }) setCanReturnToSimpleMode(false) return true } - const [showConfirm, setShowConfirm] = useState(false) + const [restoreConfirmOpen, setRestoreConfirmOpen] = useState(false) const resetAppConfig = () => { syncToPublishedConfig(publishedConfig!) - setShowConfirm(false) + setRestoreConfirmOpen(false) } const [showUseGPT4Confirm, setShowUseGPT4Confirm] = useState(false) @@ -788,26 +788,20 @@ const Configuration: FC = () => {
)} - {isMobile && ( )} - {debugWithMultipleModel - ? ( handlePublish(false, item)} - />) - : ()} - {/* */} + setRestoreConfirmOpen(true), + }} />
@@ -832,14 +826,14 @@ const Configuration: FC = () => {
} - {showConfirm && ( + {restoreConfirmOpen && ( setShowConfirm(false)} + isShow={restoreConfirmOpen} + onClose={() => setRestoreConfirmOpen(false)} onConfirm={resetAppConfig} - onCancel={() => setShowConfirm(false)} + onCancel={() => setRestoreConfirmOpen(false)} /> )} {showUseGPT4Confirm && ( diff --git a/web/app/components/app/overview/embedded/index.tsx b/web/app/components/app/overview/embedded/index.tsx index f53e6efee3..f9e9e999e6 100644 --- a/web/app/components/app/overview/embedded/index.tsx +++ b/web/app/components/app/overview/embedded/index.tsx @@ -14,6 +14,7 @@ type Props = { onClose: () => void accessToken: string appBaseUrl: string + className?: string } const OPTION_MAP = { @@ -22,19 +23,19 @@ const OPTION_MAP = { ``, }, scripts: { getContent: (url: string, token: string, isTestEnv?: boolean) => `