Skip to content

Commit c13806a

Browse files
committed
feat: Sync units in course outline
1 parent 9824502 commit c13806a

File tree

11 files changed

+367
-75
lines changed

11 files changed

+367
-75
lines changed

src/course-outline/__mocks__/courseOutlineIndex.js

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,11 @@ module.exports = {
292292
selectedPartitionIndex: -1,
293293
selectedGroupsLabel: '',
294294
},
295+
upstreamInfo: {
296+
readyToSync: false,
297+
upstreamRef: undefined,
298+
versionSynced: undefined,
299+
},
295300
},
296301
],
297302
},
@@ -675,6 +680,11 @@ module.exports = {
675680
selectedPartitionIndex: -1,
676681
selectedGroupsLabel: '',
677682
},
683+
upstreamInfo: {
684+
readyToSync: false,
685+
upstreamRef: undefined,
686+
versionSynced: undefined,
687+
},
678688
},
679689
{
680690
id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@vertical_2dbb0072785e',
@@ -759,6 +769,11 @@ module.exports = {
759769
selectedPartitionIndex: -1,
760770
selectedGroupsLabel: '',
761771
},
772+
upstreamInfo: {
773+
readyToSync: false,
774+
upstreamRef: undefined,
775+
versionSynced: undefined,
776+
},
762777
},
763778
{
764779
id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@vertical_98cf62510471',
@@ -843,6 +858,11 @@ module.exports = {
843858
selectedPartitionIndex: -1,
844859
selectedGroupsLabel: '',
845860
},
861+
upstreamInfo: {
862+
readyToSync: false,
863+
upstreamRef: undefined,
864+
versionSynced: undefined,
865+
},
846866
},
847867
{
848868
id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@vertical_d32bf9b2242c',
@@ -927,6 +947,11 @@ module.exports = {
927947
selectedPartitionIndex: -1,
928948
selectedGroupsLabel: '',
929949
},
950+
upstreamInfo: {
951+
readyToSync: false,
952+
upstreamRef: undefined,
953+
versionSynced: undefined,
954+
},
930955
},
931956
{
932957
id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@4e592689563243c484af947465eaef0d',
@@ -1011,6 +1036,11 @@ module.exports = {
10111036
selectedPartitionIndex: -1,
10121037
selectedGroupsLabel: '',
10131038
},
1039+
upstreamInfo: {
1040+
readyToSync: false,
1041+
upstreamRef: undefined,
1042+
versionSynced: undefined,
1043+
},
10141044
},
10151045
],
10161046
},
@@ -1196,6 +1226,11 @@ module.exports = {
11961226
selectedPartitionIndex: -1,
11971227
selectedGroupsLabel: '',
11981228
},
1229+
upstreamInfo: {
1230+
readyToSync: false,
1231+
upstreamRef: undefined,
1232+
versionSynced: undefined,
1233+
},
11991234
},
12001235
{
12011236
id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@vertical_aae927868e55',
@@ -1280,6 +1315,11 @@ module.exports = {
12801315
selectedPartitionIndex: -1,
12811316
selectedGroupsLabel: '',
12821317
},
1318+
upstreamInfo: {
1319+
readyToSync: false,
1320+
upstreamRef: undefined,
1321+
versionSynced: undefined,
1322+
},
12831323
},
12841324
{
12851325
id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@vertical_c037f3757df1',
@@ -1364,6 +1404,11 @@ module.exports = {
13641404
selectedPartitionIndex: -1,
13651405
selectedGroupsLabel: '',
13661406
},
1407+
upstreamInfo: {
1408+
readyToSync: false,
1409+
upstreamRef: undefined,
1410+
versionSynced: undefined,
1411+
},
13671412
},
13681413
{
13691414
id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@vertical_bc69a47c6fae',
@@ -1448,6 +1493,11 @@ module.exports = {
14481493
selectedPartitionIndex: -1,
14491494
selectedGroupsLabel: '',
14501495
},
1496+
upstreamInfo: {
1497+
readyToSync: false,
1498+
upstreamRef: undefined,
1499+
versionSynced: undefined,
1500+
},
14511501
},
14521502
{
14531503
id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@8f89194410954e768bde1764985454a7',
@@ -1532,6 +1582,11 @@ module.exports = {
15321582
selectedPartitionIndex: -1,
15331583
selectedGroupsLabel: '',
15341584
},
1585+
upstreamInfo: {
1586+
readyToSync: false,
1587+
upstreamRef: undefined,
1588+
versionSynced: undefined,
1589+
},
15351590
},
15361591
],
15371592
},
@@ -1717,6 +1772,11 @@ module.exports = {
17171772
selectedPartitionIndex: -1,
17181773
selectedGroupsLabel: '',
17191774
},
1775+
upstreamInfo: {
1776+
readyToSync: false,
1777+
upstreamRef: undefined,
1778+
versionSynced: undefined,
1779+
},
17201780
},
17211781
],
17221782
},
@@ -1995,6 +2055,11 @@ module.exports = {
19952055
selectedPartitionIndex: -1,
19962056
selectedGroupsLabel: '',
19972057
},
2058+
upstreamInfo: {
2059+
readyToSync: false,
2060+
upstreamRef: undefined,
2061+
versionSynced: undefined,
2062+
},
19982063
},
19992064
{
20002065
id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@vertical_f04afeac0131',
@@ -2079,6 +2144,11 @@ module.exports = {
20792144
selectedPartitionIndex: -1,
20802145
selectedGroupsLabel: '',
20812146
},
2147+
upstreamInfo: {
2148+
readyToSync: false,
2149+
upstreamRef: undefined,
2150+
versionSynced: undefined,
2151+
},
20822152
},
20832153
{
20842154
id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@b6662b497c094bcc9b870d8270c90c93',
@@ -2163,6 +2233,11 @@ module.exports = {
21632233
selectedPartitionIndex: -1,
21642234
selectedGroupsLabel: '',
21652235
},
2236+
upstreamInfo: {
2237+
readyToSync: false,
2238+
upstreamRef: undefined,
2239+
versionSynced: undefined,
2240+
},
21662241
},
21672242
{
21682243
id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@f91d8d31f7cf48ce990f8d8745ae4cfa',
@@ -2247,6 +2322,11 @@ module.exports = {
22472322
selectedPartitionIndex: -1,
22482323
selectedGroupsLabel: '',
22492324
},
2325+
upstreamInfo: {
2326+
readyToSync: false,
2327+
upstreamRef: undefined,
2328+
versionSynced: undefined,
2329+
},
22502330
},
22512331
{
22522332
id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@vertical_ac391cde8a91',
@@ -2331,6 +2411,11 @@ module.exports = {
23312411
selectedPartitionIndex: -1,
23322412
selectedGroupsLabel: '',
23332413
},
2414+
upstreamInfo: {
2415+
readyToSync: false,
2416+
upstreamRef: undefined,
2417+
versionSynced: undefined,
2418+
},
23342419
},
23352420
{
23362421
id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@vertical_36e0beb03f0a',
@@ -2415,6 +2500,11 @@ module.exports = {
24152500
selectedPartitionIndex: -1,
24162501
selectedGroupsLabel: '',
24172502
},
2503+
upstreamInfo: {
2504+
readyToSync: false,
2505+
upstreamRef: undefined,
2506+
versionSynced: undefined,
2507+
},
24182508
},
24192509
{
24202510
id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@1b0e2c2c84884b95b1c99fb678cc964c',
@@ -2499,6 +2589,11 @@ module.exports = {
24992589
selectedPartitionIndex: -1,
25002590
selectedGroupsLabel: '',
25012591
},
2592+
upstreamInfo: {
2593+
readyToSync: false,
2594+
upstreamRef: undefined,
2595+
versionSynced: undefined,
2596+
},
25022597
},
25032598
{
25042599
id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@c7e98fd39a6944edb6b286c32e1150ff',
@@ -2583,6 +2678,11 @@ module.exports = {
25832678
selectedPartitionIndex: -1,
25842679
selectedGroupsLabel: '',
25852680
},
2681+
upstreamInfo: {
2682+
readyToSync: false,
2683+
upstreamRef: undefined,
2684+
versionSynced: undefined,
2685+
},
25862686
},
25872687
{
25882688
id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@d6eaa391d2be41dea20b8b1bfbcb1c45',
@@ -2667,6 +2767,11 @@ module.exports = {
26672767
selectedPartitionIndex: -1,
26682768
selectedGroupsLabel: '',
26692769
},
2770+
upstreamInfo: {
2771+
readyToSync: false,
2772+
upstreamRef: undefined,
2773+
versionSynced: undefined,
2774+
},
26702775
},
26712776
],
26722777
},
@@ -2945,6 +3050,11 @@ module.exports = {
29453050
selectedPartitionIndex: -1,
29463051
selectedGroupsLabel: '',
29473052
},
3053+
upstreamInfo: {
3054+
readyToSync: false,
3055+
upstreamRef: undefined,
3056+
versionSynced: undefined,
3057+
},
29483058
},
29493059
],
29503060
},

