feat: plugin auto upgrade strategy (#19758)

Co-authored-by: Joel <iamjoel007@gmail.com>
Co-authored-by: crazywoola <427733928@qq.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Novice <novice12185727@gmail.com>
This commit is contained in:
Junyan Qin (Chin)
2025-07-23 15:33:39 +08:00
committed by GitHub
parent e6913744ae
commit eaae79a581
305 changed files with 2524 additions and 581 deletions

View File

@@ -4,18 +4,21 @@ import cn from '@/utils/classnames'
type OptionListItemProps = {
isSelected: boolean
onClick: () => void
noAutoScroll?: boolean
} & React.LiHTMLAttributes<HTMLLIElement>
const OptionListItem: FC<OptionListItemProps> = ({
isSelected,
onClick,
noAutoScroll,
children,
}) => {
const listItemRef = useRef<HTMLLIElement>(null)
useEffect(() => {
if (isSelected)
if (isSelected && !noAutoScroll)
listItemRef.current?.scrollIntoView({ behavior: 'instant' })
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
return (

View File

@@ -1,13 +1,18 @@
import React from 'react'
import { useTranslation } from 'react-i18next'
const Header = () => {
type Props = {
title?: string
}
const Header = ({
title,
}: Props) => {
const { t } = useTranslation()
return (
<div className='flex flex-col border-b-[0.5px] border-divider-regular'>
<div className='system-md-semibold flex items-center px-2 py-1.5 text-text-primary'>
{t('time.title.pickTime')}
{title || t('time.title.pickTime')}
</div>
</div>
)

View File

@@ -20,6 +20,9 @@ const TimePicker = ({
onChange,
onClear,
renderTrigger,
title,
minuteFilter,
popupClassName,
}: TimePickerProps) => {
const { t } = useTranslation()
const [isOpen, setIsOpen] = useState(false)
@@ -108,6 +111,15 @@ const TimePicker = ({
const displayValue = value?.format(timeFormat) || ''
const placeholderDate = isOpen && selectedTime ? selectedTime.format(timeFormat) : (placeholder || t('time.defaultPlaceholder'))
const inputElem = (
<input
className='system-xs-regular flex-1 cursor-pointer appearance-none truncate bg-transparent p-1
text-components-input-text-filled outline-none placeholder:text-components-input-text-placeholder'
readOnly
value={isOpen ? '' : displayValue}
placeholder={placeholderDate}
/>
)
return (
<PortalToFollowElem
open={isOpen}
@@ -115,18 +127,16 @@ const TimePicker = ({
placement='bottom-end'
>
<PortalToFollowElemTrigger>
{renderTrigger ? (renderTrigger()) : (
{renderTrigger ? (renderTrigger({
inputElem,
onClick: handleClickTrigger,
isOpen,
})) : (
<div
className='group flex w-[252px] cursor-pointer items-center gap-x-0.5 rounded-lg bg-components-input-bg-normal px-2 py-1 hover:bg-state-base-hover-alt'
onClick={handleClickTrigger}
>
<input
className='system-xs-regular flex-1 cursor-pointer appearance-none truncate bg-transparent p-1
text-components-input-text-filled outline-none placeholder:text-components-input-text-placeholder'
readOnly
value={isOpen ? '' : displayValue}
placeholder={placeholderDate}
/>
{inputElem}
<RiTimeLine className={cn(
'h-4 w-4 shrink-0 text-text-quaternary',
isOpen ? 'text-text-secondary' : 'group-hover:text-text-secondary',
@@ -142,14 +152,15 @@ const TimePicker = ({
</div>
)}
</PortalToFollowElemTrigger>
<PortalToFollowElemContent className='z-50'>
<PortalToFollowElemContent className={cn('z-50', popupClassName)}>
<div className='mt-1 w-[252px] rounded-xl border-[0.5px] border-components-panel-border bg-components-panel-bg shadow-lg shadow-shadow-shadow-5'>
{/* Header */}
<Header />
<Header title={title} />
{/* Time Options */}
<Options
selectedTime={selectedTime}
minuteFilter={minuteFilter}
handleSelectHour={handleSelectHour}
handleSelectMinute={handleSelectMinute}
handleSelectPeriod={handleSelectPeriod}

View File

@@ -5,6 +5,7 @@ import OptionListItem from '../common/option-list-item'
const Options: FC<TimeOptionsProps> = ({
selectedTime,
minuteFilter,
handleSelectHour,
handleSelectMinute,
handleSelectPeriod,
@@ -33,7 +34,7 @@ const Options: FC<TimeOptionsProps> = ({
{/* Minute */}
<ul className='no-scrollbar flex h-[208px] flex-col gap-y-0.5 overflow-y-auto pb-[184px]'>
{
minuteOptions.map((minute) => {
(minuteFilter ? minuteFilter(minuteOptions) : minuteOptions).map((minute) => {
const isSelected = selectedTime?.format('mm') === minute
return (
<OptionListItem
@@ -57,6 +58,7 @@ const Options: FC<TimeOptionsProps> = ({
key={period}
isSelected={isSelected}
onClick={handleSelectPeriod.bind(null, period)}
noAutoScroll // if choose PM which would hide(scrolled) AM that may make user confused that there's no am.
>
{period}
</OptionListItem>

View File

@@ -28,6 +28,7 @@ export type DatePickerProps = {
onClear: () => void
triggerWrapClassName?: string
renderTrigger?: (props: TriggerProps) => React.ReactNode
minuteFilter?: (minutes: string[]) => string[]
popupZIndexClassname?: string
}
@@ -47,13 +48,21 @@ export type DatePickerFooterProps = {
handleConfirmDate: () => void
}
export type TriggerParams = {
isOpen: boolean
inputElem: React.ReactNode
onClick: (e: React.MouseEvent) => void
}
export type TimePickerProps = {
value: Dayjs | undefined
timezone?: string
placeholder?: string
onChange: (date: Dayjs | undefined) => void
onClear: () => void
renderTrigger?: () => React.ReactNode
renderTrigger?: (props: TriggerParams) => React.ReactNode
title?: string
minuteFilter?: (minutes: string[]) => string[]
popupClassName?: string
}
export type TimePickerFooterProps = {
@@ -81,6 +90,7 @@ export type CalendarItemProps = {
export type TimeOptionsProps = {
selectedTime: Dayjs | undefined
minuteFilter?: (minutes: string[]) => string[]
handleSelectHour: (hour: string) => void
handleSelectMinute: (minute: string) => void
handleSelectPeriod: (period: Period) => void

View File

@@ -2,6 +2,7 @@ import dayjs, { type Dayjs } from 'dayjs'
import type { Day } from '../types'
import utc from 'dayjs/plugin/utc'
import timezone from 'dayjs/plugin/timezone'
import tz from '@/utils/timezone.json'
dayjs.extend(utc)
dayjs.extend(timezone)
@@ -78,3 +79,14 @@ export const getHourIn12Hour = (date: Dayjs) => {
export const getDateWithTimezone = (props: { date?: Dayjs, timezone?: string }) => {
return props.date ? dayjs.tz(props.date, props.timezone) : dayjs().tz(props.timezone)
}
// Asia/Shanghai -> UTC+8
const DEFAULT_OFFSET_STR = 'UTC+0'
export const convertTimezoneToOffsetStr = (timezone?: string) => {
if (!timezone)
return DEFAULT_OFFSET_STR
const tzItem = tz.find(item => item.value === timezone)
if(!tzItem)
return DEFAULT_OFFSET_STR
return `UTC${tzItem.name.charAt(0)}${tzItem.name.charAt(2)}`
}

View File

@@ -0,0 +1,7 @@
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M28.0049 16C28.0049 20.4183 24.4231 24 20.0049 24C15.5866 24 12.0049 20.4183 12.0049 16C12.0049 11.5817 15.5866 8 20.0049 8C24.4231 8 28.0049 11.5817 28.0049 16Z" stroke="#676F83" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M4.00488 16H6.67155" stroke="#676F83" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M4.00488 9.33334H8.00488" stroke="#676F83" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M4.00488 22.6667H8.00488" stroke="#676F83" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M26 22L29.3333 25.3333" stroke="#676F83" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 823 B

View File

@@ -0,0 +1,4 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.46257 4.43262C7.21556 2.91688 9.5007 2 12 2C17.5228 2 22 6.47715 22 12C22 14.1361 21.3302 16.1158 20.1892 17.7406L17 12H20C20 7.58172 16.4183 4 12 4C9.84982 4 7.89777 4.84827 6.46023 6.22842L5.46257 4.43262ZM18.5374 19.5674C16.7844 21.0831 14.4993 22 12 22C6.47715 22 2 17.5228 2 12C2 9.86386 2.66979 7.88416 3.8108 6.25944L7 12H4C4 16.4183 7.58172 20 12 20C14.1502 20 16.1022 19.1517 17.5398 17.7716L18.5374 19.5674Z" fill="black"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M16.3308 16H14.2915L13.6249 13.9476H10.3761L9.70846 16H7.66918L10.7759 7H13.2281L16.3308 16ZM10.8595 12.4622H13.1435L12.0378 9.05639H11.9673L10.8595 12.4622Z" fill="black"/>
</svg>

After

Width:  |  Height:  |  Size: 772 B

View File

@@ -75,7 +75,7 @@ Icon.displayName = '<%= svgName %>'
export default Icon
`.trim())
await writeFile(path.resolve(currentPath, `${fileName}.json`), JSON.stringify(svgData, '', '\t'))
await writeFile(path.resolve(currentPath, `${fileName}.json`), `${JSON.stringify(svgData, '', '\t')}\n`)
await writeFile(path.resolve(currentPath, `${fileName}.tsx`), `${componentRender({ svgName: fileName })}\n`)
const indexingRender = template(`

File diff suppressed because one or more lines are too long

View File

@@ -4,12 +4,16 @@
import * as React from 'react'
import data from './AliyunIcon.json'
import IconBase from '@/app/components/base/icons/IconBase'
import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase'
import type { 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} />)
const Icon = (
{
ref,
...props
}: React.SVGProps<SVGSVGElement> & {
ref?: React.RefObject<React.MutableRefObject<HTMLOrSVGElement>>;
},
) => <IconBase {...props} ref={ref} data={data as IconData} />
Icon.displayName = 'AliyunIcon'

File diff suppressed because one or more lines are too long

View File

@@ -4,12 +4,16 @@
import * as React from 'react'
import data from './AliyunIconBig.json'
import IconBase from '@/app/components/base/icons/IconBase'
import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase'
import type { 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} />)
const Icon = (
{
ref,
...props
}: React.SVGProps<SVGSVGElement> & {
ref?: React.RefObject<React.MutableRefObject<HTMLOrSVGElement>>;
},
) => <IconBase {...props} ref={ref} data={data as IconData} />
Icon.displayName = 'AliyunIconBig'

View File

@@ -4,12 +4,16 @@
import * as React from 'react'
import data from './WeaveIcon.json'
import IconBase from '@/app/components/base/icons/IconBase'
import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase'
import type { 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} />)
const Icon = (
{
ref,
...props
}: React.SVGProps<SVGSVGElement> & {
ref?: React.RefObject<React.MutableRefObject<HTMLOrSVGElement>>;
},
) => <IconBase {...props} ref={ref} data={data as IconData} />
Icon.displayName = 'WeaveIcon'

View File

@@ -4,12 +4,16 @@
import * as React from 'react'
import data from './WeaveIconBig.json'
import IconBase from '@/app/components/base/icons/IconBase'
import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase'
import type { 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} />)
const Icon = (
{
ref,
...props
}: React.SVGProps<SVGSVGElement> & {
ref?: React.RefObject<React.MutableRefObject<HTMLOrSVGElement>>;
},
) => <IconBase {...props} ref={ref} data={data as IconData} />
Icon.displayName = 'WeaveIconBig'

View File

@@ -1,3 +1,5 @@
export { default as AliyunIconBig } from './AliyunIconBig'
export { default as AliyunIcon } from './AliyunIcon'
export { default as ArizeIconBig } from './ArizeIconBig'
export { default as ArizeIcon } from './ArizeIcon'
export { default as LangfuseIconBig } from './LangfuseIconBig'
@@ -11,5 +13,3 @@ export { default as PhoenixIcon } from './PhoenixIcon'
export { default as TracingIcon } from './TracingIcon'
export { default as WeaveIconBig } from './WeaveIconBig'
export { default as WeaveIcon } from './WeaveIcon'
export { default as AliyunIconBig } from './AliyunIconBig'
export { default as AliyunIcon } from './AliyunIcon'

View File

@@ -23,4 +23,4 @@
]
},
"name": "Citations"
}
}

View File

@@ -25,4 +25,4 @@
]
},
"name": "ContentModeration"
}
}

View File

@@ -20,4 +20,4 @@
]
},
"name": "Document"
}
}

View File

@@ -23,4 +23,4 @@
]
},
"name": "FolderUpload"
}
}

View File

@@ -23,4 +23,4 @@
]
},
"name": "LoveMessage"
}
}

View File

@@ -25,4 +25,4 @@
]
},
"name": "MessageFast"
}
}

View File

@@ -34,4 +34,4 @@
]
},
"name": "Microphone01"
}
}

View File

@@ -74,4 +74,4 @@
]
},
"name": "TextToAudio"
}
}

