Skip to content

Commit

Permalink
Use browser locale to determine the first day of the week in date pic…
Browse files Browse the repository at this point in the history
…kers.

Fixes #7250.
  • Loading branch information
fniessink committed Jan 23, 2025
1 parent 2c8abfc commit 881aed1
Show file tree
Hide file tree
Showing 10 changed files with 52 additions and 19 deletions.
5 changes: 2 additions & 3 deletions components/frontend/src/AppUI.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import "./App.css"
import { useColorScheme } from "@mui/material/styles"
import { LocalizationProvider } from "@mui/x-date-pickers"
import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs"
import { locale_en_gb } from "dayjs/locale/en-gb"
import { bool, func, number, object, string } from "prop-types"
import HashLinkObserver from "react-hash-link"
import { ToastContainer } from "react-toastify"
Expand All @@ -15,6 +14,7 @@ import { Permissions } from "./context/Permissions"
import { Footer } from "./header_footer/Footer"
import { Menubar } from "./header_footer/Menubar"
import { SettingsPanel } from "./header_footer/SettingsPanel"
import { adapterLocale } from "./locale"
import { PageContent } from "./PageContent"
import {
datePropType,
Expand Down Expand Up @@ -63,9 +63,8 @@ export function AppUI({
settings.sortColumn.set(column)
}
}

return (
<LocalizationProvider dateAdapter={AdapterDayjs} adapterLocale={locale_en_gb}>
<LocalizationProvider dateAdapter={AdapterDayjs} adapterLocale={adapterLocale(navigator.language)}>
<HashLinkObserver />
<Menubar
email={email}
Expand Down
31 changes: 31 additions & 0 deletions components/frontend/src/locale.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import "dayjs/locale/en-gb"
import "dayjs/locale/nl"

import dayjs from "dayjs"
import localeData from "dayjs/plugin/localeData"
import updateLocale from "dayjs/plugin/updateLocale"
import { string } from "prop-types"

export function adapterLocale(language) {
// Quick and dirty solution while we wait for a more generic solution to finding the user's locale
// Our issue: https://github.com/ICTU/quality-time/issues/10710
// Upstream issue: https://github.com/iamkun/dayjs/issues/732
let locale = "en-GB"
if (language === "nl-NL") {
// Use the Dutch locale, but keep the language English
locale = "nl" // dayjs doesn't have nl-NL
dayjs.extend(updateLocale)
dayjs.extend(localeData)
dayjs.updateLocale("nl", {
months: dayjs.months(),
monthsShort: dayjs.monthsShort(),
weekdays: dayjs.weekdays(),
weekdaysShort: dayjs.weekdaysShort(),
weekdaysMin: dayjs.weekdaysMin(),
})
}
return locale
}
adapterLocale.propTypes = {
language: string,
}
9 changes: 9 additions & 0 deletions components/frontend/src/locale.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { adapterLocale } from "./locale"

it("returns the default locale", () => {
expect(adapterLocale("en")).toBe("en-GB")
})

it("returns the Dutch locale", () => {
expect(adapterLocale("nl-NL")).toBe("nl")
})
1 change: 0 additions & 1 deletion components/frontend/src/metric/MetricDebtParameters.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@ function TechnicalDebtEndDate({ metric, metric_uuid, reload }) {
<DatePicker
defaultValue={debtEndDateTime}
disabled={disabled}
format="YYYY-MM-DD"
label="Technical debt end date"
onChange={(value) => set_metric_attribute(metric_uuid, "debt_end_date", value, reload)}
slotProps={{ field: { clearable: true }, textField: { helperText: helperText } }}
Expand Down
8 changes: 3 additions & 5 deletions components/frontend/src/metric/MetricDebtParameters.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs"
import { render, screen } from "@testing-library/react"
import userEvent from "@testing-library/user-event"
import dayjs from "dayjs"
import { locale_en_gb } from "dayjs/locale/en-gb"

import * as fetch_server_api from "../api/fetch_server_api"
import { DataModel } from "../context/DataModel"
Expand Down Expand Up @@ -38,7 +37,7 @@ const dataModel = {

function renderMetricDebtParameters({ accept_debt = false, debt_end_date = null } = {}) {
render(
<LocalizationProvider dateAdapter={AdapterDayjs} adapterLocale={locale_en_gb}>
<LocalizationProvider dateAdapter={AdapterDayjs}>
<Permissions.Provider value={[EDIT_REPORT_PERMISSION]}>
<DataModel.Provider value={dataModel}>
<MetricDebtParameters
Expand Down Expand Up @@ -113,12 +112,11 @@ it("undoes changes to a comment", async () => {
it("sets the technical debt end date", async () => {
fetch_server_api.fetch_server_api = jest.fn().mockResolvedValue({ ok: true })
renderMetricDebtParameters()
await userEvent.type(screen.getByPlaceholderText(/YYYY-MM-DD/), "20221231{Enter}")
const expectedDate = dayjs("2022-12-31")
await userEvent.type(screen.getByPlaceholderText(/YYYY/), "12312022{Enter}")
expect(fetch_server_api.fetch_server_api).toHaveBeenLastCalledWith(
"post",
"metric/metric_uuid/attribute/debt_end_date",
{ debt_end_date: expectedDate },
{ debt_end_date: dayjs("2022-12-31") },
)
})

Expand Down
1 change: 0 additions & 1 deletion components/frontend/src/source/SourceEntityDetails.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,6 @@ export function SourceEntityDetails({
<DatePicker
defaultValue={status_end_date ? dayjs(status_end_date) : null}
disabled={disabled}
format="YYYY-MM-DD"
label={`${capitalize(name)} status end date`}
onChange={(value) =>
set_source_entity_attribute(
Expand Down
7 changes: 3 additions & 4 deletions components/frontend/src/source/SourceEntityDetails.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs"
import { fireEvent, render, screen } from "@testing-library/react"
import userEvent from "@testing-library/user-event"
import dayjs from "dayjs"
import { locale_en_gb } from "dayjs/locale/en-gb"

import * as source from "../api/source"
import { EDIT_ENTITY_PERMISSION, Permissions } from "../context/Permissions"
Expand All @@ -15,7 +14,7 @@ const reload = jest.fn

function renderSourceEntityDetails({ report = null, status_end_date = null } = {}) {
render(
<LocalizationProvider dateAdapter={AdapterDayjs} adapterLocale={locale_en_gb}>
<LocalizationProvider dateAdapter={AdapterDayjs}>
<Permissions.Provider value={[EDIT_ENTITY_PERMISSION]}>
<SourceEntityDetails
metric_uuid="metric_uuid"
Expand Down Expand Up @@ -94,13 +93,13 @@ it("changes the entity status", () => {
it("shows the entity status end date", async () => {
source.set_source_entity_attribute = jest.fn()
renderSourceEntityDetails({ status_end_date: "20250112" })
expect(screen.queryAllByDisplayValue(/2025-01-12/).length).toBe(1)
expect(screen.queryAllByDisplayValue("01/12/2025").length).toBe(1)
})

it("changes the entity status end date", async () => {
source.set_source_entity_attribute = jest.fn()
renderSourceEntityDetails()
await userEvent.type(screen.getByPlaceholderText(/YYYY-MM-DD/), "22220101{Enter}")
await userEvent.type(screen.getByPlaceholderText(/YYYY/), "01012222{Enter}")
expect(source.set_source_entity_attribute).toHaveBeenCalledWith(
"metric_uuid",
"source_uuid",
Expand Down
1 change: 0 additions & 1 deletion components/frontend/src/source/SourceParameter.js
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,6 @@ export function SourceParameter({
<DatePicker
{...parameterProps}
defaultValue={parameter_value ? dayjs(parameter_value) : null}
format="YYYY-MM-DD"
slotProps={{
field: { clearable: true },
textField: { helperText: helperText, InputProps: { startAdornment: startAdornment } },
Expand Down
7 changes: 3 additions & 4 deletions components/frontend/src/source/SourceParameter.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { LocalizationProvider } from "@mui/x-date-pickers"
import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs"
import { fireEvent, render, screen } from "@testing-library/react"
import userEvent from "@testing-library/user-event"
import { locale_en_gb } from "dayjs/locale/en-gb"

import * as fetch_server_api from "../api/fetch_server_api"
import { EDIT_REPORT_PERMISSION, Permissions } from "../context/Permissions"
Expand Down Expand Up @@ -48,7 +47,7 @@ function renderSourceParameter({
warning = false,
}) {
return render(
<LocalizationProvider dateAdapter={AdapterDayjs} adapterLocale={locale_en_gb}>
<LocalizationProvider dateAdapter={AdapterDayjs}>
<Permissions.Provider value={[EDIT_REPORT_PERMISSION]}>
<SourceParameter
help={help}
Expand Down Expand Up @@ -100,7 +99,7 @@ it("renders a date parameter", () => {
parameter_value: "2021-10-10",
})
expect(screen.queryAllByLabelText(/Date/).length).toBe(1)
expect(screen.queryAllByDisplayValue("2021-10-10").length).toBe(1)
expect(screen.queryAllByDisplayValue("10/10/2021").length).toBe(1)
})

it("renders a date parameter without date", () => {
Expand All @@ -110,7 +109,7 @@ it("renders a date parameter without date", () => {
parameter_value: "",
})
expect(screen.queryAllByLabelText(/Date/).length).toBe(1)
expect(screen.queryAllByPlaceholderText(/YYYY-MM-DD/).length).toBe(1)
expect(screen.queryAllByPlaceholderText(/YYYY/).length).toBe(1)
})

it("renders an integer parameter", () => {
Expand Down
1 change: 1 addition & 0 deletions docs/src/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ If your currently installed *Quality-time* version is not the latest version, pl

### Fixed

- Use browser locale to determine the first day of the week in date pickers. Fixes [#7250](https://github.com/ICTU/quality-time/issues/7250).
- Fix accessibility issues in dark mode. Fixes [#7251](https://github.com/ICTU/quality-time/issues/7251).
- When measuring security warnings with Trivy JSON as source, be prepared for optional fields not being present. Fixes [#10672](https://github.com/ICTU/quality-time/issues/10672).
- Docker compose has been integrated into Docker as a subcommand for a while, but the developer documentation did not reflect that. Change `docker-compose` to `docker compose` in the documentation. Fixes [#10684](https://github.com/ICTU/quality-time/issues/10684).
Expand Down

0 comments on commit 881aed1

Please sign in to comment.