feat: enhance dataset detail layout with button disable logic based on pipeline status

pull/21398/head
twwu 11 months ago
parent 6ff6525d1d
commit 9176790adf

@ -120,10 +120,32 @@ const DatasetDetailLayout: FC<IAppDetailLayoutProps> = (props) => {
const { data: relatedApps } = useDatasetRelatedApps(datasetId) const { data: relatedApps } = useDatasetRelatedApps(datasetId)
const isButtonDisabledWithPipeline = useMemo(() => {
if (!datasetRes)
return true
if (datasetRes.provider === 'external')
return false
if (!datasetRes.pipeline_id)
return false
return !datasetRes.is_published
}, [datasetRes])
const navigation = useMemo(() => { const navigation = useMemo(() => {
const baseNavigation = [ const baseNavigation = [
{ name: t('common.datasetMenus.hitTesting'), href: `/datasets/${datasetId}/hitTesting`, icon: RiFocus2Line, selectedIcon: RiFocus2Fill }, {
{ name: t('common.datasetMenus.settings'), href: `/datasets/${datasetId}/settings`, icon: RiEqualizer2Line, selectedIcon: RiEqualizer2Fill }, name: t('common.datasetMenus.hitTesting'),
href: `/datasets/${datasetId}/hitTesting`,
icon: RiFocus2Line,
selectedIcon: RiFocus2Fill,
disabled: isButtonDisabledWithPipeline,
},
{
name: t('common.datasetMenus.settings'),
href: `/datasets/${datasetId}/settings`,
icon: RiEqualizer2Line,
selectedIcon: RiEqualizer2Fill,
disabled: false,
},
] ]
if (datasetRes?.provider !== 'external') { if (datasetRes?.provider !== 'external') {
@ -132,15 +154,17 @@ const DatasetDetailLayout: FC<IAppDetailLayoutProps> = (props) => {
href: `/datasets/${datasetId}/documents`, href: `/datasets/${datasetId}/documents`,
icon: RiFileTextLine, icon: RiFileTextLine,
selectedIcon: RiFileTextFill, selectedIcon: RiFileTextFill,
disabled: isButtonDisabledWithPipeline,
}, { }, {
name: t('common.datasetMenus.pipeline'), name: t('common.datasetMenus.pipeline'),
href: `/datasets/${datasetId}/pipeline`, href: `/datasets/${datasetId}/pipeline`,
icon: PipelineLine as RemixiconComponentType, icon: PipelineLine as RemixiconComponentType,
selectedIcon: PipelineFill as RemixiconComponentType, selectedIcon: PipelineFill as RemixiconComponentType,
disabled: false,
}]) }])
} }
return baseNavigation return baseNavigation
}, [datasetRes?.provider, datasetId, t]) }, [t, datasetId, isButtonDisabledWithPipeline, datasetRes?.provider])
useDocumentTitle(datasetRes?.name || t('common.menus.datasets')) useDocumentTitle(datasetRes?.name || t('common.menus.datasets'))