View File

@@ -32,4 +32,4 @@
]
},
"name": "VirtualAssistant"
}
}

View File

@@ -25,4 +25,4 @@
]
},
"name": "Vision"
}
}

View File

@@ -36,4 +36,4 @@
]
},
"name": "AlertTriangle"
}
}

View File

@@ -63,4 +63,4 @@
]
},
"name": "ThumbsDown"
}
}

View File

@@ -63,4 +63,4 @@
]
},
"name": "ThumbsUp"
}
}

View File

@@ -26,4 +26,4 @@
]
},
"name": "ArrowNarrowLeft"
}
}

View File

@@ -36,4 +36,4 @@
]
},
"name": "ArrowUpRight"
}
}

View File

@@ -36,4 +36,4 @@
]
},
"name": "ChevronDownDouble"
}
}

View File

@@ -36,4 +36,4 @@
]
},
"name": "ChevronRight"
}
}

View File

@@ -26,4 +26,4 @@
]
},
"name": "ChevronSelectorVertical"
}
}

View File

@@ -26,4 +26,4 @@
]
},
"name": "RefreshCcw01"
}
}

View File

@@ -26,4 +26,4 @@
]
},
"name": "RefreshCw05"
}
}

View File

@@ -36,4 +36,4 @@
]
},
"name": "ReverseLeft"
}
}

