-
Notifications
You must be signed in to change notification settings - Fork 75
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
Use A+ as an LTI 1.3 tool #1104
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Made some minor stylistic comments. There are quite a lot of commits, I think many of them could still be combined together (just based on a quick glance on commit messages).
from userprofile.models import UserProfile | ||
from course.models import Enrollment | ||
|
||
def get_launch_url(request): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Recently we have applied type hints at method definitions. Could do so also in these new lti_tool modules, e.g.
def get_launch_url(request: HttpRequest) -> str:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now that we are running out time, I think we have to skip the static type hinting.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I requested some minor changes.
<div id="exercise"> | ||
{{ submission.feedback|safe }} | ||
</div> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think the HTML inside Jinja2 statements should be indented more. If you imagine the HTML with the if-elif-else-statements removed, then it is incorrectly indented. This file should be checked and the other indentations also reverted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note our coding style guide: https://apluslms.github.io/contribute/styleguides/html/
{% block exercise_wait %} | ||
{% include "lti_tool/_lti_exercise_wait.html" %} | ||
{% endblock %} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The include shouldn't be indented.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not? It is easier to read when the code inside a block or tag is indented more than the surrounding block/tag.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice work! I have plenty of comments, but most of them are just small changes/improvements.
You asked about the Acos exercises. I think their points are received in the following API function and the submission is also created in the A+ database only at that time:
Lines 125 to 132 in 9b530cb
status, errors, students = self.exercise.check_submission_allowed(student) | |
if status != self.exercise.SUBMIT_STATUS.ALLOWED: | |
return Response({'success': False, 'errors': errors}) | |
submission = Submission.objects.create(exercise=self.exercise) | |
submission.submitters.set(students) | |
# grade and update submission with data | |
return Response(_post_async_submission(request, self.exercise, submission, errors)) |
<div id="exercise"> | ||
{{ submission.feedback|safe }} | ||
</div> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note our coding style guide: https://apluslms.github.io/contribute/styleguides/html/
@murhum1 after your git force push, the commit history got broken in the same way what happened once before. Your branch contains a few unwanted copies of commits that already exist in the master branch. Though, you have rebased them so that their commit checksums have changed. |
Sorry, seems like I accidentally included extra commits in the rebase. This should be fixed now. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great! I have a couple of more comments that are quick to address. Are you able to finish them before the holidays?
Question about the git commit history: it looks like you have squashed all the git commits into one. Do you prefer to keep it that way? I think you previously said that one large commit is not optimal, but I can accept the squashed history too. Separating git commits is very time-consuming and we don't have much time left.
|
||
if "exercise_path" in launch_params: | ||
url_params = { | ||
k: launch_params[k] for k in ["exercise_path", "module_slug", "course_slug", "instance_slug"] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suppose it is possible that the teacher modifies the custom parameters in the Moodle external activity settings. Then, if they remove, e.g., the "module_slug"
parameter, this line crashes to KeyError
since the launch_params
dictionary does not contain the key. At least, the students can't do that to cause crashes on purpose.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for e in children: | ||
if e.max_points > 0: | ||
li = LineItem() | ||
li.set_tag(str(e.id)).set_score_maximum(e.max_points).set_label(str(e)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did we yet talk about multilingual courses (Finnish and English materials)? What kind of name is displayed in the Moodle gradebook for the exercise grade item? Anyway, if it contains both languages now, we can return to that later and clean it up.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It does contain both languages - let's check up on that later, then.
# Create gradebook items | ||
ags = self.message_launch.get_ags() | ||
children = self.exercise.children.all() | ||
if len(children) > 0: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does the existence of children imply that this is a chapter with embedded exercises in it? Then, the gradebook items are created for the child exercises, right?
This is not important now, but in theory, any learning object may have several layers of children. I think exercise.children
includes only the direct children, not the "grandchildren" etc. We don't really have any courses that use such extra layers of children.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yea, right now it only creates gradebook items for children and not grandchildren - was not aware there could be more layers.
Thanks for the comments! I should've fixed the last issues now. I figured squashing the commits to one (+ PR change requests separately) was the least painful way of doing this for now. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! I will squash the git commits and merge this pull request now. I will soon also write more comments that we could discuss after the holidays. Further fixing and tweaking may continue in new pull requests.
|
||
class LtiSessionMixin(BaseMixin): | ||
|
||
@csrf_exempt |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I got surprised that you added this csrf_exempt
in the last changes. Why is this needed? Through this mixin class, I assume the exempt affects almost all LTI views.
try: | ||
if submission.lti_launch_id: | ||
send_lti_points(request, submission) | ||
except AttributeError: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this try-except is needed now that the property submission.lti_launch_id
contains the same try-except.
A+ may be used as an external tool from LTI platforms such as Moodle. There are some unfinished parts left in this feature, for example, the LTI grading service is missing for Acos server assignments and other assignment services that create new, graded submissions by sending the submission data via the assignment service in the end of the student's workflow. The discussion in the pull request contains more items to be fixed later. apluslms#1104 Mikko and Eerik implemented small parts of the feature. Markus did most of the work in this commit. Co-authored-by: Murhu Mikko <mikko.murhu@aalto.fi> Co-authored-by: Saksi Eerik <saksi.eerik@gmail.com>
Remaining issues that I know thus far.
Bigger design question: Is it necessary to make new view classes for LTI: The LTI classes mainly just set different HTML templates and otherwise, they are the same as the normal views. A view class could also select HTML templates dynamically in the Pseudo-code about the idea: normal views could use different LTI templates if the request includes LTI parameters. Otherwise, the normal template is rendered.
Is this related at all? Iframe links and error http status: #1115 |
The A+ LTI Tool v1.3 (apluslms#1104) implementation broke the polling of the submission feedback in full-view exercise pages. The polling was also broken in the LTI exercise full-view pages. Remove the URL `lti-submission-poll` because it used the same view as the normal `submission-poll` URL. The template `_lti_exercise_wait.html` is not needed since it was a copy of `_exercise_wait.html` with a different poll URL. The template block `exercise_wait` is now unnecessary. It was added in apluslms#1104. Adding the block was a mistake originally since the parent templates did not have such a block and it basically did not render anything. The block `exercise_wait` was not part of any existing block. The template `lti_submission.html` should not override the block `exerciseinfo`. It was copied from `submission.html` and the submission info page was thus rendered twice in the LTI submission page. Fixes apluslms#1114 Closes apluslms#1162
The A+ LTI Tool v1.3 (apluslms#1104) implementation broke the polling of the submission feedback in full-view exercise pages. The polling was also broken in the LTI exercise full-view pages. Remove the URL `lti-submission-poll` because it used the same view as the normal `submission-poll` URL. The template `_lti_exercise_wait.html` is not needed since it was a copy of `_exercise_wait.html` with a different poll URL. Poll.js is changed so that the final target URL can be configured through HTML data attributes. Previously, poll.js had a hardcoded assumption that the final target URL could be derived from the poll URL by dropping the word "poll" from the end of the poll URL. That was not flexible enough for LTI Tool URLs that start with the "/lti" prefix. The template block `exercise_wait` is now unnecessary. It was added in apluslms#1104. Adding the block was a mistake originally since the parent templates did not have such a block and it basically did not render anything. The block `exercise_wait` was not part of any existing block. The template `lti_submission.html` should not override the block `exerciseinfo`. It was copied from `submission.html` and the submission info page was thus rendered twice in the LTI submission page. Fixes apluslms#1114 Closes apluslms#1162
The A+ LTI Tool v1.3 (apluslms#1104) implementation broke the polling of the submission feedback in full-view exercise pages. The polling was also broken in the LTI exercise full-view pages. Remove the URL `lti-submission-poll` because it used the same view as the normal `submission-poll` URL. The template `_lti_exercise_wait.html` is not needed since it was a copy of `_exercise_wait.html` with a different poll URL. Poll.js is changed so that the final target URL can be configured through HTML data attributes. Previously, poll.js had a hardcoded assumption that the final target URL could be derived from the poll URL by dropping the word "poll" from the end of the poll URL. That was not flexible enough for LTI Tool URLs that start with the "/lti" prefix. The template block `exercise_wait` is now unnecessary. It was added in apluslms#1104. Adding the block was a mistake originally since the parent templates did not have such a block and it basically did not render anything. The block `exercise_wait` was not part of any existing block. The template `lti_submission.html` should not override the block `exerciseinfo`. It was copied from `submission.html` and the submission info page was thus rendered twice in the LTI submission page. Fixes apluslms#1114 Closes apluslms#1162
Description
This PR adds functionality to A+ that enables it to be used as an LTI 1.3 tool in Moodle and possibly other LTI platforms.
Why?
Historically, the A+ Astra moodle plugin that enables A+ exercises to be used in Moodle, required updates whenever the deployed Moodle version changed. By using the LTI standard to add the functionality instead, we ensure compatibility through version updates.
How?
The PR adds LTI protocol specific urls, views, and templates that allow embedding A+ material in an LTI context, and allow users to submit exercises to be graded in A+, with grading results being sent back to the Moodle gradebook. LTI deep linking is also supported, allowing teachers to select content via a UI.
Testing
What type of test did you run?
Tested in Moodle:
Did you test the changes in
Mostly Firefox; Chrome only occasionally during development.
Think of what is affected by these changes and could become broken
Most of the functionality is standalone and should not affect main A+ functionality. Some templates have been modified, mainly adding overwritable blocks, which shouldn't break things. Some code was added to submitting exercise solutions and receiving grades, but the additions are only used in LTI contexts.
Programming style
Have you updated the README or other relevant documentation?
Documentation regarding the local development setup should be added later.
Is it Done?
Known issues
ACOS exercises do not have their grading results sent to Moodle - this still requires extra thought.