src/course-outline/card-header/CardHeader.jsx

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
import {
1616
MoreVert as MoveVertIcon,
1717
EditOutline as EditIcon,
18+
Sync as SyncIcon,
1819
} from '@openedx/paragon/icons';
1920

2021
import { useContentTagsCount } from '../../generic/data/apiHooks';
@@ -55,6 +56,8 @@ const CardHeader = ({
5556
discussionsSettings,
5657
parentInfo,
5758
extraActionsComponent,
59+
onClickSync,
60+
readyToSync,
5861
}) => {
5962
const intl = useIntl();
6063
const [searchParams] = useSearchParams();
@@ -130,8 +133,17 @@ const CardHeader = ({
130133
) : (
131134
<>
132135
{titleComponent}
136+
{readyToSync && (
137+
<IconButton
138+
className="item-card-button-icon"
139+
data-testid={`${namePrefix}-sync-button`}
140+
alt={intl.formatMessage(messages.readyToSyncButtonAlt)}
141+
iconAs={SyncIcon}
142+
onClick={onClickSync}
143+
/>
144+
)}
133145
<IconButton
134-
className="item-card-edit-icon"
146+
className="item-card-button-icon"
135147
data-testid={`${namePrefix}-edit-button`}
136148
alt={intl.formatMessage(messages.altButtonEdit)}
137149
iconAs={EditIcon}
@@ -259,6 +271,8 @@ CardHeader.defaultProps = {
259271
parentInfo: {},
260272
cardId: '',
261273
extraActionsComponent: null,
274+
readyToSync: false,
275+
onClickSync: null,
262276
};
263277

264278
CardHeader.propTypes = {
@@ -305,6 +319,8 @@ CardHeader.propTypes = {
305319
// An optional component that is rendered before the dropdown. This is used by the Subsection
306320
// and Unit card components to render their plugin slots.
307321
extraActionsComponent: PropTypes.node,
322+
onClickSync: PropTypes.func,
323+
readyToSync: PropTypes.bool,
308324
};
309325

310326
export default CardHeader;

src/course-outline/card-header/CardHeader.scss

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
color: $black;
1313
}
1414

15-
.item-card-edit-icon {
15+
.item-card-button-icon {
1616
opacity: 0;
1717
transition: opacity .3s linear;
1818
margin-right: .5rem;
@@ -23,7 +23,7 @@
2323
}
2424

2525
&:hover {
26-
.item-card-edit-icon {
26+
.item-card-button-icon {
2727
opacity: 1;
2828
}
2929
}

src/course-outline/card-header/CardHeader.test.jsx

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,4 +368,19 @@ describe('<CardHeader />', () => {
368368
renderComponent();
369369
expect(screen.queryByText('0')).not.toBeInTheDocument();
370370
});
371+
372+
it('should render sync button when is ready to sync', () => {
373+
const mockClickSync = jest.fn();
374+
375+
renderComponent({
376+
readyToSync: true,
377+
onClickSync: mockClickSync,
378+
});
379+
380+
const syncButton = screen.getByRole('button', { name: /update available - click to sync/i });
381+
expect(syncButton).toBeInTheDocument();
382+
fireEvent.click(syncButton);
383+
384+
expect(mockClickSync).toHaveBeenCalled();
385+
});
371386
});

src/course-outline/card-header/messages.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,11 @@ const messages = defineMessages({
7777
id: 'course-authoring.course-outline.card.menu.manageTags',
7878
defaultMessage: 'Manage tags',
7979
},
80+
readyToSyncButtonAlt: {
81+
id: 'course-authoring.course-outline.card.button.sync.alt',
82+
defaultMessage: 'Update available - click to sync',
83+
description: 'Alt text for the sync icon button.',
84+
},
8085
});
8186

8287
export default messages;

0 commit comments

Comments
 (0)