diff --git a/web/app/components/datasets/documents/detail/index.tsx b/web/app/components/datasets/documents/detail/index.tsx index 4f1e850fc8..839e8e202c 100644 --- a/web/app/components/datasets/documents/detail/index.tsx +++ b/web/app/components/datasets/documents/detail/index.tsx @@ -2,11 +2,11 @@ import type { FC } from 'react' import React, { useState } from 'react' import useSWR from 'swr' -import { ArrowLeftIcon } from '@heroicons/react/24/solid' import { createContext, useContext } from 'use-context-selector' import { useTranslation } from 'react-i18next' import { useRouter } from 'next/navigation' import { omit } from 'lodash-es' +import { RiArrowDownSLine, RiArrowLeftLine, RiLayoutRight2Line } from '@remixicon/react' import { OperationAction, StatusItem } from '../list' import s from '../style.module.css' import Completed from './completed' @@ -21,7 +21,7 @@ import Loading from '@/app/components/base/loading' import type { MetadataType } from '@/service/datasets' import { checkSegmentBatchImportProgress, fetchDocumentDetail, segmentBatchImport } from '@/service/datasets' import { ToastContext } from '@/app/components/base/toast' -import type { DocForm } from '@/models/datasets' +import type { DocForm, 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' @@ -31,17 +31,36 @@ export const DocumentContext = createContext<{ datasetId?: string; documentId?: type DocumentTitleProps = { extension?: string name?: string + processMode?: ProcessMode + parent_mode?: ParentMode iconCls?: string textCls?: string wrapperCls?: string } -export const DocumentTitle: FC = ({ extension, name, iconCls, textCls, wrapperCls }) => { +export const DocumentTitle: FC = ({ extension, name, processMode, parent_mode, iconCls, textCls, wrapperCls }) => { const localExtension = extension?.toLowerCase() || name?.split('.')?.pop()?.toLowerCase() - return
-
- {name || '--'} -
+ return ( +
+ {/* // todo: add file switcher */} +
+ {/* // todo: add icons map */} +
+
+
+ {name || '--'} + +
+
+
+ + {`${processMode || '--'}${processMode === 'hierarchical' ? `ยท${parent_mode || '--'}` : ''}`} + +
+
+
+
+ ) } type Props = { @@ -130,14 +149,17 @@ const DocumentDetail: FC = ({ datasetId, documentId }) => { return (
-
-
- +
+
+
- - -
- + +
{embeddingAvailable && documentDetail && !documentDetail.archived && ( = ({ datasetId, documentId }) => { showBatchModal={showBatchModal} /> )} + + = ({ datasetId, documentId }) => { }} datasetId={datasetId} onUpdate={handleOperate} - className='!w-[216px]' + className='!w-[200px]' />
diff --git a/web/app/components/datasets/documents/detail/segment-add/index.tsx b/web/app/components/datasets/documents/detail/segment-add/index.tsx index 0d9d31c34b..486154e859 100644 --- a/web/app/components/datasets/documents/detail/segment-add/index.tsx +++ b/web/app/components/datasets/documents/detail/segment-add/index.tsx @@ -66,13 +66,13 @@ const SegmentAdd: FC = ({ return (
+ bg-components-button-secondary-bg shadow-xs shadow-shadow-shadow-3 backdrop-blur-[5px] relative z-20'>
- + {t('datasetDocuments.list.action.addButton')}
@@ -83,7 +83,7 @@ const SegmentAdd: FC = ({ htmlContent={
{t('datasetDocuments.list.action.batchAdd')} @@ -99,7 +99,7 @@ const SegmentAdd: FC = ({ open ? '!bg-state-base-hover' : '')} popupClassName='!min-w-[128px] !bg-components-panel-bg-blur !rounded-xl border-[0.5px] !ring-0 border-components-panel-border !shadow-xl !shadow-shadow-shadow-5 backdrop-blur-[5px]' - className='min-w-[128px] h-fit !z-20' + className='min-w-[128px] h-fit' />
) diff --git a/web/app/components/datasets/documents/detail/style.module.css b/web/app/components/datasets/documents/detail/style.module.css index 69295ab31c..8a59ef6f06 100644 --- a/web/app/components/datasets/documents/detail/style.module.css +++ b/web/app/components/datasets/documents/detail/style.module.css @@ -5,11 +5,7 @@ @apply h-6 w-6 !important; } .layoutRightIcon { - @apply w-8 h-8 ml-2 box-border border border-gray-200 rounded-lg hover:bg-gray-50 cursor-pointer hover:shadow-[0_1px_2px_rgba(16,24,40,0.05)]; -} -.iconShow { - background: center center url(../assets/layoutRightShow.svg) no-repeat; -} -.iconClose { - background: center center url(../assets/layoutRightClose.svg) no-repeat; + @apply p-2 ml-2 border-[0.5px] border-components-button-secondary-border hover:border-components-button-secondary-border-hover + rounded-lg bg-components-button-secondary-bg hover:bg-components-button-secondary-bg-hover cursor-pointer + shadow-xs shadow-shadow-shadow-3 backdrop-blur-[5px]; } diff --git a/web/app/components/datasets/documents/list.tsx b/web/app/components/datasets/documents/list.tsx index 0e0eebb034..ee883e912b 100644 --- a/web/app/components/datasets/documents/list.tsx +++ b/web/app/components/datasets/documents/list.tsx @@ -1,11 +1,15 @@ -/* eslint-disable no-mixed-operators */ 'use client' -import type { FC, SVGProps } from 'react' +import type { FC } from 'react' import React, { useCallback, useEffect, useState } from 'react' import { useBoolean, useDebounceFn } from 'ahooks' -import { ArrowDownIcon, TrashIcon } from '@heroicons/react/24/outline' +import { ArrowDownIcon } from '@heroicons/react/24/outline' import { pick } from 'lodash-es' import { + RiArchive2Line, + RiDeleteBinLine, + RiEditLine, + RiEqualizer2Line, + RiLoopLeftLine, RiMoreFill, } from '@remixicon/react' import { useContext } from 'use-context-selector' @@ -23,7 +27,7 @@ import Popover from '@/app/components/base/popover' import Confirm from '@/app/components/base/confirm' import Tooltip from '@/app/components/base/tooltip' import { ToastContext } from '@/app/components/base/toast' -import type { IndicatorProps } from '@/app/components/header/indicator' +import type { ColorMap, IndicatorProps } from '@/app/components/header/indicator' import Indicator from '@/app/components/header/indicator' import { asyncRunSafe } from '@/utils' import { formatNumber } from '@/utils/format' @@ -34,30 +38,6 @@ import { DataSourceType, type DocumentDisplayStatus, type SimpleDocumentDetail } import type { CommonResponse } from '@/models/common' import useTimestamp from '@/hooks/use-timestamp' -export const SettingsIcon = ({ className }: SVGProps) => { - return - - -} - -export const SyncIcon = () => { - return - - -} - -export const FilePlusIcon = ({ className }: SVGProps) => { - return - - -} - -export const ArchiveIcon = ({ className }: SVGProps) => { - return - - -} - export const useIndexStatus = () => { const { t } = useTranslation() return { @@ -72,6 +52,15 @@ export const useIndexStatus = () => { } } +const STATUS_TEXT_COLOR_MAP: ColorMap = { + green: 'text-util-colors-green-green-600', + orange: 'text-util-colors-warning-warning-600', + red: 'text-util-colors-red-red-600', + blue: 'text-util-colors-blue-light-blue-light-600', + yellow: 'text-util-colors-warning-warning-600', + gray: 'text-text-tertiary', +} + // status item for list export const StatusItem: FC<{ status: DocumentDisplayStatus @@ -79,16 +68,75 @@ export const StatusItem: FC<{ scene?: 'list' | 'detail' textCls?: string errorMessage?: string -}> = ({ status, reverse = false, scene = 'list', textCls = '', errorMessage }) => { + detail?: { + enabled: boolean + archived: boolean + id: string + } + datasetId?: string + onUpdate?: (operationName?: string) => void + +}> = ({ status, reverse = false, scene = 'list', textCls = '', errorMessage, datasetId = '', detail, onUpdate }) => { const DOC_INDEX_STATUS_MAP = useIndexStatus() const localStatus = status.toLowerCase() as keyof typeof DOC_INDEX_STATUS_MAP + const { enabled = false, archived = false, id = '' } = detail || {} + const { notify } = useContext(ToastContext) + const { t } = useTranslation() + + const onOperate = async (operationName: OperationName) => { + let opApi = deleteDocument + switch (operationName) { + case 'enable': + opApi = enableDocument + break + case 'disable': + opApi = disableDocument + break + } + const [e] = await asyncRunSafe(opApi({ datasetId, documentId: id }) as Promise) + if (!e) + notify({ type: 'success', message: t('common.actionMsg.modifiedSuccessfully') }) + else + notify({ type: 'error', message: t('common.actionMsg.modifiedUnsuccessfully') }) + onUpdate?.(operationName) + } + + const { run: handleSwitch } = useDebounceFn((operationName: OperationName) => { + if (operationName === 'enable' && enabled) + return + if (operationName === 'disable' && !enabled) + return + onOperate(operationName) + }, { wait: 500 }) + return
- {DOC_INDEX_STATUS_MAP[localStatus]?.text} + + {DOC_INDEX_STATUS_MAP[localStatus]?.text} + + { + scene === 'detail' && ( +
+ + !archived && handleSwitch(v ? 'enable' : 'disable')} + disabled={archived} + size='md' + /> + +
+ ) + } { errorMessage && ( )} {embeddingAvailable && ( - - {!isListScene && <> -
- - {!archived && enabled ? t('datasetDocuments.list.index.enable') : t('datasetDocuments.list.index.disable')} - - -
- !archived && handleSwitch(v ? 'enable' : 'disable')} - disabled={archived} - size='md' - /> + <> + +
router.push(`/datasets/${datasetId}/documents/${detail.id}/settings`)}> + +
+
+ + {!archived && ( + <> +
{ + handleShowRenameModal({ + id: detail.id, + name: detail.name, + }) + }}> + + {t('datasetDocuments.list.table.rename')}
- -
-
- {!archived && enabled ? t('datasetDocuments.list.index.enableTip') : t('datasetDocuments.list.index.disableTip')} -
- - } - {!archived && ( - <> -
{ - handleShowRenameModal({ - id: detail.id, - name: detail.name, - }) - }}> - - {t('datasetDocuments.list.table.rename')} + {['notion_import', DataSourceType.WEB].includes(data_source_type) && ( +
onOperate('sync')}> + + {t('datasetDocuments.list.action.sync')} +
+ )} + + + )} + {!archived &&
onOperate('archive')}> + + {t('datasetDocuments.list.action.archive')} +
} + {archived && ( +
onOperate('un_archive')}> + + {t('datasetDocuments.list.action.unarchive')}
-
router.push(`/datasets/${datasetId}/documents/${detail.id}/settings`)}> - - {t('datasetDocuments.list.action.settings')} -
- {['notion_import', DataSourceType.WEB].includes(data_source_type) && ( -
onOperate('sync')}> - - {t('datasetDocuments.list.action.sync')} -
- )} - - - )} - {!archived &&
onOperate('archive')}> - - {t('datasetDocuments.list.action.archive')} -
} - {archived && ( -
onOperate('un_archive')}> - - {t('datasetDocuments.list.action.unarchive')} + )} +
setShowModal(true)}> + + {t('datasetDocuments.list.action.delete')}
- )} -
setShowModal(true)}> - - {t('datasetDocuments.list.action.delete')}
-
- } - trigger='click' - position='br' - btnElement={ -
- -
- } - btnClassName={open => cn(isListScene ? s.actionIconWrapperList : s.actionIconWrapperDetail, open ? '!bg-gray-100 !shadow-none' : '!bg-transparent')} - className={`flex justify-end !w-[200px] h-fit !z-20 ${className}`} - /> + } + trigger='click' + position='br' + btnElement={ +
+ +
+ } + btnClassName={open => cn(isListScene ? s.actionIconWrapperList : s.actionIconWrapperDetail, open ? '!bg-gray-100 !shadow-none' : '!bg-transparent')} + popupClassName='!w-full' + className={`flex justify-end !w-[200px] h-fit !z-20 ${className}`} + /> + )} {showModal &&