Feat: dark mode for logs and annotations (#11575)
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
import type { FC } from 'react'
|
||||
import React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Textarea from 'rc-textarea'
|
||||
import Textarea from '@/app/components/base/textarea'
|
||||
import { Robot, User } from '@/app/components/base/icons/src/public/avatar'
|
||||
|
||||
export enum EditItemType {
|
||||
@@ -31,12 +31,10 @@ const EditItem: FC<Props> = ({
|
||||
{avatar}
|
||||
</div>
|
||||
<div className='grow'>
|
||||
<div className='mb-1 leading-[18px] text-xs font-semibold text-gray-900'>{name}</div>
|
||||
<div className='mb-1 system-xs-semibold text-text-primary'>{name}</div>
|
||||
<Textarea
|
||||
className='mt-1 block w-full leading-5 max-h-none text-sm text-gray-700 outline-none appearance-none resize-none'
|
||||
value={content}
|
||||
onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => onChange(e.target.value)}
|
||||
autoSize={{ minRows: 3 }}
|
||||
placeholder={placeholder}
|
||||
autoFocus
|
||||
/>
|
||||
|
||||
@@ -4,6 +4,7 @@ import React, { useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import type { AnnotationItemBasic } from '../type'
|
||||
import EditItem, { EditItemType } from './edit-item'
|
||||
import Checkbox from '@/app/components/base/checkbox'
|
||||
import Drawer from '@/app/components/base/drawer-plus'
|
||||
import Button from '@/app/components/base/button'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
@@ -96,11 +97,11 @@ const AddAnnotationModal: FC<Props> = ({
|
||||
<AnnotationFull />
|
||||
</div>
|
||||
)}
|
||||
<div className='px-6 flex h-16 items-center justify-between border-t border-black/5 bg-gray-50 rounded-bl-xl rounded-br-xl leading-[18px] text-[13px] font-medium text-gray-500'>
|
||||
<div className='px-4 flex h-16 items-center justify-between border-t border-divider-subtle bg-background-section-burn rounded-bl-xl rounded-br-xl system-sm-medium text-text-tertiary'>
|
||||
<div
|
||||
className='flex items-center space-x-2'
|
||||
>
|
||||
<input type="checkbox" checked={isCreateNext} onChange={() => setIsCreateNext(!isCreateNext)} className="w-4 h-4 rounded border-gray-300 text-blue-700 focus:ring-blue-700" />
|
||||
<Checkbox checked={isCreateNext} onCheck={() => setIsCreateNext(!isCreateNext)} />
|
||||
<div>{t('appAnnotation.addModal.createNext')}</div>
|
||||
</div>
|
||||
<div className='mt-2 flex space-x-2'>
|
||||
|
||||
@@ -33,19 +33,19 @@ const CSVDownload: FC = () => {
|
||||
|
||||
return (
|
||||
<div className='mt-6'>
|
||||
<div className='text-sm text-gray-900 font-medium'>{t('share.generation.csvStructureTitle')}</div>
|
||||
<div className='system-sm-medium text-text-primary'>{t('share.generation.csvStructureTitle')}</div>
|
||||
<div className='mt-2 max-h-[500px] overflow-auto'>
|
||||
<table className='table-fixed w-full border-separate border-spacing-0 border border-gray-200 rounded-lg text-xs'>
|
||||
<thead className='text-gray-500'>
|
||||
<table className='table-fixed w-full border-separate border-spacing-0 border border-divider-regular rounded-lg text-xs'>
|
||||
<thead className='text-text-tertiary'>
|
||||
<tr>
|
||||
<td className='h-9 pl-3 pr-2 border-b border-gray-200'>{t('appAnnotation.batchModal.question')}</td>
|
||||
<td className='h-9 pl-3 pr-2 border-b border-gray-200'>{t('appAnnotation.batchModal.answer')}</td>
|
||||
<td className='h-9 pl-3 pr-2 border-b border-divider-regular'>{t('appAnnotation.batchModal.question')}</td>
|
||||
<td className='h-9 pl-3 pr-2 border-b border-divider-regular'>{t('appAnnotation.batchModal.answer')}</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className='text-gray-700'>
|
||||
<tr>
|
||||
<td className='h-9 pl-3 pr-2 border-b border-gray-100 text-[13px]'>{t('appAnnotation.batchModal.question')} 1</td>
|
||||
<td className='h-9 pl-3 pr-2 border-b border-gray-100 text-[13px]'>{t('appAnnotation.batchModal.answer')} 1</td>
|
||||
<td className='h-9 pl-3 pr-2 border-b border-divider-subtle text-[13px]'>{t('appAnnotation.batchModal.question')} 1</td>
|
||||
<td className='h-9 pl-3 pr-2 border-b border-divider-subtle text-[13px]'>{t('appAnnotation.batchModal.answer')} 1</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className='h-9 pl-3 pr-2 text-[13px]'>{t('appAnnotation.batchModal.question')} 2</td>
|
||||
@@ -61,7 +61,7 @@ const CSVDownload: FC = () => {
|
||||
bom={true}
|
||||
data={getTemplate()}
|
||||
>
|
||||
<div className='flex items-center h-[18px] space-x-1 text-[#155EEF] text-xs font-medium'>
|
||||
<div className='flex items-center h-[18px] space-x-1 text-text-accent system-xs-medium'>
|
||||
<DownloadIcon className='w-3 h-3 mr-1' />
|
||||
{t('appAnnotation.batchModal.template')}
|
||||
</div>
|
||||
|
||||
@@ -91,29 +91,29 @@ const CSVUploader: FC<Props> = ({
|
||||
/>
|
||||
<div ref={dropRef}>
|
||||
{!file && (
|
||||
<div className={cn('flex items-center h-20 rounded-xl bg-gray-50 border border-dashed border-gray-200 text-sm font-normal', dragging && 'bg-[#F5F8FF] border border-[#B2CCFF]')}>
|
||||
<div className={cn('flex items-center h-20 rounded-xl bg-components-dropzone-bg border border-dashed border-components-dropzone-border system-sm-regular', dragging && 'bg-components-dropzone-bg-accent border border-components-dropzone-border-accent')}>
|
||||
<div className='w-full flex items-center justify-center space-x-2'>
|
||||
<CSVIcon className="shrink-0" />
|
||||
<div className='text-gray-500'>
|
||||
<div className='text-text-tertiary'>
|
||||
{t('appAnnotation.batchModal.csvUploadTitle')}
|
||||
<span className='text-primary-400 cursor-pointer' onClick={selectHandle}>{t('appAnnotation.batchModal.browse')}</span>
|
||||
<span className='text-text-accent cursor-pointer' onClick={selectHandle}>{t('appAnnotation.batchModal.browse')}</span>
|
||||
</div>
|
||||
</div>
|
||||
{dragging && <div ref={dragRef} className='absolute w-full h-full top-0 left-0' />}
|
||||
</div>
|
||||
)}
|
||||
{file && (
|
||||
<div className={cn('flex items-center h-20 px-6 rounded-xl bg-gray-50 border border-gray-200 text-sm font-normal group', 'hover:bg-[#F5F8FF] hover:border-[#B2CCFF]')}>
|
||||
<div className={cn('flex items-center h-20 px-6 rounded-xl bg-components-panel-bg border border-components-panel-border text-sm font-normal group', 'hover:bg-components-panel-bg-blur hover:border-components-panel-bg-blur')}>
|
||||
<CSVIcon className="shrink-0" />
|
||||
<div className='flex ml-2 w-0 grow'>
|
||||
<span className='max-w-[calc(100%_-_30px)] text-ellipsis whitespace-nowrap overflow-hidden text-gray-800'>{file.name.replace(/.csv$/, '')}</span>
|
||||
<span className='shrink-0 text-gray-500'>.csv</span>
|
||||
<span className='max-w-[calc(100%_-_30px)] text-ellipsis whitespace-nowrap overflow-hidden text-text-primary'>{file.name.replace(/.csv$/, '')}</span>
|
||||
<span className='shrink-0 text-text-tertiary'>.csv</span>
|
||||
</div>
|
||||
<div className='hidden group-hover:flex items-center'>
|
||||
<Button className='!h-8 !px-3 !py-[6px] bg-white !text-[13px] !leading-[18px] text-gray-700' onClick={selectHandle}>{t('datasetCreation.stepOne.uploader.change')}</Button>
|
||||
<div className='mx-2 w-px h-4 bg-gray-200' />
|
||||
<Button variant='secondary' onClick={selectHandle}>{t('datasetCreation.stepOne.uploader.change')}</Button>
|
||||
<div className='mx-2 w-px h-4 bg-divider-regular' />
|
||||
<div className='p-2 cursor-pointer' onClick={removeFile}>
|
||||
<RiDeleteBinLine className='w-4 h-4 text-gray-500' />
|
||||
<RiDeleteBinLine className='w-4 h-4 text-text-tertiary' />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -88,9 +88,9 @@ const BatchModal: FC<IBatchModalProps> = ({
|
||||
|
||||
return (
|
||||
<Modal isShow={isShow} onClose={() => { }} className='px-8 py-6 !max-w-[520px] !rounded-xl'>
|
||||
<div className='relative pb-1 text-xl font-medium leading-[30px] text-gray-900'>{t('appAnnotation.batchModal.title')}</div>
|
||||
<div className='relative pb-1 system-xl-medium text-text-primary'>{t('appAnnotation.batchModal.title')}</div>
|
||||
<div className='absolute right-4 top-4 p-2 cursor-pointer' onClick={onCancel}>
|
||||
<RiCloseLine className='w-4 h-4 text-gray-500' />
|
||||
<RiCloseLine className='w-4 h-4 text-text-tertiary' />
|
||||
</div>
|
||||
<CSVUploader
|
||||
file={currentCSV}
|
||||
@@ -105,11 +105,10 @@ const BatchModal: FC<IBatchModalProps> = ({
|
||||
)}
|
||||
|
||||
<div className='mt-[28px] pt-6 flex justify-end'>
|
||||
<Button className='mr-2 text-gray-700 text-sm font-medium' onClick={onCancel}>
|
||||
<Button className='mr-2 text-text-tertiary system-sm-medium' onClick={onCancel}>
|
||||
{t('appAnnotation.batchModal.cancel')}
|
||||
</Button>
|
||||
<Button
|
||||
className='text-sm font-medium'
|
||||
variant="primary"
|
||||
onClick={handleSend}
|
||||
disabled={isAnnotationFull || !currentCSV}
|
||||
|
||||
@@ -2,13 +2,11 @@
|
||||
import type { FC } from 'react'
|
||||
import React, { useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Textarea from 'rc-textarea'
|
||||
import { RiDeleteBinLine } from '@remixicon/react'
|
||||
import cn from '@/utils/classnames'
|
||||
import { RiDeleteBinLine, RiEditFill, RiEditLine } from '@remixicon/react'
|
||||
import { Robot, User } from '@/app/components/base/icons/src/public/avatar'
|
||||
import { Edit04 } from '@/app/components/base/icons/src/vender/line/general'
|
||||
import { Edit04 as EditSolid } from '@/app/components/base/icons/src/vender/solid/general'
|
||||
import Textarea from '@/app/components/base/textarea'
|
||||
import Button from '@/app/components/base/button'
|
||||
import cn from '@/utils/classnames'
|
||||
|
||||
export enum EditItemType {
|
||||
Query = 'query',
|
||||
@@ -22,8 +20,8 @@ type Props = {
|
||||
}
|
||||
|
||||
export const EditTitle: FC<{ className?: string; title: string }> = ({ className, title }) => (
|
||||
<div className={cn(className, 'flex items-center height-[18px] text-xs font-medium text-gray-500')}>
|
||||
<EditSolid className='mr-1 w-3.5 h-3.5' />
|
||||
<div className={cn(className, 'flex items-center h-[18px] system-xs-medium text-text-tertiary')}>
|
||||
<RiEditFill className='mr-1 w-3.5 h-3.5' />
|
||||
<div>{title}</div>
|
||||
<div
|
||||
className='ml-2 grow h-[1px]'
|
||||
@@ -64,32 +62,32 @@ const EditItem: FC<Props> = ({
|
||||
{avatar}
|
||||
</div>
|
||||
<div className='grow'>
|
||||
<div className='mb-1 leading-[18px] text-xs font-semibold text-gray-900'>{name}</div>
|
||||
<div className='leading-5 text-sm font-normal text-gray-900'>{content}</div>
|
||||
<div className='mb-1 system-xs-semibold text-text-primary'>{name}</div>
|
||||
<div className='system-sm-regular text-text-primary'>{content}</div>
|
||||
{!isEdit
|
||||
? (
|
||||
<div>
|
||||
{showNewContent && (
|
||||
<div className='mt-3'>
|
||||
<EditTitle title={editTitle} />
|
||||
<div className='mt-1 leading-5 text-sm font-normal text-gray-900'>{newContent}</div>
|
||||
<div className='mt-1 system-sm-regular text-text-primary'>{newContent}</div>
|
||||
</div>
|
||||
)}
|
||||
<div className='mt-2 flex items-center'>
|
||||
{!readonly && (
|
||||
<div
|
||||
className='flex items-center space-x-1 leading-[18px] text-xs font-medium text-[#155EEF] cursor-pointer'
|
||||
className='flex items-center space-x-1 system-xs-medium text-text-accent cursor-pointer'
|
||||
onClick={() => {
|
||||
setIsEdit(true)
|
||||
}}
|
||||
>
|
||||
<Edit04 className='mr-1 w-3.5 h-3.5' />
|
||||
<RiEditLine className='mr-1 w-3.5 h-3.5' />
|
||||
<div>{t('common.operation.edit')}</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{showNewContent && (
|
||||
<div className='ml-2 flex items-center leading-[18px] text-xs font-medium text-gray-500'>
|
||||
<div className='ml-2 flex items-center system-xs-medium text-text-tertiary'>
|
||||
<div className='mr-2'>·</div>
|
||||
<div
|
||||
className='flex items-center space-x-1 cursor-pointer'
|
||||
@@ -112,10 +110,8 @@ const EditItem: FC<Props> = ({
|
||||
<div className='mt-3'>
|
||||
<EditTitle title={editTitle} />
|
||||
<Textarea
|
||||
className='mt-1 block w-full leading-5 max-h-none text-sm text-gray-700 outline-none appearance-none resize-none'
|
||||
value={newContent}
|
||||
onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => setNewContent(e.target.value)}
|
||||
autoSize={{ minRows: 3 }}
|
||||
placeholder={placeholder}
|
||||
autoFocus
|
||||
/>
|
||||
|
||||
@@ -123,7 +123,7 @@ const EditAnnotationModal: FC<Props> = ({
|
||||
{
|
||||
annotationId
|
||||
? (
|
||||
<div className='px-4 flex h-16 items-center justify-between border-t border-black/5 bg-gray-50 rounded-bl-xl rounded-br-xl leading-[18px] text-[13px] font-medium text-gray-500'>
|
||||
<div className='px-4 flex h-16 items-center justify-between border-t border-divider-subtle bg-background-section-burn rounded-bl-xl rounded-br-xl system-sm-medium text-text-tertiary'>
|
||||
<div
|
||||
className='flex items-center pl-3 space-x-2 cursor-pointer'
|
||||
onClick={() => setShowModal(true)}
|
||||
|
||||
@@ -4,6 +4,7 @@ import React, { Fragment, useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import {
|
||||
RiAddLine,
|
||||
RiMoreFill,
|
||||
} from '@remixicon/react'
|
||||
import { useContext } from 'use-context-selector'
|
||||
import {
|
||||
@@ -14,7 +15,6 @@ import Button from '../../../base/button'
|
||||
import AddAnnotationModal from '../add-annotation-modal'
|
||||
import type { AnnotationItemBasic } from '../type'
|
||||
import BatchAddModal from '../batch-add-annotation-modal'
|
||||
import s from './style.module.css'
|
||||
import cn from '@/utils/classnames'
|
||||
import CustomPopover from '@/app/components/base/popover'
|
||||
import { FileDownload02, FilePlus02 } from '@/app/components/base/icons/src/vender/line/files'
|
||||
@@ -80,17 +80,17 @@ const HeaderOptions: FC<Props> = ({
|
||||
const Operations = () => {
|
||||
return (
|
||||
<div className="w-full py-1">
|
||||
<button className={s.actionItem} onClick={() => {
|
||||
<button className='h-9 py-2 px-3 mx-1 flex items-center space-x-2 hover:bg-components-panel-on-panel-item-bg-hover rounded-lg cursor-pointer disabled:opacity-50 w-[calc(100%_-_8px)]' onClick={() => {
|
||||
setShowBulkImportModal(true)
|
||||
}}>
|
||||
<FilePlus02 className={s.actionItemIcon} />
|
||||
<span className={s.actionName}>{t('appAnnotation.table.header.bulkImport')}</span>
|
||||
<FilePlus02 className='w-4 h-4 text-text-tertiary' />
|
||||
<span className='grow text-text-secondary system-sm-regular text-left'>{t('appAnnotation.table.header.bulkImport')}</span>
|
||||
</button>
|
||||
<Menu as="div" className="relative w-full h-full">
|
||||
<Menu.Button className={s.actionItem}>
|
||||
<FileDownload02 className={s.actionItemIcon} />
|
||||
<span className={s.actionName}>{t('appAnnotation.table.header.bulkExport')}</span>
|
||||
<ChevronRight className='shrink-0 w-[14px] h-[14px] text-gray-500' />
|
||||
<Menu.Button className='h-9 py-2 px-3 mx-1 flex items-center space-x-2 hover:bg-components-panel-on-panel-item-bg-hover rounded-lg cursor-pointer disabled:opacity-50 w-[calc(100%_-_8px)]'>
|
||||
<FileDownload02 className='w-4 h-4 text-text-tertiary' />
|
||||
<span className='grow text-text-secondary system-sm-regular text-left'>{t('appAnnotation.table.header.bulkExport')}</span>
|
||||
<ChevronRight className='shrink-0 w-[14px] h-[14px] text-text-tertiary' />
|
||||
</Menu.Button>
|
||||
<Transition
|
||||
as={Fragment}
|
||||
@@ -103,11 +103,7 @@ const HeaderOptions: FC<Props> = ({
|
||||
>
|
||||
<Menu.Items
|
||||
className={cn(
|
||||
`
|
||||
absolute top-[1px] py-1 min-w-[100px] z-10 bg-white border-[0.5px] border-gray-200
|
||||
divide-y divide-gray-100 origin-top-right rounded-xl
|
||||
`,
|
||||
s.popup,
|
||||
'absolute top-[1px] left-1 -translate-x-full py-1 min-w-[100px] z-10 bg-components-panel-bg border-[0.5px] border-components-panel-on-panel-item-bg origin-top-right rounded-xl shadow-xs',
|
||||
)}
|
||||
>
|
||||
<CSVDownloader
|
||||
@@ -119,12 +115,12 @@ const HeaderOptions: FC<Props> = ({
|
||||
...list.map(item => [item.question, item.answer]),
|
||||
]}
|
||||
>
|
||||
<button disabled={annotationUnavailable} className={s.actionItem}>
|
||||
<span className={s.actionName}>CSV</span>
|
||||
<button disabled={annotationUnavailable} className='h-9 py-2 px-3 mx-1 flex items-center space-x-2 hover:bg-components-panel-on-panel-item-bg-hover rounded-lg cursor-pointer disabled:opacity-50 w-[calc(100%_-_8px)]'>
|
||||
<span className='grow text-text-secondary system-sm-regular text-left'>CSV</span>
|
||||
</button>
|
||||
</CSVDownloader>
|
||||
<button disabled={annotationUnavailable} className={cn(s.actionItem, '!border-0')} onClick={JSONLOutput}>
|
||||
<span className={s.actionName}>JSONL</span>
|
||||
<button disabled={annotationUnavailable} className={cn('h-9 py-2 px-3 mx-1 flex items-center space-x-2 hover:bg-components-panel-on-panel-item-bg-hover rounded-lg cursor-pointer disabled:opacity-50 w-[calc(100%_-_8px)]', '!border-0')} onClick={JSONLOutput}>
|
||||
<span className='grow text-text-secondary system-sm-regular text-left'>JSONL</span>
|
||||
</button>
|
||||
</Menu.Items>
|
||||
</Transition>
|
||||
@@ -137,21 +133,20 @@ const HeaderOptions: FC<Props> = ({
|
||||
|
||||
return (
|
||||
<div className='flex space-x-2'>
|
||||
<Button variant='primary' onClick={() => setShowAddModal(true)} className='flex items-center !h-8 !px-3 !text-[13px] space-x-2'>
|
||||
<RiAddLine className='w-4 h-4' />
|
||||
<Button variant='primary' onClick={() => setShowAddModal(true)}>
|
||||
<RiAddLine className='w-4 h-4 mr-0.5' />
|
||||
<div>{t('appAnnotation.table.header.addAnnotation')}</div>
|
||||
</Button>
|
||||
<CustomPopover
|
||||
htmlContent={<Operations />}
|
||||
position="br"
|
||||
trigger="click"
|
||||
btnElement={<div className={cn(s.actionIcon, s.commonIcon)} />}
|
||||
btnClassName={open =>
|
||||
cn(
|
||||
open ? 'border-gray-300 !bg-gray-100 !shadow-none' : 'border-gray-200',
|
||||
s.actionIconWrapper,
|
||||
)
|
||||
btnElement={
|
||||
<Button variant='secondary' className='w-8 p-0'>
|
||||
<RiMoreFill className='w-4 h-4' />
|
||||
</Button>
|
||||
}
|
||||
btnClassName='p-0 border-0'
|
||||
className={'!w-[155px] h-fit !z-20'}
|
||||
popupClassName='!w-full !overflow-visible'
|
||||
manualClose
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
.actionIconWrapper {
|
||||
@apply h-8 w-8 p-2 rounded-md hover:bg-gray-100 !important;
|
||||
}
|
||||
|
||||
.commonIcon {
|
||||
@apply w-4 h-4 inline-block align-middle;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center center;
|
||||
background-size: contain;
|
||||
}
|
||||
|
||||
.actionIcon {
|
||||
@apply bg-gray-500;
|
||||
mask-image: url(~@/assets/action.svg);
|
||||
}
|
||||
|
||||
.actionItemIcon {
|
||||
@apply w-4 h-4 text-gray-500;
|
||||
}
|
||||
|
||||
.actionItem {
|
||||
@apply h-9 py-2 px-3 mx-1 flex items-center space-x-2 hover:bg-gray-100 rounded-lg cursor-pointer disabled:opacity-50;
|
||||
width: calc(100% - 0.5rem);
|
||||
}
|
||||
|
||||
.deleteActionItem {
|
||||
@apply hover:bg-red-50 !important;
|
||||
}
|
||||
|
||||
.actionName {
|
||||
@apply grow text-gray-700 text-sm text-left;
|
||||
}
|
||||
|
||||
.popup {
|
||||
left: 4px;
|
||||
transform: translateX(-100%);
|
||||
box-shadow: 0px 12px 16px -4px rgba(16, 24, 40, 0.08), 0px 4px 6px -2px rgba(16, 24, 40, 0.03);
|
||||
}
|
||||
@@ -3,6 +3,7 @@ import type { FC } from 'react'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useDebounce } from 'ahooks'
|
||||
import { RiEqualizer2Line } from '@remixicon/react'
|
||||
import Toast from '../../base/toast'
|
||||
import Filter from './filter'
|
||||
import type { QueryParam } from './filter'
|
||||
@@ -11,7 +12,8 @@ import EmptyElement from './empty-element'
|
||||
import HeaderOpts from './header-opts'
|
||||
import { AnnotationEnableStatus, type AnnotationItem, type AnnotationItemBasic, JobStatus } from './type'
|
||||
import ViewAnnotationModal from './view-annotation-modal'
|
||||
import cn from '@/utils/classnames'
|
||||
import { MessageFast } from '@/app/components/base/icons/src/vender/solid/communication'
|
||||
import ActionButton from '@/app/components/base/action-button'
|
||||
import Pagination from '@/app/components/base/pagination'
|
||||
import Switch from '@/app/components/base/switch'
|
||||
import { addAnnotation, delAnnotation, fetchAnnotationConfig as doFetchAnnotationConfig, editAnnotation, fetchAnnotationList, queryAnnotationJobStatus, updateAnnotationScore, updateAnnotationStatus } from '@/service/annotation'
|
||||
@@ -22,8 +24,8 @@ import type { AnnotationReplyConfig } from '@/models/debug'
|
||||
import { sleep } from '@/utils'
|
||||
import { useProviderContext } from '@/context/provider-context'
|
||||
import AnnotationFullModal from '@/app/components/billing/annotation-full/modal'
|
||||
import { Settings04 } from '@/app/components/base/icons/src/vender/line/general'
|
||||
import type { App } from '@/types/app'
|
||||
import cn from '@/utils/classnames'
|
||||
|
||||
type Props = {
|
||||
appDetail: App
|
||||
@@ -157,8 +159,9 @@ const Annotation: FC<Props> = ({
|
||||
<div className='flex items-center space-x-2'>
|
||||
{isChatApp && (
|
||||
<>
|
||||
<div className={cn(!annotationConfig?.enabled && 'pr-2', 'flex items-center h-7 rounded-lg border border-gray-200 pl-2 space-x-1')}>
|
||||
<div className='leading-[18px] text-[13px] font-medium text-gray-900'>{t('appAnnotation.name')}</div>
|
||||
<div className={cn(!annotationConfig?.enabled && 'pr-2', 'flex items-center h-7 rounded-lg bg-components-panel-bg-blur border border-components-panel-border pl-2 space-x-1')}>
|
||||
<MessageFast className='w-4 h-4 text-util-colors-indigo-indigo-600' />
|
||||
<div className='system-sm-medium text-text-primary'>{t('appAnnotation.name')}</div>
|
||||
<Switch
|
||||
key={controlRefreshSwitch}
|
||||
defaultValue={annotationConfig?.enabled}
|
||||
@@ -185,22 +188,14 @@ const Annotation: FC<Props> = ({
|
||||
></Switch>
|
||||
{annotationConfig?.enabled && (
|
||||
<div className='flex items-center pl-1.5'>
|
||||
<div className='shrink-0 mr-1 w-[1px] h-3.5 bg-gray-200'></div>
|
||||
<div
|
||||
className={`
|
||||
shrink-0 h-7 w-7 flex items-center justify-center
|
||||
text-xs text-gray-700 font-medium
|
||||
`}
|
||||
onClick={() => { setIsShowEdit(true) }}
|
||||
>
|
||||
<div className='flex h-6 w-6 items-center justify-center rounded-md cursor-pointer hover:bg-gray-200'>
|
||||
<Settings04 className='w-4 h-4' />
|
||||
</div>
|
||||
</div>
|
||||
<div className='shrink-0 mr-1 w-[1px] h-3.5 bg-divider-subtle'></div>
|
||||
<ActionButton onClick={() => setIsShowEdit(true)}>
|
||||
<RiEqualizer2Line className='w-4 h-4 text-text-tertiary' />
|
||||
</ActionButton>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className='shrink-0 mx-3 w-[1px] h-3.5 bg-gray-200'></div>
|
||||
<div className='shrink-0 mx-3 w-[1px] h-3.5 bg-divider-regular'></div>
|
||||
</>
|
||||
)}
|
||||
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
import type { FC } from 'react'
|
||||
import React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { RiDeleteBinLine } from '@remixicon/react'
|
||||
import { Edit02 } from '../../base/icons/src/vender/line/general'
|
||||
import { RiDeleteBinLine, RiEditLine } from '@remixicon/react'
|
||||
import type { AnnotationItem } from './type'
|
||||
import RemoveAnnotationConfirmModal from './remove-annotation-confirm-modal'
|
||||
import cn from '@/utils/classnames'
|
||||
import ActionButton from '@/app/components/base/action-button'
|
||||
import useTimestamp from '@/hooks/use-timestamp'
|
||||
import cn from '@/utils/classnames'
|
||||
|
||||
type Props = {
|
||||
list: AnnotationItem[]
|
||||
@@ -59,26 +59,18 @@ const List: FC<Props> = ({
|
||||
<td className='p-3 pr-2'>{item.hit_count}</td>
|
||||
<td className='w-[96px] p-3 pr-2' onClick={e => e.stopPropagation()}>
|
||||
{/* Actions */}
|
||||
<div className='flex space-x-2 text-gray-500'>
|
||||
<div
|
||||
className='p-1 cursor-pointer rounded-md hover:bg-black/5'
|
||||
onClick={
|
||||
() => {
|
||||
onView(item)
|
||||
}
|
||||
}
|
||||
>
|
||||
<Edit02 className='w-4 h-4' />
|
||||
</div>
|
||||
<div
|
||||
className='p-1 cursor-pointer rounded-md hover:bg-black/5'
|
||||
<div className='flex space-x-1 text-text-tertiary'>
|
||||
<ActionButton onClick={() => onView(item)}>
|
||||
<RiEditLine className='w-4 h-4' />
|
||||
</ActionButton>
|
||||
<ActionButton
|
||||
onClick={() => {
|
||||
setCurrId(item.id)
|
||||
setShowConfirmDelete(true)
|
||||
}}
|
||||
>
|
||||
<RiDeleteBinLine className='w-4 h-4' />
|
||||
</div>
|
||||
</ActionButton>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@@ -7,11 +7,11 @@ import { ClockFastForward } from '@/app/components/base/icons/src/vender/line/ti
|
||||
const HitHistoryNoData: FC = () => {
|
||||
const { t } = useTranslation()
|
||||
return (
|
||||
<div className='mx-auto mt-20 w-[480px] p-5 rounded-2xl bg-gray-50 space-y-2'>
|
||||
<div className='inline-block p-3 rounded-lg border border-gray-200'>
|
||||
<ClockFastForward className='w-5 h-5 text-gray-500' />
|
||||
<div className='mx-auto mt-20 w-[480px] p-5 rounded-2xl bg-background-section-burn space-y-2'>
|
||||
<div className='inline-block p-3 rounded-lg border border-divider-subtle'>
|
||||
<ClockFastForward className='w-5 h-5 text-text-tertiary' />
|
||||
</div>
|
||||
<div className='leading-5 text-sm font-normal text-gray-500'>{t('appAnnotation.viewModal.noHitHistory')}</div>
|
||||
<div className='system-sm-regular text-text-tertiary'>{t('appAnnotation.viewModal.noHitHistory')}</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -4,17 +4,17 @@ import React, { useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import EditItem, { EditItemType } from '../edit-annotation-modal/edit-item'
|
||||
import type { AnnotationItem, HitHistoryItem } from '../type'
|
||||
import s from './style.module.css'
|
||||
import HitHistoryNoData from './hit-history-no-data'
|
||||
import cn from '@/utils/classnames'
|
||||
import Pagination from '@/app/components/base/pagination'
|
||||
import Badge from '@/app/components/base/badge'
|
||||
import Drawer from '@/app/components/base/drawer-plus'
|
||||
import Pagination from '@/app/components/base/pagination'
|
||||
import { MessageCheckRemove } from '@/app/components/base/icons/src/vender/line/communication'
|
||||
import Confirm from '@/app/components/base/confirm'
|
||||
import TabSlider from '@/app/components/base/tab-slider-plain'
|
||||
import { fetchHitHistoryList } from '@/service/annotation'
|
||||
import { APP_PAGE_LIMIT } from '@/config'
|
||||
import useTimestamp from '@/hooks/use-timestamp'
|
||||
import cn from '@/utils/classnames'
|
||||
|
||||
type Props = {
|
||||
appId: string
|
||||
@@ -72,7 +72,9 @@ const ViewAnnotationModal: FC<Props> = ({
|
||||
? (
|
||||
<div className='flex items-center space-x-1'>
|
||||
<div>{t('appAnnotation.viewModal.hitHistory')}</div>
|
||||
<div className='flex px-1.5 item-center rounded-md border border-black/[8%] h-5 text-xs font-medium text-gray-500'>{total} {t(`appAnnotation.viewModal.hit${hitHistoryList.length > 1 ? 's' : ''}`)}</div>
|
||||
<Badge
|
||||
text={`${total} ${t(`appAnnotation.viewModal.hit${hitHistoryList.length > 1 ? 's' : ''}`)}`}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
: t('appAnnotation.viewModal.hitHistory')
|
||||
@@ -111,44 +113,45 @@ const ViewAnnotationModal: FC<Props> = ({
|
||||
? (<HitHistoryNoData />)
|
||||
: (
|
||||
<div>
|
||||
<table className={cn(s.table, 'w-full min-w-[440px] border-collapse border-0 text-sm')} >
|
||||
<thead className="h-8 leading-8 border-b border-gray-200 text-gray-500 font-bold">
|
||||
<tr className='uppercase'>
|
||||
<td className='whitespace-nowrap'>{t('appAnnotation.hitHistoryTable.query')}</td>
|
||||
<td className='whitespace-nowrap'>{t('appAnnotation.hitHistoryTable.match')}</td>
|
||||
<td className='whitespace-nowrap'>{t('appAnnotation.hitHistoryTable.response')}</td>
|
||||
<td className='whitespace-nowrap'>{t('appAnnotation.hitHistoryTable.source')}</td>
|
||||
<td className='whitespace-nowrap'>{t('appAnnotation.hitHistoryTable.score')}</td>
|
||||
<td className='whitespace-nowrap w-[160px]'>{t('appAnnotation.hitHistoryTable.time')}</td>
|
||||
<table className={cn('w-full min-w-[440px] border-collapse border-0')} >
|
||||
<thead className="system-xs-medium-uppercase text-text-tertiary">
|
||||
<tr>
|
||||
<td className='pl-2 pr-1 w-5 rounded-l-lg bg-background-section-burn whitespace-nowrap'>{t('appAnnotation.hitHistoryTable.query')}</td>
|
||||
<td className='pl-3 py-1.5 bg-background-section-burn whitespace-nowrap'>{t('appAnnotation.hitHistoryTable.match')}</td>
|
||||
<td className='pl-3 py-1.5 bg-background-section-burn whitespace-nowrap'>{t('appAnnotation.hitHistoryTable.response')}</td>
|
||||
<td className='pl-3 py-1.5 bg-background-section-burn whitespace-nowrap'>{t('appAnnotation.hitHistoryTable.source')}</td>
|
||||
<td className='pl-3 py-1.5 bg-background-section-burn whitespace-nowrap'>{t('appAnnotation.hitHistoryTable.score')}</td>
|
||||
<td className='pl-3 py-1.5 rounded-r-lg bg-background-section-burn whitespace-nowrap w-[160px]'>{t('appAnnotation.hitHistoryTable.time')}</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="text-gray-500">
|
||||
<tbody className="text-text-secondary system-sm-regular">
|
||||
{hitHistoryList.map(item => (
|
||||
<tr
|
||||
key={item.id}
|
||||
className={'border-b border-gray-200 h-8 hover:bg-gray-50 cursor-pointer'}
|
||||
className={'border-b border-divider-subtle hover:bg-background-default-hover cursor-pointer'}
|
||||
>
|
||||
<td
|
||||
className='whitespace-nowrap overflow-hidden text-ellipsis max-w-[250px]'
|
||||
className='p-3 pr-2 whitespace-nowrap overflow-hidden text-ellipsis max-w-[250px]'
|
||||
title={item.question}
|
||||
>{item.question}</td>
|
||||
<td
|
||||
className='whitespace-nowrap overflow-hidden text-ellipsis max-w-[250px]'
|
||||
className='p-3 pr-2 whitespace-nowrap overflow-hidden text-ellipsis max-w-[250px]'
|
||||
title={item.match}
|
||||
>{item.match}</td>
|
||||
<td
|
||||
className='whitespace-nowrap overflow-hidden text-ellipsis max-w-[250px]'
|
||||
className='p-3 pr-2 whitespace-nowrap overflow-hidden text-ellipsis max-w-[250px]'
|
||||
title={item.response}
|
||||
>{item.response}</td>
|
||||
<td>{item.source}</td>
|
||||
<td>{item.score ? item.score.toFixed(2) : '-'}</td>
|
||||
<td>{formatTime(item.created_at, t('appLog.dateTimeFormat') as string)}</td>
|
||||
<td className='p-3 pr-2'>{item.source}</td>
|
||||
<td className='p-3 pr-2'>{item.score ? item.score.toFixed(2) : '-'}</td>
|
||||
<td className='p-3 pr-2'>{formatTime(item.created_at, t('appLog.dateTimeFormat') as string)}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
{(total && total > APP_PAGE_LIMIT)
|
||||
? <Pagination
|
||||
className='px-0'
|
||||
current={currPage}
|
||||
onChange={setCurrPage}
|
||||
total={total}
|
||||
@@ -163,7 +166,6 @@ const ViewAnnotationModal: FC<Props> = ({
|
||||
isShow={isShow}
|
||||
onHide={onHide}
|
||||
maxWidthClassName='!max-w-[800px]'
|
||||
// t('appAnnotation.editModal.title') as string
|
||||
title={
|
||||
<TabSlider
|
||||
className='shrink-0 relative top-[9px]'
|
||||
@@ -193,7 +195,7 @@ const ViewAnnotationModal: FC<Props> = ({
|
||||
)}
|
||||
foot={id
|
||||
? (
|
||||
<div className='px-4 flex h-16 items-center justify-between border-t border-black/5 bg-gray-50 rounded-bl-xl rounded-br-xl leading-[18px] text-[13px] font-medium text-gray-500'>
|
||||
<div className='px-4 flex h-16 items-center justify-between border-t border-divider-subtle bg-background-section-burn rounded-bl-xl rounded-br-xl system-sm-medium text-text-tertiary'>
|
||||
<div
|
||||
className='flex items-center pl-3 space-x-2 cursor-pointer'
|
||||
onClick={() => setShowModal(true)}
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
.table td {
|
||||
padding: 7px 8px;
|
||||
box-sizing: border-box;
|
||||
max-width: 200px;
|
||||
}
|
||||
|
||||
.pagination li {
|
||||
list-style: none;
|
||||
}
|
||||
Reference in New Issue
Block a user