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,
DocumentTextIcon as DocumentTextSolidIcon,
} 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 classNames from '@/utils/classnames'
import { fetchDatasetDetail, fetchDatasetRelatedApps } from '@/service/datasets'
@ -58,13 +58,6 @@ const TargetSolidIcon = ({ className }: SVGProps<SVGElement>) => {
</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 = {
isMobile: boolean
relatedApps?: RelatedAppResponse
@ -131,7 +124,7 @@ const ExtraInfo = ({ isMobile, relatedApps, expand }: IExtraInfoProps) => {
}
target='_blank' rel='noopener noreferrer'
>
<BookOpenIcon className='mr-1' />
<RiBookOpenLine className='mr-1 text-text-accent' />
{t('common.datasetMenus.viewDoc')}
</a>
</div>

View File

@ -44,7 +44,7 @@ export default function NavLink({
key={name}
href={href}
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',
mode === 'expand' ? 'px-3' : 'px-2.5',
)}

View File

@ -34,10 +34,11 @@ export type ButtonProps = {
destructive?: boolean
loading?: boolean
styleCss?: CSSProperties
spinnerClassName?: string
} & React.ButtonHTMLAttributes<HTMLButtonElement> & VariantProps<typeof buttonVariants>
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 (
<button
type='button'
@ -50,7 +51,7 @@ const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
{...props}
>
{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>
)
},

View File

@ -20,7 +20,7 @@
"width": "16",
"height": "16",
"rx": "5",
"fill": "#F2F4F7"
"fill": "currentColor"
},
"children": []
},
@ -33,7 +33,7 @@
"width": "233",
"height": "10",
"rx": "3",
"fill": "#EAECF0"
"fill": "currentColor"
},
"children": []
},
@ -46,7 +46,7 @@
"width": "345",
"height": "6",
"rx": "3",
"fill": "#F2F4F7"
"fill": "currentColor"
},
"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 useSWR from 'swr'
import s from './base.module.css'
import { RiEqualizer2Line } from '@remixicon/react'
import WorkspaceSelector from './workspace-selector'
import SearchInput from './search-input'
import PageSelector from './page-selector'
import cn from '@/utils/classnames'
import { preImportNotionPages } from '@/service/datasets'
import { NotionConnector } from '@/app/components/datasets/create/step-one'
import type { DataSourceNotionPageMap, DataSourceNotionWorkspace, NotionPage } from '@/models/common'
@ -88,23 +87,24 @@ const NotionPageSelector = ({
}, [firstWorkspaceId])
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
? (
<>
<div className='flex items-center pl-[10px] pr-2 h-11 bg-white border-b border-b-gray-200 rounded-t-xl'>
<WorkspaceSelector
value={currentWorkspaceId || firstWorkspaceId}
items={notionWorkspaces}
onSelect={handleSelectWorkspace}
/>
<div className='mx-1 w-[1px] h-3 bg-gray-200' />
<div
className={cn(s['setting-icon'], 'w-6 h-6 cursor-pointer')}
onClick={() => setShowAccountSettingModal({ payload: 'data-source', onCancelCallback: mutate })}
/>
<div className='grow' />
<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
value={currentWorkspaceId || firstWorkspaceId}
items={notionWorkspaces}
onSelect={handleSelectWorkspace}
/>
<div className='mx-1 w-[1px] h-3 bg-divider-regular' />
<RiEqualizer2Line
className='w-4 h-4 cursor-pointer text-text-tertiary'
onClick={() => setShowAccountSettingModal({ payload: 'data-source', onCancelCallback: mutate })}
/>
</div>
<SearchInput
value={searchValue}
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 { FixedSizeList as List, areEqual } from 'react-window'
import type { ListChildComponentProps } from 'react-window'
import { RiArrowDownSLine, RiArrowRightSLine } from '@remixicon/react'
import Checkbox from '../../checkbox'
import NotionIcon from '../../notion-icon'
import s from './index.module.css'
import cn from '@/utils/classnames'
import type { DataSourceNotionPage, DataSourceNotionPageMap } from '@/models/common'
@ -94,10 +94,16 @@ const ItemComponent = ({ index, style, data }: ListChildComponentProps<{
if (hasChild) {
return (
<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 }}
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]) {
@ -112,14 +118,12 @@ const ItemComponent = ({ index, style, data }: ListChildComponentProps<{
return (
<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)' }}
>
<Checkbox
className={cn(
'shrink-0 mr-2 group-hover:border-primary-600 group-hover:border-[2px]',
disabled && 'group-hover:border-transparent',
)}
className='shrink-0 mr-2'
checked={checkedIds.has(current.page_id)}
disabled={disabled}
onCheck={() => {
@ -135,7 +139,7 @@ const ItemComponent = ({ index, style, data }: ListChildComponentProps<{
src={current.page_icon}
/>
<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}
>
{current.page_name}
@ -143,7 +147,9 @@ const ItemComponent = ({ index, style, data }: ListChildComponentProps<{
{
canPreview && (
<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)}>
{t('common.dataSource.notion.selector.preview')}
</div>
@ -152,7 +158,7 @@ const ItemComponent = ({ index, style, data }: ListChildComponentProps<{
{
searchValue && (
<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(' / ')}
>
{breadCrumbs.join(' / ')}
@ -278,7 +284,7 @@ const PageSelector = ({
if (!currentDataList.length) {
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')}
</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 type { ChangeEvent } from 'react'
import { useTranslation } from 'react-i18next'
import s from './index.module.css'
import { RiCloseCircleFill, RiSearchLine } from '@remixicon/react'
import cn from '@/utils/classnames'
type SearchInputProps = {
@ -19,18 +19,18 @@ const SearchInput = ({
}, [onChange])
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(s['search-icon'], 'mr-[6px] w-4 h-4')} />
<div className={cn('w-[200px] flex items-center p-2 h-8 rounded-lg bg-components-input-bg-normal')}>
<RiSearchLine className={'w-4 h-4 mr-0.5 shrink-0 text-components-input-text-placeholder'} />
<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}
onChange={(e: ChangeEvent<HTMLInputElement>) => onChange(e.target.value)}
placeholder={t('common.dataSource.notion.selector.searchPages') || ''}
/>
{
value && (
<div
className={cn(s['clear-icon'], 'ml-1 w-4 h-4 cursor-pointer')}
<RiCloseCircleFill
className={'w-4 h-4 shrink-0 cursor-pointer text-components-input-text-placeholder'}
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 { Fragment } from 'react'
import { Menu, Transition } from '@headlessui/react'
import { RiArrowDownSLine } from '@remixicon/react'
import NotionIcon from '../../notion-icon'
import s from './index.module.css'
import cn from '@/utils/classnames'
import type { DataSourceNotionWorkspace } from '@/models/common'
type WorkspaceSelectorProps = {
@ -25,15 +24,15 @@ export default function WorkspaceSelector({
{
({ 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
className='ml-1 mr-2'
className='mr-2'
src={currentWorkspace?.workspace_icon}
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 px-1 h-[18px] bg-primary-50 rounded-lg text-xs font-medium text-primary-600'>{currentWorkspace?.pages.length}</div>
<div className={cn(s['down-arrow'], 'mr-2 w-3 h-3')} />
<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-text-accent'>{currentWorkspace?.pages.length}</div> */}
<RiArrowDownSLine className='w-4 h-4 text-text-secondary' />
</Menu.Button>
<Transition
as={Fragment}
@ -45,19 +44,16 @@ export default function WorkspaceSelector({
leaveTo="transform opacity-0 scale-95"
>
<Menu.Items
className={cn(
s.popup,
`absolute left-0 top-8 w-80
origin-top-right rounded-lg bg-white
border-[0.5px] border-gray-200`,
)}
className='absolute left-0 top-8 z-10 w-80
origin-top-right rounded-lg bg-components-panel-bg-blur
border-[0.5px] border-components-panel-border shadow-lg shadow-shadow-shadow-5 backdrop-blur-[5px]'
>
<div className="p-1 max-h-50 overflow-auto">
{
items.map(item => (
<Menu.Item key={item.workspace_id}>
<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)}
>
<NotionIcon
@ -65,8 +61,8 @@ export default function WorkspaceSelector({
src={item.workspace_icon}
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='shrink-0 text-xs font-medium text-primary-600'>
<div className='grow mr-2 system-sm-medium text-text-secondary truncate' title={item.workspace_name}>{item.workspace_name}</div>
<div className='shrink-0 system-xs-medium text-text-accent'>
{item.pages.length} {t('common.dataSource.notion.selector.pageSelected')}
</div>
</div>

View File

@ -1,9 +1,8 @@
import type { FC } from 'react'
import { useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { RiSearchLine } from '@remixicon/react'
import { RiCloseCircleFill, RiSearchLine } from '@remixicon/react'
import cn from '@/utils/classnames'
import { XCircle } from '@/app/components/base/icons/src/vender/solid/general'
type SearchInputProps = {
placeholder?: string
@ -27,22 +26,19 @@ const SearchInput: FC<SearchInputProps> = ({
return (
<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',
focus && '!bg-white hover:bg-white shadow-xs !border-gray-300',
!focus && value && 'hover:!bg-gray-200 hover:!shadow-xs hover:!border-black/5',
'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-components-input-bg-active',
white && '!bg-white hover:!bg-white shadow-xs !border-gray-300 hover:!border-gray-300',
className,
)}>
<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>
<input
type="text"
name="query"
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',
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',
'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',
white && '!bg-white hover:!bg-white group-hover:!bg-white placeholder:!text-gray-400',
)}
placeholder={placeholder || t('common.operation.search')!}
@ -71,7 +67,7 @@ const SearchInput: FC<SearchInputProps> = ({
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>

View File

@ -234,8 +234,8 @@ const TagSelector: FC<TagSelectorProps> = ({
<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',
)}>
<Tag01 className='shrink-0 w-3 h-3' />
<div className='grow text-xs text-start leading-[18px] font-normal truncate'>
<Tag01 className='shrink-0 w-3 h-3 text-components-input-text-placeholder' />
<div className='grow text-start system-sm-regular text-components-input-text-placeholder truncate'>
{!triggerContent ? t('common.tag.addTag') : triggerContent}
</div>
</div>

View File

@ -78,7 +78,7 @@ const DocumentPicker: FC<Props> = ({
<FileIcon name={name} extension={extension} size='lg' />
<div className='flex flex-col items-start ml-1 mr-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'} />
</div>
<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 (
<>
<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'>
<RiLoader2Fill className='size-4 mr-1 animate-spin' />
<RiLoader2Fill className='size-4 mr-1 animate-spin text-text-secondary' />
{t('datasetDocuments.embedding.processing')}
</div>}
{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="text-xs truncate">
<div className="system-xs-medium text-text-secondary truncate">
{getSourceName(indexingStatusDetail.id)}
</div>
{
@ -314,7 +314,7 @@ const EmbeddingProcess: FC<Props> = ({ datasetId, batchId, documents = [], index
}
</div>
{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' && (
<Tooltip

View File

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

View File

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

View File

@ -46,13 +46,13 @@ const FilePreview = ({
return (
<div className={cn(s.filePreview, 'h-full')}>
<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>
<div className='flex items-center justify-center w-6 h-6 cursor-pointer' onClick={hidePreview}>
<XMarkIcon className='h-4 w-4'></XMarkIcon>
</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>
</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 && (
<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,54 +1,34 @@
.filePreview {
@apply flex flex-col border-l border-gray-200 shrink-0;
width: 528px;
background-color: #fcfcfd;
}
.previewHeader {
@apply border-b border-gray-200 shrink-0;
margin: 42px 32px 0;
padding-bottom: 16px;
}
.previewHeader .title {
display: flex;
justify-content: space-between;
align-items: center;
color: #101828;
font-weight: 600;
font-size: 18px;
line-height: 28px;
}
.previewHeader .fileName {
display: flex;
align-items: center;
font-weight: 400;
font-size: 12px;
line-height: 18px;
color: #1D2939;
}
.previewHeader .filetype {
color: #667085;
}
.previewContent {
@apply overflow-y-auto grow;
padding: 20px 32px;
font-weight: 400;
font-size: 16px;
line-height: 24px;
color: #344054;
}
.previewContent .loading {
width: 100%;
height: 180px;
background: #f9fafb center no-repeat url(../assets/Loading.svg);
background-size: contain;
}
.fileContent {
white-space: pre-line;
}
@apply flex flex-col border-l border-components-panel-border shrink-0 bg-background-default-lighter;
width: 528px;
}
.previewHeader {
@apply border-b border-divider-subtle shrink-0;
margin: 42px 32px 0;
padding-bottom: 16px;
}
.previewHeader .title {
@apply flex justify-between items-center text-text-primary;
}
.previewHeader .fileName {
@apply flex items-center text-text-tertiary;
}
.previewContent {
@apply overflow-y-auto grow text-text-secondary;
padding: 20px 32px;
}
.previewContent .loading {
width: 100%;
height: 180px;
background: #f9fafb center no-repeat url(../assets/Loading.svg);
background-size: contain;
}
.fileContent {
white-space: pre-line;
}

View File

@ -46,13 +46,13 @@ const NotionPagePreview = ({
return (
<div className={cn(s.filePreview, 'h-full')}>
<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>
<div className='flex items-center justify-center w-6 h-6 cursor-pointer' onClick={hidePreview}>
<XMarkIcon className='h-4 w-4'></XMarkIcon>
</div>
</div>
<div className={cn(s.fileName)}>
<div className={cn(s.fileName, 'system-xs-medium')}>
<NotionIcon
className='shrink-0 mr-1'
type='page'
@ -61,7 +61,7 @@ const NotionPagePreview = ({
{currentPage?.page_name}
</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.fileContent, 'body-md-regular')}>{previewContent}</div>

View File

@ -1,11 +1,5 @@
.stepHeader {
position: sticky;
top: 0;
left: 0;
padding: 42px 64px 12px 0;
font-weight: 600;
font-size: 18px;
line-height: 28px;
}
.form {
@ -14,38 +8,22 @@
}
.dataSourceItem {
@apply w-full box-border relative flex items-center p-3 h-14 bg-white rounded-xl cursor-pointer;
border: 0.5px solid #EAECF0;
box-shadow: 0px 1px 2px rgba(16, 24, 40, 0.05);
font-weight: 500;
font-size: 14px;
line-height: 20px;
color: #101828;
@apply w-full relative flex items-center p-3 h-14 bg-components-option-card-option-bg rounded-xl
cursor-pointer border border-components-option-card-option-border text-text-secondary;
}
.dataSourceItem:hover {
background-color: #f5f8ff;
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);
@apply bg-components-option-card-option-bg-hover border border-components-option-card-option-border-hover shadow-xs shadow-shadow-shadow-3;
}
.dataSourceItem.active {
background-color: #f5f8ff;
border: 1.5px solid #528BFF;
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;
@apply bg-components-option-card-option-selected-bg border border-components-option-card-option-selected-border
ring-[0.5px] ring-components-option-card-option-selected-border;
}
.dataSourceItem.disabled,
.dataSourceItem.disabled:hover {
background-color: #f9fafb;
border: 0.5px solid #EAECF0;
box-shadow: 0px 1px 2px rgba(16, 24, 40, 0.05);
@apply bg-components-option-card-option-bg border-[0.5px] border-components-option-card-option-border cursor-not-allowed text-text-disabled shadow-none;
}
.comingTag {
@ -64,17 +42,9 @@
}
.datasetIcon {
@apply flex shrink-0 mr-2 w-8 h-8 rounded-lg bg-center bg-no-repeat;
background-color: #F5FAFF;
@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-image: url(../assets/file.svg);
background-size: 16px;
border: 0.5px solid #D1E9FF;
}
.dataSourceItem:active .datasetIcon,
.dataSourceItem:hover .datasetIcon {
background-color: #F5F8FF;
border: 0.5px solid #E0EAFF;
}
.datasetIcon.notion {
@ -97,54 +67,7 @@
background-color: #eaecf0;
}
.notionConnectionTip {
display: flex;
flex-direction: column;
align-items: flex-start;
padding: 24px;
width: 640px;
background: #F9FAFB;
border-radius: 16px;
}
.notionIcon {
display: flex;
padding: 12px;
width: 48px;
height: 48px;
background: #fff center no-repeat url(../assets/notion.svg);
background: var(--color-components-card-bg) center no-repeat url(../assets/notion.svg);
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 VectorSpaceFull from '@/app/components/billing/vector-space-full'
import classNames from '@/utils/classnames'
import { Icon3Dots } from '@/app/components/base/icons/src/vender/line/others'
type IStepOneProps = {
datasetId?: string
@ -48,10 +49,15 @@ export const NotionConnector = ({ onSetting }: NotionConnectorProps) => {
const { t } = useTranslation()
return (
<div className={s.notionConnectionTip}>
<span className={s.notionIcon} />
<div className={s.title}>{t('datasetCreation.stepOne.notionSyncTitle')}</div>
<div className={s.tip}>{t('datasetCreation.stepOne.notionSyncTip')}</div>
<div className='flex flex-col items-start p-6 w-[640px] rounded-2xl bg-workflow-process-bg'>
<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='flex flex-col gap-y-1 pt-1 pb-3 mb-1'>
<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>
</div>
)
@ -132,7 +138,9 @@ const StepOne = ({
<div className={classNames(s.form)}>
{
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
className={cn(
s.dataSourceItem,
'system-sm-medium',
dataSourceType === DataSourceType.FILE && s.active,
dataSourceTypeDisable && dataSourceType !== DataSourceType.FILE && s.disabled,
)}
@ -163,6 +172,7 @@ const StepOne = ({
<div
className={cn(
s.dataSourceItem,
'system-sm-medium',
dataSourceType === DataSourceType.NOTION && s.active,
dataSourceTypeDisable && dataSourceType !== DataSourceType.NOTION && s.disabled,
)}
@ -185,6 +195,7 @@ const StepOne = ({
<div
className={cn(
s.dataSourceItem,
'system-sm-medium',
dataSourceType === DataSourceType.WEB && s.active,
dataSourceTypeDisable && dataSourceType !== DataSourceType.WEB && s.disabled,
)}
@ -205,7 +216,7 @@ const StepOne = ({
<>
<FileUploader
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}
onFileListUpdate={updateFileList}
onFileUpdate={updateFile}

View File

@ -34,8 +34,8 @@ const StepThree = ({ datasetId, datasetName, indexingType, creationCache, retrie
<div className="flex gap-4">
<AppIcon {...creationCache?.dataset} className="size-14 text-2xl self-center" />
<div className="grow flex flex-col gap-1">
<div className="text-[13px] leading-6 font-semibold">{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="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 text-components-input-text-filled">{datasetName || creationCache?.dataset?.name}</div>
</div>
</div>
</div>

View File

@ -581,7 +581,7 @@ const StepTwo = ({
return (
<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={'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))
|| isUploadInEmptyDataset
|| isInInit)
@ -832,10 +832,10 @@ const StepTwo = ({
</div>
</OptionCard>}
<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'>
{(!hasSetIndexType || (hasSetIndexType && indexingType === IndexingType.QUALIFIED)) && (
<OptionCard className='flex-1'
<OptionCard className='flex-1 self-stretch'
title={<div className='flex items-center'>
{t('datasetCreation.stepTwo.qualified')}
<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'}
>
<PortalToFollowElemTrigger asChild>
<OptionCard className='flex-1'
<OptionCard className='flex-1 self-stretch'
title={t('datasetCreation.stepTwo.economical')}
description={t('datasetCreation.stepTwo.economicalTip')}
icon={<Image src={indexMethodIcon.economical} alt='' />}
@ -916,11 +916,11 @@ const StepTwo = ({
</div>
{!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='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'>
<AlertTriangle className='size-4 text-text-warning-secondary' />
</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>
)}
{hasSetIndexType && indexType === IndexingType.ECONOMICAL && (
@ -932,7 +932,7 @@ const StepTwo = ({
{/* Embedding model */}
{indexType === IndexingType.QUALIFIED && (
<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
readonly={isModelAndRetrievalConfigDisabled}
triggerClassName={isModelAndRetrievalConfigDisabled ? 'opacity-50' : ''}
@ -943,7 +943,7 @@ const StepTwo = ({
}}
/>
{isModelAndRetrievalConfigDisabled && (
<div className='mt-2 system-xs-medium'>
<div className='mt-2 system-xs-medium text-text-tertiary'>
{t('datasetCreation.stepTwo.indexSettingTip')}
<Link className='text-text-accent' href={`/datasets/${datasetId}/settings`}>{t('datasetCreation.stepTwo.datasetSettingLink')}</Link>
</div>
@ -956,7 +956,7 @@ const StepTwo = ({
{!isModelAndRetrievalConfigDisabled
? (
<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'>
<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')}
@ -964,7 +964,7 @@ const StepTwo = ({
</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>
)}

View File

@ -34,7 +34,7 @@ export const OptionCardHeader: FC<OptionCardHeaderProps> = (props) => {
</div>
</div>
<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='text-text-secondary system-md-semibold'>{title}</div>

View File

@ -25,7 +25,7 @@ const CheckboxWithLabel: FC<Props> = ({
return (
<label className={cn(className, 'flex items-center h-7 space-x-2')}>
<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
popupContent={

View File

@ -5,6 +5,7 @@ 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'
import Button from '@/app/components/base/button'
type Props = {
payload: CrawlResultItemType
@ -27,13 +28,32 @@ const CrawledResultItem: FC<Props> = ({
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 className={cn(isPreview ? 'bg-state-base-active' : 'group hover:bg-state-base-hover', 'rounded-lg p-2 cursor-pointer')}>
<div className='relative flex'>
<div className='h-5 flex items-center'>
<Checkbox className='mr-2 shrink-0' checked={isChecked} onCheck={handleCheckChange} />
</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 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>
)
}

View File

@ -57,17 +57,19 @@ const CrawledResult: FC<Props> = ({
}, [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'>
<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'>
<CheckboxWithLabel
isChecked={isCheckAll}
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`, {
total: list.length,
time: usedTime.toFixed(1),
})}</div>
<div className='text-xs text-text-tertiary'>
{t(`${I18N_PREFIX}.scrapTimeInfo`, {
total: list.length,
time: usedTime.toFixed(1),
})}
</div>
</div>
<div className='p-2'>
{list.map((item, index) => (

View File

@ -2,7 +2,6 @@
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'
type Props = {
@ -19,15 +18,16 @@ const Crawling: FC<Props> = ({
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'>
<div className={className}>
<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}
</div>
<div className='p-2'>
{['', '', '', ''].map((item, index) => (
<div className='py-[5px]' key={index}>
<RowStruct />
<RowStruct className='text-text-quaternary' />
</div>
))}
</div>

View File

@ -16,13 +16,13 @@ const ErrorMessage: FC<Props> = ({
errorMsg,
}) => {
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'>
<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>
{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>
)

View File

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

View File

@ -20,7 +20,7 @@ const Input: FC<Props> = ({
const handleChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
const value = e.target.value
if (isNumber) {
let numberValue = parseInt(value, 10) // integer only
let numberValue = Number.parseInt(value, 10) // integer only
if (isNaN(numberValue)) {
onChange('')
return
@ -50,7 +50,12 @@ const Input: FC<Props> = ({
{...otherOption}
value={value}
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}
/>
)

View File

@ -3,8 +3,8 @@ import { useBoolean } from 'ahooks'
import type { FC } from 'react'
import React, { useEffect } from 'react'
import { useTranslation } from 'react-i18next'
import { RiEqualizer2Line } from '@remixicon/react'
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'
const I18N_PREFIX = 'datasetCreation.stepOne.website'
@ -34,14 +34,14 @@ const OptionsWrap: FC<Props> = ({
return (
<div className={cn(className, !fold ? 'mb-0' : 'mb-3')}>
<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}
>
<div className='flex items-center text-gray-700'>
<Settings04 className='mr-1 w-4 h-4' />
<div className='text-[13px] font-semibold text-gray-800 uppercase'>{t(`${I18N_PREFIX}.options`)}</div>
<div className='flex items-center grow'>
<RiEqualizer2Line className='mr-1 w-4 h-4 text-text-secondary' />
<span className='text-[13px] leading-[16px] font-semibold text-text-secondary uppercase'>{t(`${I18N_PREFIX}.options`)}</span>
</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>
{!fold && (
<div className='mb-4'>

View File

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

View File

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

View File

@ -9,7 +9,6 @@ import Crawling from '../base/crawling'
import ErrorMessage from '../base/error-message'
import Header from './header'
import Options from './options'
import cn from '@/utils/classnames'
import { useModalContext } from '@/context/modal-context'
import type { CrawlOptions, CrawlResultItem } from '@/models/datasets'
import Toast from '@/app/components/base/toast'
@ -99,7 +98,7 @@ const FireCrawl: FC<Props> = ({
isError: false,
data: {
...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
setCrawlResult({
...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
await sleep(2500)
@ -179,10 +178,10 @@ const FireCrawl: FC<Props> = ({
return (
<div>
<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} />
<OptionsWrap
className={cn('mt-4')}
className='mt-4'
controlFoldOptions={controlFoldOptions}
>
<Options className='mt-2' payload={crawlOptions} onChange={onCrawlOptionsChange} />
@ -194,7 +193,7 @@ const FireCrawl: FC<Props> = ({
&& <Crawling
className='mt-2'
crawledNum={crawlResult?.current || 0}
totalNum={crawlResult?.total || parseFloat(crawlOptions.limit as string) || 0}
totalNum={crawlResult?.total || Number.parseFloat(crawlOptions.limit as string) || 0}
/>}
{showError && (
<ErrorMessage className='rounded-b-xl' title={t(`${I18N_PREFIX}.exceptionErrorTitle`)} errorMsg={crawlErrorMessage} />
@ -206,7 +205,7 @@ const FireCrawl: FC<Props> = ({
checkedList={checkedCrawlResult}
onSelectedChange={onCheckedCrawlResultChange}
onPreview={onPreview}
usedTime={parseFloat(crawlResult?.time_consuming as string) || 0}
usedTime={Number.parseFloat(crawlResult?.time_consuming as string) || 0}
/>
}
</div>

View File

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

View File

@ -73,27 +73,29 @@ const Website: FC<Props> = ({
return (
<div>
<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')}
</div>
<div className="flex space-x-2">
<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
? 'bg-primary-50 text-primary-600'
: 'bg-gray-100 text-gray-600 hover:bg-gray-200'
}`}
? 'system-sm-medium bg-components-option-card-option-selected-bg text-text-primary border-[1.5px] border-components-option-card-option-selected-border'
: `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)}
>
<span className={cn(s.jinaLogo, 'mr-2')} />
<span>Jina Reader</span>
</button>
<button
className={`px-4 py-2 text-sm font-medium rounded-md ${
className={cn('px-4 py-2 rounded-lg',
selectedProvider === DataSourceProvider.fireCrawl
? 'bg-primary-50 text-primary-600'
: 'bg-gray-100 text-gray-600 hover:bg-gray-200'
}`}
? 'system-sm-medium bg-components-option-card-option-selected-bg text-text-primary border-[1.5px] border-components-option-card-option-selected-border'
: `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)}
>
🔥 Firecrawl

View File

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

View File

@ -9,7 +9,6 @@ import Crawling from '../base/crawling'
import ErrorMessage from '../base/error-message'
import Header from './header'
import Options from './options'
import cn from '@/utils/classnames'
import { useModalContext } from '@/context/modal-context'
import Toast from '@/app/components/base/toast'
import { checkJinaReaderTaskStatus, createJinaReaderTask } from '@/service/datasets'
@ -99,7 +98,7 @@ const JinaReader: FC<Props> = ({
isError: false,
data: {
...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
setCrawlResult({
...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
await sleep(2500)
@ -192,10 +191,10 @@ const JinaReader: FC<Props> = ({
return (
<div>
<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} />
<OptionsWrap
className={cn('mt-4')}
className='mt-4'
controlFoldOptions={controlFoldOptions}
>
<Options className='mt-2' payload={crawlOptions} onChange={onCrawlOptionsChange} />
@ -207,7 +206,7 @@ const JinaReader: FC<Props> = ({
&& <Crawling
className='mt-2'
crawledNum={crawlResult?.current || 0}
totalNum={crawlResult?.total || parseFloat(crawlOptions.limit as string) || 0}
totalNum={crawlResult?.total || Number.parseFloat(crawlOptions.limit as string) || 0}
/>}
{showError && (
<ErrorMessage className='rounded-b-xl' title={t(`${I18N_PREFIX}.exceptionErrorTitle`)} errorMsg={crawlErrorMessage} />
@ -219,7 +218,7 @@ const JinaReader: FC<Props> = ({
checkedList={checkedCrawlResult}
onSelectedChange={onCheckedCrawlResultChange}
onPreview={onPreview}
usedTime={parseFloat(crawlResult?.time_consuming as string) || 0}
usedTime={Number.parseFloat(crawlResult?.time_consuming as string) || 0}
/>
}
</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`)}
isChecked={payload.crawl_sub_pages}
onChange={handleChange('crawl_sub_pages')}
labelClassName='text-[13px] leading-[16px] font-medium text-text-secondary'
/>
<CheckboxWithLabel
label={t(`${I18N_PREFIX}.useSitemap`)}
isChecked={payload.use_sitemap}
onChange={handleChange('use_sitemap')}
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'>
<Field

View File

@ -37,13 +37,17 @@ const NoData: FC<Props> = ({
return (
<>
<div className='max-w-[640px] p-6 rounded-2xl bg-gray-50 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='max-w-[640px] p-6 rounded-2xl bg-workflow-process-bg mt-4'>
<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}
</div>
<div className='my-2'>
<span className='text-gray-700 font-semibold'>{currentProvider.title}<Icon3Dots className='inline relative -top-3 -left-1.5' /></span>
<div className='mt-1 pb-3 text-gray-500 text-[13px] font-normal'>
<div className='mt-2 mb-1 pt-1 pb-3 flex flex-col gap-y-1'>
<span className='text-text-secondary system-md-semibold'>
{currentProvider.title}
<Icon3Dots className='inline relative -top-2.5 -left-1.5' />
</span>
<div className='text-text-tertiary system-sm-regular'>
{currentProvider.description}
</div>
</div>

View File

@ -20,19 +20,19 @@ const WebsitePreview = ({
return (
<div className={cn(s.filePreview, 'h-full')}>
<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>
<div className='flex items-center justify-center w-6 h-6 cursor-pointer' onClick={hidePreview}>
<XMarkIcon className='h-4 w-4'></XMarkIcon>
</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}
</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 className={cn(s.previewContent)}>
<div className={cn(s.fileContent, 'body-md-regular')}>{payload.markdown}</div>
<div className={cn(s.previewContent, 'body-md-regular')}>
<div className={cn(s.fileContent)}>{payload.markdown}</div>
</div>
</div>
)

View File

@ -165,7 +165,7 @@ const ChildSegmentList: FC<IChildSegmentCardProps> = ({
onDelete={() => onDelete?.(childChunk.segment_id, childChunk.id)}
labelClassName={focused ? 'bg-state-accent-solid text-text-primary-on-surface' : ''}
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}
onClick={(e) => {
e.stopPropagation()

View File

@ -17,7 +17,7 @@ const Textarea: FC<IContentProps> = React.memo(({
return (
<textarea
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,
)}
placeholder={placeholder}
@ -83,7 +83,7 @@ const AutoResizeTextArea: FC<IAutoResizeTextAreaProps> = React.memo(({
<textarea
ref={textareaRef}
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,
)}
style={{

View File

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

View File

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

View File

@ -16,7 +16,6 @@ import { useContext } from 'use-context-selector'
import { useRouter } from 'next/navigation'
import { useTranslation } from 'react-i18next'
import dayjs from 'dayjs'
import { Edit03 } from '../../base/icons/src/vender/solid/general'
import { Globe01 } from '../../base/icons/src/vender/line/mapsAndTravel'
import ChunkingModeLabel from '../common/chunking-mode-label'
import FileTypeIcon from '../../base/file-uploader/file-type-icon'
@ -343,7 +342,7 @@ export const OperationAction: FC<{
position='br'
btnElement={
<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>
}
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)
}}
>
<Edit03 className='w-4 h-4 text-text-tertiary' />
<RiEditLine className='w-4 h-4 text-text-tertiary' />
</div>
</Tooltip>
</div>

View File

@ -59,7 +59,7 @@ const RenameModal: FC<Props> = ({
isShow
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
className='mt-2 h-10'
value={newName}

View File

@ -9,7 +9,7 @@
max-width: 200px;
}
.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 {
@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;
}
.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 {
@apply hover:bg-state-destructive-hover !important;

View File

@ -55,7 +55,7 @@ const ResultItem: FC<Props> = ({
{isParentChildRetrieval && (
<div className='mt-1'>
<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) => {
e.stopPropagation()
toggleFold()

View File

@ -6,7 +6,7 @@ import useSWR from 'swr'
import { omit } from 'lodash-es'
import { useBoolean } from 'ahooks'
import { useContext } from 'use-context-selector'
import { RiApps2Line, RiFocus2Line } from '@remixicon/react'
import { RiApps2Line, RiFocus2Line, RiHistoryLine } from '@remixicon/react'
import Textarea from './textarea'
import s from './style.module.css'
import ModifyRetrievalModal from './modify-retrieval-modal'
@ -34,11 +34,11 @@ type Props = {
const RecordsEmpty: FC = () => {
const { t } = useTranslation()
return <div className='bg-gray-50 rounded-2xl p-5'>
<div className={s.clockWrapper}>
<div className={cn(s.clockIcon, 'w-5 h-5')}></div>
return <div className='bg-workflow-process-bg rounded-2xl p-5'>
<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]'>
<RiHistoryLine className='w-5 h-5 text-text-tertiary' />
</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>
}

View File

@ -59,33 +59,41 @@ const ModifyRetrievalModal: FC<Props> = ({
return (
<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={{
height: 'calc(100vh - 72px)',
}}
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='text-base font-semibold text-gray-900'>
<div className='shrink-0 flex justify-between pt-3.5 pb-1 px-3 h-15'>
<div className='text-base font-semibold text-text-primary'>
<div>{t('datasetSettings.form.retrievalSetting.title')}</div>
<div className='leading-[18px] text-xs font-normal text-gray-500'>
<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>
<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>
{t('datasetSettings.form.retrievalSetting.description')}
</div>
</div>
<div className='flex items-center'>
<div className='flex'>
<div
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 className='p-6 border-b' style={{
borderBottom: 'rgba(0, 0, 0, 0.05)',
}}>
<div className='px-4 py-2'>
<div className='mb-1 text-text-secondary text-[13px] leading-6 font-semibold'>
{t('datasetSettings.form.retrievalSetting.method')}
</div>
{indexMethod === 'high_quality'
? (
<RetrievalMethodConfig
@ -100,12 +108,7 @@ const ModifyRetrievalModal: FC<Props> = ({
/>
)}
</div>
<div
className='flex justify-end pt-6 px-6 border-t'
style={{
borderColor: 'rgba(0, 0, 0, 0.05)',
}}
>
<div className='flex justify-end p-4 pt-2'>
<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>
</div>

View File

@ -15,7 +15,7 @@ import { asyncRunSafe } from '@/utils'
import { RETRIEVE_METHOD, type RetrievalConfig } from '@/types/app'
import promptS from '@/app/components/app/configuration/config-prompt/style.module.css'
interface TextAreaWithButtonIProps {
type TextAreaWithButtonIProps = {
datasetId: string
onUpdateList: () => void
setHitResult: (res: HitTestingResponse) => void
@ -108,7 +108,7 @@ const TextAreaWithButton = ({
return (
<>
<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">
<span className="text-text-secondary font-semibold text-[13px] leading-4 uppercase">
{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 className='px-4 pb-11 bg-background-default rounded-b-xl'>
<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}
onChange={handleTextChange}
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)}
className='block'
>
{isOnlyMe && (
<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')}>
<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>
{!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')}>
<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]' />
</div>
<div className='grow mr-2 text-text-primary 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')}>
<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]' />
</div>
<div title={selectedMembers} className='grow mr-2 text-text-primary text-sm leading-5 truncate'>{selectedMembers}</div>
{!disabled && <RiArrowDownSLine className='shrink-0 w-4 h-4 text-text-secondary' />}
</div>
)}
<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',
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} />
<div className='grow mr-2 text-components-input-text-filled text-sm leading-5'>{t('datasetSettings.form.permissionsOnlyMe')}</div>
</>
)
}
{
isAllTeamMembers && (
<>
<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]' />
</div>
<div className='grow mr-2 text-components-input-text-filled text-sm leading-5'>{t('datasetSettings.form.permissionsAllMember')}</div>
</>
)
}
{
isPartialMembers && (
<>
<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]' />
</div>
<div title={selectedMembers} className='grow mr-2 text-components-input-text-filled text-sm leading-5 truncate'>{selectedMembers}</div>
</>
)
}
<RiArrowDownSLine className={cn('shrink-0 w-4 h-4 text-text-secondary', disabled && '!text-components-input-text-placeholder')} />
</div>
</PortalToFollowElemTrigger>
<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'>

View File

@ -19,10 +19,10 @@ import { useModalContext } from '@/context/modal-context'
import { getDocDownloadUrl } from '@/service/common'
enum DocName {
'SOC2_Type_I' = 'SOC2_Type_I',
'SOC2_Type_II' = 'SOC2_Type_II',
'ISO_27001' = 'ISO_27001',
'GDPR' = 'GDPR',
SOC2_Type_I = 'SOC2_Type_I',
SOC2_Type_II = 'SOC2_Type_II',
ISO_27001 = 'ISO_27001',
GDPR = 'GDPR',
}
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',
open && 'bg-state-base-hover',
)}>
<RiVerifiedBadgeLine className='flex-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>
<RiVerifiedBadgeLine className='shrink-0 size-4 text-text-tertiary' />
<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' />
</Menu.Button>
<Transition
@ -140,8 +140,8 @@ export default function Compliance() {
className={cn(itemClassName, 'group justify-between',
active && 'bg-state-base-hover',
)}>
<Soc2 className='flex-shrink-0 size-7' />
<div className='system-md-regular flex-grow text-text-secondary px-1 truncate'>{t('common.compliance.soc2Type1')}</div>
<Soc2 className='shrink-0 size-7' />
<div className='system-md-regular grow text-text-secondary px-1 truncate'>{t('common.compliance.soc2Type1')}</div>
<UpgradeOrDownload doc_name={DocName.SOC2_Type_I} />
</div>}
</Menu.Item>
@ -150,8 +150,8 @@ export default function Compliance() {
className={cn(itemClassName, 'group justify-between',
active && 'bg-state-base-hover',
)}>
<Soc2 className='flex-shrink-0 size-7' />
<div className='system-md-regular flex-grow text-text-secondary px-1 truncate'>{t('common.compliance.soc2Type2')}</div>
<Soc2 className='shrink-0 size-7' />
<div className='system-md-regular grow text-text-secondary px-1 truncate'>{t('common.compliance.soc2Type2')}</div>
<UpgradeOrDownload doc_name={DocName.SOC2_Type_II} />
</div>}
</Menu.Item>
@ -160,8 +160,8 @@ export default function Compliance() {
className={cn(itemClassName, 'group justify-between',
active && 'bg-state-base-hover',
)}>
<Iso className='flex-shrink-0 size-7' />
<div className='system-md-regular flex-grow text-text-secondary px-1 truncate'>{t('common.compliance.iso27001')}</div>
<Iso className='shrink-0 size-7' />
<div className='system-md-regular grow text-text-secondary px-1 truncate'>{t('common.compliance.iso27001')}</div>
<UpgradeOrDownload doc_name={DocName.ISO_27001} />
</div>}
</Menu.Item>
@ -170,8 +170,8 @@ export default function Compliance() {
className={cn(itemClassName, 'group justify-between',
active && 'bg-state-base-hover',
)}>
<Gdpr className='flex-shrink-0 size-7' />
<div className='system-md-regular flex-grow text-text-secondary px-1 truncate'>{t('common.compliance.gdpr')}</div>
<Gdpr className='shrink-0 size-7' />
<div className='system-md-regular grow text-text-secondary px-1 truncate'>{t('common.compliance.gdpr')}</div>
<UpgradeOrDownload doc_name={DocName.GDPR} />
</div>}
</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',
open && 'bg-state-base-hover',
)}>
<RiQuestionLine className='flex-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>
<RiQuestionLine className='shrink-0 size-4 text-text-tertiary' />
<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' />
</Menu.Button>
<Transition
@ -55,9 +55,9 @@ export default function Support() {
)}
href={mailToSupport(userProfile.email, plan.type, langeniusVersionInfo.current_version)}
target='_blank' rel='noopener noreferrer'>
<RiMailSendLine className='flex-shrink-0 size-4 text-text-tertiary' />
<div className='flex-grow system-md-regular text-text-secondary px-1'>{t('common.userProfile.emailSupport')}</div>
<RiArrowRightUpLine className='flex-shrink-0 size-[14px] text-text-tertiary' />
<RiMailSendLine className='shrink-0 size-4 text-text-tertiary' />
<div className='grow system-md-regular text-text-secondary px-1'>{t('common.userProfile.emailSupport')}</div>
<RiArrowRightUpLine className='shrink-0 size-[14px] text-text-tertiary' />
</a>}
</Menu.Item>}
<Menu.Item>
@ -67,9 +67,9 @@ export default function Support() {
)}
href='https://github.com/langgenius/dify/discussions/categories/feedbacks'
target='_blank' rel='noopener noreferrer'>
<RiFeedbackLine className='flex-shrink-0 size-4 text-text-tertiary' />
<div className='flex-grow system-md-regular text-text-secondary px-1'>{t('common.userProfile.communityFeedback')}</div>
<RiArrowRightUpLine className='flex-shrink-0 size-[14px] text-text-tertiary' />
<RiFeedbackLine className='shrink-0 size-4 text-text-tertiary' />
<div className='grow system-md-regular text-text-secondary px-1'>{t('common.userProfile.communityFeedback')}</div>
<RiArrowRightUpLine className='shrink-0 size-[14px] text-text-tertiary' />
</Link>}
</Menu.Item>
<Menu.Item>
@ -79,9 +79,9 @@ export default function Support() {
)}
href='https://discord.gg/5AEfbxcd9k'
target='_blank' rel='noopener noreferrer'>
<RiDiscordLine className='flex-shrink-0 size-4 text-text-tertiary' />
<div className='flex-grow system-md-regular text-text-secondary px-1'>{t('common.userProfile.community')}</div>
<RiArrowRightUpLine className='flex-shrink-0 size-[14px] text-text-tertiary' />
<RiDiscordLine className='shrink-0 size-4 text-text-tertiary' />
<div className='grow system-md-regular text-text-secondary px-1'>{t('common.userProfile.community')}</div>
<RiArrowRightUpLine className='shrink-0 size-[14px] text-text-tertiary' />
</Link>}
</Menu.Item>
</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 { FILE_STRUCT } from '@/app/components/workflow/constants'
interface ObjectChildrenProps {
type ObjectChildrenProps = {
nodeId: string
title: string
data: Var[]
@ -28,7 +28,7 @@ interface ObjectChildrenProps {
isSupportFileVar?: boolean
}
interface ItemProps {
type ItemProps = {
nodeId: string
title: string
objPath: string[]
@ -227,7 +227,7 @@ const ObjectChildren: FC<ObjectChildrenProps> = ({
)
}
interface Props {
type Props = {
hideSearch?: boolean
searchBoxClassName?: string
vars: NodeOutPutVar[]

View File

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

View File

@ -26,6 +26,7 @@ const translation = {
embeddingModelTipLink: 'Settings',
retrievalSetting: {
title: 'Retrieval Setting',
method: 'Retrieval Method',
learnMore: 'Learn more',
description: ' about retrieval method.',
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 未配置',
jinaReaderNotConfiguredDescription: '请配置 Jina Reader 的免费 API 密钥以访问它。',
configure: '配置',
configureFirecrawl: '配置 Firecrawl',
configureJinaReader: '配置 Jina Reader',
run: '运行',
firecrawlTitle: '使用 🔥Firecrawl 提取网页内容',
firecrawlDoc: 'Firecrawl 文档',

View File

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

View File

@ -113,6 +113,7 @@ const config = {
'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-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)',
'premium-yearly-tip-text-background': 'var(--color-premium-yearly-tip-text-background)',
'price-premium-text-background': 'var(--color-premium-text-background)',

View File

@ -38,8 +38,8 @@ html[data-theme="dark"] {
rgba(240, 68, 56, 0.3) 0%,
rgba(0, 0, 0, 0) 100%);
--color-toast-info-bg: linear-gradient(92deg,
rgba(11, 165, 236, 0.3) 0%),
--color-account-teams-bg: linear-gradient(271deg,
rgba(11, 165, 236, 0.3) 0%);
--color-account-teams-bg: linear-gradient(271deg,
rgba(34, 34, 37, 0.9) -0.1%,
rgba(29, 29, 32, 0.9) 98.26%);
--color-app-detail-bg: linear-gradient(169deg,
@ -60,4 +60,5 @@ html[data-theme="dark"] {
--mask-top2bottom-gray-50-to-transparent: linear-gradient(180deg,
rgba(24, 24, 27, 0.08) 0%,
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

@ -1,63 +1,64 @@
html[data-theme="light"] {
--color-chatbot-bg: linear-gradient(180deg,
rgba(249, 250, 251, 0.9) 0%,
rgba(242, 244, 247, 0.9) 90.48%);
--color-chat-bubble-bg: linear-gradient(180deg,
#fff 0%,
rgba(255, 255, 255, 0.6) 100%);
--color-workflow-process-bg: linear-gradient(90deg,
rgba(200, 206, 218, 0.2) 0%,
rgba(200, 206, 218, 0.04) 100%);
--color-dataset-chunk-process-success-bg: linear-gradient(92deg, rgba(23, 178, 106, 0.25) 0%, rgba(255, 255, 255, 0.00) 100%);
--color-dataset-chunk-process-error-bg: linear-gradient(92deg, rgba(240, 68, 56, 0.25) 0%, rgba(255, 255, 255, 0.00) 100%);
--color-dataset-chunk-detail-card-hover-bg: linear-gradient(180deg, #F2F4F7 0%, #F9FAFB 100%);
--color-dataset-child-chunk-expand-btn-bg: linear-gradient(90deg, rgba(200, 206, 218, 0.20) 0%, rgba(200, 206, 218, 0.04) 100%);
--color-dataset-option-card-blue-gradient: linear-gradient(90deg, #F2F4F7 0%, #F9FAFB 100%);
--color-dataset-option-card-purple-gradient: linear-gradient(90deg, #F0EEFA 0%, #F9FAFB 100%);
--color-dataset-option-card-orange-gradient: linear-gradient(90deg, #F8F2EE 0%, #F9FAFB 100%);
--color-dataset-chunk-list-mask-bg: linear-gradient(180deg, rgba(255, 255, 255, 0.00) 0%, #FFF 100%);
--mask-top2bottom-gray-50-to-transparent: linear-gradient(180deg,
rgba(200, 206, 218, 0.2) 0%,
rgba(255, 255, 255, 0) 100%);
--color-premium-yearly-tip-text-background: linear-gradient(91deg, #F79009 2.18%, #DC6803 108.79%);
--color-premium-badge-background: linear-gradient(95deg, rgba(152, 162, 178, 0.90) 0%, rgba(103, 111, 131, 0.90) 105.58%);
--color-premium-text-background: linear-gradient(92deg, rgba(252, 252, 253, 0.95) 0%, rgba(242, 244, 247, 0.95) 97.78%);
--color-price-enterprise-background: linear-gradient(180deg, rgba(185, 211, 234, 0.00) 0%, rgba(180, 209, 234, 0.92) 100%);
--color-grid-mask-background: linear-gradient(0deg, #FFF 0%, rgba(217, 217, 217, 0.10) 62.25%, rgba(217, 217, 217, 0.10) 100%);
--color-chat-input-mask: linear-gradient(180deg,
rgba(255, 255, 255, 0.01) 0%,
#F2F4F7 100%);
--color-workflow-run-failed-bg: linear-gradient(98deg,
rgba(240, 68, 56, 0.10) 0%,
rgba(255, 255, 255, 0) 26.01%);
--color-workflow-batch-failed-bg: linear-gradient(92deg,
rgba(240, 68, 56, 0.25) 0%,
rgba(255, 255, 255, 0) 100%);
--color-marketplace-divider-bg: linear-gradient(90deg,
rgba(16, 24, 40, 0.08) 0%,
rgba(255, 255, 255, 0) 100%);
--color-marketplace-plugin-empty: linear-gradient(180deg,
rgba(255, 255, 255, 0) 0%,
#fcfcfd 100%);
--color-toast-success-bg: linear-gradient(92deg,
rgba(23, 178, 106, 0.25) 0%,
rgba(255, 255, 255, 0) 100%);
--color-toast-warning-bg: linear-gradient(92deg,
rgba(247, 144, 9, 0.25) 0%,
rgba(255, 255, 255, 0) 100%);
--color-toast-error-bg: linear-gradient(92deg,
rgba(240, 68, 56, 0.25) 0%,
rgba(255, 255, 255, 0) 100%);
--color-toast-info-bg: linear-gradient(92deg,
rgba(11, 165, 236, 0.25) 0%);
--color-account-teams-bg: linear-gradient(271deg,
rgba(249, 250, 251, 0.9) -0.1%,
rgba(242, 244, 247, 0.9) 98.26%);
--color-app-detail-bg: linear-gradient(169deg,
#F2F4F7 1.18%,
#F9FAFB 99.52%);
--color-app-detail-overlay-bg: linear-gradient(270deg,
rgba(0, 0, 0, 0.00) 0%,
rgba(16, 24, 40, 0.01) 8%,
rgba(16, 24, 40, 0.18) 100%);
--color-chatbot-bg: linear-gradient(180deg,
rgba(249, 250, 251, 0.9) 0%,
rgba(242, 244, 247, 0.9) 90.48%);
--color-chat-bubble-bg: linear-gradient(180deg,
#fff 0%,
rgba(255, 255, 255, 0.6) 100%);
--color-workflow-process-bg: linear-gradient(90deg,
rgba(200, 206, 218, 0.2) 0%,
rgba(200, 206, 218, 0.04) 100%);
--color-dataset-chunk-process-success-bg: linear-gradient(92deg, rgba(23, 178, 106, 0.25) 0%, rgba(255, 255, 255, 0.00) 100%);
--color-dataset-chunk-process-error-bg: linear-gradient(92deg, rgba(240, 68, 56, 0.25) 0%, rgba(255, 255, 255, 0.00) 100%);
--color-dataset-chunk-detail-card-hover-bg: linear-gradient(180deg, #F2F4F7 0%, #F9FAFB 100%);
--color-dataset-child-chunk-expand-btn-bg: linear-gradient(90deg, rgba(200, 206, 218, 0.20) 0%, rgba(200, 206, 218, 0.04) 100%);
--color-dataset-option-card-blue-gradient: linear-gradient(90deg, #F2F4F7 0%, #F9FAFB 100%);
--color-dataset-option-card-purple-gradient: linear-gradient(90deg, #F0EEFA 0%, #F9FAFB 100%);
--color-dataset-option-card-orange-gradient: linear-gradient(90deg, #F8F2EE 0%, #F9FAFB 100%);
--color-dataset-chunk-list-mask-bg: linear-gradient(180deg, rgba(255, 255, 255, 0.00) 0%, #FFF 100%);
--mask-top2bottom-gray-50-to-transparent: linear-gradient(180deg,
rgba(200, 206, 218, 0.2) 0%,
rgba(255, 255, 255, 0) 100%);
--color-premium-yearly-tip-text-background: linear-gradient(91deg, #F79009 2.18%, #DC6803 108.79%);
--color-premium-badge-background: linear-gradient(95deg, rgba(152, 162, 178, 0.90) 0%, rgba(103, 111, 131, 0.90) 105.58%);
--color-premium-text-background: linear-gradient(92deg, rgba(252, 252, 253, 0.95) 0%, rgba(242, 244, 247, 0.95) 97.78%);
--color-price-enterprise-background: linear-gradient(180deg, rgba(185, 211, 234, 0.00) 0%, rgba(180, 209, 234, 0.92) 100%);
--color-grid-mask-background: linear-gradient(0deg, #FFF 0%, rgba(217, 217, 217, 0.10) 62.25%, rgba(217, 217, 217, 0.10) 100%);
--color-chat-input-mask: linear-gradient(180deg,
rgba(255, 255, 255, 0.01) 0%,
#F2F4F7 100%);
--color-workflow-run-failed-bg: linear-gradient(98deg,
rgba(240, 68, 56, 0.10) 0%,
rgba(255, 255, 255, 0) 26.01%);
--color-workflow-batch-failed-bg: linear-gradient(92deg,
rgba(240, 68, 56, 0.25) 0%,
rgba(255, 255, 255, 0) 100%);
--color-marketplace-divider-bg: linear-gradient(90deg,
rgba(16, 24, 40, 0.08) 0%,
rgba(255, 255, 255, 0) 100%);
--color-marketplace-plugin-empty: linear-gradient(180deg,
rgba(255, 255, 255, 0) 0%,
#fcfcfd 100%);
--color-toast-success-bg: linear-gradient(92deg,
rgba(23, 178, 106, 0.25) 0%,
rgba(255, 255, 255, 0) 100%);
--color-toast-warning-bg: linear-gradient(92deg,
rgba(247, 144, 9, 0.25) 0%,
rgba(255, 255, 255, 0) 100%);
--color-toast-error-bg: linear-gradient(92deg,
rgba(240, 68, 56, 0.25) 0%,
rgba(255, 255, 255, 0) 100%);
--color-toast-info-bg: linear-gradient(92deg,
rgba(11, 165, 236, 0.25) 0%);
--color-account-teams-bg: linear-gradient(271deg,
rgba(249, 250, 251, 0.9) -0.1%,
rgba(242, 244, 247, 0.9) 98.26%);
--color-app-detail-bg: linear-gradient(169deg,
#F2F4F7 1.18%,
#F9FAFB 99.52%);
--color-app-detail-overlay-bg: linear-gradient(270deg,
rgba(0, 0, 0, 0.00) 0%,
rgba(16, 24, 40, 0.01) 8%,
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%);
}