Add workflow API docs drawer to deployment tokens

This commit is contained in:
Stephen Zhou
2026-05-29 18:34:56 +08:00
parent 7ab48f0112
commit 2e759440b3
4 changed files with 161 additions and 4 deletions

View File

@ -0,0 +1,129 @@
'use client'
import type { App } from '@/types/app'
import { cn } from '@langgenius/dify-ui/cn'
import {
Drawer,
DrawerBackdrop,
DrawerCloseButton,
DrawerContent,
DrawerDescription,
DrawerPopup,
DrawerPortal,
DrawerTitle,
DrawerViewport,
} from '@langgenius/dify-ui/drawer'
import { useTranslation } from 'react-i18next'
import TemplateWorkflowEn from '@/app/components/develop/template/template_workflow.en.mdx'
import TemplateWorkflowJa from '@/app/components/develop/template/template_workflow.ja.mdx'
import TemplateWorkflowZh from '@/app/components/develop/template/template_workflow.zh.mdx'
import { useLocale } from '@/context/i18n'
import useTheme from '@/hooks/use-theme'
import { getDocLanguage } from '@/i18n-config/language'
import { AppModeEnum, Theme } from '@/types/app'
type PromptVariable = { key: string, name: string }
type WorkflowDocTemplateProps = {
appDetail: App
variables: PromptVariable[]
inputs: Record<string, string>
}
const EMPTY_VARIABLES: PromptVariable[] = []
const EMPTY_INPUTS: Record<string, string> = {}
function WorkflowDocTemplate({ docLanguage, appDetail, variables, inputs }: WorkflowDocTemplateProps & {
docLanguage: string
}) {
if (docLanguage === 'zh') {
return (
<TemplateWorkflowZh
appDetail={appDetail}
variables={variables}
inputs={inputs}
/>
)
}
if (docLanguage === 'ja') {
return (
<TemplateWorkflowJa
appDetail={appDetail}
variables={variables}
inputs={inputs}
/>
)
}
return (
<TemplateWorkflowEn
appDetail={appDetail}
variables={variables}
inputs={inputs}
/>
)
}
export function DeveloperApiDocsDrawer({
open,
appInstanceId,
apiBaseUrl,
onOpenChange,
}: {
open: boolean
appInstanceId: string
apiBaseUrl: string
onOpenChange: (open: boolean) => void
}) {
const { t } = useTranslation('deployments')
const locale = useLocale()
const { theme } = useTheme()
const docLanguage = getDocLanguage(locale)
const appDetail = {
id: appInstanceId,
mode: AppModeEnum.WORKFLOW,
api_base_url: apiBaseUrl,
} as App
return (
<Drawer
open={open}
modal
swipeDirection="right"
onOpenChange={onOpenChange}
>
<DrawerPortal>
<DrawerBackdrop />
<DrawerViewport>
<DrawerPopup className="data-[swipe-direction=right]:top-16 data-[swipe-direction=right]:right-2 data-[swipe-direction=right]:bottom-2 data-[swipe-direction=right]:h-auto data-[swipe-direction=right]:w-[840px] data-[swipe-direction=right]:max-w-[calc(100vw-1rem)] data-[swipe-direction=right]:rounded-xl data-[swipe-direction=right]:border-[0.5px]">
<DrawerCloseButton
aria-label={t('access.api.docsClose')}
className="absolute top-4 right-5 size-6 rounded-md"
/>
<DrawerContent className="flex min-h-0 flex-1 flex-col bg-components-panel-bg p-0 pb-0">
<div className="shrink-0 border-b border-divider-subtle px-6 py-5 pr-14">
<DrawerTitle className="title-xl-semi-bold text-text-primary">
{t('access.api.docsTitle')}
</DrawerTitle>
<DrawerDescription className="mt-1 system-sm-regular text-text-tertiary">
{t('access.api.docsDescription')}
</DrawerDescription>
</div>
<div className="min-h-0 flex-1 overflow-x-hidden overflow-y-auto px-6 py-5">
<article className={cn('prose max-w-none', theme === Theme.dark && 'prose-invert')}>
<WorkflowDocTemplate
docLanguage={docLanguage}
appDetail={appDetail}
variables={EMPTY_VARIABLES}
inputs={EMPTY_INPUTS}
/>
</article>
</div>
</DrawerContent>
</DrawerPopup>
</DrawerViewport>
</DrawerPortal>
</Drawer>
)
}

