Skip to content

Commit 1877f6f

Browse files
author
alfredpichard
committed
✨(frontend) add shared note widget
classroom dashboard widget to list session-shared notes
1 parent d9496c8 commit 1877f6f

File tree

6 files changed

+178
-6
lines changed

6 files changed

+178
-6
lines changed

src/frontend/packages/lib_classroom/src/components/ClassroomWidgetProvider/index.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { Description } from './widgets/Description';
1111
import { Invite } from './widgets/Invite';
1212
import { Recordings } from './widgets/Recordings';
1313
import { Scheduling } from './widgets/Scheduling';
14+
import { SharedNotes } from './widgets/SharedNotes';
1415
import { SupportSharing } from './widgets/SupportSharing';
1516
import { ToolsAndApplications } from './widgets/ToolsAndApplications';
1617

@@ -21,6 +22,7 @@ enum WidgetType {
2122
INVITE = 'INVITE',
2223
SUPPORT_SHARING = 'SUPPORT_SHARING',
2324
RECORDINGS = 'RECORDINGS',
25+
SHARED_NOTES = 'SHARED_NOTES',
2426
}
2527

2628
const widgetLoader: { [key in WidgetType]: WidgetProps } = {
@@ -48,6 +50,10 @@ const widgetLoader: { [key in WidgetType]: WidgetProps } = {
4850
component: <ToolsAndApplications />,
4951
size: WidgetSize.DEFAULT,
5052
},
53+
[WidgetType.SHARED_NOTES]: {
54+
component: <SharedNotes />,
55+
size: WidgetSize.DEFAULT,
56+
},
5157
};
5258