@ -16,6 +16,7 @@ export type IAppDetailNavProps = {
href: string href: string
icon: NavIcon icon: NavIcon
selectedIcon: NavIcon selectedIcon: NavIcon
disabled?: boolean
}> }>
extraInfo?: (modeState: string) => React.ReactNode extraInfo?: (modeState: string) => React.ReactNode
} }
@ -78,7 +79,14 @@ const AppDetailNav = ({
> >
{navigation.map((item, index) => { {navigation.map((item, index) => {
return ( return (
<NavLink key={index} mode={appSidebarExpand} iconMap={{ selected: item.selectedIcon, normal: item.icon }} name={item.name} href={item.href} /> <NavLink
key={index}
mode={appSidebarExpand}
iconMap={{ selected: item.selectedIcon, normal: item.icon }}
name={item.name}
href={item.href}
disabled={!!item.disabled}
/>
) )
})} })}
</nav> </nav>

@ -6,10 +6,10 @@ import classNames from '@/utils/classnames'
import type { RemixiconComponentType } from '@remixicon/react' import type { RemixiconComponentType } from '@remixicon/react'
export type NavIcon = React.ComponentType< export type NavIcon = React.ComponentType<
React.PropsWithoutRef<React.ComponentProps<'svg'>> & { React.PropsWithoutRef<React.ComponentProps<'svg'>> & {
title?: string | undefined title?: string | undefined
titleId?: string | undefined titleId?: string | undefined
}> | RemixiconComponentType }> | RemixiconComponentType
export type NavLinkProps = { export type NavLinkProps = {
name: string name: string
@ -19,6 +19,7 @@ export type NavLinkProps = {
normal: NavIcon normal: NavIcon
} }
mode?: string mode?: string
disabled?: boolean
} }
export default function NavLink({ export default function NavLink({
@ -26,6 +27,7 @@ export default function NavLink({
href, href,
iconMap, iconMap,
mode = 'expand', mode = 'expand',
disabled = false,
}: NavLinkProps) { }: NavLinkProps) {
const segment = useSelectedLayoutSegment() const segment = useSelectedLayoutSegment()
const formattedSegment = (() => { const formattedSegment = (() => {
@ -39,13 +41,38 @@ export default function NavLink({
const isActive = href.toLowerCase().split('/')?.pop() === formattedSegment const isActive = href.toLowerCase().split('/')?.pop() === formattedSegment
const NavIcon = isActive ? iconMap.selected : iconMap.normal const NavIcon = isActive ? iconMap.selected : iconMap.normal
if (disabled) {
return (
<button
key={name}
type='button'
disabled
className={classNames(
'opacity-30 text-components-menu-item-text hover:bg-state-base-hover group flex items-center h-9 rounded-md py-2 system-sm-medium cursor-not-allowed',
mode === 'expand' ? 'px-3' : 'px-2.5',
)}
title={mode === 'collapse' ? name : ''}
aria-disabled
>
<NavIcon
className={classNames(
'h-4 w-4 flex-shrink-0',
mode === 'expand' ? 'mr-2' : 'mr-0',
)}
aria-hidden="true"
/>
{mode === 'expand' && name}
</button>
)
}
return ( return (
<Link <Link
key={name} key={name}
href={href} href={href}
className={classNames( className={classNames(
isActive ? 'bg-state-accent-active text-text-accent font-semibold' : 'text-components-menu-item-text hover:bg-state-base-hover hover:text-components-menu-item-text-hover', isActive ? 'bg-state-accent-active text-text-accent font-semibold' : 'text-components-menu-item-text hover:bg-state-base-hover hover:text-components-menu-item-text-hover',
'group flex items-center h-9 rounded-md py-2 text-sm font-normal', 'group flex items-center h-9 rounded-md py-2 system-sm-medium',
mode === 'expand' ? 'px-3' : 'px-2.5', mode === 'expand' ? 'px-3' : 'px-2.5',
)} )}
title={mode === 'collapse' ? name : ''} title={mode === 'collapse' ? name : ''}

@ -27,7 +27,7 @@ import { DatasourceType } from '@/models/pipeline'
import { TransferMethod } from '@/types/app' import { TransferMethod } from '@/types/app'
import { useAddDocumentsSteps, useLocalFile, useNotionsPages, useWebsiteCrawl } from './hooks' import { useAddDocumentsSteps, useLocalFile, useNotionsPages, useWebsiteCrawl } from './hooks'
const TestRunPanel = () => { const CreateFormPipeline = () => {
const { t } = useTranslation() const { t } = useTranslation()
const plan = useProviderContextSelector(state => state.plan) const plan = useProviderContextSelector(state => state.plan)
const enableBilling = useProviderContextSelector(state => state.enableBilling) const enableBilling = useProviderContextSelector(state => state.enableBilling)
@ -348,4 +348,4 @@ const TestRunPanel = () => {
) )
} }
export default TestRunPanel export default CreateFormPipeline

@ -5,12 +5,10 @@ import OptionCard from '../option-card'
type ChunkStructureProps = { type ChunkStructureProps = {
chunkStructure: ChunkingMode chunkStructure: ChunkingMode
onChunkStructureChange: (value: ChunkingMode) => void
} }
const ChunkStructure = ({ const ChunkStructure = ({
chunkStructure, chunkStructure,
onChunkStructureChange,
}: ChunkStructureProps) => { }: ChunkStructureProps) => {
const { const {
options, options,
@ -27,9 +25,6 @@ const ChunkStructure = ({
iconActiveColor={option.iconActiveColor} iconActiveColor={option.iconActiveColor}
title={option.title} title={option.title}
description={option.description} description={option.description}
onClick={() => {
onChunkStructureChange(option.id)
}}
isActive={chunkStructure === option.id} isActive={chunkStructure === option.id}
effectColor={option.effectColor} effectColor={option.effectColor}
showEffectColor showEffectColor

@ -67,13 +67,12 @@ const Form = () => {
const [showAppIconPicker, setShowAppIconPicker] = useState(false) const [showAppIconPicker, setShowAppIconPicker] = useState(false)
const [description, setDescription] = useState(currentDataset?.description ?? '') const [description, setDescription] = useState(currentDataset?.description ?? '')
const [permission, setPermission] = useState(currentDataset?.permission) const [permission, setPermission] = useState(currentDataset?.permission)
const [chunkStructure, setChunkStructure] = useState(currentDataset?.doc_form ?? ChunkingMode.text)
const [topK, setTopK] = useState(currentDataset?.external_retrieval_model.top_k ?? 2) const [topK, setTopK] = useState(currentDataset?.external_retrieval_model.top_k ?? 2)
const [scoreThreshold, setScoreThreshold] = useState(currentDataset?.external_retrieval_model.score_threshold ?? 0.5) const [scoreThreshold, setScoreThreshold] = useState(currentDataset?.external_retrieval_model.score_threshold ?? 0.5)
const [scoreThresholdEnabled, setScoreThresholdEnabled] = useState(currentDataset?.external_retrieval_model.score_threshold_enabled ?? false) const [scoreThresholdEnabled, setScoreThresholdEnabled] = useState(currentDataset?.external_retrieval_model.score_threshold_enabled ?? false)
const [selectedMemberIDs, setSelectedMemberIDs] = useState<string[]>(currentDataset?.partial_member_list || []) const [selectedMemberIDs, setSelectedMemberIDs] = useState<string[]>(currentDataset?.partial_member_list || [])
const [memberList, setMemberList] = useState<Member[]>([]) const [memberList, setMemberList] = useState<Member[]>([])
const [indexMethod, setIndexMethod] = useState(currentDataset?.indexing_technique ?? IndexingType.QUALIFIED) const [indexMethod, setIndexMethod] = useState(currentDataset?.indexing_technique)
const [keywordNumber, setKeywordNumber] = useState(currentDataset?.keyword_number ?? 10) const [keywordNumber, setKeywordNumber] = useState(currentDataset?.keyword_number ?? 10)
const [retrievalConfig, setRetrievalConfig] = useState(currentDataset?.retrieval_model_dict as RetrievalConfig) const [retrievalConfig, setRetrievalConfig] = useState(currentDataset?.retrieval_model_dict as RetrievalConfig)
const [embeddingModel, setEmbeddingModel] = useState<DefaultModel>( const [embeddingModel, setEmbeddingModel] = useState<DefaultModel>(
@ -164,7 +163,7 @@ const Form = () => {
body: { body: {
name, name,
icon_info: iconInfo, icon_info: iconInfo,
doc_form: chunkStructure, doc_form: currentDataset?.doc_form,
description, description,
permission, permission,
indexing_technique: indexMethod, indexing_technique: indexMethod,
@ -209,7 +208,7 @@ const Form = () => {
} }
} }
const isShowIndexMethod = chunkStructure !== ChunkingMode.parentChild && currentDataset && currentDataset.indexing_technique const isShowIndexMethod = currentDataset && currentDataset.doc_form !== ChunkingMode.parentChild && currentDataset.indexing_technique && indexMethod
return ( return (
<div className='flex w-full flex-col gap-y-4 px-20 py-8 sm:w-[960px]'> <div className='flex w-full flex-col gap-y-4 px-20 py-8 sm:w-[960px]'>
@ -268,7 +267,7 @@ const Form = () => {
</div> </div>
</div> </div>
{ {
!currentDataset?.doc_form && ( currentDataset?.doc_form && (
<> <>
<Divider <Divider
type='horizontal' type='horizontal'
@ -294,8 +293,7 @@ const Form = () => {
</div> </div>
<div className='grow'> <div className='grow'>
<ChunkStructure <ChunkStructure
chunkStructure={chunkStructure!} chunkStructure={currentDataset?.doc_form}
onChunkStructureChange={setChunkStructure}
/> />
</div> </div>
</div> </div>

@ -36,8 +36,11 @@ const Publisher = () => {
}} }}
> >
<PortalToFollowElemTrigger onClick={() => handleOpenChange(!open)}> <PortalToFollowElemTrigger onClick={() => handleOpenChange(!open)}>
<Button variant='primary'> <Button
{t('workflow.common.publish')} className='px-2'
variant='primary'
>
<span className='pl-1'>{t('workflow.common.publish')}</span>
<RiArrowDownSLine className='h-4 w-4' /> <RiArrowDownSLine className='h-4 w-4' />
</Button> </Button>
</PortalToFollowElemTrigger> </PortalToFollowElemTrigger>

@ -125,6 +125,7 @@ const Popup = () => {
className='mb-1 w-full hover:bg-state-accent-hover hover:text-text-accent' className='mb-1 w-full hover:bg-state-accent-hover hover:text-text-accent'
variant='tertiary' variant='tertiary'
onClick={goToAddDocuments} onClick={goToAddDocuments}
disabled={!published}
> >
<div className='flex grow items-center'> <div className='flex grow items-center'>
<RiPlayCircleLine className='mr-2 h-4 w-4' /> <RiPlayCircleLine className='mr-2 h-4 w-4' />
@ -135,6 +136,7 @@ const Popup = () => {
<Button <Button
className='w-full hover:bg-state-accent-hover hover:text-text-accent' className='w-full hover:bg-state-accent-hover hover:text-text-accent'
variant='tertiary' variant='tertiary'
disabled={!published}
> >
<div className='flex grow items-center'> <div className='flex grow items-center'>
<RiTerminalBoxLine className='mr-2 h-4 w-4' /> <RiTerminalBoxLine className='mr-2 h-4 w-4' />

@ -81,6 +81,7 @@ export type DataSet = {
doc_metadata?: MetadataInDoc[] doc_metadata?: MetadataInDoc[]
keyword_number?: number keyword_number?: number
pipeline_id?: string pipeline_id?: string
is_published?: boolean // Indicates if the pipeline is published
} }
export type ExternalAPIItem = { export type ExternalAPIItem = {

Loading…
Cancel
Save