diff --git a/web/app/components/app/annotation/header-opts/index.tsx b/web/app/components/app/annotation/header-opts/index.tsx index 58bc31d12e..b5c749bcd7 100644 --- a/web/app/components/app/annotation/header-opts/index.tsx +++ b/web/app/components/app/annotation/header-opts/index.tsx @@ -1,12 +1,13 @@ 'use client' import type { FC } from 'react' -import React, { useEffect, useState } from 'react' +import React, { Fragment, useEffect, useState } from 'react' import { useTranslation } from 'react-i18next' import cn from 'classnames' import { useContext } from 'use-context-selector' import { useCSVDownloader, } from 'react-papaparse' +import { Menu, Transition } from '@headlessui/react' import Button from '../../../base/button' import { Plus } from '../../../base/icons/src/vender/line/general' import AddAnnotationModal from '../add-annotation-modal' @@ -15,9 +16,12 @@ import BatchAddModal from '../batch-add-annotation-modal' import s from './style.module.css' import CustomPopover from '@/app/components/base/popover' import { FileDownload02, FilePlus02 } from '@/app/components/base/icons/src/vender/line/files' +import { ChevronRight } from '@/app/components/base/icons/src/vender/line/arrows' + import I18n from '@/context/i18n' import { fetchExportAnnotationList } from '@/service/annotation' import { LanguagesSupportedUnderscore, getModelRuntimeSupported } from '@/utils/language' + const CSV_HEADER_QA_EN = ['Question', 'Answer'] const CSV_HEADER_QA_CN = ['问题', '答案'] @@ -26,14 +30,12 @@ type Props = { onAdd: (payload: AnnotationItemBasic) => void onAdded: () => void controlUpdateList: number - // onClearAll: () => void } const HeaderOptions: FC = ({ appId, onAdd, onAdded, - // onClearAll, controlUpdateList, }) => { const { t } = useTranslation() @@ -41,6 +43,23 @@ const HeaderOptions: FC = ({ const language = getModelRuntimeSupported(locale) const { CSVDownloader, Type } = useCSVDownloader() const [list, setList] = useState([]) + + const listTransformer = (list: AnnotationItemBasic[]) => list.map( + (item: AnnotationItemBasic) => { + const dataString = `{"messages": [{"role": "system", "content": ""}, {"role": "user", "content": ${JSON.stringify(item.question)}}, {"role": "assistant", "content": ${JSON.stringify(item.answer)}}]}` + return dataString + }, + ) + + const JSONLOutput = () => { + const a = document.createElement('a') + const content = listTransformer(list).join('\n') + const file = new Blob([content], { type: 'application/jsonl' }) + a.href = URL.createObjectURL(file) + a.download = `annotations-${language}.jsonl` + a.click() + } + const fetchList = async () => { const { data }: any = await fetchExportAnnotationList(appId) setList(data as AnnotationItemBasic[]) @@ -65,32 +84,49 @@ const HeaderOptions: FC = ({ {t('appAnnotation.table.header.bulkImport')} - - [item.question, item.answer]), - ]} - > - - - - {/* -
- - - {t('appAnnotation.table.header.clearAll')} - -
*/} + + + + + [item.question, item.answer]), + ]} + > + + + + + + ) } @@ -114,9 +150,8 @@ const HeaderOptions: FC = ({ s.actionIconWrapper, ) } - // !w-[208px] - className={'!w-[135px] h-fit !z-20'} - popupClassName='!w-full' + className={'!w-[154px] h-fit !z-20'} + popupClassName='!w-full !overflow-visible' manualClose /> {showAddModal && ( diff --git a/web/app/components/app/annotation/header-opts/style.module.css b/web/app/components/app/annotation/header-opts/style.module.css index f568387f60..29d43f449d 100644 --- a/web/app/components/app/annotation/header-opts/style.module.css +++ b/web/app/components/app/annotation/header-opts/style.module.css @@ -28,5 +28,11 @@ } .actionName { - @apply text-gray-700 text-sm; + @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); } \ No newline at end of file