diff --git a/api/controllers/console/app/site.py b/api/controllers/console/app/site.py index ff832ac5da..2024db65b2 100644 --- a/api/controllers/console/app/site.py +++ b/api/controllers/console/app/site.py @@ -28,6 +28,7 @@ def parse_app_site_args(): required=False, location='json') parser.add_argument('prompt_public', type=bool, required=False, location='json') + parser.add_argument('show_workflow_steps', type=bool, required=False, location='json') return parser.parse_args() @@ -59,7 +60,8 @@ class AppSite(Resource): 'privacy_policy', 'custom_disclaimer', 'customize_token_strategy', - 'prompt_public' + 'prompt_public', + 'show_workflow_steps' ]: value = args.get(attr_name) if value is not None: diff --git a/api/controllers/web/site.py b/api/controllers/web/site.py index a084b56b08..c5c70d810a 100644 --- a/api/controllers/web/site.py +++ b/api/controllers/web/site.py @@ -33,7 +33,8 @@ class AppSiteApi(WebApiResource): 'privacy_policy': fields.String, 'custom_disclaimer': fields.String, 'default_language': fields.String, - 'prompt_public': fields.Boolean + 'prompt_public': fields.Boolean, + 'show_workflow_steps': fields.Boolean, } app_fields = { diff --git a/api/fields/app_fields.py b/api/fields/app_fields.py index 212c3e7f17..e314fa21a3 100644 --- a/api/fields/app_fields.py +++ b/api/fields/app_fields.py @@ -117,6 +117,7 @@ site_fields = { 'customize_token_strategy': fields.String, 'prompt_public': fields.Boolean, 'app_base_url': fields.String, + 'show_workflow_steps': fields.Boolean, } app_detail_fields_with_site = { @@ -149,5 +150,6 @@ app_site_fields = { 'privacy_policy': fields.String, 'custom_disclaimer': fields.String, 'customize_token_strategy': fields.String, - 'prompt_public': fields.Boolean + 'prompt_public': fields.Boolean, + 'show_workflow_steps': fields.Boolean, } diff --git a/api/migrations/versions/4ff534e1eb11_add_workflow_to_site.py b/api/migrations/versions/4ff534e1eb11_add_workflow_to_site.py new file mode 100644 index 0000000000..c09cf2af60 --- /dev/null +++ b/api/migrations/versions/4ff534e1eb11_add_workflow_to_site.py @@ -0,0 +1,33 @@ +"""add workflow to site + +Revision ID: 4ff534e1eb11 +Revises: 7b45942e39bb +Create Date: 2024-06-21 04:16:03.419634 + +""" +import sqlalchemy as sa +from alembic import op + +import models as models + +# revision identifiers, used by Alembic. +revision = '4ff534e1eb11' +down_revision = '7b45942e39bb' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + with op.batch_alter_table('sites', schema=None) as batch_op: + batch_op.add_column(sa.Column('show_workflow_steps', sa.Boolean(), server_default=sa.text('true'), nullable=False)) + + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + with op.batch_alter_table('sites', schema=None) as batch_op: + batch_op.drop_column('show_workflow_steps') + + # ### end Alembic commands ### diff --git a/api/models/model.py b/api/models/model.py index 657db5a5c2..3024be0b4c 100644 --- a/api/models/model.py +++ b/api/models/model.py @@ -1043,6 +1043,7 @@ class Site(db.Model): default_language = db.Column(db.String(255), nullable=False) copyright = db.Column(db.String(255)) privacy_policy = db.Column(db.String(255)) + show_workflow_steps = db.Column(db.Boolean, nullable=False, server_default=db.text('true')) custom_disclaimer = db.Column(db.String(255), nullable=True) customize_domain = db.Column(db.String(255)) customize_token_strategy = db.Column(db.String(255), nullable=False) diff --git a/web/app/components/app/overview/settings/index.tsx b/web/app/components/app/overview/settings/index.tsx index 78e26dd167..01bd5525e2 100644 --- a/web/app/components/app/overview/settings/index.tsx +++ b/web/app/components/app/overview/settings/index.tsx @@ -34,6 +34,7 @@ export type ConfigParams = { custom_disclaimer: string icon: string icon_background: string + show_workflow_steps: boolean } const prefixSettings = 'appOverview.overview.appInfo.settings' @@ -47,8 +48,8 @@ const SettingsModal: FC = ({ const { notify } = useToastContext() const [isShowMore, setIsShowMore] = useState(false) const { icon, icon_background } = appInfo - const { title, description, copyright, privacy_policy, custom_disclaimer, default_language } = appInfo.site - const [inputInfo, setInputInfo] = useState({ title, desc: description, copyright, privacyPolicy: privacy_policy, customDisclaimer: custom_disclaimer }) + const { title, description, copyright, privacy_policy, custom_disclaimer, default_language, show_workflow_steps } = appInfo.site + const [inputInfo, setInputInfo] = useState({ title, desc: description, copyright, privacyPolicy: privacy_policy, customDisclaimer: custom_disclaimer, show_workflow_steps }) const [language, setLanguage] = useState(default_language) const [saveLoading, setSaveLoading] = useState(false) const { t } = useTranslation() @@ -57,7 +58,7 @@ const SettingsModal: FC = ({ const [emoji, setEmoji] = useState({ icon, icon_background }) useEffect(() => { - setInputInfo({ title, desc: description, copyright, privacyPolicy: privacy_policy, customDisclaimer: custom_disclaimer }) + setInputInfo({ title, desc: description, copyright, privacyPolicy: privacy_policy, customDisclaimer: custom_disclaimer, show_workflow_steps }) setLanguage(default_language) setEmoji({ icon, icon_background }) }, [appInfo]) @@ -85,6 +86,7 @@ const SettingsModal: FC = ({ custom_disclaimer: inputInfo.customDisclaimer, icon: emoji.icon, icon_background: emoji.icon_background, + show_workflow_steps: inputInfo.show_workflow_steps, } await onSave?.(params) setSaveLoading(false) @@ -134,6 +136,14 @@ const SettingsModal: FC = ({ defaultValue={language} onSelect={item => setLanguage(item.value as Language)} /> + {(appInfo.mode === 'workflow' || appInfo.mode === 'advanced-chat') && <> +
{t(`${prefixSettings}.workflow.title`)}
+ setInputInfo({ ...inputInfo, show_workflow_steps: item.value === 'true' })} + /> + } {!isShowMore &&
setIsShowMore(true)}>
{t(`${prefixSettings}.more.entry`)}
diff --git a/web/app/components/app/text-generate/item/index.tsx b/web/app/components/app/text-generate/item/index.tsx index 1260c8e272..486ab90edb 100644 --- a/web/app/components/app/text-generate/item/index.tsx +++ b/web/app/components/app/text-generate/item/index.tsx @@ -28,6 +28,7 @@ import EditReplyModal from '@/app/components/app/annotation/edit-annotation-moda import { useStore as useAppStore } from '@/app/components/app/store' import WorkflowProcessItem from '@/app/components/base/chat/chat/answer/workflow-process' import type { WorkflowProcess } from '@/app/components/base/chat/types' +import type { SiteInfo } from '@/models/share' const MAX_DEPTH = 3 @@ -62,6 +63,7 @@ export type IGenerationItemProps = { contentClassName?: string footerClassName?: string hideProcessDetail?: boolean + siteInfo: SiteInfo | null } export const SimpleBtn = ({ className, isDisabled, onClick, children }: { @@ -113,6 +115,7 @@ const GenerationItem: FC = ({ innerClassName, contentClassName, hideProcessDetail, + siteInfo, }) => { const { t } = useTranslation() const params = useParams() @@ -152,6 +155,7 @@ const GenerationItem: FC = ({ installedAppId, controlClearMoreLikeThis, isWorkflow, + siteInfo, } const handleMoreLikeThis = async () => { @@ -297,7 +301,7 @@ const GenerationItem: FC = ({ }
- {workflowProcessData && ( + {siteInfo && siteInfo.show_workflow_steps && workflowProcessData && ( )} {workflowProcessData && !isError && ( diff --git a/web/app/components/base/chat/chat-with-history/chat-wrapper.tsx b/web/app/components/base/chat/chat-with-history/chat-wrapper.tsx index 99c106293d..9dcd4cc7ab 100644 --- a/web/app/components/base/chat/chat-with-history/chat-wrapper.tsx +++ b/web/app/components/base/chat/chat-with-history/chat-wrapper.tsx @@ -29,6 +29,7 @@ const ChatWrapper = () => { appMeta, handleFeedback, currentChatInstanceRef, + appData, } = useChatWithHistoryContext() const appConfig = useMemo(() => { const config = appParams || {} @@ -128,6 +129,7 @@ const ChatWrapper = () => { return ( { const { id, app } = installedAppInfo! return { app_id: id, - site: { title: app.name, icon: app.icon, icon_background: app.icon_background, prompt_public: false, copyright: '' }, + site: { + title: app.name, + icon: app.icon, + icon_background: app.icon_background, + prompt_public: false, + copyright: '', + show_workflow_steps: true, + }, plan: 'basic', } as AppData } diff --git a/web/app/components/base/chat/chat/answer/index.tsx b/web/app/components/base/chat/chat/answer/index.tsx index 4e88283663..213ac99e28 100644 --- a/web/app/components/base/chat/chat/answer/index.tsx +++ b/web/app/components/base/chat/chat/answer/index.tsx @@ -20,6 +20,7 @@ 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 type { AppData } from '@/models/share' type AnswerProps = { item: ChatItem @@ -32,6 +33,7 @@ type AnswerProps = { showPromptLog?: boolean chatAnswerContainerInner?: string hideProcessDetail?: boolean + appData?: AppData } const Answer: FC = ({ item, @@ -44,6 +46,7 @@ const Answer: FC = ({ showPromptLog, chatAnswerContainerInner, hideProcessDetail, + appData, }) => { const { t } = useTranslation() const { @@ -129,8 +132,20 @@ const Answer: FC = ({ /> ) } + {/** Render the normal steps */} { - workflowProcess && ( + workflowProcess && !hideProcessDetail && ( + + ) + } + {/** Hide workflow steps by it's settings in siteInfo */} + { + workflowProcess && hideProcessDetail && appData && appData.site.show_workflow_steps && ( = ({ + appData, config, onSend, chatList, @@ -196,6 +199,7 @@ const Chat: FC = ({ const isLast = item.id === chatList[chatList.length - 1]?.id return ( { const { + appData, appParams, appPrevChatList, currentConversationId, @@ -114,6 +115,7 @@ const ChatWrapper = () => { return ( = ({ visionConfig={visionConfig} completionFiles={completionFiles} isShowTextToSpeech={!!textToSpeechConfig?.enabled} + siteInfo={siteInfo} />) const renderBatchRes = () => { diff --git a/web/app/components/share/text-generation/result/index.tsx b/web/app/components/share/text-generation/result/index.tsx index b0c20f3b85..67210a9856 100644 --- a/web/app/components/share/text-generation/result/index.tsx +++ b/web/app/components/share/text-generation/result/index.tsx @@ -18,6 +18,7 @@ import { TransferMethod, type VisionFile, type VisionSettings } from '@/types/ap import { NodeRunningStatus, WorkflowRunningStatus } from '@/app/components/workflow/types' import type { WorkflowProcess } from '@/app/components/base/chat/types' import { sleep } from '@/utils' +import type { SiteInfo } from '@/models/share' export type IResultProps = { isWorkflow: boolean @@ -42,6 +43,7 @@ export type IResultProps = { moderationService?: (text: string) => ReturnType visionConfig: VisionSettings completionFiles: VisionFile[] + siteInfo: SiteInfo | null } const Result: FC = ({ @@ -65,6 +67,7 @@ const Result: FC = ({ onCompleted, visionConfig, completionFiles, + siteInfo, }) => { const [isResponding, { setTrue: setRespondingTrue, setFalse: setRespondingFalse }] = useBoolean(false) useEffect(() => { @@ -375,6 +378,7 @@ const Result: FC = ({ controlClearMoreLikeThis={controlClearMoreLikeThis} isShowTextToSpeech={isShowTextToSpeech} hideProcessDetail + siteInfo={siteInfo} /> ) diff --git a/web/i18n/de-DE/app-overview.ts b/web/i18n/de-DE/app-overview.ts index 98c6d2f5fa..6c043df21b 100644 --- a/web/i18n/de-DE/app-overview.ts +++ b/web/i18n/de-DE/app-overview.ts @@ -44,6 +44,11 @@ const translation = { webDescTip: 'Dieser Text wird auf der Clientseite angezeigt und bietet grundlegende Anleitungen zur Verwendung der Anwendung', webDescPlaceholder: 'Geben Sie die Beschreibung der WebApp ein', language: 'Sprache', + workflow: { + title: 'Workflow-Schritte', + show: 'Anzeigen', + hide: 'Verbergen', + }, more: { entry: 'Mehr Einstellungen anzeigen', copyright: 'Urheberrecht', diff --git a/web/i18n/en-US/app-overview.ts b/web/i18n/en-US/app-overview.ts index 0b49cb731e..0887ef25b7 100644 --- a/web/i18n/en-US/app-overview.ts +++ b/web/i18n/en-US/app-overview.ts @@ -44,6 +44,11 @@ const translation = { webDescTip: 'This text will be displayed on the client side, providing basic guidance on how to use the application', webDescPlaceholder: 'Enter the description of the WebApp', language: 'Language', + workflow: { + title: 'Workflow Steps', + show: 'Show', + hide: 'Hide', + }, more: { entry: 'Show more settings', copyright: 'Copyright', diff --git a/web/i18n/fr-FR/app-overview.ts b/web/i18n/fr-FR/app-overview.ts index c018ada374..316af61629 100644 --- a/web/i18n/fr-FR/app-overview.ts +++ b/web/i18n/fr-FR/app-overview.ts @@ -44,6 +44,11 @@ const translation = { webDescTip: 'Ce texte sera affiché côté client, fournissant des directives de base sur la façon d\'utiliser l\'application', webDescPlaceholder: 'Entrez la description de l\'application Web', language: 'Langue', + workflow: { + title: 'Étapes du workflow', + show: 'Afficher', + hide: 'Masquer', + }, more: { entry: 'Afficher plus de paramètres', copyright: 'Droits d\'auteur', diff --git a/web/i18n/hi-IN/app-overview.ts b/web/i18n/hi-IN/app-overview.ts index b31844d1b7..a51023ae15 100644 --- a/web/i18n/hi-IN/app-overview.ts +++ b/web/i18n/hi-IN/app-overview.ts @@ -48,6 +48,11 @@ const translation = { 'यह टेक्स्ट क्लाइंट साइड पर प्रदर्शित होगा, जो एप्लिकेशन का उपयोग करने के लिए बुनियादी मार्गदर्शन प्रदान करेगा', webDescPlaceholder: 'वेबऐप का विवरण दर्ज करें', language: 'भाषा', + workflow: { + title: 'वर्कफ़्लो स्टेप्स', + show: 'दिखाएं', + hide: 'छुपाएं', + }, more: { entry: 'अधिक सेटिंग्स दिखाएं', copyright: 'कॉपीराइट', diff --git a/web/i18n/ja-JP/app-overview.ts b/web/i18n/ja-JP/app-overview.ts index 6691ef0c63..32b2768d2c 100644 --- a/web/i18n/ja-JP/app-overview.ts +++ b/web/i18n/ja-JP/app-overview.ts @@ -44,6 +44,11 @@ const translation = { webDescTip: 'このテキストはクライアント側に表示され、アプリケーションの使用方法の基本的なガイダンスを提供します。', webDescPlaceholder: 'WebAppの説明を入力してください', language: '言語', + workflow: { + title: 'ワークフローステップ', + show: '表示', + hide: '非表示', + }, more: { entry: 'その他の設定を表示', copyright: '著作権', diff --git a/web/i18n/ko-KR/app-overview.ts b/web/i18n/ko-KR/app-overview.ts index 0130f68047..ca58a3c535 100644 --- a/web/i18n/ko-KR/app-overview.ts +++ b/web/i18n/ko-KR/app-overview.ts @@ -44,6 +44,11 @@ const translation = { webDescTip: '이 텍스트는 클라이언트 측에서 표시되며, 애플리케이션의 사용 방법에 대한 기본적인 안내를 제공합니다.', webDescPlaceholder: '웹앱 설명을 입력하세요', language: '언어', + workflow: { + title: '워크플로 단계', + show: '표시', + hide: '숨기기', + }, more: { entry: '추가 설정 보기', copyright: '저작권', diff --git a/web/i18n/pl-PL/app-overview.ts b/web/i18n/pl-PL/app-overview.ts index aa399e8ff6..08aa7547ab 100644 --- a/web/i18n/pl-PL/app-overview.ts +++ b/web/i18n/pl-PL/app-overview.ts @@ -48,6 +48,11 @@ const translation = { 'Ten tekst będzie wyświetlany po stronie klienta, zapewniając podstawowe wskazówki, jak korzystać z aplikacji', webDescPlaceholder: 'Wpisz opis WebApp', language: 'Język', + workflow: { + title: 'Kroki przepływu pracy', + show: 'Pokaż', + hide: 'Ukryj', + }, more: { entry: 'Pokaż więcej ustawień', copyright: 'Prawa autorskie', diff --git a/web/i18n/pt-BR/app-overview.ts b/web/i18n/pt-BR/app-overview.ts index ef8833e67d..b8c6feb846 100644 --- a/web/i18n/pt-BR/app-overview.ts +++ b/web/i18n/pt-BR/app-overview.ts @@ -44,6 +44,11 @@ const translation = { webDescTip: 'Este texto será exibido no lado do cliente, fornecendo orientações básicas sobre como usar o aplicativo', webDescPlaceholder: 'Insira a descrição do WebApp', language: 'Idioma', + workflow: { + title: 'Etapas do fluxo de trabalho', + show: 'Mostrar', + hide: 'Ocultar', + }, more: { entry: 'Mostrar mais configurações', copyright: 'Direitos autorais', diff --git a/web/i18n/ro-RO/app-overview.ts b/web/i18n/ro-RO/app-overview.ts index 82655964f6..5bb4aabb17 100644 --- a/web/i18n/ro-RO/app-overview.ts +++ b/web/i18n/ro-RO/app-overview.ts @@ -44,6 +44,11 @@ const translation = { webDescTip: 'Acest text va fi afișat pe partea clientului, oferind îndrumare de bază privind modul de utilizare a aplicației', webDescPlaceholder: 'Introduceți descrierea aplicației web', language: 'Limbă', + workflow: { + title: 'Pași flux de lucru', + show: 'Afișați', + hide: 'Ascundeți', + }, more: { entry: 'Afișați mai multe setări', copyright: 'Drepturi de autor', diff --git a/web/i18n/uk-UA/app-overview.ts b/web/i18n/uk-UA/app-overview.ts index f9041afc7d..b1fcc92d4a 100644 --- a/web/i18n/uk-UA/app-overview.ts +++ b/web/i18n/uk-UA/app-overview.ts @@ -44,6 +44,11 @@ const translation = { webDescTip: 'Цей текст буде відображений на клієнтському боці, надаючи базові вказівки щодо використання додатка', webDescPlaceholder: 'Введіть опис веб-додатку', language: 'Мова', + workflow: { + title: 'Кроки робочого процесу', + show: 'Показати', + hide: 'Приховати', + }, more: { entry: 'Показати додаткові налаштування', copyright: 'Авторське право', diff --git a/web/i18n/vi-VN/app-overview.ts b/web/i18n/vi-VN/app-overview.ts index cb156cc1d5..09005e46d9 100644 --- a/web/i18n/vi-VN/app-overview.ts +++ b/web/i18n/vi-VN/app-overview.ts @@ -44,6 +44,11 @@ const translation = { webDescTip: 'Văn bản này sẽ được hiển thị ở phía máy khách, cung cấp hướng dẫn cơ bản về cách sử dụng ứng dụng', webDescPlaceholder: 'Nhập mô tả của ứng dụng web', language: 'Ngôn ngữ', + workflow: { + title: 'Các Bước Quy trình', + show: 'Hiển thị', + hide: 'Ẩn', + }, more: { entry: 'Hiển thị thêm cài đặt', copyright: 'Bản quyền', diff --git a/web/i18n/zh-Hans/app-overview.ts b/web/i18n/zh-Hans/app-overview.ts index d063a21797..16638cab70 100644 --- a/web/i18n/zh-Hans/app-overview.ts +++ b/web/i18n/zh-Hans/app-overview.ts @@ -44,6 +44,11 @@ const translation = { webDescTip: '以下文字将展示在客户端中,对应用进行说明和使用上的基本引导', webDescPlaceholder: '请输入 WebApp 的描述', language: '语言', + workflow: { + title: '工作流详情', + show: '显示', + hide: '隐藏', + }, more: { entry: '展示更多设置', copyright: '版权', diff --git a/web/i18n/zh-Hant/app-overview.ts b/web/i18n/zh-Hant/app-overview.ts index 4910a458e8..e93c24ed8a 100644 --- a/web/i18n/zh-Hant/app-overview.ts +++ b/web/i18n/zh-Hant/app-overview.ts @@ -44,6 +44,11 @@ const translation = { webDescTip: '以下文字將展示在客戶端中,對應用進行說明和使用上的基本引導', webDescPlaceholder: '請輸入 WebApp 的描述', language: '語言', + workflow: { + title: '工作流程步驟', + show: '展示', + hide: '隱藏', + }, more: { entry: '展示更多設定', copyright: '版權', diff --git a/web/models/share.ts b/web/models/share.ts index 0d29c1232e..32b565eb65 100644 --- a/web/models/share.ts +++ b/web/models/share.ts @@ -19,6 +19,7 @@ export type SiteInfo = { copyright?: string privacy_policy?: string custom_disclaimer?: string + show_workflow_steps?: boolean } export type AppMeta = { diff --git a/web/types/app.ts b/web/types/app.ts index 0086cb1faf..3ad4592e67 100644 --- a/web/types/app.ts +++ b/web/types/app.ts @@ -274,6 +274,8 @@ export type SiteConfig = { icon: string icon_background: string + + show_workflow_steps: boolean } /**