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:
David Joy
2021-01-08 14:07:24 -05:00
committed by GitHub
parent 9c63ab8044
commit 78667fa972
9 changed files with 269 additions and 1 deletions

View File

@@ -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>

View 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;
}
}

View File

@@ -0,0 +1,5 @@
describe('example', () => {
it('will pass because it is an example', () => {
});
});

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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>&nbsp;</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,
};

View 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;

View File

@@ -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";