View File

@@ -36,4 +36,4 @@
]
},
"name": "AiText"
}
}

View File

@@ -90,4 +90,4 @@
]
},
"name": "ChatBot"
}
}

View File

@@ -65,4 +65,4 @@
]
},
"name": "ChatBotSlim"
}
}

View File

@@ -36,4 +36,4 @@
]
},
"name": "CuteRobot"
}
}

View File

@@ -36,4 +36,4 @@
]
},
"name": "MessageCheckRemove"
}
}

View File

@@ -26,4 +26,4 @@
]
},
"name": "MessageFastPlus"
}
}

View File

@@ -26,4 +26,4 @@
]
},
"name": "ArtificialBrain"
}
}

View File

@@ -36,4 +36,4 @@
]
},
"name": "BarChartSquare02"
}
}

View File

@@ -26,4 +26,4 @@
]
},
"name": "BracketsX"
}
}

View File

@@ -36,4 +36,4 @@
]
},
"name": "CodeBrowser"
}
}

View File

@@ -26,4 +26,4 @@
]
},
"name": "Container"
}
}

View File

@@ -26,4 +26,4 @@
]
},
"name": "Database01"
}
}

View File

@@ -26,4 +26,4 @@
]
},
"name": "Database03"
}
}

View File

@@ -49,4 +49,4 @@
]
},
"name": "FileHeart02"
}
}

