From c7e20df516bf3a991ce46c937223948bcdb6b8f0 Mon Sep 17 00:00:00 2001 From: moonrailgun Date: Sun, 20 Oct 2024 22:47:22 +0800 Subject: [PATCH] feat: add timezone support #114 --- src/client/routes/settings/workspace.tsx | 63 +- .../utils/__snapshots__/date.spec.ts.snap | 1678 +++++++++++++++++ src/client/utils/date.spec.ts | 10 + src/client/utils/date.ts | 22 + src/server/init.ts | 6 + src/server/model/monitor/manager.ts | 37 +- src/server/model/monitor/runner.ts | 25 +- src/server/model/monitor/types.ts | 5 + src/server/trpc/routers/monitor.ts | 2 +- src/server/trpc/routers/workspace.ts | 9 + 10 files changed, 1838 insertions(+), 19 deletions(-) create mode 100644 src/client/utils/__snapshots__/date.spec.ts.snap create mode 100644 src/client/utils/date.spec.ts create mode 100644 src/server/model/monitor/types.ts diff --git a/src/client/routes/settings/workspace.tsx b/src/client/routes/settings/workspace.tsx index c2b868d..67ab2b3 100644 --- a/src/client/routes/settings/workspace.tsx +++ b/src/client/routes/settings/workspace.tsx @@ -38,13 +38,22 @@ import { } from '@/components/ui/form'; import { useForm } from 'react-hook-form'; import { Button } from '@/components/ui/button'; -import { useEventWithLoading } from '@/hooks/useEvent'; +import { useEvent, useEventWithLoading } from '@/hooks/useEvent'; import { zodResolver } from '@hookform/resolvers/zod'; import { z } from 'zod'; import { AlertConfirm } from '@/components/AlertConfirm'; import { ROLES } from '@tianji/shared'; import { cn } from '@/utils/style'; import { Separator } from '@/components/ui/separator'; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from '@/components/ui/select'; +import dayjs from 'dayjs'; +import { getTimezoneList } from '@/utils/date'; export const Route = createFileRoute('/settings/workspace')({ beforeLoad: routeAuthBeforeLoad, @@ -62,7 +71,7 @@ const columnHelper = createColumnHelper(); function PageComponent() { const { t } = useTranslation(); - const { id: workspaceId, name, role } = useCurrentWorkspace(); + const { id: workspaceId, name, role, settings } = useCurrentWorkspace(); const hasAdminPermission = useHasAdminPermission(); const { data: members = [], refetch: refetchMembers } = trpc.workspace.members.useQuery({ @@ -71,6 +80,9 @@ function PageComponent() { const updateCurrentWorkspaceName = useUserStore( (state) => state.updateCurrentWorkspaceName ); + const updateCurrentWorkspaceSettings = useUserStore( + (state) => state.updateCurrentWorkspaceSettings + ); const form = useForm({ resolver: zodResolver(inviteFormSchema), defaultValues: { @@ -89,6 +101,10 @@ function PageComponent() { onSuccess: defaultSuccessHandler, onError: defaultErrorHandler, }); + const updateSettings = trpc.workspace.updateSettings.useMutation({ + onSuccess: defaultSuccessHandler, + onError: defaultErrorHandler, + }); const [renameWorkspaceName, setRenameWorkspaceName] = useState(''); const [handleRename, isRenameLoading] = useEventWithLoading(async () => { @@ -112,6 +128,19 @@ function PageComponent() { } ); + const handleUpdateSettings = useEvent(async (key: string, value: string) => { + const { settings } = await updateSettings.mutateAsync({ + workspaceId, + settings: { + [key]: value, + }, + }); + + updateCurrentWorkspaceSettings(settings); + }); + + const timezoneList = useMemo(() => getTimezoneList(), []); + const columns = useMemo(() => { return [ columnHelper.accessor( @@ -167,6 +196,36 @@ function PageComponent() { + + + {t('General')} + + +
+
{t('Timezone')}
+
+ +
+
+
+
+
should return timezone list with correct labels and values 1`] = ` +[ + { + "label": "Africa/Abidjan (+00:00)", + "value": "Africa/Abidjan", + }, + { + "label": "Africa/Accra (+00:00)", + "value": "Africa/Accra", + }, + { + "label": "Africa/Addis_Ababa (+03:00)", + "value": "Africa/Addis_Ababa", + }, + { + "label": "Africa/Algiers (+01:00)", + "value": "Africa/Algiers", + }, + { + "label": "Africa/Asmera (+03:00)", + "value": "Africa/Asmera", + }, + { + "label": "Africa/Bamako (+00:00)", + "value": "Africa/Bamako", + }, + { + "label": "Africa/Bangui (+01:00)", + "value": "Africa/Bangui", + }, + { + "label": "Africa/Banjul (+00:00)", + "value": "Africa/Banjul", + }, + { + "label": "Africa/Bissau (+00:00)", + "value": "Africa/Bissau", + }, + { + "label": "Africa/Blantyre (+02:00)", + "value": "Africa/Blantyre", + }, + { + "label": "Africa/Brazzaville (+01:00)", + "value": "Africa/Brazzaville", + }, + { + "label": "Africa/Bujumbura (+02:00)", + "value": "Africa/Bujumbura", + }, + { + "label": "Africa/Cairo (+03:00)", + "value": "Africa/Cairo", + }, + { + "label": "Africa/Casablanca (+01:00)", + "value": "Africa/Casablanca", + }, + { + "label": "Africa/Ceuta (+02:00)", + "value": "Africa/Ceuta", + }, + { + "label": "Africa/Conakry (+00:00)", + "value": "Africa/Conakry", + }, + { + "label": "Africa/Dakar (+00:00)", + "value": "Africa/Dakar", + }, + { + "label": "Africa/Dar_es_Salaam (+03:00)", + "value": "Africa/Dar_es_Salaam", + }, + { + "label": "Africa/Djibouti (+03:00)", + "value": "Africa/Djibouti", + }, + { + "label": "Africa/Douala (+01:00)", + "value": "Africa/Douala", + }, + { + "label": "Africa/El_Aaiun (+01:00)", + "value": "Africa/El_Aaiun", + }, + { + "label": "Africa/Freetown (+00:00)", + "value": "Africa/Freetown", + }, + { + "label": "Africa/Gaborone (+02:00)", + "value": "Africa/Gaborone", + }, + { + "label": "Africa/Harare (+02:00)", + "value": "Africa/Harare", + }, + { + "label": "Africa/Johannesburg (+02:00)", + "value": "Africa/Johannesburg", + }, + { + "label": "Africa/Juba (+02:00)", + "value": "Africa/Juba", + }, + { + "label": "Africa/Kampala (+03:00)", + "value": "Africa/Kampala", + }, + { + "label": "Africa/Khartoum (+02:00)", + "value": "Africa/Khartoum", + }, + { + "label": "Africa/Kigali (+02:00)", + "value": "Africa/Kigali", + }, + { + "label": "Africa/Kinshasa (+01:00)", + "value": "Africa/Kinshasa", + }, + { + "label": "Africa/Lagos (+01:00)", + "value": "Africa/Lagos", + }, + { + "label": "Africa/Libreville (+01:00)", + "value": "Africa/Libreville", + }, + { + "label": "Africa/Lome (+00:00)", + "value": "Africa/Lome", + }, + { + "label": "Africa/Luanda (+01:00)", + "value": "Africa/Luanda", + }, + { + "label": "Africa/Lubumbashi (+02:00)", + "value": "Africa/Lubumbashi", + }, + { + "label": "Africa/Lusaka (+02:00)", + "value": "Africa/Lusaka", + }, + { + "label": "Africa/Malabo (+01:00)", + "value": "Africa/Malabo", + }, + { + "label": "Africa/Maputo (+02:00)", + "value": "Africa/Maputo", + }, + { + "label": "Africa/Maseru (+02:00)", + "value": "Africa/Maseru", + }, + { + "label": "Africa/Mbabane (+02:00)", + "value": "Africa/Mbabane", + }, + { + "label": "Africa/Mogadishu (+03:00)", + "value": "Africa/Mogadishu", + }, + { + "label": "Africa/Monrovia (+00:00)", + "value": "Africa/Monrovia", + }, + { + "label": "Africa/Nairobi (+03:00)", + "value": "Africa/Nairobi", + }, + { + "label": "Africa/Ndjamena (+01:00)", + "value": "Africa/Ndjamena", + }, + { + "label": "Africa/Niamey (+01:00)", + "value": "Africa/Niamey", + }, + { + "label": "Africa/Nouakchott (+00:00)", + "value": "Africa/Nouakchott", + }, + { + "label": "Africa/Ouagadougou (+00:00)", + "value": "Africa/Ouagadougou", + }, + { + "label": "Africa/Porto-Novo (+01:00)", + "value": "Africa/Porto-Novo", + }, + { + "label": "Africa/Sao_Tome (+00:00)", + "value": "Africa/Sao_Tome", + }, + { + "label": "Africa/Tripoli (+02:00)", + "value": "Africa/Tripoli", + }, + { + "label": "Africa/Tunis (+01:00)", + "value": "Africa/Tunis", + }, + { + "label": "Africa/Windhoek (+02:00)", + "value": "Africa/Windhoek", + }, + { + "label": "America/Adak (-09:00)", + "value": "America/Adak", + }, + { + "label": "America/Anchorage (-08:00)", + "value": "America/Anchorage", + }, + { + "label": "America/Anguilla (-04:00)", + "value": "America/Anguilla", + }, + { + "label": "America/Antigua (-04:00)", + "value": "America/Antigua", + }, + { + "label": "America/Araguaina (-03:00)", + "value": "America/Araguaina", + }, + { + "label": "America/Argentina/La_Rioja (-03:00)", + "value": "America/Argentina/La_Rioja", + }, + { + "label": "America/Argentina/Rio_Gallegos (-03:00)", + "value": "America/Argentina/Rio_Gallegos", + }, + { + "label": "America/Argentina/Salta (-03:00)", + "value": "America/Argentina/Salta", + }, + { + "label": "America/Argentina/San_Juan (-03:00)", + "value": "America/Argentina/San_Juan", + }, + { + "label": "America/Argentina/San_Luis (-03:00)", + "value": "America/Argentina/San_Luis", + }, + { + "label": "America/Argentina/Tucuman (-03:00)", + "value": "America/Argentina/Tucuman", + }, + { + "label": "America/Argentina/Ushuaia (-03:00)", + "value": "America/Argentina/Ushuaia", + }, + { + "label": "America/Aruba (-04:00)", + "value": "America/Aruba", + }, + { + "label": "America/Asuncion (-03:00)", + "value": "America/Asuncion", + }, + { + "label": "America/Bahia (-03:00)", + "value": "America/Bahia", + }, + { + "label": "America/Bahia_Banderas (-06:00)", + "value": "America/Bahia_Banderas", + }, + { + "label": "America/Barbados (-04:00)", + "value": "America/Barbados", + }, + { + "label": "America/Belem (-03:00)", + "value": "America/Belem", + }, + { + "label": "America/Belize (-06:00)", + "value": "America/Belize", + }, + { + "label": "America/Blanc-Sablon (-04:00)", + "value": "America/Blanc-Sablon", + }, + { + "label": "America/Boa_Vista (-04:00)", + "value": "America/Boa_Vista", + }, + { + "label": "America/Bogota (-05:00)", + "value": "America/Bogota", + }, + { + "label": "America/Boise (-06:00)", + "value": "America/Boise", + }, + { + "label": "America/Buenos_Aires (-03:00)", + "value": "America/Buenos_Aires", + }, + { + "label": "America/Cambridge_Bay (-06:00)", + "value": "America/Cambridge_Bay", + }, + { + "label": "America/Campo_Grande (-04:00)", + "value": "America/Campo_Grande", + }, + { + "label": "America/Cancun (-05:00)", + "value": "America/Cancun", + }, + { + "label": "America/Caracas (-04:00)", + "value": "America/Caracas", + }, + { + "label": "America/Catamarca (-03:00)", + "value": "America/Catamarca", + }, + { + "label": "America/Cayenne (-03:00)", + "value": "America/Cayenne", + }, + { + "label": "America/Cayman (-05:00)", + "value": "America/Cayman", + }, + { + "label": "America/Chicago (-05:00)", + "value": "America/Chicago", + }, + { + "label": "America/Chihuahua (-06:00)", + "value": "America/Chihuahua", + }, + { + "label": "America/Ciudad_Juarez (-06:00)", + "value": "America/Ciudad_Juarez", + }, + { + "label": "America/Coral_Harbour (-05:00)", + "value": "America/Coral_Harbour", + }, + { + "label": "America/Cordoba (-03:00)", + "value": "America/Cordoba", + }, + { + "label": "America/Costa_Rica (-06:00)", + "value": "America/Costa_Rica", + }, + { + "label": "America/Creston (-07:00)", + "value": "America/Creston", + }, + { + "label": "America/Cuiaba (-04:00)", + "value": "America/Cuiaba", + }, + { + "label": "America/Curacao (-04:00)", + "value": "America/Curacao", + }, + { + "label": "America/Danmarkshavn (+00:00)", + "value": "America/Danmarkshavn", + }, + { + "label": "America/Dawson (-07:00)", + "value": "America/Dawson", + }, + { + "label": "America/Dawson_Creek (-07:00)", + "value": "America/Dawson_Creek", + }, + { + "label": "America/Denver (-06:00)", + "value": "America/Denver", + }, + { + "label": "America/Detroit (-04:00)", + "value": "America/Detroit", + }, + { + "label": "America/Dominica (-04:00)", + "value": "America/Dominica", + }, + { + "label": "America/Edmonton (-06:00)", + "value": "America/Edmonton", + }, + { + "label": "America/Eirunepe (-05:00)", + "value": "America/Eirunepe", + }, + { + "label": "America/El_Salvador (-06:00)", + "value": "America/El_Salvador", + }, + { + "label": "America/Fort_Nelson (-07:00)", + "value": "America/Fort_Nelson", + }, + { + "label": "America/Fortaleza (-03:00)", + "value": "America/Fortaleza", + }, + { + "label": "America/Glace_Bay (-03:00)", + "value": "America/Glace_Bay", + }, + { + "label": "America/Godthab (-01:00)", + "value": "America/Godthab", + }, + { + "label": "America/Goose_Bay (-03:00)", + "value": "America/Goose_Bay", + }, + { + "label": "America/Grand_Turk (-04:00)", + "value": "America/Grand_Turk", + }, + { + "label": "America/Grenada (-04:00)", + "value": "America/Grenada", + }, + { + "label": "America/Guadeloupe (-04:00)", + "value": "America/Guadeloupe", + }, + { + "label": "America/Guatemala (-06:00)", + "value": "America/Guatemala", + }, + { + "label": "America/Guayaquil (-05:00)", + "value": "America/Guayaquil", + }, + { + "label": "America/Guyana (-04:00)", + "value": "America/Guyana", + }, + { + "label": "America/Halifax (-03:00)", + "value": "America/Halifax", + }, + { + "label": "America/Havana (-04:00)", + "value": "America/Havana", + }, + { + "label": "America/Hermosillo (-07:00)", + "value": "America/Hermosillo", + }, + { + "label": "America/Indiana/Knox (-05:00)", + "value": "America/Indiana/Knox", + }, + { + "label": "America/Indiana/Marengo (-04:00)", + "value": "America/Indiana/Marengo", + }, + { + "label": "America/Indiana/Petersburg (-04:00)", + "value": "America/Indiana/Petersburg", + }, + { + "label": "America/Indiana/Tell_City (-05:00)", + "value": "America/Indiana/Tell_City", + }, + { + "label": "America/Indiana/Vevay (-04:00)", + "value": "America/Indiana/Vevay", + }, + { + "label": "America/Indiana/Vincennes (-04:00)", + "value": "America/Indiana/Vincennes", + }, + { + "label": "America/Indiana/Winamac (-04:00)", + "value": "America/Indiana/Winamac", + }, + { + "label": "America/Indianapolis (-04:00)", + "value": "America/Indianapolis", + }, + { + "label": "America/Inuvik (-06:00)", + "value": "America/Inuvik", + }, + { + "label": "America/Iqaluit (-04:00)", + "value": "America/Iqaluit", + }, + { + "label": "America/Jamaica (-05:00)", + "value": "America/Jamaica", + }, + { + "label": "America/Jujuy (-03:00)", + "value": "America/Jujuy", + }, + { + "label": "America/Juneau (-08:00)", + "value": "America/Juneau", + }, + { + "label": "America/Kentucky/Monticello (-04:00)", + "value": "America/Kentucky/Monticello", + }, + { + "label": "America/Kralendijk (-04:00)", + "value": "America/Kralendijk", + }, + { + "label": "America/La_Paz (-04:00)", + "value": "America/La_Paz", + }, + { + "label": "America/Lima (-05:00)", + "value": "America/Lima", + }, + { + "label": "America/Los_Angeles (-07:00)", + "value": "America/Los_Angeles", + }, + { + "label": "America/Louisville (-04:00)", + "value": "America/Louisville", + }, + { + "label": "America/Lower_Princes (-04:00)", + "value": "America/Lower_Princes", + }, + { + "label": "America/Maceio (-03:00)", + "value": "America/Maceio", + }, + { + "label": "America/Managua (-06:00)", + "value": "America/Managua", + }, + { + "label": "America/Manaus (-04:00)", + "value": "America/Manaus", + }, + { + "label": "America/Marigot (-04:00)", + "value": "America/Marigot", + }, + { + "label": "America/Martinique (-04:00)", + "value": "America/Martinique", + }, + { + "label": "America/Matamoros (-05:00)", + "value": "America/Matamoros", + }, + { + "label": "America/Mazatlan (-07:00)", + "value": "America/Mazatlan", + }, + { + "label": "America/Mendoza (-03:00)", + "value": "America/Mendoza", + }, + { + "label": "America/Menominee (-05:00)", + "value": "America/Menominee", + }, + { + "label": "America/Merida (-06:00)", + "value": "America/Merida", + }, + { + "label": "America/Metlakatla (-08:00)", + "value": "America/Metlakatla", + }, + { + "label": "America/Mexico_City (-06:00)", + "value": "America/Mexico_City", + }, + { + "label": "America/Miquelon (-02:00)", + "value": "America/Miquelon", + }, + { + "label": "America/Moncton (-03:00)", + "value": "America/Moncton", + }, + { + "label": "America/Monterrey (-06:00)", + "value": "America/Monterrey", + }, + { + "label": "America/Montevideo (-03:00)", + "value": "America/Montevideo", + }, + { + "label": "America/Montserrat (-04:00)", + "value": "America/Montserrat", + }, + { + "label": "America/Nassau (-04:00)", + "value": "America/Nassau", + }, + { + "label": "America/New_York (-04:00)", + "value": "America/New_York", + }, + { + "label": "America/Nome (-08:00)", + "value": "America/Nome", + }, + { + "label": "America/Noronha (-02:00)", + "value": "America/Noronha", + }, + { + "label": "America/North_Dakota/Beulah (-05:00)", + "value": "America/North_Dakota/Beulah", + }, + { + "label": "America/North_Dakota/Center (-05:00)", + "value": "America/North_Dakota/Center", + }, + { + "label": "America/North_Dakota/New_Salem (-05:00)", + "value": "America/North_Dakota/New_Salem", + }, + { + "label": "America/Ojinaga (-05:00)", + "value": "America/Ojinaga", + }, + { + "label": "America/Panama (-05:00)", + "value": "America/Panama", + }, + { + "label": "America/Paramaribo (-03:00)", + "value": "America/Paramaribo", + }, + { + "label": "America/Phoenix (-07:00)", + "value": "America/Phoenix", + }, + { + "label": "America/Port-au-Prince (-04:00)", + "value": "America/Port-au-Prince", + }, + { + "label": "America/Port_of_Spain (-04:00)", + "value": "America/Port_of_Spain", + }, + { + "label": "America/Porto_Velho (-04:00)", + "value": "America/Porto_Velho", + }, + { + "label": "America/Puerto_Rico (-04:00)", + "value": "America/Puerto_Rico", + }, + { + "label": "America/Punta_Arenas (-03:00)", + "value": "America/Punta_Arenas", + }, + { + "label": "America/Rankin_Inlet (-05:00)", + "value": "America/Rankin_Inlet", + }, + { + "label": "America/Recife (-03:00)", + "value": "America/Recife", + }, + { + "label": "America/Regina (-06:00)", + "value": "America/Regina", + }, + { + "label": "America/Resolute (-05:00)", + "value": "America/Resolute", + }, + { + "label": "America/Rio_Branco (-05:00)", + "value": "America/Rio_Branco", + }, + { + "label": "America/Santarem (-03:00)", + "value": "America/Santarem", + }, + { + "label": "America/Santiago (-03:00)", + "value": "America/Santiago", + }, + { + "label": "America/Santo_Domingo (-04:00)", + "value": "America/Santo_Domingo", + }, + { + "label": "America/Sao_Paulo (-03:00)", + "value": "America/Sao_Paulo", + }, + { + "label": "America/Scoresbysund (-01:00)", + "value": "America/Scoresbysund", + }, + { + "label": "America/Sitka (-08:00)", + "value": "America/Sitka", + }, + { + "label": "America/St_Barthelemy (-04:00)", + "value": "America/St_Barthelemy", + }, + { + "label": "America/St_Johns (-02:30)", + "value": "America/St_Johns", + }, + { + "label": "America/St_Kitts (-04:00)", + "value": "America/St_Kitts", + }, + { + "label": "America/St_Lucia (-04:00)", + "value": "America/St_Lucia", + }, + { + "label": "America/St_Thomas (-04:00)", + "value": "America/St_Thomas", + }, + { + "label": "America/St_Vincent (-04:00)", + "value": "America/St_Vincent", + }, + { + "label": "America/Swift_Current (-06:00)", + "value": "America/Swift_Current", + }, + { + "label": "America/Tegucigalpa (-06:00)", + "value": "America/Tegucigalpa", + }, + { + "label": "America/Thule (-03:00)", + "value": "America/Thule", + }, + { + "label": "America/Tijuana (-07:00)", + "value": "America/Tijuana", + }, + { + "label": "America/Toronto (-04:00)", + "value": "America/Toronto", + }, + { + "label": "America/Tortola (-04:00)", + "value": "America/Tortola", + }, + { + "label": "America/Vancouver (-07:00)", + "value": "America/Vancouver", + }, + { + "label": "America/Whitehorse (-07:00)", + "value": "America/Whitehorse", + }, + { + "label": "America/Winnipeg (-05:00)", + "value": "America/Winnipeg", + }, + { + "label": "America/Yakutat (-08:00)", + "value": "America/Yakutat", + }, + { + "label": "Antarctica/Casey (+08:00)", + "value": "Antarctica/Casey", + }, + { + "label": "Antarctica/Davis (+07:00)", + "value": "Antarctica/Davis", + }, + { + "label": "Antarctica/DumontDUrville (+10:00)", + "value": "Antarctica/DumontDUrville", + }, + { + "label": "Antarctica/Macquarie (+11:00)", + "value": "Antarctica/Macquarie", + }, + { + "label": "Antarctica/Mawson (+05:00)", + "value": "Antarctica/Mawson", + }, + { + "label": "Antarctica/McMurdo (+13:00)", + "value": "Antarctica/McMurdo", + }, + { + "label": "Antarctica/Palmer (-03:00)", + "value": "Antarctica/Palmer", + }, + { + "label": "Antarctica/Rothera (-03:00)", + "value": "Antarctica/Rothera", + }, + { + "label": "Antarctica/Syowa (+03:00)", + "value": "Antarctica/Syowa", + }, + { + "label": "Antarctica/Troll (+02:00)", + "value": "Antarctica/Troll", + }, + { + "label": "Antarctica/Vostok (+05:00)", + "value": "Antarctica/Vostok", + }, + { + "label": "Arctic/Longyearbyen (+02:00)", + "value": "Arctic/Longyearbyen", + }, + { + "label": "Asia/Aden (+03:00)", + "value": "Asia/Aden", + }, + { + "label": "Asia/Almaty (+05:00)", + "value": "Asia/Almaty", + }, + { + "label": "Asia/Amman (+03:00)", + "value": "Asia/Amman", + }, + { + "label": "Asia/Anadyr (+12:00)", + "value": "Asia/Anadyr", + }, + { + "label": "Asia/Aqtau (+05:00)", + "value": "Asia/Aqtau", + }, + { + "label": "Asia/Aqtobe (+05:00)", + "value": "Asia/Aqtobe", + }, + { + "label": "Asia/Ashgabat (+05:00)", + "value": "Asia/Ashgabat", + }, + { + "label": "Asia/Atyrau (+05:00)", + "value": "Asia/Atyrau", + }, + { + "label": "Asia/Baghdad (+03:00)", + "value": "Asia/Baghdad", + }, + { + "label": "Asia/Bahrain (+03:00)", + "value": "Asia/Bahrain", + }, + { + "label": "Asia/Baku (+04:00)", + "value": "Asia/Baku", + }, + { + "label": "Asia/Bangkok (+07:00)", + "value": "Asia/Bangkok", + }, + { + "label": "Asia/Barnaul (+07:00)", + "value": "Asia/Barnaul", + }, + { + "label": "Asia/Beirut (+03:00)", + "value": "Asia/Beirut", + }, + { + "label": "Asia/Bishkek (+06:00)", + "value": "Asia/Bishkek", + }, + { + "label": "Asia/Brunei (+08:00)", + "value": "Asia/Brunei", + }, + { + "label": "Asia/Calcutta (+05:30)", + "value": "Asia/Calcutta", + }, + { + "label": "Asia/Chita (+09:00)", + "value": "Asia/Chita", + }, + { + "label": "Asia/Choibalsan (+08:00)", + "value": "Asia/Choibalsan", + }, + { + "label": "Asia/Colombo (+05:30)", + "value": "Asia/Colombo", + }, + { + "label": "Asia/Damascus (+03:00)", + "value": "Asia/Damascus", + }, + { + "label": "Asia/Dhaka (+06:00)", + "value": "Asia/Dhaka", + }, + { + "label": "Asia/Dili (+09:00)", + "value": "Asia/Dili", + }, + { + "label": "Asia/Dubai (+04:00)", + "value": "Asia/Dubai", + }, + { + "label": "Asia/Dushanbe (+05:00)", + "value": "Asia/Dushanbe", + }, + { + "label": "Asia/Famagusta (+03:00)", + "value": "Asia/Famagusta", + }, + { + "label": "Asia/Gaza (+03:00)", + "value": "Asia/Gaza", + }, + { + "label": "Asia/Hebron (+03:00)", + "value": "Asia/Hebron", + }, + { + "label": "Asia/Hong_Kong (+08:00)", + "value": "Asia/Hong_Kong", + }, + { + "label": "Asia/Hovd (+07:00)", + "value": "Asia/Hovd", + }, + { + "label": "Asia/Irkutsk (+08:00)", + "value": "Asia/Irkutsk", + }, + { + "label": "Asia/Jakarta (+07:00)", + "value": "Asia/Jakarta", + }, + { + "label": "Asia/Jayapura (+09:00)", + "value": "Asia/Jayapura", + }, + { + "label": "Asia/Jerusalem (+03:00)", + "value": "Asia/Jerusalem", + }, + { + "label": "Asia/Kabul (+04:30)", + "value": "Asia/Kabul", + }, + { + "label": "Asia/Kamchatka (+12:00)", + "value": "Asia/Kamchatka", + }, + { + "label": "Asia/Karachi (+05:00)", + "value": "Asia/Karachi", + }, + { + "label": "Asia/Katmandu (+05:45)", + "value": "Asia/Katmandu", + }, + { + "label": "Asia/Khandyga (+09:00)", + "value": "Asia/Khandyga", + }, + { + "label": "Asia/Krasnoyarsk (+07:00)", + "value": "Asia/Krasnoyarsk", + }, + { + "label": "Asia/Kuala_Lumpur (+08:00)", + "value": "Asia/Kuala_Lumpur", + }, + { + "label": "Asia/Kuching (+08:00)", + "value": "Asia/Kuching", + }, + { + "label": "Asia/Kuwait (+03:00)", + "value": "Asia/Kuwait", + }, + { + "label": "Asia/Macau (+08:00)", + "value": "Asia/Macau", + }, + { + "label": "Asia/Magadan (+11:00)", + "value": "Asia/Magadan", + }, + { + "label": "Asia/Makassar (+08:00)", + "value": "Asia/Makassar", + }, + { + "label": "Asia/Manila (+08:00)", + "value": "Asia/Manila", + }, + { + "label": "Asia/Muscat (+04:00)", + "value": "Asia/Muscat", + }, + { + "label": "Asia/Nicosia (+03:00)", + "value": "Asia/Nicosia", + }, + { + "label": "Asia/Novokuznetsk (+07:00)", + "value": "Asia/Novokuznetsk", + }, + { + "label": "Asia/Novosibirsk (+07:00)", + "value": "Asia/Novosibirsk", + }, + { + "label": "Asia/Omsk (+06:00)", + "value": "Asia/Omsk", + }, + { + "label": "Asia/Oral (+05:00)", + "value": "Asia/Oral", + }, + { + "label": "Asia/Phnom_Penh (+07:00)", + "value": "Asia/Phnom_Penh", + }, + { + "label": "Asia/Pontianak (+07:00)", + "value": "Asia/Pontianak", + }, + { + "label": "Asia/Pyongyang (+09:00)", + "value": "Asia/Pyongyang", + }, + { + "label": "Asia/Qatar (+03:00)", + "value": "Asia/Qatar", + }, + { + "label": "Asia/Qostanay (+05:00)", + "value": "Asia/Qostanay", + }, + { + "label": "Asia/Qyzylorda (+05:00)", + "value": "Asia/Qyzylorda", + }, + { + "label": "Asia/Rangoon (+06:30)", + "value": "Asia/Rangoon", + }, + { + "label": "Asia/Riyadh (+03:00)", + "value": "Asia/Riyadh", + }, + { + "label": "Asia/Saigon (+07:00)", + "value": "Asia/Saigon", + }, + { + "label": "Asia/Sakhalin (+11:00)", + "value": "Asia/Sakhalin", + }, + { + "label": "Asia/Samarkand (+05:00)", + "value": "Asia/Samarkand", + }, + { + "label": "Asia/Seoul (+09:00)", + "value": "Asia/Seoul", + }, + { + "label": "Asia/Shanghai (+08:00)", + "value": "Asia/Shanghai", + }, + { + "label": "Asia/Singapore (+08:00)", + "value": "Asia/Singapore", + }, + { + "label": "Asia/Srednekolymsk (+11:00)", + "value": "Asia/Srednekolymsk", + }, + { + "label": "Asia/Taipei (+08:00)", + "value": "Asia/Taipei", + }, + { + "label": "Asia/Tashkent (+05:00)", + "value": "Asia/Tashkent", + }, + { + "label": "Asia/Tbilisi (+04:00)", + "value": "Asia/Tbilisi", + }, + { + "label": "Asia/Tehran (+03:30)", + "value": "Asia/Tehran", + }, + { + "label": "Asia/Thimphu (+06:00)", + "value": "Asia/Thimphu", + }, + { + "label": "Asia/Tokyo (+09:00)", + "value": "Asia/Tokyo", + }, + { + "label": "Asia/Tomsk (+07:00)", + "value": "Asia/Tomsk", + }, + { + "label": "Asia/Ulaanbaatar (+08:00)", + "value": "Asia/Ulaanbaatar", + }, + { + "label": "Asia/Urumqi (+06:00)", + "value": "Asia/Urumqi", + }, + { + "label": "Asia/Ust-Nera (+10:00)", + "value": "Asia/Ust-Nera", + }, + { + "label": "Asia/Vientiane (+07:00)", + "value": "Asia/Vientiane", + }, + { + "label": "Asia/Vladivostok (+10:00)", + "value": "Asia/Vladivostok", + }, + { + "label": "Asia/Yakutsk (+09:00)", + "value": "Asia/Yakutsk", + }, + { + "label": "Asia/Yekaterinburg (+05:00)", + "value": "Asia/Yekaterinburg", + }, + { + "label": "Asia/Yerevan (+04:00)", + "value": "Asia/Yerevan", + }, + { + "label": "Atlantic/Azores (+00:00)", + "value": "Atlantic/Azores", + }, + { + "label": "Atlantic/Bermuda (-03:00)", + "value": "Atlantic/Bermuda", + }, + { + "label": "Atlantic/Canary (+01:00)", + "value": "Atlantic/Canary", + }, + { + "label": "Atlantic/Cape_Verde (-01:00)", + "value": "Atlantic/Cape_Verde", + }, + { + "label": "Atlantic/Faeroe (+01:00)", + "value": "Atlantic/Faeroe", + }, + { + "label": "Atlantic/Madeira (+01:00)", + "value": "Atlantic/Madeira", + }, + { + "label": "Atlantic/Reykjavik (+00:00)", + "value": "Atlantic/Reykjavik", + }, + { + "label": "Atlantic/South_Georgia (-02:00)", + "value": "Atlantic/South_Georgia", + }, + { + "label": "Atlantic/St_Helena (+00:00)", + "value": "Atlantic/St_Helena", + }, + { + "label": "Atlantic/Stanley (-03:00)", + "value": "Atlantic/Stanley", + }, + { + "label": "Australia/Adelaide (+10:30)", + "value": "Australia/Adelaide", + }, + { + "label": "Australia/Brisbane (+10:00)", + "value": "Australia/Brisbane", + }, + { + "label": "Australia/Broken_Hill (+10:30)", + "value": "Australia/Broken_Hill", + }, + { + "label": "Australia/Darwin (+09:30)", + "value": "Australia/Darwin", + }, + { + "label": "Australia/Eucla (+08:45)", + "value": "Australia/Eucla", + }, + { + "label": "Australia/Hobart (+11:00)", + "value": "Australia/Hobart", + }, + { + "label": "Australia/Lindeman (+10:00)", + "value": "Australia/Lindeman", + }, + { + "label": "Australia/Lord_Howe (+11:00)", + "value": "Australia/Lord_Howe", + }, + { + "label": "Australia/Melbourne (+11:00)", + "value": "Australia/Melbourne", + }, + { + "label": "Australia/Perth (+08:00)", + "value": "Australia/Perth", + }, + { + "label": "Australia/Sydney (+11:00)", + "value": "Australia/Sydney", + }, + { + "label": "Europe/Amsterdam (+02:00)", + "value": "Europe/Amsterdam", + }, + { + "label": "Europe/Andorra (+02:00)", + "value": "Europe/Andorra", + }, + { + "label": "Europe/Astrakhan (+04:00)", + "value": "Europe/Astrakhan", + }, + { + "label": "Europe/Athens (+03:00)", + "value": "Europe/Athens", + }, + { + "label": "Europe/Belgrade (+02:00)", + "value": "Europe/Belgrade", + }, + { + "label": "Europe/Berlin (+02:00)", + "value": "Europe/Berlin", + }, + { + "label": "Europe/Bratislava (+02:00)", + "value": "Europe/Bratislava", + }, + { + "label": "Europe/Brussels (+02:00)", + "value": "Europe/Brussels", + }, + { + "label": "Europe/Bucharest (+03:00)", + "value": "Europe/Bucharest", + }, + { + "label": "Europe/Budapest (+02:00)", + "value": "Europe/Budapest", + }, + { + "label": "Europe/Busingen (+02:00)", + "value": "Europe/Busingen", + }, + { + "label": "Europe/Chisinau (+03:00)", + "value": "Europe/Chisinau", + }, + { + "label": "Europe/Copenhagen (+02:00)", + "value": "Europe/Copenhagen", + }, + { + "label": "Europe/Dublin (+01:00)", + "value": "Europe/Dublin", + }, + { + "label": "Europe/Gibraltar (+02:00)", + "value": "Europe/Gibraltar", + }, + { + "label": "Europe/Guernsey (+01:00)", + "value": "Europe/Guernsey", + }, + { + "label": "Europe/Helsinki (+03:00)", + "value": "Europe/Helsinki", + }, + { + "label": "Europe/Isle_of_Man (+01:00)", + "value": "Europe/Isle_of_Man", + }, + { + "label": "Europe/Istanbul (+03:00)", + "value": "Europe/Istanbul", + }, + { + "label": "Europe/Jersey (+01:00)", + "value": "Europe/Jersey", + }, + { + "label": "Europe/Kaliningrad (+02:00)", + "value": "Europe/Kaliningrad", + }, + { + "label": "Europe/Kiev (+03:00)", + "value": "Europe/Kiev", + }, + { + "label": "Europe/Kirov (+03:00)", + "value": "Europe/Kirov", + }, + { + "label": "Europe/Lisbon (+01:00)", + "value": "Europe/Lisbon", + }, + { + "label": "Europe/Ljubljana (+02:00)", + "value": "Europe/Ljubljana", + }, + { + "label": "Europe/London (+01:00)", + "value": "Europe/London", + }, + { + "label": "Europe/Luxembourg (+02:00)", + "value": "Europe/Luxembourg", + }, + { + "label": "Europe/Madrid (+02:00)", + "value": "Europe/Madrid", + }, + { + "label": "Europe/Malta (+02:00)", + "value": "Europe/Malta", + }, + { + "label": "Europe/Mariehamn (+03:00)", + "value": "Europe/Mariehamn", + }, + { + "label": "Europe/Minsk (+03:00)", + "value": "Europe/Minsk", + }, + { + "label": "Europe/Monaco (+02:00)", + "value": "Europe/Monaco", + }, + { + "label": "Europe/Moscow (+03:00)", + "value": "Europe/Moscow", + }, + { + "label": "Europe/Oslo (+02:00)", + "value": "Europe/Oslo", + }, + { + "label": "Europe/Paris (+02:00)", + "value": "Europe/Paris", + }, + { + "label": "Europe/Podgorica (+02:00)", + "value": "Europe/Podgorica", + }, + { + "label": "Europe/Prague (+02:00)", + "value": "Europe/Prague", + }, + { + "label": "Europe/Riga (+03:00)", + "value": "Europe/Riga", + }, + { + "label": "Europe/Rome (+02:00)", + "value": "Europe/Rome", + }, + { + "label": "Europe/Samara (+04:00)", + "value": "Europe/Samara", + }, + { + "label": "Europe/San_Marino (+02:00)", + "value": "Europe/San_Marino", + }, + { + "label": "Europe/Sarajevo (+02:00)", + "value": "Europe/Sarajevo", + }, + { + "label": "Europe/Saratov (+04:00)", + "value": "Europe/Saratov", + }, + { + "label": "Europe/Simferopol (+03:00)", + "value": "Europe/Simferopol", + }, + { + "label": "Europe/Skopje (+02:00)", + "value": "Europe/Skopje", + }, + { + "label": "Europe/Sofia (+03:00)", + "value": "Europe/Sofia", + }, + { + "label": "Europe/Stockholm (+02:00)", + "value": "Europe/Stockholm", + }, + { + "label": "Europe/Tallinn (+03:00)", + "value": "Europe/Tallinn", + }, + { + "label": "Europe/Tirane (+02:00)", + "value": "Europe/Tirane", + }, + { + "label": "Europe/Ulyanovsk (+04:00)", + "value": "Europe/Ulyanovsk", + }, + { + "label": "Europe/Vaduz (+02:00)", + "value": "Europe/Vaduz", + }, + { + "label": "Europe/Vatican (+02:00)", + "value": "Europe/Vatican", + }, + { + "label": "Europe/Vienna (+02:00)", + "value": "Europe/Vienna", + }, + { + "label": "Europe/Vilnius (+03:00)", + "value": "Europe/Vilnius", + }, + { + "label": "Europe/Volgograd (+03:00)", + "value": "Europe/Volgograd", + }, + { + "label": "Europe/Warsaw (+02:00)", + "value": "Europe/Warsaw", + }, + { + "label": "Europe/Zagreb (+02:00)", + "value": "Europe/Zagreb", + }, + { + "label": "Europe/Zurich (+02:00)", + "value": "Europe/Zurich", + }, + { + "label": "Indian/Antananarivo (+03:00)", + "value": "Indian/Antananarivo", + }, + { + "label": "Indian/Chagos (+06:00)", + "value": "Indian/Chagos", + }, + { + "label": "Indian/Christmas (+07:00)", + "value": "Indian/Christmas", + }, + { + "label": "Indian/Cocos (+06:30)", + "value": "Indian/Cocos", + }, + { + "label": "Indian/Comoro (+03:00)", + "value": "Indian/Comoro", + }, + { + "label": "Indian/Kerguelen (+05:00)", + "value": "Indian/Kerguelen", + }, + { + "label": "Indian/Mahe (+04:00)", + "value": "Indian/Mahe", + }, + { + "label": "Indian/Maldives (+05:00)", + "value": "Indian/Maldives", + }, + { + "label": "Indian/Mauritius (+04:00)", + "value": "Indian/Mauritius", + }, + { + "label": "Indian/Mayotte (+03:00)", + "value": "Indian/Mayotte", + }, + { + "label": "Indian/Reunion (+04:00)", + "value": "Indian/Reunion", + }, + { + "label": "Pacific/Apia (+13:00)", + "value": "Pacific/Apia", + }, + { + "label": "Pacific/Auckland (+13:00)", + "value": "Pacific/Auckland", + }, + { + "label": "Pacific/Bougainville (+11:00)", + "value": "Pacific/Bougainville", + }, + { + "label": "Pacific/Chatham (+13:45)", + "value": "Pacific/Chatham", + }, + { + "label": "Pacific/Easter (-05:00)", + "value": "Pacific/Easter", + }, + { + "label": "Pacific/Efate (+11:00)", + "value": "Pacific/Efate", + }, + { + "label": "Pacific/Enderbury (+13:00)", + "value": "Pacific/Enderbury", + }, + { + "label": "Pacific/Fakaofo (+13:00)", + "value": "Pacific/Fakaofo", + }, + { + "label": "Pacific/Fiji (+12:00)", + "value": "Pacific/Fiji", + }, + { + "label": "Pacific/Funafuti (+12:00)", + "value": "Pacific/Funafuti", + }, + { + "label": "Pacific/Galapagos (-06:00)", + "value": "Pacific/Galapagos", + }, + { + "label": "Pacific/Gambier (-09:00)", + "value": "Pacific/Gambier", + }, + { + "label": "Pacific/Guadalcanal (+11:00)", + "value": "Pacific/Guadalcanal", + }, + { + "label": "Pacific/Guam (+10:00)", + "value": "Pacific/Guam", + }, + { + "label": "Pacific/Honolulu (-10:00)", + "value": "Pacific/Honolulu", + }, + { + "label": "Pacific/Kiritimati (+14:00)", + "value": "Pacific/Kiritimati", + }, + { + "label": "Pacific/Kosrae (+11:00)", + "value": "Pacific/Kosrae", + }, + { + "label": "Pacific/Kwajalein (+12:00)", + "value": "Pacific/Kwajalein", + }, + { + "label": "Pacific/Majuro (+12:00)", + "value": "Pacific/Majuro", + }, + { + "label": "Pacific/Marquesas (-09:30)", + "value": "Pacific/Marquesas", + }, + { + "label": "Pacific/Midway (-11:00)", + "value": "Pacific/Midway", + }, + { + "label": "Pacific/Nauru (+12:00)", + "value": "Pacific/Nauru", + }, + { + "label": "Pacific/Niue (-11:00)", + "value": "Pacific/Niue", + }, + { + "label": "Pacific/Norfolk (+12:00)", + "value": "Pacific/Norfolk", + }, + { + "label": "Pacific/Noumea (+11:00)", + "value": "Pacific/Noumea", + }, + { + "label": "Pacific/Pago_Pago (-11:00)", + "value": "Pacific/Pago_Pago", + }, + { + "label": "Pacific/Palau (+09:00)", + "value": "Pacific/Palau", + }, + { + "label": "Pacific/Pitcairn (-08:00)", + "value": "Pacific/Pitcairn", + }, + { + "label": "Pacific/Ponape (+11:00)", + "value": "Pacific/Ponape", + }, + { + "label": "Pacific/Port_Moresby (+10:00)", + "value": "Pacific/Port_Moresby", + }, + { + "label": "Pacific/Rarotonga (-10:00)", + "value": "Pacific/Rarotonga", + }, + { + "label": "Pacific/Saipan (+10:00)", + "value": "Pacific/Saipan", + }, + { + "label": "Pacific/Tahiti (-10:00)", + "value": "Pacific/Tahiti", + }, + { + "label": "Pacific/Tarawa (+12:00)", + "value": "Pacific/Tarawa", + }, + { + "label": "Pacific/Tongatapu (+13:00)", + "value": "Pacific/Tongatapu", + }, + { + "label": "Pacific/Truk (+10:00)", + "value": "Pacific/Truk", + }, + { + "label": "Pacific/Wake (+12:00)", + "value": "Pacific/Wake", + }, + { + "label": "Pacific/Wallis (+12:00)", + "value": "Pacific/Wallis", + }, +] +`; diff --git a/src/client/utils/date.spec.ts b/src/client/utils/date.spec.ts new file mode 100644 index 0000000..47fc41b --- /dev/null +++ b/src/client/utils/date.spec.ts @@ -0,0 +1,10 @@ +import { describe, expect, test } from 'vitest'; +import { getTimezoneList } from './date'; + +describe('getTimezoneList', () => { + test('should return timezone list with correct labels and values', () => { + const result = getTimezoneList(); + + expect(result).toMatchSnapshot(); + }); +}); diff --git a/src/client/utils/date.ts b/src/client/utils/date.ts index d24f945..091f1c4 100644 --- a/src/client/utils/date.ts +++ b/src/client/utils/date.ts @@ -68,3 +68,25 @@ export function formatDateWithUnit(val: dayjs.ConfigType, unit: DateUnit) { return formatDate(val); } + +function formatOffset(offset: number) { + const sign = offset >= 0 ? '+' : '-'; + const absOffset = Math.abs(offset); + const hours = String(Math.floor(absOffset / 60)).padStart(2, '0'); + const minutes = String(absOffset % 60).padStart(2, '0'); + + return `${sign}${hours}:${minutes}`; +} + +export function getTimezoneList() { + const timezones = Intl.supportedValuesOf('timeZone'); + + return timezones.map((timezone) => { + const offset = dayjs().tz(timezone).utcOffset(); + + return { + label: `${timezone} (${formatOffset(offset)})`, + value: timezone, + }; + }); +} diff --git a/src/server/init.ts b/src/server/init.ts index baaa8a9..d3735e8 100644 --- a/src/server/init.ts +++ b/src/server/init.ts @@ -1,8 +1,14 @@ import { version } from '@tianji/shared'; import axios from 'axios'; +import dayjs from 'dayjs'; +import utc from 'dayjs/plugin/utc.js'; +import timezone from 'dayjs/plugin/timezone.js'; axios.defaults.headers.common['User-Agent'] = `tianji/${version}`; +dayjs.extend(utc); +dayjs.extend(timezone); + (BigInt.prototype as any).toJSON = function () { const int = Number.parseInt(this.toString()); return int ?? this.toString(); diff --git a/src/server/model/monitor/manager.ts b/src/server/model/monitor/manager.ts index fca25e0..a7efa72 100644 --- a/src/server/model/monitor/manager.ts +++ b/src/server/model/monitor/manager.ts @@ -1,7 +1,8 @@ -import { Monitor, Notification } from '@prisma/client'; +import { Monitor } from '@prisma/client'; import { prisma } from '../_client.js'; import { MonitorRunner } from './runner.js'; import { logger } from '../../utils/logger.js'; +import { MonitorWithNotification } from './types.js'; export type MonitorUpsertData = Pick< Monitor, @@ -13,8 +14,6 @@ export type MonitorUpsertData = Pick< payload: Record; }; -type MonitorWithNotification = Monitor & { notifications: Notification[] }; - export class MonitorManager { private monitorRunner: Record = {}; private isStarted = false; @@ -64,9 +63,7 @@ export class MonitorManager { delete this.monitorRunner[monitor.id]; } - const runner = (this.monitorRunner[monitor.id] = new MonitorRunner( - monitor - )); + const runner = await this.createRunner(monitor); runner.startMonitor(); return monitor; @@ -112,7 +109,7 @@ export class MonitorManager { Promise.all( monitors.map(async (m) => { try { - const runner = new MonitorRunner(m); + const runner = await this.createRunner(m); this.monitorRunner[m.id] = runner; await runner.startMonitor(); } catch (err) { @@ -128,8 +125,32 @@ export class MonitorManager { return this.monitorRunner[monitorId]; } - createRunner(monitor: MonitorWithNotification) { + /** + * Restart all runner basic on workspace id + */ + restartWithWorkspaceId(workspaceId: string) { + Object.values(this.monitorRunner).map((runner) => { + if (runner.workspace.id === workspaceId) { + this.createRunner(runner.monitor); + } + }); + } + + /** + * create runner + */ + async createRunner(monitor: MonitorWithNotification) { + if (this.monitorRunner[monitor.id]) { + this.monitorRunner[monitor.id].stopMonitor(); + } + + const workspace = await prisma.workspace.findUniqueOrThrow({ + where: { + id: monitor.workspaceId, + }, + }); const runner = (this.monitorRunner[monitor.id] = new MonitorRunner( + workspace, monitor )); diff --git a/src/server/model/monitor/runner.ts b/src/server/model/monitor/runner.ts index 48e5ccf..26c4dfe 100644 --- a/src/server/model/monitor/runner.ts +++ b/src/server/model/monitor/runner.ts @@ -1,4 +1,4 @@ -import { Monitor, Notification } from '@prisma/client'; +import { Notification, Workspace } from '@prisma/client'; import { subscribeEventBus } from '../../ws/shared.js'; import { prisma } from '../_client.js'; import { monitorProviders } from './provider/index.js'; @@ -8,6 +8,8 @@ import { logger } from '../../utils/logger.js'; import { token } from '../notification/token/index.js'; import { ContentToken } from '../notification/token/type.js'; import { createAuditLog } from '../auditLog.js'; +import { MonitorWithNotification } from './types.js'; +import { get } from 'lodash-es'; /** * Class which actually run monitor data collect @@ -17,7 +19,14 @@ export class MonitorRunner { timer: NodeJS.Timeout | null = null; retriedNum = 0; - constructor(public monitor: Monitor & { notifications: Notification[] }) {} + constructor( + public workspace: Workspace, + public monitor: MonitorWithNotification + ) {} + + getTimezone(): string { + return get(this.workspace, ['settings', 'timezone']) || 'utc'; + } /** * Start single monitor @@ -74,9 +83,9 @@ export class MonitorRunner { ); await this.notify(`[${monitor.name}] 🔴 Down`, [ token.text( - `[${monitor.name}] 🔴 Down\nTime: ${dayjs().format( - 'YYYY-MM-DD HH:mm:ss (z)' - )}` + `[${monitor.name}] 🔴 Down\nTime: ${dayjs() + .tz(this.getTimezone()) + .format('YYYY-MM-DD HH:mm:ss (z)')}` ), ]); currentStatus = 'DOWN'; @@ -88,9 +97,9 @@ export class MonitorRunner { ); await this.notify(`[${monitor.name}] ✅ Up`, [ token.text( - `[${monitor.name}] ✅ Up\nTime: ${dayjs().format( - 'YYYY-MM-DD HH:mm:ss (z)' - )}` + `[${monitor.name}] ✅ Up\nTime: ${dayjs() + .tz(this.getTimezone()) + .format('YYYY-MM-DD HH:mm:ss (z)')}` ), ]); currentStatus = 'UP'; diff --git a/src/server/model/monitor/types.ts b/src/server/model/monitor/types.ts new file mode 100644 index 0000000..15e7085 --- /dev/null +++ b/src/server/model/monitor/types.ts @@ -0,0 +1,5 @@ +import { Monitor, Notification } from '@prisma/client'; + +export type MonitorWithNotification = Monitor & { + notifications: Notification[]; +}; diff --git a/src/server/trpc/routers/monitor.ts b/src/server/trpc/routers/monitor.ts index 360bd68..75f68d1 100644 --- a/src/server/trpc/routers/monitor.ts +++ b/src/server/trpc/routers/monitor.ts @@ -292,7 +292,7 @@ export const monitorRouter = router({ }); let runner = monitorManager.getRunner(monitorId); if (!runner) { - runner = monitorManager.createRunner(monitor); + runner = await monitorManager.createRunner(monitor); } if (active === true) { diff --git a/src/server/trpc/routers/workspace.ts b/src/server/trpc/routers/workspace.ts index ab1ac3e..d93f45e 100644 --- a/src/server/trpc/routers/workspace.ts +++ b/src/server/trpc/routers/workspace.ts @@ -270,6 +270,15 @@ export const workspaceRouter = router({ settings: merge({}, prev.settings, settings), }, }); + + if ( + 'timezone' in settings && + get(prev, ['settings', 'timezone']) !== settings.timezone + ) { + // should be restart all monitor + monitorManager.restartWithWorkspaceId(workspaceId); + } + return res; }), invite: workspaceAdminProcedure