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

Add refetch button to assignment list #1930

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
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
20 changes: 11 additions & 9 deletions nbgrader/server_extensions/assignment_list/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ def list_courses(self):

return retvalue

def fetch_assignment(self, course_id, assignment_id):
def fetch_assignment(self, course_id, assignment_id, replace_missing_files=False):
with self.get_assignment_dir_config() as config:
try:
config = self.load_config()
Expand All @@ -205,7 +205,9 @@ def fetch_assignment(self, course_id, assignment_id):
fetch = ExchangeFactory(config=config).FetchAssignment(
coursedir=coursedir,
authenticator=authenticator,
config=config)
config=config,
replace_missing_files=replace_missing_files
)
fetch.start()

except:
Expand Down Expand Up @@ -310,22 +312,22 @@ def post(self, action):
except web.MissingArgumentError:
data = self.get_json_body()

assignment_id = data['assignment_id']
course_id = data['course_id']

if action == 'fetch':
assignment_id = data['assignment_id']
course_id = data['course_id']
self.manager.fetch_assignment(course_id, assignment_id)
self.finish(json.dumps(self.manager.list_assignments(course_id=course_id)))
elif action == 'fetch_missing':
self.manager.fetch_assignment(course_id, assignment_id, replace_missing_files=True)
self.finish(json.dumps(self.manager.list_assignments(course_id=course_id)))
elif action == 'submit':
assignment_id = data['assignment_id']
course_id = data['course_id']
output = self.manager.submit_assignment(course_id, assignment_id)
if output['success']:
self.finish(json.dumps(self.manager.list_assignments(course_id=course_id)))
else:
self.finish(json.dumps(output))
elif action == 'fetch_feedback':
assignment_id = data['assignment_id']
course_id = data['course_id']
self.manager.fetch_feedback(course_id, assignment_id)
self.finish(json.dumps(self.manager.list_assignments(course_id=course_id)))

Expand Down Expand Up @@ -367,7 +369,7 @@ def get(self):
#-----------------------------------------------------------------------------


_assignment_action_regex = r"(?P<action>fetch|submit|fetch_feedback)"
_assignment_action_regex = r"(?P<action>fetch|fetch_missing|submit|fetch_feedback)"

default_handlers = [
(r"/assignments", AssignmentListHandler),
Expand Down
30 changes: 30 additions & 0 deletions src/assignment_list/assignmentlist.ts
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,36 @@ class Assignment {

}
} else if (this.data.status == 'fetched') {
var refetchButton = document.createElement('button');
refetchButton.classList.add('btn', 'btn-danger', 'btn-xs');
refetchButton.setAttribute('data-bs-toggle', 'tooltip');
refetchButton.setAttribute('data-bs-placement', 'top');
refetchButton.setAttribute('style', 'background:#d43f3a; margin-left:5px');
refetchButton.setAttribute('title', 'If you broke any of your assignment files and you want to redownload them, delete those files and click this button to refetch the original version of those files.')
container.append(refetchButton);

refetchButton.innerText = 'Refetch';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Refetch" is quite ambiguous, somebody might expect that it will overwrite existing files. Can we call it "Fetch missing files" (or "Refetch missing files")?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would also be nice to have the button disabled if no files are actually missing.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, the button can be renamed to "Refetch missing files".

The problem with disabling the button is that the Exchange has no API for listing all the files of an assignment. Or well... there is ExchangeList.list_files(), but in the default exchange, it is implemented in a weird way, where it does not really list any files. Instead, it returns a list of assignments. So it sure can be done by modifying the exchange a bit, but people can already rely on the way it works now so then it would break their stuff. Someone can even have their own exchange implementation, and since the output of list_files() is not unified, I think, it will not work for everyone.

Do you have any better idea regarding this?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, so the API would probably have to be extended with a new function... But it can be done later, this is still a big improvement!

refetchButton.onclick = async function(){
refetchButton.innerText = 'Refetching...';
refetchButton.setAttribute('disabled', 'disabled');
const dataToSend = { course_id: that.data['course_id'], assignment_id: that.data['assignment_id']};
try {
const reply = await requestAPI<any>('assignments/fetch_missing', {
body: JSON.stringify(dataToSend),
method: 'POST'
});

that.on_refresh(reply);

} catch (reason) {
remove_children(container);
container.innerText = 'Error refetching assignment.';
console.error(
`Error on POST /assignment_list/fetch_missing ${dataToSend}.\n${reason}`
);
}
}

button.innerText = "Submit";
button.onclick = async function(){
button.innerText = 'submitting...';
Expand Down
Loading