From 95ce7b6f47b2f03db1f93cb0fd727d9a67136fbe Mon Sep 17 00:00:00 2001 From: Joel Date: Thu, 10 Jul 2025 11:34:05 +0800 Subject: [PATCH] feat: add time zone --- .../time-picker/index.tsx | 23 ++++--- .../base/date-and-time-picker/types.ts | 7 +- .../base/date-and-time-picker/utils/dayjs.ts | 12 ++++ .../auto-update-setting/index.tsx | 67 ++++++++++++++++--- web/i18n/en-US/plugin.ts | 2 + web/i18n/zh-Hans/plugin.ts | 2 + 6 files changed, 93 insertions(+), 20 deletions(-) diff --git a/web/app/components/base/date-and-time-picker/time-picker/index.tsx b/web/app/components/base/date-and-time-picker/time-picker/index.tsx index 7a6f9f94fd..d493106667 100644 --- a/web/app/components/base/date-and-time-picker/time-picker/index.tsx +++ b/web/app/components/base/date-and-time-picker/time-picker/index.tsx @@ -111,6 +111,15 @@ const TimePicker = ({ const displayValue = value?.format(timeFormat) || '' const placeholderDate = isOpen && selectedTime ? selectedTime.format(timeFormat) : (placeholder || t('time.defaultPlaceholder')) + const inputElem = ( + + ) return ( - {renderTrigger ? (renderTrigger()) : ( + {renderTrigger ? (renderTrigger({ + inputElem, + onClick: handleClickTrigger, + isOpen, + })) : (
- + {inputElem} 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 diff --git a/web/app/components/base/date-and-time-picker/utils/dayjs.ts b/web/app/components/base/date-and-time-picker/utils/dayjs.ts index 0928fa5d58..4ba6af3f58 100644 --- a/web/app/components/base/date-and-time-picker/utils/dayjs.ts +++ b/web/app/components/base/date-and-time-picker/utils/dayjs.ts @@ -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)}` +} diff --git a/web/app/components/plugins/reference-setting-modal/auto-update-setting/index.tsx b/web/app/components/plugins/reference-setting-modal/auto-update-setting/index.tsx index 3a8d148c34..a4875fc11b 100644 --- a/web/app/components/plugins/reference-setting-modal/auto-update-setting/index.tsx +++ b/web/app/components/plugins/reference-setting-modal/auto-update-setting/index.tsx @@ -4,12 +4,17 @@ import React, { useCallback, useMemo } from 'react' import { AUTO_UPDATE_MODE, AUTO_UPDATE_STRATEGY, type AutoUpdateConfig } from './types' import Label from '../label' import StrategyPicker from './strategy-picker' -import { useTranslation } from 'react-i18next' +import { Trans, useTranslation } from 'react-i18next' import TimePicker from '@/app/components/base/date-and-time-picker/time-picker' import OptionCard from '@/app/components/workflow/nodes/_base/components/option-card' import PluginsPicker from './plugins-picker' import { convertLocalSecondsToUTCDaySeconds, convertUTCDaySecondsToLocalSeconds, dayjsToTimeOfDay, timeOfDayToDayjs } from './utils' import { useAppContext } from '@/context/app-context' +import type { TriggerParams } from '@/app/components/base/date-and-time-picker/types' +import { RiTimeLine } from '@remixicon/react' +import cn from '@/utils/classnames' +import { convertTimezoneToOffsetStr } from '@/app/components/base/date-and-time-picker/utils/dayjs' +import { useModalContextSelector } from '@/context/modal-context' const i18nPrefix = 'plugin.autoUpdate' @@ -18,6 +23,16 @@ type Props = { onChange: (payload: AutoUpdateConfig) => void } +const SettingTimeZone: FC<{ + children?: React.ReactNode +}> = ({ + children, +}) => { + const setShowAccountSettingModal = useModalContextSelector(s => s.setShowAccountSettingModal) + return ( + setShowAccountSettingModal({ payload: 'language' })} >{children} + ) +} const AutoUpdateSetting: FC = ({ payload, onChange, @@ -83,10 +98,29 @@ const AutoUpdateSetting: FC = ({ }) } }, [payload, onChange]) + + const renderTimePickerTrigger = useCallback(({ inputElem, onClick, isOpen }: TriggerParams) => { + return ( +
+
+ + {inputElem} +
+
{convertTimezoneToOffsetStr(timezone)}
+
+ ) + }, [timezone]) + return (
-
Updates Settings
+
{t(`${i18nPrefix}.updateSettings`)}
@@ -99,15 +133,26 @@ const AutoUpdateSetting: FC = ({ <>