fix(timezone): fix UTC offset display bug and add timezone labels

- Fixed convertTimezoneToOffsetStr() that only extracted first digit
  * UTC-11 was incorrectly displayed as UTC-1, UTC+10 as UTC+0
  * Now correctly extracts full offset using regex and removes leading zeros
- Created reusable TimezoneLabel component with inline mode support
- Added comprehensive unit tests with 100% coverage
- Integrated timezone labels into 3 locations:
  * Panel time picker (next to time input)
  * Node next execution display
  * Panel next 5 executions list
This commit is contained in:
lyzno1
2025-10-13 16:27:45 +08:00
parent ee21b4d435
commit af6dae3498
6 changed files with 236 additions and 17 deletions

View File

@ -2,6 +2,7 @@ import React from 'react'
import { useTranslation } from 'react-i18next'
import type { ScheduleTriggerNodeType } from '../types'
import { getFormattedExecutionTimes } from '../utils/execution-time-calculator'
import TimezoneLabel from '@/app/components/base/timezone-label'
type NextExecutionTimesProps = {
data: ScheduleTriggerNodeType
@ -31,6 +32,8 @@ const NextExecutionTimes = ({ data }: NextExecutionTimesProps) => {
</span>
<span className="pl-2 pr-3 font-mono font-normal leading-[150%] tracking-wider text-text-secondary">
{time}
{' '}
<TimezoneLabel timezone={data.timezone} inline className="text-xs" />
</span>
</div>
))}

View File

@ -4,6 +4,7 @@ import { useTranslation } from 'react-i18next'
import type { ScheduleTriggerNodeType } from './types'
import type { NodeProps } from '@/app/components/workflow/types'
import { getNextExecutionTime } from './utils/execution-time-calculator'
import TimezoneLabel from '@/app/components/base/timezone-label'
const i18nPrefix = 'workflow.nodes.triggerSchedule'
@ -19,8 +20,10 @@ const Node: FC<NodeProps<ScheduleTriggerNodeType>> = ({
</div>
<div className="flex h-[26px] items-center rounded-md bg-workflow-block-parma-bg px-2 text-xs text-text-secondary">
<div className="w-0 grow">
<div className="truncate" title={getNextExecutionTime(data)}>
<div className="truncate" title={`${getNextExecutionTime(data)} ${data.timezone}`}>
{getNextExecutionTime(data)}
{' '}
<TimezoneLabel timezone={data.timezone} inline className="text-xs" />
</div>
</div>
</div>

View File

@ -12,6 +12,7 @@ import NextExecutionTimes from './components/next-execution-times'
import MonthlyDaysSelector from './components/monthly-days-selector'
import OnMinuteSelector from './components/on-minute-selector'
import Input from '@/app/components/base/input'
import TimezoneLabel from '@/app/components/base/timezone-label'
import useConfig from './use-config'
const i18nPrefix = 'workflow.nodes.triggerSchedule'
@ -69,21 +70,24 @@ const Panel: FC<NodePanelProps<ScheduleTriggerNodeType>> = ({
<label className="mb-2 block text-xs font-medium text-gray-500">
{t('workflow.nodes.triggerSchedule.time')}
</label>
<TimePicker
notClearable={true}
timezone={inputs.timezone}
value={inputs.visual_config?.time || '12:00 AM'}
onChange={(time) => {
if (time) {
const timeString = time.format('h:mm A')
handleTimeChange(timeString)
}
}}
onClear={() => {
handleTimeChange('12:00 AM')
}}
placeholder={t('workflow.nodes.triggerSchedule.selectTime')}
/>
<div className="flex items-center gap-2">
<TimePicker
notClearable={true}
timezone={inputs.timezone}
value={inputs.visual_config?.time || '12:00 AM'}
onChange={(time) => {
if (time) {
const timeString = time.format('h:mm A')
handleTimeChange(timeString)
}
}}
onClear={() => {
handleTimeChange('12:00 AM')
}}
placeholder={t('workflow.nodes.triggerSchedule.selectTime')}
/>
<TimezoneLabel timezone={inputs.timezone} />
</div>
</>
)}
</div>