From be84c91981207ba975db9b0ce7c657bcaa0cd5a2 Mon Sep 17 00:00:00 2001 From: Matt Hughes Date: Fri, 23 Aug 2019 17:25:06 -0400 Subject: [PATCH] Move filters to push-aside drawer - makes gradebook full-width (to accommodate push-aside) - while the drawer is open the rest of the page is left-right scrollable JIRA:EDUCATOR-4579 --- src/App.scss | 2 + src/components/Drawer/Drawer.scss | 48 ++++ src/components/Drawer/index.jsx | 86 +++++++ src/components/Gradebook/gradebook.scss | 19 +- src/components/Gradebook/index.jsx | 286 ++++++++++++------------ 5 files changed, 287 insertions(+), 154 deletions(-) create mode 100644 src/components/Drawer/Drawer.scss create mode 100644 src/components/Drawer/index.jsx diff --git a/src/App.scss b/src/App.scss index 61c7c71..658d09f 100755 --- a/src/App.scss +++ b/src/App.scss @@ -11,3 +11,5 @@ $input-focus-box-shadow: $input-box-shadow; // hack to get upgrade to paragon 4. @import "~@edx/frontend-component-footer/src/lib/scss/site-footer"; @import "./components/Gradebook/gradebook"; +@import "./components/Drawer/Drawer"; + diff --git a/src/components/Drawer/Drawer.scss b/src/components/Drawer/Drawer.scss new file mode 100644 index 0000000..372d273 --- /dev/null +++ b/src/components/Drawer/Drawer.scss @@ -0,0 +1,48 @@ +$drawer-width: 350px; + +.drawer-contents { + overflow-x: auto; + transition: margin 300ms cubic-bezier(0.4,0,0.2,1); + margin-left: 0; + .drawer.open + & { + margin-left: $drawer-width; + } + &.opened { + width: calc(100vw - #{$drawer-width}); + } +} + +.drawer-contents { + overflow-x: auto; + transition: margin 300ms cubic-bezier(0.4,0,0.2,1); + margin-left: 0; + .drawer.open + & { + margin-left: $drawer-width; + } + &.opened { + width: calc(100vw - #{$drawer-width}); + } +} + +.drawer-header { + display: flex; + align-items: flex-start; + justify-content: space-between; + padding: 15px; +} + +.drawer-container .collapsible { + margin-bottom: 1em; +} + +.drawer { + height: 100%; + width: $drawer-width; + position: absolute; + transform: translateX(-$drawer-width); + flex-direction: column; + transition: transform 300ms cubic-bezier(0.4,0,0.2,1); + &.open { + transform: translateX(0%); + } +} diff --git a/src/components/Drawer/index.jsx b/src/components/Drawer/index.jsx new file mode 100644 index 0000000..d626750 --- /dev/null +++ b/src/components/Drawer/index.jsx @@ -0,0 +1,86 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import classNames from 'classnames'; +import { Button } from '@edx/paragon'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { faTimes } from '@fortawesome/free-solid-svg-icons'; + +export default class Drawer extends React.Component { + constructor(props) { + super(props); + this.state = { + open: props.initiallyOpen, + transitioning: false, + }; + } + + deferToNextRepaint(callback) { + window.requestAnimationFrame(() => + window.setTimeout(callback, 0)); + } + + close = () => { + if (this.state.open) { + this.toggleOpen(); + } + }; + + toggleOpen = () => { + this.setState({ transitioning: true }); + // defer the transition to the next repaint so we can be sure that + // opening drawer is visible before it transitions + // (the start state of the opening animation doesn't work if the element starts hidden) + this.deferToNextRepaint(() => this.setState(prevState => ({ open: !prevState.open }))); + }; + + handleSlideDone = (e) => { + if (e.currentTarget === e.target) { + this.setState({ transitioning: false }); + } + }; + + render() { + return ( +
+ +
+ {this.props.mainContent(this.toggleOpen)} +
+
+ ); + } +} + +Drawer.propTypes = { + initiallyOpen: PropTypes.bool.isRequired, + children: PropTypes.node.isRequired, + mainContent: PropTypes.func.isRequired, + title: PropTypes.node.isRequired, +}; diff --git a/src/components/Gradebook/gradebook.scss b/src/components/Gradebook/gradebook.scss index 05a9f3a..7f15c2d 100644 --- a/src/components/Gradebook/gradebook.scss +++ b/src/components/Gradebook/gradebook.scss @@ -17,18 +17,10 @@ color: black; } -.gradebook-container{ - width: 500px; - @media only screen and (min-width: 640px) { - width: 630px; - } - @media only screen and (min-width: 992px) { - width: 900px; - } - @media only screen and (min-width: 1200px) { - width: 1024px; - } - +.gradebook-content { + // note that this width isn't well-abstracted from Drawer code. + // if we need to change it we may need to dig into those styles as well + width: 100vw; .search-help-text { margin-left: 20px; } @@ -79,7 +71,8 @@ .table { padding-left: 244px; - + // prevents the table from shrinking to a width where "Final 01" breaks to two lines + min-width: 731px; th { vertical-align: top; font-size: 14px; diff --git a/src/components/Gradebook/index.jsx b/src/components/Gradebook/index.jsx index f091e27..caea9ea 100644 --- a/src/components/Gradebook/index.jsx +++ b/src/components/Gradebook/index.jsx @@ -16,9 +16,10 @@ import { import { trackEvent } from '@redux-beacon/segment'; import queryString from 'query-string'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { faDownload, faSpinner } from '@fortawesome/free-solid-svg-icons'; +import { faDownload, faSpinner, faFilter } from '@fortawesome/free-solid-svg-icons'; import { configuration } from '../../config'; import PageButtons from '../PageButtons'; +import Drawer from '../Drawer'; import { formatDateForDisplay } from '../../data/actions/utils'; import { trackingCategory } from '../../data/store'; @@ -495,11 +496,12 @@ export default class Gradebook extends React.Component { return valueAsInt >= 0 && valueAsInt <= 100; }; + render() { return ( -
-
-
+ ( +
Step 1: Filter the Grade Report
{this.props.showSpinner &&
} -
- -
-
- - Assignment Types: - - -
-
- - Assignment: - - -
-

Grade Range (0% - 100%)

-
- - % - - % -
- -
- -
-
-
- - Student Groups: - - - -
-
- - Course Grade (0%-100%) - -
- this.handleCourseGradeFilterChange('min', value)} - type="number" - min={0} - max={100} - /> - % - this.handleCourseGradeFilterChange('max', value)} - type="number" - min={0} - max={100} - /> - % - -
-
-
+
@@ -710,7 +589,7 @@ export default class Gradebook extends React.Component { {this.props.showBulkManagement && (
)}
-
- +
+
+
+ {PageButtons(this.props)} )} - - + )} + initiallyOpen={false} + title={ + + Filter By... + + } + > + +
+
+ + Assignment Types: + + +
+
+ + Assignment: + + +
+

Grade Range (0% - 100%)

+
+ + % + + % +
+ +
+ +
+
+ +
+ this.handleCourseGradeFilterChange('min', value)} + type="number" + min={0} + max={100} + /> + % + this.handleCourseGradeFilterChange('max', value)} + type="number" + min={0} + max={100} + /> + % + +
+
+ + + + + ); } }