Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Submission scores in Assigment List #1934

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions nbgrader/exchange/default/list.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import shutil
import re
import hashlib
from lxml import html

from nbgrader.exchange.abc import ExchangeList as ABCExchangeList
from nbgrader.utils import notebook_hash, make_unique_key
Expand All @@ -14,6 +15,13 @@ def _checksum(path):
m.update(open(path, 'rb').read())
return m.hexdigest()

def get_meta_value(html_data, key):
document = html.fromstring(html_data)
meta_content = document.xpath(f'//meta[@name="nbgrader-{key}"]/@content')
if meta_content:
return meta_content[0]
return None


class ExchangeList(ABCExchangeList, Exchange):

Expand Down Expand Up @@ -209,11 +217,22 @@ def parse_assignments(self):
for key in assignment_keys:
submissions = [x for x in assignments if _match_key(x, key)]
submissions = sorted(submissions, key=lambda x: x['timestamp'])

submisstions_with_feedback = [x for x in submissions if x['has_local_feedback']]
score, max_score = None, None
if len(submisstions_with_feedback) > 0 and submisstions_with_feedback[-1]['local_feedback_path'] is not None:
feedback_file = os.path.join(submisstions_with_feedback[-1]['local_feedback_path'], key[2] + ".html")
feedback_html = open(feedback_file, 'r').read()
score = get_meta_value(feedback_html, 'score')
max_score = get_meta_value(feedback_html, 'max-score')

info = {
'course_id': key[0],
'student_id': key[1],
'assignment_id': key[2],
'status': submissions[0]['status'],
'score': float(score) if score is not None else None,
'max_score': float(max_score) if max_score is not None else None,
'submissions': submissions
}
assignment_submissions.append(info)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
<head>

<meta charset="utf-8" />
<meta name="nbgrader-score" content="{{ resources.nbgrader.score | float | round(2) }}" />
<meta name="nbgrader-max-score" content="{{ resources.nbgrader.max_score | float | round(2) }}" />
<title>{{ resources.nbgrader.notebook }}</title>

{{ resources.include_css('bootstrap.min.css')}}
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ dependencies = [
"setuptools",
"sqlalchemy>=1.4,<3",
"PyYAML>=6.0",
"lxml>=5.3.0",
]
version = "0.9.3"

Expand Down
33 changes: 32 additions & 1 deletion src/assignment_list/assignmentlist.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@ export class AssignmentList {
private load_list_success(data: string | any[]): void {
this.clear_list(false);

var total_score = 0;
var total_max_score = 0;
var show_score = false;
var len = data.length;
for (var i=0; i<len; i++) {
var element = document.createElement('div');
Expand All @@ -102,8 +105,28 @@ export class AssignmentList {
} else if (data[i]['status'] === 'submitted') {
this.submitted_element.append(element);
(<HTMLDivElement>this.submitted_element.children.namedItem('submitted_assignments_list_placeholder')).hidden = true;

if (data[i]['score'] != null && data[i]['max_score'] != null) {
total_score += data[i]['score'];
total_max_score += data[i]['max_score'];
show_score = true;
}
}
}

var score_heading_element = document.getElementById(this.options.get('score_heading_id'));
var total_score_container = document.getElementById(this.options.get('total_score_container_id'));
var total_score_element = document.getElementById(this.options.get('total_score_id'));

if (score_heading_element) {
score_heading_element.style.visibility = show_score ? 'visible' : 'hidden';
}
if (total_score_container) {
total_score_container.style.visibility = show_score ? 'visible' : 'hidden';
}
if (total_score_element) {
total_score_element.innerText = `${total_score}/${total_max_score}`;
}

var assignments = this.fetched_element.getElementsByClassName('assignment-notebooks-link');
for(let a of assignments){
Expand Down Expand Up @@ -226,7 +249,7 @@ class Assignment {

private make_link(): HTMLSpanElement {
var container = document.createElement('span');;
container.classList.add('item_name', 'col-sm-6');
container.classList.add('item_name', 'col-sm-4');

var link;
if (this.data['status'] === 'fetched') {
Expand Down Expand Up @@ -360,10 +383,18 @@ class Assignment {
s.classList.add('item_course', 'col-sm-2')
s.innerText = this.data['course_id']
row.append(s)
var score = document.createElement('span');
score.classList.add('item_status', 'col-sm-2');
score.setAttribute('style', 'text-align:left');
row.append(score);

var id, element;
var children = document.createElement('div');
if (this.data['status'] == 'submitted') {
if (this.data['score'] != null && this.data['max_score'] != null) {
score.innerText = this.data['score'] + '/' + this.data['max_score'];
}

id = this.escape_id() + '-submissions';
children.id = id;
children.classList.add('panel-collapse', 'list_container', 'assignment-notebooks');
Expand Down
10 changes: 9 additions & 1 deletion src/assignment_list/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,8 @@ export class AssignmentListWidget extends Widget {
' </div>',
' <div class="panel panel-default">',
' <div class="panel-heading">',
' Submitted assignments',
' <span class="col-sm-6">Submitted assignments</span>',
' <span id="score-heading">Score</span>',
' </div>',
' <div class="panel-body">',
' <div id="submitted_assignments_list" class="list_container">',
Expand All @@ -97,6 +98,10 @@ export class AssignmentListWidget extends Widget {
' </div>',
' </div>',
' </div>',
' <div id="total-score-row" class="panel-heading">',
' <span class="col-sm-6"><b>Total Score</b></span>',
' <b id="total-score"></b>',
' </div>',
' </div>',
' </div> ',
'</div>'
Expand All @@ -108,6 +113,9 @@ export class AssignmentListWidget extends Widget {
let base_url = PageConfig.getBaseUrl();
let options = new Map();
options.set('base_url',base_url);
options.set('score_heading_id', 'score-heading');
options.set('total_score_container_id', 'total-score-row');
options.set('total_score_id', 'total-score');
var assignment_l = new AssignmentList(this,
'released_assignments_list',
'fetched_assignments_list',
Expand Down
Loading