Skip to content

Commit

Permalink
Add support to start week on Monday
Browse files Browse the repository at this point in the history
  • Loading branch information
rsandz committed Feb 3, 2024
1 parent e181be4 commit 01453d7
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 2 deletions.
13 changes: 13 additions & 0 deletions src/gui/Calendar/CalendarHeader.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { weekdaysShort } from "moment";
import React from "react";
import styled from "styled-components";
import useOnSettingsChange from "../hooks/useOnSettingsChange";
import { WEEK_START_DAY, WeekStartDay } from "@constants/Settings";

const HeaderCell = styled.th`
font-size: var(--joplin-font-size);
Expand All @@ -19,6 +21,17 @@ function CalendarHeader(props: CalendarHeaderProps) {
const calendarHeader = weekdaysShort().map((day) => (
<HeaderCell>{day}</HeaderCell>
));

const weekStartDay = useOnSettingsChange<WeekStartDay>(
WEEK_START_DAY,
WeekStartDay.Sunday
);

// Need to shift the headers based on the week start day
if (weekStartDay === WeekStartDay.Monday) {
calendarHeader.push(calendarHeader.shift());
}

return <HeaderRow>{...calendarHeader}</HeaderRow>;
}

Expand Down
28 changes: 28 additions & 0 deletions src/gui/Calendar/__tests__/Calendar.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,15 @@ import moment from "moment";
import { act } from "react-dom/test-utils";
import useGetMonthStatistics from "../../hooks/useGetMonthStatistics";
import useWebviewApiOnMessage from "../../hooks/useWebViewApiOnMessage";
import { WeekStartDay } from "@constants/Settings";
import useOnSettingsChange from "../../hooks/useOnSettingsChange";

jest.mock("../../hooks/useGetMonthStatistics");
const mockedUseGetMonthStatistics = jest.mocked(useGetMonthStatistics);

jest.mock("../../hooks/useOnSettingsChange");
const mockedUseOnSettingsChange = jest.mocked(useOnSettingsChange);

global.webviewApi = {
postMessage: jest.fn(),
onMessage: jest.fn(),
Expand All @@ -26,6 +31,7 @@ describe("calendar", () => {
},
refetch: jest.fn(),
});
mockedUseOnSettingsChange.mockReset();
});

it("displays dates correctly", () => {
Expand All @@ -51,6 +57,28 @@ describe("calendar", () => {
}
});

it("displays dates correctly if week starts on Monday", () => {
mockedUseOnSettingsChange.mockReturnValue(WeekStartDay.Monday);

const date = moment("May-29-2023", "MMM-DD-YYYY");
render(<Calendar selectedDate={date} />);

expect(screen.getByText("May 2023")).toBeDefined();

const cells = screen.getAllByRole("cell");
expect(cells).toHaveLength(42); // 7 days * 6 rows

// Assert May (No April)
for (let i = 0; i <= 30; i++) {
expect(cells[i].textContent).toEqual((i + 1).toString());
}

// Assert June
for (let i = 1; i <= 11; i++) {
expect(cells[i + 30].textContent).toEqual(i.toString());
}
});

it("calls callback when next month clicked", () => {
const nextMonthCallback = jest.fn();
const date = moment("May-29-2023", "MMM-DD-YYYY");
Expand Down
27 changes: 25 additions & 2 deletions src/gui/Calendar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import useGetMonthStatistics from "../hooks/useGetMonthStatistics";
import MsgType from "@constants/messageTypes";
import { PluginPostMessage } from "@constants/pluginMessageTypes";
import useWebviewApiOnMessage from "../hooks/useWebViewApiOnMessage";
import useOnSettingsChange from "../hooks/useOnSettingsChange";
import { WEEK_START_DAY, WeekStartDay } from "@constants/Settings";

const DAYS_IN_A_WEEK = 7;
const CALENDAR_ROWS = 6;
Expand Down Expand Up @@ -78,16 +80,37 @@ function Calendar({
[onKeyboardNavigation]
);

const weekStartDay = useOnSettingsChange<WeekStartDay>(
WEEK_START_DAY,
WeekStartDay.Sunday
);

const currentMonthFirstDay = shownMonth.startOf("month");

const calendarBody: React.JSX.Element[] = [];
const firstRowOffset = -currentMonthFirstDay.weekday();
let firstRowBacktrackOffset;
if (weekStartDay === WeekStartDay.Monday) {
// If the current month starts on a day other than Monday, we need to backtrack.
// Monday has isoWeek 1, and we need to backtrack 0 days.
// Tuesday has isoWeek 2, and we need to backtrack 1 days.
// ...
// Sunday has isoWeek 7, and we need to backtrack 6 days.
firstRowBacktrackOffset = currentMonthFirstDay.isoWeekday() - 1;
} else {
// Fallback to asssuming week starts on Sunday.
// If current month starts on a day other than Sunday, we need to backtrack.
// Monday has isoWeek 1, and we need to backtrack 1 day.
// Tuesday has isoWeek 2, and we need to backtrack 2 days.
// ...
// Sunday has isoWeek 7, and we need to backtrack no days.
firstRowBacktrackOffset = currentMonthFirstDay.isoWeekday() % 7;
}

// Note: Moment JS uses in place operations
const workingDate = currentMonthFirstDay.clone();

// Offset to fill in dates from previous month till first of current month.
workingDate.add(firstRowOffset, "days");
workingDate.subtract(firstRowBacktrackOffset, "days");

for (let row = 0; row < CALENDAR_ROWS; row++) {
const cols: React.JSX.Element[] = [];
Expand Down

0 comments on commit 01453d7

Please sign in to comment.