diff --git a/.gitignore b/.gitignore index 0aac7e519..a72456e5c 100755 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,9 @@ temp/babel-plugin-react-intl ### pyenv ### .python-version +### vim ### +*.swp + ### Emacs ### *~ /temp diff --git a/package.json b/package.json index f88e021b0..83e80f5c2 100644 --- a/package.json +++ b/package.json @@ -44,6 +44,7 @@ "@fortawesome/free-solid-svg-icons": "5.11.2", "@fortawesome/react-fontawesome": "0.1.9", "babel-polyfill": "6.26.0", + "classnames": "^2.2.6", "email-validator": "^2.0.4", "moment": "^2.27.0", "prop-types": "15.7.2", diff --git a/src/course-page-resources/CoursePageResources.jsx b/src/course-page-resources/CoursePageResources.jsx new file mode 100644 index 000000000..3a2583eaf --- /dev/null +++ b/src/course-page-resources/CoursePageResources.jsx @@ -0,0 +1,118 @@ +import PropTypes from 'prop-types'; +import React, { useContext } from 'react'; +import { injectIntl, intlShape } from '@edx/frontend-platform/i18n'; +import { AppContext } from '@edx/frontend-platform/react'; + +import CoursePageConfigCard from './course-page/CoursePageConfigCard'; +import messages from './messages'; + +// XXX this is just for testing and should be removed ASAP +const coursePages = [ + { + id: 'cp-discussion', + title: 'Discussion', + isEnabled: false, + showSettings: false, + showStatus: false, + showEnable: true, + description: 'Encourage participation and engagement in your course with discussion forums', + }, + { + id: 'cp-teams', + title: 'Teams', + isEnabled: true, + showSettings: true, + showStatus: true, + showEnable: false, + description: 'Leverage teams to allow learners to connect by topic of interest', + }, + { + id: 'cp-progress', + title: 'Progress', + isEnabled: false, + showSettings: true, + showStatus: true, + showEnable: false, + description: 'Allow students to track their progress throughout the course lorem ipsum', + }, + { + id: 'cp-textbooks', + title: 'Textbooks', + isEnabled: true, + showSettings: true, + showStatus: true, + showEnable: false, + description: 'Provide links to applicable resources for your course', + }, + { + id: 'cp-notes', + title: 'Notes', + isEnabled: true, + showSettings: true, + showStatus: true, + showEnable: false, + description: 'Support individual note taking that is visible only to the students', + }, + { + id: 'cp-wiki', + title: 'Wiki', + isEnabled: false, + showSettings: false, + showStatus: false, + showEnable: true, + description: 'Share your wiki content to provide additional course material', + }, +]; + +function CoursePageResources({ intl, courseId }) { + const { config } = useContext(AppContext); + const lmsCourseURL = `${config.LMS_BASE_URL}/courses/${courseId}`; + return ( +
+
+
+

{intl.formatMessage(messages.heading)}

+ + {intl.formatMessage(messages['viewLive.button'])} + +
+
+

+ {intl.formatMessage(messages['pages.subheading'])} +

+
+ {coursePages.map((coursePage) => ( +
+ +
+ ))} +
+
+
+

{intl.formatMessage(messages['resources.subheading'])}

