mirror of
https://git.mirrors.martin98.com/https://github.com/langgenius/dify.git
synced 2025-07-31 01:06:59 +08:00
Feat: dataset dark mode (#17993)
This commit is contained in:
parent
cd7fd100a7
commit
ed63fbaf9a
@ -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
|
||||
|
@ -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;
|
||||
}
|
@ -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>
|
||||
|
@ -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;
|
||||
}
|
@ -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)} />
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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>
|
||||
)}
|
||||
|
@ -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>
|
||||
)}
|
||||
|
@ -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;
|
||||
|
@ -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')}
|
||||
|
@ -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>
|
||||
|
@ -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">
|
||||
|
@ -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'>
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user