Merge remote-tracking branch 'origin/main' into feat/queue-based-graph-engine

This commit is contained in:
-LAN-
2025-08-29 17:01:42 +08:00
74 changed files with 1595 additions and 145 deletions

View File

@ -4,6 +4,7 @@ import {
FloatingPortal,
autoUpdate,
flip,
hide,
offset,
shift,
size,
@ -39,7 +40,7 @@ export function usePortalToFollowElem({
triggerPopupSameWidth,
}: PortalToFollowElemOptions = {}) {
const setOpen = setControlledOpen
const container = document.getElementById('workflow-container') || document.body
const data = useFloating({
placement,
open,
@ -50,9 +51,17 @@ export function usePortalToFollowElem({
flip({
crossAxis: placement.includes('-'),
fallbackAxisSideDirection: 'start',
padding: 5,
padding: 8,
}),
shift({
padding: 8,
boundary: container,
altBoundary: true,
}),
hide({
// hide when the reference element is not visible
boundary: container,
}),
shift({ padding: 5 }),
size({
apply({ rects, elements }) {
if (triggerPopupSameWidth)
@ -133,9 +142,9 @@ export const PortalToFollowElemTrigger = (
context.getReferenceProps({
ref,
...props,
...children.props,
...(children.props || {}),
'data-state': context.open ? 'open' : 'closed',
}),
} as React.HTMLProps<HTMLElement>),
)
}
@ -177,6 +186,7 @@ export const PortalToFollowElemContent = (
style={{
...context.floatingStyles,
...style,
visibility: context.middlewareData.hide?.referenceHidden ? 'hidden' : 'visible',
}}
{...context.getFloatingProps(props)}
/>

View File

@ -14,6 +14,7 @@ type TagInputProps = {
customizedConfirmKey?: 'Enter' | 'Tab'
isInWorkflow?: boolean
placeholder?: string
required?: boolean
}
const TagInput: FC<TagInputProps> = ({
@ -24,6 +25,7 @@ const TagInput: FC<TagInputProps> = ({
customizedConfirmKey = 'Enter',
isInWorkflow,
placeholder,
required = false,
}) => {
const { t } = useTranslation()
const { notify } = useToastContext()
@ -42,7 +44,8 @@ const TagInput: FC<TagInputProps> = ({
const handleNewTag = useCallback((value: string) => {
const valueTrimmed = value.trim()
if (!valueTrimmed) {
notify({ type: 'error', message: t('datasetDocuments.segment.keywordEmpty') })
if (required)
notify({ type: 'error', message: t('datasetDocuments.segment.keywordEmpty') })
return
}
@ -60,7 +63,7 @@ const TagInput: FC<TagInputProps> = ({
setTimeout(() => {
setValue('')
})
}, [items, onChange, notify, t])
}, [items, onChange, notify, t, required])
const handleKeyDown = (e: KeyboardEvent) => {
if (isSpecialMode && e.key === 'Enter')

View File

@ -56,12 +56,11 @@ const Toast = ({
'top-0',
'right-0',
)}>
<div className={`absolute inset-0 -z-10 opacity-40 ${
(type === 'success' && 'bg-toast-success-bg')
<div className={`absolute inset-0 -z-10 opacity-40 ${(type === 'success' && 'bg-toast-success-bg')
|| (type === 'warning' && 'bg-toast-warning-bg')
|| (type === 'error' && 'bg-toast-error-bg')
|| (type === 'info' && 'bg-toast-info-bg')
}`}
}`}
/>
<div className={`flex ${size === 'md' ? 'gap-1' : 'gap-0.5'}`}>
<div className={`flex items-center justify-center ${size === 'md' ? 'p-0.5' : 'p-1'}`}>
@ -162,7 +161,9 @@ Toast.notify = ({
</ToastContext.Provider>,
)
document.body.appendChild(holder)
setTimeout(toastHandler.clear, duration || defaultDuring)
const d = duration ?? defaultDuring
if (d > 0)
setTimeout(toastHandler.clear, d)
}
return toastHandler

View File

@ -236,6 +236,7 @@ const ParameterItem: FC<ParameterItemProps> = ({
onChange={handleTagChange}
customizedConfirmKey='Tab'
isInWorkflow={isInWorkflow}
required={parameterRule.required}
/>
</div>
)

View File

@ -9,6 +9,7 @@ import {
EDUCATION_VERIFYING_LOCALSTORAGE_ITEM,
EDUCATION_VERIFY_URL_SEARCHPARAMS_ACTION,
} from '@/app/education-apply/constants'
import { resolvePostLoginRedirect } from '../signin/utils/post-login-redirect'
type SwrInitializerProps = {
children: ReactNode
@ -63,7 +64,11 @@ const SwrInitializer = ({
if (searchParams.has('access_token') || searchParams.has('refresh_token')) {
consoleToken && localStorage.setItem('console_token', consoleToken)
refreshToken && localStorage.setItem('refresh_token', refreshToken)
router.replace(pathname)
const redirectUrl = resolvePostLoginRedirect(searchParams)
if (redirectUrl)
location.replace(redirectUrl)
else
router.replace(pathname)
}
setInit(true)

View File

@ -38,7 +38,7 @@ const Field: FC<Props> = ({
<div className={cn(className, inline && 'flex w-full items-center justify-between')}>
<div
onClick={() => supportFold && toggleFold()}
className={cn('flex items-center justify-between', supportFold && 'cursor-pointer')}>
className={cn('sticky top-0 z-10 flex items-center justify-between bg-components-panel-bg', supportFold && 'cursor-pointer')}>
<div className='flex h-6 items-center'>
<div className={cn(isSubTitle ? 'system-xs-medium-uppercase text-text-tertiary' : 'system-sm-semibold-uppercase text-text-secondary')}>
{title} {required && <span className='text-text-destructive'>*</span>}

View File

@ -418,9 +418,8 @@ const BasePanel: FC<BasePanelProps> = ({
}
<Split />
</div>
{tabType === TabType.settings && (
<>
<div className='flex-1 overflow-y-auto'>
<div>
{cloneElement(children as any, {
id,
@ -465,7 +464,7 @@ const BasePanel: FC<BasePanelProps> = ({
</div>
)
}
</>
</div>
)}
{tabType === TabType.lastRun && (