Переглянути джерело

Revert "Feat/parent child retrieval" (#12095)

-LAN- 4 місяців тому
батько
коміт
db2aa83a7c
100 змінених файлів з 1513 додано та 3405 видалено
  1. 1 12
      api/poetry.lock
  2. 95 61
      web/app/(commonLayout)/datasets/(datasetDetailLayout)/[datasetId]/layout.tsx
  3. 3 3
      web/app/(commonLayout)/datasets/(datasetDetailLayout)/[datasetId]/settings/page.tsx
  4. 9 0
      web/app/(commonLayout)/datasets/(datasetDetailLayout)/[datasetId]/style.module.css
  5. 5 12
      web/app/(commonLayout)/datasets/Container.tsx
  6. 5 5
      web/app/(commonLayout)/datasets/DatasetCard.tsx
  7. 0 45
      web/app/components/app-sidebar/dataset-info.tsx
  8. 11 19
      web/app/components/app-sidebar/index.tsx
  9. 6 10
      web/app/components/app/configuration/dataset-config/settings-modal/index.tsx
  10. 0 19
      web/app/components/base/app-icon/style.module.css
  11. 0 2
      web/app/components/base/auto-height-textarea/common.tsx
  12. 2 4
      web/app/components/base/badge.tsx
  13. 0 5
      web/app/components/base/checkbox/assets/mixed.svg
  14. 0 10
      web/app/components/base/checkbox/index.module.css
  15. 1 4
      web/app/components/base/checkbox/index.tsx
  16. 1 1
      web/app/components/base/divider/index.tsx
  17. 0 23
      web/app/components/base/divider/with-label.tsx
  18. 1 3
      web/app/components/base/drawer/index.tsx
  19. 5 2
      web/app/components/base/file-uploader/file-type-icon.tsx
  20. 0 13
      web/app/components/base/icons/assets/public/knowledge/chunk.svg
  21. 0 9
      web/app/components/base/icons/assets/public/knowledge/collapse.svg
  22. 0 5
      web/app/components/base/icons/assets/public/knowledge/general-type.svg
  23. 0 5
      web/app/components/base/icons/assets/public/knowledge/layout-right-2-line-mod.svg
  24. 0 7
      web/app/components/base/icons/assets/public/knowledge/parent-child-type.svg
  25. 0 13
      web/app/components/base/icons/assets/public/knowledge/selection-mod.svg
  26. 0 116
      web/app/components/base/icons/src/public/knowledge/Chunk.json
  27. 0 16
      web/app/components/base/icons/src/public/knowledge/Chunk.tsx
  28. 0 62
      web/app/components/base/icons/src/public/knowledge/Collapse.json
  29. 0 16
      web/app/components/base/icons/src/public/knowledge/Collapse.tsx
  30. 0 38
      web/app/components/base/icons/src/public/knowledge/GeneralType.json
  31. 0 16
      web/app/components/base/icons/src/public/knowledge/GeneralType.tsx
  32. 0 36
      web/app/components/base/icons/src/public/knowledge/LayoutRight2LineMod.json
  33. 0 16
      web/app/components/base/icons/src/public/knowledge/LayoutRight2LineMod.tsx
  34. 0 56
      web/app/components/base/icons/src/public/knowledge/ParentChildType.json
  35. 0 16
      web/app/components/base/icons/src/public/knowledge/ParentChildType.tsx
  36. 0 116
      web/app/components/base/icons/src/public/knowledge/SelectionMod.json
  37. 0 16
      web/app/components/base/icons/src/public/knowledge/SelectionMod.tsx
  38. 0 6
      web/app/components/base/icons/src/public/knowledge/index.ts
  39. 1 1
      web/app/components/base/icons/src/vender/features/index.ts
  40. 0 86
      web/app/components/base/input-number/index.tsx
  41. 0 62
      web/app/components/base/linked-apps-panel/index.tsx
  42. 1 1
      web/app/components/base/pagination/index.tsx
  43. 15 21
      web/app/components/base/param-item/index.tsx
  44. 9 14
      web/app/components/base/radio-card/index.tsx
  45. 85 0
      web/app/components/base/retry-button/index.tsx
  46. 4 0
      web/app/components/base/retry-button/style.module.css
  47. 3 4
      web/app/components/base/simple-pie-chart/index.tsx
  48. 5 8
      web/app/components/base/skeleton/index.tsx
  49. 0 3
      web/app/components/base/switch/index.tsx
  50. 24 27
      web/app/components/base/tag-input/index.tsx
  51. 7 12
      web/app/components/base/toast/index.tsx
  52. 1 3
      web/app/components/base/tooltip/index.tsx
  53. 7 12
      web/app/components/billing/priority-label/index.tsx
  54. 0 54
      web/app/components/datasets/chunk.tsx
  55. 0 29
      web/app/components/datasets/common/chunking-mode-label.tsx
  56. 0 40
      web/app/components/datasets/common/document-file-icon.tsx
  57. 0 42
      web/app/components/datasets/common/document-picker/document-list.tsx
  58. 0 118
      web/app/components/datasets/common/document-picker/index.tsx
  59. 0 82
      web/app/components/datasets/common/document-picker/preview-document-picker.tsx
  60. 0 38
      web/app/components/datasets/common/document-status-with-action/auto-disabled-document.tsx
  61. 0 69
      web/app/components/datasets/common/document-status-with-action/index-failed.tsx
  62. 0 65
      web/app/components/datasets/common/document-status-with-action/status-with-action.tsx
  63. 14 13
      web/app/components/datasets/common/economical-retrieval-method-config/index.tsx
  64. 41 48
      web/app/components/datasets/common/retrieval-method-config/index.tsx
  65. 10 10
      web/app/components/datasets/common/retrieval-method-info/index.tsx
  66. 18 20
      web/app/components/datasets/common/retrieval-param-config/index.tsx
  67. 0 6
      web/app/components/datasets/create/assets/family-mod.svg
  68. 0 5
      web/app/components/datasets/create/assets/file-list-3-fill.svg
  69. 0 4
      web/app/components/datasets/create/assets/gold.svg
  70. 0 5
      web/app/components/datasets/create/assets/note-mod.svg
  71. 0 12
      web/app/components/datasets/create/assets/option-card-effect-blue.svg
  72. 0 12
      web/app/components/datasets/create/assets/option-card-effect-orange.svg
  73. 0 12
      web/app/components/datasets/create/assets/option-card-effect-purple.svg
  74. 0 12
      web/app/components/datasets/create/assets/pattern-recognition-mod.svg
  75. 0 7
      web/app/components/datasets/create/assets/piggy-bank-mod.svg
  76. 0 8
      web/app/components/datasets/create/assets/progress-indicator.svg
  77. 0 13
      web/app/components/datasets/create/assets/rerank.svg
  78. 0 6
      web/app/components/datasets/create/assets/research-mod.svg
  79. 0 12
      web/app/components/datasets/create/assets/selection-mod.svg
  80. 0 4
      web/app/components/datasets/create/assets/setting-gear-mod.svg
  81. 39 13
      web/app/components/datasets/create/embedding-process/index.module.css
  82. 55 137
      web/app/components/datasets/create/embedding-process/index.tsx
  83. 1 2
      web/app/components/datasets/create/file-preview/index.module.css
  84. 2 2
      web/app/components/datasets/create/file-preview/index.tsx
  85. 66 1
      web/app/components/datasets/create/file-uploader/index.module.css
  86. 28 54
      web/app/components/datasets/create/file-uploader/index.tsx
  87. 0 16
      web/app/components/datasets/create/icons.ts
  88. 28 30
      web/app/components/datasets/create/index.tsx
  89. 2 2
      web/app/components/datasets/create/notion-page-preview/index.tsx
  90. 23 15
      web/app/components/datasets/create/step-one/index.module.css
  91. 127 160
      web/app/components/datasets/create/step-one/index.tsx
  92. 21 32
      web/app/components/datasets/create/step-three/index.tsx
  93. 30 8
      web/app/components/datasets/create/step-two/index.module.css
  94. 692 843
      web/app/components/datasets/create/step-two/index.tsx
  95. 0 77
      web/app/components/datasets/create/step-two/inputs.tsx
  96. 9 24
      web/app/components/datasets/create/step-two/language-select/index.tsx
  97. 0 98
      web/app/components/datasets/create/step-two/option-card.tsx
  98. 0 27
      web/app/components/datasets/create/stepper/index.tsx
  99. 0 46
      web/app/components/datasets/create/stepper/step.tsx
  100. 0 0
      web/app/components/datasets/create/top-bar/index.tsx

+ 1 - 12
api/poetry.lock

@@ -1,15 +1,4 @@
-# This file is automatically @generated by Poetry 1.8.5 and should not be changed by hand.
-
-[[package]]
-name = "aiofiles"
-version = "24.1.0"
-description = "File support for asyncio."
-optional = false
-python-versions = ">=3.8"
-files = [
-    {file = "aiofiles-24.1.0-py3-none-any.whl", hash = "sha256:b4ec55f4195e3eb5d7abd1bf7e061763e864dd4954231fb8539a0ef8bb8260e5"},
-    {file = "aiofiles-24.1.0.tar.gz", hash = "sha256:22a075c9e5a3810f0c2e48f3008c94d68c65d763b9b03857924c99e57355166c"},
-]
+# This file is automatically @generated by Poetry 1.8.4 and should not be changed by hand.
 
 [[package]]
 name = "aiofiles"

+ 95 - 61
web/app/(commonLayout)/datasets/(datasetDetailLayout)/[datasetId]/layout.tsx

@@ -7,36 +7,85 @@ import { useTranslation } from 'react-i18next'
 import { useBoolean } from 'ahooks'
 import {
   Cog8ToothIcon,
+  // CommandLineIcon,
+  Squares2X2Icon,
+  // eslint-disable-next-line sort-imports
+  PuzzlePieceIcon,
   DocumentTextIcon,
   PaperClipIcon,
+  QuestionMarkCircleIcon,
 } from '@heroicons/react/24/outline'
 import {
   Cog8ToothIcon as Cog8ToothSolidIcon,
   // CommandLineIcon as CommandLineSolidIcon,
   DocumentTextIcon as DocumentTextSolidIcon,
 } from '@heroicons/react/24/solid'
-import { RiApps2AddLine, RiInformation2Line } from '@remixicon/react'
+import Link from 'next/link'
 import s from './style.module.css'
 import classNames from '@/utils/classnames'
 import { fetchDatasetDetail, fetchDatasetRelatedApps } from '@/service/datasets'
-import type { RelatedAppResponse } from '@/models/datasets'
+import type { RelatedApp, RelatedAppResponse } from '@/models/datasets'
 import AppSideBar from '@/app/components/app-sidebar'
+import Divider from '@/app/components/base/divider'
+import AppIcon from '@/app/components/base/app-icon'
 import Loading from '@/app/components/base/loading'
+import FloatPopoverContainer from '@/app/components/base/float-popover-container'
 import DatasetDetailContext from '@/context/dataset-detail'
 import { DataSourceType } from '@/models/datasets'
 import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
 import { LanguagesSupported } from '@/i18n/language'
 import { useStore } from '@/app/components/app/store'
+import { AiText, ChatBot, CuteRobot } from '@/app/components/base/icons/src/vender/solid/communication'
+import { Route } from '@/app/components/base/icons/src/vender/solid/mapsAndTravel'
 import { getLocaleOnClient } from '@/i18n'
 import { useAppContext } from '@/context/app-context'
-import Tooltip from '@/app/components/base/tooltip'
-import LinkedAppsPanel from '@/app/components/base/linked-apps-panel'
 
 export type IAppDetailLayoutProps = {
   children: React.ReactNode
   params: { datasetId: string }
 }
 
+type ILikedItemProps = {
+  type?: 'plugin' | 'app'
+  appStatus?: boolean
+  detail: RelatedApp
+  isMobile: boolean
+}
+
+const LikedItem = ({
+  type = 'app',
+  detail,
+  isMobile,
+}: ILikedItemProps) => {
+  return (
+    <Link className={classNames(s.itemWrapper, 'px-2', isMobile && 'justify-center')} href={`/app/${detail?.id}/overview`}>
+      <div className={classNames(s.iconWrapper, 'mr-0')}>
+        <AppIcon size='tiny' iconType={detail.icon_type} icon={detail.icon} background={detail.icon_background} imageUrl={detail.icon_url} />
+        {type === 'app' && (
+          <span className='absolute bottom-[-2px] right-[-2px] w-3.5 h-3.5 p-0.5 bg-white rounded border-[0.5px] border-[rgba(0,0,0,0.02)] shadow-sm'>
+            {detail.mode === 'advanced-chat' && (
+              <ChatBot className='w-2.5 h-2.5 text-[#1570EF]' />
+            )}
+            {detail.mode === 'agent-chat' && (
+              <CuteRobot className='w-2.5 h-2.5 text-indigo-600' />
+            )}
+            {detail.mode === 'chat' && (
+              <ChatBot className='w-2.5 h-2.5 text-[#1570EF]' />
+            )}
+            {detail.mode === 'completion' && (
+              <AiText className='w-2.5 h-2.5 text-[#0E9384]' />
+            )}
+            {detail.mode === 'workflow' && (
+              <Route className='w-2.5 h-2.5 text-[#f79009]' />
+            )}
+          </span>
+        )}
+      </div>
+      {!isMobile && <div className={classNames(s.appInfo, 'ml-2')}>{detail?.name || '--'}</div>}
+    </Link>
+  )
+}
+
 const TargetIcon = ({ className }: SVGProps<SVGElement>) => {
   return <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" className={className ?? ''}>
     <g clipPath="url(#clip0_4610_6951)">
@@ -68,80 +117,65 @@ const BookOpenIcon = ({ className }: SVGProps<SVGElement>) => {
 type IExtraInfoProps = {
   isMobile: boolean
   relatedApps?: RelatedAppResponse
-  expand: boolean
 }
 
-const ExtraInfo = ({ isMobile, relatedApps, expand }: IExtraInfoProps) => {
+const ExtraInfo = ({ isMobile, relatedApps }: IExtraInfoProps) => {
   const locale = getLocaleOnClient()
   const [isShowTips, { toggle: toggleTips, set: setShowTips }] = useBoolean(!isMobile)
   const { t } = useTranslation()
 
-  const hasRelatedApps = relatedApps?.data && relatedApps?.data?.length > 0
-  const relatedAppsTotal = relatedApps?.data?.length || 0
-
   useEffect(() => {
     setShowTips(!isMobile)
   }, [isMobile, setShowTips])
 
-  return <div>
-    {hasRelatedApps && (
+  return <div className='w-full flex flex-col items-center'>
+    <Divider className='mt-5' />
+    {(relatedApps?.data && relatedApps?.data?.length > 0) && (
       <>
-        {!isMobile && (
-          <Tooltip
-            position='right'
-            noDecoration
-            needsDelay
-            popupContent={
-              <LinkedAppsPanel
-                relatedApps={relatedApps.data}
-                isMobile={isMobile}
-              />
-            }
-          >
-            <div className='inline-flex items-center system-xs-medium-uppercase text-text-secondary space-x-1 cursor-pointer'>
-              <span>{relatedAppsTotal || '--'} {t('common.datasetMenus.relatedApp')}</span>
-              <RiInformation2Line className='w-4 h-4' />
-            </div>
-          </Tooltip>
-        )}
-
+        {!isMobile && <div className='w-full px-2 pb-1 pt-4 uppercase text-xs text-gray-500 font-medium'>{relatedApps?.total || '--'} {t('common.datasetMenus.relatedApp')}</div>}
         {isMobile && <div className={classNames(s.subTitle, 'flex items-center justify-center !px-0 gap-1')}>
-          {relatedAppsTotal || '--'}
+          {relatedApps?.total || '--'}
           <PaperClipIcon className='h-4 w-4 text-gray-700' />
         </div>}
+        {relatedApps?.data?.map((item, index) => (<LikedItem key={index} isMobile={isMobile} detail={item} />))}
       </>
     )}
-    {!hasRelatedApps && !expand && (
-      <Tooltip
-        position='right'
-        noDecoration
-        needsDelay
-        popupContent={
-          <div className='p-4 w-[240px] bg-components-panel-bg-blur border-[0.5px] border-components-panel-border rounded-xl'>
-            <div className='inline-flex p-2 rounded-lg border-[0.5px] border-components-panel-border-subtle bg-background-default-subtle'>
-              <RiApps2AddLine className='h-4 w-4 text-text-tertiary' />
-            </div>
-            <div className='text-xs text-text-tertiary my-2'>{t('common.datasetMenus.emptyTip')}</div>
-            <a
-              className='inline-flex items-center text-xs text-text-accent mt-2 cursor-pointer'
-              href={
-                locale === LanguagesSupported[1]
-                  ? 'https://docs.dify.ai/v/zh-hans/guides/knowledge-base/integrate-knowledge-within-application'
-                  : 'https://docs.dify.ai/guides/knowledge-base/integrate-knowledge-within-application'
-              }
-              target='_blank' rel='noopener noreferrer'
-            >
-              <BookOpenIcon className='mr-1' />
-              {t('common.datasetMenus.viewDoc')}
-            </a>
+    {!relatedApps?.data?.length && (
+      <FloatPopoverContainer
+        placement='bottom-start'
+        open={isShowTips}
+        toggle={toggleTips}
+        isMobile={isMobile}
+        triggerElement={
+          <div className={classNames('h-7 w-7 inline-flex justify-center items-center rounded-lg bg-transparent', isShowTips && '!bg-gray-50')}>
+            <QuestionMarkCircleIcon className='h-4 w-4 flex-shrink-0 text-gray-500' />
           </div>
         }
       >
-        <div className='inline-flex items-center system-xs-medium-uppercase text-text-secondary space-x-1 cursor-pointer'>
-          <span>{t('common.datasetMenus.noRelatedApp')}</span>
-          <RiInformation2Line className='w-4 h-4' />
+        <div className={classNames('mt-5 p-3', isMobile && 'border-[0.5px] border-gray-200 shadow-lg rounded-lg bg-white w-[160px]')}>
+          <div className='flex items-center justify-start gap-2'>
+            <div className={s.emptyIconDiv}>
+              <Squares2X2Icon className='w-3 h-3 text-gray-500' />
+            </div>
+            <div className={s.emptyIconDiv}>
+              <PuzzlePieceIcon className='w-3 h-3 text-gray-500' />
+            </div>
+          </div>
+          <div className='text-xs text-gray-500 mt-2'>{t('common.datasetMenus.emptyTip')}</div>
+          <a
+            className='inline-flex items-center text-xs text-primary-600 mt-2 cursor-pointer'
+            href={
+              locale === LanguagesSupported[1]
+                ? 'https://docs.dify.ai/v/zh-hans/guides/knowledge-base/integrate-knowledge-within-application'
+                : 'https://docs.dify.ai/guides/knowledge-base/integrate-knowledge-within-application'
+            }
+            target='_blank' rel='noopener noreferrer'
+          >
+            <BookOpenIcon className='mr-1' />
+            {t('common.datasetMenus.viewDoc')}
+          </a>
         </div>
-      </Tooltip>
+      </FloatPopoverContainer>
     )}
   </div>
 }
@@ -201,7 +235,7 @@ const DatasetDetailLayout: FC<IAppDetailLayoutProps> = (props) => {
   }, [isMobile, setAppSiderbarExpand])
 
   if (!datasetRes && !error)
-    return <Loading type='app' />
+    return <Loading />
 
   return (
     <div className='grow flex overflow-hidden'>
@@ -212,7 +246,7 @@ const DatasetDetailLayout: FC<IAppDetailLayoutProps> = (props) => {
         desc={datasetRes?.description || '--'}
         isExternal={datasetRes?.provider === 'external'}
         navigation={navigation}
-        extraInfo={!isCurrentWorkspaceDatasetOperator ? mode => <ExtraInfo isMobile={mode === 'collapse'} relatedApps={relatedApps} expand={mode === 'collapse'} /> : undefined}
+        extraInfo={!isCurrentWorkspaceDatasetOperator ? mode => <ExtraInfo isMobile={mode === 'collapse'} relatedApps={relatedApps} /> : undefined}
         iconType={datasetRes?.data_source_type === DataSourceType.NOTION ? 'notion' : 'dataset'}
       />}
       <DatasetDetailContext.Provider value={{
@@ -220,7 +254,7 @@ const DatasetDetailLayout: FC<IAppDetailLayoutProps> = (props) => {
         dataset: datasetRes,
         mutateDatasetRes: () => mutateDatasetRes(),
       }}>
-        <div className="bg-background-default-subtle grow overflow-hidden">{children}</div>
+        <div className="bg-white grow overflow-hidden">{children}</div>
       </DatasetDetailContext.Provider>
     </div>
   )

+ 3 - 3
web/app/(commonLayout)/datasets/(datasetDetailLayout)/[datasetId]/settings/page.tsx

@@ -7,10 +7,10 @@ const Settings = async () => {
   const { t } = await translate(locale, 'dataset-settings')
 
   return (
-    <div className='h-full overflow-y-auto'>
+    <div className='bg-white h-full overflow-y-auto'>
       <div className='px-6 py-3'>
-        <div className='mb-1 system-xl-semibold text-text-primary'>{t('title')}</div>
-        <div className='system-sm-regular text-text-tertiary'>{t('desc')}</div>
+        <div className='mb-1 text-lg font-semibold text-gray-900'>{t('title')}</div>
+        <div className='text-sm text-gray-500'>{t('desc')}</div>
       </div>
       <Form />
     </div>

+ 9 - 0
web/app/(commonLayout)/datasets/(datasetDetailLayout)/[datasetId]/style.module.css

@@ -1,3 +1,12 @@
+.itemWrapper {
+  @apply flex items-center w-full h-10 rounded-lg hover:bg-gray-50 cursor-pointer;
+}
+.appInfo {
+  @apply truncate text-gray-700 text-sm font-normal;
+}
+.iconWrapper {
+  @apply relative w-6 h-6 rounded-lg;
+}
 .statusPoint {
   @apply flex justify-center items-center absolute -right-0.5 -bottom-0.5 w-2.5 h-2.5 bg-white rounded;
 }

+ 5 - 12
web/app/(commonLayout)/datasets/Container.tsx

@@ -17,6 +17,7 @@ import TagManagementModal from '@/app/components/base/tag-management'
 import TagFilter from '@/app/components/base/tag-management/filter'
 import Button from '@/app/components/base/button'
 import { ApiConnectionMod } from '@/app/components/base/icons/src/vender/solid/development'
+import SearchInput from '@/app/components/base/search-input'
 
 // Services
 import { fetchDatasetApiBaseUrl } from '@/service/datasets'
@@ -28,7 +29,6 @@ import { useAppContext } from '@/context/app-context'
 import { useExternalApiPanel } from '@/context/external-api-panel-context'
 // eslint-disable-next-line import/order
 import { useQuery } from '@tanstack/react-query'
-import Input from '@/app/components/base/input'
 
 const Container = () => {
   const { t } = useTranslation()
@@ -81,24 +81,17 @@ const Container = () => {
   }, [currentWorkspace, router])
 
   return (
-    <div ref={containerRef} className='grow relative flex flex-col bg-background-body overflow-y-auto'>
-      <div className='sticky top-0 flex justify-between pt-4 px-12 pb-2 leading-[56px] bg-background-body z-10 flex-wrap gap-y-2'>
+    <div ref={containerRef} className='grow relative flex flex-col bg-gray-100 overflow-y-auto'>
+      <div className='sticky top-0 flex justify-between pt-4 px-12 pb-2 leading-[56px] bg-gray-100 z-10 flex-wrap gap-y-2'>
         <TabSliderNew
           value={activeTab}
           onChange={newActiveTab => setActiveTab(newActiveTab)}
           options={options}
         />
         {activeTab === 'dataset' && (
-          <div className='flex items-center justify-center gap-2'>
+          <div className='flex items-center gap-2'>
             <TagFilter type='knowledge' value={tagFilterValue} onChange={handleTagsChange} />
-            <Input
-              showLeftIcon
-              showClearIcon
-              wrapperClassName='w-[200px]'
-              value={keywords}
-              onChange={e => handleKeywordsChange(e.target.value)}
-              onClear={() => handleKeywordsChange('')}
-            />
+            <SearchInput className='w-[200px]' value={keywords} onChange={handleKeywordsChange} />
             <div className="w-[1px] h-4 bg-divider-regular" />
             <Button
               className='gap-0.5 shadows-shadow-xs'

+ 5 - 5
web/app/(commonLayout)/datasets/DatasetCard.tsx

@@ -111,7 +111,7 @@ const DatasetCard = ({
   return (
     <>
       <div
-        className='group relative col-span-1 bg-components-card-bg border-[0.5px] border-solid border-components-card-border rounded-xl shadow-sm min-h-[160px] flex flex-col transition-all duration-200 ease-in-out cursor-pointer hover:shadow-lg'
+        className='group relative col-span-1 bg-white border-[0.5px] border-solid border-transparent rounded-xl shadow-sm min-h-[160px] flex flex-col transition-all duration-200 ease-in-out cursor-pointer hover:shadow-lg'
         data-disable-nprogress={true}
         onClick={(e) => {
           e.preventDefault()
@@ -129,8 +129,8 @@ const DatasetCard = ({
             <Folder className='w-5 h-5 text-[#444CE7]' />
           </div>
           <div className='grow w-0 py-[1px]'>
-            <div className='flex items-center text-sm leading-5 font-semibold text-text-secondary'>
-              <div className={cn('truncate', !dataset.embedding_available && 'opacity-50 hover:opacity-100 text-text-tertiary')} title={dataset.name}>{dataset.name}</div>
+            <div className='flex items-center text-sm leading-5 font-semibold text-gray-800'>
+              <div className={cn('truncate', !dataset.embedding_available && 'opacity-50 hover:opacity-100')} title={dataset.name}>{dataset.name}</div>
               {!dataset.embedding_available && (
                 <Tooltip
                   popupContent={t('dataset.unavailableTip')}
@@ -139,7 +139,7 @@ const DatasetCard = ({
                 </Tooltip>
               )}
             </div>
-            <div className='flex items-center mt-[1px] text-xs leading-[18px] text-text-tertiary'>
+            <div className='flex items-center mt-[1px] text-xs leading-[18px] text-gray-500'>
               <div
                 className={cn('truncate', (!dataset.embedding_available || !dataset.document_count) && 'opacity-50')}
                 title={dataset.provider === 'external' ? `${dataset.app_count}${t('dataset.appCount')}` : `${dataset.document_count}${t('dataset.documentCount')} · ${Math.round(dataset.word_count / 1000)}${t('dataset.wordCount')} · ${dataset.app_count}${t('dataset.appCount')}`}
@@ -162,7 +162,7 @@ const DatasetCard = ({
         </div>
         <div
           className={cn(
-            'grow mb-2 px-[14px] max-h-[72px] text-xs leading-normal text-text-tertiary group-hover:line-clamp-2 group-hover:max-h-[36px]',
+            'grow mb-2 px-[14px] max-h-[72px] text-xs leading-normal text-gray-500 group-hover:line-clamp-2 group-hover:max-h-[36px]',
             tags.length ? 'line-clamp-2' : 'line-clamp-4',
             !dataset.embedding_available && 'opacity-50 hover:opacity-100',
           )}

Різницю між файлами не показано, бо вона завелика
+ 0 - 45
web/app/components/app-sidebar/dataset-info.tsx


+ 11 - 19
web/app/components/app-sidebar/index.tsx

@@ -1,15 +1,15 @@
 import React, { useEffect } from 'react'
 import { useShallow } from 'zustand/react/shallow'
-import { RiLayoutRight2Line } from '@remixicon/react'
-import { LayoutRight2LineMod } from '../base/icons/src/public/knowledge'
 import NavLink from './navLink'
 import type { NavIcon } from './navLink'
 import AppBasic from './basic'
 import AppInfo from './app-info'
-import DatasetInfo from './dataset-info'
 import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
+import {
+  AlignLeft01,
+  AlignRight01,
+} from '@/app/components/base/icons/src/vender/line/layout'
 import { useStore as useAppStore } from '@/app/components/app/store'
-import cn from '@/utils/classnames'
 
 export type IAppDetailNavProps = {
   iconType?: 'app' | 'dataset' | 'notion'
@@ -63,16 +63,7 @@ const AppDetailNav = ({ title, desc, isExternal, icon, icon_background, navigati
         {iconType === 'app' && (
           <AppInfo expand={expand} />
         )}
-        {iconType === 'dataset' && (
-          <DatasetInfo
-            name={title}
-            description={desc}
-            isExternal={isExternal}
-            expand={expand}
-            extraInfo={extraInfo && extraInfo(appSidebarExpand)}
-          />
-        )}
-        {!['app', 'dataset'].includes(iconType) && (
+        {iconType !== 'app' && (
           <AppBasic
             mode={appSidebarExpand}
             iconType={iconType}
@@ -84,9 +75,9 @@ const AppDetailNav = ({ title, desc, isExternal, icon, icon_background, navigati
           />
         )}
       </div>
-      <div className='px-4'>
-        <div className={cn('mt-1 mx-auto h-[1px] bg-divider-subtle', !expand && 'w-6')} />
-      </div>
+      {!expand && (
+        <div className='mt-1 mx-auto w-6 h-[1px] bg-divider-subtle' />
+      )}
       <nav
         className={`
           grow space-y-1
@@ -98,6 +89,7 @@ const AppDetailNav = ({ title, desc, isExternal, icon, icon_background, navigati
             <NavLink key={index} mode={appSidebarExpand} iconMap={{ selected: item.selectedIcon, normal: item.icon }} name={item.name} href={item.href} />
           )
         })}
+        {extraInfo && extraInfo(appSidebarExpand)}
       </nav>
       {
         !isMobile && (
@@ -113,8 +105,8 @@ const AppDetailNav = ({ title, desc, isExternal, icon, icon_background, navigati
             >
               {
                 expand
-                  ? <RiLayoutRight2Line className='w-5 h-5 text-components-menu-item-text' />
-                  : <LayoutRight2LineMod className='w-5 h-5 text-components-menu-item-text' />
+                  ? <AlignLeft01 className='w-[14px] h-[14px]' />
+                  : <AlignRight01 className='w-[14px] h-[14px]' />
               }
             </div>
           </div>

+ 6 - 10
web/app/components/app/configuration/dataset-config/settings-modal/index.tsx

@@ -12,7 +12,7 @@ import Divider from '@/app/components/base/divider'
 import Button from '@/app/components/base/button'
 import Input from '@/app/components/base/input'
 import Textarea from '@/app/components/base/textarea'
-import { type DataSet, RerankingModeEnum } from '@/models/datasets'
+import type { DataSet } from '@/models/datasets'
 import { useToastContext } from '@/app/components/base/toast'
 import { updateDatasetSetting } from '@/service/datasets'
 import { useAppContext } from '@/context/app-context'
@@ -111,10 +111,7 @@ const SettingsModal: FC<SettingsModalProps> = ({
     }
     const postRetrievalConfig = ensureRerankModelSelected({
       rerankDefaultModel: rerankDefaultModel!,
-      retrievalConfig: {
-        ...retrievalConfig,
-        reranking_enable: retrievalConfig.reranking_mode === RerankingModeEnum.RerankingModel,
-      },
+      retrievalConfig,
       indexMethod,
     })
     try {
@@ -258,8 +255,7 @@ const SettingsModal: FC<SettingsModalProps> = ({
                 disable={!localeCurrentDataset?.embedding_available}
                 value={indexMethod}
                 onChange={v => setIndexMethod(v!)}
-                docForm={currentDataset.doc_form}
-                currentValue={currentDataset.indexing_technique}
+                itemClassName='sm:!w-[280px]'
               />
             </div>
           </div>
@@ -291,7 +287,7 @@ const SettingsModal: FC<SettingsModalProps> = ({
         {/* Retrieval Method Config */}
         {currentDataset?.provider === 'external'
           ? <>
-            <div className={rowClass}><Divider /></div>
+            <div className={rowClass}><Divider/></div>
             <div className={rowClass}>
               <div className={labelClass}>
                 <div className='text-text-secondary system-sm-semibold'>{t('datasetSettings.form.retrievalSetting.title')}</div>
@@ -304,7 +300,7 @@ const SettingsModal: FC<SettingsModalProps> = ({
                 isInRetrievalSetting={true}
               />
             </div>
-            <div className={rowClass}><Divider /></div>
+            <div className={rowClass}><Divider/></div>
             <div className={rowClass}>
               <div className={labelClass}>
                 <div className='text-text-secondary system-sm-semibold'>{t('datasetSettings.form.externalKnowledgeAPI')}</div>
@@ -330,7 +326,7 @@ const SettingsModal: FC<SettingsModalProps> = ({
                 </div>
               </div>
             </div>
-            <div className={rowClass}><Divider /></div>
+            <div className={rowClass}><Divider/></div>
           </>
           : <div className={rowClass}>
             <div className={cn(labelClass, 'w-auto min-w-[168px]')}>

+ 0 - 19
web/app/components/base/app-icon/style.module.css

@@ -1,19 +0,0 @@
-.appIcon.large {
-  @apply w-10 h-10;
-}
-
-.appIcon.small {
-  @apply w-8 h-8;
-}
-
-.appIcon.tiny {
-  @apply w-6 h-6 text-base;
-}
-
-.appIcon.xs {
-  @apply w-3 h-3 text-base;
-}
-
-.appIcon.rounded {
-  @apply rounded-full;
-}

+ 0 - 2
web/app/components/base/auto-height-textarea/common.tsx

@@ -49,6 +49,4 @@ const AutoHeightTextarea = forwardRef<HTMLTextAreaElement, AutoHeightTextareaPro
   },
 )
 
-AutoHeightTextarea.displayName = 'AutoHeightTextarea'
-
 export default AutoHeightTextarea

+ 2 - 4
web/app/components/base/badge.tsx

@@ -3,15 +3,13 @@ import cn from '@/utils/classnames'
 
 type BadgeProps = {
   className?: string
-  text?: string
-  children?: React.ReactNode
+  text: string
   uppercase?: boolean
 }
 
 const Badge = ({
   className,
   text,
-  children,
   uppercase = true,
 }: BadgeProps) => {
   return (
@@ -22,7 +20,7 @@ const Badge = ({
         className,
       )}
     >
-      {children || text}
+      {text}
     </div>
   )
 }

+ 0 - 5
web/app/components/base/checkbox/assets/mixed.svg

@@ -1,5 +0,0 @@
-<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
-<g id="check">
-<path id="Vector 1" d="M2.5 6H9.5" stroke="white" stroke-width="1.5" stroke-linecap="round"/>
-</g>
-</svg>

+ 0 - 10
web/app/components/base/checkbox/index.module.css

@@ -1,10 +0,0 @@
-.mixed {
-  background: var(--color-components-checkbox-bg) url(./assets/mixed.svg) center center no-repeat;
-  background-size: 12px 12px;
-  border: none;
-}
-
-.checked.disabled {
-  background-color: #d0d5dd;
-  border-color: #d0d5dd;
-}

+ 1 - 4
web/app/components/base/checkbox/index.tsx

@@ -1,5 +1,4 @@
 import { RiCheckLine } from '@remixicon/react'
-import s from './index.module.css'
 import cn from '@/utils/classnames'
 
 type CheckboxProps = {
@@ -7,17 +6,15 @@ type CheckboxProps = {
   onCheck?: () => void
   className?: string
   disabled?: boolean
-  mixed?: boolean
 }
 
-const Checkbox = ({ checked, onCheck, className, disabled, mixed }: CheckboxProps) => {
+const Checkbox = ({ checked, onCheck, className, disabled }: CheckboxProps) => {
   if (!checked) {
     return (
       <div
         className={cn(
           'w-4 h-4 rounded-[4px] bg-components-checkbox-bg-unchecked border border-components-checkbox-border hover:bg-components-checkbox-bg-unchecked-hover hover:border-components-checkbox-border-hover shadow-xs cursor-pointer',
           disabled && 'border-components-checkbox-border-disabled bg-components-checkbox-bg-disabled hover:border-components-checkbox-border-disabled hover:bg-components-checkbox-bg-disabled cursor-not-allowed',
-          mixed && s.mixed,
           className,
         )}
         onClick={() => {

+ 1 - 1
web/app/components/base/divider/index.tsx

@@ -22,7 +22,7 @@ const dividerVariants = cva('',
   },
 )
 
-export type DividerProps = {
+type DividerProps = {
   className?: string
   style?: CSSProperties
 } & VariantProps<typeof dividerVariants>

+ 0 - 23
web/app/components/base/divider/with-label.tsx

@@ -1,23 +0,0 @@
-import type { FC } from 'react'
-import type { DividerProps } from '.'
-import Divider from '.'
-import classNames from '@/utils/classnames'
-
-export type DividerWithLabelProps = DividerProps & {
-  label: string
-}
-
-export const DividerWithLabel: FC<DividerWithLabelProps> = (props) => {
-  const { label, className, ...rest } = props
-  return <div
-    className="flex items-center gap-2 my-2"
-  >
-    <Divider {...rest} className={classNames('flex-1', className)} />
-    <span className="text-text-tertiary text-xs">
-      {label}
-    </span>
-    <Divider {...rest} className={classNames('flex-1', className)} />
-  </div>
-}
-
-export default DividerWithLabel

+ 1 - 3
web/app/components/base/drawer/index.tsx

@@ -19,7 +19,6 @@ export type IDrawerProps = {
   onClose: () => void
   onCancel?: () => void
   onOk?: () => void
-  unmount?: boolean
 }
 
 export default function Drawer({
@@ -36,12 +35,11 @@ export default function Drawer({
   onClose,
   onCancel,
   onOk,
-  unmount = false,
 }: IDrawerProps) {
   const { t } = useTranslation()
   return (
     <Dialog
-      unmount={unmount}
+      unmount={false}
       open={isOpen}
       onClose={() => !clickOutsideNotOpen && onClose()}
       className="fixed z-30 inset-0 overflow-y-auto"

+ 5 - 2
web/app/components/base/file-uploader/file-type-icon.tsx

@@ -82,8 +82,11 @@ const FileTypeIcon = ({
   size = 'sm',
   className,
 }: FileTypeIconProps) => {
-  const Icon = FILE_TYPE_ICON_MAP[type]?.component || FILE_TYPE_ICON_MAP[FileAppearanceTypeEnum.document].component
-  const color = FILE_TYPE_ICON_MAP[type]?.color || FILE_TYPE_ICON_MAP[FileAppearanceTypeEnum.document].color
+  const Icon = FILE_TYPE_ICON_MAP[type].component
+  const color = FILE_TYPE_ICON_MAP[type].color
+
+  if (!Icon)
+    return null
 
   return <Icon className={cn('shrink-0', SizeMap[size], color, className)} />
 }

+ 0 - 13
web/app/components/base/icons/assets/public/knowledge/chunk.svg

@@ -1,13 +0,0 @@
-<svg width="10" height="10" viewBox="0 0 10 10" fill="none" xmlns="http://www.w3.org/2000/svg">
-<g id="Group">
-<path id="Vector" d="M2.5 10H0V7.5H2.5V10Z" fill="#676F83"/>
-<path id="Vector_2" d="M6.25 6.25H3.75V3.75H6.25V6.25Z" fill="#676F83"/>
-<path id="Vector_3" d="M2.5 6.25H0V3.75H2.5V6.25Z" fill="#676F83"/>
-<path id="Vector_4" d="M6.25 2.5H3.75V0H6.25V2.5Z" fill="#676F83"/>
-<path id="Vector_5" d="M2.5 2.5H0V0H2.5V2.5Z" fill="#676F83"/>
-<path id="Vector_6" d="M10 2.5H7.5V0H10V2.5Z" fill="#676F83"/>
-<path id="Vector_7" d="M9.58342 7.91663H7.91675V9.58329H9.58342V7.91663Z" fill="#676F83"/>
-<path id="Vector_8" d="M9.58342 4.16663H7.91675V5.83329H9.58342V4.16663Z" fill="#676F83"/>
-<path id="Vector_9" d="M5.83341 7.91663H4.16675V9.58329H5.83341V7.91663Z" fill="#676F83"/>
-</g>
-</svg>

+ 0 - 9
web/app/components/base/icons/assets/public/knowledge/collapse.svg

@@ -1,9 +0,0 @@
-<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
-<g id="Icon L">
-<g id="Vector">
-<path d="M2.66602 11.3333H0.666016L3.33268 8.66667L5.99935 11.3333H3.99935L3.99935 14H2.66602L2.66602 11.3333Z" fill="#354052"/>
-<path d="M2.66602 4.66667L2.66602 2L3.99935 2L3.99935 4.66667L5.99935 4.66667L3.33268 7.33333L0.666016 4.66667L2.66602 4.66667Z" fill="#354052"/>
-<path d="M7.33268 2.66667H13.9993V4H7.33268V2.66667ZM7.33268 12H13.9993V13.3333H7.33268V12ZM5.99935 7.33333H13.9993V8.66667H5.99935V7.33333Z" fill="#354052"/>
-</g>
-</g>
-</svg>

Різницю між файлами не показано, бо вона завелика
+ 0 - 5
web/app/components/base/icons/assets/public/knowledge/general-type.svg


+ 0 - 5
web/app/components/base/icons/assets/public/knowledge/layout-right-2-line-mod.svg

@@ -1,5 +0,0 @@
-<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
-<g id="Icon L">
-<path id="Vector" d="M14.0002 2C14.3684 2 14.6668 2.29848 14.6668 2.66667V13.3333C14.6668 13.7015 14.3684 14 14.0002 14H2.00016C1.63198 14 1.3335 13.7015 1.3335 13.3333V2.66667C1.3335 2.29848 1.63198 2 2.00016 2H14.0002ZM13.3335 3.33333H2.66683V12.6667H13.3335V3.33333ZM14.0002 2.66667V13.3333H10.0002V2.66667H14.0002Z" fill="#354052"/>
-</g>
-</svg>

Різницю між файлами не показано, бо вона завелика
+ 0 - 7
web/app/components/base/icons/assets/public/knowledge/parent-child-type.svg


+ 0 - 13
web/app/components/base/icons/assets/public/knowledge/selection-mod.svg

@@ -1,13 +0,0 @@
-<svg width="10" height="10" viewBox="0 0 10 10" fill="none" xmlns="http://www.w3.org/2000/svg">
-<g id="Group">
-<path id="Vector" d="M2.5 10H0V7.5H2.5V10Z" fill="#676F83"/>
-<path id="Vector_2" d="M6.25 6.25H3.75V3.75H6.25V6.25Z" fill="#676F83"/>
-<path id="Vector_3" d="M2.5 6.25H0V3.75H2.5V6.25Z" fill="#676F83"/>
-<path id="Vector_4" d="M6.25 2.5H3.75V0H6.25V2.5Z" fill="#676F83"/>
-<path id="Vector_5" d="M2.5 2.5H0V0H2.5V2.5Z" fill="#676F83"/>
-<path id="Vector_6" d="M10 2.5H7.5V0H10V2.5Z" fill="#676F83"/>
-<path id="Vector_7" d="M9.58332 7.91663H7.91666V9.58329H9.58332V7.91663Z" fill="#676F83"/>
-<path id="Vector_8" d="M9.58332 4.16663H7.91666V5.83329H9.58332V4.16663Z" fill="#676F83"/>
-<path id="Vector_9" d="M5.83332 7.91663H4.16666V9.58329H5.83332V7.91663Z" fill="#676F83"/>
-</g>
-</svg>

+ 0 - 116
web/app/components/base/icons/src/public/knowledge/Chunk.json

@@ -1,116 +0,0 @@
-{
-	"icon": {
-		"type": "element",
-		"isRootNode": true,
-		"name": "svg",
-		"attributes": {
-			"width": "10",
-			"height": "10",
-			"viewBox": "0 0 10 10",
-			"fill": "none",
-			"xmlns": "http://www.w3.org/2000/svg"
-		},
-		"children": [
-			{
-				"type": "element",
-				"name": "g",
-				"attributes": {
-					"id": "Group"
-				},
-				"children": [
-					{
-						"type": "element",
-						"name": "path",
-						"attributes": {
-							"id": "Vector",
-							"d": "M2.5 10H0V7.5H2.5V10Z",
-							"fill": "currentColor"
-						},
-						"children": []
-					},
-					{
-						"type": "element",
-						"name": "path",
-						"attributes": {
-							"id": "Vector_2",
-							"d": "M6.25 6.25H3.75V3.75H6.25V6.25Z",
-							"fill": "currentColor"
-						},
-						"children": []
-					},
-					{
-						"type": "element",
-						"name": "path",
-						"attributes": {
-							"id": "Vector_3",
-							"d": "M2.5 6.25H0V3.75H2.5V6.25Z",
-							"fill": "currentColor"
-						},
-						"children": []
-					},
-					{
-						"type": "element",
-						"name": "path",
-						"attributes": {
-							"id": "Vector_4",
-							"d": "M6.25 2.5H3.75V0H6.25V2.5Z",
-							"fill": "currentColor"
-						},
-						"children": []
-					},
-					{
-						"type": "element",
-						"name": "path",
-						"attributes": {
-							"id": "Vector_5",
-							"d": "M2.5 2.5H0V0H2.5V2.5Z",
-							"fill": "currentColor"
-						},
-						"children": []
-					},
-					{
-						"type": "element",
-						"name": "path",
-						"attributes": {
-							"id": "Vector_6",
-							"d": "M10 2.5H7.5V0H10V2.5Z",
-							"fill": "currentColor"
-						},
-						"children": []
-					},
-					{
-						"type": "element",
-						"name": "path",
-						"attributes": {
-							"id": "Vector_7",
-							"d": "M9.58342 7.91663H7.91675V9.58329H9.58342V7.91663Z",
-							"fill": "currentColor"
-						},
-						"children": []
-					},
-					{
-						"type": "element",
-						"name": "path",
-						"attributes": {
-							"id": "Vector_8",
-							"d": "M9.58342 4.16663H7.91675V5.83329H9.58342V4.16663Z",
-							"fill": "currentColor"
-						},
-						"children": []
-					},
-					{
-						"type": "element",
-						"name": "path",
-						"attributes": {
-							"id": "Vector_9",
-							"d": "M5.83341 7.91663H4.16675V9.58329H5.83341V7.91663Z",
-							"fill": "currentColor"
-						},
-						"children": []
-					}
-				]
-			}
-		]
-	},
-	"name": "Chunk"
-}

+ 0 - 16
web/app/components/base/icons/src/public/knowledge/Chunk.tsx

@@ -1,16 +0,0 @@
-// GENERATE BY script
-// DON NOT EDIT IT MANUALLY
-
-import * as React from 'react'
-import data from './Chunk.json'
-import IconBase from '@/app/components/base/icons/IconBase'
-import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase'
-
-const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>((
-  props,
-  ref,
-) => <IconBase {...props} ref={ref} data={data as IconData} />)
-
-Icon.displayName = 'Chunk'
-
-export default Icon

+ 0 - 62
web/app/components/base/icons/src/public/knowledge/Collapse.json

@@ -1,62 +0,0 @@
-{
-	"icon": {
-		"type": "element",
-		"isRootNode": true,
-		"name": "svg",
-		"attributes": {
-			"width": "16",
-			"height": "16",
-			"viewBox": "0 0 16 16",
-			"fill": "none",
-			"xmlns": "http://www.w3.org/2000/svg"
-		},
-		"children": [
-			{
-				"type": "element",
-				"name": "g",
-				"attributes": {
-					"id": "Icon L"
-				},
-				"children": [
-					{
-						"type": "element",
-						"name": "g",
-						"attributes": {
-							"id": "Vector"
-						},
-						"children": [
-							{
-								"type": "element",
-								"name": "path",
-								"attributes": {
-									"d": "M2.66602 11.3333H0.666016L3.33268 8.66667L5.99935 11.3333H3.99935L3.99935 14H2.66602L2.66602 11.3333Z",
-									"fill": "currentColor"
-								},
-								"children": []
-							},
-							{
-								"type": "element",
-								"name": "path",
-								"attributes": {
-									"d": "M2.66602 4.66667L2.66602 2L3.99935 2L3.99935 4.66667L5.99935 4.66667L3.33268 7.33333L0.666016 4.66667L2.66602 4.66667Z",
-									"fill": "currentColor"
-								},
-								"children": []
-							},
-							{
-								"type": "element",
-								"name": "path",
-								"attributes": {
-									"d": "M7.33268 2.66667H13.9993V4H7.33268V2.66667ZM7.33268 12H13.9993V13.3333H7.33268V12ZM5.99935 7.33333H13.9993V8.66667H5.99935V7.33333Z",
-									"fill": "currentColor"
-								},
-								"children": []
-							}
-						]
-					}
-				]
-			}
-		]
-	},
-	"name": "Collapse"
-}

+ 0 - 16
web/app/components/base/icons/src/public/knowledge/Collapse.tsx

@@ -1,16 +0,0 @@
-// GENERATE BY script
-// DON NOT EDIT IT MANUALLY
-
-import * as React from 'react'
-import data from './Collapse.json'
-import IconBase from '@/app/components/base/icons/IconBase'
-import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase'
-
-const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>((
-  props,
-  ref,
-) => <IconBase {...props} ref={ref} data={data as IconData} />)
-
-Icon.displayName = 'Collapse'
-
-export default Icon

Різницю між файлами не показано, бо вона завелика
+ 0 - 38
web/app/components/base/icons/src/public/knowledge/GeneralType.json


+ 0 - 16
web/app/components/base/icons/src/public/knowledge/GeneralType.tsx

@@ -1,16 +0,0 @@
-// GENERATE BY script
-// DON NOT EDIT IT MANUALLY
-
-import * as React from 'react'
-import data from './GeneralType.json'
-import IconBase from '@/app/components/base/icons/IconBase'
-import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase'
-
-const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>((
-  props,
-  ref,
-) => <IconBase {...props} ref={ref} data={data as IconData} />)
-
-Icon.displayName = 'GeneralType'
-
-export default Icon

+ 0 - 36
web/app/components/base/icons/src/public/knowledge/LayoutRight2LineMod.json

@@ -1,36 +0,0 @@
-{
-	"icon": {
-		"type": "element",
-		"isRootNode": true,
-		"name": "svg",
-		"attributes": {
-			"width": "16",
-			"height": "16",
-			"viewBox": "0 0 16 16",
-			"fill": "none",
-			"xmlns": "http://www.w3.org/2000/svg"
-		},
-		"children": [
-			{
-				"type": "element",
-				"name": "g",
-				"attributes": {
-					"id": "Icon L"
-				},
-				"children": [
-					{
-						"type": "element",
-						"name": "path",
-						"attributes": {
-							"id": "Vector",
-							"d": "M14.0002 2C14.3684 2 14.6668 2.29848 14.6668 2.66667V13.3333C14.6668 13.7015 14.3684 14 14.0002 14H2.00016C1.63198 14 1.3335 13.7015 1.3335 13.3333V2.66667C1.3335 2.29848 1.63198 2 2.00016 2H14.0002ZM13.3335 3.33333H2.66683V12.6667H13.3335V3.33333ZM14.0002 2.66667V13.3333H10.0002V2.66667H14.0002Z",
-							"fill": "currentColor"
-						},
-						"children": []
-					}
-				]
-			}
-		]
-	},
-	"name": "LayoutRight2LineMod"
-}

+ 0 - 16
web/app/components/base/icons/src/public/knowledge/LayoutRight2LineMod.tsx

@@ -1,16 +0,0 @@
-// GENERATE BY script
-// DON NOT EDIT IT MANUALLY
-
-import * as React from 'react'
-import data from './LayoutRight2LineMod.json'
-import IconBase from '@/app/components/base/icons/IconBase'
-import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase'
-
-const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>((
-  props,
-  ref,
-) => <IconBase {...props} ref={ref} data={data as IconData} />)
-
-Icon.displayName = 'LayoutRight2LineMod'
-
-export default Icon

Різницю між файлами не показано, бо вона завелика
+ 0 - 56
web/app/components/base/icons/src/public/knowledge/ParentChildType.json


+ 0 - 16
web/app/components/base/icons/src/public/knowledge/ParentChildType.tsx

@@ -1,16 +0,0 @@
-// GENERATE BY script
-// DON NOT EDIT IT MANUALLY
-
-import * as React from 'react'
-import data from './ParentChildType.json'
-import IconBase from '@/app/components/base/icons/IconBase'
-import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase'
-
-const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>((
-  props,
-  ref,
-) => <IconBase {...props} ref={ref} data={data as IconData} />)
-
-Icon.displayName = 'ParentChildType'
-
-export default Icon

+ 0 - 116
web/app/components/base/icons/src/public/knowledge/SelectionMod.json

@@ -1,116 +0,0 @@
-{
-	"icon": {
-		"type": "element",
-		"isRootNode": true,
-		"name": "svg",
-		"attributes": {
-			"width": "10",
-			"height": "10",
-			"viewBox": "0 0 10 10",
-			"fill": "none",
-			"xmlns": "http://www.w3.org/2000/svg"
-		},
-		"children": [
-			{
-				"type": "element",
-				"name": "g",
-				"attributes": {
-					"id": "Group"
-				},
-				"children": [
-					{
-						"type": "element",
-						"name": "path",
-						"attributes": {
-							"id": "Vector",
-							"d": "M2.5 10H0V7.5H2.5V10Z",
-							"fill": "#676F83"
-						},
-						"children": []
-					},
-					{
-						"type": "element",
-						"name": "path",
-						"attributes": {
-							"id": "Vector_2",
-							"d": "M6.25 6.25H3.75V3.75H6.25V6.25Z",
-							"fill": "#676F83"
-						},
-						"children": []
-					},
-					{
-						"type": "element",
-						"name": "path",
-						"attributes": {
-							"id": "Vector_3",
-							"d": "M2.5 6.25H0V3.75H2.5V6.25Z",
-							"fill": "#676F83"
-						},
-						"children": []
-					},
-					{
-						"type": "element",
-						"name": "path",
-						"attributes": {
-							"id": "Vector_4",
-							"d": "M6.25 2.5H3.75V0H6.25V2.5Z",
-							"fill": "#676F83"
-						},
-						"children": []
-					},
-					{
-						"type": "element",
-						"name": "path",
-						"attributes": {
-							"id": "Vector_5",
-							"d": "M2.5 2.5H0V0H2.5V2.5Z",
-							"fill": "#676F83"
-						},
-						"children": []
-					},
-					{
-						"type": "element",
-						"name": "path",
-						"attributes": {
-							"id": "Vector_6",
-							"d": "M10 2.5H7.5V0H10V2.5Z",
-							"fill": "#676F83"
-						},
-						"children": []
-					},
-					{
-						"type": "element",
-						"name": "path",
-						"attributes": {
-							"id": "Vector_7",
-							"d": "M9.58332 7.91663H7.91666V9.58329H9.58332V7.91663Z",
-							"fill": "#676F83"
-						},
-						"children": []
-					},
-					{
-						"type": "element",
-						"name": "path",
-						"attributes": {
-							"id": "Vector_8",
-							"d": "M9.58332 4.16663H7.91666V5.83329H9.58332V4.16663Z",
-							"fill": "#676F83"
-						},
-						"children": []
-					},
-					{
-						"type": "element",
-						"name": "path",
-						"attributes": {
-							"id": "Vector_9",
-							"d": "M5.83332 7.91663H4.16666V9.58329H5.83332V7.91663Z",
-							"fill": "#676F83"
-						},
-						"children": []
-					}
-				]
-			}
-		]
-	},
-	"name": "SelectionMod"
-}

+ 0 - 16
web/app/components/base/icons/src/public/knowledge/SelectionMod.tsx

@@ -1,16 +0,0 @@
-// GENERATE BY script
-// DON NOT EDIT IT MANUALLY
-
-import * as React from 'react'
-import data from './SelectionMod.json'
-import IconBase from '@/app/components/base/icons/IconBase'
-import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase'
-
-const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>((
-  props,
-  ref,
-) => <IconBase {...props} ref={ref} data={data as IconData} />)
-
-Icon.displayName = 'SelectionMod'
-
-export default Icon

+ 0 - 6
web/app/components/base/icons/src/public/knowledge/index.ts

@@ -1,6 +0,0 @@
-export { default as Chunk } from './Chunk'
-export { default as Collapse } from './Collapse'
-export { default as GeneralType } from './GeneralType'
-export { default as LayoutRight2LineMod } from './LayoutRight2LineMod'
-export { default as ParentChildType } from './ParentChildType'
-export { default as SelectionMod } from './SelectionMod'

+ 1 - 1
web/app/components/base/icons/src/vender/features/index.ts

@@ -1,6 +1,5 @@
 export { default as Citations } from './Citations'
 export { default as ContentModeration } from './ContentModeration'
-export { default as Document } from './Document'
 export { default as FolderUpload } from './FolderUpload'
 export { default as LoveMessage } from './LoveMessage'
 export { default as MessageFast } from './MessageFast'
@@ -8,3 +7,4 @@ export { default as Microphone01 } from './Microphone01'
 export { default as TextToAudio } from './TextToAudio'
 export { default as VirtualAssistant } from './VirtualAssistant'
 export { default as Vision } from './Vision'
+export { default as Document } from './Document'

+ 0 - 86
web/app/components/base/input-number/index.tsx

@@ -1,86 +0,0 @@
-import type { FC } from 'react'
-import { RiArrowDownSLine, RiArrowUpSLine } from '@remixicon/react'
-import Input, { type InputProps } from '../input'
-import classNames from '@/utils/classnames'
-
-export type InputNumberProps = {
-  unit?: string
-  value?: number
-  onChange: (value?: number) => void
-  amount?: number
-  size?: 'sm' | 'md'
-  max?: number
-  min?: number
-  defaultValue?: number
-} & Omit<InputProps, 'value' | 'onChange' | 'size' | 'min' | 'max' | 'defaultValue'>
-
-export const InputNumber: FC<InputNumberProps> = (props) => {
-  const { unit, className, onChange, amount = 1, value, size = 'md', max, min, defaultValue, ...rest } = props
-
-  const isValidValue = (v: number) => {
-    if (max && v > max)
-      return false
-    if (min && v < min)
-      return false
-    return true
-  }
-
-  const inc = () => {
-    if (value === undefined) {
-      onChange(defaultValue)
-      return
-    }
-    const newValue = value + amount
-    if (!isValidValue(newValue))
-      return
-    onChange(newValue)
-  }
-  const dec = () => {
-    if (value === undefined) {
-      onChange(defaultValue)
-      return
-    }
-    const newValue = value - amount
-    if (!isValidValue(newValue))
-      return
-    onChange(newValue)
-  }
-
-  return <div className='flex'>
-    <Input {...rest}
-      // disable default controller
-      type='text'
-      className={classNames('rounded-r-none', className)}
-      value={value}
-      max={max}
-      min={min}
-      onChange={(e) => {
-        if (e.target.value === '')
-          onChange(undefined)
-
-        const parsed = Number(e.target.value)
-        if (Number.isNaN(parsed))
-          return
-
-        if (!isValidValue(parsed))
-          return
-        onChange(parsed)
-      }}
-      unit={unit}
-    />
-    <div className='flex flex-col bg-components-input-bg-normal rounded-r-md border-l border-divider-subtle text-text-tertiary focus:shadow-xs'>
-      <button onClick={inc} className={classNames(
-        size === 'sm' ? 'pt-1' : 'pt-1.5',
-        'px-1.5 hover:bg-components-input-bg-hover',
-      )}>
-        <RiArrowUpSLine className='size-3' />
-      </button>
-      <button onClick={dec} className={classNames(
-        size === 'sm' ? 'pb-1' : 'pb-1.5',
-        'px-1.5 hover:bg-components-input-bg-hover',
-      )}>
-        <RiArrowDownSLine className='size-3' />
-      </button>
-    </div>
-  </div>
-}

+ 0 - 62
web/app/components/base/linked-apps-panel/index.tsx

@@ -1,62 +0,0 @@
-'use client'
-import type { FC } from 'react'
-import React from 'react'
-import Link from 'next/link'
-import { useTranslation } from 'react-i18next'
-import { RiArrowRightUpLine } from '@remixicon/react'
-import cn from '@/utils/classnames'
-import AppIcon from '@/app/components/base/app-icon'
-import type { RelatedApp } from '@/models/datasets'
-
-type ILikedItemProps = {
-  appStatus?: boolean
-  detail: RelatedApp
-  isMobile: boolean
-}
-
-const appTypeMap = {
-  'chat': 'Chatbot',
-  'completion': 'Completion',
-  'agent-chat': 'Agent',
-  'advanced-chat': 'Chatflow',
-  'workflow': 'Workflow',
-}
-
-const LikedItem = ({
-  detail,
-  isMobile,
-}: ILikedItemProps) => {
-  return (
-    <Link className={cn('group/link-item flex items-center justify-between w-full h-8 rounded-lg hover:bg-state-base-hover cursor-pointer px-2', isMobile && 'justify-center')} href={`/app/${detail?.id}/overview`}>
-      <div className='flex items-center'>
-        <div className={cn('relative w-6 h-6 rounded-md')}>
-          <AppIcon size='tiny' iconType={detail.icon_type} icon={detail.icon} background={detail.icon_background} imageUrl={detail.icon_url} />
-        </div>
-        {!isMobile && <div className={cn(' ml-2 truncate system-sm-medium text-text-primary')}>{detail?.name || '--'}</div>}
-      </div>
-      <div className='group-hover/link-item:hidden shrink-0 system-2xs-medium-uppercase text-text-tertiary'>{appTypeMap[detail.mode]}</div>
-      <RiArrowRightUpLine className='hidden group-hover/link-item:block w-4 h-4 text-text-tertiary' />
-    </Link>
-  )
-}
-
-type Props = {
-  relatedApps: RelatedApp[]
-  isMobile: boolean
-}
-
-const LinkedAppsPanel: FC<Props> = ({
-  relatedApps,
-  isMobile,
-}) => {
-  const { t } = useTranslation()
-  return (
-    <div className='p-1 w-[320px] bg-components-panel-bg-blur border-[0.5px] border-components-panel-border shadow-lg rounded-xl  backdrop-blur-[5px]'>
-      <div className='mt-1 mb-0.5 pl-2 system-xs-medium-uppercase text-text-tertiary'>{relatedApps.length || '--'} {t('common.datasetMenus.relatedApp')}</div>
-      {relatedApps.map((item, index) => (
-        <LikedItem key={index} detail={item} isMobile={isMobile} />
-      ))}
-    </div>
-  )
-}
-export default React.memo(LinkedAppsPanel)

+ 1 - 1
web/app/components/base/pagination/index.tsx

@@ -8,7 +8,7 @@ import Button from '@/app/components/base/button'
 import Input from '@/app/components/base/input'
 import cn from '@/utils/classnames'
 
-export type Props = {
+type Props = {
   className?: string
   current: number
   onChange: (cur: number) => void

+ 15 - 21
web/app/components/base/param-item/index.tsx

@@ -1,6 +1,5 @@
 'use client'
 import type { FC } from 'react'
-import { InputNumber } from '../input-number'
 import Tooltip from '@/app/components/base/tooltip'
 import Slider from '@/app/components/base/slider'
 import Switch from '@/app/components/base/switch'
@@ -24,44 +23,39 @@ type Props = {
 const ParamItem: FC<Props> = ({ className, id, name, noTooltip, tip, step = 0.1, min = 0, max, value, enable, onChange, hasSwitch, onSwitchChange }) => {
   return (
     <div className={className}>
-      <div className="flex items-center justify-between">
-        <div className="flex items-center h-6">
+      <div className="flex items-center h-8 justify-between">
+        <div className="flex items-center">
           {hasSwitch && (
             <Switch
               size='md'
-              className='mr-2'
               defaultValue={enable}
               onChange={async (val) => {
                 onSwitchChange?.(id, val)
               }}
             />
           )}
-          <span className="mr-1 text-text-secondary system-sm-semibold">{name}</span>
+          <span className="mx-1 text-gray-900 text-[13px] leading-[18px] font-medium">{name}</span>
           {!noTooltip && (
             <Tooltip
               triggerClassName='w-4 h-4 shrink-0'
               popupContent={<div className="w-[200px]">{tip}</div>}
             />
           )}
+
         </div>
+        <div className="flex items-center"></div>
       </div>
-      <div className="mt-1 flex items-center">
-        <div className="mr-3 flex shrink-0 items-center">
-          <InputNumber
-            disabled={!enable}
-            type="number"
-            min={min}
-            max={max}
-            step={step}
-            size='sm'
-            value={value}
-            onChange={(value) => {
-              onChange(id, value)
-            }}
-            className='w-[72px]'
-          />
+      <div className="mt-2 flex items-center">
+        <div className="mr-4 flex shrink-0 items-center">
+          <input disabled={!enable} type="number" min={min} max={max} step={step} className="block w-[48px] h-7 text-xs leading-[18px] rounded-lg border-0 pl-1 pl py-1.5 bg-gray-50 text-gray-900  placeholder:text-gray-400 focus:ring-1 focus:ring-inset focus:ring-primary-600 disabled:opacity-60" value={(value === null || value === undefined) ? '' : value} onChange={(e) => {
+            const value = parseFloat(e.target.value)
+            if (value < min || value > max)
+              return
+
+            onChange(id, value)
+          }} />
         </div>
-        <div className="flex items-center grow">
+        <div className="flex items-center h-7 grow">
           <Slider
             className='w-full'
             disabled={!enable}

+ 9 - 14
web/app/components/base/radio-card/index.tsx

@@ -26,26 +26,24 @@ const RadioCard: FC<Props> = ({
   onChosen = () => { },
   chosenConfig,
   chosenConfigWrapClassName,
-  className,
 }) => {
   return (
     <div
       className={cn(
-        'relative p-3 border-[0.5px] border-components-option-card-option-border bg-components-option-card-option-bg rounded-xl cursor-pointer',
-        isChosen && 'border-[1.5px] bg-components-option-card-option-selected-bg',
-        className,
+        'border border-components-option-card-option-border bg-components-option-card-option-bg rounded-xl hover:shadow-xs cursor-pointer',
+        isChosen && 'bg-components-option-card-option-selected-bg border-components-panel-border shadow-xs',
       )}
     >
-      <div className='flex gap-x-2' onClick={onChosen}>
-        <div className={cn(iconBgClassName, 'shrink-0 flex size-8 justify-center items-center rounded-lg shadow-md')}>
+      <div className='flex py-3 pl-3 pr-4' onClick={onChosen}>
+        <div className={cn(iconBgClassName, 'mr-3 shrink-0 flex w-8 justify-center h-8 items-center rounded-lg')}>
           {icon}
         </div>
         <div className='grow'>
-          <div className='system-sm-semibold text-text-secondary mb-1'>{title}</div>
-          <div className='system-xs-regular text-text-tertiary'>{description}</div>
+          <div className='leading-5 text-sm font-medium text-gray-900'>{title}</div>
+          <div className='leading-[18px] text-xs font-normal text-[#667085]'>{description}</div>
         </div>
         {!noRadio && (
-          <div className='absolute top-3 right-3'>
+          <div className='shrink-0 flex items-center h-8'>
             <div className={cn(
               'w-4 h-4 border border-components-radio-border bg-components-radio-bg shadow-xs rounded-full',
               isChosen && 'border-[5px] border-components-radio-border-checked',
@@ -54,11 +52,8 @@ const RadioCard: FC<Props> = ({
         )}
       </div>
       {((isChosen && chosenConfig) || noRadio) && (
-        <div className='flex gap-x-2 mt-2'>
-          <div className='size-8 shrink-0'></div>
-          <div className={cn(chosenConfigWrapClassName, 'grow')}>
-            {chosenConfig}
-          </div>
+        <div className={cn(chosenConfigWrapClassName, 'p-3 border-t border-gray-200')}>
+          {chosenConfig}
         </div>
       )}
     </div>

Різницю між файлами не показано, бо вона завелика
+ 85 - 0
web/app/components/base/retry-button/index.tsx


+ 4 - 0
web/app/components/base/retry-button/style.module.css

@@ -0,0 +1,4 @@
+.retryBtn {
+    @apply inline-flex justify-center items-center content-center h-9 leading-5 rounded-lg px-4 py-2 text-base;
+    @apply border-solid border border-gray-200 text-gray-500 hover:bg-white hover:shadow-sm hover:border-gray-300;
+}

+ 3 - 4
web/app/components/base/simple-pie-chart/index.tsx

@@ -10,11 +10,10 @@ export type SimplePieChartProps = {
   fill?: string
   stroke?: string
   size?: number
-  animationDuration?: number
   className?: string
 }
 
-const SimplePieChart = ({ percentage = 80, fill = '#fdb022', stroke = '#f79009', size = 12, animationDuration, className }: SimplePieChartProps) => {
+const SimplePieChart = ({ percentage = 80, fill = '#fdb022', stroke = '#f79009', size = 12, className }: SimplePieChartProps) => {
   const option: EChartsOption = useMemo(() => ({
     series: [
       {
@@ -35,7 +34,7 @@ const SimplePieChart = ({ percentage = 80, fill = '#fdb022', stroke = '#f79009',
       {
         type: 'pie',
         radius: '83%',
-        animationDuration: animationDuration ?? 600,
+        animationDuration: 600,
         data: [
           { value: percentage, itemStyle: { color: fill } },
           { value: 100 - percentage, itemStyle: { color: '#fff' } },
@@ -49,7 +48,7 @@ const SimplePieChart = ({ percentage = 80, fill = '#fdb022', stroke = '#f79009',
         cursor: 'default',
       },
     ],
-  }), [stroke, fill, percentage, animationDuration])
+  }), [stroke, fill, percentage])
 
   return (
     <ReactECharts

+ 5 - 8
web/app/components/base/skeleton/index.tsx

@@ -3,7 +3,7 @@ import classNames from '@/utils/classnames'
 
 type SkeletonProps = ComponentProps<'div'>
 
-export const SkeletonContainer: FC<SkeletonProps> = (props) => {
+export const SkeletonContanier: FC<SkeletonProps> = (props) => {
   const { className, children, ...rest } = props
   return (
     <div className={classNames('flex flex-col gap-1', className)} {...rest}>
@@ -30,14 +30,11 @@ export const SkeletonRectangle: FC<SkeletonProps> = (props) => {
   )
 }
 
-export const SkeletonPoint: FC<SkeletonProps> = (props) => {
-  const { className, ...rest } = props
-  return (
-    <div className={classNames('text-text-quaternary text-xs font-medium', className)} {...rest}>·</div>
-  )
-}
+export const SkeletonPoint: FC = () =>
+  <div className='text-text-quaternary text-xs font-medium'>·</div>
+
 /** Usage
- * <SkeletonContainer>
+ * <SkeletonContanier>
  *  <SkeletonRow>
  *    <SkeletonRectangle className="w-96" />
  *    <SkeletonPoint />

+ 0 - 3
web/app/components/base/switch/index.tsx

@@ -64,7 +64,4 @@ const Switch = ({ onChange, size = 'md', defaultValue = false, disabled = false,
     </OriginalSwitch>
   )
 }
-
-Switch.displayName = 'Switch'
-
 export default React.memo(Switch)

+ 24 - 27
web/app/components/base/tag-input/index.tsx

@@ -3,8 +3,8 @@ import type { ChangeEvent, FC, KeyboardEvent } from 'react'
 import { } from 'use-context-selector'
 import { useTranslation } from 'react-i18next'
 import AutosizeInput from 'react-18-input-autosize'
-import { RiAddLine, RiCloseLine } from '@remixicon/react'
 import cn from '@/utils/classnames'
+import { X } from '@/app/components/base/icons/src/vender/line/general'
 import { useToastContext } from '@/app/components/base/toast'
 
 type TagInputProps = {
@@ -75,14 +75,14 @@ const TagInput: FC<TagInputProps> = ({
         (items || []).map((item, index) => (
           <div
             key={item}
-            className={cn('flex items-center mr-1 mt-1 pl-1.5 pr-1 py-1 system-xs-regular text-text-secondary border border-divider-deep bg-components-badge-white-to-dark rounded-md')}
-          >
+            className={cn('flex items-center mr-1 mt-1 px-2 py-1 text-sm text-gray-700 border border-gray-200', isSpecialMode ? 'bg-white rounded-md' : 'rounded-lg')}>
             {item}
             {
               !disableRemove && (
-                <div className='flex items-center justify-center w-4 h-4 cursor-pointer' onClick={() => handleRemove(index)}>
-                  <RiCloseLine className='ml-0.5 w-3.5 h-3.5 text-text-tertiary' />
-                </div>
+                <X
+                  className='ml-0.5 w-3 h-3 text-gray-500 cursor-pointer'
+                  onClick={() => handleRemove(index)}
+                />
               )
             }
           </div>
@@ -90,27 +90,24 @@ const TagInput: FC<TagInputProps> = ({
       }
       {
         !disableAdd && (
-          <div className={cn('flex items-center gap-x-0.5 mt-1 group/tag-add', !isSpecialMode ? 'px-1.5 rounded-md border border-dashed border-divider-deep' : '')}>
-            {!isSpecialMode && !focused && <RiAddLine className='w-3.5 h-3.5 text-text-placeholder group-hover/tag-add:text-text-secondary' />}
-            <AutosizeInput
-              inputClassName={cn('outline-none appearance-none placeholder:text-text-placeholder caret-[#295EFF] group-hover/tag-add:placeholder:text-text-secondary', isSpecialMode ? 'bg-transparent' : '')}
-              className={cn(
-                !isInWorkflow && 'max-w-[300px]',
-                isInWorkflow && 'max-w-[146px]',
-                `
-                py-1 rounded-md overflow-hidden system-xs-regular
-                ${focused && isSpecialMode && 'px-1.5 border border-dashed border-divider-deep'}
-              `)}
-              onFocus={() => setFocused(true)}
-              onBlur={handleBlur}
-              value={value}
-              onChange={(e: ChangeEvent<HTMLInputElement>) => {
-                setValue(e.target.value)
-              }}
-              onKeyDown={handleKeyDown}
-              placeholder={t(placeholder || (isSpecialMode ? 'common.model.params.stop_sequencesPlaceholder' : 'datasetDocuments.segment.addKeyWord'))}
-            />
-          </div>
+          <AutosizeInput
+            inputClassName={cn('outline-none appearance-none placeholder:text-gray-300 caret-primary-600 hover:placeholder:text-gray-400', isSpecialMode ? 'bg-transparent' : '')}
+            className={cn(
+              !isInWorkflow && 'max-w-[300px]',
+              isInWorkflow && 'max-w-[146px]',
+              `
+              mt-1 py-1 rounded-lg border border-transparent text-sm  overflow-hidden
+              ${focused && 'px-2 border !border-dashed !border-gray-200'}
+            `)}
+            onFocus={() => setFocused(true)}
+            onBlur={handleBlur}
+            value={value}
+            onChange={(e: ChangeEvent<HTMLInputElement>) => {
+              setValue(e.target.value)
+            }}
+            onKeyDown={handleKeyDown}
+            placeholder={t(placeholder || (isSpecialMode ? 'common.model.params.stop_sequencesPlaceholder' : 'datasetDocuments.segment.addKeyWord'))}
+          />
         )
       }
     </div>

+ 7 - 12
web/app/components/base/toast/index.tsx

@@ -21,7 +21,6 @@ export type IToastProps = {
   children?: ReactNode
   onClose?: () => void
   className?: string
-  customComponent?: ReactNode
 }
 type IToastContext = {
   notify: (props: IToastProps) => void
@@ -36,7 +35,6 @@ const Toast = ({
   message,
   children,
   className,
-  customComponent,
 }: IToastProps) => {
   const { close } = useToastContext()
   // sometimes message is react node array. Not handle it.
@@ -51,7 +49,8 @@ const Toast = ({
     'top-0',
     'right-0',
   )}>
-    <div className={`absolute inset-0 opacity-40 -z-10 ${(type === 'success' && 'bg-[linear-gradient(92deg,rgba(23,178,106,0.25)_0%,rgba(255,255,255,0.00)_100%)]')
+    <div className={`absolute inset-0 opacity-40 ${
+      (type === 'success' && 'bg-[linear-gradient(92deg,rgba(23,178,106,0.25)_0%,rgba(255,255,255,0.00)_100%)]')
       || (type === 'warning' && 'bg-[linear-gradient(92deg,rgba(247,144,9,0.25)_0%,rgba(255,255,255,0.00)_100%)]')
       || (type === 'error' && 'bg-[linear-gradient(92deg,rgba(240,68,56,0.25)_0%,rgba(255,255,255,0.00)_100%)]')
       || (type === 'info' && 'bg-[linear-gradient(92deg,rgba(11,165,236,0.25)_0%,rgba(255,255,255,0.00)_100%)]')
@@ -64,17 +63,14 @@ const Toast = ({
         {type === 'warning' && <RiAlertFill className={`${size === 'md' ? 'w-5 h-5' : 'w-4 h-4'} text-text-warning-secondary`} aria-hidden="true" />}
         {type === 'info' && <RiInformation2Fill className={`${size === 'md' ? 'w-5 h-5' : 'w-4 h-4'} text-text-accent`} aria-hidden="true" />}
       </div>
-      <div className={`flex py-1 ${size === 'md' ? 'px-1' : 'px-0.5'} flex-col items-start gap-1 flex-grow z-10`}>
-        <div className='flex items-center gap-1'>
-          <div className='text-text-primary system-sm-semibold'>{message}</div>
-          {customComponent}
-        </div>
+      <div className={`flex py-1 ${size === 'md' ? 'px-1' : 'px-0.5'} flex-col items-start gap-1 flex-grow`}>
+        <div className='text-text-primary system-sm-semibold'>{message}</div>
         {children && <div className='text-text-secondary system-xs-regular'>
           {children}
         </div>
         }
       </div>
-      <ActionButton onClick={close}>
+      <ActionButton className='z-[1000]' onClick={close}>
         <RiCloseLine className='w-4 h-4 flex-shrink-0 text-text-tertiary' />
       </ActionButton>
     </div>
@@ -121,8 +117,7 @@ Toast.notify = ({
   message,
   duration,
   className,
-  customComponent,
-}: Pick<IToastProps, 'type' | 'size' | 'message' | 'duration' | 'className' | 'customComponent'>) => {
+}: Pick<IToastProps, 'type' | 'size' | 'message' | 'duration' | 'className'>) => {
   const defaultDuring = (type === 'success' || type === 'info') ? 3000 : 6000
   if (typeof window === 'object') {
     const holder = document.createElement('div')
@@ -138,7 +133,7 @@ Toast.notify = ({
           }
         },
       }}>
-        <Toast type={type} size={size} message={message} duration={duration} className={className} customComponent={customComponent} />
+        <Toast type={type} size={size} message={message} duration={duration} className={className} />
       </ToastContext.Provider>,
     )
     document.body.appendChild(holder)

+ 1 - 3
web/app/components/base/tooltip/index.tsx

@@ -14,7 +14,6 @@ export type TooltipProps = {
   popupContent?: React.ReactNode
   children?: React.ReactNode
   popupClassName?: string
-  noDecoration?: boolean
   offset?: OffsetOptions
   needsDelay?: boolean
   asChild?: boolean
@@ -28,7 +27,6 @@ const Tooltip: FC<TooltipProps> = ({
   popupContent,
   children,
   popupClassName,
-  noDecoration,
   offset,
   asChild = true,
   needsDelay = false,
@@ -98,7 +96,7 @@ const Tooltip: FC<TooltipProps> = ({
       >
         {popupContent && (<div
           className={cn(
-            !noDecoration && 'relative px-3 py-2 system-xs-regular text-text-tertiary bg-components-panel-bg rounded-md shadow-lg break-words',
+            'relative px-3 py-2 system-xs-regular text-text-tertiary bg-components-panel-bg rounded-md shadow-lg break-words',
             popupClassName,
           )}
           onMouseEnter={() => triggerMethod === 'hover' && setHoverPopup()}

+ 7 - 12
web/app/components/billing/priority-label/index.tsx

@@ -4,7 +4,6 @@ import {
   DocumentProcessingPriority,
   Plan,
 } from '../type'
-import cn from '@/utils/classnames'
 import { useProviderContext } from '@/context/provider-context'
 import {
   ZapFast,
@@ -12,11 +11,7 @@ import {
 } from '@/app/components/base/icons/src/vender/solid/general'
 import Tooltip from '@/app/components/base/tooltip'
 
-type PriorityLabelProps = {
-  className?: string
-}
-
-const PriorityLabel = ({ className }: PriorityLabelProps) => {
+const PriorityLabel = () => {
   const { t } = useTranslation()
   const { plan } = useProviderContext()
 
@@ -42,18 +37,18 @@ const PriorityLabel = ({ className }: PriorityLabelProps) => {
         }
       </div>
     }>
-      <span className={cn(`
-        shrink-0 flex items-center ml-1 px-1 h-[18px] rounded-[5px] border border-text-accent-secondary
-        text-2xs font-medium text-text-accent-secondary
-      `, className)}>
+      <span className={`
+        flex items-center ml-1 px-[5px] h-[18px] rounded border border-[#C7D7FE]
+        text-[10px] font-medium text-[#3538CD]
+      `}>
         {
           plan.type === Plan.professional && (
-            <ZapNarrow className='mr-0.5 size-3' />
+            <ZapNarrow className='mr-0.5 w-3 h-3' />
           )
         }
         {
           (plan.type === Plan.team || plan.type === Plan.enterprise) && (
-            <ZapFast className='mr-0.5 size-3' />
+            <ZapFast className='mr-0.5 w-3 h-3' />
           )
         }
         {t(`billing.plansCommon.priority.${priority}`)}

+ 0 - 54
web/app/components/datasets/chunk.tsx

@@ -1,54 +0,0 @@
-import type { FC, PropsWithChildren } from 'react'
-import { SelectionMod } from '../base/icons/src/public/knowledge'
-import type { QA } from '@/models/datasets'
-
-export type ChunkLabelProps = {
-  label: string
-  characterCount: number
-}
-
-export const ChunkLabel: FC<ChunkLabelProps> = (props) => {
-  const { label, characterCount } = props
-  return <div className='flex items-center text-text-tertiary text-xs font-medium'>
-    <SelectionMod className='size-[10px]' />
-    <p className='flex gap-2 ml-0.5'><span>
-      {label}
-    </span>
-    <span>
-        ·
-    </span>
-    <span>
-      {`${characterCount} characters`}
-    </span></p>
-  </div>
-}
-
-export type ChunkContainerProps = ChunkLabelProps & PropsWithChildren
-
-export const ChunkContainer: FC<ChunkContainerProps> = (props) => {
-  const { label, characterCount, children } = props
-  return <div className='space-y-2'>
-    <ChunkLabel label={label} characterCount={characterCount} />
-    <div className='text-text-secondary body-md-regular'>
-      {children}
-    </div>
-  </div>
-}
-
-export type QAPreviewProps = {
-  qa: QA
-}
-
-export const QAPreview: FC<QAPreviewProps> = (props) => {
-  const { qa } = props
-  return <div className='flex flex-col gap-y-2'>
-    <div className='flex gap-x-1'>
-      <label className='text-text-tertiary text-[13px] font-medium leading-[20px] shrink-0'>Q</label>
-      <p className='text-text-secondary body-md-regular'>{qa.question}</p>
-    </div>
-    <div className='flex gap-x-1'>
-      <label className='text-text-tertiary text-[13px] font-medium leading-[20px] shrink-0'>A</label>
-      <p className='text-text-secondary body-md-regular'>{qa.answer}</p>
-    </div>
-  </div>
-}

+ 0 - 29
web/app/components/datasets/common/chunking-mode-label.tsx

@@ -1,29 +0,0 @@
-'use client'
-import type { FC } from 'react'
-import React from 'react'
-import { useTranslation } from 'react-i18next'
-import Badge from '@/app/components/base/badge'
-import { GeneralType, ParentChildType } from '@/app/components/base/icons/src/public/knowledge'
-
-type Props = {
-  isGeneralMode: boolean
-  isQAMode: boolean
-}
-
-const ChunkingModeLabel: FC<Props> = ({
-  isGeneralMode,
-  isQAMode,
-}) => {
-  const { t } = useTranslation()
-  const TypeIcon = isGeneralMode ? GeneralType : ParentChildType
-
-  return (
-    <Badge>
-      <div className='flex items-center h-full space-x-0.5 text-text-tertiary'>
-        <TypeIcon className='w-3 h-3' />
-        <span className='system-2xs-medium-uppercase'>{isGeneralMode ? `${t('dataset.chunkingMode.general')}${isQAMode ? ' · QA' : ''}` : t('dataset.chunkingMode.parentChild')}</span>
-      </div>
-    </Badge>
-  )
-}
-export default React.memo(ChunkingModeLabel)

+ 0 - 40
web/app/components/datasets/common/document-file-icon.tsx

@@ -1,40 +0,0 @@
-'use client'
-import type { FC } from 'react'
-import React from 'react'
-import FileTypeIcon from '../../base/file-uploader/file-type-icon'
-import type { FileAppearanceType } from '@/app/components/base/file-uploader/types'
-import { FileAppearanceTypeEnum } from '@/app/components/base/file-uploader/types'
-
-const extendToFileTypeMap: { [key: string]: FileAppearanceType } = {
-  pdf: FileAppearanceTypeEnum.pdf,
-  json: FileAppearanceTypeEnum.document,
-  html: FileAppearanceTypeEnum.document,
-  txt: FileAppearanceTypeEnum.document,
-  markdown: FileAppearanceTypeEnum.markdown,
-  md: FileAppearanceTypeEnum.markdown,
-  xlsx: FileAppearanceTypeEnum.excel,
-  xls: FileAppearanceTypeEnum.excel,
-  csv: FileAppearanceTypeEnum.excel,
-  doc: FileAppearanceTypeEnum.word,
-  docx: FileAppearanceTypeEnum.word,
-}
-
-type Props = {
-  extension?: string
-  name?: string
-  size?: 'sm' | 'lg' | 'md'
-  className?: string
-}
-
-const DocumentFileIcon: FC<Props> = ({
-  extension,
-  name,
-  size = 'md',
-  className,
-}) => {
-  const localExtension = extension?.toLowerCase() || name?.split('.')?.pop()?.toLowerCase()
-  return (
-    <FileTypeIcon type={extendToFileTypeMap[localExtension!] || FileAppearanceTypeEnum.document} size={size} className={className} />
-  )
-}
-export default React.memo(DocumentFileIcon)

+ 0 - 42
web/app/components/datasets/common/document-picker/document-list.tsx

@@ -1,42 +0,0 @@
-'use client'
-import type { FC } from 'react'
-import React, { useCallback } from 'react'
-import FileIcon from '../document-file-icon'
-import cn from '@/utils/classnames'
-import type { DocumentItem } from '@/models/datasets'
-
-type Props = {
-  className?: string
-  list: DocumentItem[]
-  onChange: (value: DocumentItem) => void
-}
-
-const DocumentList: FC<Props> = ({
-  className,
-  list,
-  onChange,
-}) => {
-  const handleChange = useCallback((item: DocumentItem) => {
-    return () => onChange(item)
-  }, [onChange])
-
-  return (
-    <div className={cn(className)}>
-      {list.map((item) => {
-        const { id, name, extension } = item
-        return (
-          <div
-            key={id}
-            className='flex items-center h-8 px-2 hover:bg-state-base-hover rounded-lg space-x-2 cursor-pointer'
-            onClick={handleChange(item)}
-          >
-            <FileIcon name={item.name} extension={extension} size='md' />
-            <div className='truncate text-text-secondary text-sm'>{name}</div>
-          </div>
-        )
-      })}
-    </div>
-  )
-}
-
-export default React.memo(DocumentList)

+ 0 - 118
web/app/components/datasets/common/document-picker/index.tsx

@@ -1,118 +0,0 @@
-'use client'
-import type { FC } from 'react'
-import React, { useCallback, useState } from 'react'
-import { useBoolean } from 'ahooks'
-import { RiArrowDownSLine } from '@remixicon/react'
-import { useTranslation } from 'react-i18next'
-import FileIcon from '../document-file-icon'
-import DocumentList from './document-list'
-import type { DocumentItem, ParentMode, SimpleDocumentDetail } from '@/models/datasets'
-import { ProcessMode } from '@/models/datasets'
-import {
-  PortalToFollowElem,
-  PortalToFollowElemContent,
-  PortalToFollowElemTrigger,
-} from '@/app/components/base/portal-to-follow-elem'
-import cn from '@/utils/classnames'
-import SearchInput from '@/app/components/base/search-input'
-import { GeneralType, ParentChildType } from '@/app/components/base/icons/src/public/knowledge'
-import { useDocumentList } from '@/service/knowledge/use-document'
-import Loading from '@/app/components/base/loading'
-
-type Props = {
-  datasetId: string
-  value: {
-    name?: string
-    extension?: string
-    processMode?: ProcessMode
-    parentMode?: ParentMode
-  }
-  onChange: (value: SimpleDocumentDetail) => void
-}
-
-const DocumentPicker: FC<Props> = ({
-  datasetId,
-  value,
-  onChange,
-}) => {
-  const { t } = useTranslation()
-  const {
-    name,
-    extension,
-    processMode,
-    parentMode,
-  } = value
-  const [query, setQuery] = useState('')
-
-  const { data } = useDocumentList({
-    datasetId,
-    query: {
-      keyword: query,
-      page: 1,
-      limit: 20,
-    },
-  })
-  const documentsList = data?.data
-  const isParentChild = processMode === ProcessMode.parentChild
-  const TypeIcon = isParentChild ? ParentChildType : GeneralType
-
-  const [open, {
-    set: setOpen,
-    toggle: togglePopup,
-  }] = useBoolean(false)
-  const ArrowIcon = RiArrowDownSLine
-
-  const handleChange = useCallback(({ id }: DocumentItem) => {
-    onChange(documentsList?.find(item => item.id === id) as SimpleDocumentDetail)
-    setOpen(false)
-  }, [documentsList, onChange, setOpen])
-
-  return (
-    <PortalToFollowElem
-      open={open}
-      onOpenChange={setOpen}
-      placement='bottom-start'
-    >
-      <PortalToFollowElemTrigger onClick={togglePopup}>
-        <div className={cn('flex items-center ml-1 px-2 py-0.5 rounded-lg hover:bg-state-base-hover select-none cursor-pointer', open && 'bg-state-base-hover')}>
-          <FileIcon name={name} extension={extension} size='lg' />
-          <div className='flex flex-col items-start ml-1 mr-0.5'>
-            <div className='flex items-center space-x-0.5'>
-              <span className={cn('system-md-semibold')}> {name || '--'}</span>
-              <ArrowIcon className={'h-4 w-4 text-text-primary'} />
-            </div>
-            <div className='flex items-center h-3 text-text-tertiary space-x-0.5'>
-              <TypeIcon className='w-3 h-3' />
-              <span className={cn('system-2xs-medium-uppercase', isParentChild && 'mt-0.5' /* to icon problem cause not ver align */)}>
-                {isParentChild ? t('dataset.chunkingMode.parentChild') : t('dataset.chunkingMode.general')}
-                {isParentChild && ` · ${!parentMode ? '--' : parentMode === 'paragraph' ? t('dataset.parentMode.paragraph') : t('dataset.parentMode.fullDoc')}`}
-              </span>
-            </div>
-          </div>
-        </div>
-      </PortalToFollowElemTrigger>
-      <PortalToFollowElemContent className='z-[11]'>
-        <div className='w-[360px] p-1 pt-2 rounded-xl border-[0.5px] border-components-panel-border bg-components-panel-bg-blur shadow-lg backdrop-blur-[5px]'>
-          <SearchInput value={query} onChange={setQuery} className='mx-1' />
-          {documentsList
-            ? (
-              <DocumentList
-                className='mt-2'
-                list={documentsList.map(d => ({
-                  id: d.id,
-                  name: d.name,
-                  extension: d.data_source_detail_dict?.upload_file?.extension || '',
-                }))}
-                onChange={handleChange}
-              />
-            )
-            : (<div className='mt-2 flex items-center justify-center w-[360px] h-[100px]'>
-              <Loading />
-            </div>)}
-        </div>
-
-      </PortalToFollowElemContent>
-    </PortalToFollowElem>
-  )
-}
-export default React.memo(DocumentPicker)

+ 0 - 82
web/app/components/datasets/common/document-picker/preview-document-picker.tsx

@@ -1,82 +0,0 @@
-'use client'
-import type { FC } from 'react'
-import React, { useCallback } from 'react'
-import { useBoolean } from 'ahooks'
-import { RiArrowDownSLine } from '@remixicon/react'
-import { useTranslation } from 'react-i18next'
-import FileIcon from '../document-file-icon'
-import DocumentList from './document-list'
-import {
-  PortalToFollowElem,
-  PortalToFollowElemContent,
-  PortalToFollowElemTrigger,
-} from '@/app/components/base/portal-to-follow-elem'
-import cn from '@/utils/classnames'
-import Loading from '@/app/components/base/loading'
-import type { DocumentItem } from '@/models/datasets'
-
-type Props = {
-  className?: string
-  value: DocumentItem
-  files: DocumentItem[]
-  onChange: (value: DocumentItem) => void
-}
-
-const PreviewDocumentPicker: FC<Props> = ({
-  className,
-  value,
-  files,
-  onChange,
-}) => {
-  const { t } = useTranslation()
-  const { name, extension } = value
-
-  const [open, {
-    set: setOpen,
-    toggle: togglePopup,
-  }] = useBoolean(false)
-  const ArrowIcon = RiArrowDownSLine
-
-  const handleChange = useCallback((item: DocumentItem) => {
-    onChange(item)
-    setOpen(false)
-  }, [onChange, setOpen])
-
-  return (
-    <PortalToFollowElem
-      open={open}
-      onOpenChange={setOpen}
-      placement='bottom-start'
-      offset={4}
-    >
-      <PortalToFollowElemTrigger onClick={togglePopup}>
-        <div className={cn('flex items-center h-6 px-1 rounded-md hover:bg-state-base-hover select-none', open && 'bg-state-base-hover', className)}>
-          <FileIcon name={name} extension={extension} size='md' />
-          <div className='flex flex-col items-start ml-1'>
-            <div className='flex items-center space-x-0.5'>
-              <span className={cn('system-md-semibold max-w-[200px] truncate text-text-primary')}> {name || '--'}</span>
-              <ArrowIcon className={'h-[18px] w-[18px] text-text-primary'} />
-            </div>
-          </div>
-        </div>
-      </PortalToFollowElemTrigger>
-      <PortalToFollowElemContent className='z-[11]'>
-        <div className='w-[392px] p-1 rounded-xl border-[0.5px] border-components-panel-border bg-components-panel-bg-blur shadow-lg backdrop-blur-[5px]'>
-          {files?.length > 1 && <div className='pl-2 flex items-center h-8 system-xs-medium-uppercase text-text-tertiary'>{t('dataset.preprocessDocument', { num: files.length })}</div>}
-          {files?.length > 0
-            ? (
-              <DocumentList
-                list={files}
-                onChange={handleChange}
-              />
-            )
-            : (<div className='mt-2 flex items-center justify-center w-[360px] h-[100px]'>
-              <Loading />
-            </div>)}
-        </div>
-
-      </PortalToFollowElemContent>
-    </PortalToFollowElem>
-  )
-}
-export default React.memo(PreviewDocumentPicker)

+ 0 - 38
web/app/components/datasets/common/document-status-with-action/auto-disabled-document.tsx

@@ -1,38 +0,0 @@
-'use client'
-import type { FC } from 'react'
-import React, { useCallback } from 'react'
-import { useTranslation } from 'react-i18next'
-import StatusWithAction from './status-with-action'
-import { useAutoDisabledDocuments, useDocumentEnable, useInvalidDisabledDocument } from '@/service/knowledge/use-document'
-import Toast from '@/app/components/base/toast'
-type Props = {
-  datasetId: string
-}
-
-const AutoDisabledDocument: FC<Props> = ({
-  datasetId,
-}) => {
-  const { t } = useTranslation()
-  const { data, isLoading } = useAutoDisabledDocuments(datasetId)
-  const invalidDisabledDocument = useInvalidDisabledDocument()
-  const documentIds = data?.document_ids
-  const hasDisabledDocument = documentIds && documentIds.length > 0
-  const { mutateAsync: enableDocument } = useDocumentEnable()
-  const handleEnableDocuments = useCallback(async () => {
-    await enableDocument({ datasetId, documentIds })
-    invalidDisabledDocument()
-    Toast.notify({ type: 'success', message: t('common.actionMsg.modifiedSuccessfully') })
-  }, [])
-  if (!hasDisabledDocument || isLoading)
-    return null
-
-  return (
-    <StatusWithAction
-      type='info'
-      description={t('dataset.documentsDisabled', { num: documentIds?.length })}
-      actionText={t('dataset.enable')}
-      onAction={handleEnableDocuments}
-    />
-  )
-}
-export default React.memo(AutoDisabledDocument)

+ 0 - 69
web/app/components/datasets/common/document-status-with-action/index-failed.tsx

@@ -1,69 +0,0 @@
-'use client'
-import type { FC } from 'react'
-import React, { useEffect, useReducer } from 'react'
-import { useTranslation } from 'react-i18next'
-import useSWR from 'swr'
-import StatusWithAction from './status-with-action'
-import { getErrorDocs, retryErrorDocs } from '@/service/datasets'
-import type { IndexingStatusResponse } from '@/models/datasets'
-
-type Props = {
-  datasetId: string
-}
-type IIndexState = {
-  value: string
-}
-type ActionType = 'retry' | 'success' | 'error'
-
-type IAction = {
-  type: ActionType
-}
-const indexStateReducer = (state: IIndexState, action: IAction) => {
-  const actionMap = {
-    retry: 'retry',
-    success: 'success',
-    error: 'error',
-  }
-
-  return {
-    ...state,
-    value: actionMap[action.type] || state.value,
-  }
-}
-
-const RetryButton: FC<Props> = ({ datasetId }) => {
-  const { t } = useTranslation()
-  const [indexState, dispatch] = useReducer(indexStateReducer, { value: 'success' })
-  const { data: errorDocs, isLoading } = useSWR({ datasetId }, getErrorDocs)
-
-  const onRetryErrorDocs = async () => {
-    dispatch({ type: 'retry' })
-    const document_ids = errorDocs?.data.map((doc: IndexingStatusResponse) => doc.id) || []
-    const res = await retryErrorDocs({ datasetId, document_ids })
-    if (res.result === 'success')
-      dispatch({ type: 'success' })
-    else
-      dispatch({ type: 'error' })
-  }
-
-  useEffect(() => {
-    if (errorDocs?.total === 0)
-      dispatch({ type: 'success' })
-    else
-      dispatch({ type: 'error' })
-  }, [errorDocs?.total])
-
-  if (isLoading || indexState.value === 'success')
-    return null
-
-  return (
-    <StatusWithAction
-      type='warning'
-      description={`${errorDocs?.total} ${t('dataset.docsFailedNotice')}`}
-      actionText={t('dataset.retry')}
-      disabled={indexState.value === 'retry'}
-      onAction={indexState.value === 'error' ? onRetryErrorDocs : () => { }}
-    />
-  )
-}
-export default RetryButton

+ 0 - 65
web/app/components/datasets/common/document-status-with-action/status-with-action.tsx

@@ -1,65 +0,0 @@
-'use client'
-import { RiAlertFill, RiCheckboxCircleFill, RiErrorWarningFill, RiInformation2Fill } from '@remixicon/react'
-import type { FC } from 'react'
-import React from 'react'
-import cn from '@/utils/classnames'
-import Divider from '@/app/components/base/divider'
-
-type Status = 'success' | 'error' | 'warning' | 'info'
-type Props = {
-  type?: Status
-  description: string
-  actionText: string
-  onAction: () => void
-  disabled?: boolean
-}
-
-const IconMap = {
-  success: {
-    Icon: RiCheckboxCircleFill,
-    color: 'text-text-success',
-  },
-  error: {
-    Icon: RiErrorWarningFill,
-    color: 'text-text-destructive',
-  },
-  warning: {
-    Icon: RiAlertFill,
-    color: 'text-text-warning-secondary',
-  },
-  info: {
-    Icon: RiInformation2Fill,
-    color: 'text-text-accent',
-  },
-}
-
-const getIcon = (type: Status) => {
-  return IconMap[type]
-}
-
-const StatusAction: FC<Props> = ({
-  type = 'info',
-  description,
-  actionText,
-  onAction,
-  disabled,
-}) => {
-  const { Icon, color } = getIcon(type)
-  return (
-    <div className='relative flex items-center h-[34px] rounded-lg pl-2 pr-3 border border-components-panel-border bg-components-panel-bg-blur shadow-xs'>
-      <div className={`absolute inset-0 opacity-40 rounded-lg ${(type === 'success' && 'bg-[linear-gradient(92deg,rgba(23,178,106,0.25)_0%,rgba(255,255,255,0.00)_100%)]')
-        || (type === 'warning' && 'bg-[linear-gradient(92deg,rgba(247,144,9,0.25)_0%,rgba(255,255,255,0.00)_100%)]')
-        || (type === 'error' && 'bg-[linear-gradient(92deg,rgba(240,68,56,0.25)_0%,rgba(255,255,255,0.00)_100%)]')
-        || (type === 'info' && 'bg-[linear-gradient(92deg,rgba(11,165,236,0.25)_0%,rgba(255,255,255,0.00)_100%)]')
-      }`}
-      />
-      <div className='relative z-10 flex h-full items-center space-x-2'>
-        <Icon className={cn('w-4 h-4', color)} />
-        <div className='text-[13px] font-normal text-text-secondary'>{description}</div>
-        <Divider type='vertical' className='!h-4' />
-        <div onClick={onAction} className={cn('text-text-accent font-semibold text-[13px] cursor-pointer', disabled && 'text-text-disabled cursor-not-allowed')}>{actionText}</div>
-      </div>
-    </div>
-  )
-}
-export default React.memo(StatusAction)

+ 14 - 13
web/app/components/datasets/common/economical-retrieval-method-config/index.tsx

@@ -2,11 +2,10 @@
 import type { FC } from 'react'
 import React from 'react'
 import { useTranslation } from 'react-i18next'
-import Image from 'next/image'
 import RetrievalParamConfig from '../retrieval-param-config'
-import { OptionCard } from '../../create/step-two/option-card'
-import { retrievalIcon } from '../../create/icons'
 import { RETRIEVE_METHOD } from '@/types/app'
+import RadioCard from '@/app/components/base/radio-card'
+import { HighPriority } from '@/app/components/base/icons/src/vender/solid/arrows'
 import type { RetrievalConfig } from '@/types/app'
 
 type Props = {
@@ -22,17 +21,19 @@ const EconomicalRetrievalMethodConfig: FC<Props> = ({
 
   return (
     <div className='space-y-2'>
-      <OptionCard icon={<Image className='w-4 h-4' src={retrievalIcon.vector} alt='' />}
+      <RadioCard
+        icon={<HighPriority className='w-4 h-4 text-[#7839EE]' />}
         title={t('dataset.retrieval.invertedIndex.title')}
-        description={t('dataset.retrieval.invertedIndex.description')} isActive
-        activeHeaderClassName='bg-dataset-option-card-purple-gradient'
-      >
-        <RetrievalParamConfig
-          type={RETRIEVE_METHOD.invertedIndex}
-          value={value}
-          onChange={onChange}
-        />
-      </OptionCard>
+        description={t('dataset.retrieval.invertedIndex.description')}
+        noRadio
+        chosenConfig={
+          <RetrievalParamConfig
+            type={RETRIEVE_METHOD.invertedIndex}
+            value={value}
+            onChange={onChange}
+          />
+        }
+      />
     </div>
   )
 }

+ 41 - 48
web/app/components/datasets/common/retrieval-method-config/index.tsx

@@ -2,13 +2,12 @@
 import type { FC } from 'react'
 import React from 'react'
 import { useTranslation } from 'react-i18next'
-import Image from 'next/image'
 import RetrievalParamConfig from '../retrieval-param-config'
-import { OptionCard } from '../../create/step-two/option-card'
-import Effect from '../../create/assets/option-card-effect-purple.svg'
-import { retrievalIcon } from '../../create/icons'
 import type { RetrievalConfig } from '@/types/app'
 import { RETRIEVE_METHOD } from '@/types/app'
+import RadioCard from '@/app/components/base/radio-card'
+import { PatternRecognition, Semantic } from '@/app/components/base/icons/src/vender/solid/development'
+import { FileSearch02 } from '@/app/components/base/icons/src/vender/solid/files'
 import { useProviderContext } from '@/context/provider-context'
 import { useDefaultModel } from '@/app/components/header/account-setting/model-provider-page/hooks'
 import { ModelTypeEnum } from '@/app/components/header/account-setting/model-provider-page/declarations'
@@ -17,7 +16,6 @@ import {
   RerankingModeEnum,
   WeightedScoreEnum,
 } from '@/models/datasets'
-import Badge from '@/app/components/base/badge'
 
 type Props = {
   value: RetrievalConfig
@@ -58,72 +56,67 @@ const RetrievalMethodConfig: FC<Props> = ({
   return (
     <div className='space-y-2'>
       {supportRetrievalMethods.includes(RETRIEVE_METHOD.semantic) && (
-        <OptionCard icon={<Image className='w-4 h-4' src={retrievalIcon.vector} alt='' />}
+        <RadioCard
+          icon={<Semantic className='w-4 h-4 text-[#7839EE]' />}
           title={t('dataset.retrieval.semantic_search.title')}
           description={t('dataset.retrieval.semantic_search.description')}
-          isActive={
-            value.search_method === RETRIEVE_METHOD.semantic
-          }
-          onSwitched={() => onChange({
+          isChosen={value.search_method === RETRIEVE_METHOD.semantic}
+          onChosen={() => onChange({
             ...value,
             search_method: RETRIEVE_METHOD.semantic,
           })}
-          effectImg={Effect.src}
-          activeHeaderClassName='bg-dataset-option-card-purple-gradient'
-        >
-          <RetrievalParamConfig
-            type={RETRIEVE_METHOD.semantic}
-            value={value}
-            onChange={onChange}
-          />
-        </OptionCard>
+          chosenConfig={
+            <RetrievalParamConfig
+              type={RETRIEVE_METHOD.semantic}
+              value={value}
+              onChange={onChange}
+            />
+          }
+        />
       )}
       {supportRetrievalMethods.includes(RETRIEVE_METHOD.semantic) && (
-        <OptionCard icon={<Image className='w-4 h-4' src={retrievalIcon.fullText} alt='' />}
+        <RadioCard
+          icon={<FileSearch02 className='w-4 h-4 text-[#7839EE]' />}
           title={t('dataset.retrieval.full_text_search.title')}
           description={t('dataset.retrieval.full_text_search.description')}
-          isActive={
-            value.search_method === RETRIEVE_METHOD.fullText
-          }
-          onSwitched={() => onChange({
+          isChosen={value.search_method === RETRIEVE_METHOD.fullText}
+          onChosen={() => onChange({
             ...value,
             search_method: RETRIEVE_METHOD.fullText,
           })}
-          effectImg={Effect.src}
-          activeHeaderClassName='bg-dataset-option-card-purple-gradient'
-        >
-          <RetrievalParamConfig
-            type={RETRIEVE_METHOD.fullText}
-            value={value}
-            onChange={onChange}
-          />
-        </OptionCard>
+          chosenConfig={
+            <RetrievalParamConfig
+              type={RETRIEVE_METHOD.fullText}
+              value={value}
+              onChange={onChange}
+            />
+          }
+        />
       )}
       {supportRetrievalMethods.includes(RETRIEVE_METHOD.semantic) && (
-        <OptionCard icon={<Image className='w-4 h-4' src={retrievalIcon.hybrid} alt='' />}
+        <RadioCard
+          icon={<PatternRecognition className='w-4 h-4 text-[#7839EE]' />}
           title={
             <div className='flex items-center space-x-1'>
               <div>{t('dataset.retrieval.hybrid_search.title')}</div>
-              <Badge text={t('dataset.retrieval.hybrid_search.recommend')!} className='border-text-accent-secondary text-text-accent-secondary ml-1 h-[18px]' uppercase />
+              <div className='flex h-full items-center px-1.5 rounded-md border border-[#E0EAFF] text-xs font-medium text-[#444CE7]'>{t('dataset.retrieval.hybrid_search.recommend')}</div>
             </div>
           }
-          description={t('dataset.retrieval.hybrid_search.description')} isActive={
-            value.search_method === RETRIEVE_METHOD.hybrid
-          }
-          onSwitched={() => onChange({
+          description={t('dataset.retrieval.hybrid_search.description')}
+          isChosen={value.search_method === RETRIEVE_METHOD.hybrid}
+          onChosen={() => onChange({
             ...value,
             search_method: RETRIEVE_METHOD.hybrid,
             reranking_enable: true,
           })}
-          effectImg={Effect.src}
-          activeHeaderClassName='bg-dataset-option-card-purple-gradient'
-        >
-          <RetrievalParamConfig
-            type={RETRIEVE_METHOD.hybrid}
-            value={value}
-            onChange={onChange}
-          />
-        </OptionCard>
+          chosenConfig={
+            <RetrievalParamConfig
+              type={RETRIEVE_METHOD.hybrid}
+              value={value}
+              onChange={onChange}
+            />
+          }
+        />
       )}
     </div>
   )

+ 10 - 10
web/app/components/datasets/common/retrieval-method-info/index.tsx

@@ -2,11 +2,12 @@
 import type { FC } from 'react'
 import React from 'react'
 import { useTranslation } from 'react-i18next'
-import Image from 'next/image'
-import { retrievalIcon } from '../../create/icons'
 import type { RetrievalConfig } from '@/types/app'
 import { RETRIEVE_METHOD } from '@/types/app'
 import RadioCard from '@/app/components/base/radio-card'
+import { HighPriority } from '@/app/components/base/icons/src/vender/solid/arrows'
+import { PatternRecognition, Semantic } from '@/app/components/base/icons/src/vender/solid/development'
+import { FileSearch02 } from '@/app/components/base/icons/src/vender/solid/files'
 
 type Props = {
   value: RetrievalConfig
@@ -14,12 +15,11 @@ type Props = {
 
 export const getIcon = (type: RETRIEVE_METHOD) => {
   return ({
-    [RETRIEVE_METHOD.semantic]: retrievalIcon.vector,
-    [RETRIEVE_METHOD.fullText]: retrievalIcon.fullText,
-    [RETRIEVE_METHOD.hybrid]: retrievalIcon.hybrid,
-    [RETRIEVE_METHOD.invertedIndex]: retrievalIcon.vector,
-    [RETRIEVE_METHOD.keywordSearch]: retrievalIcon.vector,
-  })[type] || retrievalIcon.vector
+    [RETRIEVE_METHOD.semantic]: Semantic,
+    [RETRIEVE_METHOD.fullText]: FileSearch02,
+    [RETRIEVE_METHOD.hybrid]: PatternRecognition,
+    [RETRIEVE_METHOD.invertedIndex]: HighPriority,
+  })[type] || FileSearch02
 }
 
 const EconomicalRetrievalMethodConfig: FC<Props> = ({
@@ -28,11 +28,11 @@ const EconomicalRetrievalMethodConfig: FC<Props> = ({
 }) => {
   const { t } = useTranslation()
   const type = value.search_method
-  const icon = <Image className='size-3.5 text-util-colors-purple-purple-600' src={getIcon(type)} alt='' />
+  const Icon = getIcon(type)
   return (
     <div className='space-y-2'>
       <RadioCard
-        icon={icon}
+        icon={<Icon className='w-4 h-4 text-[#7839EE]' />}
         title={t(`dataset.retrieval.${type}.title`)}
         description={t(`dataset.retrieval.${type}.description`)}
         noRadio

+ 18 - 20
web/app/components/datasets/common/retrieval-param-config/index.tsx

@@ -3,9 +3,6 @@ import type { FC } from 'react'
 import React, { useCallback } from 'react'
 import { useTranslation } from 'react-i18next'
 
-import Image from 'next/image'
-import ProgressIndicator from '../../create/assets/progress-indicator.svg'
-import Reranking from '../../create/assets/rerank.svg'
 import cn from '@/utils/classnames'
 import TopKItem from '@/app/components/base/param-item/top-k-item'
 import ScoreThresholdItem from '@/app/components/base/param-item/score-threshold-item'
@@ -23,7 +20,6 @@ import {
 } from '@/models/datasets'
 import WeightedScore from '@/app/components/app/configuration/dataset-config/params-config/weighted-score'
 import Toast from '@/app/components/base/toast'
-import RadioCard from '@/app/components/base/radio-card'
 
 type Props = {
   type: RETRIEVE_METHOD
@@ -120,7 +116,7 @@ const RetrievalParamConfig: FC<Props> = ({
     <div>
       {!isEconomical && !isHybridSearch && (
         <div>
-          <div className='flex items-center space-x-2 mb-2'>
+          <div className='flex h-8 items-center text-[13px] font-medium text-gray-900 space-x-2'>
             {canToggleRerankModalEnable && (
               <div
                 className='flex items-center'
@@ -140,7 +136,7 @@ const RetrievalParamConfig: FC<Props> = ({
               </div>
             )}
             <div className='flex items-center'>
-              <span className='mr-0.5 system-sm-semibold text-text-secondary'>{t('common.modelProvider.rerankModel.key')}</span>
+              <span className='mr-0.5'>{t('common.modelProvider.rerankModel.key')}</span>
               <Tooltip
                 popupContent={
                   <div className="w-[200px]">{t('common.modelProvider.rerankModel.tip')}</div>
@@ -167,7 +163,7 @@ const RetrievalParamConfig: FC<Props> = ({
       )}
       {
         !isHybridSearch && (
-          <div className={cn(!isEconomical && 'mt-4', 'flex space-between space-x-4')}>
+          <div className={cn(!isEconomical && 'mt-4', 'flex space-between space-x-6')}>
             <TopKItem
               className='grow'
               value={value.top_k}
@@ -205,22 +201,24 @@ const RetrievalParamConfig: FC<Props> = ({
       {
         isHybridSearch && (
           <>
-            <div className='flex gap-2 mb-4'>
+            <div className='flex items-center justify-between'>
               {
                 rerankingModeOptions.map(option => (
-                  <RadioCard
+                  <div
                     key={option.value}
-                    isChosen={value.reranking_mode === option.value}
-                    onChosen={() => handleChangeRerankMode(option.value)}
-                    icon={<Image src={
-                      option.value === RerankingModeEnum.WeightedScore
-                        ? ProgressIndicator
-                        : Reranking
-                    } alt=''/>}
-                    title={option.label}
-                    description={option.tips}
-                    className='flex-1'
-                  />
+                    className={cn(
+                      'flex items-center justify-center mb-4 w-[calc((100%-8px)/2)] h-8 rounded-lg border border-components-option-card-option-border bg-components-option-card-option-bg cursor-pointer system-sm-medium text-text-secondary',
+                      value.reranking_mode === RerankingModeEnum.WeightedScore && option.value === RerankingModeEnum.WeightedScore && 'border-[1.5px] border-components-option-card-option-selected-border bg-components-option-card-option-selected-bg text-text-primary',
+                      value.reranking_mode !== RerankingModeEnum.WeightedScore && option.value !== RerankingModeEnum.WeightedScore && 'border-[1.5px] border-components-option-card-option-selected-border bg-components-option-card-option-selected-bg text-text-primary',
+                    )}
+                    onClick={() => handleChangeRerankMode(option.value)}
+                  >
+                    <div className='truncate'>{option.label}</div>
+                    <Tooltip
+                      popupContent={<div className='w-[200px]'>{option.tips}</div>}
+                      triggerClassName='ml-0.5 w-3.5 h-3.5'
+                    />
+                  </div>
                 ))
               }
             </div>

Різницю між файлами не показано, бо вона завелика
+ 0 - 6
web/app/components/datasets/create/assets/family-mod.svg


Різницю між файлами не показано, бо вона завелика
+ 0 - 5
web/app/components/datasets/create/assets/file-list-3-fill.svg


Різницю між файлами не показано, бо вона завелика
+ 0 - 4
web/app/components/datasets/create/assets/gold.svg


Різницю між файлами не показано, бо вона завелика
+ 0 - 5
web/app/components/datasets/create/assets/note-mod.svg


+ 0 - 12
web/app/components/datasets/create/assets/option-card-effect-blue.svg

@@ -1,12 +0,0 @@
-<svg width="220" height="220" viewBox="0 0 220 220" fill="none" xmlns="http://www.w3.org/2000/svg">
-<g id="Effect" opacity="0.8" filter="url(#filter0_f_1328_28605)">
-<circle cx="32" cy="32" r="28" fill="#444CE7"/>
-</g>
-<defs>
-<filter id="filter0_f_1328_28605" x="-156" y="-156" width="376" height="376" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
-<feFlood flood-opacity="0" result="BackgroundImageFix"/>
-<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
-<feGaussianBlur stdDeviation="80" result="effect1_foregroundBlur_1328_28605"/>
-</filter>
-</defs>
-</svg>

+ 0 - 12
web/app/components/datasets/create/assets/option-card-effect-orange.svg

@@ -1,12 +0,0 @@
-<svg width="220" height="220" viewBox="0 0 220 220" fill="none" xmlns="http://www.w3.org/2000/svg">
-<g id="Effect" opacity="0.8" filter="url(#filter0_f_481_16338)">
-<circle cx="32" cy="32" r="28" fill="#EF6820"/>
-</g>
-<defs>
-<filter id="filter0_f_481_16338" x="-156" y="-156" width="376" height="376" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
-<feFlood flood-opacity="0" result="BackgroundImageFix"/>
-<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
-<feGaussianBlur stdDeviation="80" result="effect1_foregroundBlur_481_16338"/>
-</filter>
-</defs>
-</svg>

+ 0 - 12
web/app/components/datasets/create/assets/option-card-effect-purple.svg

@@ -1,12 +0,0 @@
-<svg width="220" height="220" viewBox="0 0 220 220" fill="none" xmlns="http://www.w3.org/2000/svg">
-<g id="Effect" opacity="0.8" filter="url(#filter0_f_481_16453)">
-<circle cx="32" cy="32" r="28" fill="#6938EF"/>
-</g>
-<defs>
-<filter id="filter0_f_481_16453" x="-156" y="-156" width="376" height="376" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
-<feFlood flood-opacity="0" result="BackgroundImageFix"/>
-<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
-<feGaussianBlur stdDeviation="80" result="effect1_foregroundBlur_481_16453"/>
-</filter>
-</defs>
-</svg>

Різницю між файлами не показано, бо вона завелика
+ 0 - 12
web/app/components/datasets/create/assets/pattern-recognition-mod.svg


Різницю між файлами не показано, бо вона завелика
+ 0 - 7
web/app/components/datasets/create/assets/piggy-bank-mod.svg


+ 0 - 8
web/app/components/datasets/create/assets/progress-indicator.svg

@@ -1,8 +0,0 @@
-<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
-<g id="progress-indicator">
-<g id="Vector">
-<path d="M18.4029 10.7639H1.59738C1.17572 10.7639 0.833496 11.1061 0.833496 11.5278V16.1111C0.833496 16.5328 1.17572 16.875 1.59738 16.875H18.4029C18.8246 16.875 19.1668 16.5328 19.1668 16.1111V11.5278C19.1668 11.1061 18.8246 10.7639 18.4029 10.7639ZM17.6391 15.3472H10.0002V12.2917H17.6391V15.3472Z" fill="#1570EF"/>
-<path d="M9.716 7.58153C9.78933 7.66174 9.89169 7.70833 10.0002 7.70833C10.1086 7.70833 10.211 7.6625 10.2843 7.58153L13.7218 3.76208C13.8227 3.64979 13.8479 3.48937 13.7868 3.35111C13.7249 3.21361 13.5881 3.125 13.4377 3.125H6.56266C6.41218 3.125 6.27544 3.21361 6.21356 3.35111C6.15245 3.48937 6.17766 3.64979 6.2785 3.76208L9.716 7.58153Z" fill="#1570EF"/>
-</g>
-</g>
-</svg>

+ 0 - 13
web/app/components/datasets/create/assets/rerank.svg

@@ -1,13 +0,0 @@
-<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
-<g id="rerank">
-<g id="Vector">
-<path d="M18.3333 4.58329C18.3333 5.73389 17.4005 6.66663 16.2499 6.66663C15.0993 6.66663 14.1666 5.73389 14.1666 4.58329C14.1666 3.4327 15.0993 2.49996 16.2499 2.49996C17.4005 2.49996 18.3333 3.4327 18.3333 4.58329Z" fill="#0E9384"/>
-<path d="M13.3333 15.4166C13.3333 16.5672 12.4005 17.5 11.2499 17.5C10.0993 17.5 9.16658 16.5672 9.16658 15.4166C9.16658 14.266 10.0993 13.3333 11.2499 13.3333C12.4005 13.3333 13.3333 14.266 13.3333 15.4166Z" fill="#0E9384"/>
-<path d="M12.0833 4.58329C12.0833 5.27365 11.5236 5.83329 10.8333 5.83329C10.1429 5.83329 9.58325 5.27365 9.58325 4.58329C9.58325 3.89294 10.1429 3.33329 10.8333 3.33329C11.5236 3.33329 12.0833 3.89294 12.0833 4.58329Z" fill="#0E9384"/>
-<path d="M17.4999 15.4166C17.4999 16.107 16.9403 16.6666 16.2499 16.6666C15.5596 16.6666 14.9999 16.107 14.9999 15.4166C14.9999 14.7263 15.5596 14.1666 16.2499 14.1666C16.9403 14.1666 17.4999 14.7263 17.4999 15.4166Z" fill="#0E9384"/>
-<path d="M7.49992 15.4166C7.49992 17.0275 6.19408 18.3333 4.58325 18.3333C2.97242 18.3333 1.66659 17.0275 1.66659 15.4166C1.66659 13.8058 2.97242 12.5 4.58325 12.5C6.19408 12.5 7.49992 13.8058 7.49992 15.4166Z" fill="#0E9384"/>
-<path d="M7.49992 4.58329C7.49992 6.19412 6.19408 7.49996 4.58325 7.49996C2.97242 7.49996 1.66659 6.19412 1.66659 4.58329C1.66659 2.97246 2.97242 1.66663 4.58325 1.66663C6.19408 1.66663 7.49992 2.97246 7.49992 4.58329Z" fill="#0E9384"/>
-<path d="M0.833252 9.99996C0.833252 9.53972 1.20635 9.16663 1.66659 9.16663H18.3333C18.7935 9.16663 19.1666 9.53972 19.1666 9.99996C19.1666 10.4602 18.7935 10.8333 18.3333 10.8333H1.66659C1.20635 10.8333 0.833252 10.4602 0.833252 9.99996Z" fill="#0E9384"/>
-</g>
-</g>
-</svg>

Різницю між файлами не показано, бо вона завелика
+ 0 - 6
web/app/components/datasets/create/assets/research-mod.svg


+ 0 - 12
web/app/components/datasets/create/assets/selection-mod.svg

@@ -1,12 +0,0 @@
-<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
-    <path d="M5.83317 18.3334H1.6665V14.1667H5.83317V18.3334Z" fill="#6938EF"/>
-    <path d="M12.0832 12.0834H7.9165V7.91669H12.0832V12.0834Z" fill="#6938EF"/>
-    <path d="M5.83317 12.0834H1.6665V7.91669H5.83317V12.0834Z" fill="#6938EF"/>
-    <path d="M12.0832 5.83335H7.9165V1.66669H12.0832V5.83335Z" fill="#6938EF"/>
-    <path d="M5.83317 5.83335H1.6665V1.66669H5.83317V5.83335Z" fill="#6938EF"/>
-    <path d="M18.3332 5.83335H14.1665V1.66669H18.3332V5.83335Z" fill="#6938EF"/>
-    <path d="M17.6386 14.8611H14.8608V17.6389H17.6386V14.8611Z" fill="#6938EF"/>
-    <path d="M17.6386 8.61115H14.8608V11.3889H17.6386V8.61115Z" fill="#6938EF"/>
-    <path d="M11.3886 14.8611H8.61084V17.6389H11.3886V14.8611Z" fill="#6938EF"/>
-    </svg>
-    

Різницю між файлами не показано, бо вона завелика
+ 0 - 4
web/app/components/datasets/create/assets/setting-gear-mod.svg


+ 39 - 13
web/app/components/datasets/create/embedding-process/index.module.css

@@ -14,7 +14,24 @@
   border-radius: 6px;
   overflow: hidden;
 }
-
+.sourceItem.error {
+  background: #FEE4E2;
+}
+.sourceItem.success {
+  background: #D1FADF;
+}
+.progressbar {
+  position: absolute;
+  top: 0;
+  left: 0;
+  height: 100%;
+  background-color: #B2CCFF;
+}
+.sourceItem .info {
+  display: flex;
+  align-items: center;
+  z-index: 1;
+}
 .sourceItem .info .name {
   font-weight: 500;
   font-size: 12px;
@@ -38,6 +55,13 @@
   color: #05603A;
 }
 
+
+.cost {
+  @apply flex justify-between items-center text-xs text-gray-700;
+}
+.embeddingStatus {
+  @apply flex items-center justify-between text-gray-900 font-medium text-sm mr-2;
+}
 .commonIcon {
   @apply w-3 h-3 mr-1 inline-block align-middle;
 }
@@ -57,33 +81,35 @@
   @apply text-xs font-medium;
 }
 
-.unknownFileIcon {
+.fileIcon {
+  @apply w-4 h-4 mr-1 bg-center bg-no-repeat;
   background-image: url(../assets/unknown.svg);
+  background-size: 16px;
 }
-.csv {
+.fileIcon.csv {
   background-image: url(../assets/csv.svg);
 }
-.docx {
+.fileIcon.docx {
   background-image: url(../assets/docx.svg);
 }
-.xlsx,
-.xls {
+.fileIcon.xlsx,
+.fileIcon.xls {
   background-image: url(../assets/xlsx.svg);
 }
-.pdf {
+.fileIcon.pdf {
   background-image: url(../assets/pdf.svg);
 }
-.html,
-.htm {
+.fileIcon.html,
+.fileIcon.htm {
   background-image: url(../assets/html.svg);
 }
-.md,
-.markdown {
+.fileIcon.md,
+.fileIcon.markdown {
   background-image: url(../assets/md.svg);
 }
-.txt {
+.fileIcon.txt {
   background-image: url(../assets/txt.svg);
 }
-.json {
+.fileIcon.json {
   background-image: url(../assets/json.svg);
 }

+ 55 - 137
web/app/components/datasets/create/embedding-process/index.tsx

@@ -6,44 +6,32 @@ import { useTranslation } from 'react-i18next'
 import { omit } from 'lodash-es'
 import { ArrowRightIcon } from '@heroicons/react/24/solid'
 import {
-  RiCheckboxCircleFill,
   RiErrorWarningFill,
-  RiLoader2Fill,
-  RiTerminalBoxLine,
 } from '@remixicon/react'
-import Image from 'next/image'
-import { indexMethodIcon, retrievalIcon } from '../icons'
-import { IndexingType } from '../step-two'
-import DocumentFileIcon from '../../common/document-file-icon'
+import s from './index.module.css'
 import cn from '@/utils/classnames'
 import { FieldInfo } from '@/app/components/datasets/documents/detail/metadata'
 import Button from '@/app/components/base/button'
 import type { FullDocumentDetail, IndexingStatusResponse, ProcessRuleResponse } from '@/models/datasets'
 import { fetchIndexingStatusBatch as doFetchIndexingStatus, fetchProcessRule } from '@/service/datasets'
-import { DataSourceType, ProcessMode } from '@/models/datasets'
+import { DataSourceType } from '@/models/datasets'
 import NotionIcon from '@/app/components/base/notion-icon'
 import PriorityLabel from '@/app/components/billing/priority-label'
 import { Plan } from '@/app/components/billing/type'
 import { ZapFast } from '@/app/components/base/icons/src/vender/solid/general'
 import UpgradeBtn from '@/app/components/billing/upgrade-btn'
 import { useProviderContext } from '@/context/provider-context'
-import { sleep } from '@/utils'
-import { RETRIEVE_METHOD } from '@/types/app'
 import Tooltip from '@/app/components/base/tooltip'
+import { sleep } from '@/utils'
 
 type Props = {
   datasetId: string
   batchId: string
   documents?: FullDocumentDetail[]
   indexingType?: string
-  retrievalMethod?: string
 }
 
-const RuleDetail: FC<{
-  sourceData?: ProcessRuleResponse
-  indexingType?: string
-  retrievalMethod?: string
-}> = ({ sourceData, indexingType, retrievalMethod }) => {
+const RuleDetail: FC<{ sourceData?: ProcessRuleResponse }> = ({ sourceData }) => {
   const { t } = useTranslation()
 
   const segmentationRuleMap = {
@@ -63,47 +51,29 @@ const RuleDetail: FC<{
       return t('datasetCreation.stepTwo.removeStopwords')
   }
 
-  const isNumber = (value: unknown) => {
-    return typeof value === 'number'
-  }
-
   const getValue = useCallback((field: string) => {
     let value: string | number | undefined = '-'
-    const maxTokens = isNumber(sourceData?.rules?.segmentation?.max_tokens)
-      ? sourceData.rules.segmentation.max_tokens
-      : value
-    const childMaxTokens = isNumber(sourceData?.rules?.subchunk_segmentation?.max_tokens)
-      ? sourceData.rules.subchunk_segmentation.max_tokens
-      : value
     switch (field) {
       case 'mode':
-        value = !sourceData?.mode
-          ? value
-          : sourceData.mode === ProcessMode.general
-            ? (t('datasetDocuments.embedding.custom') as string)
-            : `${t('datasetDocuments.embedding.hierarchical')} · ${sourceData?.rules?.parent_mode === 'paragraph'
-              ? t('dataset.parentMode.paragraph')
-              : t('dataset.parentMode.fullDoc')}`
+        value = sourceData?.mode === 'automatic' ? (t('datasetDocuments.embedding.automatic') as string) : (t('datasetDocuments.embedding.custom') as string)
         break
       case 'segmentLength':
-        value = !sourceData?.mode
-          ? value
-          : sourceData.mode === ProcessMode.general
-            ? maxTokens
-            : `${t('datasetDocuments.embedding.parentMaxTokens')} ${maxTokens}; ${t('datasetDocuments.embedding.childMaxTokens')} ${childMaxTokens}`
+        value = sourceData?.rules?.segmentation?.max_tokens
         break
       default:
-        value = !sourceData?.mode
-          ? value
-          : sourceData?.rules?.pre_processing_rules?.filter(rule =>
-            rule.enabled).map(rule => getRuleName(rule.id)).join(',')
+        value = sourceData?.mode === 'automatic'
+          ? (t('datasetDocuments.embedding.automatic') as string)
+          // eslint-disable-next-line array-callback-return
+          : sourceData?.rules?.pre_processing_rules?.map((rule) => {
+            if (rule.enabled)
+              return getRuleName(rule.id)
+          }).filter(Boolean).join(';')
         break
     }
     return value
-    // eslint-disable-next-line react-hooks/exhaustive-deps
   }, [sourceData])
 
-  return <div className='flex flex-col gap-1'>
+  return <div className='flex flex-col pt-8 pb-10 first:mt-0'>
     {Object.keys(segmentationRuleMap).map((field) => {
       return <FieldInfo
         key={field}
@@ -111,43 +81,10 @@ const RuleDetail: FC<{
         displayedValue={String(getValue(field))}
       />
     })}
-    <FieldInfo
-      label={t('datasetCreation.stepTwo.indexMode')}
-      displayedValue={t(`datasetCreation.stepTwo.${indexingType === IndexingType.ECONOMICAL ? 'economical' : 'qualified'}`) as string}
-      valueIcon={
-        <Image
-          className='size-4'
-          src={
-            indexingType === IndexingType.ECONOMICAL
-              ? indexMethodIcon.economical
-              : indexMethodIcon.high_quality
-          }
-          alt=''
-        />
-      }
-    />
-    <FieldInfo
-      label={t('datasetSettings.form.retrievalSetting.title')}
-      // displayedValue={t(`datasetSettings.form.retrievalSetting.${retrievalMethod}`) as string}
-      displayedValue={t(`dataset.retrieval.${indexingType === IndexingType.ECONOMICAL ? 'invertedIndex' : retrievalMethod}.title`) as string}
-      valueIcon={
-        <Image
-          className='size-4'
-          src={
-            retrievalMethod === RETRIEVE_METHOD.fullText
-              ? retrievalIcon.fullText
-              : retrievalMethod === RETRIEVE_METHOD.hybrid
-                ? retrievalIcon.hybrid
-                : retrievalIcon.vector
-          }
-          alt=''
-        />
-      }
-    />
   </div>
 }
 
-const EmbeddingProcess: FC<Props> = ({ datasetId, batchId, documents = [], indexingType, retrievalMethod }) => {
+const EmbeddingProcess: FC<Props> = ({ datasetId, batchId, documents = [], indexingType }) => {
   const { t } = useTranslation()
   const { enableBilling, plan } = useProviderContext()
 
@@ -190,7 +127,6 @@ const EmbeddingProcess: FC<Props> = ({ datasetId, batchId, documents = [], index
   }
 
   useEffect(() => {
-    setIsStopQuery(false)
     startQueryStatus()
     return () => {
       stopQueryStatus()
@@ -210,9 +146,6 @@ const EmbeddingProcess: FC<Props> = ({ datasetId, batchId, documents = [], index
   const navToDocumentList = () => {
     router.push(`/datasets/${datasetId}/documents`)
   }
-  const navToApiDocs = () => {
-    router.push('/datasets?category=api')
-  }
 
   const isEmbedding = useMemo(() => {
     return indexingStatusBatchDetail.some(indexingStatusDetail => ['indexing', 'splitting', 'parsing', 'cleaning'].includes(indexingStatusDetail?.indexing_status || ''))
@@ -244,17 +177,13 @@ const EmbeddingProcess: FC<Props> = ({ datasetId, batchId, documents = [], index
 
     return doc?.data_source_info.notion_page_icon
   }
-  const isSourceEmbedding = (detail: IndexingStatusResponse) =>
-    ['indexing', 'splitting', 'parsing', 'cleaning', 'waiting'].includes(detail.indexing_status || '')
+  const isSourceEmbedding = (detail: IndexingStatusResponse) => ['indexing', 'splitting', 'parsing', 'cleaning', 'waiting'].includes(detail.indexing_status || '')
 
   return (
     <>
-      <div className="h-5 flex items-center mb-3">
-        <div className="flex items-center justify-between text-gray-900 font-medium text-sm mr-2">
-          {isEmbedding && <div className='flex items-center'>
-            <RiLoader2Fill className='size-4 mr-1 animate-spin' />
-            {t('datasetDocuments.embedding.processing')}
-          </div>}
+      <div className='h-5 flex items-center mb-5'>
+        <div className={s.embeddingStatus}>
+          {isEmbedding && t('datasetDocuments.embedding.processing')}
           {isEmbeddingCompleted && t('datasetDocuments.embedding.completed')}
         </div>
       </div>
@@ -271,80 +200,69 @@ const EmbeddingProcess: FC<Props> = ({ datasetId, batchId, documents = [], index
           </div>
         )
       }
-      <div className="flex flex-col gap-0.5 pb-2">
+      <div className={s.progressContainer}>
         {indexingStatusBatchDetail.map(indexingStatusDetail => (
           <div key={indexingStatusDetail.id} className={cn(
-            'relative h-[26px] bg-components-progress-bar-bg rounded-md overflow-hidden',
-            indexingStatusDetail.indexing_status === 'error' && 'bg-state-destructive-hover-alt',
-            // indexingStatusDetail.indexing_status === 'completed' && 's.success',
+            s.sourceItem,
+            indexingStatusDetail.indexing_status === 'error' && s.error,
+            indexingStatusDetail.indexing_status === 'completed' && s.success,
           )}>
             {isSourceEmbedding(indexingStatusDetail) && (
-              <div className="absolute top-0 left-0 h-full min-w-0.5 bg-components-progress-bar-progress border-r-[2px] border-r-components-progress-bar-progress-highlight" style={{ width: `${getSourcePercent(indexingStatusDetail)}%` }} />
+              <div className={s.progressbar} style={{ width: `${getSourcePercent(indexingStatusDetail)}%` }} />
             )}
-            <div className="flex gap-1 pl-[6px] pr-2 h-full items-center z-[1]">
+            <div className={`${s.info} grow`}>
               {getSourceType(indexingStatusDetail.id) === DataSourceType.FILE && (
-                // <div className={cn(
-                //   'shrink-0 marker:size-4 bg-center bg-no-repeat bg-contain',
-                //   s[getFileType(getSourceName(indexingStatusDetail.id))] || s.unknownFileIcon,
-                // )} />
-                <DocumentFileIcon
-                  className="shrink-0 size-4"
-                  name={getSourceName(indexingStatusDetail.id)}
-                  extension={getFileType(getSourceName(indexingStatusDetail.id))}
-                />
+                <div className={cn(s.fileIcon, s[getFileType(getSourceName(indexingStatusDetail.id))])} />
               )}
               {getSourceType(indexingStatusDetail.id) === DataSourceType.NOTION && (
                 <NotionIcon
-                  className='shrink-0'
+                  className='shrink-0 mr-1'
                   type='page'
                   src={getIcon(indexingStatusDetail.id)}
                 />
               )}
-              <div className="grow flex items-center gap-1 w-0" title={getSourceName(indexingStatusDetail.id)}>
-                <div className="text-xs truncate">
-                  {getSourceName(indexingStatusDetail.id)}
-                </div>
-                {
-                  enableBilling && (
-                    <PriorityLabel className='ml-0' />
-                  )
-                }
-              </div>
+              <div className={`${s.name} truncate`} title={getSourceName(indexingStatusDetail.id)}>{getSourceName(indexingStatusDetail.id)}</div>
+              {
+                enableBilling && (
+                  <PriorityLabel />
+                )
+              }
+            </div>
+            <div className='shrink-0'>
               {isSourceEmbedding(indexingStatusDetail) && (
-                <div className="shrink-0 text-xs">{`${getSourcePercent(indexingStatusDetail)}%`}</div>
+                <div className={s.percent}>{`${getSourcePercent(indexingStatusDetail)}%`}</div>
               )}
-              {indexingStatusDetail.indexing_status === 'error' && (
+              {indexingStatusDetail.indexing_status === 'error' && indexingStatusDetail.error && (
                 <Tooltip
-                  popupClassName='px-4 py-[14px] max-w-60 text-sm leading-4 text-text-secondary border-[0.5px] border-components-panel-border rounded-xl'
-                  offset={4}
-                  popupContent={indexingStatusDetail.error}
+                  popupContent={(
+                    <div className='max-w-[400px]'>
+                      {indexingStatusDetail.error}
+                    </div>
+                  )}
                 >
-                  <span>
-                    <RiErrorWarningFill className='shrink-0 size-4 text-text-destructive' />
-                  </span>
+                  <div className={cn(s.percent, s.error, 'flex items-center')}>
+                    Error
+                    <RiErrorWarningFill className='ml-1 w-4 h-4' />
+                  </div>
                 </Tooltip>
               )}
+              {indexingStatusDetail.indexing_status === 'error' && !indexingStatusDetail.error && (
+                <div className={cn(s.percent, s.error, 'flex items-center')}>
+                  Error
+                </div>
+              )}
               {indexingStatusDetail.indexing_status === 'completed' && (
-                <RiCheckboxCircleFill className='shrink-0 size-4 text-text-success' />
+                <div className={cn(s.percent, s.success)}>100%</div>
               )}
             </div>
           </div>
         ))}
       </div>
-      <hr className="my-3 h-[1px] bg-divider-subtle border-0" />
-      <RuleDetail
-        sourceData={ruleDetail}
-        indexingType={indexingType}
-        retrievalMethod={retrievalMethod}
-      />
-      <div className='flex items-center gap-2 my-10'>
-        <Button className='w-fit' onClick={navToApiDocs}>
-          <RiTerminalBoxLine className='size-4 mr-2' />
-          <span>Access the API</span>
-        </Button>
+      <RuleDetail sourceData={ruleDetail} />
+      <div className='flex items-center gap-2 mt-10'>
         <Button className='w-fit' variant='primary' onClick={navToDocumentList}>
           <span>{t('datasetCreation.stepThree.navTo')}</span>
-          <ArrowRightIcon className='size-4 ml-2 stroke-current stroke-1' />
+          <ArrowRightIcon className='h-4 w-4 ml-2 stroke-current stroke-1' />
         </Button>
       </div>
     </>

+ 1 - 2
web/app/components/datasets/create/file-preview/index.module.css

@@ -1,6 +1,6 @@
 .filePreview {
     @apply flex flex-col border-l border-gray-200 shrink-0;
-    width: 100%;
+    width: 528px;
     background-color: #fcfcfd;
   }
   
@@ -48,6 +48,5 @@
   }
   .fileContent {
     white-space: pre-line;
-    word-break: break-all;
   }
   

+ 2 - 2
web/app/components/datasets/create/file-preview/index.tsx

@@ -44,7 +44,7 @@ const FilePreview = ({
   }, [file])
 
   return (
-    <div className={cn(s.filePreview, 'h-full')}>
+    <div className={cn(s.filePreview)}>
       <div className={cn(s.previewHeader)}>
         <div className={cn(s.title)}>
           <span>{t('datasetCreation.stepOne.filePreview')}</span>
@@ -59,7 +59,7 @@ const FilePreview = ({
       <div className={cn(s.previewContent)}>
         {loading && <div className={cn(s.loading)} />}
         {!loading && (
-          <div className={cn(s.fileContent, 'body-md-regular')}>{previewContent}</div>
+          <div className={cn(s.fileContent)}>{previewContent}</div>
         )}
       </div>
     </div>

+ 66 - 1
web/app/components/datasets/create/file-uploader/index.module.css

@@ -1,3 +1,68 @@
+.fileUploader {
+  @apply mb-6;
+}
+
+.fileUploader .title {
+  @apply mb-2;
+  font-weight: 500;
+  font-size: 16px;
+  line-height: 24px;
+  color: #344054;
+}
+
+.fileUploader .tip {
+  font-weight: 400;
+  font-size: 12px;
+  line-height: 18px;
+  color: #667085;
+}
+
+.uploader {
+  @apply relative box-border flex justify-center items-center mb-2 p-3;
+  flex-direction: column;
+  max-width: 640px;
+  min-height: 80px;
+  background: #F9FAFB;
+  border: 1px dashed #EAECF0;
+  border-radius: 12px;
+  font-weight: 400;
+  font-size: 14px;
+  line-height: 20px;
+  color: #667085;
+}
+
+.uploader.dragging {
+  background: #F5F8FF;
+  border: 1px dashed #B2CCFF;
+}
+
+.uploader .draggingCover {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+}
+
+.uploader .uploadIcon {
+  content: '';
+  display: block;
+  margin-right: 8px;
+  width: 24px;
+  height: 24px;
+  background: center no-repeat url(../assets/upload-cloud-01.svg);
+  background-size: contain;
+}
+
+.uploader .browse {
+  @apply pl-1 cursor-pointer;
+  color: #155eef;
+}
+
+.fileList {
+  @apply space-y-2;
+}
+
 .file {
   @apply box-border relative flex items-center justify-between;
   padding: 8px 12px 8px 8px;
@@ -128,4 +193,4 @@
 
 .file:hover .actionWrapper .remove {
   display: block;
-}
+}

+ 28 - 54
web/app/components/datasets/create/file-uploader/index.tsx

@@ -3,12 +3,10 @@ import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
 import { useTranslation } from 'react-i18next'
 import { useContext } from 'use-context-selector'
 import useSWR from 'swr'
-import { RiDeleteBinLine, RiUploadCloud2Line } from '@remixicon/react'
-import DocumentFileIcon from '../../common/document-file-icon'
+import s from './index.module.css'
 import cn from '@/utils/classnames'
 import type { CustomFile as File, FileItem } from '@/models/datasets'
 import { ToastContext } from '@/app/components/base/toast'
-import SimplePieChart from '@/app/components/base/simple-pie-chart'
 
 import { upload } from '@/service/base'
 import { fetchFileUploadConfig } from '@/service/common'
@@ -16,8 +14,6 @@ import { fetchSupportFileTypes } from '@/service/datasets'
 import I18n from '@/context/i18n'
 import { LanguagesSupported } from '@/i18n/language'
 import { IS_CE_EDITION } from '@/config'
-import { useAppContext } from '@/context/app-context'
-import { Theme } from '@/types/app'
 
 const FILES_NUMBER_LIMIT = 20
 
@@ -226,9 +222,6 @@ const FileUploader = ({
     initialUpload(files.filter(isValid))
   }, [isValid, initialUpload])
 
-  const { theme } = useAppContext()
-  const chartColor = useMemo(() => theme === Theme.dark ? '#5289ff' : '#296dff', [theme])
-
   useEffect(() => {
     dropRef.current?.addEventListener('dragenter', handleDragEnter)
     dropRef.current?.addEventListener('dragover', handleDragOver)
@@ -243,12 +236,12 @@ const FileUploader = ({
   }, [handleDrop])
 
   return (
-    <div className="mb-5 w-[640px]">
+    <div className={s.fileUploader}>
       {!hideUpload && (
         <input
           ref={fileUploader}
           id="fileUploader"
-          className="hidden"
+          style={{ display: 'none' }}
           type="file"
           multiple={!notSupportBatchUpload}
           accept={ACCEPTS.join(',')}
@@ -256,71 +249,52 @@ const FileUploader = ({
         />
       )}
 
-      <div className={cn('text-text-tertiary text-sm font-semibold leading-6 mb-1', titleClassName)}>{t('datasetCreation.stepOne.uploader.title')}</div>
-
+      <div className={cn(s.title, titleClassName)}>{t('datasetCreation.stepOne.uploader.title')}</div>
       {!hideUpload && (
-        <div ref={dropRef} className={cn('relative box-border flex flex-col justify-center items-center gap-1 mb-2 px-4 py-3 max-w-[640px] min-h-20 leading-4 text-xs text-text-tertiary bg-components-dropzone-bg border border-dashed border-components-dropzone-border rounded-xl', dragging && 'bg-components-dropzone-bg-accent border-components-dropzone-border-accent')}>
-          <div className="flex justify-center items-center min-h-5 text-sm leading-4 text-text-secondary">
-            <RiUploadCloud2Line className='mr-2 size-5' />
 
+        <div ref={dropRef} className={cn(s.uploader, dragging && s.dragging)}>
+          <div className='flex justify-center items-center min-h-6 mb-2'>
+            <span className={s.uploadIcon} />
             <span>
               {t('datasetCreation.stepOne.uploader.button')}
-              {supportTypes.length > 0 && (
-                <label className="ml-1 text-text-accent cursor-pointer" onClick={selectHandle}>{t('datasetCreation.stepOne.uploader.browse')}</label>
-              )}
+              <label className={s.browse} onClick={selectHandle}>{t('datasetCreation.stepOne.uploader.browse')}</label>
             </span>
           </div>
-          <div>{t('datasetCreation.stepOne.uploader.tip', {
+          <div className={s.tip}>{t('datasetCreation.stepOne.uploader.tip', {
             size: fileUploadConfig.file_size_limit,
             supportTypes: supportTypesShowNames,
           })}</div>
-          {dragging && <div ref={dragRef} className='absolute top-0 left-0 w-full h-full' />}
+          {dragging && <div ref={dragRef} className={s.draggingCover} />}
         </div>
       )}
-      <div className='space-y-1 max-w-[640px] cursor-default'>
-
+      <div className={s.fileList}>
         {fileList.map((fileItem, index) => (
           <div
             key={`${fileItem.fileID}-${index}`}
             onClick={() => fileItem.file?.id && onPreview(fileItem.file)}
             className={cn(
-              'flex items-center h-12 max-w-[640px] bg-components-panel-on-panel-item-bg text-xs leading-3 text-text-tertiary border border-components-panel-border rounded-lg shadow-xs',
-              // 'border-state-destructive-border bg-state-destructive-hover',
+              s.file,
+              fileItem.progress < 100 && s.uploading,
             )}
           >
-            <div className="shrink-0 flex justify-center items-center w-12">
-              <DocumentFileIcon
-                className="shrink-0 size-6"
-                name={fileItem.file.name}
-                extension={getFileType(fileItem.file)}
-              />
-            </div>
-            <div className="grow shrink flex flex-col gap-0.5">
-              <div className='flex w-full'>
-                <div className="text-sm leading-4 text-text-secondary w-0 grow truncate">{fileItem.file.name}</div>
-              </div>
-              <div className="w-full leading-3 truncate text-text-tertiary">
-                <span className='uppercase'>{getFileType(fileItem.file)}</span>
-                <span className='px-1 text-text-quaternary'>·</span>
-                <span>{getFileSize(fileItem.file.size)}</span>
-                {/* <span className='px-1 text-text-quaternary'>·</span>
-                  <span>10k characters</span> */}
-              </div>
+            {fileItem.progress < 100 && (
+              <div className={s.progressbar} style={{ width: `${fileItem.progress}%` }} />
+            )}
+            <div className={s.fileInfo}>
+              <div className={cn(s.fileIcon, s[getFileType(fileItem.file)])} />
+              <div className={s.filename}>{fileItem.file.name}</div>
+              <div className={s.size}>{getFileSize(fileItem.file.size)}</div>
             </div>
-            <div className="shrink-0 flex items-center justify-end gap-1 pr-3 w-16">
-              {/* <span className="flex justify-center items-center w-6 h-6 cursor-pointer">
-                  <RiErrorWarningFill className='size-4 text-text-warning' />
-                </span> */}
+            <div className={s.actionWrapper}>
               {(fileItem.progress < 100 && fileItem.progress >= 0) && (
-                // <div className={s.percent}>{`${fileItem.progress}%`}</div>
-                <SimplePieChart percentage={fileItem.progress} stroke={chartColor} fill={chartColor} animationDuration={0} />
+                <div className={s.percent}>{`${fileItem.progress}%`}</div>
+              )}
+              {fileItem.progress === 100 && (
+                <div className={s.remove} onClick={(e) => {
+                  e.stopPropagation()
+                  removeFile(fileItem.fileID)
+                }} />
               )}
-              <span className="flex justify-center items-center w-6 h-6 cursor-pointer" onClick={(e) => {
-                e.stopPropagation()
-                removeFile(fileItem.fileID)
-              }}>
-                <RiDeleteBinLine className='size-4 text-text-tertiary' />
-              </span>
             </div>
           </div>
         ))}

+ 0 - 16
web/app/components/datasets/create/icons.ts

@@ -1,16 +0,0 @@
-import GoldIcon from './assets/gold.svg'
-import Piggybank from './assets/piggy-bank-mod.svg'
-import Selection from './assets/selection-mod.svg'
-import Research from './assets/research-mod.svg'
-import PatternRecognition from './assets/pattern-recognition-mod.svg'
-
-export const indexMethodIcon = {
-  high_quality: GoldIcon,
-  economical: Piggybank,
-}
-
-export const retrievalIcon = {
-  vector: Selection,
-  fullText: Research,
-  hybrid: PatternRecognition,
-}

+ 28 - 30
web/app/components/datasets/create/index.tsx

@@ -3,10 +3,10 @@ import React, { useCallback, useEffect, useState } from 'react'
 import { useTranslation } from 'react-i18next'
 import AppUnavailable from '../../base/app-unavailable'
 import { ModelTypeEnum } from '../../header/account-setting/model-provider-page/declarations'
+import StepsNavBar from './steps-nav-bar'
 import StepOne from './step-one'
 import StepTwo from './step-two'
 import StepThree from './step-three'
-import { Topbar } from './top-bar'
 import { DataSourceType } from '@/models/datasets'
 import type { CrawlOptions, CrawlResultItem, DataSet, FileItem, createDocumentResponse } from '@/models/datasets'
 import { fetchDataSource } from '@/service/common'
@@ -36,7 +36,6 @@ const DatasetUpdateForm = ({ datasetId }: DatasetUpdateFormProps) => {
   const [dataSourceType, setDataSourceType] = useState<DataSourceType>(DataSourceType.FILE)
   const [step, setStep] = useState(1)
   const [indexingTypeCache, setIndexTypeCache] = useState('')
-  const [retrievalMethodCache, setRetrievalMethodCache] = useState('')
   const [fileList, setFiles] = useState<FileItem[]>([])
   const [result, setResult] = useState<createDocumentResponse | undefined>()
   const [hasError, setHasError] = useState(false)
@@ -81,9 +80,6 @@ const DatasetUpdateForm = ({ datasetId }: DatasetUpdateFormProps) => {
   const updateResultCache = (res?: createDocumentResponse) => {
     setResult(res)
   }
-  const updateRetrievalMethodCache = (method: string) => {
-    setRetrievalMethodCache(method)
-  }
 
   const nextStep = useCallback(() => {
     setStep(step + 1)
@@ -122,29 +118,33 @@ const DatasetUpdateForm = ({ datasetId }: DatasetUpdateFormProps) => {
     return <AppUnavailable code={500} unknownReason={t('datasetCreation.error.unavailable') as string} />
 
   return (
-    <div className='flex flex-col bg-components-panel-bg' style={{ height: 'calc(100vh - 56px)' }}>
-      <Topbar activeIndex={step - 1} />
-      <div style={{ height: 'calc(100% - 52px)' }}>
-        {step === 1 && <StepOne
-          hasConnection={hasConnection}
-          onSetting={() => setShowAccountSettingModal({ payload: 'data-source' })}
-          datasetId={datasetId}
-          dataSourceType={dataSourceType}
-          dataSourceTypeDisable={!!detail?.data_source_type}
-          changeType={setDataSourceType}
-          files={fileList}
-          updateFile={updateFile}
-          updateFileList={updateFileList}
-          notionPages={notionPages}
-          updateNotionPages={updateNotionPages}
-          onStepChange={nextStep}
-          websitePages={websitePages}
-          updateWebsitePages={setWebsitePages}
-          onWebsiteCrawlProviderChange={setWebsiteCrawlProvider}
-          onWebsiteCrawlJobIdChange={setWebsiteCrawlJobId}
-          crawlOptions={crawlOptions}
-          onCrawlOptionsChange={setCrawlOptions}
-        />}
+    <div className='flex' style={{ height: 'calc(100vh - 56px)' }}>
+      <div className="flex flex-col w-11 sm:w-56 overflow-y-auto bg-white border-r border-gray-200 shrink-0">
+        <StepsNavBar step={step} datasetId={datasetId} />
+      </div>
+      <div className="grow bg-white">
+        <div className={step === 1 ? 'block h-full' : 'hidden'}>
+          <StepOne
+            hasConnection={hasConnection}
+            onSetting={() => setShowAccountSettingModal({ payload: 'data-source' })}
+            datasetId={datasetId}
+            dataSourceType={dataSourceType}
+            dataSourceTypeDisable={!!detail?.data_source_type}
+            changeType={setDataSourceType}
+            files={fileList}
+            updateFile={updateFile}
+            updateFileList={updateFileList}
+            notionPages={notionPages}
+            updateNotionPages={updateNotionPages}
+            onStepChange={nextStep}
+            websitePages={websitePages}
+            updateWebsitePages={setWebsitePages}
+            onWebsiteCrawlProviderChange={setWebsiteCrawlProvider}
+            onWebsiteCrawlJobIdChange={setWebsiteCrawlJobId}
+            crawlOptions={crawlOptions}
+            onCrawlOptionsChange={setCrawlOptions}
+          />
+        </div>
         {(step === 2 && (!datasetId || (datasetId && !!detail))) && <StepTwo
           isAPIKeySet={!!embeddingsDefaultModel}
           onSetting={() => setShowAccountSettingModal({ payload: 'provider' })}
@@ -158,7 +158,6 @@ const DatasetUpdateForm = ({ datasetId }: DatasetUpdateFormProps) => {
           websiteCrawlJobId={websiteCrawlJobId}
           onStepChange={changeStep}
           updateIndexingTypeCache={updateIndexingTypeCache}
-          updateRetrievalMethodCache={updateRetrievalMethodCache}
           updateResultCache={updateResultCache}
           crawlOptions={crawlOptions}
         />}
@@ -166,7 +165,6 @@ const DatasetUpdateForm = ({ datasetId }: DatasetUpdateFormProps) => {
           datasetId={datasetId}
           datasetName={detail?.name}
           indexingType={detail?.indexing_technique || indexingTypeCache}
-          retrievalMethod={detail?.retrieval_model_dict?.search_method || retrievalMethodCache}
           creationCache={result}
         />}
       </div>

+ 2 - 2
web/app/components/datasets/create/notion-page-preview/index.tsx

@@ -44,7 +44,7 @@ const NotionPagePreview = ({
   }, [currentPage])
 
   return (
-    <div className={cn(s.filePreview, 'h-full')}>
+    <div className={cn(s.filePreview)}>
       <div className={cn(s.previewHeader)}>
         <div className={cn(s.title)}>
           <span>{t('datasetCreation.stepOne.pagePreview')}</span>
@@ -64,7 +64,7 @@ const NotionPagePreview = ({
       <div className={cn(s.previewContent)}>
         {loading && <div className={cn(s.loading)} />}
         {!loading && (
-          <div className={cn(s.fileContent, 'body-md-regular')}>{previewContent}</div>
+          <div className={cn(s.fileContent)}>{previewContent}</div>
         )}
       </div>
     </div>

+ 23 - 15
web/app/components/datasets/create/step-one/index.module.css

@@ -2,19 +2,21 @@
   position: sticky;
   top: 0;
   left: 0;
-  padding: 42px 64px 12px 0;
+  padding: 42px 64px 12px;
   font-weight: 600;
   font-size: 18px;
   line-height: 28px;
+  color: #101828;
 }
 
 .form {
   position: relative;
   padding: 12px 64px;
+  background-color: #fff;
 }
 
 .dataSourceItem {
-  @apply box-border relative grow shrink-0 flex items-center p-3 h-14 bg-white rounded-xl cursor-pointer;
+  @apply box-border relative shrink-0 flex items-center mr-3 p-3 h-14 bg-white rounded-xl cursor-pointer;
   border: 0.5px solid #EAECF0;
   box-shadow: 0px 1px 2px rgba(16, 24, 40, 0.05);
   font-weight: 500;
@@ -22,32 +24,27 @@
   line-height: 20px;
   color: #101828;
 }
-
 .dataSourceItem:hover {
   background-color: #f5f8ff;
   border: 0.5px solid #B2CCFF;
   box-shadow: 0px 12px 16px -4px rgba(16, 24, 40, 0.08), 0px 4px 6px -2px rgba(16, 24, 40, 0.03);
 }
-
 .dataSourceItem.active {
   background-color: #f5f8ff;
   border: 1.5px solid #528BFF;
   box-shadow: 0px 1px 3px rgba(16, 24, 40, 0.1), 0px 1px 2px rgba(16, 24, 40, 0.06);
 }
-
 .dataSourceItem.disabled {
   background-color: #f9fafb;
   border: 0.5px solid #EAECF0;
   box-shadow: 0px 1px 2px rgba(16, 24, 40, 0.05);
   cursor: default;
 }
-
 .dataSourceItem.disabled:hover {
   background-color: #f9fafb;
   border: 0.5px solid #EAECF0;
   box-shadow: 0px 1px 2px rgba(16, 24, 40, 0.05);
 }
-
 .comingTag {
   @apply flex justify-center items-center bg-white;
   position: absolute;
@@ -62,7 +59,6 @@
   line-height: 18px;
   color: #444CE7;
 }
-
 .datasetIcon {
   @apply flex mr-2 w-8 h-8 rounded-lg bg-center bg-no-repeat;
   background-color: #F5FAFF;
@@ -70,18 +66,15 @@
   background-size: 16px;
   border: 0.5px solid #D1E9FF;
 }
-
 .dataSourceItem:active .datasetIcon,
 .dataSourceItem:hover .datasetIcon {
   background-color: #F5F8FF;
   border: 0.5px solid #E0EAFF;
 }
-
 .datasetIcon.notion {
   background-image: url(../assets/notion.svg);
   background-size: 20px;
 }
-
 .datasetIcon.web {
   background-image: url(../assets/web.svg);
 }
@@ -97,12 +90,29 @@
   background-color: #eaecf0;
 }
 
+.OtherCreationOption {
+  @apply flex items-center cursor-pointer;
+  font-weight: 500;
+  font-size: 13px;
+  line-height: 18px;
+  color: #155EEF;
+}
+.OtherCreationOption::before {
+  content: '';
+  display: block;
+  margin-right: 4px;
+  width: 16px;
+  height: 16px;
+  background: center no-repeat url(../assets/folder-plus.svg);
+  background-size: contain;
+}
+
 .notionConnectionTip {
   display: flex;
   flex-direction: column;
   align-items: flex-start;
   padding: 24px;
-  width: 640px;
+  max-width: 640px;
   background: #F9FAFB;
   border-radius: 16px;
 }
@@ -128,7 +138,6 @@
   line-height: 24px;
   color: #374151;
 }
-
 .notionConnectionTip .title::after {
   content: '';
   position: absolute;
@@ -139,7 +148,6 @@
   background: center no-repeat url(../assets/Icon-3-dots.svg);
   background-size: contain;
 }
-
 .notionConnectionTip .tip {
   margin-bottom: 20px;
   font-style: normal;
@@ -147,4 +155,4 @@
   font-size: 13px;
   line-height: 18px;
   color: #6B7280;
-}
+}

+ 127 - 160
web/app/components/datasets/create/step-one/index.tsx

@@ -1,7 +1,6 @@
 'use client'
 import React, { useMemo, useState } from 'react'
 import { useTranslation } from 'react-i18next'
-import { RiArrowRightLine, RiFolder6Line } from '@remixicon/react'
 import FilePreview from '../file-preview'
 import FileUploader from '../file-uploader'
 import NotionPagePreview from '../notion-page-preview'
@@ -18,7 +17,6 @@ import { NotionPageSelector } from '@/app/components/base/notion-page-selector'
 import { useDatasetDetailContext } from '@/context/dataset-detail'
 import { useProviderContext } from '@/context/provider-context'
 import VectorSpaceFull from '@/app/components/billing/vector-space-full'
-import classNames from '@/utils/classnames'
 
 type IStepOneProps = {
   datasetId?: string
@@ -122,174 +120,143 @@ const StepOne = ({
       return true
     if (isShowVectorSpaceFull)
       return true
-    return false
-  }, [files, isShowVectorSpaceFull])
 
+    return false
+  }, [files])
   return (
     <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>
-                  <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 className='grow overflow-y-auto relative'>
+        {
+          shouldShowDataSourceTypeList && (
+            <div className={s.stepHeader}>{t('datasetCreation.steps.one')}</div>
+          )
+        }
+        <div className={s.form}>
+          {
+            shouldShowDataSourceTypeList && (
+              <div className='flex items-center mb-8 flex-wrap gap-y-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>
-              )
-            }
-            {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
+                  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>
-              </>
-            )}
-            {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='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={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
+                  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>
-                {isShowVectorSpaceFull && (
-                  <div className='max-w-[640px] mb-4'>
-                    <VectorSpaceFull />
+              )}
+              <Button disabled={nextDisabled} className={s.submitButton} variant='primary' onClick={onStepChange}>{t('datasetCreation.stepOne.button')}</Button>
+            </>
+          )}
+          {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="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>
+                  {isShowVectorSpaceFull && (
+                    <div className='max-w-[640px] mb-4'>
+                      <VectorSpaceFull />
+                    </div>
+                  )}
+                  <Button disabled={isShowVectorSpaceFull || !notionPages.length} className={s.submitButton} variant='primary' onClick={onStepChange}>{t('datasetCreation.stepOne.button')}</Button>
+                </>
+              )}
+            </>
+          )}
+          {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='max-w-[640px] mb-4'>
+                  <VectorSpaceFull />
                 </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} />
+              )}
+              <Button disabled={isShowVectorSpaceFull || !websitePages.length} className={s.submitButton} variant='primary' onClick={onStepChange}>{t('datasetCreation.stepOne.button')}</Button>
+            </>
+          )}
+          {!datasetId && (
+            <>
+              <div className={s.dividerLine} />
+              <div onClick={modalShowHandle} className={s.OtherCreationOption}>{t('datasetCreation.stepOne.emptyDatasetCreation')}</div>
+            </>
+          )}
         </div>
+        <EmptyDatasetCreationModal show={showModal} onHide={modalCloseHandle} />
       </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>
+      {currentFile && <FilePreview file={currentFile} hidePreview={hideFilePreview} />}
+      {currentNotionPage && <NotionPagePreview currentPage={currentNotionPage} hidePreview={hideNotionPagePreview} />}
+      {currentWebsite && <WebsitePreview payload={currentWebsite} hidePreview={hideWebsitePreview} />}
     </div>
   )
 }

+ 21 - 32
web/app/components/datasets/create/step-three/index.tsx

@@ -1,51 +1,45 @@
 'use client'
 import React from 'react'
 import { useTranslation } from 'react-i18next'
-import { RiBookOpenLine } from '@remixicon/react'
 import EmbeddingProcess from '../embedding-process'
 
+import s from './index.module.css'
+import cn from '@/utils/classnames'
 import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
 import type { FullDocumentDetail, createDocumentResponse } from '@/models/datasets'
-import AppIcon from '@/app/components/base/app-icon'
 
 type StepThreeProps = {
   datasetId?: string
   datasetName?: string
   indexingType?: string
-  retrievalMethod?: string
   creationCache?: createDocumentResponse
 }
 
-const StepThree = ({ datasetId, datasetName, indexingType, creationCache, retrievalMethod }: StepThreeProps) => {
+const StepThree = ({ datasetId, datasetName, indexingType, creationCache }: StepThreeProps) => {
   const { t } = useTranslation()
 
   const media = useBreakpoints()
   const isMobile = media === MediaType.mobile
 
   return (
-    <div className="flex justify-center w-full max-h-full h-full overflow-y-auto">
-      <div className="grow shrink-0 h-full max-w-[960px] overflow-y-auto px-14 sm:px-16">
-        <div className="mx-auto max-w-[640px]">
+    <div className='flex w-full h-full'>
+      <div className={'h-full w-full overflow-y-scroll px-6 sm:px-16'}>
+        <div className='max-w-[636px]'>
           {!datasetId && (
             <>
-              <div className="pt-10">
-                <div className="mb-1 text-xl leading-[22px] font-semibold text-text-primary">{t('datasetCreation.stepThree.creationTitle')}</div>
-                <div className="mb-7 text-[13px] leading-4 text-text-tertiary">{t('datasetCreation.stepThree.creationContent')}</div>
-                <div className="flex gap-4">
-                  <AppIcon {...creationCache?.dataset} className="size-14 text-2xl self-center" />
-                  <div className="grow flex flex-col gap-1">
-                    <div className="text-[13px] leading-6 font-semibold">{t('datasetCreation.stepThree.label')}</div>
-                    <div className="w-full px-3 py-2 text-[13px] leading-4 bg-components-input-bg-normal rounded-lg truncate">{datasetName || creationCache?.dataset?.name}</div>
-                  </div>
-                </div>
+              <div className={s.creationInfo}>
+                <div className={s.title}>{t('datasetCreation.stepThree.creationTitle')}</div>
+                <div className={s.content}>{t('datasetCreation.stepThree.creationContent')}</div>
+                <div className={s.label}>{t('datasetCreation.stepThree.label')}</div>
+                <div className={s.datasetName}>{datasetName || creationCache?.dataset?.name}</div>
               </div>
-              <hr className="my-6 h-[1px] bg-divider-subtle border-0" />
+              <div className={s.dividerLine} />
             </>
           )}
           {datasetId && (
-            <div className="pt-10">
-              <div className="mb-1 text-xl leading-[22px] font-semibold text-text-primary">{t('datasetCreation.stepThree.additionTitle')}</div>
-              <div className="mb-7 text-[13px] leading-4 text-text-tertiary">{`${t('datasetCreation.stepThree.additionP1')} ${datasetName || creationCache?.dataset?.name} ${t('datasetCreation.stepThree.additionP2')}`}</div>
+            <div className={s.creationInfo}>
+              <div className={s.title}>{t('datasetCreation.stepThree.additionTitle')}</div>
+              <div className={s.content}>{`${t('datasetCreation.stepThree.additionP1')} ${datasetName || creationCache?.dataset?.name} ${t('datasetCreation.stepThree.additionP2')}`}</div>
             </div>
           )}
           <EmbeddingProcess
@@ -53,21 +47,16 @@ const StepThree = ({ datasetId, datasetName, indexingType, creationCache, retrie
             batchId={creationCache?.batch || ''}
             documents={creationCache?.documents as FullDocumentDetail[]}
             indexingType={indexingType || creationCache?.dataset?.indexing_technique}
-            retrievalMethod={retrievalMethod || creationCache?.dataset?.retrieval_model?.search_method}
           />
         </div>
       </div>
-      {!isMobile && (
-        <div className="shrink-0 pt-[88px] pr-8 text-xs">
-          <div className="flex flex-col gap-3 w-[328px] p-6 text-text-tertiary bg-background-section rounded-xl">
-            <div className="flex justify-center items-center size-10 bg-components-card-bg rounded-[10px] shadow-lg">
-              <RiBookOpenLine className="size-5 text-text-accent" />
-            </div>
-            <div className="text-base font-semibold text-text-secondary">{t('datasetCreation.stepThree.sideTipTitle')}</div>
-            <div className="text-text-tertiary">{t('datasetCreation.stepThree.sideTipContent')}</div>
-          </div>
+      {!isMobile && <div className={cn(s.sideTip)}>
+        <div className={s.tipCard}>
+          <span className={s.icon} />
+          <div className={s.title}>{t('datasetCreation.stepThree.sideTipTitle')}</div>
+          <div className={s.content}>{t('datasetCreation.stepThree.sideTipContent')}</div>
         </div>
-      )}
+      </div>}
     </div>
   )
 }

+ 30 - 8
web/app/components/datasets/create/step-two/index.module.css

@@ -13,6 +13,18 @@
   z-index: 10;
 }
 
+.form {
+  @apply px-16 pb-8;
+}
+
+.form .label {
+  @apply pt-6 pb-2 flex items-center;
+  font-weight: 500;
+  font-size: 16px;
+  line-height: 24px;
+  color: #344054;
+}
+
 .segmentationItem {
   min-height: 68px;
 }
@@ -63,10 +75,6 @@
   cursor: pointer;
 }
 
-.disabled {
-  cursor: not-allowed !important;
-}
-
 .indexItem.disabled:hover {
   background-color: #fcfcfd;
   border-color: #f2f4f7;
@@ -79,7 +87,8 @@
 }
 
 .radioItem {
-  @apply relative mb-2 rounded-xl border border-components-option-card-option-border cursor-pointer bg-components-option-card-option-bg;
+  @apply relative mb-2 rounded-xl border border-gray-100 cursor-pointer;
+  background-color: #fcfcfd;
 }
 
 .radioItem.segmentationItem.custom {
@@ -137,7 +146,7 @@
 }
 
 .typeIcon.economical {
-  background-image: url(../assets/piggy-bank-mod.svg);
+  background-image: url(../assets/piggy-bank-01.svg);
 }
 
 .radioItem .radio {
@@ -238,7 +247,7 @@
 }
 
 .ruleItem {
-  @apply flex items-center py-1.5;
+  @apply flex items-center;
 }
 
 .formFooter {
@@ -385,6 +394,19 @@
   max-width: 524px;
 }
 
+.previewHeader {
+  position: sticky;
+  top: 0;
+  left: 0;
+  padding-top: 42px;
+  background-color: #fff;
+  font-weight: 600;
+  font-size: 18px;
+  line-height: 28px;
+  color: #101828;
+  z-index: 10;
+}
+
 /* 
  * `fixed` must under `previewHeader` because of style override would not work
  */
@@ -410,4 +432,4 @@
     font-size: 12px;
     line-height: 18px;
   }
-}
+}

Різницю між файлами не показано, бо вона завелика
+ 692 - 843
web/app/components/datasets/create/step-two/index.tsx


+ 0 - 77
web/app/components/datasets/create/step-two/inputs.tsx

@@ -1,77 +0,0 @@
-import type { FC, PropsWithChildren, ReactNode } from 'react'
-import { useTranslation } from 'react-i18next'
-import type { InputProps } from '@/app/components/base/input'
-import Input from '@/app/components/base/input'
-import Tooltip from '@/app/components/base/tooltip'
-import type { InputNumberProps } from '@/app/components/base/input-number'
-import { InputNumber } from '@/app/components/base/input-number'
-
-const TextLabel: FC<PropsWithChildren> = (props) => {
-  return <label className='text-text-secondary text-xs font-semibold leading-none'>{props.children}</label>
-}
-
-const FormField: FC<PropsWithChildren<{ label: ReactNode }>> = (props) => {
-  return <div className='space-y-2 flex-1'>
-    <TextLabel>{props.label}</TextLabel>
-    {props.children}
-  </div>
-}
-
-export const DelimiterInput: FC<InputProps & { tooltip?: string }> = (props) => {
-  const { t } = useTranslation()
-  return <FormField label={<div className='flex items-center mb-1'>
-    <span className='system-sm-semibold mr-0.5'>{t('datasetCreation.stepTwo.separator')}</span>
-    <Tooltip
-      popupContent={
-        <div className='max-w-[200px]'>
-          {props.tooltip || t('datasetCreation.stepTwo.separatorTip')}
-        </div>
-      }
-    />
-  </div>}>
-    <Input
-      type="text"
-      className='h-9'
-      placeholder={t('datasetCreation.stepTwo.separatorPlaceholder')!}
-      {...props}
-    />
-  </FormField>
-}
-
-export const MaxLengthInput: FC<InputNumberProps> = (props) => {
-  const { t } = useTranslation()
-  return <FormField label={<div className='system-sm-semibold mb-1'>
-    {t('datasetCreation.stepTwo.maxLength')}
-  </div>}>
-    <InputNumber
-      type="number"
-      className='h-9'
-      placeholder={'≤ 4000'}
-      max={4000}
-      min={1}
-      {...props}
-    />
-  </FormField>
-}
-
-export const OverlapInput: FC<InputNumberProps> = (props) => {
-  const { t } = useTranslation()
-  return <FormField label={<div className='flex items-center mb-1'>
-    <span className='system-sm-semibold'>{t('datasetCreation.stepTwo.overlap')}</span>
-    <Tooltip
-      popupContent={
-        <div className='max-w-[200px]'>
-          {t('datasetCreation.stepTwo.overlapTip')}
-        </div>
-      }
-    />
-  </div>}>
-    <InputNumber
-      type="number"
-      className='h-9'
-      placeholder={t('datasetCreation.stepTwo.overlap') || ''}
-      min={1}
-      {...props}
-    />
-  </FormField>
-}

+ 9 - 24
web/app/components/datasets/create/step-two/language-select/index.tsx

@@ -1,7 +1,7 @@
 'use client'
 import type { FC } from 'react'
 import React from 'react'
-import { RiArrowDownSLine, RiCheckLine } from '@remixicon/react'
+import { RiArrowDownSLine } from '@remixicon/react'
 import cn from '@/utils/classnames'
 import Popover from '@/app/components/base/popover'
 import { languages } from '@/i18n/language'
@@ -22,40 +22,25 @@ const LanguageSelect: FC<ILanguageSelectProps> = ({
       manualClose
       trigger='click'
       disabled={disabled}
-      popupClassName='z-20'
       htmlContent={
-        <div className='w-full p-1'>
+        <div className='w-full py-1'>
           {languages.filter(language => language.supported).map(({ prompt_name }) => (
             <div
               key={prompt_name}
-              className='w-full py-2 px-3 inline-flex items-center justify-between hover:bg-state-base-hover rounded-lg cursor-pointer'
-              onClick={() => onSelect(prompt_name)}
-            >
-              <span className='text-text-secondary system-sm-medium'>{prompt_name}</span>
-              {(currentLanguage === prompt_name) && <RiCheckLine className='size-4 text-text-accent' />}
+              className='py-2 px-3 mx-1 flex items-center gap-2 hover:bg-gray-100 rounded-lg cursor-pointer text-gray-700 text-sm'
+              onClick={() => onSelect(prompt_name)}>{prompt_name}
             </div>
           ))}
         </div>
       }
       btnElement={
-        <div className={cn('inline-flex items-center gap-x-[1px]', disabled && 'cursor-not-allowed')}>
-          <span className={cn(
-            'px-[3px] system-xs-semibold text-components-button-tertiary-text',
-            disabled ? 'text-components-button-tertiary-text-disabled' : '',
-          )}>
-            {currentLanguage}
-          </span>
-          <RiArrowDownSLine className={cn(
-            'size-3.5 text-components-button-tertiary-text',
-            disabled ? 'text-components-button-tertiary-text-disabled' : '',
-          )} />
+        <div className='inline-flex items-center'>
+          <span className='pr-[2px] text-xs leading-[18px] font-medium'>{currentLanguage}</span>
+          <RiArrowDownSLine className='w-3 h-3 opacity-60' />
         </div>
       }
-      btnClassName={() => cn(
-        '!border-0 rounded-md !px-1.5 !py-1 !mx-1 !bg-components-button-tertiary-bg !hover:bg-components-button-tertiary-bg',
-        disabled ? 'bg-components-button-tertiary-bg-disabled' : '',
-      )}
-      className='!w-[140px] h-fit !z-20 !translate-x-0 !left-1'
+      btnClassName={open => cn('!border-0 !px-0 !py-0 !bg-inherit !hover:bg-inherit', open ? 'text-blue-600' : 'text-gray-500')}
+      className='!w-[120px] h-fit !z-20 !translate-x-0 !left-[-16px]'
     />
   )
 }

+ 0 - 98
web/app/components/datasets/create/step-two/option-card.tsx

@@ -1,98 +0,0 @@
-import { type ComponentProps, type FC, type ReactNode, forwardRef } from 'react'
-import Image from 'next/image'
-import classNames from '@/utils/classnames'
-
-const TriangleArrow: FC<ComponentProps<'svg'>> = props => (
-  <svg xmlns="http://www.w3.org/2000/svg" width="24" height="11" viewBox="0 0 24 11" fill="none" {...props}>
-    <path d="M9.87868 1.12132C11.0503 -0.0502525 12.9497 -0.0502525 14.1213 1.12132L23.3137 10.3137H0.686292L9.87868 1.12132Z" fill="currentColor"/>
-  </svg>
-)
-
-type OptionCardHeaderProps = {
-  icon: ReactNode
-  title: ReactNode
-  description: string
-  isActive?: boolean
-  activeClassName?: string
-  effectImg?: string
-}
-
-export const OptionCardHeader: FC<OptionCardHeaderProps> = (props) => {
-  const { icon, title, description, isActive, activeClassName, effectImg } = props
-  return <div className={classNames(
-    'flex h-full overflow-hidden rounded-t-xl relative',
-    isActive && activeClassName,
-  )}>
-    <div className='size-14 flex items-center justify-center relative overflow-hidden'>
-      {isActive && effectImg && <Image src={effectImg} className='absolute top-0 left-0 w-full h-full' alt='' width={56} height={56} />}
-      <div className='p-1'>
-        <div className='size-8 rounded-lg border p-1.5 shadow-md border-components-panel-border-subtle justify-center flex bg-background-default-dodge'>
-          {icon}
-        </div>
-      </div>
-    </div>
-    <TriangleArrow
-      className='absolute left-4 -bottom-1.5 text-components-panel-bg'
-    />
-    <div className='flex-1 space-y-0.5 py-3 pr-4'>
-      <div className='text-text-secondary system-md-semibold'>{title}</div>
-      <div className='text-text-tertiary system-xs-regular'>{description}</div>
-    </div>
-  </div>
-}
-
-type OptionCardProps = {
-  icon: ReactNode
-  className?: string
-  activeHeaderClassName?: string
-  title: ReactNode
-  description: string
-  isActive?: boolean
-  actions?: ReactNode
-  effectImg?: string
-  onSwitched?: () => void
-  noHighlight?: boolean
-  disabled?: boolean
-} & Omit<ComponentProps<'div'>, 'title' | 'onClick'>
-
-export const OptionCard: FC<OptionCardProps> = forwardRef((props, ref) => {
-  const { icon, className, title, description, isActive, children, actions, activeHeaderClassName, style, effectImg, onSwitched, noHighlight, disabled, ...rest } = props
-  return <div
-    className={classNames(
-      'rounded-xl bg-components-option-card-option-bg shadow-xs',
-      (isActive && !noHighlight)
-        ? 'border-[1.5px] border-components-option-card-option-selected-border'
-        : 'border border-components-option-card-option-border',
-      disabled && 'opacity-50',
-      className,
-    )}
-    style={{
-      ...style,
-    }}
-    onClick={() => {
-      if (!isActive && !disabled)
-        onSwitched?.()
-    }}
-    {...rest}
-    ref={ref}
-  >
-    <OptionCardHeader
-      icon={icon}
-      title={title}
-      description={description}
-      isActive={isActive && !noHighlight}
-      activeClassName={activeHeaderClassName}
-      effectImg={effectImg}
-    />
-    {/** Body */}
-    {isActive && (children || actions) && <div className='py-3 px-4 bg-components-panel-bg rounded-b-xl'>
-      {children}
-      {actions && <div className='flex gap-2 mt-4'>
-        {actions}
-      </div>
-      }
-    </div>}
-  </div>
-})
-
-OptionCard.displayName = 'OptionCard'

+ 0 - 27
web/app/components/datasets/create/stepper/index.tsx

@@ -1,27 +0,0 @@
-import { type FC, Fragment } from 'react'
-import type { Step } from './step'
-import { StepperStep } from './step'
-
-export type StepperProps = {
-  steps: Step[]
-  activeIndex: number
-}
-
-export const Stepper: FC<StepperProps> = (props) => {
-  const { steps, activeIndex } = props
-  return <div className='flex items-center gap-3'>
-    {steps.map((step, index) => {
-      const isLast = index === steps.length - 1
-      return (
-        <Fragment key={index}>
-          <StepperStep
-            {...step}
-            activeIndex={activeIndex}
-            index={index}
-          />
-          {!isLast && <div className='w-4 h-px bg-divider-deep' />}
-        </Fragment>
-      )
-    })}
-  </div>
-}

+ 0 - 46
web/app/components/datasets/create/stepper/step.tsx

@@ -1,46 +0,0 @@
-import type { FC } from 'react'
-import classNames from '@/utils/classnames'
-
-export type Step = {
-  name: string
-}
-
-export type StepperStepProps = Step & {
-  index: number
-  activeIndex: number
-}
-
-export const StepperStep: FC<StepperStepProps> = (props) => {
-  const { name, activeIndex, index } = props
-  const isActive = index === activeIndex
-  const isDisabled = activeIndex < index
-  const label = isActive ? `STEP ${index + 1}` : `${index + 1}`
-  return <div className='flex items-center gap-2'>
-    <div className={classNames(
-      'h-5 px-2 py-1 rounded-3xl flex-col justify-center items-center gap-2 inline-flex',
-      isActive
-        ? 'bg-state-accent-solid'
-        : !isDisabled
-          ? 'border border-text-quaternary'
-          : 'border border-divider-deep',
-    )}>
-      <div className={classNames(
-        'text-center system-2xs-semibold-uppercase',
-        isActive
-          ? 'text-text-primary-on-surface'
-          : !isDisabled
-            ? 'text-text-tertiary'
-            : 'text-text-quaternary',
-      )}>
-        {label}
-      </div>
-    </div>
-    <div className={classNames('system-xs-medium-uppercase',
-      isActive
-        ? 'text-text-accent system-xs-semibold-uppercase'
-        : !isDisabled
-          ? 'text-text-tertiary'
-          : 'text-text-quaternary',
-    )}>{name}</div>
-  </div>
-}

+ 0 - 0
web/app/components/datasets/create/top-bar/index.tsx


Деякі файли не було показано, через те що забагато файлів було змінено