This is an automated email from the ASF dual-hosted git repository. github-merge-queue[bot] pushed a commit to branch gh-readonly-queue/main/pr-8107-9ccf250d29d1cd85b78dea47c090b65c4cf30dd8 in repository https://gitbox.apache.org/repos/asf/texera.git
commit b8f6c5bf5267c26fde4100b4eaae8c35c85a5eea Author: carloea2 <[email protected]> AuthorDate: Sun Aug 30 01:32:11 2026 +0000 feat(frontend): preserve dashboard filter dates (#8107) ### What changes were proposed in this PR? Dashboard date filters now serialize the local calendar year, month, and day instead of converting local midnight to UTC first. Before: August 29 through September 1 became August 28 through August 31 in Asia Tokyo. After: August 29 through September 1 remains August 29 through September 1. ### Any related issues, documentation, discussions? Closes #8106 ### How was this PR tested? `yarn test --include src/app/dashboard/type/search-filter-parameters.spec.ts` `yarn format:ci` Manual: 1. Start Texera locally. 2. Open Your Work, then Workflows in Chrome with timezone Asia Tokyo. 3. Select August 29 through September 1. 4. Confirm the request contains `createDateStart=2026-08-29&createDateEnd=2026-09-01`. ### Was this PR authored or co-authored using generative AI tooling? Generated-by: Codex --- .../dashboard/type/search-filter-parameters.spec.ts | 21 ++++++++++----------- .../app/dashboard/type/search-filter-parameters.ts | 11 +++++++---- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/frontend/src/app/dashboard/type/search-filter-parameters.spec.ts b/frontend/src/app/dashboard/type/search-filter-parameters.spec.ts index 7cf70ce56d..531663d346 100644 --- a/frontend/src/app/dashboard/type/search-filter-parameters.spec.ts +++ b/frontend/src/app/dashboard/type/search-filter-parameters.spec.ts @@ -54,19 +54,18 @@ describe("toQueryStrings", () => { expect(toQueryStrings(["a b&c=d"], makeEmptyFilter())).toBe("query=a%20b%26c%3Dd"); }); - // The date assertions below pin the CURRENT behavior: dates are serialized via - // toISOString(), i.e. as the UTC calendar day. Callers pass local-midnight Dates, - // so in UTC+ timezones the emitted day is one earlier than the day the user picked - // (known off-by-one bug, tracked separately). The Date literals here are anchored - // to 12:00 UTC so these tests are stable in every timezone. - it("should serialize all four date filters as UTC YYYY-MM-DD in a fixed order", () => { + it("should preserve all four local date filters in a UTC-positive timezone", () => { + vi.stubEnv("TZ", "Asia/Tokyo"); const filter = makeEmptyFilter(); - filter.createDateStart = new Date("2024-01-15T12:00:00Z"); - filter.createDateEnd = new Date("2024-02-20T12:00:00Z"); - filter.modifiedDateStart = new Date("2024-03-05T12:00:00Z"); - filter.modifiedDateEnd = new Date("2024-04-10T12:00:00Z"); + filter.createDateStart = new Date(2024, 0, 15); + filter.createDateEnd = new Date(2024, 1, 20); + filter.modifiedDateStart = new Date(2024, 2, 5); + filter.modifiedDateEnd = new Date(2024, 3, 10); - expect(toQueryStrings([], filter)).toBe( + const query = toQueryStrings([], filter); + vi.unstubAllEnvs(); + + expect(query).toBe( "createDateStart=2024-01-15&createDateEnd=2024-02-20&modifiedDateStart=2024-03-05&modifiedDateEnd=2024-04-10" ); }); diff --git a/frontend/src/app/dashboard/type/search-filter-parameters.ts b/frontend/src/app/dashboard/type/search-filter-parameters.ts index a573d63d09..8052ce80fd 100644 --- a/frontend/src/app/dashboard/type/search-filter-parameters.ts +++ b/frontend/src/app/dashboard/type/search-filter-parameters.ts @@ -38,6 +38,9 @@ export const toQueryStrings = ( type?: "workflow" | "file" | "dataset" | null, orderBy?: SortMethod ): string => { + const toLocalDate = (date: Date) => + `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, "0")}-${String(date.getDate()).padStart(2, "0")}`; + function* getQueryParameters(): Iterable<[name: string, value: string]> { if (keywords) { for (const keyword of keywords) { @@ -48,10 +51,10 @@ export const toQueryStrings = ( const modifiedDateStart = params.modifiedDateStart; const createDateEnd = params.createDateEnd; const modifiedDateEnd = params.modifiedDateEnd; - if (createDateStart) yield ["createDateStart", createDateStart.toISOString().split("T")[0]]; - if (createDateEnd) yield ["createDateEnd", createDateEnd.toISOString().split("T")[0]]; - if (modifiedDateStart) yield ["modifiedDateStart", modifiedDateStart.toISOString().split("T")[0]]; - if (modifiedDateEnd) yield ["modifiedDateEnd", modifiedDateEnd.toISOString().split("T")[0]]; + if (createDateStart) yield ["createDateStart", toLocalDate(createDateStart)]; + if (createDateEnd) yield ["createDateEnd", toLocalDate(createDateEnd)]; + if (modifiedDateStart) yield ["modifiedDateStart", toLocalDate(modifiedDateStart)]; + if (modifiedDateEnd) yield ["modifiedDateEnd", toLocalDate(modifiedDateEnd)]; for (const owner of params.owners) { yield ["owner", owner]; }
