Skip to content

Commit e040882

Browse files
committed
feat: Add slots to add tab links and add mechanism for plugin routes
1 parent f28528e commit e040882

File tree

2 files changed

+50
-39
lines changed

2 files changed

+50
-39
lines changed
Lines changed: 30 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,28 @@
11
import React from 'react';
2-
import PropTypes from 'prop-types';
3-
import { useIntl } from '@edx/frontend-platform/i18n';
42
import classNames from 'classnames';
5-
6-
import messages from './messages';
7-
import Tabs from '../generic/tabs/Tabs';
3+
import { useIntl } from '@edx/frontend-platform/i18n';
4+
import { PluginSlot } from '@openedx/frontend-plugin-framework';
85
import { CoursewareSearch, CoursewareSearchToggle } from '../course-home/courseware-search';
96
import { useCoursewareSearchState } from '../course-home/courseware-search/hooks';
107

8+
import Tabs from '../generic/tabs/Tabs';
9+
import messages from './messages';
10+
11+
interface CourseTabsNavigationProps {
12+
activeTabSlug?: string;
13+
className?: string | null;
14+
tabs: Array<{
15+
title: string;
16+
slug: string;
17+
url: string;
18+
}>;
19+
}
20+
1121
const CourseTabsNavigation = ({
12-
activeTabSlug, className, tabs,
13-
}) => {
22+
activeTabSlug = undefined,
23+
className = null,
24+
tabs,
25+
}:CourseTabsNavigationProps) => {
1426
const intl = useIntl();
1527
const { show } = useCoursewareSearchState();
1628

@@ -23,15 +35,17 @@ const CourseTabsNavigation = ({
2335
className="nav-underline-tabs"
2436
aria-label={intl.formatMessage(messages.courseMaterial)}
2537
>
26-
{tabs.map(({ url, title, slug }) => (
27-
<a
28-
key={slug}
29-
className={classNames('nav-item flex-shrink-0 nav-link', { active: slug === activeTabSlug })}
30-
href={url}
31-
>
32-
{title}
33-
</a>
34-
))}
38+
<PluginSlot id="course_tab_links_slot">
39+
{tabs.map(({ url, title, slug }) => (
40+
<a
41+
key={slug}
42+
className={classNames('nav-item flex-shrink-0 nav-link', { active: slug === activeTabSlug })}
43+
href={url}
44+
>
45+
{title}
46+
</a>
47+
))}
48+
</PluginSlot>
3549
</Tabs>
3650
</div>
3751
<div className="search-toggle">
@@ -44,19 +58,4 @@ const CourseTabsNavigation = ({
4458
);
4559
};
4660

47-
CourseTabsNavigation.propTypes = {
48-
activeTabSlug: PropTypes.string,
49-
className: PropTypes.string,
50-
tabs: PropTypes.arrayOf(PropTypes.shape({
51-
title: PropTypes.string.isRequired,
52-
slug: PropTypes.string.isRequired,
53-
url: PropTypes.string.isRequired,
54-
})).isRequired,
55-
};
56-
57-
CourseTabsNavigation.defaultProps = {
58-
activeTabSlug: undefined,
59-
className: null,
60-
};
61-
6261
export default CourseTabsNavigation;

src/index.jsx

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
getConfig,
55
} from '@edx/frontend-platform';
66
import { AppProvider, ErrorPage, PageWrap } from '@edx/frontend-platform/react';
7+
import { PluginSlot } from '@openedx/frontend-plugin-framework';
78
import { StrictMode } from 'react';
89
import { createRoot } from 'react-dom/client';
910
import { Routes, Route } from 'react-router-dom';
@@ -58,7 +59,7 @@ subscribe(APP_READY, () => {
5859
path={ROUTES.PREFERENCES_UNSUBSCRIBE}
5960
element={
6061
<PageWrap><PreferencesUnsubscribe /></PageWrap>
61-
}
62+
}
6263
/>
6364
<Route
6465
path={DECODE_ROUTES.ACCESS_DENIED}
@@ -72,7 +73,7 @@ subscribe(APP_READY, () => {
7273
<OutlineTab />
7374
</TabContainer>
7475
</DecodePageRoute>
75-
)}
76+
)}
7677
/>
7778
<Route
7879
path={DECODE_ROUTES.LIVE}
@@ -82,7 +83,7 @@ subscribe(APP_READY, () => {
8283
<LiveTab />
8384
</TabContainer>
8485
</DecodePageRoute>
85-
)}
86+
)}
8687
/>
8788
<Route
8889
path={DECODE_ROUTES.DATES}
@@ -92,7 +93,7 @@ subscribe(APP_READY, () => {
9293
<DatesTab />
9394
</TabContainer>
9495
</DecodePageRoute>
95-
)}
96+
)}
9697
/>
9798
<Route
9899
path={DECODE_ROUTES.DISCUSSION}
@@ -102,7 +103,7 @@ subscribe(APP_READY, () => {
102103
<DiscussionTab />
103104
</TabContainer>
104105
</DecodePageRoute>
105-
)}
106+
)}
106107
/>
107108
{DECODE_ROUTES.PROGRESS.map((route) => (
108109
<Route
@@ -119,7 +120,7 @@ subscribe(APP_READY, () => {
119120
<ProgressTab />
120121
</TabContainer>
121122
</DecodePageRoute>
122-
)}
123+
)}
123124
/>
124125
))}
125126
<Route
@@ -130,7 +131,7 @@ subscribe(APP_READY, () => {
130131
<CourseExit />
131132
</TabContainer>
132133
</DecodePageRoute>
133-
)}
134+
)}
134135
/>
135136
{DECODE_ROUTES.COURSEWARE.map((route) => (
136137
<Route
@@ -140,7 +141,18 @@ subscribe(APP_READY, () => {
140141
<DecodePageRoute>
141142
<CoursewareContainer />
142143
</DecodePageRoute>
143-
)}
144+
)}
145+
/>
146+
))}
147+
{getConfig()?.PLUGIN_ROUTES?.map((route) => (
148+
<Route
149+
key={route}
150+
path={route}
151+
element={(
152+
<DecodePageRoute>
153+
<PluginSlot id="course_page_route_slot" pluginProps={{ route }} />
154+
</DecodePageRoute>
155+
)}
144156
/>
145157
))}
146158
</Routes>

0 commit comments

Comments
 (0)