View File

@@ -36,4 +36,4 @@
]
},
"name": "GitBranch01"
}
}

View File

@@ -62,4 +62,4 @@
]
},
"name": "PromptEngineering"
}
}

View File

@@ -63,4 +63,4 @@
]
},
"name": "PuzzlePiece01"
}
}

View File

@@ -36,4 +36,4 @@
]
},
"name": "TerminalSquare"
}
}

View File

@@ -59,4 +59,4 @@
]
},
"name": "Variable"
}
}

View File

@@ -86,4 +86,4 @@
]
},
"name": "Webhooks"
}
}

View File

@@ -36,4 +36,4 @@
]
},
"name": "AlignLeft"
}
}

View File

@@ -35,4 +35,4 @@
]
},
"name": "BezierCurve03"
}
}

View File

@@ -59,4 +59,4 @@
]
},
"name": "Collapse"
}
}

View File

@@ -36,4 +36,4 @@
]
},
"name": "Colors"
}
}

View File

@@ -36,4 +36,4 @@
]
},
"name": "ImageIndentLeft"
}
}

View File

@@ -26,4 +26,4 @@
]
},
"name": "LeftIndent02"
}
}

View File

@@ -36,4 +36,4 @@
]
},
"name": "LetterSpacing01"
}
}

View File

