chore:run once file
parent
ea9278e29c
commit
cb61ead939
@ -0,0 +1,5 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M3.66699 1.33366C3.66699 0.965469 3.36852 0.666992 3.00033 0.666992C2.63214 0.666992 2.33366 0.965469 2.33366 1.33366V2.33366H1.33366C0.965469 2.33366 0.666992 2.63214 0.666992 3.00033C0.666992 3.36852 0.965469 3.66699 1.33366 3.66699H2.33366V4.66699C2.33366 5.03518 2.63214 5.33366 3.00033 5.33366C3.36852 5.33366 3.66699 5.03518 3.66699 4.66699V3.66699H4.66699C5.03518 3.66699 5.33366 3.36852 5.33366 3.00033C5.33366 2.63214 5.03518 2.33366 4.66699 2.33366H3.66699V1.33366Z" fill="#444CE7"/>
|
||||
<path d="M3.66699 11.3337C3.66699 10.9655 3.36852 10.667 3.00033 10.667C2.63214 10.667 2.33366 10.9655 2.33366 11.3337V12.3337H1.33366C0.965469 12.3337 0.666992 12.6321 0.666992 13.0003C0.666992 13.3685 0.965469 13.667 1.33366 13.667H2.33366V14.667C2.33366 15.0352 2.63214 15.3337 3.00033 15.3337C3.36852 15.3337 3.66699 15.0352 3.66699 14.667V13.667H4.66699C5.03518 13.667 5.33366 13.3685 5.33366 13.0003C5.33366 12.6321 5.03518 12.3337 4.66699 12.3337H3.66699V11.3337Z" fill="#444CE7"/>
|
||||
<path d="M9.28922 1.76101C9.1902 1.50354 8.94284 1.33366 8.66699 1.33366C8.39114 1.33366 8.14378 1.50354 8.04476 1.76101L6.88864 4.76691C6.68837 5.28761 6.62544 5.43766 6.53936 5.55872C6.45299 5.68019 6.34686 5.78632 6.22539 5.87269C6.10432 5.95878 5.95428 6.02171 5.43358 6.22198L2.42767 7.37809C2.17021 7.47712 2.00033 7.72448 2.00033 8.00033C2.00033 8.27617 2.17021 8.52353 2.42767 8.62256L5.43358 9.77867C5.95428 9.97894 6.10432 10.0419 6.22539 10.128C6.34686 10.2143 6.45299 10.3205 6.53936 10.4419C6.62544 10.563 6.68837 10.713 6.88864 11.2337L8.04476 14.2396C8.14379 14.4971 8.39114 14.667 8.66699 14.667C8.94284 14.667 9.1902 14.4971 9.28922 14.2396L10.4453 11.2337C10.6456 10.713 10.7085 10.563 10.7946 10.4419C10.881 10.3205 10.9871 10.2143 11.1086 10.128C11.2297 10.0419 11.3797 9.97894 11.9004 9.77867L14.9063 8.62256C15.1638 8.52353 15.3337 8.27617 15.3337 8.00033C15.3337 7.72448 15.1638 7.47712 14.9063 7.37809L11.9004 6.22198C11.3797 6.02171 11.2297 5.95878 11.1086 5.87269C10.9871 5.78632 10.881 5.68019 10.7946 5.55872C10.7085 5.43766 10.6456 5.28761 10.4453 4.76691L9.28922 1.76101Z" fill="#444CE7"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.2 KiB |
@ -0,0 +1,26 @@
|
||||
import type { FC } from 'react'
|
||||
import React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
const StarIcon = (
|
||||
<svg width="50" height="50" viewBox="0 0 50 50" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M7.50033 48.3337V36.667M7.50033 13.3337V1.66699M1.66699 7.50033H13.3337M1.66699 42.5003H13.3337M27.3337 4.00032L23.2872 14.521C22.6292 16.2319 22.3002 17.0873 21.7886 17.8069C21.3351 18.4446 20.7779 19.0018 20.1402 19.4552C19.4206 19.9669 18.5652 20.2959 16.8543 20.9539L6.33366 25.0003L16.8543 29.0467C18.5652 29.7048 19.4206 30.0338 20.1402 30.5454C20.7779 30.9989 21.3351 31.5561 21.7886 32.1938C22.3002 32.9133 22.6292 33.7688 23.2872 35.4796L27.3337 46.0003L31.3801 35.4796C32.0381 33.7688 32.3671 32.9133 32.8788 32.1938C33.3322 31.5561 33.8894 30.9989 34.5271 30.5454C35.2467 30.0338 36.1021 29.7048 37.813 29.0467L48.3337 25.0003L37.813 20.9539C36.1021 20.2959 35.2467 19.9669 34.5271 19.4552C33.8894 19.0018 33.3322 18.4446 32.8788 17.8069C32.3671 17.0873 32.0381 16.2319 31.3801 14.521L27.3337 4.00032Z" stroke="#EAECF0" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round" />
|
||||
</svg>
|
||||
|
||||
)
|
||||
|
||||
export type INoDataProps = {}
|
||||
const NoData: FC<INoDataProps> = () => {
|
||||
const { t } = useTranslation()
|
||||
return (
|
||||
<div className='flex flex-col h-full w-full justify-center items-center'>
|
||||
{StarIcon}
|
||||
<div
|
||||
className='mt-3 text-gray-300 text-xs leading-3'
|
||||
>
|
||||
{t('share.generation.noData')}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
export default React.memo(NoData)
|
||||
@ -0,0 +1,34 @@
|
||||
import type { FC } from 'react'
|
||||
import React from 'react'
|
||||
import Header from './header'
|
||||
import type { FeedbackType } from '@/app/components/base/chat/chat/type'
|
||||
import { format } from '@/service/base'
|
||||
|
||||
export type IResultProps = {
|
||||
content: string
|
||||
showFeedback: boolean
|
||||
feedback: FeedbackType
|
||||
onFeedback: (feedback: FeedbackType) => void
|
||||
}
|
||||
const Result: FC<IResultProps> = ({
|
||||
content,
|
||||
showFeedback,
|
||||
feedback,
|
||||
onFeedback,
|
||||
}) => {
|
||||
return (
|
||||
<div className='basis-3/4 h-max'>
|
||||
<Header result={content} showFeedback={showFeedback} feedback={feedback} onFeedback={onFeedback} />
|
||||
<div
|
||||
className='mt-4 w-full flex text-sm leading-5 overflow-scroll font-normal text-gray-900'
|
||||
style={{
|
||||
maxHeight: '70vh',
|
||||
}}
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: format(content),
|
||||
}}
|
||||
></div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
export default React.memo(Result)
|
||||
@ -0,0 +1,113 @@
|
||||
'use client'
|
||||
import type { FC } from 'react'
|
||||
import React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { ClipboardDocumentIcon, HandThumbDownIcon, HandThumbUpIcon } from '@heroicons/react/24/outline'
|
||||
import copy from 'copy-to-clipboard'
|
||||
import type { FeedbackType } from '@/app/components/base/chat/chat/type'
|
||||
import Button from '@/app/components/base/button'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
|
||||
type IResultHeaderProps = {
|
||||
result: string
|
||||
showFeedback: boolean
|
||||
feedback: FeedbackType
|
||||
onFeedback: (feedback: FeedbackType) => void
|
||||
}
|
||||
|
||||
const Header: FC<IResultHeaderProps> = ({
|
||||
feedback,
|
||||
showFeedback,
|
||||
onFeedback,
|
||||
result,
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
return (
|
||||
<div className='flex w-full justify-between items-center '>
|
||||
<div className='text-gray-800 text-2xl leading-4 font-normal'>{t('share.generation.resultTitle')}</div>
|
||||
<div className='flex items-center space-x-2'>
|
||||
<Button
|
||||
className='h-7 p-[2px] pr-2'
|
||||
onClick={() => {
|
||||
copy(result)
|
||||
Toast.notify({ type: 'success', message: 'copied' })
|
||||
}}
|
||||
>
|
||||
<>
|
||||
<ClipboardDocumentIcon className='text-gray-500 w-4 h-3 mr-1' />
|
||||
<span className='text-gray-500 text-xs leading-3'>{t('share.generation.copy')}</span>
|
||||
</>
|
||||
</Button>
|
||||
|
||||
{showFeedback && feedback.rating && feedback.rating === 'like' && (
|
||||
<Tooltip
|
||||
popupContent="Undo Great Rating"
|
||||
>
|
||||
<div
|
||||
onClick={() => {
|
||||
onFeedback({
|
||||
rating: null,
|
||||
})
|
||||
}}
|
||||
className='flex w-7 h-7 items-center justify-center rounded-md cursor-pointer !text-primary-600 border border-primary-200 bg-primary-100 hover:border-primary-300 hover:bg-primary-200'>
|
||||
<HandThumbUpIcon width={16} height={16} />
|
||||
</div>
|
||||
</Tooltip>
|
||||
)}
|
||||
|
||||
{showFeedback && feedback.rating && feedback.rating === 'dislike' && (
|
||||
<Tooltip
|
||||
popupContent="Undo Undesirable Response"
|
||||
>
|
||||
<div
|
||||
onClick={() => {
|
||||
onFeedback({
|
||||
rating: null,
|
||||
})
|
||||
}}
|
||||
className='flex w-7 h-7 items-center justify-center rounded-md cursor-pointer !text-red-600 border border-red-200 bg-red-100 hover:border-red-300 hover:bg-red-200'>
|
||||
<HandThumbDownIcon width={16} height={16} />
|
||||
</div>
|
||||
</Tooltip>
|
||||
)}
|
||||
|
||||
{showFeedback && !feedback.rating && (
|
||||
<div className='flex rounded-lg border border-gray-200 p-[1px] space-x-1'>
|
||||
<Tooltip
|
||||
popupContent="Great Rating"
|
||||
needsDelay={false}
|
||||
>
|
||||
<div
|
||||
onClick={() => {
|
||||
onFeedback({
|
||||
rating: 'like',
|
||||
})
|
||||
}}
|
||||
className='flex w-6 h-6 items-center justify-center rounded-md cursor-pointer hover:bg-gray-100'>
|
||||
<HandThumbUpIcon width={16} height={16} />
|
||||
</div>
|
||||
</Tooltip>
|
||||
<Tooltip
|
||||
popupContent="Undesirable Response"
|
||||
needsDelay={false}
|
||||
>
|
||||
<div
|
||||
onClick={() => {
|
||||
onFeedback({
|
||||
rating: 'dislike',
|
||||
})
|
||||
}}
|
||||
className='flex w-6 h-6 items-center justify-center rounded-md cursor-pointer hover:bg-gray-100'>
|
||||
<HandThumbDownIcon width={16} height={16} />
|
||||
</div>
|
||||
</Tooltip>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default React.memo(Header)
|
||||
@ -0,0 +1,70 @@
|
||||
'use client'
|
||||
import type { FC } from 'react'
|
||||
import React from 'react'
|
||||
import {
|
||||
useCSVDownloader,
|
||||
} from 'react-papaparse'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Download02 as DownloadIcon } from '@/app/components/base/icons/src/vender/solid/general'
|
||||
|
||||
export type ICSVDownloadProps = {
|
||||
vars: { name: string }[]
|
||||
}
|
||||
|
||||
const CSVDownload: FC<ICSVDownloadProps> = ({
|
||||
vars,
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
const { CSVDownloader, Type } = useCSVDownloader()
|
||||
const addQueryContentVars = [...vars]
|
||||
const template = (() => {
|
||||
const res: Record<string, string> = {}
|
||||
addQueryContentVars.forEach((item) => {
|
||||
res[item.name] = ''
|
||||
})
|
||||
return res
|
||||
})()
|
||||
|
||||
return (
|
||||
<div className='mt-6'>
|
||||
<div className='text-sm text-gray-900 font-medium'>{t('share.generation.csvStructureTitle')}</div>
|
||||
<div className='mt-2 max-h-[500px] overflow-auto'>
|
||||
<table className='w-full border-separate border-spacing-0 border border-gray-200 rounded-lg text-xs'>
|
||||
<thead className='text-gray-500'>
|
||||
<tr>
|
||||
{addQueryContentVars.map((item, i) => (
|
||||
<td key={i} className='h-9 pl-4 border-b border-gray-200'>{item.name}</td>
|
||||
))}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className='text-gray-300'>
|
||||
<tr>
|
||||
{addQueryContentVars.map((item, i) => (
|
||||
<td key={i} className='h-9 pl-4'>{item.name} {t('share.generation.field')}</td>
|
||||
))}
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<CSVDownloader
|
||||
className="block mt-2 cursor-pointer"
|
||||
type={Type.Link}
|
||||
filename={'template'}
|
||||
bom={true}
|
||||
config={{
|
||||
// delimiter: ';',
|
||||
}}
|
||||
data={[
|
||||
template,
|
||||
]}
|
||||
>
|
||||
<div className='flex items-center h-[18px] space-x-1 text-[#155EEF] text-xs font-medium'>
|
||||
<DownloadIcon className='w-3 h-3' />
|
||||
<span>{t('share.generation.downloadTemplate')}</span>
|
||||
</div>
|
||||
</CSVDownloader>
|
||||
</div>
|
||||
|
||||
)
|
||||
}
|
||||
export default React.memo(CSVDownload)
|
||||
@ -0,0 +1,70 @@
|
||||
'use client'
|
||||
import type { FC } from 'react'
|
||||
import React, { useState } from 'react'
|
||||
import {
|
||||
useCSVReader,
|
||||
} from 'react-papaparse'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import s from './style.module.css'
|
||||
import cn from '@/utils/classnames'
|
||||
import { Csv as CSVIcon } from '@/app/components/base/icons/src/public/files'
|
||||
|
||||
export type Props = {
|
||||
onParsed: (data: string[][]) => void
|
||||
}
|
||||
|
||||
const CSVReader: FC<Props> = ({
|
||||
onParsed,
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
const { CSVReader } = useCSVReader()
|
||||
const [zoneHover, setZoneHover] = useState(false)
|
||||
return (
|
||||
<CSVReader
|
||||
onUploadAccepted={(results: any) => {
|
||||
onParsed(results.data)
|
||||
setZoneHover(false)
|
||||
}}
|
||||
onDragOver={(event: DragEvent) => {
|
||||
event.preventDefault()
|
||||
setZoneHover(true)
|
||||
}}
|
||||
onDragLeave={(event: DragEvent) => {
|
||||
event.preventDefault()
|
||||
setZoneHover(false)
|
||||
}}
|
||||
>
|
||||
{({
|
||||
getRootProps,
|
||||
acceptedFile,
|
||||
}: any) => (
|
||||
<>
|
||||
<div
|
||||
{...getRootProps()}
|
||||
className={cn(s.zone, zoneHover && s.zoneHover, acceptedFile ? 'px-6' : 'justify-center border-dashed text-gray-500')}
|
||||
>
|
||||
{
|
||||
acceptedFile
|
||||
? (
|
||||
<div className='w-full flex items-center space-x-2'>
|
||||
<CSVIcon className="shrink-0" />
|
||||
<div className='flex w-0 grow'>
|
||||
<span className='max-w-[calc(100%_-_30px)] text-ellipsis whitespace-nowrap overflow-hidden text-gray-800'>{acceptedFile.name.replace(/.csv$/, '')}</span>
|
||||
<span className='shrink-0 text-gray-500'>.csv</span>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
: (
|
||||
<div className='flex items-center justify-center space-x-2'>
|
||||
<CSVIcon className="shrink-0" />
|
||||
<div className='text-gray-500'>{t('share.generation.csvUploadTitle')}<span className='text-primary-400'>{t('share.generation.browse')}</span></div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</CSVReader>
|
||||
)
|
||||
}
|
||||
|
||||
export default React.memo(CSVReader)
|
||||
@ -0,0 +1,11 @@
|
||||
.zone {
|
||||
@apply flex items-center h-20 rounded-xl bg-gray-50 border border-gray-200 cursor-pointer text-sm font-normal;
|
||||
}
|
||||
|
||||
.zoneHover {
|
||||
@apply border-solid bg-gray-100;
|
||||
}
|
||||
|
||||
.info {
|
||||
@apply text-gray-800 text-sm;
|
||||
}
|
||||
@ -0,0 +1,59 @@
|
||||
'use client'
|
||||
import type { FC } from 'react'
|
||||
import React from 'react'
|
||||
import {
|
||||
PlayIcon,
|
||||
} from '@heroicons/react/24/solid'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import {
|
||||
RiLoader2Line,
|
||||
} from '@remixicon/react'
|
||||
import CSVReader from './csv-reader'
|
||||
import CSVDownload from './csv-download'
|
||||
import cn from '@/utils/classnames'
|
||||
import Button from '@/app/components/base/button'
|
||||
export type IRunBatchProps = {
|
||||
vars: { name: string }[]
|
||||
onSend: (data: string[][]) => void
|
||||
isAllFinished: boolean
|
||||
}
|
||||
|
||||
const RunBatch: FC<IRunBatchProps> = ({
|
||||
vars,
|
||||
onSend,
|
||||
isAllFinished,
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
const [csvData, setCsvData] = React.useState<string[][]>([])
|
||||
const [isParsed, setIsParsed] = React.useState(false)
|
||||
const handleParsed = (data: string[][]) => {
|
||||
setCsvData(data)
|
||||
// console.log(data)
|
||||
setIsParsed(true)
|
||||
}
|
||||
|
||||
const handleSend = () => {
|
||||
onSend(csvData)
|
||||
}
|
||||
const Icon = isAllFinished ? PlayIcon : RiLoader2Line
|
||||
return (
|
||||
<div className='pt-4'>
|
||||
<CSVReader onParsed={handleParsed} />
|
||||
<CSVDownload vars={vars} />
|
||||
<div className='mt-4 h-[1px] bg-gray-100'></div>
|
||||
<div className='flex justify-end'>
|
||||
<Button
|
||||
variant="primary"
|
||||
className='mt-4 pl-3 pr-4'
|
||||
onClick={handleSend}
|
||||
disabled={!isParsed || !isAllFinished}
|
||||
>
|
||||
<Icon className={cn(!isAllFinished && 'animate-spin', 'shrink-0 w-4 h-4 mr-1')} aria-hidden="true" />
|
||||
<span className='uppercase text-[13px]'>{t('share.generation.run')}</span>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
export default React.memo(RunBatch)
|
||||
@ -0,0 +1,41 @@
|
||||
'use client'
|
||||
import type { FC } from 'react'
|
||||
import React from 'react'
|
||||
import {
|
||||
useCSVDownloader,
|
||||
} from 'react-papaparse'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import cn from '@/utils/classnames'
|
||||
import { Download02 as DownloadIcon } from '@/app/components/base/icons/src/vender/solid/general'
|
||||
import Button from '@/app/components/base/button'
|
||||
export type IResDownloadProps = {
|
||||
isMobile: boolean
|
||||
values: Record<string, string>[]
|
||||
}
|
||||
|
||||
const ResDownload: FC<IResDownloadProps> = ({
|
||||
isMobile,
|
||||
values,
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
const { CSVDownloader, Type } = useCSVDownloader()
|
||||
|
||||
return (
|
||||
<CSVDownloader
|
||||
className="block cursor-pointer"
|
||||
type={Type.Link}
|
||||
filename={'result'}
|
||||
bom={true}
|
||||
config={{
|
||||
// delimiter: ';',
|
||||
}}
|
||||
data={values}
|
||||
>
|
||||
<Button className={cn('space-x-2 bg-white', isMobile ? '!p-0 !w-8 justify-center' : '')}>
|
||||
<DownloadIcon className='w-4 h-4 text-[#155EEF]' />
|
||||
{!isMobile && <span className='text-[#155EEF]'>{t('common.operation.download')}</span>}
|
||||
</Button>
|
||||
</CSVDownloader>
|
||||
)
|
||||
}
|
||||
export default React.memo(ResDownload)
|
||||
Loading…
Reference in New Issue