mirror of
https://github.com/langgenius/dify.git
synced 2026-05-09 21:28:25 +08:00
fix(web): align Tailwind v4 CSS migration (#35829)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
parent
506e1a8bc7
commit
03e227f8f1
@ -438,11 +438,6 @@
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"web/app/components/app/configuration/dataset-config/select-dataset/index.tsx": {
|
||||
"no-restricted-imports": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"web/app/components/app/configuration/dataset-config/settings-modal/index.tsx": {
|
||||
"react/set-state-in-effect": {
|
||||
"count": 2
|
||||
@ -3567,11 +3562,6 @@
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"web/app/components/workflow/dsl-export-confirm-modal.tsx": {
|
||||
"no-restricted-imports": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"web/app/components/workflow/header/run-mode.tsx": {
|
||||
"no-console": {
|
||||
"count": 1
|
||||
|
||||
@ -46,6 +46,12 @@ vi.mock('@/app/components/workflow/update-dsl-modal', () => ({
|
||||
}))
|
||||
|
||||
vi.mock('@/app/components/workflow/dsl-export-confirm-modal', () => ({
|
||||
DSLExportConfirmContent: ({ onConfirm, onClose }: { onConfirm: (include?: boolean) => void, onClose: () => void }) => (
|
||||
<div data-testid="dsl-export-confirm-modal">
|
||||
<button type="button" onClick={() => onConfirm(true)}>Export Include</button>
|
||||
<button type="button" onClick={onClose}>Close Export</button>
|
||||
</div>
|
||||
),
|
||||
default: ({ onConfirm, onClose }: { onConfirm: (include?: boolean) => void, onClose: () => void }) => (
|
||||
<div data-testid="dsl-export-confirm-modal">
|
||||
<button type="button" onClick={() => onConfirm(true)}>Export Include</button>
|
||||
|
||||
@ -228,6 +228,21 @@ describe('AppOperations', () => {
|
||||
})
|
||||
|
||||
describe('Visible operations click', () => {
|
||||
it('should keep focus ring inside visible operation buttons', () => {
|
||||
const cleanup = setupDomMeasurements(500, 60, [80])
|
||||
const editOp = createOperation('edit', 'Edit')
|
||||
|
||||
render(<AppOperations gap={4} operations={[editOp]} />)
|
||||
|
||||
const visibleButton = screen.getAllByText('Edit')
|
||||
.map(label => label.closest('button'))
|
||||
.find(button => button?.tabIndex !== -1)
|
||||
|
||||
expect(visibleButton).toHaveClass('focus-visible:ring-inset')
|
||||
|
||||
cleanup()
|
||||
})
|
||||
|
||||
it('should call onClick when a visible operation is clicked', async () => {
|
||||
const cleanup = setupDomMeasurements(500, 60, [80, 80])
|
||||
const user = userEvent.setup()
|
||||
|
||||
@ -16,13 +16,13 @@ import * as React from 'react'
|
||||
import { useCallback, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Input from '@/app/components/base/input'
|
||||
import { DSLExportConfirmContent } from '@/app/components/workflow/dsl-export-confirm-modal'
|
||||
import dynamic from '@/next/dynamic'
|
||||
|
||||
const SwitchAppModal = dynamic(() => import('@/app/components/app/switch-app-modal'), { ssr: false })
|
||||
const CreateAppModal = dynamic(() => import('@/app/components/explore/create-app-modal'), { ssr: false })
|
||||
const DuplicateAppModal = dynamic(() => import('@/app/components/app/duplicate-modal'), { ssr: false })
|
||||
const UpdateDSLModal = dynamic(() => import('@/app/components/workflow/update-dsl-modal'), { ssr: false })
|
||||
const DSLExportConfirmModal = dynamic(() => import('@/app/components/workflow/dsl-export-confirm-modal'), { ssr: false })
|
||||
|
||||
type AppInfoModalsProps = {
|
||||
appDetail: App & Partial<AppSSO>
|
||||
@ -54,7 +54,14 @@ const AppInfoModals = ({
|
||||
const { t } = useTranslation()
|
||||
const [confirmDeleteInput, setConfirmDeleteInput] = useState('')
|
||||
const [isConfirmingExport, setIsConfirmingExport] = useState(false)
|
||||
const [isSecretExporting, setIsSecretExporting] = useState(false)
|
||||
const isDeleteConfirmDisabled = confirmDeleteInput !== appDetail.name
|
||||
const exportDialogMode = secretEnvList.length > 0
|
||||
? 'secret'
|
||||
: activeModal === 'exportWarning'
|
||||
? 'warning'
|
||||
: null
|
||||
const isExportDialogOpen = exportDialogMode !== null
|
||||
|
||||
const handleDeleteDialogClose = () => {
|
||||
setConfirmDeleteInput('')
|
||||
@ -74,6 +81,22 @@ const AppInfoModals = ({
|
||||
}
|
||||
}, [handleConfirmExport, isConfirmingExport])
|
||||
|
||||
const handleExportDialogClose = useCallback(() => {
|
||||
if (exportDialogMode === 'secret') {
|
||||
setSecretEnvList([])
|
||||
return
|
||||
}
|
||||
|
||||
closeModal()
|
||||
}, [closeModal, exportDialogMode, setSecretEnvList])
|
||||
|
||||
const handleExportDialogOpenChange = useCallback((open: boolean) => {
|
||||
if (open || isConfirmingExport || isSecretExporting)
|
||||
return
|
||||
|
||||
handleExportDialogClose()
|
||||
}, [handleExportDialogClose, isConfirmingExport, isSecretExporting])
|
||||
|
||||
return (
|
||||
<>
|
||||
{activeModal === 'switch' && (
|
||||
@ -163,38 +186,42 @@ const AppInfoModals = ({
|
||||
onBackup={exportCheck}
|
||||
/>
|
||||
)}
|
||||
<AlertDialog open={activeModal === 'exportWarning'} onOpenChange={open => !open && closeModal()}>
|
||||
<AlertDialogContent>
|
||||
<div className="flex flex-col gap-2 px-6 pt-6 pb-4">
|
||||
<AlertDialogTitle className="w-full truncate title-2xl-semi-bold text-text-primary">
|
||||
{t('sidebar.exportWarning', { ns: 'workflow' })}
|
||||
</AlertDialogTitle>
|
||||
<AlertDialogDescription className="w-full system-md-regular wrap-break-word whitespace-pre-wrap text-text-tertiary">
|
||||
{t('sidebar.exportWarningDesc', { ns: 'workflow' })}
|
||||
</AlertDialogDescription>
|
||||
</div>
|
||||
<AlertDialogActions>
|
||||
<AlertDialogCancelButton>{t('operation.cancel', { ns: 'common' })}</AlertDialogCancelButton>
|
||||
<AlertDialogConfirmButton
|
||||
tone="default"
|
||||
loading={isConfirmingExport}
|
||||
disabled={isConfirmingExport}
|
||||
onClick={handleExportWarningConfirm}
|
||||
>
|
||||
{isConfirmingExport
|
||||
? t('operation.exporting', { ns: 'common' })
|
||||
: t('operation.confirm', { ns: 'common' })}
|
||||
</AlertDialogConfirmButton>
|
||||
</AlertDialogActions>
|
||||
</AlertDialogContent>
|
||||
<AlertDialog open={isExportDialogOpen} onOpenChange={handleExportDialogOpenChange}>
|
||||
{exportDialogMode === 'secret'
|
||||
? (
|
||||
<DSLExportConfirmContent
|
||||
envList={secretEnvList}
|
||||
onConfirm={onExport}
|
||||
onClose={() => setSecretEnvList([])}
|
||||
onExportingChange={setIsSecretExporting}
|
||||
/>
|
||||
)
|
||||
: exportDialogMode === 'warning' && (
|
||||
<AlertDialogContent>
|
||||
<div className="flex flex-col gap-2 px-6 pt-6 pb-4">
|
||||
<AlertDialogTitle className="w-full truncate title-2xl-semi-bold text-text-primary">
|
||||
{t('sidebar.exportWarning', { ns: 'workflow' })}
|
||||
</AlertDialogTitle>
|
||||
<AlertDialogDescription className="w-full system-md-regular wrap-break-word whitespace-pre-wrap text-text-tertiary">
|
||||
{t('sidebar.exportWarningDesc', { ns: 'workflow' })}
|
||||
</AlertDialogDescription>
|
||||
</div>
|
||||
<AlertDialogActions>
|
||||
<AlertDialogCancelButton>{t('operation.cancel', { ns: 'common' })}</AlertDialogCancelButton>
|
||||
<AlertDialogConfirmButton
|
||||
tone="default"
|
||||
loading={isConfirmingExport}
|
||||
disabled={isConfirmingExport}
|
||||
onClick={handleExportWarningConfirm}
|
||||
>
|
||||
{isConfirmingExport
|
||||
? t('operation.exporting', { ns: 'common' })
|
||||
: t('operation.confirm', { ns: 'common' })}
|
||||
</AlertDialogConfirmButton>
|
||||
</AlertDialogActions>
|
||||
</AlertDialogContent>
|
||||
)}
|
||||
</AlertDialog>
|
||||
{secretEnvList.length > 0 && (
|
||||
<DSLExportConfirmModal
|
||||
envList={secretEnvList}
|
||||
onConfirm={onExport}
|
||||
onClose={() => setSecretEnvList([])}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@ -133,7 +133,7 @@ const AppOperations = ({
|
||||
data-targetid={operation.id}
|
||||
size="small"
|
||||
variant="secondary"
|
||||
className="gap-px"
|
||||
className="gap-px focus-visible:ring-inset"
|
||||
tabIndex={-1}
|
||||
>
|
||||
{cloneElement(operation.icon, { className: 'h-3.5 w-3.5 text-components-button-secondary-text' })}
|
||||
@ -146,7 +146,7 @@ const AppOperations = ({
|
||||
id="more-measure"
|
||||
size="small"
|
||||
variant="secondary"
|
||||
className="gap-px"
|
||||
className="gap-px focus-visible:ring-inset"
|
||||
tabIndex={-1}
|
||||
>
|
||||
<RiMoreLine className="h-3.5 w-3.5 text-components-button-secondary-text" />
|
||||
@ -162,7 +162,7 @@ const AppOperations = ({
|
||||
data-targetid={operation.id}
|
||||
size="small"
|
||||
variant="secondary"
|
||||
className="gap-px"
|
||||
className="gap-px focus-visible:ring-inset"
|
||||
onClick={operation.onClick}
|
||||
>
|
||||
{cloneElement(operation.icon, { className: 'h-3.5 w-3.5 text-components-button-secondary-text' })}
|
||||
@ -178,7 +178,7 @@ const AppOperations = ({
|
||||
<Button
|
||||
size="small"
|
||||
variant="secondary"
|
||||
className="gap-px"
|
||||
className="gap-px focus-visible:ring-inset"
|
||||
/>
|
||||
)}
|
||||
>
|
||||
|
||||
@ -121,7 +121,7 @@ type BaseItemProps = {
|
||||
}
|
||||
function BaseItem({ icon, onRemove, children }: BaseItemProps) {
|
||||
return (
|
||||
<div className="group flex flex-row items-center gap-x-1 rounded-full border-[0.5px] bg-components-badge-white-to-dark p-1 pr-1.5 shadow-xs">
|
||||
<div className="group flex flex-row items-center gap-x-1 rounded-full border-[0.5px] border-components-panel-border-subtle bg-components-badge-white-to-dark p-1 pr-1.5 shadow-xs">
|
||||
<div className="h-5 w-5 overflow-hidden rounded-full bg-components-icon-bg-blue-solid">
|
||||
<div className="bg-access-app-icon-mask-bg flex h-full w-full items-center justify-center">
|
||||
{icon}
|
||||
|
||||
@ -74,7 +74,7 @@ const AgentSetting: FC<Props> = ({
|
||||
</div>
|
||||
{/* Body */}
|
||||
<div
|
||||
className="grow overflow-y-auto border-b p-6 pt-5 pb-[68px]"
|
||||
className="grow overflow-y-auto border-b border-divider-regular p-6 pt-5 pb-[68px]"
|
||||
style={{
|
||||
borderBottom: 'rgba(0, 0, 0, 0.05)',
|
||||
}}
|
||||
|
||||
@ -174,14 +174,12 @@ const ConfigurationView: FC<ConfigurationViewModel> = ({
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
|
||||
{isShowSelectDataSet && (
|
||||
<SelectDataSet
|
||||
isShow={isShowSelectDataSet}
|
||||
onClose={onCloseSelectDataSet}
|
||||
selectedIds={selectedIds}
|
||||
onSelect={onSelectDataSets}
|
||||
/>
|
||||
)}
|
||||
<SelectDataSet
|
||||
isShow={isShowSelectDataSet}
|
||||
onClose={onCloseSelectDataSet}
|
||||
selectedIds={selectedIds}
|
||||
onSelect={onSelectDataSets}
|
||||
/>
|
||||
|
||||
{isShowHistoryModal && (
|
||||
<EditHistoryModal
|
||||
|
||||
@ -3,14 +3,14 @@ import type { FC } from 'react'
|
||||
import type { DataSet } from '@/models/datasets'
|
||||
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 { useInfiniteScroll } from 'ahooks'
|
||||
import * as React from 'react'
|
||||
import { useMemo, useRef, useState } from 'react'
|
||||
import { useCallback, useMemo, useRef, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import AppIcon from '@/app/components/base/app-icon'
|
||||
import Badge from '@/app/components/base/badge'
|
||||
import Loading from '@/app/components/base/loading'
|
||||
import Modal from '@/app/components/base/modal'
|
||||
import { ModelFeatureEnum } from '@/app/components/header/account-setting/model-provider-page/declarations'
|
||||
import FeatureIcon from '@/app/components/header/account-setting/model-provider-page/model-selector/feature-icon'
|
||||
import { useKnowledge } from '@/hooks/use-knowledge'
|
||||
@ -79,100 +79,103 @@ const SelectDataSet: FC<ISelectDataSetProps> = ({
|
||||
onSelect(selected)
|
||||
}
|
||||
|
||||
const handleClose = useCallback(() => {
|
||||
setSelectedIdsInModal(selectedIds)
|
||||
onClose()
|
||||
}, [onClose, selectedIds])
|
||||
|
||||
const handleOpenChange = useCallback((open: boolean) => {
|
||||
if (!open)
|
||||
handleClose()
|
||||
}, [handleClose])
|
||||
|
||||
return (
|
||||
<Modal
|
||||
isShow={isShow}
|
||||
onClose={onClose}
|
||||
className="w-[400px]"
|
||||
title={t('feature.dataSet.selectTitle', { ns: 'appDebug' })}
|
||||
>
|
||||
{(isLoading && datasets.length === 0) && (
|
||||
<div className="flex h-[200px]">
|
||||
<Loading type="area" />
|
||||
</div>
|
||||
)}
|
||||
<Dialog open={isShow} onOpenChange={handleOpenChange}>
|
||||
<DialogContent className="w-100 overflow-hidden">
|
||||
<DialogTitle className="title-2xl-semi-bold text-text-primary">
|
||||
{t('feature.dataSet.selectTitle', { ns: 'appDebug' })}
|
||||
</DialogTitle>
|
||||
<DialogCloseButton aria-label={t('operation.close', { ns: 'common' })} />
|
||||
{(isLoading && datasets.length === 0) && (
|
||||
<div className="flex h-50">
|
||||
<Loading type="area" />
|
||||
</div>
|
||||
)}
|
||||
|
||||
{hasNoData && (
|
||||
<div
|
||||
className="mt-6 flex h-[128px] items-center justify-center space-x-1 rounded-lg border text-[13px]"
|
||||
style={{
|
||||
background: 'rgba(0, 0, 0, 0.02)',
|
||||
borderColor: 'rgba(0, 0, 0, 0.02',
|
||||
}}
|
||||
>
|
||||
<span className="text-text-tertiary">{t('feature.dataSet.noDataSet', { ns: 'appDebug' })}</span>
|
||||
<Link href="/datasets/create" className="font-normal text-text-accent">{t('feature.dataSet.toCreate', { ns: 'appDebug' })}</Link>
|
||||
</div>
|
||||
)}
|
||||
{hasNoData && (
|
||||
<div className="mt-6 flex h-32 items-center justify-center space-x-1 rounded-lg border border-divider-subtle bg-components-panel-on-panel-item-bg text-[13px]">
|
||||
<span className="text-text-tertiary">{t('feature.dataSet.noDataSet', { ns: 'appDebug' })}</span>
|
||||
<Link href="/datasets/create" className="font-normal text-text-accent">{t('feature.dataSet.toCreate', { ns: 'appDebug' })}</Link>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{datasets.length > 0 && (
|
||||
<>
|
||||
<div ref={listRef} className="mt-7 max-h-[286px] space-y-1 overflow-y-auto">
|
||||
{datasets.map(item => (
|
||||
<div
|
||||
key={item.id}
|
||||
className={cn(
|
||||
'flex h-10 cursor-pointer items-center rounded-lg border-[0.5px] border-components-panel-border-subtle bg-components-panel-on-panel-item-bg px-2 shadow-xs hover:border-components-panel-border hover:bg-components-panel-on-panel-item-bg-hover hover:shadow-sm',
|
||||
selectedIdsInModal.includes(item.id) && 'border-[1.5px] border-components-option-card-option-selected-border bg-state-accent-hover shadow-xs hover:border-components-option-card-option-selected-border hover:bg-state-accent-hover hover:shadow-xs',
|
||||
!item.embedding_available && 'hover:border-components-panel-border-subtle hover:bg-components-panel-on-panel-item-bg hover:shadow-xs',
|
||||
)}
|
||||
onClick={() => {
|
||||
if (!item.embedding_available)
|
||||
return
|
||||
toggleSelect(item)
|
||||
}}
|
||||
>
|
||||
<div className="mr-1 flex grow items-center overflow-hidden">
|
||||
<div className={cn('mr-2', !item.embedding_available && 'opacity-30')}>
|
||||
<AppIcon
|
||||
size="tiny"
|
||||
iconType={item.icon_info.icon_type}
|
||||
icon={item.icon_info.icon}
|
||||
background={item.icon_info.icon_type === 'image' ? undefined : item.icon_info.icon_background}
|
||||
imageUrl={item.icon_info.icon_type === 'image' ? item.icon_info.icon_url : undefined}
|
||||
/>
|
||||
</div>
|
||||
<div className={cn('max-w-[200px] truncate text-[13px] font-medium text-text-secondary', !item.embedding_available && 'max-w-[120px]! opacity-30')}>{item.name}</div>
|
||||
{!item.embedding_available && (
|
||||
<span className="ml-1 shrink-0 rounded-md border border-divider-deep px-1 text-xs leading-[18px] font-normal text-text-tertiary">{t('unavailable', { ns: 'dataset' })}</span>
|
||||
{datasets.length > 0 && (
|
||||
<>
|
||||
<div ref={listRef} className="mt-7 max-h-71.5 space-y-1 overflow-y-auto">
|
||||
{datasets.map(item => (
|
||||
<button
|
||||
key={item.id}
|
||||
type="button"
|
||||
disabled={!item.embedding_available}
|
||||
className={cn(
|
||||
'flex h-10 w-full cursor-pointer items-center rounded-lg border-[0.5px] border-components-panel-border-subtle bg-components-panel-on-panel-item-bg px-2 text-left shadow-xs outline-hidden hover:border-components-panel-border hover:bg-components-panel-on-panel-item-bg-hover hover:shadow-sm focus-visible:ring-2 focus-visible:ring-state-accent-solid',
|
||||
selectedIdsInModal.includes(item.id) && 'border-[1.5px] border-components-option-card-option-selected-border bg-state-accent-hover shadow-xs hover:border-components-option-card-option-selected-border hover:bg-state-accent-hover hover:shadow-xs',
|
||||
!item.embedding_available && 'cursor-default hover:border-components-panel-border-subtle hover:bg-components-panel-on-panel-item-bg hover:shadow-xs',
|
||||
)}
|
||||
</div>
|
||||
{item.is_multimodal && (
|
||||
<div className="mr-1 shrink-0">
|
||||
<FeatureIcon feature={ModelFeatureEnum.vision} />
|
||||
onClick={() => toggleSelect(item)}
|
||||
>
|
||||
<div className="mr-1 flex grow items-center overflow-hidden">
|
||||
<div className={cn('mr-2', !item.embedding_available && 'opacity-30')}>
|
||||
<AppIcon
|
||||
size="tiny"
|
||||
iconType={item.icon_info.icon_type}
|
||||
icon={item.icon_info.icon}
|
||||
background={item.icon_info.icon_type === 'image' ? undefined : item.icon_info.icon_background}
|
||||
imageUrl={item.icon_info.icon_type === 'image' ? item.icon_info.icon_url : undefined}
|
||||
/>
|
||||
</div>
|
||||
<div className={cn('max-w-50 truncate text-[13px] font-medium text-text-secondary', !item.embedding_available && 'max-w-30! opacity-30')}>{item.name}</div>
|
||||
{!item.embedding_available && (
|
||||
<span className="ml-1 shrink-0 rounded-md border border-divider-deep px-1 text-xs leading-[18px] font-normal text-text-tertiary">{t('unavailable', { ns: 'dataset' })}</span>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
{
|
||||
!!item.indexing_technique && (
|
||||
<Badge
|
||||
className="shrink-0"
|
||||
text={formatIndexingTechniqueAndMethod(item.indexing_technique, item.retrieval_model_dict?.search_method)}
|
||||
/>
|
||||
)
|
||||
}
|
||||
{
|
||||
item.provider === 'external' && (
|
||||
<Badge className="shrink-0" text={t('externalTag', { ns: 'dataset' })} />
|
||||
)
|
||||
}
|
||||
</div>
|
||||
))}
|
||||
{isFetchingNextPage && <Loading />}
|
||||
{item.is_multimodal && (
|
||||
<div className="mr-1 shrink-0">
|
||||
<FeatureIcon feature={ModelFeatureEnum.vision} />
|
||||
</div>
|
||||
)}
|
||||
{
|
||||
!!item.indexing_technique && (
|
||||
<Badge
|
||||
className="shrink-0"
|
||||
text={formatIndexingTechniqueAndMethod(item.indexing_technique, item.retrieval_model_dict?.search_method)}
|
||||
/>
|
||||
)
|
||||
}
|
||||
{
|
||||
item.provider === 'external' && (
|
||||
<Badge className="shrink-0" text={t('externalTag', { ns: 'dataset' })} />
|
||||
)
|
||||
}
|
||||
</button>
|
||||
))}
|
||||
{isFetchingNextPage && <Loading />}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
{!isLoading && (
|
||||
<div className="mt-8 flex items-center justify-between">
|
||||
<div className="text-sm font-medium text-text-secondary">
|
||||
{selected.length > 0 && `${selected.length} ${t('feature.dataSet.selected', { ns: 'appDebug' })}`}
|
||||
</div>
|
||||
<div className="flex space-x-2">
|
||||
<Button onClick={handleClose}>{t('operation.cancel', { ns: 'common' })}</Button>
|
||||
<Button variant="primary" onClick={handleSelect} disabled={hasNoData}>{t('operation.add', { ns: 'common' })}</Button>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
{!isLoading && (
|
||||
<div className="mt-8 flex items-center justify-between">
|
||||
<div className="text-sm font-medium text-text-secondary">
|
||||
{selected.length > 0 && `${selected.length} ${t('feature.dataSet.selected', { ns: 'appDebug' })}`}
|
||||
</div>
|
||||
<div className="flex space-x-2">
|
||||
<Button onClick={onClose}>{t('operation.cancel', { ns: 'common' })}</Button>
|
||||
<Button variant="primary" onClick={handleSelect} disabled={hasNoData}>{t('operation.add', { ns: 'common' })}</Button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</Modal>
|
||||
)}
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
export default React.memo(SelectDataSet)
|
||||
|
||||
@ -95,7 +95,7 @@ const ImageInput: FC<UploaderProps> = ({
|
||||
return (
|
||||
<div className={cn(className, 'w-full px-3 py-1.5')}>
|
||||
<div
|
||||
className={cn(isDragActive && 'border-primary-600', 'relative flex aspect-square flex-col items-center justify-center rounded-lg border-[1.5px] border-dashed text-gray-500')}
|
||||
className={cn('relative flex aspect-square flex-col items-center justify-center rounded-lg border-[1.5px] border-dashed border-components-input-border-hover text-gray-500', isDragActive && 'border-primary-600')}
|
||||
onDragEnter={handleDragEnter}
|
||||
onDragOver={handleDragOver}
|
||||
onDragLeave={handleDragLeave}
|
||||
|
||||
@ -146,7 +146,7 @@ const ChatInputArea = ({ readonly, botName, showFeatureBar, showFileUpload, feat
|
||||
<div ref={textValueRef} className="pointer-events-none invisible absolute h-auto w-auto p-1 body-lg-regular leading-6 whitespace-pre">
|
||||
{query}
|
||||
</div>
|
||||
<Textarea ref={ref => textareaRef.current = ref as any} className={cn('w-full resize-none bg-transparent p-1 body-lg-regular leading-6 text-text-primary outline-none')} placeholder={decode(t(readonly ? 'chat.inputDisabledPlaceholder' : 'chat.inputPlaceholder', { ns: 'common', botName }) || '')} autoFocus minRows={1} value={query} onChange={e => handleQueryChange(e.target.value)} onKeyDown={handleKeyDown} onCompositionStart={handleCompositionStart} onCompositionEnd={handleCompositionEnd} onPaste={handleClipboardPasteFile} onDragEnter={handleDragFileEnter} onDragLeave={handleDragFileLeave} onDragOver={handleDragFileOver} onDrop={handleDropFile} readOnly={readonly} />
|
||||
<Textarea ref={ref => textareaRef.current = ref as any} className={cn('w-full resize-none bg-transparent p-1 body-lg-regular leading-6 text-text-primary outline-hidden')} placeholder={decode(t(readonly ? 'chat.inputDisabledPlaceholder' : 'chat.inputPlaceholder', { ns: 'common', botName }) || '')} autoFocus minRows={1} value={query} onChange={e => handleQueryChange(e.target.value)} onKeyDown={handleKeyDown} onCompositionStart={handleCompositionStart} onCompositionEnd={handleCompositionEnd} onPaste={handleClipboardPasteFile} onDragEnter={handleDragFileEnter} onDragLeave={handleDragFileLeave} onDragOver={handleDragFileOver} onDrop={handleDropFile} readOnly={readonly} />
|
||||
</div>
|
||||
{!isMultipleLine && operation}
|
||||
</div>
|
||||
|
||||
@ -80,7 +80,7 @@ const FileImageItem = ({
|
||||
}
|
||||
{
|
||||
showDownloadAction && (
|
||||
<div className="bg-opacity-[0.3] absolute inset-0.5 z-10 hidden bg-background-overlay-alt group-hover/file-image:block">
|
||||
<div className="absolute inset-0.5 z-10 hidden bg-background-overlay-alt group-hover/file-image:block">
|
||||
<div
|
||||
className="absolute right-0.5 bottom-0.5 flex h-6 w-6 items-center justify-center rounded-lg bg-components-actionbar-bg shadow-md"
|
||||
onClick={(e) => {
|
||||
|
||||
@ -77,7 +77,7 @@ const TagInput: FC<TagInputProps> = ({ items, onChange, disableAdd, disableRemov
|
||||
<div className={cn('group/tag-add mt-1 flex items-center gap-x-0.5', !isSpecialMode ? 'rounded-md border border-dashed border-divider-deep px-1.5' : '')}>
|
||||
{!isSpecialMode && !focused && <span className="i-ri-add-line h-3.5 w-3.5 text-text-placeholder group-hover/tag-add:text-text-secondary" />}
|
||||
<AutosizeInput
|
||||
inputClassName={cn('appearance-none text-text-primary caret-[#295EFF] outline-none placeholder:text-text-placeholder group-hover/tag-add:placeholder:text-text-secondary', isSpecialMode ? 'bg-transparent' : '', inputClassName)}
|
||||
inputClassName={cn('appearance-none text-text-primary caret-[#295EFF] outline-hidden placeholder:text-text-placeholder group-hover/tag-add:placeholder:text-text-secondary', isSpecialMode ? 'bg-transparent' : '', inputClassName)}
|
||||
className={cn(!isInWorkflow && 'max-w-[300px]', isInWorkflow && 'max-w-[146px]', 'overflow-hidden rounded-md py-1 system-xs-regular', isSpecialMode && 'border border-transparent px-1.5', focused && isSpecialMode && 'border-dashed border-divider-deep')}
|
||||
onFocus={() => setFocused(true)}
|
||||
onBlur={handleBlur}
|
||||
|
||||
@ -53,7 +53,7 @@ const TagManagementModal = ({ show, type }: TagManagementModalProps) => {
|
||||
<span className="i-ri-close-line h-4 w-4 text-text-tertiary" data-testid="tag-management-modal-close-button" />
|
||||
</div>
|
||||
<div className="mt-3 flex flex-wrap gap-2">
|
||||
<input className="w-[100px] shrink-0 appearance-none rounded-lg border border-dashed border-divider-regular bg-transparent px-2 py-1 text-sm leading-5 text-text-secondary caret-primary-600 outline-none placeholder:text-text-quaternary focus:border-solid" placeholder={t('tag.addNew', { ns: 'common' }) || ''} autoFocus value={name} onChange={e => setName(e.target.value)} onKeyDown={e => e.key === 'Enter' && !e.nativeEvent.isComposing && createNewTag()} onBlur={createNewTag} />
|
||||
<input className="w-[100px] shrink-0 appearance-none rounded-lg border border-dashed border-divider-regular bg-transparent px-2 py-1 text-sm leading-5 text-text-secondary caret-primary-600 outline-hidden placeholder:text-text-quaternary focus:border-solid" placeholder={t('tag.addNew', { ns: 'common' }) || ''} autoFocus value={name} onChange={e => setName(e.target.value)} onKeyDown={e => e.key === 'Enter' && !e.nativeEvent.isComposing && createNewTag()} onBlur={createNewTag} />
|
||||
{tagList.map(tag => (<TagItemEditor key={tag.id} tag={tag} />))}
|
||||
</div>
|
||||
</Modal>
|
||||
|
||||
@ -124,7 +124,7 @@ const TagItemEditor: FC<TagItemEditorProps> = ({ tag }) => {
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
{isEditing && (<input className="shrink-0 appearance-none caret-primary-600 outline-none placeholder:text-text-quaternary" autoFocus value={name} onChange={e => setName(e.target.value)} onKeyDown={e => e.key === 'Enter' && editTag(tag.id, name)} onBlur={() => editTag(tag.id, name)} />)}
|
||||
{isEditing && (<input className="shrink-0 appearance-none caret-primary-600 outline-hidden placeholder:text-text-quaternary" autoFocus value={name} onChange={e => setName(e.target.value)} onKeyDown={e => e.key === 'Enter' && editTag(tag.id, name)} onBlur={() => editTag(tag.id, name)} />)}
|
||||
</div>
|
||||
<AlertDialog open={showRemoveModal} onOpenChange={open => !open && setShowRemoveModal(false)}>
|
||||
<AlertDialogContent>
|
||||
|
||||
@ -31,7 +31,7 @@ const COLOR_MAP = {
|
||||
export default function Tag({ children, color = 'green', className = '', bordered = false, hideBg = false }: ITagProps) {
|
||||
return (
|
||||
<div className={
|
||||
cn('inline-flex shrink-0 items-center rounded-md px-2.5 py-px text-xs leading-5', COLOR_MAP[color] ? `${COLOR_MAP[color].text} ${COLOR_MAP[color].bg}` : '', bordered ? 'border' : '', hideBg ? 'bg-transparent' : '', className)
|
||||
cn('inline-flex shrink-0 items-center rounded-md px-2.5 py-px text-xs leading-5', COLOR_MAP[color] ? `${COLOR_MAP[color].text} ${COLOR_MAP[color].bg}` : '', bordered ? 'border border-divider-regular' : '', hideBg ? 'bg-transparent' : '', className)
|
||||
}
|
||||
>
|
||||
{children}
|
||||
|
||||
@ -48,8 +48,8 @@ const HeaderBillingBtn: FC<Props> = ({
|
||||
<div
|
||||
onClick={handleClick}
|
||||
className={cn(
|
||||
'flex h-[22px] items-center rounded-md border border-divider-regular px-2 text-xs font-semibold uppercase',
|
||||
classNames,
|
||||
'flex h-[22px] items-center rounded-md border px-2 text-xs font-semibold uppercase',
|
||||
isDisplayOnly ? 'cursor-default' : 'cursor-pointer',
|
||||
)}
|
||||
>
|
||||
|
||||
@ -26,7 +26,7 @@
|
||||
@apply text-text-secondary text-sm;
|
||||
}
|
||||
.addFileBtn {
|
||||
@apply mt-4 w-fit !text-[13px] font-medium border-[0.5px];
|
||||
@apply mt-4 w-fit !text-[13px] font-medium border-[0.5px] border-components-button-secondary-border;
|
||||
}
|
||||
.plusIcon {
|
||||
@apply w-4 h-4 mr-2 stroke-current stroke-[1.5px];
|
||||
|
||||
@ -79,7 +79,7 @@ const ExternalApiSelect: React.FC<ExternalApiSelectProps> = ({ items, value, onS
|
||||
<RiArrowDownSLine className={`h-4 w-4 text-text-quaternary transition-transform ${isOpen ? 'text-text-secondary' : ''}`} />
|
||||
</div>
|
||||
{isOpen && (
|
||||
<div className="absolute z-10 mt-1 w-full rounded-xl border bg-components-panel-bg-blur shadow-lg">
|
||||
<div className="absolute z-10 mt-1 w-full rounded-xl border border-components-panel-border bg-components-panel-bg-blur shadow-lg">
|
||||
{items.map(item => (
|
||||
<div
|
||||
key={item.value}
|
||||
|
||||
@ -47,7 +47,7 @@ const InvitationLink = ({
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<div className="h-4 shrink-0 border bg-divider-regular" />
|
||||
<div className="h-4 shrink-0 border border-divider-regular bg-divider-regular" />
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
|
||||
@ -141,7 +141,7 @@ const NavSelector = ({ curNav, navigationItems, createText, isApp, onCreate, onL
|
||||
className="
|
||||
absolute right-0 -left-11 mt-1.5 w-60 max-w-80
|
||||
origin-top-right divide-y divide-divider-regular rounded-lg bg-components-panel-bg-blur
|
||||
shadow-lg outline-none
|
||||
shadow-lg outline-hidden
|
||||
"
|
||||
>
|
||||
<div className="overflow-auto px-1 py-1" style={{ maxHeight: '50vh' }} onScroll={handleScroll}>
|
||||
|
||||
@ -535,7 +535,7 @@ const MentionInputInner = forwardRef<HTMLTextAreaElement, MentionInputProps>(({
|
||||
<Textarea
|
||||
ref={textareaRef}
|
||||
className={cn(
|
||||
'relative z-10 w-full resize-none bg-transparent p-1 body-lg-regular leading-6 text-transparent caret-primary-500 outline-none',
|
||||
'relative z-10 w-full resize-none bg-transparent p-1 body-lg-regular leading-6 text-transparent caret-primary-500 outline-hidden',
|
||||
'placeholder:text-text-tertiary',
|
||||
)}
|
||||
style={{ paddingRight, paddingBottom }}
|
||||
|
||||
@ -1,15 +1,18 @@
|
||||
'use client'
|
||||
import type { EnvironmentVariable } from '@/app/components/workflow/types'
|
||||
import { Button } from '@langgenius/dify-ui/button'
|
||||
import {
|
||||
AlertDialog,
|
||||
AlertDialogActions,
|
||||
AlertDialogCancelButton,
|
||||
AlertDialogConfirmButton,
|
||||
AlertDialogContent,
|
||||
AlertDialogTitle,
|
||||
} from '@langgenius/dify-ui/alert-dialog'
|
||||
import { cn } from '@langgenius/dify-ui/cn'
|
||||
import { RiCloseLine, RiLock2Line } from '@remixicon/react'
|
||||
import { noop } from 'es-toolkit/function'
|
||||
import * as React from 'react'
|
||||
import { useCallback, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Checkbox from '@/app/components/base/checkbox'
|
||||
import { Env } from '@/app/components/base/icons/src/vender/line/others'
|
||||
import Modal from '@/app/components/base/modal'
|
||||
|
||||
export type DSLExportConfirmModalProps = {
|
||||
envList: EnvironmentVariable[]
|
||||
@ -17,11 +20,16 @@ export type DSLExportConfirmModalProps = {
|
||||
onClose: () => void
|
||||
}
|
||||
|
||||
const DSLExportConfirmModal = ({
|
||||
type DSLExportConfirmContentProps = DSLExportConfirmModalProps & {
|
||||
onExportingChange?: (isExporting: boolean) => void
|
||||
}
|
||||
|
||||
export const DSLExportConfirmContent = ({
|
||||
envList = [],
|
||||
onConfirm,
|
||||
onClose,
|
||||
}: DSLExportConfirmModalProps) => {
|
||||
onExportingChange,
|
||||
}: DSLExportConfirmContentProps) => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
const [exportSecrets, setExportSecrets] = useState<boolean>(false)
|
||||
@ -32,73 +40,75 @@ const DSLExportConfirmModal = ({
|
||||
return
|
||||
|
||||
setIsExporting(true)
|
||||
onExportingChange?.(true)
|
||||
try {
|
||||
await onConfirm(exportSecrets)
|
||||
onClose()
|
||||
}
|
||||
finally {
|
||||
setIsExporting(false)
|
||||
onExportingChange?.(false)
|
||||
}
|
||||
}, [exportSecrets, isExporting, onClose, onConfirm])
|
||||
}, [exportSecrets, isExporting, onClose, onConfirm, onExportingChange])
|
||||
|
||||
return (
|
||||
<Modal
|
||||
isShow={true}
|
||||
onClose={noop}
|
||||
className={cn('w-[480px] max-w-[480px]')}
|
||||
>
|
||||
<div className="relative pb-6 title-2xl-semi-bold text-text-primary">{t('env.export.title', { ns: 'workflow' })}</div>
|
||||
<div
|
||||
className={cn('absolute top-4 right-4 p-2', !isExporting && 'cursor-pointer')}
|
||||
onClick={() => !isExporting && onClose()}
|
||||
>
|
||||
<RiCloseLine className="h-4 w-4 text-text-tertiary" />
|
||||
</div>
|
||||
<div className="relative">
|
||||
<table className="w-full border-separate border-spacing-0 rounded-lg border border-divider-regular shadow-xs">
|
||||
<thead className="system-xs-medium-uppercase text-text-tertiary">
|
||||
<tr>
|
||||
<td width={220} className="h-7 border-r border-b border-divider-regular pl-3">{t('env.export.name', { ns: 'workflow' })}</td>
|
||||
<td className="h-7 border-b border-divider-regular pl-3">{t('env.export.value', { ns: 'workflow' })}</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{envList.map((env, index) => (
|
||||
<tr key={env.name}>
|
||||
<td className={cn('h-7 border-r pl-3 system-xs-medium', index + 1 !== envList.length && 'border-b')}>
|
||||
<div className="flex w-[200px] items-center gap-1">
|
||||
<Env className="h-4 w-4 shrink-0 text-util-colors-violet-violet-600" />
|
||||
<div className="truncate text-text-primary">{env.name}</div>
|
||||
<div className="shrink-0 text-text-tertiary">{t('env.export.secret', { ns: 'workflow' })}</div>
|
||||
<RiLock2Line className="h-3 w-3 shrink-0 text-text-tertiary" />
|
||||
</div>
|
||||
</td>
|
||||
<td className={cn('h-7 pl-3', index + 1 !== envList.length && 'border-b')}>
|
||||
<div className="truncate system-xs-regular text-text-secondary">{env.value}</div>
|
||||
</td>
|
||||
<AlertDialogContent className="w-120 max-w-120">
|
||||
<div className="px-6 pt-6">
|
||||
<AlertDialogTitle className="pb-6 title-2xl-semi-bold text-text-primary">
|
||||
{t('env.export.title', { ns: 'workflow' })}
|
||||
</AlertDialogTitle>
|
||||
<div className="relative">
|
||||
<table className="w-full border-separate border-spacing-0 rounded-lg border border-divider-regular shadow-xs">
|
||||
<thead className="system-xs-medium-uppercase text-text-tertiary">
|
||||
<tr>
|
||||
<td width={220} className="h-7 border-r border-b border-divider-regular pl-3">{t('env.export.name', { ns: 'workflow' })}</td>
|
||||
<td className="h-7 border-b border-divider-regular pl-3">{t('env.export.value', { ns: 'workflow' })}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div className="mt-4 flex gap-2">
|
||||
<Checkbox
|
||||
className="shrink-0"
|
||||
checked={exportSecrets}
|
||||
disabled={isExporting}
|
||||
onCheck={() => setExportSecrets(!exportSecrets)}
|
||||
/>
|
||||
<div
|
||||
className={cn('system-sm-medium text-text-primary', !isExporting && 'cursor-pointer')}
|
||||
onClick={() => !isExporting && setExportSecrets(!exportSecrets)}
|
||||
>
|
||||
{t('env.export.checkbox', { ns: 'workflow' })}
|
||||
</thead>
|
||||
<tbody>
|
||||
{envList.map((env, index) => (
|
||||
<tr key={env.name}>
|
||||
<td className={cn('h-7 border-r border-divider-regular pl-3 system-xs-medium', index + 1 !== envList.length && 'border-b border-divider-regular')}>
|
||||
<div className="flex w-50 items-center gap-1">
|
||||
<span aria-hidden="true" className="i-custom-vender-line-others-env h-4 w-4 shrink-0 text-util-colors-violet-violet-600" />
|
||||
<div className="truncate text-text-primary">{env.name}</div>
|
||||
<div className="shrink-0 text-text-tertiary">{t('env.export.secret', { ns: 'workflow' })}</div>
|
||||
<span aria-hidden="true" className="i-ri-lock-2-line h-3 w-3 shrink-0 text-text-tertiary" />
|
||||
</div>
|
||||
</td>
|
||||
<td className={cn('h-7 pl-3', index + 1 !== envList.length && 'border-b border-divider-regular')}>
|
||||
<div className="truncate system-xs-regular text-text-secondary">{env.value}</div>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div className="mt-4 flex gap-2">
|
||||
<Checkbox
|
||||
className="shrink-0"
|
||||
checked={exportSecrets}
|
||||
disabled={isExporting}
|
||||
onCheck={() => setExportSecrets(!exportSecrets)}
|
||||
ariaLabelledBy="dsl-export-secrets-checkbox-label"
|
||||
/>
|
||||
<button
|
||||
id="dsl-export-secrets-checkbox-label"
|
||||
type="button"
|
||||
disabled={isExporting}
|
||||
className="cursor-pointer rounded-sm text-left system-sm-medium text-text-primary outline-hidden focus-visible:ring-1 focus-visible:ring-components-input-border-hover disabled:cursor-not-allowed disabled:opacity-50"
|
||||
onClick={() => setExportSecrets(!exportSecrets)}
|
||||
>
|
||||
{t('env.export.checkbox', { ns: 'workflow' })}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-row-reverse pt-6">
|
||||
<Button
|
||||
className="ml-2"
|
||||
variant="primary"
|
||||
<AlertDialogActions>
|
||||
<AlertDialogCancelButton disabled={isExporting}>
|
||||
{t('operation.cancel', { ns: 'common' })}
|
||||
</AlertDialogCancelButton>
|
||||
<AlertDialogConfirmButton
|
||||
tone="default"
|
||||
loading={isExporting}
|
||||
disabled={isExporting}
|
||||
onClick={submit}
|
||||
@ -108,10 +118,28 @@ const DSLExportConfirmModal = ({
|
||||
: exportSecrets
|
||||
? t('env.export.export', { ns: 'workflow' })
|
||||
: t('env.export.ignore', { ns: 'workflow' })}
|
||||
</Button>
|
||||
<Button disabled={isExporting} onClick={onClose}>{t('operation.cancel', { ns: 'common' })}</Button>
|
||||
</div>
|
||||
</Modal>
|
||||
</AlertDialogConfirmButton>
|
||||
</AlertDialogActions>
|
||||
</AlertDialogContent>
|
||||
)
|
||||
}
|
||||
|
||||
const DSLExportConfirmModal = (props: DSLExportConfirmModalProps) => {
|
||||
const { envList, onClose } = props
|
||||
const [isExporting, setIsExporting] = useState(false)
|
||||
const isDialogOpen = envList.length > 0
|
||||
|
||||
const handleOpenChange = useCallback((open: boolean) => {
|
||||
if (open || isExporting)
|
||||
return
|
||||
|
||||
onClose()
|
||||
}, [isExporting, onClose])
|
||||
|
||||
return (
|
||||
<AlertDialog open={isDialogOpen} onOpenChange={handleOpenChange}>
|
||||
<DSLExportConfirmContent {...props} onExportingChange={setIsExporting} />
|
||||
</AlertDialog>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@ -43,7 +43,7 @@ const Field: FC<Props> = ({
|
||||
disabled={depth !== MAX_DEPTH + 1}
|
||||
render={(
|
||||
<div
|
||||
className={cn('flex items-center justify-between rounded-md pr-2 outline-none focus:outline-none focus-visible:outline-none', !readonly && 'hover:bg-state-base-hover', depth !== MAX_DEPTH + 1 && 'cursor-pointer')}
|
||||
className={cn('flex items-center justify-between rounded-md pr-2 outline-hidden focus:outline-hidden focus-visible:outline-hidden', !readonly && 'hover:bg-state-base-hover', depth !== MAX_DEPTH + 1 && 'cursor-pointer')}
|
||||
onMouseDown={() => !readonly && onSelect?.([...valueSelector, name])}
|
||||
>
|
||||
<div className="flex grow items-stretch">
|
||||
|
||||
@ -211,7 +211,7 @@ const Item: FC<ItemProps> = ({
|
||||
className={cn(
|
||||
(isObj || isStructureOutput) ? 'pr-1' : 'pr-[18px]',
|
||||
(isHovering || isSelected) && ((isObj || isStructureOutput) ? 'bg-components-panel-on-panel-item-bg-hover' : 'bg-state-base-hover'),
|
||||
'relative flex h-6 w-full cursor-pointer items-center rounded-md pl-3 outline-none focus:outline-none focus-visible:outline-none',
|
||||
'relative flex h-6 w-full cursor-pointer items-center rounded-md pl-3 outline-hidden focus:outline-hidden focus-visible:outline-hidden',
|
||||
className,
|
||||
)}
|
||||
data-selected={isSelected ? 'true' : 'false'}
|
||||
|
||||
@ -26,17 +26,20 @@ const AddDataset: FC<Props> = ({
|
||||
}, [onChange, hideModal])
|
||||
return (
|
||||
<div>
|
||||
<div className="cursor-pointer rounded-md p-1 select-none hover:bg-state-base-hover" onClick={showModal} data-testid="add-button">
|
||||
<span className="i-ri-add-line h-4 w-4 text-text-tertiary" />
|
||||
</div>
|
||||
{isShowModal && (
|
||||
<SelectDataset
|
||||
isShow={isShowModal}
|
||||
onClose={hideModal}
|
||||
selectedIds={selectedIds}
|
||||
onSelect={handleSelect}
|
||||
/>
|
||||
)}
|
||||
<button
|
||||
type="button"
|
||||
className="cursor-pointer rounded-md p-1 outline-hidden select-none hover:bg-state-base-hover focus-visible:ring-2 focus-visible:ring-state-accent-solid"
|
||||
onClick={showModal}
|
||||
data-testid="add-button"
|
||||
>
|
||||
<span aria-hidden="true" className="i-ri-add-line h-4 w-4 text-text-tertiary" />
|
||||
</button>
|
||||
<SelectDataset
|
||||
isShow={isShowModal}
|
||||
onClose={hideModal}
|
||||
selectedIds={selectedIds}
|
||||
onSelect={handleSelect}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@ -18,7 +18,7 @@ const StatusContainer: FC<Props> = ({
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
'relative rounded-lg border px-3 py-2.5 system-xs-regular break-all',
|
||||
'relative rounded-lg border border-workflow-display-disabled-border-1 px-3 py-2.5 system-xs-regular break-all',
|
||||
status === 'succeeded' && 'border-[rgba(23,178,106,0.8)] bg-workflow-display-success-bg bg-[url(~@/app/components/workflow/run/assets/bg-line-success.svg)] text-text-success',
|
||||
status === 'succeeded' && theme === Theme.light && 'shadow-[inset_2px_2px_0_0_rgba(255,255,255,0.5),inset_0_1px_3px_0_rgba(0,0,0,0.12),inset_0_2px_24px_0_rgba(23,178,106,0.2),0_1px_2px_0_rgba(9,9,11,0.05),0_0_0_1px_rgba(0,0,0,0.05)]',
|
||||
status === 'succeeded' && theme === Theme.dark && 'shadow-[inset_2px_2px_0_0_rgba(255,255,255,0.12),inset_0_1px_3px_0_rgba(0,0,0,0.4),inset_0_2px_24px_0_rgba(23,178,106,0.25),0_1px_2px_0_rgba(0,0,0,0.1),0_0_0_1px_rgba(24,24,27,0.95)]',
|
||||
|
||||
@ -12,7 +12,7 @@
|
||||
@import 'tailwindcss/theme.css' layer(theme);
|
||||
@import 'tailwindcss/utilities.css' layer(utilities);
|
||||
|
||||
/* Local preflight (replaces v3 `corePlugins.preflight: false`). */
|
||||
/* Local preflight keeps the browser baseline controlled across app entries. */
|
||||
@import './preflight.css' layer(base);
|
||||
|
||||
/* Design system: palette overrides, semantic tokens, light/dark themes,
|
||||
@ -98,19 +98,6 @@
|
||||
--background-image-chat-answer-human-input-form-divider-bg: var(--color-chat-answer-human-input-form-divider-bg);
|
||||
}
|
||||
|
||||
/* ---------- Backwards-compat: gray-200 default border color ----------- *
|
||||
* v4 changed the default border color to `currentColor`. Preserve the v3
|
||||
* baseline used throughout the codebase. */
|
||||
@layer base {
|
||||
*,
|
||||
::after,
|
||||
::before,
|
||||
::backdrop,
|
||||
::file-selector-button {
|
||||
border-color: var(--color-gray-200, currentcolor);
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------- App-level component CSS ----------------------------------- */
|
||||
@layer components {
|
||||
[class*='code-'] {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user