fix merge error

This commit is contained in:
JzoNg
2026-04-20 11:58:17 +08:00
parent e7fc22c6b3
commit 76c0aed05c
40 changed files with 197 additions and 167 deletions

View File

@@ -26,14 +26,14 @@ vi.mock('@/utils/download', () => ({
downloadBlob: (args: { data: Blob, fileName: string }) => mockDownloadBlob(args),
}))
vi.mock('@/app/components/base/ui/toast', () => ({
vi.mock('@langgenius/dify-ui/toast', () => ({
toast: {
success: (...args: unknown[]) => mockToastSuccess(...args),
error: (...args: unknown[]) => mockToastError(...args),
},
}))
vi.mock('@/app/components/base/ui/dropdown-menu', () => ({
vi.mock('@langgenius/dify-ui/dropdown-menu', () => ({
DropdownMenu: ({
open,
onOpenChange,

View File

@@ -2,9 +2,6 @@
import type { AppIconSelection } from '@/app/components/base/app-icon-picker'
import type { SnippetDetail } from '@/models/snippet'
import { cn } from '@langgenius/dify-ui/cn'
import * as React from 'react'
import { useTranslation } from 'react-i18next'
import {
AlertDialog,
AlertDialogActions,
@@ -13,15 +10,18 @@ import {
AlertDialogContent,
AlertDialogDescription,
AlertDialogTitle,
} from '@/app/components/base/ui/alert-dialog'
} from '@langgenius/dify-ui/alert-dialog'
import { cn } from '@langgenius/dify-ui/cn'
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from '@/app/components/base/ui/dropdown-menu'
import { toast } from '@/app/components/base/ui/toast'
} from '@langgenius/dify-ui/dropdown-menu'
import { toast } from '@langgenius/dify-ui/toast'
import * as React from 'react'
import { useTranslation } from 'react-i18next'
import CreateSnippetDialog from '@/app/components/workflow/create-snippet-dialog'
import { useRouter } from '@/next/navigation'
import { useDeleteSnippetMutation, useExportSnippetMutation, useUpdateSnippetMutation } from '@/service/use-snippets'

View File

@@ -18,6 +18,7 @@ const mockToastError = vi.fn()
const mockConvertWorkflowType = vi.fn()
const mockRefetchEvaluationWorkflowAssociatedTargets = vi.fn()
const mockInvalidateAppWorkflow = vi.fn()
let mockCanAccessSnippetsAndEvaluation = true
const sectionProps = vi.hoisted(() => ({
summary: null as null | Record<string, any>,
@@ -72,6 +73,13 @@ vi.mock('@/hooks/use-async-window-open', () => ({
useAsyncWindowOpen: () => mockOpenAsyncWindow,
}))
vi.mock('@/hooks/use-snippet-and-evaluation-plan-access', () => ({
useSnippetAndEvaluationPlanAccess: () => ({
canAccess: mockCanAccessSnippetsAndEvaluation,
isReady: true,
}),
}))
vi.mock('@/service/access-control', () => ({
useGetUserCanAccessApp: () => ({
data: { result: true },
@@ -194,6 +202,7 @@ describe('AppPublisher', () => {
sectionProps.summary = null
sectionProps.access = null
sectionProps.actions = null
mockCanAccessSnippetsAndEvaluation = true
mockAppDetail = {
id: 'app-1',
name: 'Demo App',
@@ -657,4 +666,25 @@ describe('AppPublisher', () => {
expect(sectionProps.summary?.workflowTypeSwitchDisabled).toBe(true)
expect(sectionProps.summary?.workflowTypeSwitchDisabledReason).toBe('common.switchToEvaluationWorkflowDisabledTip')
})
it('should keep the evaluation workflow switch visible but disabled when the current plan cannot access it', () => {
mockCanAccessSnippetsAndEvaluation = false
render(
<AppPublisher
publishedAt={Date.now()}
/>,
)
fireEvent.click(screen.getByText('common.publish'))
expect(sectionProps.summary?.workflowTypeSwitchConfig).toEqual({
targetType: AppTypeEnum.EVALUATION,
publishLabelKey: 'common.publishAsEvaluationWorkflow',
switchLabelKey: 'common.switchToEvaluationWorkflow',
tipKey: 'common.switchToEvaluationWorkflowTip',
})
expect(sectionProps.summary?.workflowTypeSwitchDisabled).toBe(true)
expect(sectionProps.summary?.workflowTypeSwitchDisabledReason).toBe('compliance.sandboxUpgradeTooltip')
})
})

View File

@@ -2,8 +2,6 @@
import type { EvaluationWorkflowAssociatedTarget, EvaluationWorkflowAssociatedTargetType } from '@/types/evaluation'
import type { I18nKeysWithPrefix } from '@/types/i18n'
import { cn } from '@langgenius/dify-ui/cn'
import { useTranslation } from 'react-i18next'
import {
AlertDialog,
AlertDialogActions,
@@ -12,7 +10,9 @@ import {
AlertDialogContent,
AlertDialogDescription,
AlertDialogTitle,
} from '@/app/components/base/ui/alert-dialog'
} from '@langgenius/dify-ui/alert-dialog'
import { cn } from '@langgenius/dify-ui/cn'
import { useTranslation } from 'react-i18next'
import Link from '@/next/link'
type EvaluationWorkflowSwitchConfirmDialogProps = {
@@ -80,7 +80,7 @@ const DependentTargetItem = ({
<span className={cn(meta.icon, 'size-5')} />
</span>
<span className="flex min-w-0 flex-1 flex-col gap-1 py-px">
<span className="system-md-semibold truncate text-text-secondary">
<span className="truncate system-md-semibold text-text-secondary">
{targetName}
</span>
<span className="system-2xs-medium-uppercase text-text-tertiary">
@@ -108,10 +108,10 @@ const EvaluationWorkflowSwitchConfirmDialog = ({
<AlertDialog open={open} onOpenChange={onOpenChange}>
<AlertDialogContent className="w-[480px]">
<div className="flex flex-col gap-2 px-6 pt-6 pb-4">
<AlertDialogTitle className="title-2xl-semi-bold w-full text-text-primary">
<AlertDialogTitle className="w-full title-2xl-semi-bold text-text-primary">
{t('common.switchToStandardWorkflowConfirm.title', { ns: 'workflow' })}
</AlertDialogTitle>
<AlertDialogDescription className="system-md-regular w-full text-text-secondary">
<AlertDialogDescription className="w-full system-md-regular text-text-secondary">
<span className="block">
{t('common.switchToStandardWorkflowConfirm.activeIn', { ns: 'workflow', count: targets.length })}
</span>
@@ -123,7 +123,7 @@ const EvaluationWorkflowSwitchConfirmDialog = ({
<div className="flex flex-col gap-2 px-6 py-3">
<div className="flex items-center gap-2">
<span className="system-xs-medium-uppercase shrink-0 text-text-quaternary">
<span className="shrink-0 system-xs-medium-uppercase text-text-quaternary">
{t('common.switchToStandardWorkflowConfirm.dependentWorkflows', { ns: 'workflow' })}
</span>
<span className="h-px min-w-0 flex-1 bg-divider-subtle" />

View File

@@ -149,11 +149,8 @@ const AppPublisher = ({
if (!isWorkflowTypeConversionTarget(appDetail?.type))
return undefined
if (appDetail.type !== AppTypeEnum.EVALUATION && !canAccessSnippetsAndEvaluation)
return undefined
return WORKFLOW_TYPE_SWITCH_CONFIG[appDetail.type]
}, [appDetail?.type, canAccessSnippetsAndEvaluation])
}, [appDetail?.type])
const isEvaluationWorkflowType = appDetail?.type === AppTypeEnum.EVALUATION
const {
refetch: refetchEvaluationWorkflowAssociatedTargets,
@@ -163,11 +160,14 @@ const AppPublisher = ({
if (workflowTypeSwitchConfig?.targetType !== AppTypeEnum.EVALUATION)
return undefined
if (!canAccessSnippetsAndEvaluation)
return t('compliance.sandboxUpgradeTooltip', { ns: 'common' })
if (!hasHumanInputNode && !hasTriggerNode)
return undefined
return t('common.switchToEvaluationWorkflowDisabledTip', { ns: 'workflow' })
}, [hasHumanInputNode, hasTriggerNode, t, workflowTypeSwitchConfig?.targetType])
}, [canAccessSnippetsAndEvaluation, hasHumanInputNode, hasTriggerNode, t, workflowTypeSwitchConfig?.targetType])
const { data: userCanAccessApp, isLoading: isGettingUserCanAccessApp, refetch } = useGetUserCanAccessApp({ appId: appDetail?.id, enabled: false })
const { data: appAccessSubjects, isLoading: isGettingAppWhiteListSubjects } = useAppWhiteListSubjects(appDetail?.id, open && systemFeatures.webapp_auth.enabled && appDetail?.access_mode === AccessMode.SPECIFIC_GROUPS_MEMBERS)

View File

@@ -2,13 +2,13 @@
import type { EvaluationLogItem } from '@/models/log'
import { cn } from '@langgenius/dify-ui/cn'
import { useState } from 'react'
import { useTranslation } from 'react-i18next'
import {
Popover,
PopoverContent,
PopoverTrigger,
} from '@/app/components/base/ui/popover'
} from '@langgenius/dify-ui/popover'
import { useState } from 'react'
import { useTranslation } from 'react-i18next'
import { getNodeVisual, getToneClasses } from '@/app/components/evaluation/components/metric-selector/utils'
type EvaluationCellProps = {
@@ -30,7 +30,7 @@ const EvaluationCell = ({
if (!evaluation.length) {
return (
<div className="system-sm-regular flex items-center justify-center px-2 py-3 text-text-quaternary">
<div className="flex items-center justify-center px-2 py-3 system-sm-regular text-text-quaternary">
-
</div>
)
@@ -73,19 +73,19 @@ const EvaluationCell = ({
)}
>
<div className="min-w-0">
<div className="system-sm-medium truncate text-text-secondary">{item.name}</div>
<div className="truncate system-sm-medium text-text-secondary">{item.name}</div>
{item.nodeInfo && nodeVisual && nodeToneClasses && (
<div className="mt-1 flex min-w-0 items-center gap-1.5">
<div className={cn('flex h-[18px] w-[18px] shrink-0 items-center justify-center rounded-md border-[0.45px] border-divider-subtle shadow-xs shadow-shadow-shadow-3', nodeToneClasses.solid)}>
<span aria-hidden="true" className={cn(nodeVisual.icon, 'h-3.5 w-3.5')} />
</div>
<span className="system-xs-regular truncate text-text-tertiary">
<span className="truncate system-xs-regular text-text-tertiary">
{item.nodeInfo.title}
</span>
</div>
)}
</div>
<div className="system-sm-regular max-w-[120px] text-right wrap-break-word text-text-secondary">
<div className="max-w-[120px] text-right system-sm-regular wrap-break-word text-text-secondary">
{formatEvaluationValue(item.value)}
</div>
</div>

View File

@@ -1,16 +1,16 @@
'use client'
import { Avatar } from '@langgenius/dify-ui/avatar'
import { cn } from '@langgenius/dify-ui/cn'
import { useCallback, useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next'
import Checkbox from '@/app/components/base/checkbox'
import Input from '@/app/components/base/input'
import { Avatar } from '@/app/components/base/ui/avatar'
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuTrigger,
} from '@/app/components/base/ui/dropdown-menu'
} from '@langgenius/dify-ui/dropdown-menu'
import { useCallback, useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next'
import Checkbox from '@/app/components/base/checkbox'
import Input from '@/app/components/base/input'
import { useAppContext } from '@/context/app-context'
import { useMembers } from '@/service/use-common'

View File

@@ -1,16 +1,16 @@
import type { EvaluationResourceProps } from '../../types'
import type { EvaluationLog, EvaluationLogFile } from '@/types/evaluation'
import { cn } from '@langgenius/dify-ui/cn'
import { keepPreviousData, useMutation, useQuery } from '@tanstack/react-query'
import { useEffect, useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next'
import Pagination from '@/app/components/base/pagination'
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from '@/app/components/base/ui/dropdown-menu'
} from '@langgenius/dify-ui/dropdown-menu'
import { keepPreviousData, useMutation, useQuery } from '@tanstack/react-query'
import { useEffect, useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next'
import Pagination from '@/app/components/base/pagination'
import { consoleClient, consoleQuery } from '@/service/client'
import { downloadUrl } from '@/utils/download'
import { useEvaluationResource, useEvaluationStore } from '../../store'
@@ -92,15 +92,15 @@ const HistoryTab = ({
</colgroup>
<thead>
<tr className="border-b border-divider-regular">
<th className="system-xs-medium-uppercase h-7 px-3 text-left text-text-tertiary">
<th className="h-7 px-3 text-left system-xs-medium-uppercase text-text-tertiary">
<span className="inline-flex items-center gap-0.5">
{t('history.columns.time')}
<span aria-hidden="true" className="i-ri-arrow-down-line h-3.5 w-3.5" />
</span>
</th>
<th className="system-xs-medium-uppercase h-7 px-3 text-left text-text-tertiary">{t('history.columns.creator')}</th>
<th className="system-xs-medium-uppercase h-7 px-3 text-left text-text-tertiary">{t('history.columns.version')}</th>
<th className="system-xs-medium-uppercase h-7 px-3 text-left text-text-tertiary">{t('history.columns.status')}</th>
<th className="h-7 px-3 text-left system-xs-medium-uppercase text-text-tertiary">{t('history.columns.creator')}</th>
<th className="h-7 px-3 text-left system-xs-medium-uppercase text-text-tertiary">{t('history.columns.version')}</th>
<th className="h-7 px-3 text-left system-xs-medium-uppercase text-text-tertiary">{t('history.columns.status')}</th>
<th className="h-7 text-center text-text-tertiary">
<span aria-hidden="true" className="i-ri-download-2-line inline-block h-3.5 w-3.5" />
</th>
@@ -128,9 +128,9 @@ const HistoryTab = ({
setSelectedRunId(resourceType, resourceId, runId)
}}
>
<td className="system-sm-regular h-10 truncate px-3 text-text-secondary">{formatCreatedAt(record.created_at)}</td>
<td className="system-sm-regular h-10 truncate px-3 text-text-secondary">{record.created_by}</td>
<td className="system-sm-regular h-10 truncate px-3 text-text-secondary">{record.version || '-'}</td>
<td className="h-10 truncate px-3 system-sm-regular text-text-secondary">{formatCreatedAt(record.created_at)}</td>
<td className="h-10 truncate px-3 system-sm-regular text-text-secondary">{record.created_by}</td>
<td className="h-10 truncate px-3 system-sm-regular text-text-secondary">{record.version || '-'}</td>
<td className="h-10 px-3 text-center">
{record.result_file
? <span aria-label={t('history.status.completed')} className="i-ri-checkbox-circle-fill inline-block h-4 w-4 text-util-colors-green-green-600" />
@@ -181,7 +181,7 @@ const HistoryTab = ({
</tbody>
</table>
{!isInitialLoading && records.length === 0 && (
<div className="system-sm-regular rounded-2xl border border-dashed border-divider-subtle px-4 py-10 text-center text-text-tertiary">
<div className="rounded-2xl border border-dashed border-divider-subtle px-4 py-10 text-center system-sm-regular text-text-tertiary">
{t('history.empty')}
</div>
)}

View File

@@ -1,10 +1,10 @@
'use client'
import type { BatchTestTab, EvaluationResourceProps } from '../../types'
import { Button } from '@langgenius/dify-ui/button'
import { cn } from '@langgenius/dify-ui/cn'
import { toast } from '@langgenius/dify-ui/toast'
import { useTranslation } from 'react-i18next'
import { Button } from '@/app/components/base/ui/button'
import { toast } from '@/app/components/base/ui/toast'
import { useSaveEvaluationConfigMutation } from '@/service/use-evaluation'
import { isEvaluationRunnable, useEvaluationResource, useEvaluationStore } from '../../store'
import { buildEvaluationConfigPayload } from '../../store-utils'
@@ -65,7 +65,7 @@ const BatchTestPanel = ({
<div className="flex items-start justify-between gap-3">
<div className="min-w-0">
<div className="system-xl-semibold text-text-primary">{t('batch.title')}</div>
<div className="system-sm-regular mt-1 text-text-tertiary">{t('batch.description')}</div>
<div className="mt-1 system-sm-regular text-text-tertiary">{t('batch.description')}</div>
</div>
<Button
className="shrink-0"

View File

@@ -1,6 +1,6 @@
import type { EvaluationResourceProps } from '../../types'
import { Button } from '@langgenius/dify-ui/button'
import { useTranslation } from 'react-i18next'
import { Button } from '@/app/components/base/ui/button'
import { getEvaluationMockConfig } from '../../mock'
import InputFieldsRequirements from './input-fields/input-fields-requirements'
import UploadRunPopover from './input-fields/upload-run-popover'

View File

@@ -1,14 +1,14 @@
import type { ChangeEvent, DragEvent } from 'react'
import type { InputField } from './input-fields-utils'
import { Button } from '@langgenius/dify-ui/button'
import { cn } from '@langgenius/dify-ui/cn'
import { useRef } from 'react'
import { useTranslation } from 'react-i18next'
import { Button } from '@/app/components/base/ui/button'
import {
Popover,
PopoverContent,
PopoverTrigger,
} from '@/app/components/base/ui/popover'
} from '@langgenius/dify-ui/popover'
import { useRef } from 'react'
import { useTranslation } from 'react-i18next'
import { getExampleValue } from './input-fields-utils'
type UploadRunPopoverProps = {
@@ -92,10 +92,10 @@ const UploadRunPopover = ({
<span aria-hidden="true" className="i-ri-file-excel-fill h-6 w-6 text-util-colors-green-green-600" />
</div>
<div className="min-w-0 flex-1 py-1 pr-2">
<div className="system-xs-medium truncate text-text-secondary">
<div className="truncate system-xs-medium text-text-secondary">
{currentFileName}
</div>
<div className="system-2xs-medium mt-0.5 flex h-3 items-center gap-1 text-text-tertiary">
<div className="mt-0.5 flex h-3 items-center gap-1 system-2xs-medium text-text-tertiary">
{!!currentFileExtension && <span className="uppercase">{currentFileExtension}</span>}
{!!currentFileExtension && !!currentFileSize && <span className="text-text-quaternary">·</span>}
{!!currentFileSize && <span>{currentFileSize}</span>}
@@ -138,7 +138,7 @@ const UploadRunPopover = ({
{' '}
{t('batch.uploadDropzoneSuffix')}
</div>
<div className="system-xs-regular mt-0.5 text-text-tertiary">
<div className="mt-0.5 system-xs-regular text-text-tertiary">
{t('batch.uploadDropzoneDownloadPrefix')}
{' '}
<button
@@ -159,10 +159,10 @@ const UploadRunPopover = ({
<div className="flex overflow-hidden rounded-lg border border-divider-regular">
{previewFields.map((field, index) => (
<div key={field.name} className={cn('min-w-0 flex-1', index < previewFields.length - 1 && 'border-r border-divider-subtle')}>
<div className="system-xs-medium-uppercase min-h-8 border-b border-divider-regular px-3 py-2 text-text-tertiary">
<div className="min-h-8 border-b border-divider-regular px-3 py-2 system-xs-medium-uppercase text-text-tertiary">
{field.name}
</div>
<div className="system-sm-regular min-h-8 px-3 py-2 text-text-secondary">
<div className="min-h-8 px-3 py-2 system-sm-regular text-text-secondary">
{getExampleValue(field, booleanExampleValue)}
</div>
</div>

View File

@@ -1,9 +1,9 @@
import type { EvaluationResourceProps } from '../../../types'
import type { InputField } from './input-fields-utils'
import { toast } from '@langgenius/dify-ui/toast'
import { useMutation } from '@tanstack/react-query'
import { useState } from 'react'
import { useTranslation } from 'react-i18next'
import { toast } from '@/app/components/base/ui/toast'
import { upload } from '@/service/base'
import { useStartEvaluationRunMutation } from '@/service/use-evaluation'
import { formatFileSize } from '@/utils/format'

View File

@@ -2,8 +2,6 @@
import type { ConditionMetricOptionGroup, EvaluationResourceProps } from '../../types'
import { cn } from '@langgenius/dify-ui/cn'
import { useState } from 'react'
import { useTranslation } from 'react-i18next'
import {
Select,
SelectContent,
@@ -11,7 +9,9 @@ import {
SelectGroupLabel,
SelectItem,
SelectTrigger,
} from '@/app/components/base/ui/select'
} from '@langgenius/dify-ui/select'
import { useState } from 'react'
import { useTranslation } from 'react-i18next'
import { useEvaluationStore } from '../../store'
import { getConditionMetricValueTypeTranslationKey } from '../../utils'
@@ -46,7 +46,7 @@ const AddConditionSelect = ({
<SelectContent placement="bottom-start" popupClassName="w-[320px]">
{metricOptionGroups.map(group => (
<SelectGroup key={group.label}>
<SelectGroupLabel className="system-xs-medium-uppercase px-3 pt-2 pb-1 text-text-tertiary">{group.label}</SelectGroupLabel>
<SelectGroupLabel className="px-3 pt-2 pb-1 system-xs-medium-uppercase text-text-tertiary">{group.label}</SelectGroupLabel>
{group.options.map(option => (
<SelectItem
key={option.id}
@@ -58,8 +58,8 @@ const AddConditionSelect = ({
}}
>
<div className="flex min-w-0 flex-1 items-center gap-3">
<span className="system-sm-medium truncate text-text-secondary">{option.itemLabel}</span>
<span className="system-xs-medium ml-auto shrink-0 text-text-tertiary">
<span className="truncate system-sm-medium text-text-secondary">{option.itemLabel}</span>
<span className="ml-auto shrink-0 system-xs-medium text-text-tertiary">
{t(getConditionMetricValueTypeTranslationKey(option.valueType))}
</span>
</div>

View File

@@ -6,11 +6,8 @@ import type {
EvaluationResourceProps,
JudgmentConditionItem,
} from '../../types'
import { Button } from '@langgenius/dify-ui/button'
import { cn } from '@langgenius/dify-ui/cn'
import { useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import Input from '@/app/components/base/input'
import { Button } from '@/app/components/base/ui/button'
import {
Select,
SelectContent,
@@ -19,7 +16,10 @@ import {
SelectItem,
SelectTrigger,
SelectValue,
} from '@/app/components/base/ui/select'
} from '@langgenius/dify-ui/select'
import { useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import Input from '@/app/components/base/input'
import { getAllowedOperators, requiresConditionValue, useEvaluationResource, useEvaluationStore } from '../../store'
import {
buildConditionMetricOptions,
@@ -71,15 +71,15 @@ const ConditionMetricLabel = ({
placeholder,
}: ConditionMetricLabelProps) => {
if (!metric)
return <span className="system-sm-regular px-1 text-components-input-text-placeholder">{placeholder}</span>
return <span className="px-1 system-sm-regular text-components-input-text-placeholder">{placeholder}</span>
return (
<div className="flex min-w-0 items-center gap-2 px-1">
<div className="inline-flex h-6 min-w-0 items-center gap-1 rounded-md border-[0.5px] border-components-panel-border-subtle bg-components-badge-white-to-dark pr-1.5 pl-[5px] shadow-xs">
<span className={cn(getMetricValueTypeIconClassName(metric.valueType), 'h-3 w-3 shrink-0 text-text-secondary')} />
<span className="system-xs-medium truncate text-text-secondary">{metric.itemLabel}</span>
<span className="truncate system-xs-medium text-text-secondary">{metric.itemLabel}</span>
</div>
<span className="system-xs-regular shrink-0 text-text-tertiary">{metric.groupLabel}</span>
<span className="shrink-0 system-xs-regular text-text-tertiary">{metric.groupLabel}</span>
</div>
)
}
@@ -110,13 +110,13 @@ const ConditionMetricSelect = ({
<SelectContent popupClassName="w-[360px]">
{groupedMetricOptions.map(group => (
<SelectGroup key={group.label}>
<SelectGroupLabel className="system-xs-medium-uppercase px-3 pt-2 pb-1 text-text-tertiary">{group.label}</SelectGroupLabel>
<SelectGroupLabel className="px-3 pt-2 pb-1 system-xs-medium-uppercase text-text-tertiary">{group.label}</SelectGroupLabel>
{group.options.map(option => (
<SelectItem key={option.id} value={serializeVariableSelector(option.variableSelector)}>
<div className="flex min-w-0 flex-1 items-center gap-2">
<span className={cn(getMetricValueTypeIconClassName(option.valueType), 'h-3.5 w-3.5 shrink-0 text-text-tertiary')} />
<span className="truncate">{option.itemLabel}</span>
<span className="system-xs-medium ml-auto shrink-0 text-text-quaternary">
<span className="ml-auto shrink-0 system-xs-medium text-text-quaternary">
{t(getConditionMetricValueTypeTranslationKey(option.valueType))}
</span>
</div>
@@ -139,7 +139,7 @@ const ConditionOperatorSelect = ({
return (
<Select value={operator} onValueChange={value => value && onChange(value as ComparisonOperator)}>
<SelectTrigger className="h-8 w-auto min-w-[88px] gap-1 rounded-md bg-transparent px-1.5 py-0 hover:bg-state-base-hover-alt focus-visible:bg-state-base-hover-alt">
<span className="system-xs-medium truncate text-text-secondary">{getComparisonOperatorLabel(operator, t)}</span>
<span className="truncate system-xs-medium text-text-secondary">{getComparisonOperatorLabel(operator, t)}</span>
</SelectTrigger>
<SelectContent className="z-[1002]" popupClassName="w-[240px] bg-components-panel-bg-blur backdrop-blur-[10px]">
{operators.map(nextOperator => (
@@ -232,7 +232,7 @@ const ConditionGroup = ({
key={operator}
type="button"
className={cn(
'system-xs-medium-uppercase rounded-md px-3 py-1.5',
'rounded-md px-3 py-1.5 system-xs-medium-uppercase',
resource.judgmentConfig.logicalOperator === operator
? 'bg-components-card-bg text-text-primary shadow-xs'
: 'text-text-tertiary',

View File

@@ -2,24 +2,24 @@
import type { AvailableEvaluationWorkflow } from '@/types/evaluation'
import { cn } from '@langgenius/dify-ui/cn'
import { useInfiniteScroll } from 'ahooks'
import * as React from 'react'
import { useDeferredValue, useMemo, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
import Input from '@/app/components/base/input'
import Loading from '@/app/components/base/loading'
import {
Popover,
PopoverContent,
PopoverTrigger,
} from '@/app/components/base/ui/popover'
} from '@langgenius/dify-ui/popover'
import {
ScrollAreaContent,
ScrollAreaRoot,
ScrollAreaScrollbar,
ScrollAreaThumb,
ScrollAreaViewport,
} from '@/app/components/base/ui/scroll-area'
} from '@langgenius/dify-ui/scroll-area'
import { useInfiniteScroll } from 'ahooks'
import * as React from 'react'
import { useDeferredValue, useMemo, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
import Input from '@/app/components/base/input'
import Loading from '@/app/components/base/loading'
import { useAvailableEvaluationWorkflows } from '@/service/use-evaluation'
type WorkflowSelectorProps = {
@@ -119,7 +119,7 @@ const WorkflowSelector = ({
</div>
<div className="min-w-0 flex-1 px-1 py-1 text-left">
<div className={cn(
'system-sm-regular truncate',
'truncate system-sm-regular',
currentWorkflowName ? 'text-text-secondary' : 'text-components-input-text-placeholder',
)}
>
@@ -158,7 +158,7 @@ const WorkflowSelector = ({
)
: !workflows.length
? (
<div className="system-sm-regular flex h-[120px] items-center justify-center text-text-tertiary">
<div className="flex h-[120px] items-center justify-center system-sm-regular text-text-tertiary">
{t('noData', { ns: 'common' })}
</div>
)
@@ -184,7 +184,7 @@ const WorkflowSelector = ({
<span aria-hidden="true" className="i-ri-equalizer-2-line h-3.5 w-3.5 text-text-tertiary" />
</div>
</div>
<div className="system-sm-medium min-w-0 flex-1 truncate px-1 py-1 text-text-secondary">
<div className="min-w-0 flex-1 truncate px-1 py-1 system-sm-medium text-text-secondary">
{getWorkflowName(workflow)}
</div>
{workflow.id === value && (

View File

@@ -2,16 +2,16 @@
import type { EvaluationMetric, EvaluationResourceProps } from '../../types'
import type { NodeInfo } from '@/types/evaluation'
import { Button } from '@langgenius/dify-ui/button'
import { cn } from '@langgenius/dify-ui/cn'
import { useState } from 'react'
import { useTranslation } from 'react-i18next'
import { Button } from '@/app/components/base/ui/button'
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from '@/app/components/base/ui/dropdown-menu'
} from '@langgenius/dify-ui/dropdown-menu'
import { useState } from 'react'
import { useTranslation } from 'react-i18next'
import { useEvaluationStore } from '../../store'
import { dedupeNodeInfoList, getMetricVisual, getNodeVisual, getToneClasses } from '../metric-selector/utils'
@@ -53,7 +53,7 @@ const BuiltinMetricCard = ({
<span aria-hidden="true" className={cn(metricVisual.icon, 'h-3.5 w-3.5')} />
</div>
<div className="flex min-w-0 items-center gap-0.5">
<div className="system-md-medium truncate text-text-secondary">{metric.label}</div>
<div className="truncate system-md-medium text-text-secondary">{metric.label}</div>
<span
aria-hidden="true"
className={cn('i-ri-arrow-down-s-line h-4 w-4 shrink-0 text-text-quaternary transition-transform', !isExpanded && '-rotate-90')}
@@ -87,7 +87,7 @@ const BuiltinMetricCard = ({
<div className={cn('flex h-[18px] w-[18px] shrink-0 items-center justify-center rounded-md border-[0.45px] border-divider-subtle shadow-xs shadow-shadow-shadow-3', nodeToneClasses.solid)}>
<span aria-hidden="true" className={cn(nodeVisual.icon, 'h-3.5 w-3.5')} />
</div>
<span className="system-xs-regular px-1 text-text-primary">{nodeInfo.title}</span>
<span className="px-1 system-xs-regular text-text-primary">{nodeInfo.title}</span>
<button
type="button"
className="flex h-4 w-4 items-center justify-center rounded-sm text-text-quaternary transition-colors hover:text-text-secondary"
@@ -105,7 +105,7 @@ const BuiltinMetricCard = ({
)
})
: (
<span className="system-xs-regular px-1 text-text-tertiary">{t('metrics.nodesAll')}</span>
<span className="px-1 system-xs-regular text-text-tertiary">{t('metrics.nodesAll')}</span>
)}
{shouldShowAddNode && (
@@ -144,7 +144,7 @@ const BuiltinMetricCard = ({
<div className={cn('flex h-[18px] w-[18px] shrink-0 items-center justify-center rounded-md border-[0.45px] border-divider-subtle shadow-xs shadow-shadow-shadow-3', nodeToneClasses.solid)}>
<span aria-hidden="true" className={cn(nodeVisual.icon, 'h-3.5 w-3.5')} />
</div>
<span className="system-sm-medium truncate text-text-secondary">{nodeInfo.title}</span>
<span className="truncate system-sm-medium text-text-secondary">{nodeInfo.title}</span>
</div>
</DropdownMenuItem>
)

View File

@@ -1,10 +1,10 @@
'use client'
import type { EvaluationMetric, EvaluationResourceProps } from '../../types'
import { Button } from '@langgenius/dify-ui/button'
import { cn } from '@langgenius/dify-ui/cn'
import { useTranslation } from 'react-i18next'
import Badge from '@/app/components/base/badge'
import { Button } from '@/app/components/base/ui/button'
import { isCustomMetricConfigured, useEvaluationStore } from '../../store'
import CustomMetricEditorCard from '../custom-metric-editor'
import { getToneClasses } from '../metric-selector/utils'
@@ -30,7 +30,7 @@ const CustomMetricCard = ({
<div className={cn('flex h-[18px] w-[18px] shrink-0 items-center justify-center rounded-[5px]', metricToneClasses.soft)}>
<span aria-hidden="true" className="i-ri-equalizer-2-line h-3.5 w-3.5" />
</div>
<div className="system-md-medium truncate text-text-secondary">{metric.label}</div>
<div className="truncate system-md-medium text-text-secondary">{metric.label}</div>
</div>
<div className="flex shrink-0 items-center gap-1">

View File

@@ -2,16 +2,16 @@
import type { ChangeEvent } from 'react'
import type { MetricSelectorProps } from './types'
import { Button } from '@langgenius/dify-ui/button'
import { cn } from '@langgenius/dify-ui/cn'
import { useState } from 'react'
import { useTranslation } from 'react-i18next'
import Input from '@/app/components/base/input'
import { Button } from '@/app/components/base/ui/button'
import {
Popover,
PopoverContent,
PopoverTrigger,
} from '@/app/components/base/ui/popover'
} from '@langgenius/dify-ui/popover'
import { useState } from 'react'
import { useTranslation } from 'react-i18next'
import Input from '@/app/components/base/input'
import { useEvaluationResource, useEvaluationStore } from '../../store'
import SelectorEmptyState from './selector-empty-state'
import SelectorFooter from './selector-footer'
@@ -68,7 +68,7 @@ const MetricSelector = ({
render={(
triggerStyle === 'text'
? (
<button type="button" className={cn('system-sm-medium inline-flex items-center text-text-accent', triggerClassName)}>
<button type="button" className={cn('inline-flex items-center system-sm-medium text-text-accent', triggerClassName)}>
<span aria-hidden="true" className="mr-1 i-ri-add-line h-4 w-4" />
{t('metrics.add')}
</button>

View File

@@ -2,8 +2,8 @@
import type { EvaluationResourceProps } from '../../types'
import type { InputField } from '../batch-test-panel/input-fields/input-fields-utils'
import { Button } from '@langgenius/dify-ui/button'
import { useTranslation } from 'react-i18next'
import { Button } from '@/app/components/base/ui/button'
import { getEvaluationMockConfig } from '../../mock'
import { isEvaluationRunnable, useEvaluationResource } from '../../store'
import UploadRunPopover from '../batch-test-panel/input-fields/upload-run-popover'

View File

@@ -2,10 +2,10 @@
import type { MetricOption } from '../../types'
import { cn } from '@langgenius/dify-ui/cn'
import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip'
import { useTranslation } from 'react-i18next'
import Checkbox from '@/app/components/base/checkbox'
import Input from '@/app/components/base/input'
import { Tooltip, TooltipContent, TooltipTrigger } from '@/app/components/base/ui/tooltip'
import { getTranslatedMetricDescription } from '../../default-metric-descriptions'
import { DEFAULT_PIPELINE_METRIC_THRESHOLD } from '../../store-utils'
@@ -37,7 +37,7 @@ const PipelineMetricItem = ({
onClick={onToggle}
>
<Checkbox checked={selected} />
<span className="system-sm-medium truncate text-text-secondary">{metric.label}</span>
<span className="truncate system-sm-medium text-text-secondary">{metric.label}</span>
<Tooltip>
<TooltipTrigger
render={(

View File

@@ -2,7 +2,7 @@
import type { ReactNode } from 'react'
import { cn } from '@langgenius/dify-ui/cn'
import { Tooltip, TooltipContent, TooltipTrigger } from '@/app/components/base/ui/tooltip'
import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip'
type SectionHeaderProps = {
title: string
@@ -32,7 +32,7 @@ const SectionHeader = ({
<div className={cn('flex flex-wrap items-start justify-between gap-3', className)}>
<div>
<div className={cn('system-xl-semibold text-text-primary', titleClassName)}>{title}</div>
{description && <div className={cn('system-sm-regular mt-1 text-text-tertiary', descriptionClassName)}>{description}</div>}
{description && <div className={cn('mt-1 system-sm-regular text-text-tertiary', descriptionClassName)}>{description}</div>}
</div>
{action}
</div>

View File

@@ -14,7 +14,7 @@ vi.mock('@/next/navigation', () => ({
}),
}))
vi.mock('@/app/components/base/ui/toast', () => ({
vi.mock('@langgenius/dify-ui/toast', () => ({
toast: {
success: mockToastSuccess,
error: mockToastError,

View File

@@ -1,6 +1,6 @@
import type { SnippetInputField } from '@/models/snippet'
import { toast } from '@langgenius/dify-ui/toast'
import { act, renderHook } from '@testing-library/react'
import { toast } from '@/app/components/base/ui/toast'
import { PipelineInputVarType } from '@/models/pipeline'
import { useSnippetInputFieldActions } from '../use-snippet-input-field-actions'
@@ -23,7 +23,7 @@ let snippetDetailStoreState: {
toggleInputPanel: typeof mockToggleInputPanel
}
vi.mock('@/app/components/base/ui/toast', () => ({
vi.mock('@langgenius/dify-ui/toast', () => ({
toast: {
error: vi.fn(),
},

View File

@@ -1,5 +1,5 @@
import { toast } from '@langgenius/dify-ui/toast'
import { act, renderHook, waitFor } from '@testing-library/react'
import { toast } from '@/app/components/base/ui/toast'
import { useSnippetPublish } from '../use-snippet-publish'
const mockMutateAsync = vi.fn()
@@ -15,7 +15,7 @@ vi.mock('ahooks', () => ({
useKeyPress: (...args: Parameters<typeof mockUseKeyPress>) => mockUseKeyPress(...args),
}))
vi.mock('@/app/components/base/ui/toast', () => ({
vi.mock('@langgenius/dify-ui/toast', () => ({
toast: {
error: vi.fn(),
success: vi.fn(),

View File

@@ -1,8 +1,8 @@
import type { SnippetInputField } from '@/models/snippet'
import { toast } from '@langgenius/dify-ui/toast'
import { useCallback } from 'react'
import { useTranslation } from 'react-i18next'
import { useShallow } from 'zustand/react/shallow'
import { toast } from '@/app/components/base/ui/toast'
import { useNodesSyncDraft } from '../../hooks/use-nodes-sync-draft'
import { useSnippetDetailStore } from '../../store'

View File

@@ -1,8 +1,8 @@
import { toast } from '@langgenius/dify-ui/toast'
import { useKeyPress } from 'ahooks'
import { useCallback } from 'react'
import { useTranslation } from 'react-i18next'
import { useShallow } from 'zustand/react/shallow'
import { toast } from '@/app/components/base/ui/toast'
import { useWorkflowStore } from '@/app/components/workflow/store'
import { getKeyboardKeyCodeBySystem } from '@/app/components/workflow/utils'
import { usePublishSnippetWorkflowMutation } from '@/service/use-snippet-workflows'

View File

@@ -1,12 +1,12 @@
import type { FormData, InputFieldFormProps } from '@/app/components/rag-pipeline/components/panel/input-field/editor/form/types'
import type { MoreInfo } from '@/app/components/workflow/types'
import { Button } from '@langgenius/dify-ui/button'
import { toast } from '@langgenius/dify-ui/toast'
import { useCallback, useState } from 'react'
import { useTranslation } from 'react-i18next'
import Divider from '@/app/components/base/divider'
import { useFileSizeLimit } from '@/app/components/base/file-uploader/hooks'
import { useAppForm } from '@/app/components/base/form'
import { Button } from '@/app/components/base/ui/button'
import { toast } from '@/app/components/base/ui/toast'
import HiddenFields from '@/app/components/rag-pipeline/components/panel/input-field/editor/form/hidden-fields'
import ShowAllSettings from '@/app/components/rag-pipeline/components/panel/input-field/editor/form/show-all-settings'
import { ChangeType } from '@/app/components/workflow/types'

View File

@@ -2,9 +2,9 @@
import type { SortableItem } from '@/app/components/rag-pipeline/components/panel/input-field/field-list/types'
import type { SnippetInputField } from '@/models/snippet'
import { Button } from '@langgenius/dify-ui/button'
import { memo, useCallback } from 'react'
import { useTranslation } from 'react-i18next'
import { Button } from '@/app/components/base/ui/button'
import FieldListContainer from '@/app/components/rag-pipeline/components/panel/input-field/field-list/field-list-container'
type SnippetInputFieldPanelProps = {
@@ -45,12 +45,12 @@ const SnippetInputFieldPanel = ({
return (
<div className="mr-1 flex h-full w-[min(400px,calc(100vw-24px))] flex-col rounded-2xl border border-components-panel-border bg-components-panel-bg shadow-xl shadow-shadow-shadow-5">
<div className="flex items-start justify-between gap-3 px-4 pb-2 pt-4">
<div className="flex items-start justify-between gap-3 px-4 pt-4 pb-2">
<div className="min-w-0">
<div className="text-text-primary system-xl-semibold">
<div className="system-xl-semibold text-text-primary">
{t('panelTitle')}
</div>
<div className="pt-1 text-text-tertiary system-sm-regular">
<div className="pt-1 system-sm-regular text-text-tertiary">
{t('panelDescription')}
</div>
</div>

View File

@@ -1,8 +1,8 @@
'use client'
import type { SnippetDetailUIModel } from '@/models/snippet'
import { Button } from '@langgenius/dify-ui/button'
import { useTranslation } from 'react-i18next'
import { Button } from '@/app/components/base/ui/button'
import ShortcutsName from '@/app/components/workflow/shortcuts-name'
import { useFormatTimeFromNow } from '@/hooks/use-format-time-from-now'

View File

@@ -1,9 +1,9 @@
'use client'
import type { AppIconSelection } from '@/app/components/base/app-icon-picker'
import { toast } from '@langgenius/dify-ui/toast'
import { useState } from 'react'
import { useTranslation } from 'react-i18next'
import { toast } from '@/app/components/base/ui/toast'
import CreateSnippetDialog from '@/app/components/workflow/create-snippet-dialog'
import { useRouter } from '@/next/navigation'
import {
@@ -62,22 +62,22 @@ const SnippetCreateCard = () => {
<>
<div className="relative col-span-1 inline-flex h-[160px] flex-col justify-between rounded-xl border-[0.5px] border-components-card-border bg-components-card-bg transition-opacity">
<div className="grow rounded-t-xl p-2">
<div className="px-6 pb-1 pt-2 text-xs font-medium leading-[18px] text-text-tertiary">{t('create')}</div>
<div className="px-6 pt-2 pb-1 text-xs leading-[18px] font-medium text-text-tertiary">{t('create')}</div>
<button
type="button"
className="mb-1 flex w-full cursor-pointer items-center rounded-lg px-6 py-[7px] text-[13px] font-medium leading-[18px] text-text-tertiary hover:bg-state-base-hover hover:text-text-secondary disabled:cursor-not-allowed disabled:opacity-50"
className="mb-1 flex w-full cursor-pointer items-center rounded-lg px-6 py-[7px] text-[13px] leading-[18px] font-medium text-text-tertiary hover:bg-state-base-hover hover:text-text-secondary disabled:cursor-not-allowed disabled:opacity-50"
disabled={createSnippetMutation.isPending}
onClick={handleCreateFromBlank}
>
<span aria-hidden className="i-ri-sticky-note-add-line mr-2 h-4 w-4 shrink-0" />
<span aria-hidden className="mr-2 i-ri-sticky-note-add-line h-4 w-4 shrink-0" />
{t('createFromBlank')}
</button>
<button
type="button"
className="flex w-full cursor-pointer items-center rounded-lg px-6 py-[7px] text-[13px] font-medium leading-[18px] text-text-tertiary hover:bg-state-base-hover hover:text-text-secondary"
className="flex w-full cursor-pointer items-center rounded-lg px-6 py-[7px] text-[13px] leading-[18px] font-medium text-text-tertiary hover:bg-state-base-hover hover:text-text-secondary"
onClick={handleImportDSL}
>
<span aria-hidden className="i-ri-file-upload-line mr-2 h-4 w-4 shrink-0" />
<span aria-hidden className="mr-2 i-ri-file-upload-line h-4 w-4 shrink-0" />
{t('importDSL', { ns: 'app' })}
</button>
</div>

View File

@@ -1,13 +1,13 @@
'use client'
import type { SnippetDetailUIModel } from '@/models/snippet'
import { memo } from 'react'
import { useTranslation } from 'react-i18next'
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuTrigger,
} from '@/app/components/base/ui/dropdown-menu'
} from '@langgenius/dify-ui/dropdown-menu'
import { memo } from 'react'
import { useTranslation } from 'react-i18next'
import PublishMenu from '../publish-menu'
type PublisherProps = {

View File

@@ -1,13 +1,13 @@
'use client'
import { Button } from '@langgenius/dify-ui/button'
import { cn } from '@langgenius/dify-ui/cn'
import { Dialog, DialogCloseButton, DialogContent, DialogTitle } from '@langgenius/dify-ui/dialog'
import { toast } from '@langgenius/dify-ui/toast'
import { useDebounceFn, useKeyPress } from 'ahooks'
import { useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next'
import Uploader from '@/app/components/app/create-from-dsl-modal/uploader'
import Input from '@/app/components/base/input'
import { Button } from '@/app/components/base/ui/button'
import { Dialog, DialogCloseButton, DialogContent, DialogTitle } from '@/app/components/base/ui/dialog'
import { toast } from '@/app/components/base/ui/toast'
import {
DSLImportMode,
DSLImportStatus,
@@ -169,7 +169,7 @@ const SnippetImportDSLDialog = ({
<DialogCloseButton className="top-6 right-5 h-8 w-8" />
</div>
<div className="system-md-semibold flex h-9 items-center space-x-6 border-b border-divider-subtle px-6 text-text-tertiary">
<div className="flex h-9 items-center space-x-6 border-b border-divider-subtle px-6 system-md-semibold text-text-tertiary">
{[
{ key: SnippetImportDSLTab.FromFile, label: t('importFromDSLFile', { ns: 'app' }) },
{ key: SnippetImportDSLTab.FromURL, label: t('importFromDSLUrl', { ns: 'app' }) },
@@ -201,7 +201,7 @@ const SnippetImportDSLDialog = ({
)}
{currentTab === SnippetImportDSLTab.FromURL && (
<div>
<div className="system-md-semibold mb-1 text-text-secondary">DSL URL</div>
<div className="mb-1 system-md-semibold text-text-secondary">DSL URL</div>
<Input
placeholder={t('importFromDSLUrlPlaceholder', { ns: 'app' }) || ''}
value={dslUrlValue}
@@ -234,7 +234,7 @@ const SnippetImportDSLDialog = ({
<DialogTitle className="title-2xl-semi-bold text-text-primary">
{t('newApp.appCreateDSLErrorTitle', { ns: 'app' })}
</DialogTitle>
<div className="system-md-regular flex grow flex-col text-text-secondary">
<div className="flex grow flex-col system-md-regular text-text-secondary">
<div>{t('newApp.appCreateDSLErrorPart1', { ns: 'app' })}</div>
<div>{t('newApp.appCreateDSLErrorPart2', { ns: 'app' })}</div>
<br />

View File

@@ -3,6 +3,8 @@
import type { InputForm } from '@/app/components/base/chat/chat/type'
import type { InputVar as WorkflowInputVar } from '@/app/components/workflow/types'
import type { SnippetInputField } from '@/models/snippet'
import { Button } from '@langgenius/dify-ui/button'
import { toast } from '@langgenius/dify-ui/toast'
import copy from 'copy-to-clipboard'
import {
memo,
@@ -12,11 +14,9 @@ import {
useState,
} from 'react'
import { useTranslation } from 'react-i18next'
import { Button } from '@/app/components/base/ui/button'
import { useCheckInputsForms } from '@/app/components/base/chat/chat/check-input-forms-hooks'
import { getProcessedInputs } from '@/app/components/base/chat/chat/utils'
import Loading from '@/app/components/base/loading'
import { toast } from '@/app/components/base/ui/toast'
import {
useWorkflowInteractions,
useWorkflowRun,
@@ -157,7 +157,7 @@ const SnippetRunPanel = ({
style={{ width: `${panelWidth}px` }}
>
<div
className="absolute bottom-0 left-[3px] top-1/2 z-50 h-6 w-[3px] cursor-col-resize rounded bg-gray-300"
className="absolute top-1/2 bottom-0 left-[3px] z-50 h-6 w-[3px] cursor-col-resize rounded bg-gray-300"
onMouseDown={startResizing}
/>
<div className="flex items-center justify-between p-4 pb-1 text-base font-semibold text-text-primary">
@@ -170,26 +170,26 @@ const SnippetRunPanel = ({
<div className="flex shrink-0 items-center border-b-[0.5px] border-divider-subtle px-4">
{hasInputTab && (
<div
className={`mr-6 cursor-pointer border-b-2 py-3 text-[13px] font-semibold leading-[18px] ${currentTab === 'INPUT' ? '!border-[rgb(21,94,239)] text-text-secondary' : 'border-transparent text-text-tertiary'}`}
className={`mr-6 cursor-pointer border-b-2 py-3 text-[13px] leading-[18px] font-semibold ${currentTab === 'INPUT' ? '!border-[rgb(21,94,239)] text-text-secondary' : 'border-transparent text-text-tertiary'}`}
onClick={() => setSelectedTab('INPUT')}
>
{t('input', { ns: 'runLog' })}
</div>
)}
<div
className={`mr-6 cursor-pointer border-b-2 py-3 text-[13px] font-semibold leading-[18px] ${currentTab === 'RESULT' ? '!border-[rgb(21,94,239)] text-text-secondary' : 'border-transparent text-text-tertiary'} ${!workflowRunningData ? '!cursor-not-allowed opacity-30' : ''}`}
className={`mr-6 cursor-pointer border-b-2 py-3 text-[13px] leading-[18px] font-semibold ${currentTab === 'RESULT' ? '!border-[rgb(21,94,239)] text-text-secondary' : 'border-transparent text-text-tertiary'} ${!workflowRunningData ? '!cursor-not-allowed opacity-30' : ''}`}
onClick={() => workflowRunningData && setSelectedTab('RESULT')}
>
{t('result', { ns: 'runLog' })}
</div>
<div
className={`mr-6 cursor-pointer border-b-2 py-3 text-[13px] font-semibold leading-[18px] ${currentTab === 'DETAIL' ? '!border-[rgb(21,94,239)] text-text-secondary' : 'border-transparent text-text-tertiary'} ${!workflowRunningData ? '!cursor-not-allowed opacity-30' : ''}`}
className={`mr-6 cursor-pointer border-b-2 py-3 text-[13px] leading-[18px] font-semibold ${currentTab === 'DETAIL' ? '!border-[rgb(21,94,239)] text-text-secondary' : 'border-transparent text-text-tertiary'} ${!workflowRunningData ? '!cursor-not-allowed opacity-30' : ''}`}
onClick={() => workflowRunningData && setSelectedTab('DETAIL')}
>
{t('detail', { ns: 'runLog' })}
</div>
<div
className={`mr-6 cursor-pointer border-b-2 py-3 text-[13px] font-semibold leading-[18px] ${currentTab === 'TRACING' ? '!border-[rgb(21,94,239)] text-text-secondary' : 'border-transparent text-text-tertiary'} ${!workflowRunningData ? '!cursor-not-allowed opacity-30' : ''}`}
className={`mr-6 cursor-pointer border-b-2 py-3 text-[13px] leading-[18px] font-semibold ${currentTab === 'TRACING' ? '!border-[rgb(21,94,239)] text-text-secondary' : 'border-transparent text-text-tertiary'} ${!workflowRunningData ? '!cursor-not-allowed opacity-30' : ''}`}
onClick={() => workflowRunningData && setSelectedTab('TRACING')}
>
{t('tracing', { ns: 'runLog' })}
@@ -198,7 +198,7 @@ const SnippetRunPanel = ({
<div className={`h-0 grow overflow-y-auto rounded-b-2xl ${(currentTab === 'RESULT' || currentTab === 'TRACING') ? '!bg-background-section-burn' : 'bg-components-panel-bg'}`}>
{currentTab === 'INPUT' && hasInputTab && (
<>
<div className="px-4 pb-2 pt-3">
<div className="px-4 pt-3 pb-2">
{previewFields.map((field, index) => (
<div
key={field.variable}

View File

@@ -26,7 +26,7 @@ vi.mock('@/service/client', () => ({
},
}))
vi.mock('@/app/components/base/ui/toast', () => ({
vi.mock('@langgenius/dify-ui/toast', () => ({
toast: {
success: (...args: unknown[]) => mockToastSuccess(...args),
error: (...args: unknown[]) => mockToastError(...args),

View File

@@ -38,7 +38,7 @@ vi.mock('../../../hooks', () => ({
},
}))
vi.mock('@/app/components/base/ui/toast', () => ({
vi.mock('@langgenius/dify-ui/toast', () => ({
toast: {
error: (...args: unknown[]) => mockToastError(...args),
},

View File

@@ -1,4 +1,16 @@
import { cn } from '@langgenius/dify-ui/cn'
import {
ScrollAreaContent,
ScrollAreaRoot,
ScrollAreaScrollbar,
ScrollAreaThumb,
ScrollAreaViewport,
} from '@langgenius/dify-ui/scroll-area'
import {
Tooltip,
TooltipContent,
TooltipTrigger,
} from '@langgenius/dify-ui/tooltip'
import { useInfiniteScroll } from 'ahooks'
import {
memo,
@@ -8,18 +20,6 @@ import {
useState,
} from 'react'
import Loading from '@/app/components/base/loading'
import {
ScrollAreaContent,
ScrollAreaRoot,
ScrollAreaScrollbar,
ScrollAreaThumb,
ScrollAreaViewport,
} from '@/app/components/base/ui/scroll-area'
import {
Tooltip,
TooltipContent,
TooltipTrigger,
} from '@/app/components/base/ui/tooltip'
import { useInfiniteSnippetList } from '@/service/use-snippets'
import CreateSnippetDialog from '../../create-snippet-dialog'
import SnippetDetailCard from './snippet-detail-card'

View File

@@ -1,6 +1,6 @@
import type { FC } from 'react'
import { Button } from '@langgenius/dify-ui/button'
import { useTranslation } from 'react-i18next'
import { Button } from '@/app/components/base/ui/button'
type SnippetEmptyStateProps = {
onCreate: () => void
@@ -14,7 +14,7 @@ const SnippetEmptyState: FC<SnippetEmptyStateProps> = ({
return (
<div className="flex min-h-[480px] flex-col items-center justify-center gap-2 px-4">
<span className="i-custom-vender-line-others-search-menu h-8 w-8 text-text-tertiary" />
<div className="text-text-secondary system-sm-regular">
<div className="system-sm-regular text-text-secondary">
{t('tabs.noSnippetsFound', { ns: 'workflow' })}
</div>
<Button

View File

@@ -1,7 +1,7 @@
import type { CreateSnippetDialogPayload } from '../../create-snippet-dialog'
import { toast } from '@langgenius/dify-ui/toast'
import { useState } from 'react'
import { useTranslation } from 'react-i18next'
import { toast } from '@/app/components/base/ui/toast'
import { useRouter } from '@/next/navigation'
import { consoleClient } from '@/service/client'
import { useCreateSnippetMutation } from '@/service/use-snippets'

View File

@@ -1,9 +1,9 @@
import type { Edge, Node } from '../../types'
import { toast } from '@langgenius/dify-ui/toast'
import { useQueryClient } from '@tanstack/react-query'
import { useCallback } from 'react'
import { useTranslation } from 'react-i18next'
import { useStoreApi } from 'reactflow'
import { toast } from '@/app/components/base/ui/toast'
import { consoleQuery } from '@/service/client'
import { useNodesSyncDraft, useWorkflowHistory, WorkflowHistoryEvent } from '../../hooks'

View File

@@ -3,15 +3,15 @@
import type { FC } from 'react'
import type { AppIconSelection } from '@/app/components/base/app-icon-picker'
import type { SnippetCanvasData } from '@/models/snippet'
import { Button } from '@langgenius/dify-ui/button'
import { Dialog, DialogCloseButton, DialogContent, DialogPortal, DialogTitle } from '@langgenius/dify-ui/dialog'
import { useKeyPress } from 'ahooks'
import { useCallback, useState } from 'react'
import { useTranslation } from 'react-i18next'
import AppIcon from '@/app/components/base/app-icon'
import AppIconPicker from '@/app/components/base/app-icon-picker'
import { Button } from '@/app/components/base/ui/button'
import Input from '@/app/components/base/input'
import Textarea from '@/app/components/base/textarea'
import { Dialog, DialogCloseButton, DialogContent, DialogPortal, DialogTitle } from '@/app/components/base/ui/dialog'
import ShortcutsName from './shortcuts-name'
export type CreateSnippetDialogPayload = {