diff --git a/ui/package-lock.json b/ui/package-lock.json index d9251d434..333bcf3cc 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -38,7 +38,7 @@ "react": "17.0.2", "react-app-polyfill": "3.0.0", "react-cool-dimensions": "3.0.1", - "react-day-picker": "8.10.1", + "react-day-picker": "9.6.7", "react-dom": "17.0.2", "react-hotkeys-hook": "5.2.4", "react-idle-timer": "5.7.2", @@ -2077,6 +2077,12 @@ "node": ">=18" } }, + "node_modules/@date-fns/tz": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@date-fns/tz/-/tz-1.2.0.tgz", + "integrity": "sha512-LBrd7MiJZ9McsOgxqWX7AaxrDjcFVjWH/tIKJd7pnR7McaslGYOP1QmmiBXdJH/H/yLCT+rcQ7FaPBUxRGUtrg==", + "license": "MIT" + }, "node_modules/@emnapi/core": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.8.1.tgz", @@ -6521,6 +6527,12 @@ "url": "https://github.com/sponsors/kossnocorp" } }, + "node_modules/date-fns-jalali": { + "version": "4.1.0-0", + "resolved": "https://registry.npmjs.org/date-fns-jalali/-/date-fns-jalali-4.1.0-0.tgz", + "integrity": "sha512-hTIP/z+t+qKwBDcmmsnmjWTduxCg+5KfdqWQvb2X/8C9+knYY6epN/pfxdDuyVlSVeFz0sM5eEfwIUQ70U4ckg==", + "license": "MIT" + }, "node_modules/debug": { "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", @@ -11141,17 +11153,24 @@ } }, "node_modules/react-day-picker": { - "version": "8.10.1", - "resolved": "https://registry.npmjs.org/react-day-picker/-/react-day-picker-8.10.1.tgz", - "integrity": "sha512-TMx7fNbhLk15eqcMt+7Z7S2KF7mfTId/XJDjKE8f+IUcFn0l08/kI4FiYTL/0yuOLmEcbR4Fwe3GJf/NiiMnPA==", + "version": "9.6.7", + "resolved": "https://registry.npmjs.org/react-day-picker/-/react-day-picker-9.6.7.tgz", + "integrity": "sha512-rCSt6X8FXQWpjykns/azRXjJk3cMSzkzGbDEXuEveFGNZgOjZULdJQ5wsu8Zfyo8ZgPBoYCBKQ5wRrgJfhJGbg==", "license": "MIT", + "dependencies": { + "@date-fns/tz": "1.2.0", + "date-fns": "4.1.0", + "date-fns-jalali": "4.1.0-0" + }, + "engines": { + "node": ">=18" + }, "funding": { "type": "individual", "url": "https://github.com/sponsors/gpbl" }, "peerDependencies": { - "date-fns": "^2.28.0 || ^3.0.0", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + "react": ">=16.8.0" } }, "node_modules/react-dom": { diff --git a/ui/package.json b/ui/package.json index 06c67dc40..552239e1c 100644 --- a/ui/package.json +++ b/ui/package.json @@ -34,7 +34,7 @@ "react": "17.0.2", "react-app-polyfill": "3.0.0", "react-cool-dimensions": "3.0.1", - "react-day-picker": "8.10.1", + "react-day-picker": "9.6.7", "react-dom": "17.0.2", "react-hotkeys-hook": "5.2.4", "react-idle-timer": "5.7.2", @@ -90,11 +90,6 @@ "vite": "7.3.1", "vite-tsconfig-paths": "6.1.1" }, - "overrides": { - "react-day-picker@8.10.1": { - "date-fns": "4.1.0" - } - }, "scripts": { "start": "VITE_APP_BACKEND_URI=http://localhost:8080 vite", "build": "tsc && vite build", diff --git a/ui/src/Components/SilenceModal/DateTimeSelect/__snapshots__/index.test.tsx.snap b/ui/src/Components/SilenceModal/DateTimeSelect/__snapshots__/index.test.tsx.snap index 324097d12..ba4231191 100644 --- a/ui/src/Components/SilenceModal/DateTimeSelect/__snapshots__/index.test.tsx.snap +++ b/ui/src/Components/SilenceModal/DateTimeSelect/__snapshots__/index.test.tsx.snap @@ -369,123 +369,120 @@ exports[` 'Ends' tab matches snapshot 1`] = ` class="d-flex justify-content-center align-items-center" >
+
- -
- - -
+
+ aria-selected="true" + class="rdp-day rdp-hidden rdp-outside rdp-selected rdp-range_middle" + data-day="2061-01-30" + data-hidden="true" + data-month="2061-01" + data-outside="true" + data-selected="true" + role="gridcell" + /> + aria-selected="true" + class="rdp-day rdp-hidden rdp-outside rdp-selected rdp-range_middle" + data-day="2061-01-31" + data-hidden="true" + data-month="2061-01" + data-outside="true" + data-selected="true" + role="gridcell" + /> + class="rdp-day rdp-hidden rdp-outside" + data-day="2061-03-01" + data-hidden="true" + data-month="2061-03" + data-outside="true" + role="gridcell" + /> + class="rdp-day rdp-hidden rdp-outside" + data-day="2061-03-02" + data-hidden="true" + data-month="2061-03" + data-outside="true" + role="gridcell" + /> + class="rdp-day rdp-hidden rdp-outside" + data-day="2061-03-03" + data-hidden="true" + data-month="2061-03" + data-outside="true" + role="gridcell" + /> + class="rdp-day rdp-hidden rdp-outside" + data-day="2061-03-04" + data-hidden="true" + data-month="2061-03" + data-outside="true" + role="gridcell" + /> + class="rdp-day rdp-hidden rdp-outside" + data-day="2061-03-05" + data-hidden="true" + data-month="2061-03" + data-outside="true" + role="gridcell" + /> - - - - -
-
- -
-
+
'Starts' tab matches snapshot 1`] = ` class="d-flex justify-content-center align-items-center" >
+
- -
- - -
+
+ aria-selected="true" + class="rdp-day rdp-hidden rdp-outside rdp-selected rdp-range_middle" + data-day="2060-03-01" + data-hidden="true" + data-month="2060-03" + data-outside="true" + data-selected="true" + role="gridcell" + /> + aria-selected="true" + class="rdp-day rdp-hidden rdp-outside rdp-selected rdp-range_middle" + data-day="2060-03-02" + data-hidden="true" + data-month="2060-03" + data-outside="true" + data-selected="true" + role="gridcell" + /> + aria-selected="true" + class="rdp-day rdp-hidden rdp-outside rdp-selected rdp-range_middle" + data-day="2060-03-03" + data-hidden="true" + data-month="2060-03" + data-outside="true" + data-selected="true" + role="gridcell" + /> + aria-selected="true" + class="rdp-day rdp-hidden rdp-outside rdp-selected rdp-range_middle" + data-day="2060-03-04" + data-hidden="true" + data-month="2060-03" + data-outside="true" + data-selected="true" + role="gridcell" + /> + aria-selected="true" + class="rdp-day rdp-hidden rdp-outside rdp-selected rdp-range_middle" + data-day="2060-03-05" + data-hidden="true" + data-month="2060-03" + data-outside="true" + data-selected="true" + role="gridcell" + /> + aria-selected="true" + class="rdp-day rdp-hidden rdp-outside rdp-selected rdp-range_middle" + data-day="2060-03-06" + data-hidden="true" + data-month="2060-03" + data-outside="true" + data-selected="true" + role="gridcell" + /> - - - - -
-
- -
-
+
{ describe("", () => { it("selecting date on DayPicker updates startsAt", () => { + // Verifies clicking a day in the calendar updates the startsAt date const { container } = renderTabContentStart(); expect(silenceFormStore.data.startsAt.toISOString()).toBe( new Date(2060, 1, 1, 0, 0, 0).toISOString(), ); - const dayButtons = container.querySelectorAll("button.rdp-button.rdp-day"); + // In v9, day buttons use .rdp-day_button class + const dayButtons = container.querySelectorAll("button.rdp-day_button"); fireEvent.click(dayButtons[17]); expect(silenceFormStore.data.startsAt.toISOString()).toBe( new Date(2060, 1, 18, 0, 0, 0).toISOString(), @@ -222,17 +224,15 @@ describe("", () => { expect(silenceFormStore.data.startsAt.toISOString()).toBe( new Date(2060, 1, 1, 0, 0, 0).toISOString(), ); - expect(container.querySelector(".rdp-caption_label")?.textContent).toBe( + expect(container.querySelector(".rdp-month_caption")?.textContent).toBe( "February 2060", ); - fireEvent.click( - container.querySelector("button.rdp-button.rdp-nav_button_next")!, - ); - expect(container.querySelector(".rdp-caption_label")?.textContent).toBe( + fireEvent.click(container.querySelector("button.rdp-button_next")!); + expect(container.querySelector(".rdp-month_caption")?.textContent).toBe( "March 2060", ); fireEvent.click(container.querySelector("button.btn.btn-light.btn-sm")!); - expect(container.querySelector(".rdp-caption_label")?.textContent).toBe( + expect(container.querySelector(".rdp-month_caption")?.textContent).toBe( format(new Date(), "LLLL yyyy"), ); }); @@ -353,11 +353,13 @@ const renderTabContentEnd = () => { describe("", () => { it("Selecting date on DayPicker updates endsAt", () => { + // Verifies clicking a day in the calendar updates the endsAt date const { container } = renderTabContentEnd(); expect(silenceFormStore.data.endsAt.toISOString()).toBe( new Date(2061, 1, 1, 0, 0, 0).toISOString(), ); - const dayButtons = container.querySelectorAll("button.rdp-button.rdp-day"); + // In v9, day buttons use .rdp-day_button class + const dayButtons = container.querySelectorAll("button.rdp-day_button"); fireEvent.click(dayButtons[23]); expect(silenceFormStore.data.endsAt.toISOString()).toBe( new Date(2061, 1, 24, 0, 0, 0).toISOString(), @@ -374,17 +376,15 @@ describe("", () => { expect(silenceFormStore.data.endsAt.toISOString()).toBe( new Date(2061, 1, 1, 0, 0, 0).toISOString(), ); - expect(container.querySelector(".rdp-caption_label")?.textContent).toBe( + expect(container.querySelector(".rdp-month_caption")?.textContent).toBe( "February 2061", ); - fireEvent.click( - container.querySelector("button.rdp-button.rdp-nav_button_next")!, - ); - expect(container.querySelector(".rdp-caption_label")?.textContent).toBe( + fireEvent.click(container.querySelector("button.rdp-button_next")!); + expect(container.querySelector(".rdp-month_caption")?.textContent).toBe( "March 2061", ); fireEvent.click(container.querySelector("button.btn.btn-light.btn-sm")!); - expect(container.querySelector(".rdp-caption_label")?.textContent).toBe( + expect(container.querySelector(".rdp-month_caption")?.textContent).toBe( format(new Date(), "LLLL yyyy"), ); }); diff --git a/ui/src/Components/SilenceModal/DateTimeSelect/index.tsx b/ui/src/Components/SilenceModal/DateTimeSelect/index.tsx index 2320a6748..cf2f15040 100644 --- a/ui/src/Components/SilenceModal/DateTimeSelect/index.tsx +++ b/ui/src/Components/SilenceModal/DateTimeSelect/index.tsx @@ -9,7 +9,7 @@ import { setSeconds } from "date-fns/setSeconds"; import { isSameMonth } from "date-fns/isSameMonth"; import { DayPicker } from "react-day-picker"; -import "react-day-picker/dist/style.css"; +import "react-day-picker/style.css"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faCalendarDay } from "@fortawesome/free-solid-svg-icons/faCalendarDay"; @@ -89,8 +89,8 @@ const TabContentStart: FC<{ disabled={{ before: nowZeroSeconds(), }} - onDayClick={(val) => { - const startsAt = new Date(val); + onDayClick={(date) => { + const startsAt = new Date(date); startsAt.setHours(silenceFormStore.data.startsAt.getHours()); startsAt.setMinutes(silenceFormStore.data.startsAt.getMinutes()); startsAt.setSeconds(0); @@ -148,8 +148,8 @@ const TabContentEnd: FC<{ silenceFormStore: SilenceFormStore }> = observer( disabled={{ before: setSeconds(silenceFormStore.data.startsAt, 0), }} - onDayClick={(val) => { - const endsAt = new Date(val); + onDayClick={(date) => { + const endsAt = new Date(date); endsAt.setHours(silenceFormStore.data.endsAt.getHours()); endsAt.setMinutes(silenceFormStore.data.endsAt.getMinutes()); endsAt.setSeconds(0); diff --git a/ui/src/Styles/Components/_DateTimeSelect.scss b/ui/src/Styles/Components/_DateTimeSelect.scss index f18862a0f..da0e99e06 100644 --- a/ui/src/Styles/Components/_DateTimeSelect.scss +++ b/ui/src/Styles/Components/_DateTimeSelect.scss @@ -1,12 +1,30 @@ .components-date-range { --rdp-cell-size: 40px; + --rdp-accent-color: #{$secondary}; + --rdp-selected-border: none; + --rdp-range_middle-background-color: #{$light}; - .rdp-cell { + .rdp-day_button { + padding: 0; + } + + .rdp-selected { + font-weight: inherit; + font-size: inherit; + } + + .rdp-button_previous, + .rdp-button_next { + color: $secondary; + } + + .rdp-day { + padding: 0; width: 36px; height: 36px; } - .rdp-button { + .rdp-day_button { &:focus, &:active { outline: none; @@ -19,67 +37,75 @@ background-color: $light; } - &.rdp-day_disabled { + &.rdp-disabled { opacity: 1; } } - .rdp-caption_label { + .rdp-month_caption { font-weight: 400; font-size: 120%; } - .rdp-table { + .rdp-month_grid { border-collapse: inherit; border-spacing: 0 1px; } - .rdp-day { + .rdp-day_button { &:hover, &:active { border-radius: 0.5rem; } - &:not(.rdp-day_disabled):not(.rdp-day_range_middle):not(.rdp-day_selected):hover { + &:not(.rdp-disabled):not(.rdp-range_middle):not(.rdp-selected):hover { background-color: $light; } + } - &.rdp-day_disabled { - color: $secondary; - } + .rdp-day.rdp-disabled .rdp-day_button { + color: $secondary; + } - &.rdp-day_today { - font-weight: 600; - } + .rdp-day.rdp-today .rdp-day_button { + font-weight: 600; + } - &.rdp-day_selected { - border-radius: 0; + .rdp-day.rdp-selected .rdp-day_button { + border-radius: 0; + font-weight: 400; + font-size: inherit; + } - &.rdp-day_range_start, - &.rdp-day_range_end { - font-weight: 600; - background-color: $primary; - } + .rdp-day.rdp-selected.rdp-range_start .rdp-day_button, + .rdp-day.rdp-selected.rdp-range_end .rdp-day_button { + font-weight: 600; + background-color: $primary; - &.rdp-day_range_start { - border-top-left-radius: 0.5rem; - border-bottom-left-radius: 0.5rem; - } - - &.rdp-day_range_end { - border-top-right-radius: 0.5rem; - border-bottom-right-radius: 0.5rem; - } - - &.rdp-day_start:not(.rdp-day_range_middle), - &.rdp-day_end:not(.rdp-day_range_middle) { - background-color: $primary; - color: $white; - } - &.rdp-day_range_middle:not(.rdp-day_range_start):not(.rdp-day_range_end) { - background-color: $light; - color: $components-date-range-sub-color; - } + &:hover, + &:active, + &:focus { + background-color: $primary; } } + + .rdp-day.rdp-selected.rdp-range_start .rdp-day_button { + border-top-left-radius: 0.5rem; + border-bottom-left-radius: 0.5rem; + } + + .rdp-day.rdp-selected.rdp-range_end .rdp-day_button { + border-top-right-radius: 0.5rem; + border-bottom-right-radius: 0.5rem; + } + + .rdp-day.rdp-selected:not(.rdp-range_middle) .rdp-day_button { + background-color: $primary; + color: $white; + } + + .rdp-day.rdp-selected.rdp-range_middle:not(.rdp-range_start):not(.rdp-range_end) .rdp-day_button { + background-color: $light; + color: $components-date-range-sub-color; + } }