diff --git a/src/CourseAuthoringRoutes.jsx b/src/CourseAuthoringRoutes.jsx index 9fcb37aa9..9864a9aa5 100644 --- a/src/CourseAuthoringRoutes.jsx +++ b/src/CourseAuthoringRoutes.jsx @@ -6,6 +6,7 @@ import { PageRoute } from '@edx/frontend-platform/react'; import CourseAuthoringPage from './CourseAuthoringPage'; import { CoursePageResources } from './course-page-resources'; import ProctoredExamSettings from './proctored-exam-settings/ProctoredExamSettings'; +import DiscussionToolSelectorContainer from './discussion-tool-selector/DiscussionToolSelectorContainer'; /** * As of this writing, these routes are mounted at a path prefixed with the following: @@ -27,9 +28,12 @@ export default function CourseAuthoringRoutes({ courseId }) { return ( - + + + + diff --git a/src/discussion-tool-selector/DiscussionToolSelector.scss b/src/discussion-tool-selector/DiscussionToolSelector.scss new file mode 100644 index 000000000..afb17e34c --- /dev/null +++ b/src/discussion-tool-selector/DiscussionToolSelector.scss @@ -0,0 +1,16 @@ +.discussion-tool { + &:hover, + &:focus { + border-color: theme-color("primary", "hover") !important; + } +} + +.features-table { + scroll-snap-type: x mandatory; + + th { + min-width: 7.5rem; + white-space: nowrap; + scroll-snap-align: center; + } +} diff --git a/src/discussion-tool-selector/DiscussionToolSelector.test.jsx b/src/discussion-tool-selector/DiscussionToolSelector.test.jsx new file mode 100644 index 000000000..3bad6f31d --- /dev/null +++ b/src/discussion-tool-selector/DiscussionToolSelector.test.jsx @@ -0,0 +1,5 @@ +describe('example', () => { + it('will pass because it is an example', () => { + + }); +}); diff --git a/src/discussion-tool-selector/DiscussionToolSelectorContainer.jsx b/src/discussion-tool-selector/DiscussionToolSelectorContainer.jsx new file mode 100644 index 000000000..225956225 --- /dev/null +++ b/src/discussion-tool-selector/DiscussionToolSelectorContainer.jsx @@ -0,0 +1,69 @@ +import React, { useState } from 'react'; +import { injectIntl, intlShape } from '@edx/frontend-platform/i18n'; +import DiscussionToolSelector from './discussion-tool-selector/DiscussionToolSelector'; + +// XXX this is just for testing and should be removed ASAP +const forums = [ + { + forumId: 'edX Forum', + logo: 'https://cdn-blog.lawrencemcdaniel.com/wp-content/uploads/2018/01/22125436/edx-logo.png', + description: 'Start conversations with other learners, ask questions, and interact with other learners in the course.', + supportLevel: 'Full support', + isAvailable: true, + features: ['LTI Integration', 'Discussion Page', 'Embedded Course Sections', 'Embedded Course Units', 'WCAG 2.1 Support'], + }, + { + forumId: 'Piazza', + logo: 'https://cdn-blog.lawrencemcdaniel.com/wp-content/uploads/2018/01/22125436/edx-logo.png', + description: 'Piazza is designed to connect students, TAs, and professors so every student can get the help they need when they need it', + supportLevel: 'Partial support', + isAvailable: true, + features: ['LTI Integration', 'Discussion Page', 'Embedded Course Sections', 'WCAG 2.1 Support'], + }, + { + forumId: 'Yellowdig', + logo: 'https://cdn-blog.lawrencemcdaniel.com/wp-content/uploads/2018/01/22125436/edx-logo.png', + description: 'Yellowdig is the digital solution that impacts the entire student lifecycle and enables lifelong learning.', + supportLevel: 'Coming soon', + isAvailable: false, + features: ['LTI Integration', 'Discussion Page', 'Embedded Course Sections', 'WCAG 2.1 Support'], + }, + { + forumId: 'Untitled Forum', + logo: 'https://cdn-blog.lawrencemcdaniel.com/wp-content/uploads/2018/01/22125436/edx-logo.png', + description: 'Start conversations with other learners, ask questions, and interact with other learners in the course.', + supportLevel: 'Full support', + isAvailable: true, + features: ['LTI Integration', 'Discussion Page', 'Embedded Course Sections', 'Embedded Course Units', 'WCAG 2.1 Support'], + }, +]; + +const featuresList = ['LTI Integration', 'Discussion Page', 'Embedded Course Sections', 'Embedded Course Units', 'WCAG 2.1 Support']; + +function DiscussionToolSelectorContainer({ intl }) { + const [selectedForumId, setSelectedForumId] = useState(null); + + const onSelectForum = (forumId) => { + if (selectedForumId === forumId) { + setSelectedForumId(null); + } else { + setSelectedForumId(forumId); + } + }; + + return ( + + ); +} + +DiscussionToolSelectorContainer.propTypes = { + intl: intlShape.isRequired, +}; + +export default injectIntl(DiscussionToolSelectorContainer); diff --git a/src/discussion-tool-selector/discussion-tool-selector/DiscussionToolSelector.jsx b/src/discussion-tool-selector/discussion-tool-selector/DiscussionToolSelector.jsx new file mode 100644 index 000000000..c058885c5 --- /dev/null +++ b/src/discussion-tool-selector/discussion-tool-selector/DiscussionToolSelector.jsx @@ -0,0 +1,51 @@ +import React from 'react'; +import { injectIntl, intlShape } from '@edx/frontend-platform/i18n'; +import { Button, Container, Row } from '@edx/paragon'; +import PropTypes from 'prop-types'; +import DiscussionToolOption from './discussion-tool-option/DiscussionToolOption'; +import FeaturesTable from './features-table/FeaturesTable'; +import messages from '../messages'; + +function DiscussionToolSelector({ + intl, forums, featuresList, onSelectForum, selectedForumId, +}) { + return ( + +
{intl.formatMessage(messages.heading)}
+ + + {forums.map(forum => ( + + ))} + + +
+

+ {intl.formatMessage(messages.supportedFeatures)} +

+ {selectedForumId && ( + + )} +
+ + +
+ ); +} + +DiscussionToolSelector.propTypes = { + intl: intlShape.isRequired, + forums: PropTypes.arrayOf(PropTypes.object).isRequired, + featuresList: PropTypes.arrayOf(PropTypes.object).isRequired, + onSelectForum: PropTypes.func.isRequired, + selectedForumId: PropTypes.string.isRequired, +}; + +export default injectIntl(DiscussionToolSelector); diff --git a/src/discussion-tool-selector/discussion-tool-selector/discussion-tool-option/DiscussionToolOption.jsx b/src/discussion-tool-selector/discussion-tool-selector/discussion-tool-option/DiscussionToolOption.jsx new file mode 100644 index 000000000..b21b76746 --- /dev/null +++ b/src/discussion-tool-selector/discussion-tool-selector/discussion-tool-option/DiscussionToolOption.jsx @@ -0,0 +1,60 @@ +import React from 'react'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { CheckBox, Image, Col } from '@edx/paragon'; +import { faLock } from '@fortawesome/free-solid-svg-icons'; +import PropTypes from 'prop-types'; +import { injectIntl, intlShape } from '@edx/frontend-platform/i18n'; + +import messages from '../../messages'; + +function DiscussionToolOption({ + intl, forum, selected, onSelect, +}) { + return ( + +
{ if (forum.isAvailable) { onSelect(forum.forumId); } }} + onKeyPress={() => { if (forum.isAvailable) { onSelect(forum.forumId); } }} + role="radio" + aria-checked={selected} + > +
+
+ {intl.formatMessage(messages.toolLogo, +
+
+ {forum.isAvailable ? ( + + ) : ( + + )} +
+
+
+
{forum.description}
+
+
{forum.supportLevel}
+
+ + ); +} + +DiscussionToolOption.propTypes = { + intl: intlShape.isRequired, + forum: PropTypes.objectOf(PropTypes.any).isRequired, + selected: PropTypes.bool.isRequired, + onSelect: PropTypes.func.isRequired, +}; + +export default injectIntl(DiscussionToolOption); diff --git a/src/discussion-tool-selector/discussion-tool-selector/features-table/FeaturesTable.jsx b/src/discussion-tool-selector/discussion-tool-selector/features-table/FeaturesTable.jsx new file mode 100644 index 000000000..300825b9e --- /dev/null +++ b/src/discussion-tool-selector/discussion-tool-selector/features-table/FeaturesTable.jsx @@ -0,0 +1,38 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { faCheck } from '@fortawesome/free-solid-svg-icons'; + +export default function FeaturesTable({ forums, featuresList }) { + return ( +
+ + + + + {forums.map(forum => ( + + ))} + + + + {featuresList.map(feature => ( + + + {forums.map(forum => ( + + ))} + + ))} + +
 
{forum.forumId}
{feature} + {forum.features.includes(feature) && } +
+
+ ); +} + +FeaturesTable.propTypes = { + forums: PropTypes.arrayOf(PropTypes.object).isRequired, + featuresList: PropTypes.arrayOf(PropTypes.object).isRequired, +}; diff --git a/src/discussion-tool-selector/messages.js b/src/discussion-tool-selector/messages.js new file mode 100644 index 000000000..b92db3869 --- /dev/null +++ b/src/discussion-tool-selector/messages.js @@ -0,0 +1,22 @@ +import { defineMessages } from '@edx/frontend-platform/i18n'; + +const messages = defineMessages({ + heading: { + id: 'authoring.forumSelectorTool.heading', + defaultMessage: 'Which discussion tool would you like to use for this course?', + }, + supportedFeatures: { + id: 'authoring.forumSelectorTool.supportedFeatures', + defaultMessage: 'Supported Features', + }, + configureTool: { + id: 'authoring.forumSelectorTool.configureTool', + defaultMessage: 'Configure {toolName}', + }, + toolLogo: { + id: 'authoring.forumSelectorTool.toolLogo', + defaultMessage: '{toolName} Logo', + }, +}); + +export default messages; diff --git a/src/index.scss b/src/index.scss index 765b7472a..53da5cd71 100755 --- a/src/index.scss +++ b/src/index.scss @@ -8,4 +8,7 @@ @import "~@edx/frontend-component-footer/dist/footer"; @import "proctored-exam-settings/proctoredExamSettings.scss"; + +@import "discussion-tool-selector/DiscussionToolSelector.scss"; + @import "studio-header/header.scss";