@@ -35,4 +35,4 @@
]
},
"name": "TypeSquare"
}
}

View File

@@ -46,4 +46,4 @@
]
},
"name": "BookOpen01"
}
}

View File

@@ -36,4 +36,4 @@
]
},
"name": "File02"
}
}

View File

@@ -36,4 +36,4 @@
]
},
"name": "FileArrow01"
}
}

View File

@@ -36,4 +36,4 @@
]
},
"name": "FileCheck02"
}
}

View File

@@ -26,4 +26,4 @@
]
},
"name": "FileDownload02"
}
}

View File

@@ -36,4 +36,4 @@
]
},
"name": "FilePlus01"
}
}

View File

@@ -26,4 +26,4 @@
]
},
"name": "FilePlus02"
}
}

View File

@@ -36,4 +36,4 @@
]
},
"name": "FileText"
}
}

View File

@@ -49,4 +49,4 @@
]
},
"name": "FileUpload"
}
}

View File

@@ -36,4 +36,4 @@
]
},
"name": "Folder"
}
}

View File

@@ -26,4 +26,4 @@
]
},
"name": "Balance"
}
}

View File

@@ -36,4 +36,4 @@
]
},
"name": "CoinsStacked01"
}
}

View File

@@ -117,4 +117,4 @@
]
},
"name": "GoldCoin"
}
}

View File

@@ -26,4 +26,4 @@
]
},
"name": "ReceiptList"
}
}

View File

@@ -63,4 +63,4 @@
]
},
"name": "Tag01"
}
}

View File

@@ -36,4 +36,4 @@
]
},
"name": "Tag03"
}
}

View File

@@ -63,4 +63,4 @@
]
},
"name": "AtSign"
}
}

View File

@@ -26,4 +26,4 @@
]
},
"name": "Bookmark"
}
}

View File

@@ -36,4 +36,4 @@
]
},
"name": "Check"
}
}

View File

@@ -36,4 +36,4 @@
]
},
"name": "CheckDone01"
}
}

View File

@@ -33,4 +33,4 @@
]
},
"name": "ChecklistSquare"
}
}

View File

@@ -131,4 +131,4 @@
]
},
"name": "DotsGrid"
}
}

View File

@@ -63,4 +63,4 @@
]
},
"name": "Edit02"
}
}

View File

@@ -26,4 +26,4 @@
]
},
"name": "Edit04"
}
}

View File

@@ -63,4 +63,4 @@
]
},
"name": "Edit05"
}
}

View File

@@ -35,4 +35,4 @@
]
},
"name": "Hash02"
}
}

View File

@@ -63,4 +63,4 @@
]
},
"name": "InfoCircle"
}
}

View File

@@ -54,4 +54,4 @@
]
},
"name": "Link03"
}
}

View File

@@ -35,4 +35,4 @@
]
},
"name": "LinkExternal02"
}
}

View File

@@ -50,4 +50,4 @@
]
},
"name": "LogIn04"
}
}

View File

@@ -36,4 +36,4 @@
]
},
"name": "LogOut01"
}
}

View File

@@ -50,4 +50,4 @@
]
},
"name": "LogOut04"
}
}

View File

@@ -36,4 +36,4 @@
]
},
"name": "Menu01"
}
}

View File

@@ -36,4 +36,4 @@
]
},
"name": "Pin01"
}
}

View File

@@ -26,4 +26,4 @@
]
},
"name": "Pin02"
}
}

Some files were not shown because too many files have changed in this diff Show More