mirror of
https://git.mirrors.martin98.com/https://github.com/langgenius/dify.git
synced 2025-08-12 06:29:03 +08:00
feat: option to hide workflow steps (#5436)
This commit is contained in:
parent
1336b844fd
commit
92ddb410cd
@ -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:
|
||||
|
@ -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 = {
|
||||
|
@ -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
api/migrations/versions/4ff534e1eb11_add_workflow_to_site.py
Normal file
33
api/migrations/versions/4ff534e1eb11_add_workflow_to_site.py
Normal file
@ -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 ###
|
@ -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)
|
||||
|
@ -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>
|
||||
|
@ -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 && (
|
||||
|
@ -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}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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}
|
||||
|
@ -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}
|
||||
|
@ -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}
|
||||
|
@ -442,6 +442,7 @@ const TextGeneration: FC<IMainProps> = ({
|
||||
visionConfig={visionConfig}
|
||||
completionFiles={completionFiles}
|
||||
isShowTextToSpeech={!!textToSpeechConfig?.enabled}
|
||||
siteInfo={siteInfo}
|
||||
/>)
|
||||
|
||||
const renderBatchRes = () => {
|
||||
|
@ -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}
|
||||
/>
|
||||
)
|
||||
|
||||
|
@ -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',
|
||||
|
@ -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',
|
||||
|
@ -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',
|
||||
|
@ -48,6 +48,11 @@ const translation = {
|
||||
'यह टेक्स्ट क्लाइंट साइड पर प्रदर्शित होगा, जो एप्लिकेशन का उपयोग करने के लिए बुनियादी मार्गदर्शन प्रदान करेगा',
|
||||
webDescPlaceholder: 'वेबऐप का विवरण दर्ज करें',
|
||||
language: 'भाषा',
|
||||
workflow: {
|
||||
title: 'वर्कफ़्लो स्टेप्स',
|
||||
show: 'दिखाएं',
|
||||
hide: 'छुपाएं',
|
||||
},
|
||||
more: {
|
||||
entry: 'अधिक सेटिंग्स दिखाएं',
|
||||
copyright: 'कॉपीराइट',
|
||||
|
@ -44,6 +44,11 @@ const translation = {
|
||||
webDescTip: 'このテキストはクライアント側に表示され、アプリケーションの使用方法の基本的なガイダンスを提供します。',
|
||||
webDescPlaceholder: 'WebAppの説明を入力してください',
|
||||
language: '言語',
|
||||
workflow: {
|
||||
title: 'ワークフローステップ',
|
||||
show: '表示',
|
||||
hide: '非表示',
|
||||
},
|
||||
more: {
|
||||
entry: 'その他の設定を表示',
|
||||
copyright: '著作権',
|
||||
|
@ -44,6 +44,11 @@ const translation = {
|
||||
webDescTip: '이 텍스트는 클라이언트 측에서 표시되며, 애플리케이션의 사용 방법에 대한 기본적인 안내를 제공합니다.',
|
||||
webDescPlaceholder: '웹앱 설명을 입력하세요',
|
||||
language: '언어',
|
||||
workflow: {
|
||||
title: '워크플로 단계',
|
||||
show: '표시',
|
||||
hide: '숨기기',
|
||||
},
|
||||
more: {
|
||||
entry: '추가 설정 보기',
|
||||
copyright: '저작권',
|
||||
|
@ -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',
|
||||
|
@ -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',
|
||||
|
@ -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',
|
||||
|
@ -44,6 +44,11 @@ const translation = {
|
||||
webDescTip: 'Цей текст буде відображений на клієнтському боці, надаючи базові вказівки щодо використання додатка',
|
||||
webDescPlaceholder: 'Введіть опис веб-додатку',
|
||||
language: 'Мова',
|
||||
workflow: {
|
||||
title: 'Кроки робочого процесу',
|
||||
show: 'Показати',
|
||||
hide: 'Приховати',
|
||||
},
|
||||
more: {
|
||||
entry: 'Показати додаткові налаштування',
|
||||
copyright: 'Авторське право',
|
||||
|
@ -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',
|
||||
|
@ -44,6 +44,11 @@ const translation = {
|
||||
webDescTip: '以下文字将展示在客户端中,对应用进行说明和使用上的基本引导',
|
||||
webDescPlaceholder: '请输入 WebApp 的描述',
|
||||
language: '语言',
|
||||
workflow: {
|
||||
title: '工作流详情',
|
||||
show: '显示',
|
||||
hide: '隐藏',
|
||||
},
|
||||
more: {
|
||||
entry: '展示更多设置',
|
||||
copyright: '版权',
|
||||
|
@ -44,6 +44,11 @@ const translation = {
|
||||
webDescTip: '以下文字將展示在客戶端中,對應用進行說明和使用上的基本引導',
|
||||
webDescPlaceholder: '請輸入 WebApp 的描述',
|
||||
language: '語言',
|
||||
workflow: {
|
||||
title: '工作流程步驟',
|
||||
show: '展示',
|
||||
hide: '隱藏',
|
||||
},
|
||||
more: {
|
||||
entry: '展示更多設定',
|
||||
copyright: '版權',
|
||||
|
@ -19,6 +19,7 @@ export type SiteInfo = {
|
||||
copyright?: string
|
||||
privacy_policy?: string
|
||||
custom_disclaimer?: string
|
||||
show_workflow_steps?: boolean
|
||||
}
|
||||
|
||||
export type AppMeta = {
|
||||
|
@ -274,6 +274,8 @@ export type SiteConfig = {
|
||||
|
||||
icon: string
|
||||
icon_background: string
|
||||
|
||||
show_workflow_steps: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user