| | |
| | | import { useProviderContext } from '@/context/provider-context' |
| | | import VectorSpaceFull from '@/app/components/billing/vector-space-full' |
| | | import classNames from '@/utils/classnames' |
| | | import { Icon3Dots } from '@/app/components/base/icons/src/vender/line/others' |
| | | import { ENABLE_WEBSITE_FIRECRAWL, ENABLE_WEBSITE_JINAREADER, ENABLE_WEBSITE_WATERCRAWL } from '@/config' |
| | | |
| | | type IStepOneProps = { |
| | | datasetId?: string |
| | | dataSourceType?: DataSourceType |
| | | dataSourceTypeDisable: boolean |
| | | dataSourceTypeDisable: Boolean |
| | | hasConnection: boolean |
| | | onSetting: () => void |
| | | files: FileItem[] |
| | |
| | | const { t } = useTranslation() |
| | | |
| | | return ( |
| | | <div className='flex w-[640px] flex-col items-start rounded-2xl bg-workflow-process-bg p-6'> |
| | | <span className={cn(s.notionIcon, 'mb-2 h-12 w-12 rounded-[10px] border-[0.5px] border-components-card-border p-3 shadow-lg shadow-shadow-shadow-5')} /> |
| | | <div className='mb-1 flex flex-col gap-y-1 pb-3 pt-1'> |
| | | <span className='system-md-semibold text-text-secondary'> |
| | | {t('datasetCreation.stepOne.notionSyncTitle')} |
| | | <Icon3Dots className='relative -left-1.5 -top-2.5 inline h-4 w-4 text-text-secondary' /> |
| | | </span> |
| | | <div className='system-sm-regular text-text-tertiary'>{t('datasetCreation.stepOne.notionSyncTip')}</div> |
| | | </div> |
| | | <div className={s.notionConnectionTip}> |
| | | <span className={s.notionIcon} /> |
| | | <div className={s.title}>{t('datasetCreation.stepOne.notionSyncTitle')}</div> |
| | | <div className={s.tip}>{t('datasetCreation.stepOne.notionSyncTip')}</div> |
| | | <Button className='h-8' variant='primary' onClick={onSetting}>{t('datasetCreation.stepOne.connect')}</Button> |
| | | </div> |
| | | ) |
| | |
| | | return true |
| | | if (files.some(file => !file.file.id)) |
| | | return true |
| | | return isShowVectorSpaceFull |
| | | if (isShowVectorSpaceFull) |
| | | return true |
| | | return false |
| | | }, [files, isShowVectorSpaceFull]) |
| | | |
| | | return ( |
| | | <div className='h-full w-full overflow-x-auto'> |
| | | <div className='flex h-full w-full min-w-[1440px]'> |
| | | <div className='relative h-full w-1/2 overflow-y-auto'> |
| | | <div className='flex justify-end'> |
| | | <div className={classNames(s.form)}> |
| | | { |
| | | shouldShowDataSourceTypeList && ( |
| | | <div className={classNames(s.stepHeader, 'text-text-secondary system-md-semibold')}> |
| | | {t('datasetCreation.steps.one')} |
| | | <div className='flex w-full h-full'> |
| | | <div className='w-1/2 h-full overflow-y-auto relative'> |
| | | <div className='flex justify-end'> |
| | | <div className={classNames(s.form)}> |
| | | { |
| | | shouldShowDataSourceTypeList && ( |
| | | <div className={classNames(s.stepHeader, 'z-10 text-text-secondary bg-components-panel-bg-blur')}>{t('datasetCreation.steps.one')}</div> |
| | | ) |
| | | } |
| | | { |
| | | shouldShowDataSourceTypeList && ( |
| | | <div className='flex items-center mb-8 flex-wrap gap-4'> |
| | | <div |
| | | className={cn( |
| | | s.dataSourceItem, |
| | | dataSourceType === DataSourceType.FILE && s.active, |
| | | dataSourceTypeDisable && dataSourceType !== DataSourceType.FILE && s.disabled, |
| | | )} |
| | | onClick={() => { |
| | | if (dataSourceTypeDisable) |
| | | return |
| | | changeType(DataSourceType.FILE) |
| | | hideFilePreview() |
| | | hideNotionPagePreview() |
| | | }} |
| | | > |
| | | <span className={cn(s.datasetIcon)} /> |
| | | {t('datasetCreation.stepOne.dataSourceType.file')} |
| | | </div> |
| | | ) |
| | | } |
| | | { |
| | | shouldShowDataSourceTypeList && ( |
| | | <div className='mb-8 grid grid-cols-3 gap-4'> |
| | | <div |
| | | className={cn( |
| | | s.dataSourceItem, |
| | | 'system-sm-medium', |
| | | dataSourceType === DataSourceType.FILE && s.active, |
| | | dataSourceTypeDisable && dataSourceType !== DataSourceType.FILE && s.disabled, |
| | | )} |
| | | onClick={() => { |
| | | if (dataSourceTypeDisable) |
| | | return |
| | | changeType(DataSourceType.FILE) |
| | | hideFilePreview() |
| | | hideNotionPagePreview() |
| | | }} |
| | | > |
| | | <span className={cn(s.datasetIcon)} /> |
| | | <span |
| | | title={t('datasetCreation.stepOne.dataSourceType.file')} |
| | | className='truncate' |
| | | > |
| | | {t('datasetCreation.stepOne.dataSourceType.file')} |
| | | </span> |
| | | <div |
| | | className={cn( |
| | | s.dataSourceItem, |
| | | dataSourceType === DataSourceType.NOTION && s.active, |
| | | dataSourceTypeDisable && dataSourceType !== DataSourceType.NOTION && s.disabled, |
| | | )} |
| | | onClick={() => { |
| | | if (dataSourceTypeDisable) |
| | | return |
| | | changeType(DataSourceType.NOTION) |
| | | hideFilePreview() |
| | | hideNotionPagePreview() |
| | | }} |
| | | > |
| | | <span className={cn(s.datasetIcon, s.notion)} /> |
| | | {t('datasetCreation.stepOne.dataSourceType.notion')} |
| | | </div> |
| | | <div |
| | | className={cn( |
| | | s.dataSourceItem, |
| | | dataSourceType === DataSourceType.WEB && s.active, |
| | | dataSourceTypeDisable && dataSourceType !== DataSourceType.WEB && s.disabled, |
| | | )} |
| | | onClick={() => changeType(DataSourceType.WEB)} |
| | | > |
| | | <span className={cn(s.datasetIcon, s.web)} /> |
| | | {t('datasetCreation.stepOne.dataSourceType.web')} |
| | | </div> |
| | | </div> |
| | | ) |
| | | } |
| | | {dataSourceType === DataSourceType.FILE && ( |
| | | <> |
| | | <FileUploader |
| | | fileList={files} |
| | | titleClassName={!shouldShowDataSourceTypeList ? 'mt-[30px] !mb-[44px] !text-lg !font-semibold !text-gray-900' : undefined} |
| | | prepareFileList={updateFileList} |
| | | onFileListUpdate={updateFileList} |
| | | onFileUpdate={updateFile} |
| | | onPreview={updateCurrentFile} |
| | | notSupportBatchUpload={notSupportBatchUpload} |
| | | /> |
| | | {isShowVectorSpaceFull && ( |
| | | <div className='max-w-[640px] mb-4'> |
| | | <VectorSpaceFull /> |
| | | </div> |
| | | )} |
| | | <div className="flex justify-end gap-2 max-w-[640px]"> |
| | | {/* <Button>{t('datasetCreation.stepOne.cancel')}</Button> */} |
| | | <Button disabled={nextDisabled} variant='primary' onClick={onStepChange}> |
| | | <span className="flex gap-0.5 px-[10px]"> |
| | | <span className="px-0.5">{t('datasetCreation.stepOne.button')}</span> |
| | | <RiArrowRightLine className="size-4" /> |
| | | </span> |
| | | </Button> |
| | | </div> |
| | | </> |
| | | )} |
| | | {dataSourceType === DataSourceType.NOTION && ( |
| | | <> |
| | | {!hasConnection && <NotionConnector onSetting={onSetting} />} |
| | | {hasConnection && ( |
| | | <> |
| | | <div className='mb-8 w-[640px]'> |
| | | <NotionPageSelector |
| | | value={notionPages.map(page => page.page_id)} |
| | | onSelect={updateNotionPages} |
| | | onPreview={updateCurrentPage} |
| | | /> |
| | | </div> |
| | | <div |
| | | className={cn( |
| | | s.dataSourceItem, |
| | | 'system-sm-medium', |
| | | dataSourceType === DataSourceType.NOTION && s.active, |
| | | dataSourceTypeDisable && dataSourceType !== DataSourceType.NOTION && s.disabled, |
| | | )} |
| | | onClick={() => { |
| | | if (dataSourceTypeDisable) |
| | | return |
| | | changeType(DataSourceType.NOTION) |
| | | hideFilePreview() |
| | | hideNotionPagePreview() |
| | | }} |
| | | > |
| | | <span className={cn(s.datasetIcon, s.notion)} /> |
| | | <span |
| | | title={t('datasetCreation.stepOne.dataSourceType.notion')} |
| | | className='truncate' |
| | | > |
| | | {t('datasetCreation.stepOne.dataSourceType.notion')} |
| | | </span> |
| | | </div> |
| | | {(ENABLE_WEBSITE_FIRECRAWL || ENABLE_WEBSITE_JINAREADER || ENABLE_WEBSITE_WATERCRAWL) && ( |
| | | <div |
| | | className={cn( |
| | | s.dataSourceItem, |
| | | 'system-sm-medium', |
| | | dataSourceType === DataSourceType.WEB && s.active, |
| | | dataSourceTypeDisable && dataSourceType !== DataSourceType.WEB && s.disabled, |
| | | )} |
| | | onClick={() => changeType(DataSourceType.WEB)} |
| | | > |
| | | <span className={cn(s.datasetIcon, s.web)} /> |
| | | <span |
| | | title={t('datasetCreation.stepOne.dataSourceType.web')} |
| | | className='truncate' |
| | | > |
| | | {t('datasetCreation.stepOne.dataSourceType.web')} |
| | | </span> |
| | | {isShowVectorSpaceFull && ( |
| | | <div className='max-w-[640px] mb-4'> |
| | | <VectorSpaceFull /> |
| | | </div> |
| | | )} |
| | | </div> |
| | | ) |
| | | } |
| | | {dataSourceType === DataSourceType.FILE && ( |
| | | <> |
| | | <FileUploader |
| | | fileList={files} |
| | | titleClassName={!shouldShowDataSourceTypeList ? 'mt-[30px] !mb-[44px] !text-lg' : undefined} |
| | | prepareFileList={updateFileList} |
| | | onFileListUpdate={updateFileList} |
| | | onFileUpdate={updateFile} |
| | | onPreview={updateCurrentFile} |
| | | notSupportBatchUpload={notSupportBatchUpload} |
| | | <div className="flex justify-end gap-2 max-w-[640px]"> |
| | | {/* <Button>{t('datasetCreation.stepOne.cancel')}</Button> */} |
| | | <Button disabled={isShowVectorSpaceFull || !notionPages.length} variant='primary' onClick={onStepChange}> |
| | | <span className="flex gap-0.5 px-[10px]"> |
| | | <span className="px-0.5">{t('datasetCreation.stepOne.button')}</span> |
| | | <RiArrowRightLine className="size-4" /> |
| | | </span> |
| | | </Button> |
| | | </div> |
| | | </> |
| | | )} |
| | | </> |
| | | )} |
| | | {dataSourceType === DataSourceType.WEB && ( |
| | | <> |
| | | <div className={cn('mb-8 w-[640px]', !shouldShowDataSourceTypeList && 'mt-12')}> |
| | | <Website |
| | | onPreview={setCurrentWebsite} |
| | | checkedCrawlResult={websitePages} |
| | | onCheckedCrawlResultChange={updateWebsitePages} |
| | | onCrawlProviderChange={onWebsiteCrawlProviderChange} |
| | | onJobIdChange={onWebsiteCrawlJobIdChange} |
| | | crawlOptions={crawlOptions} |
| | | onCrawlOptionsChange={onCrawlOptionsChange} |
| | | /> |
| | | {isShowVectorSpaceFull && ( |
| | | <div className='mb-4 max-w-[640px]'> |
| | | <VectorSpaceFull /> |
| | | </div> |
| | | )} |
| | | <div className="flex max-w-[640px] justify-end gap-2"> |
| | | {/* <Button>{t('datasetCreation.stepOne.cancel')}</Button> */} |
| | | <Button disabled={nextDisabled} variant='primary' onClick={onStepChange}> |
| | | <span className="flex gap-0.5 px-[10px]"> |
| | | <span className="px-0.5">{t('datasetCreation.stepOne.button')}</span> |
| | | <RiArrowRightLine className="size-4" /> |
| | | </span> |
| | | </Button> |
| | | </div> |
| | | {isShowVectorSpaceFull && ( |
| | | <div className='max-w-[640px] mb-4'> |
| | | <VectorSpaceFull /> |
| | | </div> |
| | | </> |
| | | )} |
| | | {dataSourceType === DataSourceType.NOTION && ( |
| | | <> |
| | | {!hasConnection && <NotionConnector onSetting={onSetting} />} |
| | | {hasConnection && ( |
| | | <> |
| | | <div className='mb-8 w-[640px]'> |
| | | <NotionPageSelector |
| | | value={notionPages.map(page => page.page_id)} |
| | | onSelect={updateNotionPages} |
| | | onPreview={updateCurrentPage} |
| | | /> |
| | | </div> |
| | | {isShowVectorSpaceFull && ( |
| | | <div className='mb-4 max-w-[640px]'> |
| | | <VectorSpaceFull /> |
| | | </div> |
| | | )} |
| | | <div className="flex max-w-[640px] justify-end gap-2"> |
| | | {/* <Button>{t('datasetCreation.stepOne.cancel')}</Button> */} |
| | | <Button disabled={isShowVectorSpaceFull || !notionPages.length} variant='primary' onClick={onStepChange}> |
| | | <span className="flex gap-0.5 px-[10px]"> |
| | | <span className="px-0.5">{t('datasetCreation.stepOne.button')}</span> |
| | | <RiArrowRightLine className="size-4" /> |
| | | </span> |
| | | </Button> |
| | | </div> |
| | | </> |
| | | )} |
| | | </> |
| | | )} |
| | | {dataSourceType === DataSourceType.WEB && ( |
| | | <> |
| | | <div className={cn('mb-8 w-[640px]', !shouldShowDataSourceTypeList && 'mt-12')}> |
| | | <Website |
| | | onPreview={setCurrentWebsite} |
| | | checkedCrawlResult={websitePages} |
| | | onCheckedCrawlResultChange={updateWebsitePages} |
| | | onCrawlProviderChange={onWebsiteCrawlProviderChange} |
| | | onJobIdChange={onWebsiteCrawlJobIdChange} |
| | | crawlOptions={crawlOptions} |
| | | onCrawlOptionsChange={onCrawlOptionsChange} |
| | | /> |
| | | </div> |
| | | {isShowVectorSpaceFull && ( |
| | | <div className='mb-4 max-w-[640px]'> |
| | | <VectorSpaceFull /> |
| | | </div> |
| | | )} |
| | | <div className="flex max-w-[640px] justify-end gap-2"> |
| | | {/* <Button>{t('datasetCreation.stepOne.cancel')}</Button> */} |
| | | <Button disabled={isShowVectorSpaceFull || !websitePages.length} variant='primary' onClick={onStepChange}> |
| | | <span className="flex gap-0.5 px-[10px]"> |
| | | <span className="px-0.5">{t('datasetCreation.stepOne.button')}</span> |
| | | <RiArrowRightLine className="size-4" /> |
| | | </span> |
| | | </Button> |
| | | </div> |
| | | </> |
| | | )} |
| | | {!datasetId && ( |
| | | <> |
| | | <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')} |
| | | </span> |
| | | </> |
| | | )} |
| | | </div> |
| | | <EmptyDatasetCreationModal show={showModal} onHide={modalCloseHandle} /> |
| | | )} |
| | | <div className="flex justify-end gap-2 max-w-[640px]"> |
| | | {/* <Button>{t('datasetCreation.stepOne.cancel')}</Button> */} |
| | | <Button disabled={isShowVectorSpaceFull || !websitePages.length} variant='primary' onClick={onStepChange}> |
| | | <span className="flex gap-0.5 px-[10px]"> |
| | | <span className="px-0.5">{t('datasetCreation.stepOne.button')}</span> |
| | | <RiArrowRightLine className="size-4" /> |
| | | </span> |
| | | </Button> |
| | | </div> |
| | | </> |
| | | )} |
| | | {!datasetId && ( |
| | | <> |
| | | <div className={s.dividerLine} /> |
| | | <span className="inline-flex items-center cursor-pointer text-[13px] leading-4 text-text-accent" onClick={modalShowHandle}> |
| | | <RiFolder6Line className="size-4 mr-1" /> |
| | | {t('datasetCreation.stepOne.emptyDatasetCreation')} |
| | | </span> |
| | | </> |
| | | )} |
| | | </div> |
| | | <EmptyDatasetCreationModal show={showModal} onHide={modalCloseHandle} /> |
| | | </div> |
| | | <div className='h-full w-1/2 overflow-y-auto'> |
| | | {currentFile && <FilePreview file={currentFile} hidePreview={hideFilePreview} />} |
| | | {currentNotionPage && <NotionPagePreview currentPage={currentNotionPage} hidePreview={hideNotionPagePreview} />} |
| | | {currentWebsite && <WebsitePreview payload={currentWebsite} hidePreview={hideWebsitePreview} />} |
| | | </div> |
| | | </div> |
| | | <div className='w-1/2 h-full overflow-y-auto'> |
| | | {currentFile && <FilePreview file={currentFile} hidePreview={hideFilePreview} />} |
| | | {currentNotionPage && <NotionPagePreview currentPage={currentNotionPage} hidePreview={hideNotionPagePreview} />} |
| | | {currentWebsite && <WebsitePreview payload={currentWebsite} hidePreview={hideWebsitePreview} />} |
| | | </div> |
| | | </div> |
| | | ) |