feat: dark mode for knowledge (#15236)

This commit is contained in:
Wu Tianwei 2025-03-19 11:19:57 +08:00 committed by GitHub
parent 97eadb867c
commit 411e332f1b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
72 changed files with 473 additions and 761 deletions

View File

@ -15,7 +15,7 @@ import {
// CommandLineIcon as CommandLineSolidIcon, // CommandLineIcon as CommandLineSolidIcon,
DocumentTextIcon as DocumentTextSolidIcon, DocumentTextIcon as DocumentTextSolidIcon,
} from '@heroicons/react/24/solid' } from '@heroicons/react/24/solid'
import { RiApps2AddLine, RiInformation2Line } from '@remixicon/react' import { RiApps2AddLine, RiBookOpenLine, RiInformation2Line } from '@remixicon/react'
import s from './style.module.css' import s from './style.module.css'
import classNames from '@/utils/classnames' import classNames from '@/utils/classnames'
import { fetchDatasetDetail, fetchDatasetRelatedApps } from '@/service/datasets' import { fetchDatasetDetail, fetchDatasetRelatedApps } from '@/service/datasets'
@ -58,13 +58,6 @@ const TargetSolidIcon = ({ className }: SVGProps<SVGElement>) => {
</svg> </svg>
} }
const BookOpenIcon = ({ className }: SVGProps<SVGElement>) => {
return <svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg" className={className ?? ''}>
<path opacity="0.12" d="M1 3.1C1 2.53995 1 2.25992 1.10899 2.04601C1.20487 1.85785 1.35785 1.70487 1.54601 1.60899C1.75992 1.5 2.03995 1.5 2.6 1.5H2.8C3.9201 1.5 4.48016 1.5 4.90798 1.71799C5.28431 1.90973 5.59027 2.21569 5.78201 2.59202C6 3.01984 6 3.5799 6 4.7V10.5L5.94997 10.425C5.60265 9.90398 5.42899 9.64349 5.19955 9.45491C4.99643 9.28796 4.76238 9.1627 4.5108 9.0863C4.22663 9 3.91355 9 3.28741 9H2.6C2.03995 9 1.75992 9 1.54601 8.89101C1.35785 8.79513 1.20487 8.64215 1.10899 8.45399C1 8.24008 1 7.96005 1 7.4V3.1Z" fill="#155EEF" />
<path d="M6 10.5L5.94997 10.425C5.60265 9.90398 5.42899 9.64349 5.19955 9.45491C4.99643 9.28796 4.76238 9.1627 4.5108 9.0863C4.22663 9 3.91355 9 3.28741 9H2.6C2.03995 9 1.75992 9 1.54601 8.89101C1.35785 8.79513 1.20487 8.64215 1.10899 8.45399C1 8.24008 1 7.96005 1 7.4V3.1C1 2.53995 1 2.25992 1.10899 2.04601C1.20487 1.85785 1.35785 1.70487 1.54601 1.60899C1.75992 1.5 2.03995 1.5 2.6 1.5H2.8C3.9201 1.5 4.48016 1.5 4.90798 1.71799C5.28431 1.90973 5.59027 2.21569 5.78201 2.59202C6 3.01984 6 3.5799 6 4.7M6 10.5V4.7M6 10.5L6.05003 10.425C6.39735 9.90398 6.57101 9.64349 6.80045 9.45491C7.00357 9.28796 7.23762 9.1627 7.4892 9.0863C7.77337 9 8.08645 9 8.71259 9H9.4C9.96005 9 10.2401 9 10.454 8.89101C10.6422 8.79513 10.7951 8.64215 10.891 8.45399C11 8.24008 11 7.96005 11 7.4V3.1C11 2.53995 11 2.25992 10.891 2.04601C10.7951 1.85785 10.6422 1.70487 10.454 1.60899C10.2401 1.5 9.96005 1.5 9.4 1.5H9.2C8.07989 1.5 7.51984 1.5 7.09202 1.71799C6.71569 1.90973 6.40973 2.21569 6.21799 2.59202C6 3.01984 6 3.5799 6 4.7" stroke="#155EEF" strokeLinecap="round" strokeLinejoin="round" />
</svg>
}
type IExtraInfoProps = { type IExtraInfoProps = {
isMobile: boolean isMobile: boolean
relatedApps?: RelatedAppResponse relatedApps?: RelatedAppResponse
@ -131,7 +124,7 @@ const ExtraInfo = ({ isMobile, relatedApps, expand }: IExtraInfoProps) => {
} }
target='_blank' rel='noopener noreferrer' target='_blank' rel='noopener noreferrer'
> >
<BookOpenIcon className='mr-1' /> <RiBookOpenLine className='mr-1 text-text-accent' />
{t('common.datasetMenus.viewDoc')} {t('common.datasetMenus.viewDoc')}
</a> </a>
</div> </div>

View File

@ -44,7 +44,7 @@ export default function NavLink({
key={name} key={name}
href={href} href={href}
className={classNames( className={classNames(
isActive ? 'bg-state-accent-active text-text-accent font-semibold' : 'text-components-menu-item-text hover:bg-gray-100 hover:text-components-menu-item-text-hover', isActive ? 'bg-state-accent-active text-text-accent font-semibold' : 'text-components-menu-item-text hover:bg-state-base-hover hover:text-components-menu-item-text-hover',
'group flex items-center h-9 rounded-md py-2 text-sm font-normal', 'group flex items-center h-9 rounded-md py-2 text-sm font-normal',
mode === 'expand' ? 'px-3' : 'px-2.5', mode === 'expand' ? 'px-3' : 'px-2.5',
)} )}

View File

@ -34,10 +34,11 @@ export type ButtonProps = {
destructive?: boolean destructive?: boolean
loading?: boolean loading?: boolean
styleCss?: CSSProperties styleCss?: CSSProperties
spinnerClassName?: string
} & React.ButtonHTMLAttributes<HTMLButtonElement> & VariantProps<typeof buttonVariants> } & React.ButtonHTMLAttributes<HTMLButtonElement> & VariantProps<typeof buttonVariants>
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>( const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
({ className, variant, size, destructive, loading, styleCss, children, ...props }, ref) => { ({ className, variant, size, destructive, loading, styleCss, children, spinnerClassName, ...props }, ref) => {
return ( return (
<button <button
type='button' type='button'
@ -50,7 +51,7 @@ const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
{...props} {...props}
> >
{children} {children}
{loading && <Spinner loading={loading} className='!text-white !h-3 !w-3 !border-2 !ml-1' />} {loading && <Spinner loading={loading} className={classNames('!text-white !h-3 !w-3 !border-2 !ml-1', spinnerClassName)} />}
</button> </button>
) )
}, },

View File

@ -20,7 +20,7 @@
"width": "16", "width": "16",
"height": "16", "height": "16",
"rx": "5", "rx": "5",
"fill": "#F2F4F7" "fill": "currentColor"
}, },
"children": [] "children": []
}, },
@ -33,7 +33,7 @@
"width": "233", "width": "233",
"height": "10", "height": "10",
"rx": "3", "rx": "3",
"fill": "#EAECF0" "fill": "currentColor"
}, },
"children": [] "children": []
}, },
@ -46,7 +46,7 @@
"width": "345", "width": "345",
"height": "6", "height": "6",
"rx": "3", "rx": "3",
"fill": "#F2F4F7" "fill": "currentColor"
}, },
"children": [] "children": []
} }

View File

@ -1,4 +0,0 @@
.setting-icon {
background: url(./assets/setting.svg) center center no-repeat;
background-size: 14px 14px;
}

View File

