Discussion tool selection page skeleton (#44)
* Added new components for Discussion Tool Selection * Incorporating discussion tool selector page into CourseAuthoringRoutes * Improving tool selection - will now unselect Also using a pointer cursor. * Styling tweaks, logo size and text color Making the logo so it doesn’t scale vertically - picked 100px arbitrarily. It will be changed, but is now at least a little more inline with how the Pages & Resources view behaves. Also darkening text color - it looked disabled. * Adding a “Configure forum” button It appears when a tool is selected. This is a temporary location, depending on whether or not we insist on this page being a full-page modal. In my opinion we should just keep it a normal page. Co-authored-by: Aayush <ayush@opencraft.com>
This commit is contained in:
@@ -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 (
|
||||
<CourseAuthoringPage courseId={courseId}>
|
||||
<Switch>
|
||||
<PageRoute path={`${path}/pages`}>
|
||||
<PageRoute exact path={`${path}/pages`}>
|
||||
<CoursePageResources courseId={courseId} />
|
||||
</PageRoute>
|
||||
<PageRoute path={`${path}/pages/discussion`}>
|
||||
<DiscussionToolSelectorContainer courseId={courseId} />
|
||||
</PageRoute>
|
||||
<PageRoute path={`${path}/proctored-exam-settings`}>
|
||||
<ProctoredExamSettings courseId={courseId} />
|
||||
</PageRoute>
|
||||
|
||||
16
src/discussion-tool-selector/DiscussionToolSelector.scss
Normal file
16
src/discussion-tool-selector/DiscussionToolSelector.scss
Normal file
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
describe('example', () => {
|
||||
it('will pass because it is an example', () => {
|
||||
|
||||
});
|
||||
});
|
||||
@@ -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 (
|
||||
<DiscussionToolSelector
|
||||
intl={intl}
|
||||
forums={forums}
|
||||
featuresList={featuresList}
|
||||
onSelectForum={onSelectForum}
|
||||
selectedForumId={selectedForumId}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
DiscussionToolSelectorContainer.propTypes = {
|
||||
intl: intlShape.isRequired,
|
||||
};
|
||||
|
||||
export default injectIntl(DiscussionToolSelectorContainer);
|
||||
@@ -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 (
|
||||
<Container fluid className="text-info-500">
|
||||
<h6 className="my-4 text-center">{intl.formatMessage(messages.heading)}</h6>
|
||||
|
||||
<Row>
|
||||
{forums.map(forum => (
|
||||
<DiscussionToolOption
|
||||
key={forum.forumId}
|
||||
forum={forum}
|
||||
selected={forum.forumId === selectedForumId}
|
||||
onSelect={onSelectForum}
|
||||
/>
|
||||
))}
|
||||
</Row>
|
||||
|
||||
<div className="d-flex justify-content-between align-items-center">
|
||||
<h2 className="my-3">
|
||||
{intl.formatMessage(messages.supportedFeatures)}
|
||||
</h2>
|
||||
{selectedForumId && (
|
||||
<Button variant="primary">
|
||||
{intl.formatMessage(messages.configureTool, { toolName: selectedForumId })}
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<FeaturesTable forums={forums} featuresList={featuresList} />
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
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);
|
||||
@@ -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 (
|
||||
<Col className="mb-4" xs={12} sm={6} lg={4} xl={3}>
|
||||
<div
|
||||
className="d-flex discussion-tool flex-column p-3 h-100 shadow border border-white"
|
||||
style={{
|
||||
cursor: 'pointer',
|
||||
}}
|
||||
tabIndex={forum.isAvailable ? '-1' : ''}
|
||||
onClick={() => { if (forum.isAvailable) { onSelect(forum.forumId); } }}
|
||||
onKeyPress={() => { if (forum.isAvailable) { onSelect(forum.forumId); } }}
|
||||
role="radio"
|
||||
aria-checked={selected}
|
||||
>
|
||||
<div className="d-flex flex-row justify-content-between">
|
||||
<div className="d-flex justify-content-center">
|
||||
<Image
|
||||
height={100}
|
||||
src={forum.logo}
|
||||
alt={intl.formatMessage(messages.toolLogo, {
|
||||
toolName: forum.forumId,
|
||||
})}
|
||||
/>
|
||||
</div>
|
||||
<div className="d-flex">
|
||||
{forum.isAvailable ? (
|
||||
<CheckBox checked={selected} />
|
||||
) : (
|
||||
<FontAwesomeIcon icon={faLock} />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<div className="py-4">{forum.description}</div>
|
||||
<br />
|
||||
<div className="mt-auto font-weight-bold">{forum.supportLevel}</div>
|
||||
</div>
|
||||
</Col>
|
||||
);
|
||||
}
|
||||
|
||||
DiscussionToolOption.propTypes = {
|
||||
intl: intlShape.isRequired,
|
||||
forum: PropTypes.objectOf(PropTypes.any).isRequired,
|
||||
selected: PropTypes.bool.isRequired,
|
||||
onSelect: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default injectIntl(DiscussionToolOption);
|
||||
@@ -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 (
|
||||
<div className="table-responsive features-table border border-info-300 p-3 mb-4">
|
||||
<table className="w-100">
|
||||
<thead>
|
||||
<tr>
|
||||
<th> </th>
|
||||
{forums.map(forum => (
|
||||
<th className="text-center py-3" key={forum.forumId}><h5>{forum.forumId}</h5></th>
|
||||
))}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{featuresList.map(feature => (
|
||||
<tr key={feature}>
|
||||
<th key={feature} className="py-3">{feature}</th>
|
||||
{forums.map(forum => (
|
||||
<td className="text-center py-3" key={forum.forumId}>
|
||||
{forum.features.includes(feature) && <FontAwesomeIcon icon={faCheck} />}
|
||||
</td>
|
||||
))}
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
FeaturesTable.propTypes = {
|
||||
forums: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
featuresList: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
};
|
||||
22
src/discussion-tool-selector/messages.js
Normal file
22
src/discussion-tool-selector/messages.js
Normal file
@@ -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;
|
||||
@@ -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";
|
||||
|
||||
Reference in New Issue
Block a user