Forráskód Böngészése

feat: option to hide workflow steps (#5436)

crazywoola 10 hónapja
szülő
commit
92ddb410cd

+ 3 - 1
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:

+ 2 - 1
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 = {

+ 3 - 1
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,
 }

+ 33 - 0
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 ###

+ 1 - 0
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)

+ 13 - 3
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<ISettingsModalProps> = ({
   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<ISettingsModalProps> = ({
   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<ISettingsModalProps> = ({
       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<ISettingsModalProps> = ({
           defaultValue={language}
           onSelect={item => setLanguage(item.value as Language)}
         />
+        {(appInfo.mode === 'workflow' || appInfo.mode === 'advanced-chat') && <>
+          <div className={`mt-6 mb-2 font-medium ${s.settingTitle} text-gray-900 `}>{t(`${prefixSettings}.workflow.title`)}</div>
+          <SimpleSelect
+            items={[{ name: t(`${prefixSettings}.workflow.show`), value: 'true' }, { name: t(`${prefixSettings}.workflow.hide`), value: 'false' }]}
+            defaultValue={inputInfo.show_workflow_steps ? 'true' : 'false'}
+            onSelect={item => setInputInfo({ ...inputInfo, show_workflow_steps: item.value === 'true' })}
+          />
+        </>}
         {!isShowMore && <div className='w-full cursor-pointer mt-8' onClick={() => setIsShowMore(true)}>
           <div className='flex justify-between'>
             <div className={`font-medium ${s.settingTitle} flex-grow text-gray-900`}>{t(`${prefixSettings}.more.entry`)}</div>

+ 5 - 1
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<IGenerationItemProps> = ({
   innerClassName,
   contentClassName,
   hideProcessDetail,
+  siteInfo,
 }) => {
   const { t } = useTranslation()
   const params = useParams()
@@ -152,6 +155,7 @@ const GenerationItem: FC<IGenerationItemProps> = ({
     installedAppId,
     controlClearMoreLikeThis,
     isWorkflow,
+    siteInfo,
   }
 
   const handleMoreLikeThis = async () => {
@@ -297,7 +301,7 @@ const GenerationItem: FC<IGenerationItemProps> = ({
             }
             <div className={`flex ${contentClassName}`}>
               <div className='grow w-0'>
-                {workflowProcessData && (
+                {siteInfo && siteInfo.show_workflow_steps && workflowProcessData && (
                   <WorkflowProcessItem grayBg hideInfo data={workflowProcessData} expand={workflowProcessData.expand} hideProcessDetail={hideProcessDetail} />
                 )}
                 {workflowProcessData && !isError && (

+ 2 - 0
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 (
     <Chat
+      appData={appData}
       config={appConfig}
       chatList={chatList}
       isResponding={isResponding}

+ 8 - 1
web/app/components/base/chat/chat-with-history/hooks.tsx

@@ -47,7 +47,14 @@ export const useChatWithHistory = (installedAppInfo?: InstalledApp) => {
       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
     }

+ 16 - 1
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<AnswerProps> = ({
   item,
@@ -44,6 +46,7 @@ const Answer: FC<AnswerProps> = ({
   showPromptLog,
   chatAnswerContainerInner,
   hideProcessDetail,
+  appData,
 }) => {
   const { t } = useTranslation()
   const {
@@ -129,8 +132,20 @@ const Answer: FC<AnswerProps> = ({
                 />
               )
             }
+            {/** Render the normal steps */}
             {
-              workflowProcess && (
+              workflowProcess && !hideProcessDetail && (
+                <WorkflowProcess
+                  data={workflowProcess}
+                  item={item}
+                  hideInfo
+                  hideProcessDetail={hideProcessDetail}
+                />
+              )
+            }
+            {/** Hide workflow steps by it's settings in siteInfo */}
+            {
+              workflowProcess && hideProcessDetail && appData && appData.site.show_workflow_steps && (
                 <WorkflowProcess
                   data={workflowProcess}
                   item={item}

+ 4 - 0
web/app/components/base/chat/chat/index.tsx

@@ -30,8 +30,10 @@ import { StopCircle } from '@/app/components/base/icons/src/vender/solid/mediaAn
 import AgentLogModal from '@/app/components/base/agent-log-modal'
 import PromptLogModal from '@/app/components/base/prompt-log-modal'
 import { useStore as useAppStore } from '@/app/components/app/store'
+import type { AppData } from '@/models/share'
 
 export type ChatProps = {
+  appData?: AppData
   chatList: ChatItem[]
   config?: ChatConfig
   isResponding?: boolean
@@ -57,6 +59,7 @@ export type ChatProps = {
   hideProcessDetail?: boolean
 }
 const Chat: FC<ChatProps> = ({
+  appData,
   config,
   onSend,
   chatList,
@@ -196,6 +199,7 @@ const Chat: FC<ChatProps> = ({
                   const isLast = item.id === chatList[chatList.length - 1]?.id
                   return (
                     <Answer
+                      appData={appData}
                       key={item.id}
                       item={item}
                       question={chatList[index - 1]?.content}

+ 2 - 0
web/app/components/base/chat/embedded-chatbot/chat-wrapper.tsx

@@ -18,6 +18,7 @@ import LogoAvatar from '@/app/components/base/logo/logo-embeded-chat-avatar'
 
 const ChatWrapper = () => {
   const {
+    appData,
     appParams,
     appPrevChatList,
     currentConversationId,
@@ -114,6 +115,7 @@ const ChatWrapper = () => {
 
   return (
     <Chat
+      appData={appData}
       config={appConfig}
       chatList={chatList}
       isResponding={isResponding}

+ 1 - 0
web/app/components/share/text-generation/index.tsx

@@ -442,6 +442,7 @@ const TextGeneration: FC<IMainProps> = ({
     visionConfig={visionConfig}
     completionFiles={completionFiles}
     isShowTextToSpeech={!!textToSpeechConfig?.enabled}
+    siteInfo={siteInfo}
   />)
 
   const renderBatchRes = () => {

+ 4 - 0
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<ModerationService>
   visionConfig: VisionSettings
   completionFiles: VisionFile[]
+  siteInfo: SiteInfo | null
 }
 
 const Result: FC<IResultProps> = ({
@@ -65,6 +67,7 @@ const Result: FC<IResultProps> = ({
   onCompleted,
   visionConfig,
   completionFiles,
+  siteInfo,
 }) => {
   const [isResponding, { setTrue: setRespondingTrue, setFalse: setRespondingFalse }] = useBoolean(false)
   useEffect(() => {
@@ -375,6 +378,7 @@ const Result: FC<IResultProps> = ({
       controlClearMoreLikeThis={controlClearMoreLikeThis}
       isShowTextToSpeech={isShowTextToSpeech}
       hideProcessDetail
+      siteInfo={siteInfo}
     />
   )
 

+ 5 - 0
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',

+ 5 - 0
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',

+ 5 - 0
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',

+ 5 - 0
web/i18n/hi-IN/app-overview.ts

@@ -48,6 +48,11 @@ const translation = {
           'यह टेक्स्ट क्लाइंट साइड पर प्रदर्शित होगा, जो एप्लिकेशन का उपयोग करने के लिए बुनियादी मार्गदर्शन प्रदान करेगा',
         webDescPlaceholder: 'वेबऐप का विवरण दर्ज करें',
         language: 'भाषा',
+        workflow: {
+          title: 'वर्कफ़्लो स्टेप्स',
+          show: 'दिखाएं',
+          hide: 'छुपाएं',
+        },
         more: {
           entry: 'अधिक सेटिंग्स दिखाएं',
           copyright: 'कॉपीराइट',

+ 5 - 0
web/i18n/ja-JP/app-overview.ts

@@ -44,6 +44,11 @@ const translation = {
         webDescTip: 'このテキストはクライアント側に表示され、アプリケーションの使用方法の基本的なガイダンスを提供します。',
         webDescPlaceholder: 'WebAppの説明を入力してください',
         language: '言語',
+        workflow: {
+          title: 'ワークフローステップ',
+          show: '表示',
+          hide: '非表示',
+        },
         more: {
           entry: 'その他の設定を表示',
           copyright: '著作権',

+ 5 - 0
web/i18n/ko-KR/app-overview.ts

@@ -44,6 +44,11 @@ const translation = {
         webDescTip: '이 텍스트는 클라이언트 측에서 표시되며, 애플리케이션의 사용 방법에 대한 기본적인 안내를 제공합니다.',
         webDescPlaceholder: '웹앱 설명을 입력하세요',
         language: '언어',
+        workflow: {
+          title: '워크플로 단계',
+          show: '표시',
+          hide: '숨기기',
+        },
         more: {
           entry: '추가 설정 보기',
           copyright: '저작권',

+ 5 - 0
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',

+ 5 - 0
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',

+ 5 - 0
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',

+ 5 - 0
web/i18n/uk-UA/app-overview.ts

@@ -44,6 +44,11 @@ const translation = {
         webDescTip: 'Цей текст буде відображений на клієнтському боці, надаючи базові вказівки щодо використання додатка',
         webDescPlaceholder: 'Введіть опис веб-додатку',
         language: 'Мова',
+        workflow: {
+          title: 'Кроки робочого процесу',
+          show: 'Показати',
+          hide: 'Приховати',
+        },
         more: {
           entry: 'Показати додаткові налаштування',
           copyright: 'Авторське право',

+ 5 - 0
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',

+ 5 - 0
web/i18n/zh-Hans/app-overview.ts

@@ -44,6 +44,11 @@ const translation = {
         webDescTip: '以下文字将展示在客户端中,对应用进行说明和使用上的基本引导',
         webDescPlaceholder: '请输入 WebApp 的描述',
         language: '语言',
+        workflow: {
+          title: '工作流详情',
+          show: '显示',
+          hide: '隐藏',
+        },
         more: {
           entry: '展示更多设置',
           copyright: '版权',

+ 5 - 0
web/i18n/zh-Hant/app-overview.ts

@@ -44,6 +44,11 @@ const translation = {
         webDescTip: '以下文字將展示在客戶端中,對應用進行說明和使用上的基本引導',
         webDescPlaceholder: '請輸入 WebApp 的描述',
         language: '語言',
+        workflow: {
+          title: '工作流程步驟',
+          show: '展示',
+          hide: '隱藏',
+        },
         more: {
           entry: '展示更多設定',
           copyright: '版權',

+ 1 - 0
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 = {

+ 2 - 0
web/types/app.ts

@@ -274,6 +274,8 @@ export type SiteConfig = {
 
   icon: string
   icon_background: string
+
+  show_workflow_steps: boolean
 }
 
 /**