Feat: dataset dark mode (#17993)

This commit is contained in:
KVOJJJin 2025-04-14 15:45:23 +08:00 committed by GitHub
parent cd7fd100a7
commit ed63fbaf9a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 38 additions and 83 deletions

View File

@ -1,22 +1,22 @@
'use client'
import type { FC, SVGProps } from 'react'
import type { FC } from 'react'
import React, { useEffect, useMemo } from 'react'
import { usePathname } from 'next/navigation'
import useSWR from 'swr'
import { useTranslation } from 'react-i18next'
import { useBoolean } from 'ahooks'
import {
Cog8ToothIcon,
DocumentTextIcon,
RiEqualizer2Fill,
RiEqualizer2Line,
RiFileTextFill,
RiFileTextLine,
RiFocus2Fill,
RiFocus2Line,
} from '@remixicon/react'
import {
PaperClipIcon,
} from '@heroicons/react/24/outline'
import {
Cog8ToothIcon as Cog8ToothSolidIcon,
// CommandLineIcon as CommandLineSolidIcon,
DocumentTextIcon as DocumentTextSolidIcon,
} from '@heroicons/react/24/solid'
import { RiApps2AddLine, RiBookOpenLine, RiInformation2Line } from '@remixicon/react'
import s from './style.module.css'
import classNames from '@/utils/classnames'
import { fetchDatasetDetail, fetchDatasetRelatedApps } from '@/service/datasets'
import type { RelatedAppResponse } from '@/models/datasets'
@ -37,27 +37,6 @@ export type IAppDetailLayoutProps = {
params: { datasetId: string }
}
const TargetIcon = ({ className }: SVGProps<SVGElement>) => {
return <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" className={className ?? ''}>
<g clipPath="url(#clip0_4610_6951)">
<path d="M10.6666 5.33325V3.33325L12.6666 1.33325L13.3332 2.66659L14.6666 3.33325L12.6666 5.33325H10.6666ZM10.6666 5.33325L7.9999 7.99988M14.6666 7.99992C14.6666 11.6818 11.6818 14.6666 7.99992 14.6666C4.31802 14.6666 1.33325 11.6818 1.33325 7.99992C1.33325 4.31802 4.31802 1.33325 7.99992 1.33325M11.3333 7.99992C11.3333 9.84087 9.84087 11.3333 7.99992 11.3333C6.15897 11.3333 4.66659 9.84087 4.66659 7.99992C4.66659 6.15897 6.15897 4.66659 7.99992 4.66659" stroke="#344054" strokeWidth="1.25" strokeLinecap="round" strokeLinejoin="round" />
</g>
<defs>
<clipPath id="clip0_4610_6951">
<rect width="16" height="16" fill="white" />
</clipPath>
</defs>
</svg>
}
const TargetSolidIcon = ({ className }: SVGProps<SVGElement>) => {
return <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" className={className ?? ''}>
<path fillRule="evenodd" clipRule="evenodd" d="M12.7733 0.67512C12.9848 0.709447 13.1669 0.843364 13.2627 1.03504L13.83 2.16961L14.9646 2.73689C15.1563 2.83273 15.2902 3.01486 15.3245 3.22639C15.3588 3.43792 15.2894 3.65305 15.1379 3.80458L13.1379 5.80458C13.0128 5.92961 12.8433 5.99985 12.6665 5.99985H10.9426L8.47124 8.47124C8.21089 8.73159 7.78878 8.73159 7.52843 8.47124C7.26808 8.21089 7.26808 7.78878 7.52843 7.52843L9.9998 5.05707V3.33318C9.9998 3.15637 10.07 2.9868 10.1951 2.86177L12.1951 0.861774C12.3466 0.710244 12.5617 0.640794 12.7733 0.67512Z" fill="#155EEF" />
<path d="M1.99984 7.99984C1.99984 4.68613 4.68613 1.99984 7.99984 1.99984C8.36803 1.99984 8.6665 1.70136 8.6665 1.33317C8.6665 0.964981 8.36803 0.666504 7.99984 0.666504C3.94975 0.666504 0.666504 3.94975 0.666504 7.99984C0.666504 12.0499 3.94975 15.3332 7.99984 15.3332C12.0499 15.3332 15.3332 12.0499 15.3332 7.99984C15.3332 7.63165 15.0347 7.33317 14.6665 7.33317C14.2983 7.33317 13.9998 7.63165 13.9998 7.99984C13.9998 11.3135 11.3135 13.9998 7.99984 13.9998C4.68613 13.9998 1.99984 11.3135 1.99984 7.99984Z" fill="#155EEF" />
<path d="M5.33317 7.99984C5.33317 6.52708 6.52708 5.33317 7.99984 5.33317C8.36803 5.33317 8.6665 5.03469 8.6665 4.6665C8.6665 4.29831 8.36803 3.99984 7.99984 3.99984C5.7907 3.99984 3.99984 5.7907 3.99984 7.99984C3.99984 10.209 5.7907 11.9998 7.99984 11.9998C10.209 11.9998 11.9998 10.209 11.9998 7.99984C11.9998 7.63165 11.7014 7.33317 11.3332 7.33317C10.965 7.33317 10.6665 7.63165 10.6665 7.99984C10.6665 9.4726 9.4726 10.6665 7.99984 10.6665C6.52708 10.6665 5.33317 9.4726 5.33317 7.99984Z" fill="#155EEF" />
</svg>
}
type IExtraInfoProps = {
isMobile: boolean
relatedApps?: RelatedAppResponse
@ -98,9 +77,9 @@ const ExtraInfo = ({ isMobile, relatedApps, expand }: IExtraInfoProps) => {
</Tooltip>
)}
{isMobile && <div className={classNames(s.subTitle, 'flex items-center justify-center !px-0 gap-1')}>
{isMobile && <div className={classNames('uppercase text-xs text-text-tertiary font-medium pb-2 pt-4', 'flex items-center justify-center !px-0 gap-1')}>
{relatedAppsTotal || '--'}
<PaperClipIcon className='h-4 w-4 text-gray-700' />
<PaperClipIcon className='h-4 w-4 text-text-secondary' />
</div>}
</>
)}
@ -164,17 +143,16 @@ const DatasetDetailLayout: FC<IAppDetailLayoutProps> = (props) => {
const navigation = useMemo(() => {
const baseNavigation = [
{ name: t('common.datasetMenus.hitTesting'), href: `/datasets/${datasetId}/hitTesting`, icon: TargetIcon, selectedIcon: TargetSolidIcon },
// { name: 'api & webhook', href: `/datasets/${datasetId}/api`, icon: CommandLineIcon, selectedIcon: CommandLineSolidIcon },
{ name: t('common.datasetMenus.settings'), href: `/datasets/${datasetId}/settings`, icon: Cog8ToothIcon, selectedIcon: Cog8ToothSolidIcon },
{ name: t('common.datasetMenus.hitTesting'), href: `/datasets/${datasetId}/hitTesting`, icon: RiFocus2Line, selectedIcon: RiFocus2Fill },
{ name: t('common.datasetMenus.settings'), href: `/datasets/${datasetId}/settings`, icon: RiEqualizer2Line, selectedIcon: RiEqualizer2Fill },
]
if (datasetRes?.provider !== 'external') {
baseNavigation.unshift({
name: t('common.datasetMenus.documents'),
href: `/datasets/${datasetId}/documents`,
icon: DocumentTextIcon,
selectedIcon: DocumentTextSolidIcon,
icon: RiFileTextLine,
selectedIcon: RiFileTextFill,
})
}
return baseNavigation

View File

@ -1,9 +0,0 @@
.statusPoint {
@apply flex justify-center items-center absolute -right-0.5 -bottom-0.5 w-2.5 h-2.5 bg-white rounded;
}
.subTitle {
@apply uppercase text-xs text-gray-500 font-medium px-3 pb-2 pt-4;
}
.emptyIconDiv {
@apply h-7 w-7 bg-gray-50 border border-[#EAECF5] inline-flex justify-center items-center rounded-lg;
}

View File

@ -1,7 +1,6 @@
import React, { useEffect } from 'react'
import { useShallow } from 'zustand/react/shallow'
import { RiLayoutRight2Line } from '@remixicon/react'
import { LayoutRight2LineMod } from '../base/icons/src/public/knowledge'
import { RiLayoutLeft2Line, RiLayoutRight2Line } from '@remixicon/react'
import NavLink from './navLink'
import type { NavIcon } from './navLink'
import AppBasic from './basic'
@ -108,13 +107,13 @@ const AppDetailNav = ({ title, desc, isExternal, icon, icon_background, navigati
`}
>
<div
className='flex h-6 w-6 cursor-pointer items-center justify-center text-gray-500'
className='flex h-6 w-6 cursor-pointer items-center justify-center'
onClick={() => handleToggle(appSidebarExpand)}
>
{
expand
? <RiLayoutRight2Line className='h-5 w-5 text-components-menu-item-text' />
: <LayoutRight2LineMod className='h-5 w-5 text-components-menu-item-text' />
: <RiLayoutLeft2Line className='h-5 w-5 text-components-menu-item-text' />
}
</div>
</div>

View File

@ -1,6 +0,0 @@
.default-page-icon {
width: 20px;
height: 20px;
background: url(../notion-page-selector/assets/notion-page.svg) center center no-repeat;
background-size: cover;
}

View File

@ -1,4 +1,4 @@
import s from './index.module.css'
import { RiFileTextLine } from '@remixicon/react'
import cn from '@/utils/classnames'
import type { DataSourceNotionPage } from '@/models/common'
@ -51,7 +51,7 @@ const NotionIcon = ({
}
return (
<div className={cn(s['default-page-icon'], className)} />
<RiFileTextLine className={cn('h-5 w-5 text-text-tertiary', className)} />
)
}

View File

@ -29,7 +29,7 @@
.previewContent .loading {
width: 100%;
height: 180px;
background: #f9fafb center no-repeat url(../assets/Loading.svg);
background: transparent center no-repeat url(../assets/Loading.svg);
background-size: contain;
}

View File

@ -2,6 +2,7 @@
import React, { useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { XMarkIcon } from '@heroicons/react/20/solid'
import Loading from '@/app/components/base/loading'
import s from './index.module.css'
import cn from '@/utils/classnames'
import type { CustomFile as File } from '@/models/datasets'
@ -57,7 +58,7 @@ const FilePreview = ({
</div>
</div>
<div className={cn(s.previewContent)}>
{loading && <div className={cn(s.loading)} />}
{loading && <Loading type='area' />}
{!loading && (
<div className={cn(s.fileContent, 'body-md-regular')}>{previewContent}</div>
)}

View File

@ -2,6 +2,7 @@
import React, { useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { XMarkIcon } from '@heroicons/react/20/solid'
import Loading from '@/app/components/base/loading'
import s from './index.module.css'
import cn from '@/utils/classnames'
import type { NotionPage } from '@/models/common'
@ -62,7 +63,7 @@ const NotionPagePreview = ({
</div>
</div>
<div className={cn(s.previewContent, 'body-md-regular')}>
{loading && <div className={cn(s.loading)} />}
{loading && <Loading type='area' />}
{!loading && (
<div className={cn(s.fileContent, 'body-md-regular')}>{previewContent}</div>
)}

View File

@ -60,13 +60,6 @@
width: 120px;
}
.dividerLine {
margin: 32px 0;
max-width: 640px;
height: 1px;
background-color: #eaecf0;
}
.notionIcon {
background: var(--color-components-card-bg) center no-repeat url(../assets/notion.svg);
background-size: 24px;

View File

@ -301,7 +301,7 @@ const StepOne = ({
)}
{!datasetId && (
<>
<div className={s.dividerLine} />
<div className='my-8 h-px max-w-[640px] bg-divider-regular' />
<span className="inline-flex cursor-pointer items-center text-[13px] leading-4 text-text-accent" onClick={modalShowHandle}>
<RiFolder6Line className="mr-1 size-4" />
{t('datasetCreation.stepOne.emptyDatasetCreation')}

View File

@ -4,7 +4,7 @@ import React, { useMemo, useState } from 'react'
import { createContext, useContext, useContextSelector } from 'use-context-selector'
import { useTranslation } from 'react-i18next'
import { useRouter } from 'next/navigation'
import { RiArrowLeftLine, RiLayoutRight2Line } from '@remixicon/react'
import { RiArrowLeftLine, RiLayoutLeft2Line, RiLayoutRight2Line } from '@remixicon/react'
import { OperationAction, StatusItem } from '../list'
import DocumentPicker from '../../common/document-picker'
import Completed from './completed'
@ -21,7 +21,6 @@ import type { ChunkingMode, ParentMode, ProcessMode } from '@/models/datasets'
import { useDatasetDetailContext } from '@/context/dataset-detail'
import FloatRightContainer from '@/app/components/base/float-right-container'
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
import { LayoutRight2LineMod } from '@/app/components/base/icons/src/public/knowledge'
import { useCheckSegmentBatchImportProgress, useChildSegmentListKey, useSegmentBatchImport, useSegmentListKey } from '@/service/knowledge/use-segment'
import { useDocumentDetail, useDocumentMetadata, useInvalidDocumentList } from '@/service/knowledge/use-document'
import { useInvalid } from '@/service/use-base'
@ -250,7 +249,7 @@ const DocumentDetail: FC<Props> = ({ datasetId, documentId }) => {
>
{
showMetadata
? <LayoutRight2LineMod className='h-4 w-4 text-components-button-secondary-text' />
? <RiLayoutLeft2Line className='h-4 w-4 text-components-button-secondary-text' />
: <RiLayoutRight2Line className='h-4 w-4 text-components-button-secondary-text' />
}
</button>

View File

@ -13,7 +13,6 @@ import type { ExternalKnowledgeBaseHitTestingResponse, HitTestingResponse } from
import { externalKnowledgeBaseHitTesting, hitTesting } from '@/service/datasets'
import { asyncRunSafe } from '@/utils'
import { RETRIEVE_METHOD, type RetrievalConfig } from '@/types/app'
import promptS from '@/app/components/app/configuration/config-prompt/style.module.css'
type TextAreaWithButtonIProps = {
datasetId: string
@ -107,7 +106,7 @@ const TextAreaWithButton = ({
const icon = <Image className='size-3.5 text-util-colors-purple-purple-600' src={getIcon(retrievalMethod)} alt='' />
return (
<>
<div className={cn('relative rounded-xl', promptS.gradientBorder)}>
<div className={cn('relative rounded-xl bg-gradient-to-r from-components-input-border-active-prompt-1 to-components-input-border-active-prompt-2 p-0.5 shadow-xs')}>
<div className='relative rounded-t-xl bg-background-section-burn pt-1.5'>
<div className="flex h-8 items-center justify-between pb-1 pl-4 pr-1.5">
<span className="text-[13px] font-semibold uppercase leading-4 text-text-secondary">

View File

@ -57,7 +57,7 @@ const InfoGroup: FC<Props> = ({
}
return (
<div className={cn('bg-white', className)}>
<div className={cn(className)}>
{!noHeader && (
<div className='flex items-center justify-between'>
<div className='flex items-center space-x-1'>

View File

@ -114,17 +114,17 @@ const PermissionSelector = ({ disabled, permission, value, memberList, onChange,
<PortalToFollowElemContent className='z-[1002]'>
<div className='relative w-[480px] rounded-lg border-[0.5px] border-components-panel-border bg-components-panel-bg-blur shadow-lg backdrop-blur-sm'>
<div className='p-1'>
<div className='cursor-pointer rounded-lg py-1 pl-3 pr-2 hover:bg-gray-50' onClick={() => {
<div className='cursor-pointer rounded-lg py-1 pl-3 pr-2 hover:bg-state-base-hover' onClick={() => {
onChange(DatasetPermission.onlyMe)
setOpen(false)
}}>
<div className='flex items-center gap-2'>
<Avatar avatar={userProfile.avatar_url} name={userProfile.name} className='mr-2 shrink-0' size={24} />
<div className='mr-2 grow text-sm leading-5 text-gray-900'>{t('datasetSettings.form.permissionsOnlyMe')}</div>
<div className='mr-2 grow text-sm leading-5 text-text-primary'>{t('datasetSettings.form.permissionsOnlyMe')}</div>
{isOnlyMe && <Check className='h-4 w-4 text-primary-600' />}
</div>
</div>
<div className='cursor-pointer rounded-lg py-1 pl-3 pr-2 hover:bg-gray-50' onClick={() => {
<div className='cursor-pointer rounded-lg py-1 pl-3 pr-2 hover:bg-state-base-hover' onClick={() => {
onChange(DatasetPermission.allTeamMembers)
setOpen(false)
}}>
@ -132,11 +132,11 @@ const PermissionSelector = ({ disabled, permission, value, memberList, onChange,
<div className='mr-2 flex h-6 w-6 items-center justify-center rounded-lg bg-[#EEF4FF]'>
<Users01 className='h-3.5 w-3.5 text-[#444CE7]' />
</div>
<div className='mr-2 grow text-sm leading-5 text-gray-900'>{t('datasetSettings.form.permissionsAllMember')}</div>
<div className='mr-2 grow text-sm leading-5 text-text-primary'>{t('datasetSettings.form.permissionsAllMember')}</div>
{isAllTeamMembers && <Check className='h-4 w-4 text-primary-600' />}
</div>
</div>
<div className='cursor-pointer rounded-lg py-1 pl-3 pr-2 hover:bg-gray-50' onClick={() => {
<div className='cursor-pointer rounded-lg py-1 pl-3 pr-2 hover:bg-state-base-hover' onClick={() => {
onChange(DatasetPermission.partialMembers)
onMemberSelect([userProfile.id])
}}>
@ -144,14 +144,14 @@ const PermissionSelector = ({ disabled, permission, value, memberList, onChange,
<div className={cn('mr-2 flex h-6 w-6 items-center justify-center rounded-lg bg-[#FFF6ED]', isPartialMembers && '!bg-[#EEF4FF]')}>
<UsersPlus className={cn('h-3.5 w-3.5 text-[#FB6514]', isPartialMembers && '!text-[#444CE7]')} />
</div>
<div className='mr-2 grow text-sm leading-5 text-gray-900'>{t('datasetSettings.form.permissionsInvitedMembers')}</div>
<div className='mr-2 grow text-sm leading-5 text-text-primary'>{t('datasetSettings.form.permissionsInvitedMembers')}</div>
{isPartialMembers && <Check className='h-4 w-4 text-primary-600' />}
</div>
</div>
</div>
{isPartialMembers && (
<div className='max-h-[360px] overflow-y-auto border-t-[1px] border-gray-100 p-1'>
<div className='sticky left-0 top-0 bg-white p-2 pb-1'>
<div className='max-h-[360px] overflow-y-auto border-t-[1px] border-divider-regular p-1'>
<div className='sticky left-0 top-0 p-2 pb-1'>
<Input
showLeftIcon
showClearIcon