mirror of
https://github.com/langgenius/dify.git
synced 2026-04-22 07:46:31 +08:00
feat: create top bar
This commit is contained in:
parent
13c62f83f4
commit
fdcee1cd45
@ -6,6 +6,7 @@ import { ModelTypeEnum } from '../../header/account-setting/model-provider-page/
|
|||||||
import StepOne from './step-one'
|
import StepOne from './step-one'
|
||||||
import StepTwo from './step-two'
|
import StepTwo from './step-two'
|
||||||
import StepThree from './step-three'
|
import StepThree from './step-three'
|
||||||
|
import { Topbar } from './top-bar'
|
||||||
import { DataSourceType } from '@/models/datasets'
|
import { DataSourceType } from '@/models/datasets'
|
||||||
import type { CrawlOptions, CrawlResultItem, DataSet, FileItem, createDocumentResponse } from '@/models/datasets'
|
import type { CrawlOptions, CrawlResultItem, DataSet, FileItem, createDocumentResponse } from '@/models/datasets'
|
||||||
import { fetchDataSource } from '@/service/common'
|
import { fetchDataSource } from '@/service/common'
|
||||||
@ -119,6 +120,7 @@ const DatasetUpdateForm = ({ datasetId }: DatasetUpdateFormProps) => {
|
|||||||
return (
|
return (
|
||||||
<div className='flex flex-col' style={{ height: 'calc(100vh - 56px)' }}>
|
<div className='flex flex-col' style={{ height: 'calc(100vh - 56px)' }}>
|
||||||
<div className="grow bg-white">
|
<div className="grow bg-white">
|
||||||
|
<Topbar activeStepIndex={step - 1} />
|
||||||
<div className={step === 1 ? 'block h-full' : 'hidden'}>
|
<div className={step === 1 ? 'block h-full' : 'hidden'}>
|
||||||
<StepOne
|
<StepOne
|
||||||
hasConnection={hasConnection}
|
hasConnection={hasConnection}
|
||||||
|
|||||||
@ -5,7 +5,6 @@ import { useTranslation } from 'react-i18next'
|
|||||||
import { useContext } from 'use-context-selector'
|
import { useContext } from 'use-context-selector'
|
||||||
import { useBoolean } from 'ahooks'
|
import { useBoolean } from 'ahooks'
|
||||||
import { XMarkIcon } from '@heroicons/react/20/solid'
|
import { XMarkIcon } from '@heroicons/react/20/solid'
|
||||||
import { RocketLaunchIcon } from '@heroicons/react/24/outline'
|
|
||||||
import {
|
import {
|
||||||
RiArrowLeftLine,
|
RiArrowLeftLine,
|
||||||
RiCloseLine,
|
RiCloseLine,
|
||||||
@ -51,7 +50,6 @@ import { useDatasetDetailContext } from '@/context/dataset-detail'
|
|||||||
import I18n from '@/context/i18n'
|
import I18n from '@/context/i18n'
|
||||||
import { RETRIEVE_METHOD } from '@/types/app'
|
import { RETRIEVE_METHOD } from '@/types/app'
|
||||||
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
|
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
|
||||||
import Tooltip from '@/app/components/base/tooltip'
|
|
||||||
import { useDefaultModel, useModelList, useModelListAndDefaultModelAndCurrentProviderAndModel } from '@/app/components/header/account-setting/model-provider-page/hooks'
|
import { useDefaultModel, useModelList, useModelListAndDefaultModelAndCurrentProviderAndModel } from '@/app/components/header/account-setting/model-provider-page/hooks'
|
||||||
import { LanguagesSupported } from '@/i18n/language'
|
import { LanguagesSupported } from '@/i18n/language'
|
||||||
import ModelSelector from '@/app/components/header/account-setting/model-provider-page/model-selector'
|
import ModelSelector from '@/app/components/header/account-setting/model-provider-page/model-selector'
|
||||||
@ -639,23 +637,7 @@ const StepTwo = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='flex w-full h-full'>
|
<div className='flex w-full h-full'>
|
||||||
<div ref={scrollRef} className='relative h-full w-full overflow-y-scroll'>
|
<div className='relative h-full w-full overflow-y-scroll'>
|
||||||
<div className={cn(s.pageHeader, scrolled && s.fixed, isMobile && '!px-6')}>
|
|
||||||
<span>{t('datasetCreation.steps.two')}</span>
|
|
||||||
{(isMobile || !showPreview) && (
|
|
||||||
<Button
|
|
||||||
className='border-[0.5px] !h-8 hover:outline hover:outline-[0.5px] hover:outline-gray-300 text-gray-700 font-medium bg-white shadow-[0px_1px_2px_0px_rgba(16,24,40,0.05)]'
|
|
||||||
onClick={setShowPreview}
|
|
||||||
>
|
|
||||||
<Tooltip>
|
|
||||||
<div className="flex flex-row items-center">
|
|
||||||
<RocketLaunchIcon className="h-4 w-4 mr-1.5 stroke-[1.8px]" />
|
|
||||||
<span className="text-[13px]">{t('datasetCreation.stepTwo.previewTitleButton')}</span>
|
|
||||||
</div>
|
|
||||||
</Tooltip>
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<div className={cn(s.form, isMobile && '!px-4')}>
|
<div className={cn(s.form, isMobile && '!px-4')}>
|
||||||
<div className={s.label}>{t('datasetCreation.stepTwo.segmentation')}</div>
|
<div className={s.label}>{t('datasetCreation.stepTwo.segmentation')}</div>
|
||||||
<div className='max-w-[640px]'>
|
<div className='max-w-[640px]'>
|
||||||
@ -906,7 +888,7 @@ const StepTwo = ({
|
|||||||
<MessageChatSquare className='w-4 h-4' />
|
<MessageChatSquare className='w-4 h-4' />
|
||||||
</div>
|
</div>
|
||||||
<div className='grow mx-3'>
|
<div className='grow mx-3'>
|
||||||
<div className='mb-[2px] text-md font-medium text-gray-900'>{t('datasetCreation.stepTwo.QATitle')}</div>
|
<div className='mb-0.5 text-md font-medium text-gray-900'>{t('datasetCreation.stepTwo.QATitle')}</div>
|
||||||
<div className='inline-flex items-center text-[13px] leading-[18px] text-gray-500'>
|
<div className='inline-flex items-center text-[13px] leading-[18px] text-gray-500'>
|
||||||
<span className='pr-1'>{t('datasetCreation.stepTwo.QALanguage')}</span>
|
<span className='pr-1'>{t('datasetCreation.stepTwo.QALanguage')}</span>
|
||||||
<LanguageSelect currentLanguage={docLanguage} onSelect={handleSelect} disabled={isLanguageSelectDisabled} />
|
<LanguageSelect currentLanguage={docLanguage} onSelect={handleSelect} disabled={isLanguageSelectDisabled} />
|
||||||
|
|||||||
34
web/app/components/datasets/create/stepper/index.tsx
Normal file
34
web/app/components/datasets/create/stepper/index.tsx
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import type { FC } from 'react'
|
||||||
|
import type { Step } from './step'
|
||||||
|
import { StepperStep } from './step'
|
||||||
|
|
||||||
|
export type StepperProps = {
|
||||||
|
steps: Step[]
|
||||||
|
activeStepIndex: number
|
||||||
|
}
|
||||||
|
|
||||||
|
function join<T, R = T>(array: T[], sep: R): Array<T | R> {
|
||||||
|
return array.reduce((acc, item, index) => {
|
||||||
|
if (index === 0)
|
||||||
|
return [item]
|
||||||
|
|
||||||
|
return acc.concat([sep, item])
|
||||||
|
}, [] as Array<T | R>)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Stepper: FC<StepperProps> = (props) => {
|
||||||
|
const { steps, activeStepIndex } = props
|
||||||
|
return <div className='flex items-center gap-3'>
|
||||||
|
{join(
|
||||||
|
steps.map((step, index) => (
|
||||||
|
<StepperStep
|
||||||
|
key={index}
|
||||||
|
{...step}
|
||||||
|
isActive={index === activeStepIndex}
|
||||||
|
index={index}
|
||||||
|
/>
|
||||||
|
)),
|
||||||
|
<div className="w-4 h-px bg-[#101828]/30" />,
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
33
web/app/components/datasets/create/stepper/step.tsx
Normal file
33
web/app/components/datasets/create/stepper/step.tsx
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import type { FC } from 'react'
|
||||||
|
import classNames from '@/utils/classnames'
|
||||||
|
|
||||||
|
export type Step = {
|
||||||
|
name: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export type StepperStepProps = Step & {
|
||||||
|
index: number
|
||||||
|
isActive: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export const StepperStep: FC<StepperStepProps> = (props) => {
|
||||||
|
const { name, isActive, index } = props
|
||||||
|
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-[#296cff]' : 'border border-[#101828]/30',
|
||||||
|
)}>
|
||||||
|
<div className={classNames(
|
||||||
|
'text-center text-[10px] font-semibold uppercase leading-3',
|
||||||
|
isActive ? 'text-white' : 'text-[#676f83]',
|
||||||
|
)}>
|
||||||
|
{label}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className={classNames(
|
||||||
|
' text-xs font-medium uppercase leading-none',
|
||||||
|
isActive ? 'text-[#155aef]' : 'text-[#676f83]',
|
||||||
|
)}>{name}</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
32
web/app/components/datasets/create/top-bar/index.tsx
Normal file
32
web/app/components/datasets/create/top-bar/index.tsx
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import type { FC } from 'react'
|
||||||
|
import { RiArrowLeftLine } from '@remixicon/react'
|
||||||
|
import { Stepper, type StepperProps } from '../stepper'
|
||||||
|
import classNames from '@/utils/classnames'
|
||||||
|
|
||||||
|
export type TopbarProps = Pick<StepperProps, 'activeStepIndex'> & {
|
||||||
|
className?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Topbar: FC<TopbarProps> = (props) => {
|
||||||
|
const { className, ...rest } = props
|
||||||
|
return <div className={classNames('flex items-center justify-between relative', className)}>
|
||||||
|
<div className="h-12 pl-2 pr-6 py-2 justify-start items-center gap-1 inline-flex">
|
||||||
|
<RiArrowLeftLine className='size-4 mr-2' />
|
||||||
|
<div className="text-[#101827] text-[13px] font-semibold uppercase leading-none">
|
||||||
|
Create Knowledge
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className={
|
||||||
|
'top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 absolute'
|
||||||
|
}>
|
||||||
|
<Stepper
|
||||||
|
steps={[
|
||||||
|
{ name: 'Data Source' },
|
||||||
|
{ name: 'Document Processing' },
|
||||||
|
{ name: 'Execute & Finish' },
|
||||||
|
]}
|
||||||
|
{...rest}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
@ -1,25 +1,16 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import Input from '../components/base/input'
|
import { Stepper } from '../components/datasets/create/stepper'
|
||||||
import { OptionCard } from '../components/datasets/create/step-two/option-card'
|
|
||||||
|
|
||||||
export default function Page() {
|
export default function Page() {
|
||||||
return <div className='p-4'>
|
return <div className='p-4'>
|
||||||
<OptionCard
|
<Stepper
|
||||||
icon={undefined}
|
steps={[
|
||||||
title={'General'}
|
{ name: 'Data Source' },
|
||||||
description={
|
{ name: 'Document Processing' },
|
||||||
'General text chunking mode, the chunks retrieved and recalled are the same.'
|
{ name: 'Execute & Finish' },
|
||||||
}
|
]}
|
||||||
className='w-[600px]'
|
activeStepIndex={1}
|
||||||
activeHeaderClassName='bg-gradient-to-r from-[#EFF0F9] to-[#F9FAFB]'
|
/>
|
||||||
isActive={true}>
|
|
||||||
<p
|
|
||||||
className='text-[#354052] text-sm font-semibold leading-tight'
|
|
||||||
>
|
|
||||||
Lorem ipsum
|
|
||||||
</p>
|
|
||||||
<Input className='mt-2' />
|
|
||||||
</OptionCard>
|
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user