@ -1,10 +1,9 @@
import { useCallback, useEffect, useMemo, useState } from 'react' import { useCallback, useEffect, useMemo, useState } from 'react'
import useSWR from 'swr' import useSWR from 'swr'
import s from './base.module.css' import { RiEqualizer2Line } from '@remixicon/react'
import WorkspaceSelector from './workspace-selector' import WorkspaceSelector from './workspace-selector'
import SearchInput from './search-input' import SearchInput from './search-input'
import PageSelector from './page-selector' import PageSelector from './page-selector'
import cn from '@/utils/classnames'
import { preImportNotionPages } from '@/service/datasets' import { preImportNotionPages } from '@/service/datasets'
import { NotionConnector } from '@/app/components/datasets/create/step-one' import { NotionConnector } from '@/app/components/datasets/create/step-one'
import type { DataSourceNotionPageMap, DataSourceNotionWorkspace, NotionPage } from '@/models/common' import type { DataSourceNotionPageMap, DataSourceNotionWorkspace, NotionPage } from '@/models/common'
@ -88,23 +87,24 @@ const NotionPageSelector = ({
}, [firstWorkspaceId]) }, [firstWorkspaceId])
return ( return (
<div className='bg-gray-25 border border-gray-200 rounded-xl'> <div className='bg-background-default-subtle border border-components-panel-border rounded-xl'>
{ {
data?.notion_info?.length data?.notion_info?.length
? ( ? (
<> <>
<div className='flex items-center pl-[10px] pr-2 h-11 bg-white border-b border-b-gray-200 rounded-t-xl'> <div className='flex items-center gap-x-2 p-2 h-12 bg-components-panel-bg border-b border-b-divider-regular rounded-t-xl'>
<div className='grow flex items-center gap-x-1'>
<WorkspaceSelector <WorkspaceSelector
value={currentWorkspaceId || firstWorkspaceId} value={currentWorkspaceId || firstWorkspaceId}
items={notionWorkspaces} items={notionWorkspaces}
onSelect={handleSelectWorkspace} onSelect={handleSelectWorkspace}
/> />
<div className='mx-1 w-[1px] h-3 bg-gray-200' /> <div className='mx-1 w-[1px] h-3 bg-divider-regular' />
<div <RiEqualizer2Line
className={cn(s['setting-icon'], 'w-6 h-6 cursor-pointer')} className='w-4 h-4 cursor-pointer text-text-tertiary'
onClick={() => setShowAccountSettingModal({ payload: 'data-source', onCancelCallback: mutate })} onClick={() => setShowAccountSettingModal({ payload: 'data-source', onCancelCallback: mutate })}
/> />
<div className='grow' /> </div>
<SearchInput <SearchInput
value={searchValue} value={searchValue}
onChange={handleSearchValueChange} onChange={handleSearchValueChange}

View File

@ -1,17 +0,0 @@
.arrow {
width: 20px;
height: 20px;
background: url(../assets/down-arrow.svg) center center no-repeat;
background-size: 16px 16px;
transform: rotate(-90deg);
}
.arrow-expand {
transform: rotate(0);
}
.preview-item {
background-color: #eff4ff;
border: 1px solid #D1E0FF;
box-shadow: 0px 1px 2px rgba(16, 24, 40, 0.05);
}

View File

@ -2,9 +2,9 @@ import { memo, useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { FixedSizeList as List, areEqual } from 'react-window' import { FixedSizeList as List, areEqual } from 'react-window'
import type { ListChildComponentProps } from 'react-window' import type { ListChildComponentProps } from 'react-window'
import { RiArrowDownSLine, RiArrowRightSLine } from '@remixicon/react'
import Checkbox from '../../checkbox' import Checkbox from '../../checkbox'
import NotionIcon from '../../notion-icon' import NotionIcon from '../../notion-icon'
import s from './index.module.css'
import cn from '@/utils/classnames' import cn from '@/utils/classnames'
import type { DataSourceNotionPage, DataSourceNotionPageMap } from '@/models/common' import type { DataSourceNotionPage, DataSourceNotionPageMap } from '@/models/common'
@ -94,10 +94,16 @@ const ItemComponent = ({ index, style, data }: ListChildComponentProps<{
if (hasChild) { if (hasChild) {
return ( return (
<div <div
className={cn(s.arrow, current.expand && s['arrow-expand'], 'shrink-0 mr-1 w-5 h-5 hover:bg-gray-200 rounded-md')} className='flex items-center justify-center shrink-0 mr-1 w-5 h-5 hover:bg-components-button-ghost-bg-hover rounded-md'
style={{ marginLeft: current.depth * 8 }} style={{ marginLeft: current.depth * 8 }}
onClick={() => handleToggle(index)} onClick={() => handleToggle(index)}
/> >
{
current.expand
? <RiArrowDownSLine className='w-4 h-4 text-text-tertiary' />
: <RiArrowRightSLine className='w-4 h-4 text-text-tertiary' />
}
</div>
) )
} }
if (current.parent_id === 'root' || !pagesMap[current.parent_id]) { if (current.parent_id === 'root' || !pagesMap[current.parent_id]) {
@ -112,14 +118,12 @@ const ItemComponent = ({ index, style, data }: ListChildComponentProps<{
return ( return (
<div <div
className={cn('group flex items-center pl-2 pr-[2px] rounded-md border border-transparent hover:bg-gray-100 cursor-pointer', previewPageId === current.page_id && s['preview-item'])} className={cn('group flex items-center pl-2 pr-[2px] rounded-md hover:bg-state-base-hover cursor-pointer',
previewPageId === current.page_id && 'bg-state-base-hover')}
style={{ ...style, top: style.top as number + 8, left: 8, right: 8, width: 'calc(100% - 16px)' }} style={{ ...style, top: style.top as number + 8, left: 8, right: 8, width: 'calc(100% - 16px)' }}
> >
<Checkbox <Checkbox
className={cn( className='shrink-0 mr-2'
'shrink-0 mr-2 group-hover:border-primary-600 group-hover:border-[2px]',
disabled && 'group-hover:border-transparent',
)}
checked={checkedIds.has(current.page_id)} checked={checkedIds.has(current.page_id)}
disabled={disabled} disabled={disabled}
onCheck={() => { onCheck={() => {
@ -135,7 +139,7 @@ const ItemComponent = ({ index, style, data }: ListChildComponentProps<{
src={current.page_icon} src={current.page_icon}
/> />
<div <div
className='grow text-sm font-medium text-gray-700 truncate' className='grow text-[13px] leading-4 font-medium text-text-secondary truncate'
title={current.page_name} title={current.page_name}
> >
{current.page_name} {current.page_name}
@ -143,7 +147,9 @@ const ItemComponent = ({ index, style, data }: ListChildComponentProps<{
{ {
canPreview && ( canPreview && (
<div <div
className='shrink-0 hidden group-hover:flex items-center ml-1 px-2 h-6 rounded-md text-xs font-medium text-gray-500 cursor-pointer hover:bg-gray-50 hover:text-gray-700' className='shrink-0 hidden group-hover:flex items-center ml-1 px-2 h-6 rounded-md text-xs leading-4 font-medium text-components-button-secondary-text
cursor-pointer bg-components-button-secondary-bg border-[0.5px] border-components-button-secondary-border shadow-xs shadow-shadow-shadow-3
backdrop-blur-[10px] hover:bg-components-button-secondary-bg-hover hover:border-components-button-secondary-border-hover'
onClick={() => handlePreview(index)}> onClick={() => handlePreview(index)}>
{t('common.dataSource.notion.selector.preview')} {t('common.dataSource.notion.selector.preview')}
</div> </div>
@ -152,7 +158,7 @@ const ItemComponent = ({ index, style, data }: ListChildComponentProps<{
{ {
searchValue && ( searchValue && (
<div <div
className='shrink-0 ml-1 max-w-[120px] text-xs text-gray-400 truncate' className='shrink-0 ml-1 max-w-[120px] text-xs text-text-quaternary truncate'
title={breadCrumbs.join(' / ')} title={breadCrumbs.join(' / ')}
> >
{breadCrumbs.join(' / ')} {breadCrumbs.join(' / ')}
@ -278,7 +284,7 @@ const PageSelector = ({
if (!currentDataList.length) { if (!currentDataList.length) {
return ( return (
<div className='flex items-center justify-center h-[296px] text-[13px] text-gray-500'> <div className='flex items-center justify-center h-[296px] text-[13px] text-text-tertiary'>
{t('common.dataSource.notion.selector.noSearchResult')} {t('common.dataSource.notion.selector.noSearchResult')}
</div> </div>
) )

View File

@ -1,15 +0,0 @@
.search-icon {
background: url(../assets/search.svg) center center;
background-size: 14px 14px;
}
.clear-icon {
background: url(../assets/clear.svg) center center;
background-size: contain;
}
.input-wrapper {
flex-basis: 200px;
width: 0;
box-shadow: 0px 1px 2px rgba(16, 24, 40, 0.05);
}

View File

@ -1,7 +1,7 @@
import { useCallback } from 'react' import { useCallback } from 'react'
import type { ChangeEvent } from 'react' import type { ChangeEvent } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import s from './index.module.css' import { RiCloseCircleFill, RiSearchLine } from '@remixicon/react'
import cn from '@/utils/classnames' import cn from '@/utils/classnames'
type SearchInputProps = { type SearchInputProps = {
@ -19,18 +19,18 @@ const SearchInput = ({
}, [onChange]) }, [onChange])
return ( return (
<div className={cn(s['input-wrapper'], 'flex items-center px-2 h-7 rounded-md', `${value ? 'bg-white' : 'bg-gray-100'}`)}> <div className={cn('w-[200px] flex items-center p-2 h-8 rounded-lg bg-components-input-bg-normal')}>
<div className={cn(s['search-icon'], 'mr-[6px] w-4 h-4')} /> <RiSearchLine className={'w-4 h-4 mr-0.5 shrink-0 text-components-input-text-placeholder'} />
<input <input
className='grow text-[13px] bg-inherit border-0 outline-0 appearance-none' className='min-w-0 grow px-1 text-[13px] leading-[16px] bg-transparent text-components-input-text-filled placeholder:text-components-input-text-placeholder border-0 outline-0 appearance-none'
value={value} value={value}
onChange={(e: ChangeEvent<HTMLInputElement>) => onChange(e.target.value)} onChange={(e: ChangeEvent<HTMLInputElement>) => onChange(e.target.value)}
placeholder={t('common.dataSource.notion.selector.searchPages') || ''} placeholder={t('common.dataSource.notion.selector.searchPages') || ''}
/> />
{ {
value && ( value && (
<div <RiCloseCircleFill
className={cn(s['clear-icon'], 'ml-1 w-4 h-4 cursor-pointer')} className={'w-4 h-4 shrink-0 cursor-pointer text-components-input-text-placeholder'}
onClick={handleClear} onClick={handleClear}
/> />
) )

View File

@ -1,9 +0,0 @@
.down-arrow {
background: url(../assets/down-arrow.svg) center center no-repeat;
background-size: cover;
}
.popup {
box-shadow: 0px 12px 16px -4px rgba(16, 24, 40, 0.08), 0px 4px 6px -2px rgba(16, 24, 40, 0.03);
z-index: 10;
}

View File

@ -2,9 +2,8 @@
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { Fragment } from 'react' import { Fragment } from 'react'
import { Menu, Transition } from '@headlessui/react' import { Menu, Transition } from '@headlessui/react'
import { RiArrowDownSLine } from '@remixicon/react'
import NotionIcon from '../../notion-icon' import NotionIcon from '../../notion-icon'
import s from './index.module.css'
import cn from '@/utils/classnames'
import type { DataSourceNotionWorkspace } from '@/models/common' import type { DataSourceNotionWorkspace } from '@/models/common'
type WorkspaceSelectorProps = { type WorkspaceSelectorProps = {
@ -25,15 +24,15 @@ export default function WorkspaceSelector({
{ {
({ open }) => ( ({ open }) => (
<> <>
<Menu.Button className={`flex items-center justify-center h-7 rounded-md hover:bg-gray-50 ${open && 'bg-gray-50'} cursor-pointer`}> <Menu.Button className={`flex items-center justify-center h-7 p-1 pr-2 rounded-md hover:bg-state-base-hover ${open && 'bg-state-base-hover'} cursor-pointer`}>
<NotionIcon <NotionIcon
className='ml-1 mr-2' className='mr-2'
src={currentWorkspace?.workspace_icon} src={currentWorkspace?.workspace_icon}
name={currentWorkspace?.workspace_name} name={currentWorkspace?.workspace_name}
/> />
<div className='mr-1 w-[90px] text-left text-sm font-medium text-gray-700 truncate' title={currentWorkspace?.workspace_name}>{currentWorkspace?.workspace_name}</div> <div className='mr-1 w-[90px] text-left text-sm font-medium text-text-secondary truncate' title={currentWorkspace?.workspace_name}>{currentWorkspace?.workspace_name}</div>
<div className='mr-1 px-1 h-[18px] bg-primary-50 rounded-lg text-xs font-medium text-primary-600'>{currentWorkspace?.pages.length}</div> {/* <div className='mr-1 px-1 h-[18px] bg-primary-50 rounded-lg text-xs font-medium text-text-accent'>{currentWorkspace?.pages.length}</div> */}
<div className={cn(s['down-arrow'], 'mr-2 w-3 h-3')} /> <RiArrowDownSLine className='w-4 h-4 text-text-secondary' />
</Menu.Button> </Menu.Button>
<Transition <Transition
as={Fragment} as={Fragment}
@ -45,19 +44,16 @@ export default function WorkspaceSelector({
leaveTo="transform opacity-0 scale-95" leaveTo="transform opacity-0 scale-95"
> >
<Menu.Items <Menu.Items
className={cn( className='absolute left-0 top-8 z-10 w-80
s.popup, origin-top-right rounded-lg bg-components-panel-bg-blur
`absolute left-0 top-8 w-80 border-[0.5px] border-components-panel-border shadow-lg shadow-shadow-shadow-5 backdrop-blur-[5px]'
origin-top-right rounded-lg bg-white
border-[0.5px] border-gray-200`,
)}
> >
<div className="p-1 max-h-50 overflow-auto"> <div className="p-1 max-h-50 overflow-auto">
{ {
items.map(item => ( items.map(item => (
<Menu.Item key={item.workspace_id}> <Menu.Item key={item.workspace_id}>
<div <div
className='flex items-center px-3 h-9 hover:bg-gray-50 cursor-pointer' className='flex items-center px-3 h-9 rounded-lg hover:bg-state-base-hover cursor-pointer'
onClick={() => onSelect(item.workspace_id)} onClick={() => onSelect(item.workspace_id)}
> >
<NotionIcon <NotionIcon
@ -65,8 +61,8 @@ export default function WorkspaceSelector({
src={item.workspace_icon} src={item.workspace_icon}
name={item.workspace_name} name={item.workspace_name}
/> />
<div className='grow mr-2 text-sm text-gray-700 truncate' title={item.workspace_name}>{item.workspace_name}</div> <div className='grow mr-2 system-sm-medium text-text-secondary truncate' title={item.workspace_name}>{item.workspace_name}</div>
<div className='shrink-0 text-xs font-medium text-primary-600'> <div className='shrink-0 system-xs-medium text-text-accent'>
{item.pages.length} {t('common.dataSource.notion.selector.pageSelected')} {item.pages.length} {t('common.dataSource.notion.selector.pageSelected')}
</div> </div>
</div> </div>

View File

@ -1,9 +1,8 @@
import type { FC } from 'react' import type { FC } from 'react'
import { useRef, useState } from 'react' import { useRef, useState } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { RiSearchLine } from '@remixicon/react' import { RiCloseCircleFill, RiSearchLine } from '@remixicon/react'
import cn from '@/utils/classnames' import cn from '@/utils/classnames'
import { XCircle } from '@/app/components/base/icons/src/vender/solid/general'
type SearchInputProps = { type SearchInputProps = {
placeholder?: string placeholder?: string
@ -27,22 +26,19 @@ const SearchInput: FC<SearchInputProps> = ({
return ( return (
<div className={cn( <div className={cn(
'group flex items-center px-2 h-8 rounded-lg bg-gray-200 hover:bg-gray-300 border border-transparent overflow-hidden', 'group flex items-center px-2 h-8 rounded-lg bg-components-input-bg-normal hover:bg-components-input-bg-hover border-none overflow-hidden',
focus && '!bg-white hover:bg-white shadow-xs !border-gray-300', focus && '!bg-components-input-bg-active',
!focus && value && 'hover:!bg-gray-200 hover:!shadow-xs hover:!border-black/5',
white && '!bg-white hover:!bg-white shadow-xs !border-gray-300 hover:!border-gray-300', white && '!bg-white hover:!bg-white shadow-xs !border-gray-300 hover:!border-gray-300',
className, className,
)}> )}>
<div className="pointer-events-none shrink-0 flex items-center mr-1.5 justify-center w-4 h-4"> <div className="pointer-events-none shrink-0 flex items-center mr-1.5 justify-center w-4 h-4">
<RiSearchLine className="h-3.5 w-3.5 text-gray-500" aria-hidden="true" /> <RiSearchLine className="h-4 w-4 text-components-input-text-placeholder" aria-hidden="true" />
</div> </div>
<input <input
type="text" type="text"
name="query" name="query"
className={cn( className={cn(
'grow block h-[18px] bg-gray-200 border-0 text-gray-700 text-[13px] placeholder:text-gray-500 appearance-none outline-none group-hover:bg-gray-300 caret-blue-600', 'grow block h-[18px] bg-transparent border-0 text-components-input-text-filled system-sm-regular placeholder:text-components-input-text-placeholder appearance-none outline-none caret-#295EFF',
focus && '!bg-white hover:bg-white group-hover:bg-white placeholder:!text-gray-400',
!focus && value && 'hover:!bg-gray-200 group-hover:!bg-gray-200',
white && '!bg-white hover:!bg-white group-hover:!bg-white placeholder:!text-gray-400', white && '!bg-white hover:!bg-white group-hover:!bg-white placeholder:!text-gray-400',
)} )}
placeholder={placeholder || t('common.operation.search')!} placeholder={placeholder || t('common.operation.search')!}
@ -71,7 +67,7 @@ const SearchInput: FC<SearchInputProps> = ({
setInternalValue('') setInternalValue('')
}} }}
> >
<XCircle className='w-3.5 h-3.5 text-gray-400 group-hover/clear:text-gray-600' /> <RiCloseCircleFill className='w-4 h-4 text-text-quaternary group-hover/clear:text-text-tertiary' />
</div> </div>
)} )}
</div> </div>

View File

@ -234,8 +234,8 @@ const TagSelector: FC<TagSelectorProps> = ({
<div className={cn( <div className={cn(
'group/tip relative w-full flex items-center gap-1 px-2 py-[7px] rounded-md cursor-pointer hover:bg-state-base-hover', 'group/tip relative w-full flex items-center gap-1 px-2 py-[7px] rounded-md cursor-pointer hover:bg-state-base-hover',
)}> )}>
<Tag01 className='shrink-0 w-3 h-3' /> <Tag01 className='shrink-0 w-3 h-3 text-components-input-text-placeholder' />
<div className='grow text-xs text-start leading-[18px] font-normal truncate'> <div className='grow text-start system-sm-regular text-components-input-text-placeholder truncate'>
{!triggerContent ? t('common.tag.addTag') : triggerContent} {!triggerContent ? t('common.tag.addTag') : triggerContent}
</div> </div>
</div> </div>

View File

@ -78,7 +78,7 @@ const DocumentPicker: FC<Props> = ({
<FileIcon name={name} extension={extension} size='lg' /> <FileIcon name={name} extension={extension} size='lg' />
<div className='flex flex-col items-start ml-1 mr-0.5'> <div className='flex flex-col items-start ml-1 mr-0.5'>
<div className='flex items-center space-x-0.5'> <div className='flex items-center space-x-0.5'>
<span className={cn('system-md-semibold')}> {name || '--'}</span> <span className={cn('system-md-semibold text-text-primary')}> {name || '--'}</span>
<ArrowIcon className={'h-4 w-4 text-text-primary'} /> <ArrowIcon className={'h-4 w-4 text-text-primary'} />
</div> </div>
<div className='flex items-center h-3 text-text-tertiary space-x-0.5'> <div className='flex items-center h-3 text-text-tertiary space-x-0.5'>

View File

@ -253,9 +253,9 @@ const EmbeddingProcess: FC<Props> = ({ datasetId, batchId, documents = [], index
return ( return (
<> <>
<div className="h-5 flex items-center mb-3"> <div className="h-5 flex items-center mb-3">
<div className="flex items-center justify-between text-gray-900 font-medium text-sm mr-2"> <div className="flex items-center justify-between text-text-secondary font-medium text-sm mr-2">
{isEmbedding && <div className='flex items-center'> {isEmbedding && <div className='flex items-center'>
<RiLoader2Fill className='size-4 mr-1 animate-spin' /> <RiLoader2Fill className='size-4 mr-1 animate-spin text-text-secondary' />
{t('datasetDocuments.embedding.processing')} {t('datasetDocuments.embedding.processing')}
</div>} </div>}
{isEmbeddingCompleted && t('datasetDocuments.embedding.completed')} {isEmbeddingCompleted && t('datasetDocuments.embedding.completed')}
@ -304,7 +304,7 @@ const EmbeddingProcess: FC<Props> = ({ datasetId, batchId, documents = [], index
/> />
)} )}
<div className="grow flex items-center gap-1 w-0" title={getSourceName(indexingStatusDetail.id)}> <div className="grow flex items-center gap-1 w-0" title={getSourceName(indexingStatusDetail.id)}>
<div className="text-xs truncate"> <div className="system-xs-medium text-text-secondary truncate">
{getSourceName(indexingStatusDetail.id)} {getSourceName(indexingStatusDetail.id)}
</div> </div>
{ {
@ -314,7 +314,7 @@ const EmbeddingProcess: FC<Props> = ({ datasetId, batchId, documents = [], index
} }
</div> </div>
{isSourceEmbedding(indexingStatusDetail) && ( {isSourceEmbedding(indexingStatusDetail) && (
<div className="shrink-0 text-xs">{`${getSourcePercent(indexingStatusDetail)}%`}</div> <div className="shrink-0 text-xs text-text-secondary">{`${getSourcePercent(indexingStatusDetail)}%`}</div>
)} )}
{indexingStatusDetail.indexing_status === 'error' && ( {indexingStatusDetail.indexing_status === 'error' && (
<Tooltip <Tooltip

View File

@ -6,11 +6,10 @@
@apply flex items-center place-content-between h-8; @apply flex items-center place-content-between h-8;
} }
.modalHeader .title { .modalHeader .title {
@apply grow; @apply grow text-text-primary;
font-weight: 600; font-weight: 600;
font-size: 20px; font-size: 20px;
line-height: 32px; line-height: 32px;
color: #101828;
} }
.modalHeader .close { .modalHeader .close {
@apply shrink-0 h-4 w-4 bg-center bg-no-repeat cursor-pointer; @apply shrink-0 h-4 w-4 bg-center bg-no-repeat cursor-pointer;
@ -19,20 +18,18 @@
} }
.modal .tip { .modal .tip {
@apply mt-1 mb-8; @apply mt-1 mb-8 text-text-tertiary;
font-weight: 400; font-weight: 400;
font-size: 13px; font-size: 13px;
line-height: 18px; line-height: 18px;
color: #667085;
} }
.form { .form {
@apply mb-8; @apply mb-8;
} }
.form .label { .form .label {
@apply mb-2; @apply mb-2 text-text-primary;
font-weight: 500; font-weight: 500;
font-size: 14px; font-size: 14px;
line-height: 20px; line-height: 20px;
color: #101828;
} }

View File

@ -1,43 +1,29 @@
.filePreview { .filePreview {
@apply flex flex-col border-l border-gray-200 shrink-0; @apply flex flex-col border-l border-components-panel-border shrink-0 bg-background-default-lighter;
width: 100%; width: 100%;
background-color: #fcfcfd;
} }
.previewHeader { .previewHeader {
@apply border-b border-gray-200 shrink-0; @apply border-b border-divider-subtle shrink-0;
margin: 42px 32px 0; margin: 42px 32px 0;
padding-bottom: 16px; padding-bottom: 16px;
} }
.previewHeader .title { .previewHeader .title {
display: flex; @apply flex justify-between items-center text-text-primary;
justify-content: space-between;
align-items: center;
color: #101828;
font-weight: 600;
font-size: 18px;
line-height: 28px;
} }
.previewHeader .fileName { .previewHeader .fileName {
font-weight: 400; @apply text-text-tertiary;
font-size: 12px;
line-height: 18px;
color: #1D2939;
} }
.previewHeader .filetype { .previewHeader .filetype {
color: #667085; @apply text-text-tertiary;
} }
.previewContent { .previewContent {
@apply overflow-y-auto grow; @apply overflow-y-auto grow text-text-secondary;
padding: 20px 32px; padding: 20px 32px;
font-weight: 400;
font-size: 16px;
line-height: 24px;
color: #344054;
} }
.previewContent .loading { .previewContent .loading {
@ -46,6 +32,7 @@
background: #f9fafb center no-repeat url(../assets/Loading.svg); background: #f9fafb center no-repeat url(../assets/Loading.svg);
background-size: contain; background-size: contain;
} }
.fileContent { .fileContent {
white-space: pre-line; white-space: pre-line;
word-break: break-all; word-break: break-all;

View File

@ -46,13 +46,13 @@ const FilePreview = ({
return ( return (
<div className={cn(s.filePreview, 'h-full')}> <div className={cn(s.filePreview, 'h-full')}>
<div className={cn(s.previewHeader)}> <div className={cn(s.previewHeader)}>
<div className={cn(s.title)}> <div className={cn(s.title, 'title-md-semi-bold')}>
<span>{t('datasetCreation.stepOne.filePreview')}</span> <span>{t('datasetCreation.stepOne.filePreview')}</span>
<div className='flex items-center justify-center w-6 h-6 cursor-pointer' onClick={hidePreview}> <div className='flex items-center justify-center w-6 h-6 cursor-pointer' onClick={hidePreview}>
<XMarkIcon className='h-4 w-4'></XMarkIcon> <XMarkIcon className='h-4 w-4'></XMarkIcon>
</div> </div>
</div> </div>
<div className={cn(s.fileName)}> <div className={cn(s.fileName, 'system-xs-medium')}>
<span>{getFileName(file)}</span><span className={cn(s.filetype)}>.{file?.extension}</span> <span>{getFileName(file)}</span><span className={cn(s.filetype)}>.{file?.extension}</span>
</div> </div>
</div> </div>

View File

@ -256,7 +256,7 @@ const FileUploader = ({
/> />
)} )}
<div className={cn('text-text-tertiary text-sm font-semibold leading-6 mb-1', titleClassName)}>{t('datasetCreation.stepOne.uploader.title')}</div> <div className={cn('text-text-secondary text-sm font-semibold leading-6 mb-1', titleClassName)}>{t('datasetCreation.stepOne.uploader.title')}</div>
{!hideUpload && ( {!hideUpload && (
<div ref={dropRef} className={cn('relative box-border flex flex-col justify-center items-center gap-1 mb-2 px-4 py-3 max-w-[640px] min-h-20 leading-4 text-xs text-text-tertiary bg-components-dropzone-bg border border-dashed border-components-dropzone-border rounded-xl', dragging && 'bg-components-dropzone-bg-accent border-components-dropzone-border-accent')}> <div ref={dropRef} className={cn('relative box-border flex flex-col justify-center items-center gap-1 mb-2 px-4 py-3 max-w-[640px] min-h-20 leading-4 text-xs text-text-tertiary bg-components-dropzone-bg border border-dashed border-components-dropzone-border rounded-xl', dragging && 'bg-components-dropzone-bg-accent border-components-dropzone-border-accent')}>

View File

@ -1,45 +1,25 @@
.filePreview { .filePreview {
@apply flex flex-col border-l border-gray-200 shrink-0; @apply flex flex-col border-l border-components-panel-border shrink-0 bg-background-default-lighter;
width: 528px; width: 528px;
background-color: #fcfcfd;
} }
.previewHeader { .previewHeader {
@apply border-b border-gray-200 shrink-0; @apply border-b border-divider-subtle shrink-0;
margin: 42px 32px 0; margin: 42px 32px 0;
padding-bottom: 16px; padding-bottom: 16px;
} }
.previewHeader .title { .previewHeader .title {
display: flex; @apply flex justify-between items-center text-text-primary;
justify-content: space-between;
align-items: center;
color: #101828;
font-weight: 600;
font-size: 18px;
line-height: 28px;
} }
.previewHeader .fileName { .previewHeader .fileName {
display: flex; @apply flex items-center text-text-tertiary;
align-items: center;
font-weight: 400;
font-size: 12px;
line-height: 18px;
color: #1D2939;
}
.previewHeader .filetype {
color: #667085;
} }
.previewContent { .previewContent {
@apply overflow-y-auto grow; @apply overflow-y-auto grow text-text-secondary;
padding: 20px 32px; padding: 20px 32px;
font-weight: 400;
font-size: 16px;
line-height: 24px;
color: #344054;
} }
.previewContent .loading { .previewContent .loading {

View File

@ -46,13 +46,13 @@ const NotionPagePreview = ({
return ( return (
<div className={cn(s.filePreview, 'h-full')}> <div className={cn(s.filePreview, 'h-full')}>
<div className={cn(s.previewHeader)}> <div className={cn(s.previewHeader)}>
<div className={cn(s.title)}> <div className={cn(s.title, 'title-md-semi-bold')}>
<span>{t('datasetCreation.stepOne.pagePreview')}</span> <span>{t('datasetCreation.stepOne.pagePreview')}</span>
<div className='flex items-center justify-center w-6 h-6 cursor-pointer' onClick={hidePreview}> <div className='flex items-center justify-center w-6 h-6 cursor-pointer' onClick={hidePreview}>
<XMarkIcon className='h-4 w-4'></XMarkIcon> <XMarkIcon className='h-4 w-4'></XMarkIcon>
</div> </div>
</div> </div>
<div className={cn(s.fileName)}> <div className={cn(s.fileName, 'system-xs-medium')}>
<NotionIcon <NotionIcon
className='shrink-0 mr-1' className='shrink-0 mr-1'
type='page' type='page'
@ -61,7 +61,7 @@ const NotionPagePreview = ({
{currentPage?.page_name} {currentPage?.page_name}
</div> </div>
</div> </div>
<div className={cn(s.previewContent)}> <div className={cn(s.previewContent, 'body-md-regular')}>
{loading && <div className={cn(s.loading)} />} {loading && <div className={cn(s.loading)} />}
{!loading && ( {!loading && (
<div className={cn(s.fileContent, 'body-md-regular')}>{previewContent}</div> <div className={cn(s.fileContent, 'body-md-regular')}>{previewContent}</div>

View File

@ -1,11 +1,5 @@
.stepHeader { .stepHeader {
position: sticky;
top: 0;
left: 0;
padding: 42px 64px 12px 0; padding: 42px 64px 12px 0;
font-weight: 600;
font-size: 18px;
line-height: 28px;
} }
.form { .form {
@ -14,38 +8,22 @@
} }
.dataSourceItem { .dataSourceItem {
@apply w-full box-border relative flex items-center p-3 h-14 bg-white rounded-xl cursor-pointer; @apply w-full relative flex items-center p-3 h-14 bg-components-option-card-option-bg rounded-xl
border: 0.5px solid #EAECF0; cursor-pointer border border-components-option-card-option-border text-text-secondary;
box-shadow: 0px 1px 2px rgba(16, 24, 40, 0.05);
font-weight: 500;
font-size: 14px;
line-height: 20px;
color: #101828;
} }
.dataSourceItem:hover { .dataSourceItem:hover {
background-color: #f5f8ff; @apply bg-components-option-card-option-bg-hover border border-components-option-card-option-border-hover shadow-xs shadow-shadow-shadow-3;
border: 0.5px solid #B2CCFF;
box-shadow: 0px 12px 16px -4px rgba(16, 24, 40, 0.08), 0px 4px 6px -2px rgba(16, 24, 40, 0.03);
} }
.dataSourceItem.active { .dataSourceItem.active {
background-color: #f5f8ff; @apply bg-components-option-card-option-selected-bg border border-components-option-card-option-selected-border
border: 1.5px solid #528BFF; ring-[0.5px] ring-components-option-card-option-selected-border;
box-shadow: 0px 1px 3px rgba(16, 24, 40, 0.1), 0px 1px 2px rgba(16, 24, 40, 0.06);
}
.dataSourceItem.disabled {
background-color: #f9fafb;
border: 0.5px solid #EAECF0;
box-shadow: 0px 1px 2px rgba(16, 24, 40, 0.05);
cursor: default;
} }
.dataSourceItem.disabled,
.dataSourceItem.disabled:hover { .dataSourceItem.disabled:hover {
background-color: #f9fafb; @apply bg-components-option-card-option-bg border-[0.5px] border-components-option-card-option-border cursor-not-allowed text-text-disabled shadow-none;
border: 0.5px solid #EAECF0;
box-shadow: 0px 1px 2px rgba(16, 24, 40, 0.05);
} }
.comingTag { .comingTag {
@ -64,17 +42,9 @@
} }
.datasetIcon { .datasetIcon {
@apply flex shrink-0 mr-2 w-8 h-8 rounded-lg bg-center bg-no-repeat; @apply flex shrink-0 mr-2 w-8 h-8 rounded-lg bg-center bg-no-repeat bg-text-primary-on-surface border-[0.5px] border-divider-regular backdrop-blur-sm;
background-color: #F5FAFF;
background-image: url(../assets/file.svg); background-image: url(../assets/file.svg);
background-size: 16px; background-size: 16px;
border: 0.5px solid #D1E9FF;
}
.dataSourceItem:active .datasetIcon,
.dataSourceItem:hover .datasetIcon {
background-color: #F5F8FF;
border: 0.5px solid #E0EAFF;
} }
.datasetIcon.notion { .datasetIcon.notion {
@ -97,54 +67,7 @@
background-color: #eaecf0; background-color: #eaecf0;
} }
.notionConnectionTip {
display: flex;
flex-direction: column;
align-items: flex-start;
padding: 24px;
width: 640px;
background: #F9FAFB;
border-radius: 16px;
}
.notionIcon { .notionIcon {
display: flex; background: var(--color-components-card-bg) center no-repeat url(../assets/notion.svg);
padding: 12px;
width: 48px;
height: 48px;
background: #fff center no-repeat url(../assets/notion.svg);
background-size: 24px; background-size: 24px;
border: 0.5px solid #EAECF5;
box-shadow: 0px 12px 16px -4px rgba(16, 24, 40, 0.08), 0px 4px 6px -2px rgba(16, 24, 40, 0.03);
border-radius: 12px;
}
.notionConnectionTip .title {
position: relative;
margin: 24px 0 4px;
font-style: normal;
font-weight: 600;
font-size: 16px;
line-height: 24px;
color: #374151;
}
.notionConnectionTip .title::after {
content: '';
position: absolute;
top: -6px;
right: -12px;
width: 16px;
height: 16px;
background: center no-repeat url(../assets/Icon-3-dots.svg);
background-size: contain;
}
.notionConnectionTip .tip {
margin-bottom: 20px;
font-style: normal;
font-weight: 400;
font-size: 13px;
line-height: 18px;
color: #6B7280;
} }

View File

@ -19,6 +19,7 @@ import { useDatasetDetailContext } from '@/context/dataset-detail'
import { useProviderContext } from '@/context/provider-context' import { useProviderContext } from '@/context/provider-context'
import VectorSpaceFull from '@/app/components/billing/vector-space-full' import VectorSpaceFull from '@/app/components/billing/vector-space-full'
import classNames from '@/utils/classnames' import classNames from '@/utils/classnames'
import { Icon3Dots } from '@/app/components/base/icons/src/vender/line/others'
type IStepOneProps = { type IStepOneProps = {
datasetId?: string datasetId?: string
@ -48,10 +49,15 @@ export const NotionConnector = ({ onSetting }: NotionConnectorProps) => {
const { t } = useTranslation() const { t } = useTranslation()
return ( return (
<div className={s.notionConnectionTip}> <div className='flex flex-col items-start p-6 w-[640px] rounded-2xl bg-workflow-process-bg'>
<span className={s.notionIcon} /> <span className={cn(s.notionIcon, 'w-12 h-12 p-3 border-[0.5px] border-components-card-border rounded-[10px] shadow-lg shadow-shadow-shadow-5 mb-2')} />
<div className={s.title}>{t('datasetCreation.stepOne.notionSyncTitle')}</div> <div className='flex flex-col gap-y-1 pt-1 pb-3 mb-1'>
<div className={s.tip}>{t('datasetCreation.stepOne.notionSyncTip')}</div> <span className='text-text-secondary system-md-semibold'>
{t('datasetCreation.stepOne.notionSyncTitle')}
<Icon3Dots className='inline relative -top-2.5 -left-1.5 w-4 h-4 text-text-secondary' />
</span>
<div className='text-text-tertiary system-sm-regular'>{t('datasetCreation.stepOne.notionSyncTip')}</div>
</div>
<Button className='h-8' variant='primary' onClick={onSetting}>{t('datasetCreation.stepOne.connect')}</Button> <Button className='h-8' variant='primary' onClick={onSetting}>{t('datasetCreation.stepOne.connect')}</Button>
</div> </div>
) )
@ -132,7 +138,9 @@ const StepOne = ({
<div className={classNames(s.form)}> <div className={classNames(s.form)}>
{ {
shouldShowDataSourceTypeList && ( shouldShowDataSourceTypeList && (
<div className={classNames(s.stepHeader, 'z-10 text-text-secondary bg-components-panel-bg-blur')}>{t('datasetCreation.steps.one')}</div> <div className={classNames(s.stepHeader, 'text-text-secondary system-md-semibold')}>
{t('datasetCreation.steps.one')}
</div>
) )
} }
{ {
@ -141,6 +149,7 @@ const StepOne = ({
<div <div
className={cn( className={cn(
s.dataSourceItem, s.dataSourceItem,
'system-sm-medium',
dataSourceType === DataSourceType.FILE && s.active, dataSourceType === DataSourceType.FILE && s.active,
dataSourceTypeDisable && dataSourceType !== DataSourceType.FILE && s.disabled, dataSourceTypeDisable && dataSourceType !== DataSourceType.FILE && s.disabled,
)} )}
@ -163,6 +172,7 @@ const StepOne = ({
<div <div
className={cn( className={cn(
s.dataSourceItem, s.dataSourceItem,
'system-sm-medium',
dataSourceType === DataSourceType.NOTION && s.active, dataSourceType === DataSourceType.NOTION && s.active,
dataSourceTypeDisable && dataSourceType !== DataSourceType.NOTION && s.disabled, dataSourceTypeDisable && dataSourceType !== DataSourceType.NOTION && s.disabled,
)} )}
@ -185,6 +195,7 @@ const StepOne = ({
<div <div
className={cn( className={cn(
s.dataSourceItem, s.dataSourceItem,
'system-sm-medium',
dataSourceType === DataSourceType.WEB && s.active, dataSourceType === DataSourceType.WEB && s.active,
dataSourceTypeDisable && dataSourceType !== DataSourceType.WEB && s.disabled, dataSourceTypeDisable && dataSourceType !== DataSourceType.WEB && s.disabled,
)} )}
@ -205,7 +216,7 @@ const StepOne = ({
<> <>
<FileUploader <FileUploader
fileList={files} fileList={files}
titleClassName={!shouldShowDataSourceTypeList ? 'mt-[30px] !mb-[44px] !text-lg !font-semibold !text-gray-900' : undefined} titleClassName={!shouldShowDataSourceTypeList ? 'mt-[30px] !mb-[44px] !text-lg' : undefined}
prepareFileList={updateFileList} prepareFileList={updateFileList}
onFileListUpdate={updateFileList} onFileListUpdate={updateFileList}
onFileUpdate={updateFile} onFileUpdate={updateFile}

View File

@ -34,8 +34,8 @@ const StepThree = ({ datasetId, datasetName, indexingType, creationCache, retrie
<div className="flex gap-4"> <div className="flex gap-4">
<AppIcon {...creationCache?.dataset} className="size-14 text-2xl self-center" /> <AppIcon {...creationCache?.dataset} className="size-14 text-2xl self-center" />
<div className="grow flex flex-col gap-1"> <div className="grow flex flex-col gap-1">
<div className="text-[13px] leading-6 font-semibold">{t('datasetCreation.stepThree.label')}</div> <div className="text-[13px] leading-6 font-semibold text-text-secondary">{t('datasetCreation.stepThree.label')}</div>
<div className="w-full px-3 py-2 text-[13px] leading-4 bg-components-input-bg-normal rounded-lg truncate">{datasetName || creationCache?.dataset?.name}</div> <div className="w-full px-3 py-2 text-[13px] leading-4 bg-components-input-bg-normal rounded-lg truncate text-components-input-text-filled">{datasetName || creationCache?.dataset?.name}</div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -581,7 +581,7 @@ const StepTwo = ({
return ( return (
<div className='flex w-full h-full'> <div className='flex w-full h-full'>
<div className={cn('relative h-full w-1/2 py-6 overflow-y-auto', isMobile ? 'px-4' : 'px-12')}> <div className={cn('relative h-full w-1/2 py-6 overflow-y-auto', isMobile ? 'px-4' : 'px-12')}>
<div className={'system-md-semibold mb-1'}>{t('datasetCreation.stepTwo.segmentation')}</div> <div className={'system-md-semibold text-text-secondary mb-1'}>{t('datasetCreation.stepTwo.segmentation')}</div>
{((isInUpload && [ChunkingMode.text, ChunkingMode.qa].includes(currentDataset!.doc_form)) {((isInUpload && [ChunkingMode.text, ChunkingMode.qa].includes(currentDataset!.doc_form))
|| isUploadInEmptyDataset || isUploadInEmptyDataset
|| isInInit) || isInInit)
@ -832,10 +832,10 @@ const StepTwo = ({
</div> </div>
</OptionCard>} </OptionCard>}
<Divider className='my-5' /> <Divider className='my-5' />
<div className={'system-md-semibold mb-1'}>{t('datasetCreation.stepTwo.indexMode')}</div> <div className={'system-md-semibold text-text-secondary mb-1'}>{t('datasetCreation.stepTwo.indexMode')}</div>
<div className='flex items-center gap-2'> <div className='flex items-center gap-2'>
{(!hasSetIndexType || (hasSetIndexType && indexingType === IndexingType.QUALIFIED)) && ( {(!hasSetIndexType || (hasSetIndexType && indexingType === IndexingType.QUALIFIED)) && (
<OptionCard className='flex-1' <OptionCard className='flex-1 self-stretch'
title={<div className='flex items-center'> title={<div className='flex items-center'>
{t('datasetCreation.stepTwo.qualified')} {t('datasetCreation.stepTwo.qualified')}
<Badge className={cn('ml-1 h-[18px]', (!hasSetIndexType && indexType === IndexingType.QUALIFIED) ? 'border-text-accent-secondary text-text-accent-secondary' : '')} uppercase> <Badge className={cn('ml-1 h-[18px]', (!hasSetIndexType && indexType === IndexingType.QUALIFIED) ? 'border-text-accent-secondary text-text-accent-secondary' : '')} uppercase>
@ -889,7 +889,7 @@ const StepTwo = ({
placement={'top'} placement={'top'}
> >
<PortalToFollowElemTrigger asChild> <PortalToFollowElemTrigger asChild>
<OptionCard className='flex-1' <OptionCard className='flex-1 self-stretch'
title={t('datasetCreation.stepTwo.economical')} title={t('datasetCreation.stepTwo.economical')}
description={t('datasetCreation.stepTwo.economicalTip')} description={t('datasetCreation.stepTwo.economicalTip')}
icon={<Image src={indexMethodIcon.economical} alt='' />} icon={<Image src={indexMethodIcon.economical} alt='' />}
@ -916,11 +916,11 @@ const StepTwo = ({
</div> </div>
{!hasSetIndexType && indexType === IndexingType.QUALIFIED && ( {!hasSetIndexType && indexType === IndexingType.QUALIFIED && (
<div className='mt-2 h-10 p-2 flex items-center gap-x-0.5 rounded-xl border-[0.5px] border-components-panel-border overflow-hidden bg-components-panel-bg-blur backdrop-blur-[5px] shadow-xs'> <div className='mt-2 h-10 p-2 flex items-center gap-x-0.5 rounded-xl border-[0.5px] border-components-panel-border overflow-hidden bg-components-panel-bg-blur backdrop-blur-[5px] shadow-xs'>
<div className='absolute top-0 left-0 right-0 bottom-0 bg-[linear-gradient(92deg,rgba(247,144,9,0.25)_0%,rgba(255,255,255,0.00)_100%)] opacity-40'></div> <div className='absolute top-0 left-0 right-0 bottom-0 bg-dataset-warning-message-bg opacity-40'></div>
<div className='p-1'> <div className='p-1'>
<AlertTriangle className='size-4 text-text-warning-secondary' /> <AlertTriangle className='size-4 text-text-warning-secondary' />
</div> </div>
<span className='system-xs-medium'>{t('datasetCreation.stepTwo.highQualityTip')}</span> <span className='system-xs-medium text-text-primary'>{t('datasetCreation.stepTwo.highQualityTip')}</span>
</div> </div>
)} )}
{hasSetIndexType && indexType === IndexingType.ECONOMICAL && ( {hasSetIndexType && indexType === IndexingType.ECONOMICAL && (
@ -932,7 +932,7 @@ const StepTwo = ({
{/* Embedding model */} {/* Embedding model */}
{indexType === IndexingType.QUALIFIED && ( {indexType === IndexingType.QUALIFIED && (
<div className='mt-5'> <div className='mt-5'>
<div className={cn('system-md-semibold mb-1', datasetId && 'flex justify-between items-center')}>{t('datasetSettings.form.embeddingModel')}</div> <div className={cn('system-md-semibold text-text-secondary mb-1', datasetId && 'flex justify-between items-center')}>{t('datasetSettings.form.embeddingModel')}</div>
<ModelSelector <ModelSelector
readonly={isModelAndRetrievalConfigDisabled} readonly={isModelAndRetrievalConfigDisabled}
triggerClassName={isModelAndRetrievalConfigDisabled ? 'opacity-50' : ''} triggerClassName={isModelAndRetrievalConfigDisabled ? 'opacity-50' : ''}
@ -943,7 +943,7 @@ const StepTwo = ({
}} }}
/> />
{isModelAndRetrievalConfigDisabled && ( {isModelAndRetrievalConfigDisabled && (
<div className='mt-2 system-xs-medium'> <div className='mt-2 system-xs-medium text-text-tertiary'>
{t('datasetCreation.stepTwo.indexSettingTip')} {t('datasetCreation.stepTwo.indexSettingTip')}
<Link className='text-text-accent' href={`/datasets/${datasetId}/settings`}>{t('datasetCreation.stepTwo.datasetSettingLink')}</Link> <Link className='text-text-accent' href={`/datasets/${datasetId}/settings`}>{t('datasetCreation.stepTwo.datasetSettingLink')}</Link>
</div> </div>
@ -956,7 +956,7 @@ const StepTwo = ({
{!isModelAndRetrievalConfigDisabled {!isModelAndRetrievalConfigDisabled
? ( ? (
<div className={'mb-1'}> <div className={'mb-1'}>
<div className='system-md-semibold mb-0.5'>{t('datasetSettings.form.retrievalSetting.title')}</div> <div className='system-md-semibold text-text-secondary mb-0.5'>{t('datasetSettings.form.retrievalSetting.title')}</div>
<div className='body-xs-regular text-text-tertiary'> <div className='body-xs-regular text-text-tertiary'>
<a target='_blank' rel='noopener noreferrer' href='https://docs.dify.ai/guides/knowledge-base/create-knowledge-and-upload-documents#id-4-retrieval-settings' className='text-text-accent'>{t('datasetSettings.form.retrievalSetting.learnMore')}</a> <a target='_blank' rel='noopener noreferrer' href='https://docs.dify.ai/guides/knowledge-base/create-knowledge-and-upload-documents#id-4-retrieval-settings' className='text-text-accent'>{t('datasetSettings.form.retrievalSetting.learnMore')}</a>
{t('datasetSettings.form.retrievalSetting.longDescription')} {t('datasetSettings.form.retrievalSetting.longDescription')}
@ -964,7 +964,7 @@ const StepTwo = ({
</div> </div>
) )
: ( : (
<div className={cn('system-md-semibold mb-0.5', 'flex justify-between items-center')}> <div className={cn('system-md-semibold text-text-secondary mb-0.5', 'flex justify-between items-center')}>
<div>{t('datasetSettings.form.retrievalSetting.title')}</div> <div>{t('datasetSettings.form.retrievalSetting.title')}</div>
</div> </div>
)} )}

View File

@ -34,7 +34,7 @@ export const OptionCardHeader: FC<OptionCardHeaderProps> = (props) => {
</div> </div>
</div> </div>
<TriangleArrow <TriangleArrow
className='absolute left-4 -bottom-1.5 text-components-panel-bg' className={classNames('absolute left-4 -bottom-1.5 text-transparent', isActive && 'text-components-panel-bg')}
/> />
<div className='flex-1 space-y-0.5 py-3 pr-4'> <div className='flex-1 space-y-0.5 py-3 pr-4'>
<div className='text-text-secondary system-md-semibold'>{title}</div> <div className='text-text-secondary system-md-semibold'>{title}</div>

View File

@ -25,7 +25,7 @@ const CheckboxWithLabel: FC<Props> = ({
return ( return (
<label className={cn(className, 'flex items-center h-7 space-x-2')}> <label className={cn(className, 'flex items-center h-7 space-x-2')}>
<Checkbox checked={isChecked} onCheck={() => onChange(!isChecked)} /> <Checkbox checked={isChecked} onCheck={() => onChange(!isChecked)} />
<div className={cn(labelClassName, 'text-sm font-normal text-text-secondary')}>{label}</div> <div className={cn('text-sm font-normal text-text-secondary', labelClassName)}>{label}</div>
{tooltip && ( {tooltip && (
<Tooltip <Tooltip
popupContent={ popupContent={

View File

@ -5,6 +5,7 @@ import { useTranslation } from 'react-i18next'
import cn from '@/utils/classnames' import cn from '@/utils/classnames'
import type { CrawlResultItem as CrawlResultItemType } from '@/models/datasets' import type { CrawlResultItem as CrawlResultItemType } from '@/models/datasets'
import Checkbox from '@/app/components/base/checkbox' import Checkbox from '@/app/components/base/checkbox'
import Button from '@/app/components/base/button'
type Props = { type Props = {
payload: CrawlResultItemType payload: CrawlResultItemType
@ -27,13 +28,32 @@ const CrawledResultItem: FC<Props> = ({
onCheckChange(!isChecked) onCheckChange(!isChecked)
}, [isChecked, onCheckChange]) }, [isChecked, onCheckChange])
return ( return (
<div className={cn(isPreview ? 'border-[#D1E0FF] bg-primary-50 shadow-xs' : 'group hover:bg-gray-100', 'rounded-md px-2 py-[5px] cursor-pointer border border-transparent')}> <div className={cn(isPreview ? 'bg-state-base-active' : 'group hover:bg-state-base-hover', 'rounded-lg p-2 cursor-pointer')}>
<div className='flex items-center h-5'> <div className='relative flex'>
<Checkbox className='group-hover:border-2 group-hover:border-primary-600 mr-2 shrink-0' checked={isChecked} onCheck={handleCheckChange} /> <div className='h-5 flex items-center'>
<div className='grow w-0 truncate text-sm font-medium text-gray-700' title={payload.title}>{payload.title}</div> <Checkbox className='mr-2 shrink-0' checked={isChecked} onCheck={handleCheckChange} />
<div onClick={onPreview} className='hidden group-hover:flex items-center h-6 px-2 text-xs rounded-md font-medium text-gray-500 uppercase hover:bg-gray-50'>{t('datasetCreation.stepOne.website.preview')}</div> </div>
<div className='flex flex-col grow min-w-0'>
<div
className='truncate text-sm font-medium text-text-secondary'
title={payload.title}
>
{payload.title}
</div>
<div
className='mt-0.5 truncate text-xs text-text-tertiary'
title={payload.source_url}
>
{payload.source_url}
</div>
</div>
<Button
onClick={onPreview}
className='hidden group-hover:block group-hover:absolute top-0 right-0 h-6 px-1.5 text-xs font-medium uppercase'
>
{t('datasetCreation.stepOne.website.preview')}
</Button>
</div> </div>
<div className='mt-0.5 truncate pl-6 leading-[18px] text-xs font-normal text-gray-500' title={payload.source_url}>{payload.source_url}</div>
</div> </div>
) )
} }

View File

@ -57,17 +57,19 @@ const CrawledResult: FC<Props> = ({
}, [list, onPreview]) }, [list, onPreview])
return ( return (
<div className={cn(className, 'border-t border-gray-200')}> <div className={cn(className, 'border-t-[0.5px] border-divider-regular shadow-xs shadow-shadow-shadow-3')}>
<div className='flex items-center justify-between h-[34px] px-4 bg-gray-50 shadow-xs border-b-[0.5px] border-black/8 text-xs font-normal text-gray-700'> <div className='flex items-center justify-between h-[34px] px-4'>
<CheckboxWithLabel <CheckboxWithLabel
isChecked={isCheckAll} isChecked={isCheckAll}
onChange={handleCheckedAll} label={isCheckAll ? t(`${I18N_PREFIX}.resetAll`) : t(`${I18N_PREFIX}.selectAll`)} onChange={handleCheckedAll} label={isCheckAll ? t(`${I18N_PREFIX}.resetAll`) : t(`${I18N_PREFIX}.selectAll`)}
labelClassName='!font-medium' labelClassName='system-[13px] leading-[16px] font-medium text-text-secondary'
/> />
<div>{t(`${I18N_PREFIX}.scrapTimeInfo`, { <div className='text-xs text-text-tertiary'>
{t(`${I18N_PREFIX}.scrapTimeInfo`, {
total: list.length, total: list.length,
time: usedTime.toFixed(1), time: usedTime.toFixed(1),
})}</div> })}
</div>
</div> </div>
<div className='p-2'> <div className='p-2'>
{list.map((item, index) => ( {list.map((item, index) => (

View File

@ -2,7 +2,6 @@
import type { FC } from 'react' import type { FC } from 'react'
import React from 'react' import React from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import cn from '@/utils/classnames'
import { RowStruct } from '@/app/components/base/icons/src/public/other' import { RowStruct } from '@/app/components/base/icons/src/public/other'
type Props = { type Props = {
@ -19,15 +18,16 @@ const Crawling: FC<Props> = ({
const { t } = useTranslation() const { t } = useTranslation()
return ( return (
<div className={cn(className, 'border-t border-gray-200')}> <div className={className}>
<div className='flex items-center h-[34px] px-4 bg-gray-50 shadow-xs border-b-[0.5px] border-black/8 text-xs font-normal text-gray-700'> <div className='flex items-center h-[34px] px-4 shadow-xs shadow-shadow-shadow-3
border-y-[0.5px] border-divider-regular text-xs text-text-tertiary'>
{t('datasetCreation.stepOne.website.totalPageScraped')} {crawledNum}/{totalNum} {t('datasetCreation.stepOne.website.totalPageScraped')} {crawledNum}/{totalNum}
</div> </div>
<div className='p-2'> <div className='p-2'>
{['', '', '', ''].map((item, index) => ( {['', '', '', ''].map((item, index) => (
<div className='py-[5px]' key={index}> <div className='py-[5px]' key={index}>
<RowStruct /> <RowStruct className='text-text-quaternary' />
</div> </div>
))} ))}
</div> </div>

View File

@ -16,13 +16,13 @@ const ErrorMessage: FC<Props> = ({
errorMsg, errorMsg,
}) => { }) => {
return ( return (
<div className={cn(className, 'py-2 px-4 border-t border-gray-200 bg-[#FFFAEB]')}> <div className={cn(className, 'py-2 px-4 border-t border-divider-subtle bg-dataset-warning-message-bg opacity-40')}>
<div className='flex items-center h-5'> <div className='flex items-center h-5'>
<AlertTriangle className='mr-2 w-4 h-4 text-text-warning-secondary' /> <AlertTriangle className='mr-2 w-4 h-4 text-text-warning-secondary' />
<div className='text-sm font-medium text-[#DC6803]'>{title}</div> <div className='system-md-medium text-text-warning'>{title}</div>
</div> </div>
{errorMsg && ( {errorMsg && (
<div className='mt-1 pl-6 leading-[18px] text-xs font-normal text-gray-700'>{errorMsg}</div> <div className='mt-1 pl-6 system-xs-regular text-text-secondary'>{errorMsg}</div>
)} )}
</div> </div>
) )

View File

@ -31,8 +31,8 @@ const Field: FC<Props> = ({
return ( return (
<div className={cn(className)}> <div className={cn(className)}>
<div className='flex py-[7px]'> <div className='flex py-[7px]'>
<div className={cn(labelClassName, 'flex items-center h-[18px] text-[13px] font-medium text-text-primary')}>{label} </div> <div className={cn(labelClassName, 'flex items-center h-[16px] text-[13px] font-semibold text-text-secondary')}>{label} </div>
{isRequired && <span className='ml-0.5 text-xs font-semibold text-[#D92D20]'>*</span>} {isRequired && <span className='ml-0.5 text-xs font-semibold text-text-destructive'>*</span>}
{tooltip && ( {tooltip && (
<Tooltip <Tooltip
popupContent={ popupContent={

View File

@ -20,7 +20,7 @@ const Input: FC<Props> = ({
const handleChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => { const handleChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
const value = e.target.value const value = e.target.value
if (isNumber) { if (isNumber) {
let numberValue = parseInt(value, 10) // integer only let numberValue = Number.parseInt(value, 10) // integer only
if (isNaN(numberValue)) { if (isNaN(numberValue)) {
onChange('') onChange('')
return return
@ -50,7 +50,12 @@ const Input: FC<Props> = ({
{...otherOption} {...otherOption}
value={value} value={value}
onChange={handleChange} onChange={handleChange}
className='flex h-9 w-full py-1 px-2 rounded-lg text-xs leading-normal bg-gray-100 caret-primary-600 hover:bg-gray-100 focus:ring-1 focus:ring-inset focus:ring-gray-200 focus-visible:outline-none focus:bg-gray-50 placeholder:text-gray-400' className='flex h-8 w-full p-2 rounded-lg system-xs-regular text-components-input-text-filled bg-components-input-bg-normal
caret-[#295eff] border border-transparent
hover:bg-components-input-bg-hover hover:border hover:border-components-input-border-hover
focus-visible:outline-none focus:bg-components-inout-border-active focus:border focus:border-components-input-border-active
focus:shadow-xs focus:shadow-shadow-shadow-3
placeholder:text-components-input-text-placeholder'
placeholder={placeholder} placeholder={placeholder}
/> />
) )

View File

@ -3,8 +3,8 @@ import { useBoolean } from 'ahooks'
import type { FC } from 'react' import type { FC } from 'react'
import React, { useEffect } from 'react' import React, { useEffect } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { RiEqualizer2Line } from '@remixicon/react'
import cn from '@/utils/classnames' import cn from '@/utils/classnames'
import { Settings04 } from '@/app/components/base/icons/src/vender/line/general'
import { ChevronRight } from '@/app/components/base/icons/src/vender/line/arrows' import { ChevronRight } from '@/app/components/base/icons/src/vender/line/arrows'
const I18N_PREFIX = 'datasetCreation.stepOne.website' const I18N_PREFIX = 'datasetCreation.stepOne.website'
@ -34,14 +34,14 @@ const OptionsWrap: FC<Props> = ({
return ( return (
<div className={cn(className, !fold ? 'mb-0' : 'mb-3')}> <div className={cn(className, !fold ? 'mb-0' : 'mb-3')}>
<div <div
className='flex justify-between items-center h-[26px] py-1 cursor-pointer select-none' className='flex items-center gap-x-1 h-[26px] py-1 cursor-pointer select-none'
onClick={foldToggle} onClick={foldToggle}
> >
<div className='flex items-center text-gray-700'> <div className='flex items-center grow'>
<Settings04 className='mr-1 w-4 h-4' /> <RiEqualizer2Line className='mr-1 w-4 h-4 text-text-secondary' />
<div className='text-[13px] font-semibold text-gray-800 uppercase'>{t(`${I18N_PREFIX}.options`)}</div> <span className='text-[13px] leading-[16px] font-semibold text-text-secondary uppercase'>{t(`${I18N_PREFIX}.options`)}</span>
</div> </div>
<ChevronRight className={cn(!fold && 'rotate-90', 'w-4 h-4 text-gray-500')} /> <ChevronRight className={cn(!fold && 'rotate-90', 'w-4 h-4 shrink-0 text-text-tertiary')} />
</div> </div>
{!fold && ( {!fold && (
<div className='mb-4'> <div className='mb-4'>

View File

@ -28,7 +28,7 @@ const UrlInput: FC<Props> = ({
}, [isRunning, onRun, url]) }, [isRunning, onRun, url])
return ( return (
<div className='flex items-center justify-between'> <div className='flex items-center justify-between gap-x-2'>
<Input <Input
value={url} value={url}
onChange={handleUrlChange} onChange={handleUrlChange}
@ -37,8 +37,8 @@ const UrlInput: FC<Props> = ({
<Button <Button
variant='primary' variant='primary'
onClick={handleOnRun} onClick={handleOnRun}
className='ml-2'
loading={isRunning} loading={isRunning}
spinnerClassName='!ml-0'
> >
{!isRunning ? t(`${I18N_PREFIX}.run`) : ''} {!isRunning ? t(`${I18N_PREFIX}.run`) : ''}
</Button> </Button>

View File

@ -2,8 +2,8 @@
import type { FC } from 'react' import type { FC } from 'react'
import React from 'react' import React from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { Settings01 } from '@/app/components/base/icons/src/vender/line/general' import { RiBookOpenLine, RiEqualizer2Line } from '@remixicon/react'
import { BookOpen01 } from '@/app/components/base/icons/src/vender/line/education' import Button from '@/app/components/base/button'
const I18N_PREFIX = 'datasetCreation.stepOne.website' const I18N_PREFIX = 'datasetCreation.stepOne.website'
@ -19,22 +19,23 @@ const Header: FC<Props> = ({
return ( return (
<div className='flex h-6 items-center justify-between'> <div className='flex h-6 items-center justify-between'>
<div className='flex items-center'> <div className='flex items-center'>
<div className='text-base font-medium text-gray-700'>{t(`${I18N_PREFIX}.firecrawlTitle`)}</div> <div className='text-base font-medium text-text-secondary'>{t(`${I18N_PREFIX}.firecrawlTitle`)}</div>
<div className='ml-2 mr-1 w-px h-3.5 bg-gray-200'></div> <div className='ml-2 mr-2 w-px h-3.5 bg-divider-regular' />
<div <Button className='flex items-center gap-x-[1px] h-6 px-1.5' onClick={onSetting}>
className='p-1 rounded-md hover:bg-black/5 cursor-pointer' <RiEqualizer2Line className='w-3.5 h-3.5 text-components-button-secondary-text' />
onClick={onSetting} <span className='text-components-button-secondary-text text-xs font-medium px-[3px]'>
> {t(`${I18N_PREFIX}.configureFirecrawl`)}
<Settings01 className='w-3.5 h-3.5 text-gray-500' /> </span>
</div> </Button>
</div> </div>
<a <a
href='https://docs.firecrawl.dev/introduction' href='https://docs.firecrawl.dev/introduction'
target='_blank' rel='noopener noreferrer' target='_blank'
className='flex items-center text-xs text-primary-600' rel='noopener noreferrer'
className='inline-flex items-center gap-x-1 text-xs font-medium text-text-accent'
> >
<BookOpen01 className='mr-1 w-3.5 h-3.5 text-primary-600' /> <RiBookOpenLine className='w-3.5 h-3.5 text-text-accent' />
{t(`${I18N_PREFIX}.firecrawlDoc`)} <span>{t(`${I18N_PREFIX}.firecrawlDoc`)}</span>
</a> </a>
</div> </div>
) )

View File

@ -9,7 +9,6 @@ import Crawling from '../base/crawling'
import ErrorMessage from '../base/error-message' import ErrorMessage from '../base/error-message'
import Header from './header' import Header from './header'
import Options from './options' import Options from './options'
import cn from '@/utils/classnames'
import { useModalContext } from '@/context/modal-context' import { useModalContext } from '@/context/modal-context'
import type { CrawlOptions, CrawlResultItem } from '@/models/datasets' import type { CrawlOptions, CrawlResultItem } from '@/models/datasets'
import Toast from '@/app/components/base/toast' import Toast from '@/app/components/base/toast'
@ -99,7 +98,7 @@ const FireCrawl: FC<Props> = ({
isError: false, isError: false,
data: { data: {
...res, ...res,
total: Math.min(res.total, parseFloat(crawlOptions.limit as string)), total: Math.min(res.total, Number.parseFloat(crawlOptions.limit as string)),
}, },
} }
} }
@ -116,7 +115,7 @@ const FireCrawl: FC<Props> = ({
// update the progress // update the progress
setCrawlResult({ setCrawlResult({
...res, ...res,
total: Math.min(res.total, parseFloat(crawlOptions.limit as string)), total: Math.min(res.total, Number.parseFloat(crawlOptions.limit as string)),
}) })
onCheckedCrawlResultChange(res.data || []) // default select the crawl result onCheckedCrawlResultChange(res.data || []) // default select the crawl result
await sleep(2500) await sleep(2500)
@ -179,10 +178,10 @@ const FireCrawl: FC<Props> = ({
return ( return (
<div> <div>
<Header onSetting={handleSetting} /> <Header onSetting={handleSetting} />
<div className={cn('mt-2 p-4 pb-0 rounded-xl border border-gray-200')}> <div className='mt-2 p-4 pb-0 rounded-xl border border-components-panel-border bg-background-default-subtle'>
<UrlInput onRun={handleRun} isRunning={isRunning} /> <UrlInput onRun={handleRun} isRunning={isRunning} />
<OptionsWrap <OptionsWrap
className={cn('mt-4')} className='mt-4'
controlFoldOptions={controlFoldOptions} controlFoldOptions={controlFoldOptions}
> >
<Options className='mt-2' payload={crawlOptions} onChange={onCrawlOptionsChange} /> <Options className='mt-2' payload={crawlOptions} onChange={onCrawlOptionsChange} />
@ -194,7 +193,7 @@ const FireCrawl: FC<Props> = ({
&& <Crawling && <Crawling
className='mt-2' className='mt-2'
crawledNum={crawlResult?.current || 0} crawledNum={crawlResult?.current || 0}
totalNum={crawlResult?.total || parseFloat(crawlOptions.limit as string) || 0} totalNum={crawlResult?.total || Number.parseFloat(crawlOptions.limit as string) || 0}
/>} />}
{showError && ( {showError && (
<ErrorMessage className='rounded-b-xl' title={t(`${I18N_PREFIX}.exceptionErrorTitle`)} errorMsg={crawlErrorMessage} /> <ErrorMessage className='rounded-b-xl' title={t(`${I18N_PREFIX}.exceptionErrorTitle`)} errorMsg={crawlErrorMessage} />
@ -206,7 +205,7 @@ const FireCrawl: FC<Props> = ({
checkedList={checkedCrawlResult} checkedList={checkedCrawlResult}
onSelectedChange={onCheckedCrawlResultChange} onSelectedChange={onCheckedCrawlResultChange}
onPreview={onPreview} onPreview={onPreview}
usedTime={parseFloat(crawlResult?.time_consuming as string) || 0} usedTime={Number.parseFloat(crawlResult?.time_consuming as string) || 0}
/> />
} }
</div> </div>

View File

@ -36,6 +36,7 @@ const Options: FC<Props> = ({
label={t(`${I18N_PREFIX}.crawlSubPage`)} label={t(`${I18N_PREFIX}.crawlSubPage`)}
isChecked={payload.crawl_sub_pages} isChecked={payload.crawl_sub_pages}
onChange={handleChange('crawl_sub_pages')} onChange={handleChange('crawl_sub_pages')}
labelClassName='text-[13px] leading-[16px] font-medium text-text-secondary'
/> />
<div className='flex justify-between space-x-4'> <div className='flex justify-between space-x-4'>
<Field <Field
@ -76,6 +77,7 @@ const Options: FC<Props> = ({
label={t(`${I18N_PREFIX}.extractOnlyMainContent`)} label={t(`${I18N_PREFIX}.extractOnlyMainContent`)}
isChecked={payload.only_main_content} isChecked={payload.only_main_content}
onChange={handleChange('only_main_content')} onChange={handleChange('only_main_content')}
labelClassName='text-[13px] leading-[16px] font-medium text-text-secondary'
/> />
</div> </div>
) )

View File

@ -73,27 +73,29 @@ const Website: FC<Props> = ({
return ( return (
<div> <div>
<div className="mb-4"> <div className="mb-4">
<div className="font-medium text-gray-700 mb-2 h-6"> <div className="system-md-medium text-text-secondary mb-2">
{t('datasetCreation.stepOne.website.chooseProvider')} {t('datasetCreation.stepOne.website.chooseProvider')}
</div> </div>
<div className="flex space-x-2"> <div className="flex space-x-2">
<button <button
className={`px-4 py-2 text-sm font-medium rounded-md flex items-center justify-center ${ className={cn('px-4 py-2 rounded-lg flex items-center justify-center',
selectedProvider === DataSourceProvider.jinaReader selectedProvider === DataSourceProvider.jinaReader
? 'bg-primary-50 text-primary-600' ? 'system-sm-medium bg-components-option-card-option-selected-bg text-text-primary border-[1.5px] border-components-option-card-option-selected-border'
: 'bg-gray-100 text-gray-600 hover:bg-gray-200' : `system-sm-regular bg-components-option-card-option-bg text-text-secondary border border-components-option-card-option-border
}`} hover:bg-components-option-card-option-bg-hover hover:border-components-option-card-option-border-hover hover:shadow-xs hover:shadow-shadow-shadow-3`,
)}
onClick={() => setSelectedProvider(DataSourceProvider.jinaReader)} onClick={() => setSelectedProvider(DataSourceProvider.jinaReader)}
> >
<span className={cn(s.jinaLogo, 'mr-2')} /> <span className={cn(s.jinaLogo, 'mr-2')} />
<span>Jina Reader</span> <span>Jina Reader</span>
</button> </button>
<button <button
className={`px-4 py-2 text-sm font-medium rounded-md ${ className={cn('px-4 py-2 rounded-lg',
selectedProvider === DataSourceProvider.fireCrawl selectedProvider === DataSourceProvider.fireCrawl
? 'bg-primary-50 text-primary-600' ? 'system-sm-medium bg-components-option-card-option-selected-bg text-text-primary border-[1.5px] border-components-option-card-option-selected-border'
: 'bg-gray-100 text-gray-600 hover:bg-gray-200' : `system-sm-regular bg-components-option-card-option-bg text-text-secondary border border-components-option-card-option-border
}`} hover:bg-components-option-card-option-bg-hover hover:border-components-option-card-option-border-hover hover:shadow-xs hover:shadow-shadow-shadow-3`,
)}
onClick={() => setSelectedProvider(DataSourceProvider.fireCrawl)} onClick={() => setSelectedProvider(DataSourceProvider.fireCrawl)}
> >
🔥 Firecrawl 🔥 Firecrawl

View File

@ -5,7 +5,7 @@ import cn from '@/utils/classnames'
import Checkbox from '@/app/components/base/checkbox' import Checkbox from '@/app/components/base/checkbox'
import Tooltip from '@/app/components/base/tooltip' import Tooltip from '@/app/components/base/tooltip'
interface Props { type Props = {
className?: string className?: string
isChecked: boolean isChecked: boolean
onChange: (isChecked: boolean) => void onChange: (isChecked: boolean) => void
@ -25,7 +25,7 @@ const CheckboxWithLabel: FC<Props> = ({
return ( return (
<label className={cn(className, 'flex items-center h-7 space-x-2')}> <label className={cn(className, 'flex items-center h-7 space-x-2')}>
<Checkbox checked={isChecked} onCheck={() => onChange(!isChecked)} /> <Checkbox checked={isChecked} onCheck={() => onChange(!isChecked)} />
<div className={cn(labelClassName, 'text-sm font-normal text-gray-800')}>{label}</div> <div className={cn('text-sm font-normal text-gray-800', labelClassName)}>{label}</div>
{tooltip && ( {tooltip && (
<Tooltip <Tooltip
popupContent={ popupContent={

View File

@ -1,40 +0,0 @@
'use client'
import type { FC } from 'react'
import React, { useCallback } from 'react'
import { useTranslation } from 'react-i18next'
import cn from '@/utils/classnames'
import type { CrawlResultItem as CrawlResultItemType } from '@/models/datasets'
import Checkbox from '@/app/components/base/checkbox'
interface Props {
payload: CrawlResultItemType
isChecked: boolean
isPreview: boolean
onCheckChange: (checked: boolean) => void
onPreview: () => void
}
const CrawledResultItem: FC<Props> = ({
isPreview,
payload,
isChecked,
onCheckChange,
onPreview,
}) => {
const { t } = useTranslation()
const handleCheckChange = useCallback(() => {
onCheckChange(!isChecked)
}, [isChecked, onCheckChange])
return (
<div className={cn(isPreview ? 'border-[#D1E0FF] bg-primary-50 shadow-xs' : 'group hover:bg-gray-100', 'rounded-md px-2 py-[5px] cursor-pointer border border-transparent')}>
<div className='flex items-center h-5'>
<Checkbox className='group-hover:border-2 group-hover:border-primary-600 mr-2 shrink-0' checked={isChecked} onCheck={handleCheckChange} />
<div className='grow w-0 truncate text-sm font-medium text-gray-700' title={payload.title}>{payload.title}</div>
<div onClick={onPreview} className='hidden group-hover:flex items-center h-6 px-2 text-xs rounded-md font-medium text-gray-500 uppercase hover:bg-gray-50'>{t('datasetCreation.stepOne.website.preview')}</div>
</div>
<div className='mt-0.5 truncate pl-6 leading-[18px] text-xs font-normal text-gray-500' title={payload.source_url}>{payload.source_url}</div>
</div>
)
}
export default React.memo(CrawledResultItem)

View File

@ -1,87 +0,0 @@
'use client'
import type { FC } from 'react'
import React, { useCallback } from 'react'
import { useTranslation } from 'react-i18next'
import CheckboxWithLabel from './base/checkbox-with-label'
import CrawledResultItem from './crawled-result-item'
import cn from '@/utils/classnames'
import type { CrawlResultItem } from '@/models/datasets'
const I18N_PREFIX = 'datasetCreation.stepOne.website'
interface Props {
className?: string
list: CrawlResultItem[]
checkedList: CrawlResultItem[]
onSelectedChange: (selected: CrawlResultItem[]) => void
onPreview: (payload: CrawlResultItem) => void
usedTime: number
}
const CrawledResult: FC<Props> = ({
className = '',
list,
checkedList,
onSelectedChange,
onPreview,
usedTime,
}) => {
const { t } = useTranslation()
const isCheckAll = checkedList.length === list.length
const handleCheckedAll = useCallback(() => {
if (!isCheckAll)
onSelectedChange(list)
else
onSelectedChange([])
}, [isCheckAll, list, onSelectedChange])
const handleItemCheckChange = useCallback((item: CrawlResultItem) => {
return (checked: boolean) => {
if (checked)
onSelectedChange([...checkedList, item])
else
onSelectedChange(checkedList.filter(checkedItem => checkedItem.source_url !== item.source_url))
}
}, [checkedList, onSelectedChange])
const [previewIndex, setPreviewIndex] = React.useState<number>(-1)
const handlePreview = useCallback((index: number) => {
return () => {
setPreviewIndex(index)
onPreview(list[index])
}
}, [list, onPreview])
return (
<div className={cn(className, 'border-t border-gray-200')}>
<div className='flex items-center justify-between h-[34px] px-4 bg-gray-50 shadow-xs border-b-[0.5px] border-black/8 text-xs font-normal text-gray-700'>
<CheckboxWithLabel
isChecked={isCheckAll}
onChange={handleCheckedAll} label={isCheckAll ? t(`${I18N_PREFIX}.resetAll`) : t(`${I18N_PREFIX}.selectAll`)}
labelClassName='!font-medium'
/>
<div>{t(`${I18N_PREFIX}.scrapTimeInfo`, {
total: list.length,
time: usedTime.toFixed(1),
})}</div>
</div>
<div className='p-2'>
{list.map((item, index) => (
<CrawledResultItem
key={item.source_url}
isPreview={index === previewIndex}
onPreview={handlePreview(index)}
payload={item}
isChecked={checkedList.some(checkedItem => checkedItem.source_url === item.source_url)}
onCheckChange={handleItemCheckChange(item)}
/>
))}
</div>
</div>
)
}
export default React.memo(CrawledResult)

View File

@ -1,37 +0,0 @@
'use client'
import type { FC } from 'react'
import React from 'react'
import { useTranslation } from 'react-i18next'
import cn from '@/utils/classnames'
import { RowStruct } from '@/app/components/base/icons/src/public/other'
interface Props {
className?: string
crawledNum: number
totalNum: number
}
const Crawling: FC<Props> = ({
className = '',
crawledNum,
totalNum,
}) => {
const { t } = useTranslation()
return (
<div className={cn(className, 'border-t border-gray-200')}>
<div className='flex items-center h-[34px] px-4 bg-gray-50 shadow-xs border-b-[0.5px] border-black/8 text-xs font-normal text-gray-700'>
{t('datasetCreation.stepOne.website.totalPageScraped')} {crawledNum}/{totalNum}
</div>
<div className='p-2'>
{['', '', '', ''].map((item, index) => (
<div className='py-[5px]' key={index}>
<RowStruct />
</div>
))}
</div>
</div>
)
}
export default React.memo(Crawling)

View File

@ -2,8 +2,8 @@
import type { FC } from 'react' import type { FC } from 'react'
import React from 'react' import React from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { Settings01 } from '@/app/components/base/icons/src/vender/line/general' import { RiBookOpenLine, RiEqualizer2Line } from '@remixicon/react'
import { BookOpen01 } from '@/app/components/base/icons/src/vender/line/education' import Button from '@/app/components/base/button'
const I18N_PREFIX = 'datasetCreation.stepOne.website' const I18N_PREFIX = 'datasetCreation.stepOne.website'
@ -19,22 +19,23 @@ const Header: FC<Props> = ({
return ( return (
<div className='flex h-6 items-center justify-between'> <div className='flex h-6 items-center justify-between'>
<div className='flex items-center'> <div className='flex items-center'>
<div className='text-base font-medium text-gray-700'>{t(`${I18N_PREFIX}.jinaReaderTitle`)}</div> <div className='text-sm font-semibold text-text-secondary'>{t(`${I18N_PREFIX}.jinaReaderTitle`)}</div>
<div className='ml-2 mr-1 w-px h-3.5 bg-gray-200'></div> <div className='ml-2 mr-2 w-px h-3.5 bg-divider-regular' />
<div <Button className='flex items-center gap-x-[1px] h-6 px-1.5' onClick={onSetting}>
className='p-1 rounded-md hover:bg-black/5 cursor-pointer' <RiEqualizer2Line className='w-3.5 h-3.5 text-components-button-secondary-text' />
onClick={onSetting} <span className='text-components-button-secondary-text text-xs font-medium px-[3px]'>
> {t(`${I18N_PREFIX}.configureJinaReader`)}
<Settings01 className='w-3.5 h-3.5 text-gray-500' /> </span>
</div> </Button>
</div> </div>
<a <a
href='https://jina.ai/reader' href='https://jina.ai/reader'
target='_blank' rel='noopener noreferrer' target='_blank'
className='flex items-center text-xs text-primary-600' rel='noopener noreferrer'
className='inline-flex items-center gap-x-1 text-xs font-medium text-text-accent'
> >
<BookOpen01 className='mr-1 w-3.5 h-3.5 text-primary-600' /> <RiBookOpenLine className='w-3.5 h-3.5 text-text-accent' />
{t(`${I18N_PREFIX}.jinaReaderDoc`)} <span>{t(`${I18N_PREFIX}.jinaReaderDoc`)}</span>
</a> </a>
</div> </div>
) )

View File

@ -9,7 +9,6 @@ import Crawling from '../base/crawling'
import ErrorMessage from '../base/error-message' import ErrorMessage from '../base/error-message'
import Header from './header' import Header from './header'
import Options from './options' import Options from './options'
import cn from '@/utils/classnames'
import { useModalContext } from '@/context/modal-context' import { useModalContext } from '@/context/modal-context'
import Toast from '@/app/components/base/toast' import Toast from '@/app/components/base/toast'
import { checkJinaReaderTaskStatus, createJinaReaderTask } from '@/service/datasets' import { checkJinaReaderTaskStatus, createJinaReaderTask } from '@/service/datasets'
@ -99,7 +98,7 @@ const JinaReader: FC<Props> = ({
isError: false, isError: false,
data: { data: {
...res, ...res,
total: Math.min(res.total, parseFloat(crawlOptions.limit as string)), total: Math.min(res.total, Number.parseFloat(crawlOptions.limit as string)),
}, },
} }
} }
@ -115,7 +114,7 @@ const JinaReader: FC<Props> = ({
// update the progress // update the progress
setCrawlResult({ setCrawlResult({
...res, ...res,
total: Math.min(res.total, parseFloat(crawlOptions.limit as string)), total: Math.min(res.total, Number.parseFloat(crawlOptions.limit as string)),
}) })
onCheckedCrawlResultChange(res.data || []) // default select the crawl result onCheckedCrawlResultChange(res.data || []) // default select the crawl result
await sleep(2500) await sleep(2500)
@ -192,10 +191,10 @@ const JinaReader: FC<Props> = ({
return ( return (
<div> <div>
<Header onSetting={handleSetting} /> <Header onSetting={handleSetting} />
<div className={cn('mt-2 p-4 pb-0 rounded-xl border border-gray-200')}> <div className='mt-2 p-4 pb-0 rounded-xl border border-components-panel-border bg-background-default-subtle'>
<UrlInput onRun={handleRun} isRunning={isRunning} /> <UrlInput onRun={handleRun} isRunning={isRunning} />
<OptionsWrap <OptionsWrap
className={cn('mt-4')} className='mt-4'
controlFoldOptions={controlFoldOptions} controlFoldOptions={controlFoldOptions}
> >
<Options className='mt-2' payload={crawlOptions} onChange={onCrawlOptionsChange} /> <Options className='mt-2' payload={crawlOptions} onChange={onCrawlOptionsChange} />
@ -207,7 +206,7 @@ const JinaReader: FC<Props> = ({
&& <Crawling && <Crawling
className='mt-2' className='mt-2'
crawledNum={crawlResult?.current || 0} crawledNum={crawlResult?.current || 0}
totalNum={crawlResult?.total || parseFloat(crawlOptions.limit as string) || 0} totalNum={crawlResult?.total || Number.parseFloat(crawlOptions.limit as string) || 0}
/>} />}
{showError && ( {showError && (
<ErrorMessage className='rounded-b-xl' title={t(`${I18N_PREFIX}.exceptionErrorTitle`)} errorMsg={crawlErrorMessage} /> <ErrorMessage className='rounded-b-xl' title={t(`${I18N_PREFIX}.exceptionErrorTitle`)} errorMsg={crawlErrorMessage} />
@ -219,7 +218,7 @@ const JinaReader: FC<Props> = ({
checkedList={checkedCrawlResult} checkedList={checkedCrawlResult}
onSelectedChange={onCheckedCrawlResultChange} onSelectedChange={onCheckedCrawlResultChange}
onPreview={onPreview} onPreview={onPreview}
usedTime={parseFloat(crawlResult?.time_consuming as string) || 0} usedTime={Number.parseFloat(crawlResult?.time_consuming as string) || 0}
/> />
} }
</div> </div>

View File

@ -1,24 +0,0 @@
import type { CrawlResultItem } from '@/models/datasets'
const result: CrawlResultItem[] = [
{
title: 'Start the frontend Docker container separately',
markdown: 'Markdown 1',
description: 'Description 1',
source_url: 'https://example.com/1',
},
{
title: 'Advanced Tool Integration',
markdown: 'Markdown 2',
description: 'Description 2',
source_url: 'https://example.com/2',
},
{
title: 'Local Source Code Start | English | Dify',
markdown: 'Markdown 3',
description: 'Description 3',
source_url: 'https://example.com/3',
},
]
export default result

View File

@ -36,12 +36,14 @@ const Options: FC<Props> = ({
label={t(`${I18N_PREFIX}.crawlSubPage`)} label={t(`${I18N_PREFIX}.crawlSubPage`)}
isChecked={payload.crawl_sub_pages} isChecked={payload.crawl_sub_pages}
onChange={handleChange('crawl_sub_pages')} onChange={handleChange('crawl_sub_pages')}
labelClassName='text-[13px] leading-[16px] font-medium text-text-secondary'
/> />
<CheckboxWithLabel <CheckboxWithLabel
label={t(`${I18N_PREFIX}.useSitemap`)} label={t(`${I18N_PREFIX}.useSitemap`)}
isChecked={payload.use_sitemap} isChecked={payload.use_sitemap}
onChange={handleChange('use_sitemap')} onChange={handleChange('use_sitemap')}
tooltip={t(`${I18N_PREFIX}.useSitemapTooltip`) as string} tooltip={t(`${I18N_PREFIX}.useSitemapTooltip`) as string}
labelClassName='text-[13px] leading-[16px] font-medium text-text-secondary'
/> />
<div className='flex justify-between space-x-4'> <div className='flex justify-between space-x-4'>
<Field <Field

View File

@ -37,13 +37,17 @@ const NoData: FC<Props> = ({
return ( return (
<> <>
<div className='max-w-[640px] p-6 rounded-2xl bg-gray-50 mt-4'> <div className='max-w-[640px] p-6 rounded-2xl bg-workflow-process-bg mt-4'>
<div className='flex w-11 h-11 items-center justify-center bg-gray-50 rounded-xl border-[0.5px] border-gray-100 shadow-lg'> <div className='flex w-12 h-12 items-center justify-center bg-components-card-bg rounded-[10px]
border-[0.5px] border-components-card-border shadow-lg shadow-shadow-shadow-5 backdrop-blur-[5px]'>
{currentProvider.emoji} {currentProvider.emoji}
</div> </div>
<div className='my-2'> <div className='mt-2 mb-1 pt-1 pb-3 flex flex-col gap-y-1'>
<span className='text-gray-700 font-semibold'>{currentProvider.title}<Icon3Dots className='inline relative -top-3 -left-1.5' /></span> <span className='text-text-secondary system-md-semibold'>
<div className='mt-1 pb-3 text-gray-500 text-[13px] font-normal'> {currentProvider.title}
<Icon3Dots className='inline relative -top-2.5 -left-1.5' />
</span>
<div className='text-text-tertiary system-sm-regular'>
{currentProvider.description} {currentProvider.description}
</div> </div>
</div> </div>

View File

@ -20,19 +20,19 @@ const WebsitePreview = ({
return ( return (
<div className={cn(s.filePreview, 'h-full')}> <div className={cn(s.filePreview, 'h-full')}>
<div className={cn(s.previewHeader)}> <div className={cn(s.previewHeader)}>
<div className={cn(s.title)}> <div className={cn(s.title, 'title-md-semi-bold')}>
<span>{t('datasetCreation.stepOne.pagePreview')}</span> <span>{t('datasetCreation.stepOne.pagePreview')}</span>
<div className='flex items-center justify-center w-6 h-6 cursor-pointer' onClick={hidePreview}> <div className='flex items-center justify-center w-6 h-6 cursor-pointer' onClick={hidePreview}>
<XMarkIcon className='h-4 w-4'></XMarkIcon> <XMarkIcon className='h-4 w-4'></XMarkIcon>
</div> </div>
</div> </div>
<div className='leading-5 text-sm font-medium text-gray-900 break-words'> <div className='title-sm-semi-bold text-text-primary break-words'>
{payload.title} {payload.title}
</div> </div>
<div className='truncate leading-[18px] text-xs font-normal text-gray-500' title={payload.source_url}>{payload.source_url}</div> <div className='truncate system-xs-medium text-text-tertiary' title={payload.source_url}>{payload.source_url}</div>
</div> </div>
<div className={cn(s.previewContent)}> <div className={cn(s.previewContent, 'body-md-regular')}>
<div className={cn(s.fileContent, 'body-md-regular')}>{payload.markdown}</div> <div className={cn(s.fileContent)}>{payload.markdown}</div>
</div> </div>
</div> </div>
) )

View File

@ -165,7 +165,7 @@ const ChildSegmentList: FC<IChildSegmentCardProps> = ({
onDelete={() => onDelete?.(childChunk.segment_id, childChunk.id)} onDelete={() => onDelete?.(childChunk.segment_id, childChunk.id)}
labelClassName={focused ? 'bg-state-accent-solid text-text-primary-on-surface' : ''} labelClassName={focused ? 'bg-state-accent-solid text-text-primary-on-surface' : ''}
labelInnerClassName={'text-[10px] font-semibold align-bottom leading-6'} labelInnerClassName={'text-[10px] font-semibold align-bottom leading-6'}
contentClassName={classNames('!leading-6', focused ? 'bg-state-accent-hover-alt text-text-primary' : '')} contentClassName={classNames('!leading-6', focused ? 'bg-state-accent-hover-alt text-text-primary' : 'text-text-secondary')}
showDivider={false} showDivider={false}
onClick={(e) => { onClick={(e) => {
e.stopPropagation() e.stopPropagation()

View File

@ -17,7 +17,7 @@ const Textarea: FC<IContentProps> = React.memo(({
return ( return (
<textarea <textarea
className={classNames( className={classNames(
'disabled:bg-transparent inset-0 outline-none border-none appearance-none resize-none w-full overflow-y-auto', 'bg-transparent inset-0 outline-none border-none appearance-none resize-none w-full overflow-y-auto',
className, className,
)} )}
placeholder={placeholder} placeholder={placeholder}
@ -83,7 +83,7 @@ const AutoResizeTextArea: FC<IAutoResizeTextAreaProps> = React.memo(({
<textarea <textarea
ref={textareaRef} ref={textareaRef}
className={classNames( className={classNames(
'disabled:bg-transparent inset-0 outline-none border-none appearance-none resize-none w-full', 'bg-transparent inset-0 outline-none border-none appearance-none resize-none w-full',
className, className,
)} )}
style={{ style={{

View File

@ -103,15 +103,13 @@ const SegmentAdd: FC<ISegmentAddProps> = ({
manualClose manualClose
trigger='click' trigger='click'
htmlContent={ htmlContent={
<div className='w-full p-1'>
<button <button
type='button' type='button'
className='w-full py-1.5 px-2 flex items-center hover:bg-state-base-hover rounded-lg text-text-secondary system-md-regular' className='w-full py-1.5 px-2 flex items-center rounded-lg text-text-secondary system-md-regular'
onClick={showBatchModal} onClick={showBatchModal}
> >
{t('datasetDocuments.list.action.batchAdd')} {t('datasetDocuments.list.action.batchAdd')}
</button> </button>
</div>
} }
btnElement={ btnElement={
<div className='flex justify-center items-center' > <div className='flex justify-center items-center' >

View File

@ -57,7 +57,7 @@ const DocumentSettings = ({ datasetId, documentId }: DocumentSettingsProps) => {
return ( return (
<div className='flex' style={{ height: 'calc(100vh - 56px)' }}> <div className='flex' style={{ height: 'calc(100vh - 56px)' }}>
<div className="grow bg-white"> <div className="grow">
{!documentDetail && <Loading type='app' />} {!documentDetail && <Loading type='app' />}
{dataset && documentDetail && ( {dataset && documentDetail && (
<StepTwo <StepTwo

View File

@ -16,7 +16,6 @@ import { useContext } from 'use-context-selector'
import { useRouter } from 'next/navigation' import { useRouter } from 'next/navigation'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import dayjs from 'dayjs' import dayjs from 'dayjs'
import { Edit03 } from '../../base/icons/src/vender/solid/general'
import { Globe01 } from '../../base/icons/src/vender/line/mapsAndTravel' import { Globe01 } from '../../base/icons/src/vender/line/mapsAndTravel'
import ChunkingModeLabel from '../common/chunking-mode-label' import ChunkingModeLabel from '../common/chunking-mode-label'
import FileTypeIcon from '../../base/file-uploader/file-type-icon' import FileTypeIcon from '../../base/file-uploader/file-type-icon'
@ -343,7 +342,7 @@ export const OperationAction: FC<{
position='br' position='br'
btnElement={ btnElement={
<div className={cn(s.commonIcon)}> <div className={cn(s.commonIcon)}>
<RiMoreFill className='w-4 h-4 text-text-components-button-secondary-text' /> <RiMoreFill className='w-4 h-4 text-components-button-secondary-text' />
</div> </div>
} }
btnClassName={open => cn(isListScene ? s.actionIconWrapperList : s.actionIconWrapperDetail, open ? '!hover:bg-state-base-hover !shadow-none' : '!bg-transparent')} btnClassName={open => cn(isListScene ? s.actionIconWrapperList : s.actionIconWrapperDetail, open ? '!hover:bg-state-base-hover !shadow-none' : '!bg-transparent')}
@ -598,7 +597,7 @@ const DocumentList: FC<IDocumentListProps> = ({
handleShowRenameModal(doc) handleShowRenameModal(doc)
}} }}
> >
<Edit03 className='w-4 h-4 text-text-tertiary' /> <RiEditLine className='w-4 h-4 text-text-tertiary' />
</div> </div>
</Tooltip> </Tooltip>
</div> </div>

View File

@ -59,7 +59,7 @@ const RenameModal: FC<Props> = ({
isShow isShow
onClose={onClose} onClose={onClose}
> >
<div className={'mt-6 font-medium text-sm leading-[21px] text-gray-900'}>{t('datasetDocuments.list.table.name')}</div> <div className={'mt-6 font-medium text-sm leading-[21px] text-text-primary'}>{t('datasetDocuments.list.table.name')}</div>
<Input <Input
className='mt-2 h-10' className='mt-2 h-10'
value={newName} value={newName}

View File

@ -9,7 +9,7 @@
max-width: 200px; max-width: 200px;
} }
.actionIconWrapperList { .actionIconWrapperList {
@apply h-6 w-6 rounded-md border-none p-1 hover:bg-gray-100 !important; @apply h-6 w-6 rounded-md border-none p-1 hover:bg-state-base-hover !important;
} }
.actionIconWrapperDetail { .actionIconWrapperDetail {
@apply p-2 bg-components-button-secondary-bg hover:bg-components-button-secondary-bg-hover @apply p-2 bg-components-button-secondary-bg hover:bg-components-button-secondary-bg-hover
@ -17,7 +17,7 @@
shadow-xs shadow-shadow-shadow-3 !important; shadow-xs shadow-shadow-shadow-3 !important;
} }
.actionItem { .actionItem {
@apply h-9 py-2 px-3 mx-1 flex items-center gap-2 hover:bg-gray-100 rounded-lg cursor-pointer; @apply h-9 py-2 px-3 mx-1 flex items-center gap-2 hover:bg-state-base-hover rounded-lg cursor-pointer;
} }
.deleteActionItem { .deleteActionItem {
@apply hover:bg-state-destructive-hover !important; @apply hover:bg-state-destructive-hover !important;

View File

@ -55,7 +55,7 @@ const ResultItem: FC<Props> = ({
{isParentChildRetrieval && ( {isParentChildRetrieval && (
<div className='mt-1'> <div className='mt-1'>
<div <div
className={cn('inline-flex items-center h-6 space-x-0.5 text-text-secondary select-none rounded-lg cursor-pointer', isFold && 'pl-1 bg-[linear-gradient(90deg,_rgba(200,_206,_218,_0.20)_0%,_rgba(200,_206,_218,_0.04)_100%)]')} className={cn('inline-flex items-center h-6 space-x-0.5 text-text-secondary select-none rounded-lg cursor-pointer', isFold && 'pl-1 bg-workflow-process-bg')}
onClick={(e) => { onClick={(e) => {
e.stopPropagation() e.stopPropagation()
toggleFold() toggleFold()

View File

@ -6,7 +6,7 @@ import useSWR from 'swr'
import { omit } from 'lodash-es' import { omit } from 'lodash-es'
import { useBoolean } from 'ahooks' import { useBoolean } from 'ahooks'
import { useContext } from 'use-context-selector' import { useContext } from 'use-context-selector'
import { RiApps2Line, RiFocus2Line } from '@remixicon/react' import { RiApps2Line, RiFocus2Line, RiHistoryLine } from '@remixicon/react'
import Textarea from './textarea' import Textarea from './textarea'
import s from './style.module.css' import s from './style.module.css'
import ModifyRetrievalModal from './modify-retrieval-modal' import ModifyRetrievalModal from './modify-retrieval-modal'
@ -34,11 +34,11 @@ type Props = {
const RecordsEmpty: FC = () => { const RecordsEmpty: FC = () => {
const { t } = useTranslation() const { t } = useTranslation()
return <div className='bg-gray-50 rounded-2xl p-5'> return <div className='bg-workflow-process-bg rounded-2xl p-5'>
<div className={s.clockWrapper}> <div className='flex items-center justify-center w-10 h-10 p-1 rounded-[10px] border-[0.5px] border-components-card-border bg-components-card-bg shadow-lg shadow-shadow-shadow-5 backdrop-blur-[5px]'>
<div className={cn(s.clockIcon, 'w-5 h-5')}></div> <RiHistoryLine className='w-5 h-5 text-text-tertiary' />
</div> </div>
<div className='my-2 text-gray-500 text-sm'>{t('datasetHitTesting.noRecentTip')}</div> <div className='my-2 text-text-tertiary text-[13px] leading-4 font-medium'>{t('datasetHitTesting.noRecentTip')}</div>
</div> </div>
} }

View File

@ -59,33 +59,41 @@ const ModifyRetrievalModal: FC<Props> = ({
return ( return (
<div <div
className='w-full flex flex-col bg-white border-[0.5px] border-gray-200 rounded-xl shadow-xl' className='w-full flex flex-col bg-components-panel-bg border-[0.5px] border-components-panel-border rounded-2xl shadow-2xl shadow-shadow-shadow-9'
style={{ style={{
height: 'calc(100vh - 72px)', height: 'calc(100vh - 72px)',
}} }}
ref={ref} ref={ref}
> >
<div className='shrink-0 flex justify-between items-center pl-6 pr-5 h-14 border-b border-b-gray-100'> <div className='shrink-0 flex justify-between pt-3.5 pb-1 px-3 h-15'>
<div className='text-base font-semibold text-gray-900'> <div className='text-base font-semibold text-text-primary'>
<div>{t('datasetSettings.form.retrievalSetting.title')}</div> <div>{t('datasetSettings.form.retrievalSetting.title')}</div>
<div className='leading-[18px] text-xs font-normal text-gray-500'> <div className='leading-[18px] text-xs font-normal text-text-tertiary'>
<a target='_blank' rel='noopener noreferrer' href='https://docs.dify.ai/guides/knowledge-base/create-knowledge-and-upload-documents#id-4-retrieval-settings' className='text-text-accent'>{t('datasetSettings.form.retrievalSetting.learnMore')}</a> <a
target='_blank'
rel='noopener noreferrer'
href='https://docs.dify.ai/guides/knowledge-base/create-knowledge-and-upload-documents#id-4-retrieval-settings'
className='text-text-accent'
>
{t('datasetSettings.form.retrievalSetting.learnMore')}
</a>
{t('datasetSettings.form.retrievalSetting.description')} {t('datasetSettings.form.retrievalSetting.description')}
</div> </div>
</div> </div>
<div className='flex items-center'> <div className='flex'>
<div <div
onClick={onHide} onClick={onHide}
className='flex justify-center items-center w-6 h-6 cursor-pointer' className='flex justify-center items-center w-8 h-8 cursor-pointer'
> >
<RiCloseLine className='w-4 h-4 text-gray-500' /> <RiCloseLine className='w-4 h-4 text-text-tertiary' />
</div> </div>
</div> </div>
</div> </div>
<div className='p-6 border-b' style={{ <div className='px-4 py-2'>
borderBottom: 'rgba(0, 0, 0, 0.05)', <div className='mb-1 text-text-secondary text-[13px] leading-6 font-semibold'>
}}> {t('datasetSettings.form.retrievalSetting.method')}
</div>
{indexMethod === 'high_quality' {indexMethod === 'high_quality'
? ( ? (
<RetrievalMethodConfig <RetrievalMethodConfig
@ -100,12 +108,7 @@ const ModifyRetrievalModal: FC<Props> = ({
/> />
)} )}
</div> </div>
<div <div className='flex justify-end p-4 pt-2'>
className='flex justify-end pt-6 px-6 border-t'
style={{
borderColor: 'rgba(0, 0, 0, 0.05)',
}}
>
<Button className='mr-2 flex-shrink-0' onClick={onHide}>{t('common.operation.cancel')}</Button> <Button className='mr-2 flex-shrink-0' onClick={onHide}>{t('common.operation.cancel')}</Button>
<Button variant='primary' className='flex-shrink-0' onClick={handleSave} >{t('common.operation.save')}</Button> <Button variant='primary' className='flex-shrink-0' onClick={handleSave} >{t('common.operation.save')}</Button>
</div> </div>

View File

@ -15,7 +15,7 @@ import { asyncRunSafe } from '@/utils'
import { RETRIEVE_METHOD, type RetrievalConfig } from '@/types/app' import { RETRIEVE_METHOD, type RetrievalConfig } from '@/types/app'
import promptS from '@/app/components/app/configuration/config-prompt/style.module.css' import promptS from '@/app/components/app/configuration/config-prompt/style.module.css'
interface TextAreaWithButtonIProps { type TextAreaWithButtonIProps = {
datasetId: string datasetId: string
onUpdateList: () => void onUpdateList: () => void
setHitResult: (res: HitTestingResponse) => void setHitResult: (res: HitTestingResponse) => void
@ -108,7 +108,7 @@ const TextAreaWithButton = ({
return ( return (
<> <>
<div className={cn('relative rounded-xl', promptS.gradientBorder)}> <div className={cn('relative rounded-xl', promptS.gradientBorder)}>
<div className='relative pt-1.5 rounded-tl-xl rounded-tr-xl bg-background-section-burn'> <div className='relative pt-1.5 rounded-t-xl bg-background-section-burn'>
<div className="pl-4 pr-1.5 pb-1 flex justify-between h-8 items-center"> <div className="pl-4 pr-1.5 pb-1 flex justify-between h-8 items-center">
<span className="text-text-secondary font-semibold text-[13px] leading-4 uppercase"> <span className="text-text-secondary font-semibold text-[13px] leading-4 uppercase">
{t('datasetHitTesting.input.title')} {t('datasetHitTesting.input.title')}
@ -145,11 +145,11 @@ const TextAreaWithButton = ({
/> />
) )
} }
<div className='h-2 rounded-tl-xl rounded-tr-xl bg-background-default'></div> <div className='h-2 rounded-t-xl bg-background-default'></div>
</div> </div>
<div className='px-4 pb-11 bg-background-default rounded-b-xl'> <div className='px-4 pb-11 bg-background-default rounded-b-xl'>
<textarea <textarea
className='h-[220px] border-none resize-none font-normal caret-primary-600 text-text-secondary text-sm w-full focus-visible:outline-none placeholder:text-gray-300 placeholder:text-sm placeholder:font-normal' className='h-[220px] border-none resize-none font-normal caret-[#295EFF] text-text-secondary text-sm w-full focus-visible:outline-none placeholder:text-components-input-text-placeholder placeholder:text-sm placeholder:font-normal bg-transparent'
value={text} value={text}
onChange={handleTextChange} onChange={handleTextChange}
placeholder={t('datasetHitTesting.input.placeholder') as string} placeholder={t('datasetHitTesting.input.placeholder') as string}

View File

@ -76,31 +76,40 @@ const PermissionSelector = ({ disabled, permission, value, memberList, onChange,
onClick={() => !disabled && setOpen(v => !v)} onClick={() => !disabled && setOpen(v => !v)}
className='block' className='block'
> >
{isOnlyMe && ( <div className={cn('flex items-center px-3 py-[6px] rounded-lg bg-components-input-bg-normal cursor-pointer hover:bg-state-base-hover-alt',
<div className={cn('flex items-center px-3 py-[6px] rounded-lg bg-gray-100 cursor-pointer hover:bg-gray-200', open && 'bg-gray-200', disabled && 'hover:!bg-gray-100 !cursor-default')}> open && 'bg-state-base-hover-alt',
disabled && '!bg-components-input-bg-disabled hover:!bg-components-input-bg-disabled !cursor-not-allowed',
)}>
{
isOnlyMe && (
<>
<Avatar avatar={userProfile.avatar_url} name={userProfile.name} className='shrink-0 mr-2' size={24} /> <Avatar avatar={userProfile.avatar_url} name={userProfile.name} className='shrink-0 mr-2' size={24} />
<div className='grow mr-2 text-gray-900 text-sm leading-5'>{t('datasetSettings.form.permissionsOnlyMe')}</div> <div className='grow mr-2 text-components-input-text-filled text-sm leading-5'>{t('datasetSettings.form.permissionsOnlyMe')}</div>
{!disabled && <RiArrowDownSLine className='shrink-0 w-4 h-4 text-gray-700' />} </>
</div> )
)} }
{isAllTeamMembers && ( {
<div className={cn('flex items-center px-3 py-[6px] rounded-lg bg-gray-100 cursor-pointer hover:bg-gray-200', open && 'bg-gray-200')}> isAllTeamMembers && (
<>
<div className='mr-2 flex items-center justify-center w-6 h-6 rounded-lg bg-[#EEF4FF]'> <div className='mr-2 flex items-center justify-center w-6 h-6 rounded-lg bg-[#EEF4FF]'>
<Users01 className='w-3.5 h-3.5 text-[#444CE7]' /> <Users01 className='w-3.5 h-3.5 text-[#444CE7]' />
</div> </div>
<div className='grow mr-2 text-text-primary text-sm leading-5'>{t('datasetSettings.form.permissionsAllMember')}</div> <div className='grow mr-2 text-components-input-text-filled text-sm leading-5'>{t('datasetSettings.form.permissionsAllMember')}</div>
{!disabled && <RiArrowDownSLine className='shrink-0 w-4 h-4 text-text-secondary' />} </>
</div> )
)} }
{isPartialMembers && ( {
<div className={cn('flex items-center px-3 py-[6px] rounded-lg bg-gray-100 cursor-pointer hover:bg-gray-200', open && 'bg-gray-200')}> isPartialMembers && (
<>
<div className='mr-2 flex items-center justify-center w-6 h-6 rounded-lg bg-[#EEF4FF]'> <div className='mr-2 flex items-center justify-center w-6 h-6 rounded-lg bg-[#EEF4FF]'>
<Users01 className='w-3.5 h-3.5 text-[#444CE7]' /> <Users01 className='w-3.5 h-3.5 text-[#444CE7]' />
</div> </div>
<div title={selectedMembers} className='grow mr-2 text-text-primary text-sm leading-5 truncate'>{selectedMembers}</div> <div title={selectedMembers} className='grow mr-2 text-components-input-text-filled text-sm leading-5 truncate'>{selectedMembers}</div>
{!disabled && <RiArrowDownSLine className='shrink-0 w-4 h-4 text-text-secondary' />} </>
)
}
<RiArrowDownSLine className={cn('shrink-0 w-4 h-4 text-text-secondary', disabled && '!text-components-input-text-placeholder')} />
</div> </div>
)}
</PortalToFollowElemTrigger> </PortalToFollowElemTrigger>
<PortalToFollowElemContent className='z-[1002]'> <PortalToFollowElemContent className='z-[1002]'>
<div className='relative w-[480px] rounded-lg border-[0.5px] border-components-panel-border bg-components-panel-bg-blur backdrop-blur-sm shadow-lg'> <div className='relative w-[480px] rounded-lg border-[0.5px] border-components-panel-border bg-components-panel-bg-blur backdrop-blur-sm shadow-lg'>

View File

@ -19,10 +19,10 @@ import { useModalContext } from '@/context/modal-context'
import { getDocDownloadUrl } from '@/service/common' import { getDocDownloadUrl } from '@/service/common'
enum DocName { enum DocName {
'SOC2_Type_I' = 'SOC2_Type_I', SOC2_Type_I = 'SOC2_Type_I',
'SOC2_Type_II' = 'SOC2_Type_II', SOC2_Type_II = 'SOC2_Type_II',
'ISO_27001' = 'ISO_27001', ISO_27001 = 'ISO_27001',
'GDPR' = 'GDPR', GDPR = 'GDPR',
} }
type UpgradeOrDownloadProps = { type UpgradeOrDownloadProps = {
@ -114,8 +114,8 @@ export default function Compliance() {
cn('flex items-center pl-3 pr-2 py-2 h-9 w-full group hover:bg-state-base-hover rounded-lg gap-1', cn('flex items-center pl-3 pr-2 py-2 h-9 w-full group hover:bg-state-base-hover rounded-lg gap-1',
open && 'bg-state-base-hover', open && 'bg-state-base-hover',
)}> )}>
<RiVerifiedBadgeLine className='flex-shrink-0 size-4 text-text-tertiary' /> <RiVerifiedBadgeLine className='shrink-0 size-4 text-text-tertiary' />
<div className='flex-grow text-left system-md-regular text-text-secondary px-1'>{t('common.userProfile.compliance')}</div> <div className='grow text-left system-md-regular text-text-secondary px-1'>{t('common.userProfile.compliance')}</div>
<RiArrowRightSLine className='shrink-0 size-[14px] text-text-tertiary' /> <RiArrowRightSLine className='shrink-0 size-[14px] text-text-tertiary' />
</Menu.Button> </Menu.Button>
<Transition <Transition
@ -140,8 +140,8 @@ export default function Compliance() {
className={cn(itemClassName, 'group justify-between', className={cn(itemClassName, 'group justify-between',
active && 'bg-state-base-hover', active && 'bg-state-base-hover',
)}> )}>
<Soc2 className='flex-shrink-0 size-7' /> <Soc2 className='shrink-0 size-7' />
<div className='system-md-regular flex-grow text-text-secondary px-1 truncate'>{t('common.compliance.soc2Type1')}</div> <div className='system-md-regular grow text-text-secondary px-1 truncate'>{t('common.compliance.soc2Type1')}</div>
<UpgradeOrDownload doc_name={DocName.SOC2_Type_I} /> <UpgradeOrDownload doc_name={DocName.SOC2_Type_I} />
</div>} </div>}
</Menu.Item> </Menu.Item>
@ -150,8 +150,8 @@ export default function Compliance() {
className={cn(itemClassName, 'group justify-between', className={cn(itemClassName, 'group justify-between',
active && 'bg-state-base-hover', active && 'bg-state-base-hover',
)}> )}>
<Soc2 className='flex-shrink-0 size-7' /> <Soc2 className='shrink-0 size-7' />
<div className='system-md-regular flex-grow text-text-secondary px-1 truncate'>{t('common.compliance.soc2Type2')}</div> <div className='system-md-regular grow text-text-secondary px-1 truncate'>{t('common.compliance.soc2Type2')}</div>
<UpgradeOrDownload doc_name={DocName.SOC2_Type_II} /> <UpgradeOrDownload doc_name={DocName.SOC2_Type_II} />
</div>} </div>}
</Menu.Item> </Menu.Item>
@ -160,8 +160,8 @@ export default function Compliance() {
className={cn(itemClassName, 'group justify-between', className={cn(itemClassName, 'group justify-between',
active && 'bg-state-base-hover', active && 'bg-state-base-hover',
)}> )}>
<Iso className='flex-shrink-0 size-7' /> <Iso className='shrink-0 size-7' />
<div className='system-md-regular flex-grow text-text-secondary px-1 truncate'>{t('common.compliance.iso27001')}</div> <div className='system-md-regular grow text-text-secondary px-1 truncate'>{t('common.compliance.iso27001')}</div>
<UpgradeOrDownload doc_name={DocName.ISO_27001} /> <UpgradeOrDownload doc_name={DocName.ISO_27001} />
</div>} </div>}
</Menu.Item> </Menu.Item>
@ -170,8 +170,8 @@ export default function Compliance() {
className={cn(itemClassName, 'group justify-between', className={cn(itemClassName, 'group justify-between',
active && 'bg-state-base-hover', active && 'bg-state-base-hover',
)}> )}>
<Gdpr className='flex-shrink-0 size-7' /> <Gdpr className='shrink-0 size-7' />
<div className='system-md-regular flex-grow text-text-secondary px-1 truncate'>{t('common.compliance.gdpr')}</div> <div className='system-md-regular grow text-text-secondary px-1 truncate'>{t('common.compliance.gdpr')}</div>
<UpgradeOrDownload doc_name={DocName.GDPR} /> <UpgradeOrDownload doc_name={DocName.GDPR} />
</div>} </div>}
</Menu.Item> </Menu.Item>

View File

@ -27,8 +27,8 @@ export default function Support() {
cn('flex items-center pl-3 pr-2 py-2 h-9 w-full group hover:bg-state-base-hover rounded-lg gap-1', cn('flex items-center pl-3 pr-2 py-2 h-9 w-full group hover:bg-state-base-hover rounded-lg gap-1',
open && 'bg-state-base-hover', open && 'bg-state-base-hover',
)}> )}>
<RiQuestionLine className='flex-shrink-0 size-4 text-text-tertiary' /> <RiQuestionLine className='shrink-0 size-4 text-text-tertiary' />
<div className='flex-grow text-left system-md-regular text-text-secondary px-1'>{t('common.userProfile.support')}</div> <div className='grow text-left system-md-regular text-text-secondary px-1'>{t('common.userProfile.support')}</div>
<RiArrowRightSLine className='shrink-0 size-[14px] text-text-tertiary' /> <RiArrowRightSLine className='shrink-0 size-[14px] text-text-tertiary' />
</Menu.Button> </Menu.Button>
<Transition <Transition
@ -55,9 +55,9 @@ export default function Support() {
)} )}
href={mailToSupport(userProfile.email, plan.type, langeniusVersionInfo.current_version)} href={mailToSupport(userProfile.email, plan.type, langeniusVersionInfo.current_version)}
target='_blank' rel='noopener noreferrer'> target='_blank' rel='noopener noreferrer'>
<RiMailSendLine className='flex-shrink-0 size-4 text-text-tertiary' /> <RiMailSendLine className='shrink-0 size-4 text-text-tertiary' />
<div className='flex-grow system-md-regular text-text-secondary px-1'>{t('common.userProfile.emailSupport')}</div> <div className='grow system-md-regular text-text-secondary px-1'>{t('common.userProfile.emailSupport')}</div>
<RiArrowRightUpLine className='flex-shrink-0 size-[14px] text-text-tertiary' /> <RiArrowRightUpLine className='shrink-0 size-[14px] text-text-tertiary' />
</a>} </a>}
</Menu.Item>} </Menu.Item>}
<Menu.Item> <Menu.Item>
@ -67,9 +67,9 @@ export default function Support() {
)} )}
href='https://github.com/langgenius/dify/discussions/categories/feedbacks' href='https://github.com/langgenius/dify/discussions/categories/feedbacks'
target='_blank' rel='noopener noreferrer'> target='_blank' rel='noopener noreferrer'>
<RiFeedbackLine className='flex-shrink-0 size-4 text-text-tertiary' /> <RiFeedbackLine className='shrink-0 size-4 text-text-tertiary' />
<div className='flex-grow system-md-regular text-text-secondary px-1'>{t('common.userProfile.communityFeedback')}</div> <div className='grow system-md-regular text-text-secondary px-1'>{t('common.userProfile.communityFeedback')}</div>
<RiArrowRightUpLine className='flex-shrink-0 size-[14px] text-text-tertiary' /> <RiArrowRightUpLine className='shrink-0 size-[14px] text-text-tertiary' />
</Link>} </Link>}
</Menu.Item> </Menu.Item>
<Menu.Item> <Menu.Item>
@ -79,9 +79,9 @@ export default function Support() {
)} )}
href='https://discord.gg/5AEfbxcd9k' href='https://discord.gg/5AEfbxcd9k'
target='_blank' rel='noopener noreferrer'> target='_blank' rel='noopener noreferrer'>
<RiDiscordLine className='flex-shrink-0 size-4 text-text-tertiary' /> <RiDiscordLine className='shrink-0 size-4 text-text-tertiary' />
<div className='flex-grow system-md-regular text-text-secondary px-1'>{t('common.userProfile.community')}</div> <div className='grow system-md-regular text-text-secondary px-1'>{t('common.userProfile.community')}</div>
<RiArrowRightUpLine className='flex-shrink-0 size-[14px] text-text-tertiary' /> <RiArrowRightUpLine className='shrink-0 size-[14px] text-text-tertiary' />
</Link>} </Link>}
</Menu.Item> </Menu.Item>
</div> </div>

View File

@ -17,7 +17,7 @@ import { BubbleX, Env } from '@/app/components/base/icons/src/vender/line/others
import { checkKeys } from '@/utils/var' import { checkKeys } from '@/utils/var'
import { FILE_STRUCT } from '@/app/components/workflow/constants' import { FILE_STRUCT } from '@/app/components/workflow/constants'
interface ObjectChildrenProps { type ObjectChildrenProps = {
nodeId: string nodeId: string
title: string title: string
data: Var[] data: Var[]
@ -28,7 +28,7 @@ interface ObjectChildrenProps {
isSupportFileVar?: boolean isSupportFileVar?: boolean
} }
interface ItemProps { type ItemProps = {
nodeId: string nodeId: string
title: string title: string
objPath: string[] objPath: string[]
@ -227,7 +227,7 @@ const ObjectChildren: FC<ObjectChildrenProps> = ({
) )
} }
interface Props { type Props = {
hideSearch?: boolean hideSearch?: boolean
searchBoxClassName?: string searchBoxClassName?: string
vars: NodeOutPutVar[] vars: NodeOutPutVar[]

View File

@ -67,6 +67,8 @@ const translation = {
jinaReaderNotConfigured: 'Jina Reader is not configured', jinaReaderNotConfigured: 'Jina Reader is not configured',
jinaReaderNotConfiguredDescription: 'Set up Jina Reader by entering your free API key for access.', jinaReaderNotConfiguredDescription: 'Set up Jina Reader by entering your free API key for access.',
configure: 'Configure', configure: 'Configure',
configureFirecrawl: 'Configure Firecrawl',
configureJinaReader: 'Configure Jina Reader',
run: 'Run', run: 'Run',
firecrawlTitle: 'Extract web content with 🔥Firecrawl', firecrawlTitle: 'Extract web content with 🔥Firecrawl',
firecrawlDoc: 'Firecrawl docs', firecrawlDoc: 'Firecrawl docs',

View File

@ -26,6 +26,7 @@ const translation = {
embeddingModelTipLink: 'Settings', embeddingModelTipLink: 'Settings',
retrievalSetting: { retrievalSetting: {
title: 'Retrieval Setting', title: 'Retrieval Setting',
method: 'Retrieval Method',
learnMore: 'Learn more', learnMore: 'Learn more',
description: ' about retrieval method.', description: ' about retrieval method.',
longDescription: ' about retrieval method, you can change this at any time in the Knowledge settings.', longDescription: ' about retrieval method, you can change this at any time in the Knowledge settings.',

View File

@ -67,6 +67,8 @@ const translation = {
jinaReaderNotConfigured: 'Jina Reader 未配置', jinaReaderNotConfigured: 'Jina Reader 未配置',
jinaReaderNotConfiguredDescription: '请配置 Jina Reader 的免费 API 密钥以访问它。', jinaReaderNotConfiguredDescription: '请配置 Jina Reader 的免费 API 密钥以访问它。',
configure: '配置', configure: '配置',
configureFirecrawl: '配置 Firecrawl',
configureJinaReader: '配置 Jina Reader',
run: '运行', run: '运行',
firecrawlTitle: '使用 🔥Firecrawl 提取网页内容', firecrawlTitle: '使用 🔥Firecrawl 提取网页内容',
firecrawlDoc: 'Firecrawl 文档', firecrawlDoc: 'Firecrawl 文档',

View File

@ -26,6 +26,7 @@ const translation = {
embeddingModelTipLink: '设置', embeddingModelTipLink: '设置',
retrievalSetting: { retrievalSetting: {
title: '检索设置', title: '检索设置',
method: '检索方法',
learnMore: '了解更多', learnMore: '了解更多',
description: '关于检索方法。', description: '关于检索方法。',
longDescription: '关于检索方法,您可以随时在知识库设置中更改此设置。', longDescription: '关于检索方法,您可以随时在知识库设置中更改此设置。',

View File

@ -113,6 +113,7 @@ const config = {
'dataset-option-card-purple-gradient': 'var(--color-dataset-option-card-purple-gradient)', 'dataset-option-card-purple-gradient': 'var(--color-dataset-option-card-purple-gradient)',
'dataset-option-card-orange-gradient': 'var(--color-dataset-option-card-orange-gradient)', 'dataset-option-card-orange-gradient': 'var(--color-dataset-option-card-orange-gradient)',
'dataset-chunk-list-mask-bg': 'var(--color-dataset-chunk-list-mask-bg)', 'dataset-chunk-list-mask-bg': 'var(--color-dataset-chunk-list-mask-bg)',
'dataset-warning-message-bg': 'var(--color-dataset-warning-message-bg)',
'price-premium-badge-background': 'var(--color-premium-badge-background)', 'price-premium-badge-background': 'var(--color-premium-badge-background)',
'premium-yearly-tip-text-background': 'var(--color-premium-yearly-tip-text-background)', 'premium-yearly-tip-text-background': 'var(--color-premium-yearly-tip-text-background)',
'price-premium-text-background': 'var(--color-premium-text-background)', 'price-premium-text-background': 'var(--color-premium-text-background)',

View File

@ -38,7 +38,7 @@ html[data-theme="dark"] {
rgba(240, 68, 56, 0.3) 0%, rgba(240, 68, 56, 0.3) 0%,
rgba(0, 0, 0, 0) 100%); rgba(0, 0, 0, 0) 100%);
--color-toast-info-bg: linear-gradient(92deg, --color-toast-info-bg: linear-gradient(92deg,
rgba(11, 165, 236, 0.3) 0%), rgba(11, 165, 236, 0.3) 0%);
--color-account-teams-bg: linear-gradient(271deg, --color-account-teams-bg: linear-gradient(271deg,
rgba(34, 34, 37, 0.9) -0.1%, rgba(34, 34, 37, 0.9) -0.1%,
rgba(29, 29, 32, 0.9) 98.26%); rgba(29, 29, 32, 0.9) 98.26%);
@ -60,4 +60,5 @@ html[data-theme="dark"] {
--mask-top2bottom-gray-50-to-transparent: linear-gradient(180deg, --mask-top2bottom-gray-50-to-transparent: linear-gradient(180deg,
rgba(24, 24, 27, 0.08) 0%, rgba(24, 24, 27, 0.08) 0%,
rgba(0, 0, 0, 0) 100%); rgba(0, 0, 0, 0) 100%);
--color-dataset-warning-message-bg: linear-gradient(92deg, rgba(247, 144, 9, 0.30) 0%, rgba(0, 0, 0, 0.00) 100%);
} }

View File

@ -60,4 +60,5 @@ html[data-theme="light"] {
rgba(0, 0, 0, 0.00) 0%, rgba(0, 0, 0, 0.00) 0%,
rgba(16, 24, 40, 0.01) 8%, rgba(16, 24, 40, 0.01) 8%,
rgba(16, 24, 40, 0.18) 100%); rgba(16, 24, 40, 0.18) 100%);
--color-dataset-warning-message-bg: linear-gradient(92deg, rgba(247, 144, 9, 0.25) 0%, rgba(255, 255, 255, 0.00) 100%);
} }