123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198 |
- /*
- * Copyright (C) 2017 - present Instructure, Inc.
- *
- * This file is part of Canvas.
- *
- * Canvas is free software: you can redistribute it and/or modify it under
- * the terms of the GNU Affero General Public License as published by the Free
- * Software Foundation, version 3 of the License.
- *
- * Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
- * details.
- *
- * You should have received a copy of the GNU Affero General Public License along
- * with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- import React, { Component } from 'react';
- import { connect } from 'react-redux';
- import { arrayOf, bool, func, node, shape, string } from 'prop-types';
- import $ from 'jquery';
- import 'jquery.instructure_date_and_time'
- import I18n from 'i18n!gradebook_history';
- import Container from 'instructure-ui/lib/components/Container';
- import ScreenReaderContent from 'instructure-ui/lib/components/ScreenReaderContent';
- import Spinner from 'instructure-ui/lib/components/Spinner';
- import Table from 'instructure-ui/lib/components/Table';
- import Typography from 'instructure-ui/lib/components/Typography';
- import { getHistoryNextPage } from 'jsx/gradebook-history/actions/SearchResultsActions';
- import SearchResultsRow from 'jsx/gradebook-history/SearchResultsRow';
- const colHeaders = [
- I18n.t('Date'),
- <ScreenReaderContent>{I18n.t('Anonymous Grading')}</ScreenReaderContent>,
- I18n.t('Student'),
- I18n.t('Grader'),
- I18n.t('Assignment'),
- I18n.t('Before'),
- I18n.t('After'),
- I18n.t('Current')
- ];
- const nearPageBottom = () => (
- document.body.clientHeight - (window.innerHeight + window.scrollY) < 100
- );
- class SearchResultsComponent extends Component {
- static propTypes = {
- getNextPage: func.isRequired,
- fetchHistoryStatus: string.isRequired,
- caption: node.isRequired,
- historyItems: arrayOf(shape({
- anonymous: bool.isRequired,
- assignment: string.isRequired,
- date: string.isRequired,
- displayAsPoints: bool.isRequired,
- grader: string.isRequired,
- gradeAfter: string.isRequired,
- gradeBefore: string.isRequired,
- gradeCurrent: string.isRequired,
- id: string.isRequired,
- pointsPossibleAfter: string.isRequired,
- pointsPossibleBefore: string.isRequired,
- pointsPossibleCurrent: string.isRequired,
- student: string.isRequired
- })).isRequired,
- nextPage: string.isRequired,
- requestingResults: bool.isRequired
- };
- componentDidMount () {
- this.attachListeners();
- }
- componentDidUpdate (prevProps) {
- // if the page doesn't have a scrollbar, scroll event listener can't be triggered
- if (document.body.clientHeight <= window.innerHeight) {
- this.getNextPage();
- }
- if (prevProps.historyItems.length < this.props.historyItems.length) {
- $.screenReaderFlashMessage(I18n.t('More results were added at the bottom of the page.'));
- }
- this.attachListeners();
- }
- componentWillUnmount () {
- this.detachListeners();
- }
- getNextPage = () => {
- if (!this.props.requestingResults && this.props.nextPage && nearPageBottom()) {
- this.props.getNextPage(this.props.nextPage);
- this.detachListeners();
- }
- }
- attachListeners = () => {
- if (this.props.requestingResults || !this.props.nextPage) {
- return;
- }
- document.addEventListener('scroll', this.getNextPage);
- window.addEventListener('resize', this.getNextPage);
- }
- detachListeners = () => {
- document.removeEventListener('scroll', this.getNextPage);
- window.removeEventListener('resize', this.getNextPage);
- }
- hasHistory () {
- return this.props.historyItems.length > 0;
- }
- noResultsFound () {
- return this.props.fetchHistoryStatus === 'success' && !this.hasHistory();
- }
- showResults = () => (
- <div>
- <Table
- caption={this.props.caption}
- >
- <thead>
- <tr>
- {colHeaders.map(header => (
- <th scope="col" key={`${header}-column`}>{ header }</th>
- ))}
- </tr>
- </thead>
- <tbody>
- {this.props.historyItems.map(item => (
- <SearchResultsRow
- key={`history-items-${item.id}`}
- item={item}
- />
- ))}
- </tbody>
- </Table>
- </div>
- )
- showStatus = () => {
- if (this.props.requestingResults) {
- $.screenReaderFlashMessage(I18n.t('Loading more gradebook history results.'));
- return (
- <Spinner size="small" title={I18n.t('Loading Results')} />
- );
- }
- if (this.noResultsFound()) {
- return (<Typography fontStyle="italic">{I18n.t('No results found.')}</Typography>);
- }
- if (!this.props.requestingResults && !this.props.nextPage && this.hasHistory()) {
- return (<Typography fontStyle="italic">{I18n.t('No more results to load.')}</Typography>);
- }
- return null;
- }
- render () {
- return (
- <div>
- {this.hasHistory() && this.showResults()}
- <Container as="div" textAlign="center" margin="medium 0 0 0">
- {this.showStatus()}
- </Container>
- </div>
- );
- }
- }
- const mapStateToProps = state => (
- {
- fetchHistoryStatus: state.history.fetchHistoryStatus || '',
- historyItems: state.history.items || [],
- nextPage: state.history.nextPage || '',
- requestingResults: state.history.loading || false,
- }
- );
- const mapDispatchToProps = dispatch => (
- {
- getNextPage: (url) => {
- dispatch(getHistoryNextPage(url));
- }
- }
- );
- export default connect(mapStateToProps, mapDispatchToProps)(SearchResultsComponent);
- export { SearchResultsComponent };
|