+
+
{intl.formatMessage(messages['resources.custom.title'])}
+
+ {intl.formatMessage(messages['resources.custom.description'])} +
+
+ + {intl.formatMessage(messages['resources.newPage.button'])} + +
+
+
+
+
+ ); +} + +CoursePageResources.propTypes = { + intl: intlShape.isRequired, + courseId: PropTypes.string.isRequired, +}; + +export default injectIntl(CoursePageResources); diff --git a/src/example/ExamplePage.test.jsx b/src/course-page-resources/CoursePageResources.test.jsx similarity index 60% rename from src/example/ExamplePage.test.jsx rename to src/course-page-resources/CoursePageResources.test.jsx index 3bad6f31d..82280d054 100644 --- a/src/example/ExamplePage.test.jsx +++ b/src/course-page-resources/CoursePageResources.test.jsx @@ -1,4 +1,4 @@ -describe('example', () => { +describe('coursepageresources', () => { it('will pass because it is an example', () => { }); diff --git a/src/course-page-resources/course-page/CoursePageConfigCard.jsx b/src/course-page-resources/course-page/CoursePageConfigCard.jsx new file mode 100644 index 000000000..33af177e3 --- /dev/null +++ b/src/course-page-resources/course-page/CoursePageConfigCard.jsx @@ -0,0 +1,62 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import { injectIntl, intlShape } from '@edx/frontend-platform/i18n'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { faCog } from '@fortawesome/free-solid-svg-icons'; +import { Button } from '@edx/paragon'; + +import classNames from 'classnames'; +import messages from '../messages'; + +const CoursePageShape = PropTypes.shape({ + id: PropTypes.string.isRequired, + title: PropTypes.string.isRequired, + description: PropTypes.string.isRequired, + isEnabled: PropTypes.bool.isRequired, + showSettings: PropTypes.bool.isRequired, + showStatus: PropTypes.bool.isRequired, + showEnable: PropTypes.bool.isRequired, +}); + +export { CoursePageShape }; + +function CoursePageConfigCard({ intl, coursePage }) { + const pageStatusMsgId = coursePage.isEnabled ? 'pageStatus.enabled' : 'pageStatus.disabled'; + const componentClasses = classNames( + 'course-page-config-card d-flex flex-column align-content-stretch', + 'bg-white p-3 border shadow', + { 'border-info-300': coursePage.isEnabled, 'border-gray-100': !coursePage.isEnabled }, + ); + + return ( +
+
+ {coursePage.title} + {coursePage.showSettings && } +
+ +
+ {coursePage.showStatus && {intl.formatMessage(messages[pageStatusMsgId])}} +
+ +
+

{coursePage.description}

+
+ + {coursePage.showEnable && !coursePage.isEnabled && ( +
+ +
+ )} +
+ ); +} + +CoursePageConfigCard.propTypes = { + intl: intlShape.isRequired, + coursePage: CoursePageShape.isRequired, +}; + +export default injectIntl(CoursePageConfigCard); diff --git a/src/course-page-resources/course-page/CoursePageConfigCard.test.jsx b/src/course-page-resources/course-page/CoursePageConfigCard.test.jsx new file mode 100644 index 000000000..379aaee02 --- /dev/null +++ b/src/course-page-resources/course-page/CoursePageConfigCard.test.jsx @@ -0,0 +1,5 @@ +describe('CoursePageConfigCard', () => { + it('will pass because it is an example', () => { + + }); +}); diff --git a/src/example/data/.gitkeep b/src/course-page-resources/data/.gitkeep similarity index 100% rename from src/example/data/.gitkeep rename to src/course-page-resources/data/.gitkeep diff --git a/src/example/data/README.rst b/src/course-page-resources/data/README.rst similarity index 100% rename from src/example/data/README.rst rename to src/course-page-resources/data/README.rst diff --git a/src/course-page-resources/index.js b/src/course-page-resources/index.js new file mode 100644 index 000000000..480bbe631 --- /dev/null +++ b/src/course-page-resources/index.js @@ -0,0 +1,2 @@ +/* eslint-disable import/prefer-default-export */ +export { default as CoursePageResources } from './CoursePageResources'; diff --git a/src/course-page-resources/index.scss b/src/course-page-resources/index.scss new file mode 100644 index 000000000..8164e687a --- /dev/null +++ b/src/course-page-resources/index.scss @@ -0,0 +1,3 @@ +.course-page-config-card { + flex-basis: 100%; +} diff --git a/src/course-page-resources/messages.js b/src/course-page-resources/messages.js new file mode 100644 index 000000000..16b6f3146 --- /dev/null +++ b/src/course-page-resources/messages.js @@ -0,0 +1,46 @@ +import { defineMessages } from '@edx/frontend-platform/i18n'; + +const messages = defineMessages({ + heading: { + id: 'course-authoring.pages-resources.heading', + defaultMessage: 'Pages & Resources', + }, + 'viewLive.button': { + id: 'course-authoring.pages-resources.viewLive.button', + defaultMessage: 'View Live', + }, + 'enable.button': { + id: 'course-authoring.pages-resources.enable.button', + defaultMessage: 'Enable', + }, + 'pages.subheading': { + id: 'course-authoring.pages-resources.pages.subheading', + defaultMessage: 'Course pages', + }, + 'pageStatus.enabled': { + id: 'course-authoring.pages-resources.pageStatus.enabled', + defaultMessage: 'Enabled', + }, + 'pageStatus.disabled': { + id: 'course-authoring.pages-resources.pageStatus.disabled', + defaultMessage: 'Disabled', + }, + 'resources.subheading': { + id: 'course-authoring.pages-resources.resources.subheading', + defaultMessage: 'Resources', + }, + 'resources.custom.title': { + id: 'course-authoring.pages-resources.resources.custom.title', + defaultMessage: 'Custom', + }, + 'resources.custom.description': { + id: 'course-authoring.pages-resources.resources.custom.description', + defaultMessage: 'Create and edit custom pages to provide students with additional course content and resources. Pages are publicly visible. If users know the URL of a page, they can view the page even if they are not registered for or logged in to your course.', + }, + 'resources.newPage.button': { + id: 'course-authoring.pages-resources.resources.newPage.button', + defaultMessage: 'New Page', + }, +}); + +export default messages; diff --git a/src/example/ExamplePage.jsx b/src/example/ExamplePage.jsx deleted file mode 100644 index d550b5980..000000000 --- a/src/example/ExamplePage.jsx +++ /dev/null @@ -1,18 +0,0 @@ -import React from 'react'; -import { FormattedMessage } from '@edx/frontend-platform/i18n'; - -export default function ExamplePage() { - return ( -
-
-

Example Page

-

- -

-
-
- ); -} diff --git a/src/example/index.scss b/src/example/index.scss deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/index.jsx b/src/index.jsx index bb5816050..f4a339fbb 100755 --- a/src/index.jsx +++ b/src/index.jsx @@ -8,11 +8,11 @@ import React from 'react'; import ReactDOM from 'react-dom'; import { Route, Switch } from 'react-router-dom'; -import Header, { messages as headerMessages } from '@edx/frontend-component-header'; +import { messages as headerMessages } from '@edx/frontend-component-header'; import Footer, { messages as footerMessages } from '@edx/frontend-component-footer'; import appMessages from './i18n'; -import ExamplePage from './example/ExamplePage'; +import { CoursePageResources } from './course-page-resources'; import ProctoredExamSettings from './proctored-exam-settings/ProctoredExamSettings'; import StudioHeader from './studio-header/Header'; @@ -36,10 +36,19 @@ subscribe(APP_READY, () => { ); }} /> - -
- - + { + const courseId = decodeURIComponent(match.params.course_id); + return ( + <> + + +