5359
const classroomWidgets: WidgetType[] = [
@@ -57,6 +63,7 @@ const classroomWidgets: WidgetType[] = [
5763
WidgetType.SCHEDULING,
5864
WidgetType.SUPPORT_SHARING,
5965
WidgetType.RECORDINGS,
66+
WidgetType.SHARED_NOTES,
6067
];
6168

6269
export const ClassroomWidgetProvider = () => {

src/frontend/packages/lib_classroom/src/components/ClassroomWidgetProvider/widgets/Recordings/index.spec.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,14 @@ describe('<Recordings />', () => {
1717
let classroom = classroomMockFactory({ id: '1', started: false });
1818
const classroomRecordings = [
1919
classroomRecordingMockFactory({
20-
started_at: DateTime.fromJSDate(
21-
new Date(2022, 1, 29, 11, 0, 0),
22-
).toISO() as string,
20+
started_at:
21+
DateTime.fromJSDate(new Date(2022, 1, 29, 11, 0, 0)).toISO() ||
22+
undefined,
2323
}),
2424
classroomRecordingMockFactory({
25-
started_at: DateTime.fromJSDate(
26-
new Date(2022, 1, 15, 11, 0, 0),
27-
).toISO() as string,
25+
started_at:
26+
DateTime.fromJSDate(new Date(2022, 1, 15, 11, 0, 0)).toISO() ||
27+
undefined,
2828
}),
2929
];
3030

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import { screen } from '@testing-library/react';
2+
import { InfoWidgetModalProvider } from 'lib-components';
3+
import { render } from 'lib-tests';
4+
import { DateTime } from 'luxon';
5+
import React from 'react';
6+
7+
import {
8+
classroomMockFactory,
9+
classroomSharedNoteMockFactory,
10+
} from '@lib-classroom/utils/tests/factories';
11+
import { wrapInClassroom } from '@lib-classroom/utils/wrapInClassroom';
12+
13+
import { SharedNotes } from '.';
14+
15+
describe('<SharedNotes />', () => {
16+
it('displays a list of available shared notes', () => {
17+
let classroom = classroomMockFactory({ id: '1', started: false });
18+
const classroomSharedNotes = [
19+
classroomSharedNoteMockFactory({
20+
updated_on:
21+
DateTime.fromJSDate(new Date(2022, 1, 29, 11, 0, 0)).toISO() ||
22+
undefined,
23+
}),
24+
classroomSharedNoteMockFactory({
25+
updated_on:
26+
DateTime.fromJSDate(new Date(2022, 1, 15, 11, 0, 0)).toISO() ||
27+
undefined,
28+
}),
29+
];
30+
31+
const { rerender } = render(
32+
wrapInClassroom(
33+
<InfoWidgetModalProvider value={null}>
34+
<SharedNotes />,
35+
</InfoWidgetModalProvider>,
36+
classroom,
37+
),
38+
);
39+
40+
expect(screen.getByText('Shared notes')).toBeInTheDocument();
41+
expect(screen.getByText('No shared note available')).toBeInTheDocument();
42+
43+
// simulate updated classroom
44+
classroom = {
45+
...classroom,
46+
shared_notes: classroomSharedNotes,
47+
};
48+
rerender(
49+
wrapInClassroom(
50+
<InfoWidgetModalProvider value={null}>
51+
<SharedNotes />,
52+
</InfoWidgetModalProvider>,
53+
classroom,
54+
),
55+
);
56+
expect(
57+
screen.queryByText('No shared note available'),
58+
).not.toBeInTheDocument();
59+
expect(
60+
screen.getByText('Tuesday, March 1, 2022 - 11:00 AM'),
61+
).toBeInTheDocument();
62+
expect(
63+
screen.getByText('Tuesday, February 15, 2022 - 11:00 AM'),
64+
).toBeInTheDocument();
65+
});
66+
});
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import { Box } from 'grommet';
2+
import { ClassroomSharedNote, FoldableItem, ItemList } from 'lib-components';
3+
import React from 'react';
4+
import { useIntl, defineMessages } from 'react-intl';
5+
6+
import { useCurrentClassroom } from '@lib-classroom/hooks/useCurrentClassroom';
7+
8+
const messages = defineMessages({
9+
title: {
10+
defaultMessage: 'Shared notes',
11+
description: 'Label for shared notes download in classroom form.',
12+
id: 'component.SharedNotes.title',
13+
},
14+
info: {
15+
defaultMessage: `All available shared notes can be downloaded here.`,
16+
description: 'Helptext for the widget.',
17+
id: 'component.SharedNotes.info',
18+
},
19+
noSharedNoteAvailable: {
20+
defaultMessage: 'No shared note available',
21+
description: 'Message when no recordings are available.',
22+
id: 'component.SharedNotes.noSharedNoteAvailable',
23+
},
24+
downloadSharedNoteLabel: {
25+
defaultMessage: 'Download shared note',
26+
description: 'Label for download recording button.',
27+
id: 'component.SharedNotes.downloadSharedNoteLabel',
28+
},
29+
});
30+
31+
export const SharedNotes = () => {
32+
const classroom = useCurrentClassroom();
33+
const intl = useIntl();
34+
35+
return (
36+
<FoldableItem
37+
infoText={intl.formatMessage(messages.info)}
38+
initialOpenValue
39+
title={intl.formatMessage(messages.title)}
40+
>
41+
<ItemList
42+
itemList={classroom.shared_notes}
43+
noItemsMessage={intl.formatMessage(messages.noSharedNoteAvailable)}
44+
>
45+
{(sharedNote: ClassroomSharedNote) => (
46+
<Box
47+
key={sharedNote.id}
48+
direction="row"
49+
align="center"
50+
fill="horizontal"
51+
height="60px"
52+
gap="medium"
53+
pad="small"
54+
>
55+
<a
56+
title={intl.formatMessage(messages.downloadSharedNoteLabel)}
57+
href={sharedNote.shared_note_url}
58+
target="_blank"
59+
rel="noreferrer noopener"
60+
>
61+
{intl.formatDate(sharedNote.updated_on, {
62+
year: 'numeric',
63+
month: 'long',
64+
day: 'numeric',
65+
weekday: 'long',
66+
}) +
67+
' - ' +
68+
intl.formatDate(sharedNote.updated_on, {
69+
hour: 'numeric',
70+
minute: 'numeric',
71+
})}
72+
</a>
73+
</Box>
74+
)}
75+
</ItemList>
76+
</FoldableItem>
77+
);
78+
};

src/frontend/packages/lib_classroom/src/utils/tests/factories.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
ClassroomDocument,
77
ClassroomInfos,
88
ClassroomRecording,
9+
ClassroomSharedNote,
910
} from 'lib-components';
1011

1112
const { READY } = uploadState;
@@ -29,6 +30,7 @@ export const classroomMockFactory = <T extends Partial<Classroom>>(
2930
invite_token: null,
3031
instructor_token: null,
3132
recordings: [],
33+
shared_notes: [],
3234
enable_waiting_room: false,
3335
enable_shared_notes: true,
3436
enable_chat: true,
@@ -98,3 +100,15 @@ export const classroomRecordingMockFactory = (
98100
...classroomRecording,
99101
};
100102
};
103+
104+
export const classroomSharedNoteMockFactory = (
105+
classroomSharedNote: Partial<ClassroomSharedNote> = {},
106+
): ClassroomSharedNote => {
107+
return {
108+
classroom: faker.datatype.uuid(),
109+
id: faker.datatype.uuid(),
110+
updated_on: faker.date.recent().toISOString(),
111+
shared_note_url: faker.internet.url(),
112+
...classroomSharedNote,
113+
};
114+
};

src/frontend/packages/lib_components/src/types/apps/classroom/models.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export interface Classroom extends Resource {
1717
invite_token: Nullable<string>;
1818
instructor_token: Nullable<string>;
1919
recordings: ClassroomRecording[];
20+
shared_notes: ClassroomSharedNote[];
2021
enable_waiting_room: boolean;
2122
enable_shared_notes: boolean;
2223
enable_chat: boolean;
@@ -132,3 +133,9 @@ export interface ClassroomRecording extends Resource {
132133
video_file_url: string;
133134
started_at: string;
134135
}
136+
137+
export interface ClassroomSharedNote extends Resource {
138+
classroom: string;
139+
shared_note_url: string;
140+
updated_on: string;
141+
}

0 commit comments

Comments
 (0)