瀏覽代碼

Feat/refact header (#468)

zxhlyh 1 年之前
父節點
當前提交
1226d73159
共有 36 個文件被更改,包括 784 次插入87 次删除
  1. 3 0
      web/app/components/base/icons/assets/vender/line/arrows/arrow-narrow-left.svg
  2. 3 0
      web/app/components/base/icons/assets/vender/line/development/container.svg
  3. 3 0
      web/app/components/base/icons/assets/vender/line/development/database-01.svg
  4. 10 0
      web/app/components/base/icons/assets/vender/line/development/puzzle-piece-01.svg
  5. 10 0
      web/app/components/base/icons/assets/vender/line/layout/grid-01.svg
  6. 5 0
      web/app/components/base/icons/assets/vender/solid/development/container.svg
  7. 5 0
      web/app/components/base/icons/assets/vender/solid/development/database-02.svg
  8. 5 0
      web/app/components/base/icons/assets/vender/solid/development/puzzle-piece-01.svg
  9. 10 0
      web/app/components/base/icons/assets/vender/solid/layout/grid-01.svg
  10. 29 0
      web/app/components/base/icons/src/vender/line/arrows/ArrowNarrowLeft.json
  11. 14 0
      web/app/components/base/icons/src/vender/line/arrows/ArrowNarrowLeft.tsx
  12. 1 0
      web/app/components/base/icons/src/vender/line/arrows/index.ts
  13. 29 0
      web/app/components/base/icons/src/vender/line/development/Container.json
  14. 14 0
      web/app/components/base/icons/src/vender/line/development/Container.tsx
  15. 29 0
      web/app/components/base/icons/src/vender/line/development/Database01.json
  16. 14 0
      web/app/components/base/icons/src/vender/line/development/Database01.tsx
  17. 66 0
      web/app/components/base/icons/src/vender/line/development/PuzzlePiece01.json
  18. 14 0
      web/app/components/base/icons/src/vender/line/development/PuzzlePiece01.tsx
  19. 3 0
      web/app/components/base/icons/src/vender/line/development/index.ts
  20. 83 0
      web/app/components/base/icons/src/vender/line/layout/Grid01.json
  21. 14 0
      web/app/components/base/icons/src/vender/line/layout/Grid01.tsx
  22. 1 0
      web/app/components/base/icons/src/vender/line/layout/index.ts
  23. 44 0
      web/app/components/base/icons/src/vender/solid/development/Container.json
  24. 14 0
      web/app/components/base/icons/src/vender/solid/development/Container.tsx
  25. 46 0
      web/app/components/base/icons/src/vender/solid/development/Database02.json
  26. 14 0
      web/app/components/base/icons/src/vender/solid/development/Database02.tsx
  27. 38 0
      web/app/components/base/icons/src/vender/solid/development/PuzzlePiece01.json
  28. 14 0
      web/app/components/base/icons/src/vender/solid/development/PuzzlePiece01.tsx
  29. 3 0
      web/app/components/base/icons/src/vender/solid/development/index.ts
  30. 79 0
      web/app/components/base/icons/src/vender/solid/layout/Grid01.json
  31. 14 0
      web/app/components/base/icons/src/vender/solid/layout/Grid01.tsx
  32. 1 0
      web/app/components/base/icons/src/vender/solid/layout/index.ts
  33. 57 0
      web/app/components/header/app-nav/index.tsx
  34. 53 0
      web/app/components/header/dataset-nav/index.tsx
  35. 24 75
      web/app/components/header/index.tsx
  36. 18 12
      web/app/components/header/nav/index.tsx

+ 3 - 0
web/app/components/base/icons/assets/vender/line/arrows/arrow-narrow-left.svg

@@ -0,0 +1,3 @@
+<svg width="17" height="16" viewBox="0 0 17 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M13.3625 8H2.6958M2.6958 8L6.6958 12M2.6958 8L6.6958 4" stroke="#155EEF" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
+</svg>

File diff suppressed because it is too large
+ 3 - 0
web/app/components/base/icons/assets/vender/line/development/container.svg


+ 3 - 0
web/app/components/base/icons/assets/vender/line/development/database-01.svg

@@ -0,0 +1,3 @@
+<svg width="17" height="16" viewBox="0 0 17 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M14.5 3.33337C14.5 4.43794 11.8137 5.33337 8.5 5.33337C5.18629 5.33337 2.5 4.43794 2.5 3.33337M14.5 3.33337C14.5 2.2288 11.8137 1.33337 8.5 1.33337C5.18629 1.33337 2.5 2.2288 2.5 3.33337M14.5 3.33337V12.6667C14.5 13.7734 11.8333 14.6667 8.5 14.6667C5.16667 14.6667 2.5 13.7734 2.5 12.6667V3.33337M14.5 8.00004C14.5 9.10671 11.8333 10 8.5 10C5.16667 10 2.5 9.10671 2.5 8.00004" stroke="#667085" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round"/>
+</svg>

File diff suppressed because it is too large
+ 10 - 0
web/app/components/base/icons/assets/vender/line/development/puzzle-piece-01.svg


File diff suppressed because it is too large
+ 10 - 0
web/app/components/base/icons/assets/vender/line/layout/grid-01.svg


File diff suppressed because it is too large
+ 5 - 0
web/app/components/base/icons/assets/vender/solid/development/container.svg


File diff suppressed because it is too large
+ 5 - 0
web/app/components/base/icons/assets/vender/solid/development/database-02.svg


File diff suppressed because it is too large
+ 5 - 0
web/app/components/base/icons/assets/vender/solid/development/puzzle-piece-01.svg


File diff suppressed because it is too large
+ 10 - 0
web/app/components/base/icons/assets/vender/solid/layout/grid-01.svg


+ 29 - 0
web/app/components/base/icons/src/vender/line/arrows/ArrowNarrowLeft.json

@@ -0,0 +1,29 @@
+{
+	"icon": {
+		"type": "element",
+		"isRootNode": true,
+		"name": "svg",
+		"attributes": {
+			"width": "17",
+			"height": "16",
+			"viewBox": "0 0 17 16",
+			"fill": "none",
+			"xmlns": "http://www.w3.org/2000/svg"
+		},
+		"children": [
+			{
+				"type": "element",
+				"name": "path",
+				"attributes": {
+					"d": "M13.3625 8H2.6958M2.6958 8L6.6958 12M2.6958 8L6.6958 4",
+					"stroke": "currentColor",
+					"stroke-width": "2",
+					"stroke-linecap": "round",
+					"stroke-linejoin": "round"
+				},
+				"children": []
+			}
+		]
+	},
+	"name": "ArrowNarrowLeft"
+}

+ 14 - 0
web/app/components/base/icons/src/vender/line/arrows/ArrowNarrowLeft.tsx

@@ -0,0 +1,14 @@
+// GENERATE BY script
+// DON NOT EDIT IT MANUALLY
+
+import * as React from 'react'
+import data from './ArrowNarrowLeft.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} />)
+
+export default Icon

+ 1 - 0
web/app/components/base/icons/src/vender/line/arrows/index.ts

@@ -1 +1,2 @@
+export { default as ArrowNarrowLeft } from './ArrowNarrowLeft'
 export { default as RefreshCw05 } from './RefreshCw05'

File diff suppressed because it is too large
+ 29 - 0
web/app/components/base/icons/src/vender/line/development/Container.json


+ 14 - 0
web/app/components/base/icons/src/vender/line/development/Container.tsx

@@ -0,0 +1,14 @@
+// GENERATE BY script
+// DON NOT EDIT IT MANUALLY
+
+import * as React from 'react'
+import data from './Container.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} />)
+
+export default Icon

+ 29 - 0
web/app/components/base/icons/src/vender/line/development/Database01.json

@@ -0,0 +1,29 @@
+{
+	"icon": {
+		"type": "element",
+		"isRootNode": true,
+		"name": "svg",
+		"attributes": {
+			"width": "17",
+			"height": "16",
+			"viewBox": "0 0 17 16",
+			"fill": "none",
+			"xmlns": "http://www.w3.org/2000/svg"
+		},
+		"children": [
+			{
+				"type": "element",
+				"name": "path",
+				"attributes": {
+					"d": "M14.5 3.33337C14.5 4.43794 11.8137 5.33337 8.5 5.33337C5.18629 5.33337 2.5 4.43794 2.5 3.33337M14.5 3.33337C14.5 2.2288 11.8137 1.33337 8.5 1.33337C5.18629 1.33337 2.5 2.2288 2.5 3.33337M14.5 3.33337V12.6667C14.5 13.7734 11.8333 14.6667 8.5 14.6667C5.16667 14.6667 2.5 13.7734 2.5 12.6667V3.33337M14.5 8.00004C14.5 9.10671 11.8333 10 8.5 10C5.16667 10 2.5 9.10671 2.5 8.00004",
+					"stroke": "currentColor",
+					"stroke-width": "1.25",
+					"stroke-linecap": "round",
+					"stroke-linejoin": "round"
+				},
+				"children": []
+			}
+		]
+	},
+	"name": "Database01"
+}

+ 14 - 0
web/app/components/base/icons/src/vender/line/development/Database01.tsx

@@ -0,0 +1,14 @@
+// GENERATE BY script
+// DON NOT EDIT IT MANUALLY
+
+import * as React from 'react'
+import data from './Database01.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} />)
+
+export default Icon

File diff suppressed because it is too large
+ 66 - 0
web/app/components/base/icons/src/vender/line/development/PuzzlePiece01.json


+ 14 - 0
web/app/components/base/icons/src/vender/line/development/PuzzlePiece01.tsx

@@ -0,0 +1,14 @@
+// GENERATE BY script
+// DON NOT EDIT IT MANUALLY
+
+import * as React from 'react'
+import data from './PuzzlePiece01.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} />)
+
+export default Icon

+ 3 - 0
web/app/components/base/icons/src/vender/line/development/index.ts

@@ -1 +1,4 @@
+export { default as Container } from './Container'
+export { default as Database01 } from './Database01'
 export { default as Database03 } from './Database03'
+export { default as PuzzlePiece01 } from './PuzzlePiece01'

File diff suppressed because it is too large
+ 83 - 0
web/app/components/base/icons/src/vender/line/layout/Grid01.json


+ 14 - 0
web/app/components/base/icons/src/vender/line/layout/Grid01.tsx

@@ -0,0 +1,14 @@
+// GENERATE BY script
+// DON NOT EDIT IT MANUALLY
+
+import * as React from 'react'
+import data from './Grid01.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} />)
+
+export default Icon

+ 1 - 0
web/app/components/base/icons/src/vender/line/layout/index.ts

@@ -0,0 +1 @@
+export { default as Grid01 } from './Grid01'

File diff suppressed because it is too large
+ 44 - 0
web/app/components/base/icons/src/vender/solid/development/Container.json


+ 14 - 0
web/app/components/base/icons/src/vender/solid/development/Container.tsx

@@ -0,0 +1,14 @@
+// GENERATE BY script
+// DON NOT EDIT IT MANUALLY
+
+import * as React from 'react'
+import data from './Container.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} />)
+
+export default Icon

File diff suppressed because it is too large
+ 46 - 0
web/app/components/base/icons/src/vender/solid/development/Database02.json


+ 14 - 0
web/app/components/base/icons/src/vender/solid/development/Database02.tsx

@@ -0,0 +1,14 @@
+// GENERATE BY script
+// DON NOT EDIT IT MANUALLY
+
+import * as React from 'react'
+import data from './Database02.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} />)
+
+export default Icon

File diff suppressed because it is too large
+ 38 - 0
web/app/components/base/icons/src/vender/solid/development/PuzzlePiece01.json


+ 14 - 0
web/app/components/base/icons/src/vender/solid/development/PuzzlePiece01.tsx

@@ -0,0 +1,14 @@
+// GENERATE BY script
+// DON NOT EDIT IT MANUALLY
+
+import * as React from 'react'
+import data from './PuzzlePiece01.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} />)
+
+export default Icon

+ 3 - 0
web/app/components/base/icons/src/vender/solid/development/index.ts

@@ -1 +1,4 @@
+export { default as Container } from './Container'
+export { default as Database02 } from './Database02'
 export { default as Database03 } from './Database03'
+export { default as PuzzlePiece01 } from './PuzzlePiece01'

File diff suppressed because it is too large
+ 79 - 0
web/app/components/base/icons/src/vender/solid/layout/Grid01.json


+ 14 - 0
web/app/components/base/icons/src/vender/solid/layout/Grid01.tsx

@@ -0,0 +1,14 @@
+// GENERATE BY script
+// DON NOT EDIT IT MANUALLY
+
+import * as React from 'react'
+import data from './Grid01.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} />)
+
+export default Icon

+ 1 - 0
web/app/components/base/icons/src/vender/solid/layout/index.ts

@@ -0,0 +1 @@
+export { default as Grid01 } from './Grid01'

+ 57 - 0
web/app/components/header/app-nav/index.tsx

@@ -0,0 +1,57 @@
+import { useCallback, useState } from 'react'
+import { useTranslation } from 'react-i18next'
+import { useParams } from 'next/navigation'
+import useSWR from 'swr'
+import useSWRInfinite from 'swr/infinite'
+import { flatten } from 'lodash-es'
+import Nav from '../nav'
+import { fetchAppDetail, fetchAppList } from '@/service/apps'
+import NewAppDialog from '@/app/(commonLayout)/apps/NewAppDialog'
+import { Container } from '@/app/components/base/icons/src/vender/line/development'
+import { Container as ContainerSolid } from '@/app/components/base/icons/src/vender/solid/development'
+import type { AppListResponse } from '@/models/app'
+
+const getKey = (pageIndex: number, previousPageData: AppListResponse) => {
+  if (!pageIndex || previousPageData.has_more)
+    return { url: 'apps', params: { page: pageIndex + 1, limit: 30 } }
+  return null
+}
+
+const AppNav = () => {
+  const { t } = useTranslation()
+  const [showNewAppDialog, setShowNewAppDialog] = useState(false)
+  const { appId } = useParams()
+  const { data: currentApp } = useSWR(appId ? { url: '/apps', id: appId } : null, fetchAppDetail)
+  const { data: appsData, setSize } = useSWRInfinite(appId ? getKey : () => null, fetchAppList, { revalidateFirstPage: false })
+  const appItems = flatten(appsData?.map(appData => appData.data))
+
+  const handleLoadmore = useCallback(() => {
+    setSize(size => size + 1)
+  }, [setSize])
+
+  return (
+    <>
+      <Nav
+        icon={<Container className='w-4 h-4' />}
+        activeIcon={<ContainerSolid className='w-4 h-4' />}
+        text={t('common.menus.apps')}
+        activeSegment={['apps', 'app']}
+        link='/apps'
+        curNav={currentApp}
+        navs={appItems.map(item => ({
+          id: item.id,
+          name: item.name,
+          link: `/app/${item.id}/overview`,
+          icon: item.icon,
+          icon_background: item.icon_background,
+        }))}
+        createText={t('common.menus.newApp')}
+        onCreate={() => setShowNewAppDialog(true)}
+        onLoadmore={handleLoadmore}
+      />
+      <NewAppDialog show={showNewAppDialog} onClose={() => setShowNewAppDialog(false)} />
+    </>
+  )
+}
+
+export default AppNav

+ 53 - 0
web/app/components/header/dataset-nav/index.tsx

@@ -0,0 +1,53 @@
+import { useCallback } from 'react'
+import { useTranslation } from 'react-i18next'
+import { useParams, useRouter } from 'next/navigation'
+import useSWR from 'swr'
+import useSWRInfinite from 'swr/infinite'
+import { flatten } from 'lodash-es'
+import Nav from '../nav'
+import { fetchDataDetail, fetchDatasets } from '@/service/datasets'
+import { Database01 } from '@/app/components/base/icons/src/vender/line/development'
+import { Database02 } from '@/app/components/base/icons/src/vender/solid/development'
+import type { DataSetListResponse } from '@/models/datasets'
+
+const getKey = (pageIndex: number, previousPageData: DataSetListResponse) => {
+  if (!pageIndex || previousPageData.has_more)
+    return { url: 'datasets', params: { page: pageIndex + 1, limit: 30 } }
+  return null
+}
+
+const DatasetNav = () => {
+  const { t } = useTranslation()
+  const router = useRouter()
+  const { datasetId } = useParams()
+  const { data: currentDataset } = useSWR(datasetId || null, fetchDataDetail)
+  const { data: datasetsData, setSize } = useSWRInfinite(datasetId ? getKey : () => null, fetchDatasets, { revalidateFirstPage: true })
+  const datasetItems = flatten(datasetsData?.map(datasetData => datasetData.data))
+
+  const handleLoadmore = useCallback(() => {
+    setSize(size => size + 1)
+  }, [setSize])
+
+  return (
+    <Nav
+      icon={<Database01 className='w-4 h-4' />}
+      activeIcon={<Database02 className='w-4 h-4' />}
+      text={t('common.menus.datasets')}
+      activeSegment='datasets'
+      link='/datasets'
+      curNav={currentDataset}
+      navs={datasetItems.map(dataset => ({
+        id: dataset.id,
+        name: dataset.name,
+        link: `/datasets/${dataset.id}/documents`,
+        icon: dataset.icon,
+        icon_background: dataset.icon_background,
+      }))}
+      createText={t('common.menus.newDataset')}
+      onCreate={() => router.push('/datasets/create')}
+      onLoadmore={handleLoadmore}
+    />
+  )
+}
+
+export default DatasetNav

File diff suppressed because it is too large
+ 24 - 75
web/app/components/header/index.tsx


+ 18 - 12
web/app/components/header/nav/index.tsx

@@ -4,12 +4,13 @@ import React, { useState } from 'react'
 import Link from 'next/link'
 import { useSelectedLayoutSegment } from 'next/navigation'
 import classNames from 'classnames'
-import { ArrowLeftIcon } from '@heroicons/react/24/solid'
 import type { INavSelectorProps } from './nav-selector'
 import NavSelector from './nav-selector'
+import { ArrowNarrowLeft } from '@/app/components/base/icons/src/vender/line/arrows'
 
 type INavProps = {
   icon: React.ReactNode
+  activeIcon?: React.ReactNode
   text: string
   activeSegment: string | string[]
   link: string
@@ -17,6 +18,7 @@ type INavProps = {
 
 const Nav = ({
   icon,
+  activeIcon,
   text,
   activeSegment,
   link,
@@ -32,25 +34,29 @@ const Nav = ({
 
   return (
     <div className={`
-      flex items-center h-8 mr-3 px-0.5  rounded-xl text-[14px] shrink-0
-      ${isActived && 'bg-white shadow-[0_2px_5px_-1px_rgba(0,0,0,0.05),0_2px_4px_-2px_rgba(0,0,0,0.05)]'}
+      flex items-center h-8 mr-3 px-0.5 rounded-xl text-sm shrink-0 font-medium
+      ${isActived && 'bg-white shadow-[0_2px_5px_-1px_rgba(0,0,0,0.05),0_2px_4px_-2px_rgba(0,0,0,0.05)] font-semibold'}
+      ${!curNav && !isActived && 'hover:bg-gray-200'}
     `}>
       <Link href={link}>
         <div
           className={classNames(`
-            flex items-center h-7 pl-2.5 pr-2
-            font-semibold cursor-pointer rounded-[10px]
-            ${isActived ? 'text-[#1C64F2]' : 'text-gray-500 hover:bg-gray-200'}
-            ${curNav && isActived && 'hover:bg-[#EBF5FF]'}
+            flex items-center h-7 px-2.5 cursor-pointer rounded-[10px]
+            ${isActived ? 'text-primary-600' : 'text-gray-500'}
+            ${curNav && isActived && 'hover:bg-primary-50'}
           `)}
           onMouseEnter={() => setHovered(true)}
           onMouseLeave={() => setHovered(false)}
         >
-          {
-            (hovered && curNav && isActived)
-              ? <ArrowLeftIcon className='mr-1 w-[18px] h-[18px]' />
-              : icon
-          }
+          <div className='mr-2'>
+            {
+              (hovered && curNav)
+                ? <ArrowNarrowLeft className='w-4 h-4' />
+                : isActived
+                  ? activeIcon
+                  : icon
+            }
+          </div>
           {text}
         </div>
       </Link>