View File

@ -12,6 +12,7 @@ import { Switch, SwitchSkeleton } from '@langgenius/dify-ui/switch'
import { toast } from '@langgenius/dify-ui/toast'
import { useMutation, useQueries, useQuery } from '@tanstack/react-query'
import { atom, useAtom, useSetAtom } from 'jotai'
import { useState } from 'react'
import { useTranslation } from 'react-i18next'
import { SkeletonRectangle } from '@/app/components/base/skeleton'
import { useClipboard } from '@/hooks/use-clipboard'
@ -28,6 +29,7 @@ import {
DetailTableRow,
} from '../../table'
import { API_KEY_DETAIL_TABLE_COLUMN_CLASS_NAMES } from '../../table-styles'
import { DeveloperApiDocsDrawer } from './api-docs-drawer'
import { ApiKeyGenerateMenu, ApiKeyList } from './api-keys'
import { CopyPill } from './common'
@ -396,6 +398,7 @@ export function DeveloperApiSection({
}) {
const { t } = useTranslation('deployments')
const [createdApiToken, setCreatedApiToken] = useAtom(createdApiTokenAtom)
const [apiDocsOpen, setApiDocsOpen] = useState(false)
const {
apiEnabled,
apiUrl,
@ -418,10 +421,27 @@ export function DeveloperApiSection({
? (
<div className="flex flex-col gap-4">
{apiUrl && (
<CopyPill
label={t('access.api.endpoint')}
value={apiUrl}
/>
<div className="flex min-w-0 flex-col gap-2 sm:flex-row sm:items-center">
<CopyPill
label={t('access.api.endpoint')}
value={apiUrl}
className="min-w-0 flex-1"
/>
<Button
variant="secondary"
className="shrink-0 gap-1.5"
onClick={() => setApiDocsOpen(true)}
>
<span className="i-ri-file-list-3-line size-3.5" />
{t('access.api.docs')}
</Button>
<DeveloperApiDocsDrawer
open={apiDocsOpen}
appInstanceId={appInstanceId}
apiBaseUrl={apiUrl}
onOpenChange={setApiDocsOpen}
/>
</div>
)}
{apiKeys.length === 0
? (

View File

@ -9,6 +9,10 @@
"access.api.disabled": "API access is turned off for this deployment.",
"access.api.disabledHint": "Enable API access to generate environment-scoped tokens.",
"access.api.dismissToken": "Dismiss API Token",
"access.api.docs": "API Docs",
"access.api.docsClose": "Close API docs",
"access.api.docsDescription": "View the Workflow API reference for this deployment.",
"access.api.docsTitle": "Workflow API documentation",
"access.api.empty": "Deploy to an environment first to start issuing API Tokens.",
"access.api.emptyTitle": "No deployed environments",
"access.api.endpoint": "Request URL",

View File

@ -9,6 +9,10 @@
"access.api.disabled": "该部署的 API 接入已关闭。",
"access.api.disabledHint": "开启 API 接入后即可生成绑定环境的令牌。",
"access.api.dismissToken": "关闭 API 令牌",
"access.api.docs": "API 文档",
"access.api.docsClose": "关闭 API 文档",
"access.api.docsDescription": "查看该部署的 Workflow API 参考。",
"access.api.docsTitle": "Workflow API 文档",
"access.api.empty": "请先部署到环境后再签发 API 令牌。",
"access.api.emptyTitle": "暂无已部署环境",
"access.api.endpoint": "请求地址",