From 5983141d143592409fac1d7f31ef6acc26e60206 Mon Sep 17 00:00:00 2001 From: Jonathon Choo Date: Mon, 4 Nov 2024 10:41:14 +0000 Subject: [PATCH 1/5] fix: use the server timezone to parse the cron expression --- ui/src/models/index.ts | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/ui/src/models/index.ts b/ui/src/models/index.ts index 641fc72e7..dc929d4a8 100644 --- a/ui/src/models/index.ts +++ b/ui/src/models/index.ts @@ -150,9 +150,16 @@ export function getNextSchedule(data: WorkflowListItem): number { if (!schedules || schedules.length == 0 || data.Suspended) { return Number.MAX_SAFE_INTEGER; } - const datesToRun = schedules.map((s) => - cronParser.parseExpression(s.Expression).next() - ); + const tz = null; // If we can work out how to get the server TZ, we can set this + const datesToRun = schedules.map((s) => { + const expression = tz + ? cronParser.parseExpression(s.Expression, { + currentDate: new Date(), + tz, + }) + : cronParser.parseExpression(s.Expression); + return expression.next(); + }); const sorted = datesToRun.sort((a, b) => a.getTime() - b.getTime()); return sorted[0].getTime() / 1000; } From 0d72715bc1904d52460ad0c067514d76c9abfd4c Mon Sep 17 00:00:00 2001 From: Jonathon Choo Date: Tue, 5 Nov 2024 11:00:28 +0000 Subject: [PATCH 2/5] feat: added configuration for timezone --- internal/config/config.go | 2 ++ internal/frontend/frontend.go | 1 + internal/frontend/server/server.go | 2 ++ internal/frontend/server/templates.go | 4 +++ internal/frontend/templates/base.gohtml | 43 +++++++++++----------- ui/index.html | 1 + ui/src/App.tsx | 1 + ui/src/components/molecules/DAGTable.tsx | 46 +++++++++++++----------- ui/src/models/index.ts | 3 +- 9 files changed, 60 insertions(+), 43 deletions(-) diff --git a/internal/config/config.go b/internal/config/config.go index cb8f25ccd..3f86a6814 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -54,6 +54,7 @@ type Config struct { APIBaseURL string // Base URL for API Debug bool // Enable debug mode (verbose logging) LogFormat string // Log format + TimeZone string // The server time zone } type TLS struct { @@ -178,6 +179,7 @@ func bindEnvs() { _ = viper.BindEnv("navbarColor", "DAGU_NAVBAR_COLOR") _ = viper.BindEnv("navbarTitle", "DAGU_NAVBAR_TITLE") _ = viper.BindEnv("apiBaseURL", "DAGU_API_BASE_URL") + _ = viper.BindEnv("timeZone", "DAGU_TIME_ZONE") // Basic authentication _ = viper.BindEnv("isBasicAuth", "DAGU_IS_BASICAUTH") diff --git a/internal/frontend/frontend.go b/internal/frontend/frontend.go index 49eea471b..7608bce7d 100644 --- a/internal/frontend/frontend.go +++ b/internal/frontend/frontend.go @@ -43,6 +43,7 @@ func New(cfg *config.Config, lg logger.Logger, cli client.Client) *server.Server NavbarColor: cfg.NavbarColor, NavbarTitle: cfg.NavbarTitle, APIBaseURL: cfg.APIBaseURL, + TimeZone: cfg.TimeZone, } if cfg.IsAuthToken { diff --git a/internal/frontend/server/server.go b/internal/frontend/server/server.go index a702efea1..93eb49e97 100644 --- a/internal/frontend/server/server.go +++ b/internal/frontend/server/server.go @@ -63,6 +63,7 @@ type NewServerArgs struct { NavbarColor string NavbarTitle string APIBaseURL string + TimeZone string } type BasicAuth struct { @@ -92,6 +93,7 @@ func New(params NewServerArgs) *Server { NavbarColor: params.NavbarColor, NavbarTitle: params.NavbarTitle, APIBaseURL: params.APIBaseURL, + TimeZone: params.TimeZone, }, } } diff --git a/internal/frontend/server/templates.go b/internal/frontend/server/templates.go index 19147623b..2e0cd3194 100644 --- a/internal/frontend/server/templates.go +++ b/internal/frontend/server/templates.go @@ -57,6 +57,7 @@ type funcsConfig struct { NavbarColor string NavbarTitle string APIBaseURL string + TimeZone string } func defaultFunctions(cfg funcsConfig) template.FuncMap { @@ -80,6 +81,9 @@ func defaultFunctions(cfg funcsConfig) template.FuncMap { "apiURL": func() string { return cfg.APIBaseURL }, + "timeZone": func() string { + return cfg.TimeZone + }, } } diff --git a/internal/frontend/templates/base.gohtml b/internal/frontend/templates/base.gohtml index 4b921bf22..dccc1bb28 100644 --- a/internal/frontend/templates/base.gohtml +++ b/internal/frontend/templates/base.gohtml @@ -1,27 +1,26 @@ {{define "base"}} - - - - - - {{navbarTitle}} - - - - - {{template "content" .}} - - + + + + + {{template "content" .}} + -{{ end }} \ No newline at end of file +{{ end }} diff --git a/ui/index.html b/ui/index.html index 7b3bf47ba..73417378e 100644 --- a/ui/index.html +++ b/ui/index.html @@ -12,6 +12,7 @@ title: '', navbarColor: '', version: '', + timeZone: '', }; } diff --git a/ui/src/App.tsx b/ui/src/App.tsx index b26140572..80e81f0fa 100644 --- a/ui/src/App.tsx +++ b/ui/src/App.tsx @@ -13,6 +13,7 @@ export type Config = { apiURL: string; title: string; navbarColor: string; + timeZone: string; version: string; }; diff --git a/ui/src/components/molecules/DAGTable.tsx b/ui/src/components/molecules/DAGTable.tsx index 625f6bc76..2ac090e8f 100644 --- a/ui/src/components/molecules/DAGTable.tsx +++ b/ui/src/components/molecules/DAGTable.tsx @@ -251,7 +251,7 @@ const defaultColumns = [ }), columnHelper.accessor('Type', { id: 'Schedule', - header: 'Schedule', + header: `Schedule (${getConfig().timeZone})`, enableSorting: true, cell: (props) => { const data = props.row.original!; @@ -389,7 +389,15 @@ const defaultColumns = [ }), ]; -function DAGTable({ DAGs = [], group = '', refreshFn, searchText, handleSearchTextChange, searchTag, handleSearchTagChange }: Props) { +function DAGTable({ + DAGs = [], + group = '', + refreshFn, + searchText, + handleSearchTextChange, + searchTag, + handleSearchTagChange, +}: Props) { const [columns] = React.useState(() => [ ...defaultColumns, ]); @@ -444,7 +452,7 @@ function DAGTable({ DAGs = [], group = '', refreshFn, searchText, handleSearchTe const instance = useReactTable({ data, columns, - getSubRows: (row) =>row.subRows, + getSubRows: (row) => row.subRows, getCoreRowModel: getCoreRowModel(), getSortedRowModel: getSortedRowModel(), getFilteredRowModel: getFilteredRowModel(), @@ -497,21 +505,19 @@ function DAGTable({ DAGs = [], group = '', refreshFn, searchText, handleSearchTe limitTags={1} value={searchTag} freeSolo - options={ - DAGs.reduce((acc, dag) => { - if (dag.Type == DAGDataType.DAG) { - const tags = dag.DAGStatus.DAG.Tags; - if (tags) { - tags.forEach((tag) => { - if (!acc.includes(tag)) { - acc.push(tag); - } - }); - } + options={DAGs.reduce((acc, dag) => { + if (dag.Type == DAGDataType.DAG) { + const tags = dag.DAGStatus.DAG.Tags; + if (tags) { + tags.forEach((tag) => { + if (!acc.includes(tag)) { + acc.push(tag); + } + }); } - return acc; - }, []) - } + } + return acc; + }, [])} onChange={(_, value) => { const v = value || ''; handleSearchTagChange(v); @@ -558,9 +564,9 @@ function DAGTable({ DAGs = [], group = '', refreshFn, searchText, handleSearchTe {header.isPlaceholder ? null : flexRender( - header.column.columnDef.header, - header.getContext() - )} + header.column.columnDef.header, + header.getContext() + )} {{ asc: ( { const expression = tz ? cronParser.parseExpression(s.Expression, { From 4f0b66844e3c9e3e4d5aae362315488c3026a44d Mon Sep 17 00:00:00 2001 From: Jonathon Choo Date: Tue, 5 Nov 2024 11:05:00 +0000 Subject: [PATCH 3/5] chore: remove debug line --- ui/src/models/index.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/ui/src/models/index.ts b/ui/src/models/index.ts index 0a127a3dc..c07b20b68 100644 --- a/ui/src/models/index.ts +++ b/ui/src/models/index.ts @@ -151,7 +151,6 @@ export function getNextSchedule(data: WorkflowListItem): number { return Number.MAX_SAFE_INTEGER; } const tz = getConfig().timeZone; - console.log('hello'); // If we can work out how to get the server TZ, we can set this const datesToRun = schedules.map((s) => { const expression = tz ? cronParser.parseExpression(s.Expression, { From 29ffdf5131177e7ed32da01e5b36f5ff5d26a1e1 Mon Sep 17 00:00:00 2001 From: Jonathon Choo Date: Tue, 5 Nov 2024 11:17:24 +0000 Subject: [PATCH 4/5] feat: improve UI to show the timezone --- ui/src/components/molecules/DAGTable.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ui/src/components/molecules/DAGTable.tsx b/ui/src/components/molecules/DAGTable.tsx index 2ac090e8f..39b302162 100644 --- a/ui/src/components/molecules/DAGTable.tsx +++ b/ui/src/components/molecules/DAGTable.tsx @@ -251,7 +251,9 @@ const defaultColumns = [ }), columnHelper.accessor('Type', { id: 'Schedule', - header: `Schedule (${getConfig().timeZone})`, + header: getConfig().timeZone + ? `Schedule in ${getConfig().timeZone}` + : 'Schedule', enableSorting: true, cell: (props) => { const data = props.row.original!; From c7986d29d6d94f97aa9349d598c10042b477ad04 Mon Sep 17 00:00:00 2001 From: Jonathon Choo Date: Wed, 6 Nov 2024 08:19:03 +1100 Subject: [PATCH 5/5] chore: fix whitespace --- internal/frontend/frontend.go | 2 +- internal/frontend/server/server.go | 4 ++-- internal/frontend/server/templates.go | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/internal/frontend/frontend.go b/internal/frontend/frontend.go index 7608bce7d..072c8802d 100644 --- a/internal/frontend/frontend.go +++ b/internal/frontend/frontend.go @@ -43,7 +43,7 @@ func New(cfg *config.Config, lg logger.Logger, cli client.Client) *server.Server NavbarColor: cfg.NavbarColor, NavbarTitle: cfg.NavbarTitle, APIBaseURL: cfg.APIBaseURL, - TimeZone: cfg.TimeZone, + TimeZone: cfg.TimeZone, } if cfg.IsAuthToken { diff --git a/internal/frontend/server/server.go b/internal/frontend/server/server.go index 93eb49e97..e768f9b4d 100644 --- a/internal/frontend/server/server.go +++ b/internal/frontend/server/server.go @@ -63,7 +63,7 @@ type NewServerArgs struct { NavbarColor string NavbarTitle string APIBaseURL string - TimeZone string + TimeZone string } type BasicAuth struct { @@ -93,7 +93,7 @@ func New(params NewServerArgs) *Server { NavbarColor: params.NavbarColor, NavbarTitle: params.NavbarTitle, APIBaseURL: params.APIBaseURL, - TimeZone: params.TimeZone, + TimeZone: params.TimeZone, }, } } diff --git a/internal/frontend/server/templates.go b/internal/frontend/server/templates.go index 2e0cd3194..7ca88352c 100644 --- a/internal/frontend/server/templates.go +++ b/internal/frontend/server/templates.go @@ -57,7 +57,7 @@ type funcsConfig struct { NavbarColor string NavbarTitle string APIBaseURL string - TimeZone string + TimeZone string } func defaultFunctions(cfg funcsConfig) template.FuncMap {