Adds notes visibility toggle (#44)

* added notes

* moved around components

* Addressed feedback
This commit is contained in:
Dave St.Germain
2020-04-09 14:46:33 -04:00
committed by GitHub
parent e2399e30d4
commit 15c3053e87
10 changed files with 136 additions and 11 deletions

View File

@@ -14,7 +14,7 @@ import Sequence from './sequence';
import CourseBreadcrumbs from './CourseBreadcrumbs';
import { Header, CourseTabsNavigation } from '../../course-header';
import CourseSock from './course-sock';
import Calculator from './calculator';
import ContentTools from './tools/ContentTools';
import messages from './messages';
import { useModel } from '../../model-store';
@@ -54,7 +54,7 @@ function Course({
if (courseStatus === 'loaded') {
const {
org, number, title, isStaff, tabs, verifiedMode, showCalculator,
org, number, title, isStaff, tabs, verifiedMode,
} = course;
return (
<>
@@ -96,7 +96,7 @@ function Course({
previousSequenceHandler={previousSequenceHandler}
/>
{verifiedMode && <CourseSock verifiedMode={verifiedMode} />}
{showCalculator && <Calculator />}
<ContentTools course={course} />
</div>
</>
);

View File

@@ -0,0 +1,33 @@
import React from 'react';
import PropTypes from 'prop-types';
import Calculator from './calculator';
import NotesVisibility from './notes/NotesVisibility';
import './tools.scss';
export default function ContentTools({
course,
}) {
return (
<div className="content-tools">
<div className="d-flex justify-content-end m-0">
{course.showCalculator && (
<Calculator />
)}
{course.notes.enabled && (
<NotesVisibility course={course} />
)}
</div>
</div>
);
}
ContentTools.propTypes = {
course: PropTypes.shape({
notes: PropTypes.shape({
enabled: PropTypes.bool,
}),
showCalculator: PropTypes.bool,
}).isRequired,
};

View File

@@ -0,0 +1,7 @@
.calculator {
width: 100%;
.calculator-content {
background-color: #f1f1f1;
box-shadow: 0 -1px 0 0 #ddd;
}
}

View File

@@ -41,8 +41,8 @@ class Calculator extends Component {
render() {
return (
<Collapsible.Advanced className="calculator">
<div className="container-fluid text-right">
<Collapsible.Trigger tag="a" className="calculator-trigger btn">
<div className="text-right">
<Collapsible.Trigger tag="a" className="trigger btn">
<Collapsible.Visible whenOpen>
<FontAwesomeIcon icon={faTimesCircle} aria-hidden="true" className="mr-2" />
</Collapsible.Visible>

View File

@@ -0,0 +1,6 @@
import { getConfig } from '@edx/frontend-platform';
export default function toggleNotes() {
const iframe = document.getElementById('unit-iframe');
iframe.contentWindow.postMessage('tools.toggleNotes', getConfig().LMS_BASE_URL);
}

View File

@@ -0,0 +1,66 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { getConfig } from '@edx/frontend-platform';
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
import {
injectIntl, intlShape,
} from '@edx/frontend-platform/i18n';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faPencilAlt } from '@fortawesome/free-solid-svg-icons';
import toggleNotes from '../data/api';
import messages from './messages';
class NotesVisibility extends Component {
constructor(props) {
super(props);
this.state = {
visible: props.course.notes.visible,
};
this.visibilityUrl = `${getConfig().LMS_BASE_URL}/courses/${props.course.id}/edxnotes/visibility/`;
}
handleClick = () => {
const data = { visibility: this.state.visible };
getAuthenticatedHttpClient().put(
this.visibilityUrl,
data,
).then(() => {
this.setState((state) => ({ visible: !state.visible }));
toggleNotes();
});
}
render() {
const message = this.state.visible ? 'notes.button.hide' : 'notes.button.show';
return (
<div className="trigger" style={{ width: '200px' }}>
<div
role="switch"
className={`btn ${this.state.visible ? 'text-secondary' : 'text-success'}`}
onClick={this.handleClick}
onKeyDown={this.handleClick}
tabIndex="-1"
aria-checked={this.state.visible ? 'true' : 'false'}
>
<FontAwesomeIcon icon={faPencilAlt} aria-hidden="true" className="mr-2" />
{this.props.intl.formatMessage(messages[message])}
</div>
</div>
);
}
}
NotesVisibility.propTypes = {
intl: intlShape.isRequired,
course: PropTypes.shape({
id: PropTypes.string,
notes: PropTypes.shape({
enabled: PropTypes.bool,
visible: PropTypes.bool,
}),
}).isRequired,
};
export default injectIntl(NotesVisibility);

View File

@@ -0,0 +1,16 @@
import { defineMessages } from '@edx/frontend-platform/i18n';
const messages = defineMessages({
'notes.button.show': {
id: 'notes.button.show',
defaultMessage: 'Show Notes',
description: 'Message for toggling notes visibility',
},
'notes.button.hide': {
id: 'notes.button.hide',
defaultMessage: 'Hide Notes',
description: 'Message for toggling notes visibility',
},
});
export default messages;

View File

@@ -1,10 +1,10 @@
.calculator {
.content-tools {
position: fixed;
left: 0;
right: 0;
bottom: 0;
z-index: 100;
.calculator-trigger {
.trigger {
cursor: pointer;
display: inline-block;
position: relative;
@@ -20,8 +20,4 @@
border-radius: .5rem;
}
}
.calculator-content {
background-color: #f1f1f1;
box-shadow: 0 -1px 0 0 #ddd;
}
}

View File

@@ -20,6 +20,7 @@ function normalizeMetadata(metadata) {
verifiedMode: camelCaseObject(metadata.verified_mode),
tabs: camelCaseObject(metadata.tabs),
showCalculator: metadata.show_calculator,
notes: camelCaseObject(metadata.notes),
};
}