Skip to content

Commit

Permalink
Merge pull request #6175 from mishaschwartz/v2.1.1
Browse files Browse the repository at this point in the history
V2.1.1
  • Loading branch information
mishaschwartz authored Aug 16, 2022
2 parents 1971df7 + 7823b74 commit 022e63c
Show file tree
Hide file tree
Showing 38 changed files with 884 additions and 498 deletions.
10 changes: 9 additions & 1 deletion Changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# Changelog

## [v2.1.1]
- Fix bug where files could not be uploaded using drag and drop if no files or folders previously existed. (#6117)
- Added drag and drop functionality to upload starter files and automated tests. (#6117)
- Added new summary statistics display for grade entry forms and grade entry column items (#6118)
- Moved markdown text preview to new tab in the modify/create annotation modal (#6138)
- Enable bulk removal of students from section in student table (#6145)
- Enable updating student active/inactive status in student edit form (#6145)

## [v2.1.0]
- Remove unmaintained locales (#5727)
- Introduce standalone ruby script as an alternative method to checking for repository access (#5736)
Expand Down Expand Up @@ -63,9 +71,9 @@
- Added explicit status and filtering for inactive students and groups in assignment groups page. (#6112)
- Fixed flaky automated test file tests by rearranging order of test file cleanup (#6114)
- Changed nav bar layout by moving the MarkUs logo beside the course name on the top bar (#6115)
- Ensure each file viewer has independent syntax highlighting (#6139)
- Replace standalone ruby script to check for repository access with database function (#6116)
- Update git over ssh scripts to optionally use the database function to check for repository access (#6116)
- Ensure each file viewer has independent syntax highlighting (#6139)
- Update git over ssh scripts to use the database function to check for authorized keys (#6142)
- Remove support for sqlite and mysql database types (#6143)
- Replace uglifier gem with terser gem to support ES6 syntax (#6146)
Expand Down
2 changes: 1 addition & 1 deletion app/MARKUS_VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
VERSION=2.1.0,PATCH_LEVEL=DEV
VERSION=2.1.1,PATCH_LEVEL=DEV
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import React from "react";
import {Bar} from "react-chartjs-2";
import PropTypes from "prop-types";
import {chartScales} from "../Helpers/chart_helpers";
import {CoreStatistics} from "./core_statistics";

export class AssessmentChart extends React.Component {
render() {
return (
<div className="flex-row">
<div className="distribution-graph">
<h3>{I18n.t("grade_distribution")}</h3>
<Bar
data={this.props.assessment_data}
options={{scales: chartScales()}}
width="500"
height="450"
/>
</div>
<div className="flex-row-expand">
<div className="grid-2-col">
{this.props.additional_assessment_stats}
<CoreStatistics
average={this.props.summary.average}
median={this.props.summary.median}
standard_deviation={this.props.summary.standard_deviation}
max_mark={this.props.summary.max_mark}
num_fails={this.props.summary.num_fails}
num_zeros={this.props.summary.num_zeros}
num_groupings={this.props.summary.groupings_size}
/>
{this.props.outstanding_remark_request_link}
</div>
</div>
</div>
);
}
}

AssessmentChart.propTypes = {
assessment_data: PropTypes.object.isRequired,
summary: PropTypes.object.isRequired,
additional_assessment_stats: PropTypes.element.isRequired,
outstanding_remark_request_link: PropTypes.element,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import React from "react";
import {FractionStat} from "./fraction_stat";
import PropTypes from "prop-types";

export class CoreStatistics extends React.Component {
render() {
const max_mark_value = Number(this.props.max_mark) || 0;
let percent_standard_deviation = "0.00";
if (max_mark_value !== 0) {
percent_standard_deviation = (
(100 / max_mark_value) *
(Number(this.props.standard_deviation) || 0)
).toFixed(2);
}
let num_fails = "";
if (this.props.num_fails !== undefined) {
num_fails = (
<React.Fragment>
<span className="summary-stats-label">{I18n.t("num_failed")}</span>
<FractionStat numerator={this.props.num_fails} denominator={this.props.num_groupings} />
</React.Fragment>
);
}

return (
<React.Fragment>
<span className="summary-stats-label">{I18n.t("average")}</span>
<FractionStat numerator={this.props.average} denominator={this.props.max_mark} />
<span className="summary-stats-label">{I18n.t("median")}</span>
<FractionStat numerator={this.props.median} denominator={this.props.max_mark} />
<span className="summary-stats-label">{I18n.t("standard_deviation")}</span>
<span>
{(this.props.standard_deviation || 0).toFixed(2)}
&nbsp;({percent_standard_deviation}%)
</span>
{num_fails}
<span className="summary-stats-label">{I18n.t("num_zeros")}</span>
<FractionStat numerator={this.props.num_zeros} denominator={this.props.num_groupings} />
</React.Fragment>
);
}
}

CoreStatistics.propTypes = {
average: PropTypes.number.isRequired,
median: PropTypes.number.isRequired,
standard_deviation: PropTypes.number.isRequired,
max_mark: PropTypes.number.isRequired,
num_fails: PropTypes.number,
num_zeros: PropTypes.number.isRequired,
num_groupings: PropTypes.number.isRequired,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React from "react";

export class FractionStat extends React.Component {
render() {
const numerator = +(Number(this.props.numerator) || 0).toFixed(2),
denominator = +(Number(this.props.denominator) || 0).toFixed(2);
let result = "0.00";
if (denominator !== 0) {
result = ((Number(this.props.numerator) / Number(this.props.denominator) || 0) * 100).toFixed(
2
);
}
return (
<span>
{numerator} / {denominator} ({result}%)
</span>
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import React from "react";
import {Bar} from "react-chartjs-2";
import {chartScales} from "../Helpers/chart_helpers";
import ReactTable from "react-table";
import PropTypes from "prop-types";
import {CoreStatistics} from "./core_statistics";
import {FractionStat} from "./fraction_stat";

export class GradeBreakdownChart extends React.Component {
render() {
let summary_table = "";
if (this.props.show_stats) {
summary_table = (
<div className="flex-row-expand">
<div className="grade-breakdown-summary-table">
<ReactTable
data={this.props.summary}
columns={[
{
Header: this.props.item_name,
accessor: "name",
minWidth: 150,
},
{
Header: I18n.t("average"),
accessor: "average",
sortable: false,
filterable: false,
Cell: row => (
<FractionStat
numerator={row.original.average}
denominator={row.original.max_mark}
/>
),
},
]}
defaultSorted={[{id: "position"}]}
SubComponent={row => (
<div className="grade-stats-breakdown grid-2-col">
<CoreStatistics
average={row.original.average}
median={row.original.median}
standard_deviation={row.original.standard_deviation}
max_mark={row.original.max_mark}
num_zeros={row.original.num_zeros}
num_groupings={this.props.num_groupings}
/>
</div>
)}
/>
</div>
</div>
);
}

if (this.props.summary.length > 0) {
const graph_options = {
plugins: {
legend: {
display: true,
labels: {
// Ensure criteria / grade entry item labels are sorted in position order
sort: (a, b) => {
const itemA = this.props.summary.find(item => item.name === a.text);
const itemB = this.props.summary.find(item => item.name === b.text);
return itemA.position - itemB.position;
},
},
},
},
scales: chartScales(),
};
return (
<div className="flex-row">
<div className="grade-breakdown-graph">
<h3>{this.props.chart_title}</h3>
<Bar
data={this.props.distribution_data}
options={graph_options}
width="400"
height="350"
/>
</div>
{summary_table}
</div>
);
} else {
return (
<div className="grade-breakdown-graph">
<h3>{this.props.chart_title}</h3>
<h4>
(
<a href={this.props.create_link === undefined ? "" : this.props.create_link}>
{I18n.t("helpers.submit.create", {
model: this.props.item_name,
})}
</a>
)
</h4>
</div>
);
}
}
}

GradeBreakdownChart.propTypes = {
show_stats: PropTypes.bool.isRequired,
summary: PropTypes.array.isRequired,
chart_title: PropTypes.string.isRequired,
distribution_data: PropTypes.object,
item_name: PropTypes.string.isRequired,
num_groupings: PropTypes.number.isRequired,
create_link: PropTypes.string,
};
Loading

0 comments on commit 022e63c

Please sign in to comment.