mirror of
https://github.com/langgenius/dify.git
synced 2026-09-07 18:36:02 +08:00
Co-authored-by: Joel <iamjoel007@gmail.com> Co-authored-by: zyssyz123 <916125788@qq.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: 林玮 (Jade Lin) <linw1995@icloud.com> Co-authored-by: 盐粒 Yanli <mail@yanli.one>
177 lines
6.3 KiB
TypeScript
177 lines
6.3 KiB
TypeScript
'use client'
|
|
|
|
import type { AgentIconType, AgentReferencingWorkflowResponse } from '@dify/contracts/api/console/agent/types.gen'
|
|
import type { ReactNode } from 'react'
|
|
import { Button } from '@langgenius/dify-ui/button'
|
|
import { useQuery } from '@tanstack/react-query'
|
|
import { useTranslation } from 'react-i18next'
|
|
import AppIcon from '@/app/components/base/app-icon'
|
|
import useTimestamp from '@/hooks/use-timestamp'
|
|
import Link from '@/next/link'
|
|
import { consoleQuery } from '@/service/client'
|
|
|
|
type WorkflowReferencesTableProps = {
|
|
agentId: string
|
|
enabled?: boolean
|
|
}
|
|
|
|
const workflowTableColSpan = 5
|
|
|
|
const getWorkflowReferenceHref = (reference: AgentReferencingWorkflowResponse) => `/app/${reference.app_id}/workflow`
|
|
|
|
export function WorkflowReferencesTable({
|
|
agentId,
|
|
enabled = true,
|
|
}: WorkflowReferencesTableProps) {
|
|
const { t } = useTranslation('agentV2')
|
|
const { t: tCommon } = useTranslation('common')
|
|
const workflowReferencesQuery = useQuery(consoleQuery.agent.byAgentId.referencingWorkflows.get.queryOptions({
|
|
input: {
|
|
params: {
|
|
agent_id: agentId,
|
|
},
|
|
},
|
|
enabled,
|
|
}))
|
|
const workflowReferences = workflowReferencesQuery.data?.data ?? []
|
|
|
|
return (
|
|
<div className="min-w-0 overflow-x-auto">
|
|
<table className="w-full min-w-[1212px] table-fixed border-collapse">
|
|
<colgroup>
|
|
<col className="w-[572px]" />
|
|
<col className="w-40" />
|
|
<col className="w-32" />
|
|
<col className="w-[204px]" />
|
|
<col className="w-36" />
|
|
</colgroup>
|
|
<thead>
|
|
<tr className="h-7 rounded-lg bg-background-section-burn text-left system-xs-semibold-uppercase text-text-tertiary">
|
|
<th scope="col" className="rounded-l-lg px-3 font-semibold">
|
|
{t('agentDetail.access.workflow.table.name')}
|
|
</th>
|
|
<th scope="col" className="px-3 font-semibold">
|
|
{t('agentDetail.access.workflow.table.version')}
|
|
</th>
|
|
<th scope="col" className="px-3 font-semibold">
|
|
{t('agentDetail.access.workflow.table.nodes')}
|
|
</th>
|
|
<th scope="col" className="px-3 font-semibold">
|
|
{t('agentDetail.access.workflow.table.lastUpdated')}
|
|
</th>
|
|
<th scope="col" className="rounded-r-lg px-3 font-semibold">
|
|
{t('agentDetail.access.workflow.table.actions')}
|
|
</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody className="system-sm-regular text-text-secondary">
|
|
{enabled && workflowReferencesQuery.isPending && (
|
|
<WorkflowAccessStateRow>
|
|
{t('agentDetail.access.workflow.loading')}
|
|
</WorkflowAccessStateRow>
|
|
)}
|
|
{enabled && workflowReferencesQuery.isError && (
|
|
<WorkflowAccessStateRow>
|
|
<div className="flex items-center justify-center gap-2">
|
|
<span>{t('agentDetail.access.workflow.loadFailed')}</span>
|
|
<Button
|
|
variant="secondary"
|
|
size="small"
|
|
onClick={() => {
|
|
void workflowReferencesQuery.refetch()
|
|
}}
|
|
>
|
|
{tCommon('operation.retry')}
|
|
</Button>
|
|
</div>
|
|
</WorkflowAccessStateRow>
|
|
)}
|
|
{enabled && workflowReferencesQuery.isSuccess && workflowReferences.length === 0 && (
|
|
<WorkflowAccessStateRow>
|
|
{t('agentDetail.access.workflow.empty')}
|
|
</WorkflowAccessStateRow>
|
|
)}
|
|
{enabled && workflowReferencesQuery.isSuccess && workflowReferences.map(reference => (
|
|
<WorkflowAccessRow
|
|
key={`${reference.app_id}:${reference.workflow_id}`}
|
|
reference={reference}
|
|
/>
|
|
))}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
function WorkflowAccessRow({
|
|
reference,
|
|
}: {
|
|
reference: AgentReferencingWorkflowResponse
|
|
}) {
|
|
const { t } = useTranslation('agentV2')
|
|
const { formatTime } = useTimestamp()
|
|
const imageUrl = (reference.app_icon_type === 'image' || reference.app_icon_type === 'link') ? reference.app_icon : undefined
|
|
const iconType = (imageUrl ? 'image' : reference.app_icon_type) as AgentIconType | null | undefined
|
|
const updatedAt = reference.app_updated_at != null
|
|
? formatTime(reference.app_updated_at, t('roster.dateTimeFormat'))
|
|
: t('agentDetail.access.workflow.notAvailable')
|
|
const nodeCount = reference.node_ids?.length ?? 0
|
|
|
|
return (
|
|
<tr className="h-10 border-b border-divider-subtle hover:bg-background-default-hover">
|
|
<td className="px-3">
|
|
<div className="flex min-w-0 items-center gap-2.5">
|
|
<span aria-hidden className="shrink-0">
|
|
<AppIcon
|
|
size="small"
|
|
rounded
|
|
iconType={iconType}
|
|
icon={reference.app_icon ?? undefined}
|
|
background={reference.app_icon_background}
|
|
imageUrl={imageUrl}
|
|
/>
|
|
</span>
|
|
<span className="truncate">
|
|
{reference.app_name}
|
|
</span>
|
|
</div>
|
|
</td>
|
|
<td className="truncate px-3" translate="no">
|
|
{reference.workflow_version}
|
|
</td>
|
|
<td className="px-3 tabular-nums">
|
|
{t('agentDetail.access.workflow.nodeCount', { count: nodeCount })}
|
|
</td>
|
|
<td className="px-3 tabular-nums" translate="no">
|
|
{updatedAt}
|
|
</td>
|
|
<td className="px-3">
|
|
<Link
|
|
href={getWorkflowReferenceHref(reference)}
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
aria-label={t('agentDetail.access.workflow.openInStudioFor', { name: reference.app_name })}
|
|
className="inline-flex items-center gap-0.5 rounded-sm text-text-secondary hover:text-text-accent hover:underline focus-visible:ring-2 focus-visible:ring-state-accent-solid focus-visible:outline-hidden"
|
|
>
|
|
{t('agentDetail.access.workflow.openInStudio')}
|
|
<span aria-hidden className="i-ri-external-link-line size-4" />
|
|
</Link>
|
|
</td>
|
|
</tr>
|
|
)
|
|
}
|
|
|
|
function WorkflowAccessStateRow({
|
|
children,
|
|
}: {
|
|
children: ReactNode
|
|
}) {
|
|
return (
|
|
<tr className="h-20 border-b border-divider-subtle">
|
|
<td colSpan={workflowTableColSpan} aria-live="polite" className="px-3 text-center text-text-tertiary">
|
|
{children}
|
|
</td>
|
|
</tr>
|
|
)
|
|
}
|