feat: always show total as a pct, add tooltip (#170)
This commit is contained in:
2
package-lock.json
generated
2
package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@edx/frontend-app-gradebook",
|
||||
"version": "1.4.22",
|
||||
"version": "1.4.24",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@edx/frontend-app-gradebook",
|
||||
"version": "1.4.23",
|
||||
"version": "1.4.24",
|
||||
"description": "edx editable gradebook-ui to manipulate grade overrides on subsections",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -2,12 +2,13 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { Table } from '@edx/paragon';
|
||||
|
||||
import {
|
||||
Table, OverlayTrigger, Tooltip, Icon,
|
||||
} from '@edx/paragon';
|
||||
import { formatDateForDisplay } from '../../data/actions/utils';
|
||||
import { getHeadings } from '../../data/selectors/grades';
|
||||
import { fetchGradeOverrideHistory } from '../../data/actions/grades';
|
||||
import { EMAIL_HEADING, TOTAL_COURSE_GRADE_HEADING, USERNAME_HEADING } from '../../data/constants/grades';
|
||||
|
||||
const DECIMAL_PRECISION = 2;
|
||||
|
||||
@@ -49,10 +50,10 @@ export class GradebookTable extends React.Component {
|
||||
percent: (entries, areGradesFrozen) => entries.map((entry) => {
|
||||
const learnerInformation = this.getLearnerInformation(entry);
|
||||
const results = {
|
||||
Username: (
|
||||
[USERNAME_HEADING]: (
|
||||
<div><span className="wrap-text-in-cell">{learnerInformation}</span></div>
|
||||
),
|
||||
Email: (
|
||||
[EMAIL_HEADING]: (
|
||||
<span className="wrap-text-in-cell">{entry.email}</span>
|
||||
),
|
||||
};
|
||||
@@ -73,17 +74,17 @@ export class GradebookTable extends React.Component {
|
||||
}
|
||||
return acc;
|
||||
}, {});
|
||||
const totals = { Total: `${this.roundGrade(entry.percent * 100)}%` };
|
||||
const totals = { [TOTAL_COURSE_GRADE_HEADING]: `${this.roundGrade(entry.percent * 100)}%` };
|
||||
return Object.assign(results, assignments, totals);
|
||||
}),
|
||||
|
||||
absolute: (entries, areGradesFrozen) => entries.map((entry) => {
|
||||
const learnerInformation = this.getLearnerInformation(entry);
|
||||
const results = {
|
||||
Username: (
|
||||
[USERNAME_HEADING]: (
|
||||
<div><span className="wrap-text-in-cell">{learnerInformation}</span></div>
|
||||
),
|
||||
Email: (
|
||||
[EMAIL_HEADING]: (
|
||||
<span className="wrap-text-in-cell">{entry.email}</span>
|
||||
),
|
||||
};
|
||||
@@ -111,7 +112,10 @@ export class GradebookTable extends React.Component {
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
const totals = { Total: `${this.roundGrade(entry.percent * 100)}/100` };
|
||||
// Show this as a percent no matter what the other setting is. The data
|
||||
// we're getting gives the final grade as a percentage so making it appear
|
||||
// to be "out of" 100 is misleading.
|
||||
const totals = { [TOTAL_COURSE_GRADE_HEADING]: `${this.roundGrade(entry.percent * 100)}%` };
|
||||
return Object.assign(results, assignments, totals);
|
||||
}),
|
||||
};
|
||||
@@ -120,22 +124,44 @@ export class GradebookTable extends React.Component {
|
||||
let headings = [...this.props.headings];
|
||||
|
||||
if (headings.length > 0) {
|
||||
const userInformationHeadingLabel = (
|
||||
const headerLabelReplacements = {};
|
||||
headerLabelReplacements[USERNAME_HEADING] = (
|
||||
<div>
|
||||
<div>Username</div>
|
||||
<div className="font-weight-normal student-key">Student Key*</div>
|
||||
</div>
|
||||
);
|
||||
const emailHeadingLabel = 'Email*';
|
||||
headerLabelReplacements[EMAIL_HEADING] = 'Email*';
|
||||
|
||||
headings = headings.map(heading => ({
|
||||
label: heading,
|
||||
key: heading,
|
||||
}));
|
||||
const totalGradePercentageMessage = 'Total Grade values are always displayed as a percentage.';
|
||||
headerLabelReplacements[TOTAL_COURSE_GRADE_HEADING] = (
|
||||
<div>
|
||||
<OverlayTrigger
|
||||
trigger={['hover', 'focus']}
|
||||
key="left-basic"
|
||||
placement="left"
|
||||
overlay={(<Tooltip id="course-grade-tooltip">{totalGradePercentageMessage}</Tooltip>)}
|
||||
>
|
||||
<div>
|
||||
{TOTAL_COURSE_GRADE_HEADING}
|
||||
<div id="courseGradeTooltipIcon">
|
||||
<Icon className="fa fa-info-circle" screenReaderText={totalGradePercentageMessage} />
|
||||
</div>
|
||||
</div>
|
||||
</OverlayTrigger>
|
||||
</div>
|
||||
);
|
||||
|
||||
// replace username heading label to include additional user data
|
||||
headings[0].label = userInformationHeadingLabel;
|
||||
headings[1].label = emailHeadingLabel;
|
||||
headings = headings.map(heading => {
|
||||
const result = {
|
||||
label: heading,
|
||||
key: heading,
|
||||
};
|
||||
if (headerLabelReplacements[heading] !== undefined) {
|
||||
result.label = headerLabelReplacements[heading];
|
||||
}
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
return headings;
|
||||
|
||||
@@ -72,7 +72,10 @@
|
||||
.student-key {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
|
||||
#courseGradeTooltipIcon {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.table thead tr {
|
||||
min-height: 60px;
|
||||
@@ -111,6 +114,9 @@
|
||||
td:nth-child(2) {
|
||||
width: 240px;
|
||||
}
|
||||
th:nth-last-of-type(1) {
|
||||
width: 150px;
|
||||
}
|
||||
th, td {
|
||||
width: 120px;
|
||||
}
|
||||
|
||||
5
src/data/constants/grades.js
Normal file
5
src/data/constants/grades.js
Normal file
@@ -0,0 +1,5 @@
|
||||
const EMAIL_HEADING = 'Email';
|
||||
const TOTAL_COURSE_GRADE_HEADING = 'Total Grade (%)';
|
||||
const USERNAME_HEADING = 'Username';
|
||||
|
||||
export { EMAIL_HEADING, TOTAL_COURSE_GRADE_HEADING, USERNAME_HEADING };
|
||||
@@ -1,5 +1,6 @@
|
||||
import { formatDateForDisplay } from '../actions/utils';
|
||||
import { getFilters } from './filters';
|
||||
import { EMAIL_HEADING, TOTAL_COURSE_GRADE_HEADING, USERNAME_HEADING } from '../constants/grades';
|
||||
|
||||
const getRowsProcessed = (data) => {
|
||||
const {
|
||||
@@ -52,13 +53,13 @@ const headingMapper = (category, label = 'All') => {
|
||||
|
||||
return (entry) => {
|
||||
if (entry) {
|
||||
const results = ['Username', 'Email'];
|
||||
const results = [USERNAME_HEADING, EMAIL_HEADING];
|
||||
|
||||
const assignmentHeadings = entry
|
||||
.filter(filters[filter])
|
||||
.map(s => s.label);
|
||||
|
||||
const totals = ['Total'];
|
||||
const totals = [TOTAL_COURSE_GRADE_HEADING];
|
||||
|
||||
return results.concat(assignmentHeadings).concat(totals);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user