Skip to content

Commit

Permalink
💄(frontend) replace to cunningham Datepicker
Browse files Browse the repository at this point in the history
Replace the Grommet Datepicker with the Cunningham Datepicker.
  • Loading branch information
AntoLC committed Aug 3, 2023
1 parent 26ce558 commit f7a521e
Show file tree
Hide file tree
Showing 19 changed files with 333 additions and 166 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ Versioning](https://semver.org/spec/v2.0.0.html).
- refactor videojs xapi handling as videojs plugin
- upgrade react-query to @tanstack/react-query (v4) (#2340)
- Replace component SortableTable by Cunningham DataGrid (#2311)
- Replace grommet DatePicker by Cunningham DatePicker (#2359)

### Fixed

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { screen } from '@testing-library/react';
import { screen, within } from '@testing-library/react';
import faker from 'faker';
import fetchMock from 'fetch-mock';
import { useCurrentResourceContext, useJwt } from 'lib-components';
Expand Down Expand Up @@ -33,7 +33,7 @@ describe('<ClassroomWidgetProvider />', () => {

afterEach(() => fetchMock.restore());

it('renders widgets', () => {
it('renders widgets', async () => {
mockedUseCurrentResourceContext.mockReturnValue([
{
permissions: {
Expand All @@ -55,12 +55,16 @@ describe('<ClassroomWidgetProvider />', () => {

// Description
expect(
screen.getByRole('textbox', { name: 'Description' }),
await screen.findByRole('textbox', { name: 'Description' }),
).toBeInTheDocument();

// Scheduling
const inputStartingAtDate = screen.getByLabelText(/starting date/i);
expect(inputStartingAtDate).toHaveValue('2022/01/13');
const inputStartingAtDate = within(
screen.getByTestId('starting-at-date-picker'),
).getByRole('presentation');

expect(inputStartingAtDate).toHaveTextContent('1/13/2022');

const inputStartingAtTime = screen.getByLabelText(/starting time/i);
expect(inputStartingAtTime).toHaveValue('12:00');
const inputEstimatedDuration = screen.getByLabelText(/estimated duration/i);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
import { fireEvent, screen, waitFor } from '@testing-library/react';
import { screen, waitFor, within } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import fetchMock from 'fetch-mock';
import { InfoWidgetModalProvider, useJwt } from 'lib-components';
import { render } from 'lib-tests';
import { render, userTypeDatePicker } from 'lib-tests';
import { DateTime, Settings } from 'luxon';

import { classroomMockFactory } from '@lib-classroom/utils/tests/factories';
import { wrapInClassroom } from '@lib-classroom/utils/wrapInClassroom';

import { RetentionDate } from '.';

Settings.defaultLocale = 'en';
Settings.defaultZone = 'Europe/Paris';

jest.mock('lib-components', () => ({
...jest.requireActual('lib-components'),
report: jest.fn(),
Expand Down Expand Up @@ -42,27 +46,41 @@ describe('Classroom <RetentionDate />', () => {
),
);

expect(screen.getByText('Retention date')).toBeInTheDocument();
const datePickerInput = screen.getByRole('textbox');
expect(screen.getAllByText('Retention date')).toBeTruthy();

fireEvent.change(datePickerInput, {
target: { value: '2020/01/01' },
});
const inputRetentionDate = within(
screen.getByTestId('retention-date-picker'),
).getByRole('presentation');

expect(inputRetentionDate).toHaveTextContent('mm/dd/yyyy');

expect((datePickerInput as HTMLInputElement).value).toBe('2020/01/01');
const retentionDate = DateTime.local()
.plus({ days: 1 })
.set({ second: 0, millisecond: 0 });

await userTypeDatePicker(
retentionDate,
screen.getAllByText(/Retention date/i)[1],
);

expect(inputRetentionDate).toHaveTextContent(
retentionDate.toLocaleString(),
);

await waitFor(() => expect(fetchMock.calls()).toHaveLength(1));

const lastCall = fetchMock.lastCall();
expect(lastCall).not.toBe(undefined);
expect(lastCall?.[0]).toBe(`/api/classrooms/${mockedClassroom.id}/`);
expect(lastCall?.[1]?.body).toEqual('{"retention_date":"2020-01-01"}');
expect(lastCall?.[1]?.body).toEqual(
`{"retention_date":"${retentionDate.toISODate()!}"}`,
);
expect(lastCall?.[1]?.method).toBe('PATCH');
});

it('renders the component with a default date and deletes it', async () => {
const mockedClassroom = classroomMockFactory({
retention_date: '2020-01-01',
retention_date: '2020-03-01',
});

fetchMock.mock(`/api/classrooms/${mockedClassroom.id}/`, 200, {
Expand All @@ -78,10 +96,12 @@ describe('Classroom <RetentionDate />', () => {
),
);

expect(screen.getByText('Retention date')).toBeInTheDocument();
const datePickerInput = await screen.findByRole('textbox');
expect(screen.getAllByText('Retention date')).toBeTruthy();

expect((datePickerInput as HTMLInputElement).value).toBe('2020/01/01');
const inputRetentionDate = within(
screen.getByTestId('retention-date-picker'),
).getByRole('presentation');
expect(inputRetentionDate).toHaveTextContent('3/1/2020');

const deleteButton = await screen.findByRole('button', {
name: 'Delete retention date',
Expand Down Expand Up @@ -114,7 +134,7 @@ describe('Classroom <RetentionDate />', () => {
),
);

expect(screen.getByText('Retention date')).toBeInTheDocument();
expect(screen.getAllByText('Retention date')).toBeTruthy();

const deleteButton = await screen.findByRole('button', {
name: 'Delete retention date',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Box, Button, DateInput } from 'grommet';
import { CunninghamProvider, DatePicker } from '@openfun/cunningham-react';
import { Box, Button } from 'grommet';
import { Nullable } from 'lib-common';
import { Classroom, FoldableItem, debounce } from 'lib-components';
import { DateTime } from 'luxon';
Expand Down Expand Up @@ -68,15 +69,20 @@ export const RetentionDate = () => {
},
);

function onChange(new_retention_date: string | string[]) {
let new_retention_date_formatted = null;
if (new_retention_date && typeof new_retention_date === 'string') {
const utcDateTime = DateTime.fromISO(new_retention_date, { zone: 'utc' });
const localDateTime = utcDateTime.toLocal();
new_retention_date_formatted = localDateTime.toFormat('yyyy-MM-dd');
function onChange(new_retention_date: string | null) {
setSelectedRetentionDate(new_retention_date || null);

if (
new_retention_date &&
new Date(new_retention_date).getTime() <
new Date(DateTime.local().toISODate() || '').getTime()
) {
return;
}
debouncedUpdatedClassroom({ retention_date: new_retention_date_formatted });
setSelectedRetentionDate(new_retention_date_formatted);

debouncedUpdatedClassroom({
retention_date: new_retention_date || null,
});
}

return (
Expand All @@ -85,12 +91,22 @@ export const RetentionDate = () => {
initialOpenValue
title={intl.formatMessage(messages.title)}
>
<Box direction="column" gap="small" style={{ marginTop: '0.75rem' }}>
<DateInput
format={intl.locale === 'fr' ? 'dd/mm/yyyy' : 'yyyy/mm/dd'}
value={selectedRetentionDate || ''}
onChange={({ value }) => onChange(value)}
/>
<Box
direction="column"
gap="small"
style={{ marginTop: '0.75rem' }}
data-testid="retention-date-picker"
>
<CunninghamProvider>
<DatePicker
fullWidth
label={intl.formatMessage(messages.title)}
locale={intl.locale}
minValue={DateTime.local().toISO() as string}
onChange={(value) => onChange(value)}
value={selectedRetentionDate || null}
/>
</CunninghamProvider>
<StyledAnchorButton
disabled={!selectedRetentionDate}
a11yTitle={intl.formatMessage(
Expand All @@ -105,7 +121,7 @@ export const RetentionDate = () => {
messages.deleteClassroomRetentionDateButton,
)}
onClick={() => {
onChange('');
onChange(null);
}}
/>
</Box>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { fireEvent, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import userEventInit from '@testing-library/user-event';
import fetchMock from 'fetch-mock';
import { InfoWidgetModalProvider } from 'lib-components';
import { Deferred, render } from 'lib-tests';
import { Deferred, render, userTypeDatePicker } from 'lib-tests';
import { DateTime, Duration, Settings } from 'luxon';

import { classroomMockFactory } from '@lib-classroom/utils/tests/factories';
Expand All @@ -23,6 +23,10 @@ jest.mock('lib-components', () => ({
Settings.defaultLocale = 'en';
Settings.defaultZone = 'Europe/Paris';

const userEvent = userEventInit.setup({
advanceTimers: jest.advanceTimersByTime,
});

describe('<Scheduling />', () => {
beforeEach(() => {
jest.useFakeTimers();
Expand Down Expand Up @@ -73,12 +77,12 @@ describe('<Scheduling />', () => {
),
);

// using userEvent.type with following input doesn't work
const inputStartingAtDate = screen.getByLabelText(/starting date/i);
fireEvent.change(inputStartingAtDate, {
target: { value: startingAt.toFormat('yyyy/MM/dd') },
});
fireEvent.blur(inputStartingAtDate);
await userTypeDatePicker(
startingAt,
screen.getByText(/Starting date/i),
userEvent,
);

deferredPatch.resolve({ message: 'Classroom scheduled.' });

// using userEvent.type with following input doesn't work
Expand Down
21 changes: 21 additions & 0 deletions src/frontend/packages/lib_common/src/cunningham-style.css
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,24 @@
gap: 1rem;
}
}
/**
* Date picker
*/
.c__popover.c__popover--borderless {
z-index: 3;
}
.c__date-picker__wrapper {
transition: all var(--c--theme--transitions--duration)
var(--c--theme--transitions--ease-out);
}
.c__date-picker:not(.c__date-picker--disabled):hover .c__date-picker__wrapper {
box-shadow: var(--c--theme--colors--primary-500) 0px 0px 0px 2px;
}
.c__date-picker.c__date-picker--invalid:not(.c__date-picker--disabled):hover
.c__date-picker__wrapper {
box-shadow: var(--c--theme--colors--danger-300) 0px 0px 0px 2px;
}
.c__date-picker__wrapper button[aria-label='Clear date'],
.c__date-picker.c__date-picker--invalid .c__date-picker__wrapper * {
color: var(--c--theme--colors--danger-300);
}
16 changes: 16 additions & 0 deletions src/frontend/packages/lib_common/src/cunningham-tokens.css
Original file line number Diff line number Diff line change
Expand Up @@ -101,4 +101,20 @@
--c--theme--font--weights-datagrid-header: var(--c--theme--font--weights--extrabold);
--c--theme--font--size-datagrid-header: var(--c--theme--font--sizes--ml);
--c--theme--font--size-datagrid-cell: var(--c--theme--font--sizes--ml);
--c--components--forms-datepicker--color: var(
--c--theme--colors--primary-400
);
--c--components--forms-datepicker--border-color: var(
--c--theme--colors--primary-500
);
--c--components--forms-datepicker--border-radius--hover: var(
--c--components--forms-datepicker--border-radius
);
--c--components--forms-datepicker--border-radius--focus: var(
--c--components--forms-datepicker--border-radius
);
--c--components--forms-datepicker--border-color--hover: var(
--c--components--forms-datepicker--border-color
);
--c--components--forms-field--color: var(--c--theme--colors--primary-500);
}
1 change: 1 addition & 0 deletions src/frontend/packages/lib_components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"prettier": "prettier --list-different '**/*.+(ts|tsx|json|js|jsx)' --ignore-path ../../../.prettierignore"
},
"peerDependencies": {
"@openfun/cunningham-react": "*",
"@tanstack/react-query": "*",
"@tanstack/react-query-devtools": "*",
"grommet": "*",
Expand Down
Loading

0 comments on commit f7a521e

Please sign in to comment.