-
Notifications
You must be signed in to change notification settings - Fork 305
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
General
: Add LTI integration for Atlas, Iris, and Lectures
#10338
base: develop
Are you sure you want to change the base?
Conversation
…on-table' into chore/lti/extend-content-selection-table
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.
Development
: Enhance LTI featuresGeneral
: Enhance LTI features
General
: Enhance LTI featuresGeneral
: Enhance LTI features
General
: Enhance LTI featuresGeneral
: Add LTI integration for Atlas, Iris, and Lectures
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.
Code approvals & Manual tests all complete
Maintainer checked
TODO: I will lower the coverage threshold for lti - instructions in one single commit. All important functionality is covered (even the enum ...). I do not think that additional investigation into the coverage is reasonable to meet the required threshold.
If @krusche does not approve, we will have to revert the commit and somehow have to figure out how to improve the coverage.
a83ec9e
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.
Actionable comments posted: 0
🧹 Nitpick comments (1)
gradle/jacoco.gradle (1)
17-17
: Revisit the LTI Module Coverage Threshold Setting.The threshold for the LTI module is now set to an INSTRUCTION value of
0.810
with a CLASS threshold of2
. Please confirm that these specific values have been intentionally chosen to accommodate the new LTI integration features. It may be useful to double-check whether these thresholds align with the broader coverage expectations for the project and the additional functionality introduced in this PR.
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
src/main/resources/config/liquibase/master.xml
is excluded by!**/*.xml
📒 Files selected for processing (1)
gradle/jacoco.gradle
(1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (9)
- GitHub Check: Call Build Workflow / Build and Push Docker Image
- GitHub Check: Call Build Workflow / Build .war artifact
- GitHub Check: Codacy Static Code Analysis
- GitHub Check: client-tests-selected
- GitHub Check: client-tests
- GitHub Check: server-tests
- GitHub Check: server-style
- GitHub Check: client-style
- GitHub Check: Analyse
for (DeepLinkingType deepLinkingType : values()) { | ||
if (deepLinkingType.name().equalsIgnoreCase(type)) { | ||
return deepLinkingType; | ||
} | ||
} | ||
throw new IllegalArgumentException("Invalid deep linking type: " + type); |
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 (DeepLinkingType deepLinkingType : values()) { | |
if (deepLinkingType.name().equalsIgnoreCase(type)) { | |
return deepLinkingType; | |
} | |
} | |
throw new IllegalArgumentException("Invalid deep linking type: " + type); | |
return DeepLinkingType.valueOf(type.toUpperCase()); |
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.
this is much easier ;-)
} | ||
} | ||
|
||
private Map<String, Object> createExerciseContentItem(Exercise exercise, String url) { |
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 it make sense to use a map here? I would prefer a record type
@@ -125,6 +241,14 @@ private Map<String, Object> createContentItem(Exercise exercise, String url) { | |||
return item; | |||
} | |||
|
|||
private Map<String, Object> createLectureContentItem(Lecture lecture, String url) { |
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 it make sense to use a map here? I would prefer a record type
return Map.of("type", "ltiResourceLink", "title", lecture.getTitle(), "url", url); | ||
} | ||
|
||
private Map<String, Object> createSingleUnitContentItem(String url) { |
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 it make sense to use a map here? I would prefer a record type
* | ||
* @param courseId The course ID. | ||
*/ | ||
private ArrayList<Map<String, Object>> populateCompetencyContentItems(String courseId) { |
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.
this is an ugly return type. Please use List<RecordType>
if possible, also in all other places
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.
and in general you should avoid using ArrayList
as Type (except next to the new operator), always use List
instead
String targetLink = ltiDeepLinkingService.performDeepLinking(idToken, clientRegistrationId, courseId, exerciseIds); | ||
String targetLink; | ||
|
||
if (exerciseIds != null) { |
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 long if-else block looks ugly. I wonder if there are other solutions to solve this.
@EnforceAtLeastInstructor | ||
public ResponseEntity<String> lti13DeepLinking(@PathVariable Long courseId, @RequestParam(name = "exerciseIds") Set<Long> exerciseIds, | ||
@EnforceAtLeastInstructorInCourse | ||
public ResponseEntity<String> lti13DeepLinking(@PathVariable Long courseId, @RequestParam(name = "exerciseIds", required = false) Set<Long> exerciseIds, |
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 suggest to change the input parameters. It seems that all options are mutually exclusive so you could directly send a required type (potentially string or if possible and enum) whether exercises, lectures, competency, iris or learningPath is linked. Then you have a second parameter contentIds (required = false) which are either exerciseIds or lectureIds based the previously defined type. This would be much cleaner and would also allow you to improve the code below by e.g. using a switch expression
* @param targetLinkUrl the target link URL | ||
* @return true if the target link URL references a competency, false otherwise | ||
*/ | ||
private boolean targetLinkHasCompetency(String targetLinkUrl) { |
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.
targetLinkHasCompetency(...)
, targetLinkHasLearningPath(...)
and targetLinkHasIris(...)
are almost identical. This is really bad code. I kindly ask you to unify the code already here to avoid such issues. You could e.g. have one method that returns an enum type whether competency, learningPath or iris is included.
return false; | ||
} | ||
|
||
log.info("Competency link detected: {}", targetLinkUrl); |
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.
do we need so many log.info
?
} | ||
|
||
Map<String, String> pathVariables = null; | ||
if (matcher.match(COURSE_PATH_PATTERN, targetLinkPath)) { |
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.
ugly if-else with lots of duplicated code. please refactor this
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.
Checklist
General
Server
Client
Motivation and Context
Currently, it is only possible for instructors to link Artemis exercises to Moodle learning activities. This PR enhances this functionality by adding Lectures, Competencies, Learning Activities and the Iris course dashboard to the linkable Artemis features.
To accomplish this, the UI for selecting the new content and the logic behind the LTI standard were adapted.
Description
This PR is a major addition to the existing LTI system.
Content selection table:
This PR reworks the content selection table, which instructors can use to link Artemis content to learning activities on Moodle.
The table now also features a selection for lectures, the competency page, the learning-activities page, as well as the course dashboard with a focus on the integrated Iris console.
New LTI features:
Server-side changes facilitate the new LTI features (Lectures, Competencies, Learning Paths and Iris). These changes are split into the linking process used by LTI to link the new content to a Moodle learning activity and a re-work of the authentication within the LTI services to be centered around courses instead of exercises.
Steps for Testing
Prerequisites:
Make sure you are logged in to Artemis with a Test User 16)
Navigate to Moodle and login with the same test user (Test User 16}, same PW as for the Artemis Test Server)
Go to My Courses and open the lti test course
Activate Edit mode in top right corner
Add a learning activity by clicking on the blue + in "Test Topic"

Select Linhuber TS3

Click on "Select content"

Select the LTI test course

Select the different content types you want to test and click "link" in the bottom right corner

If the content was selected successfully, scroll down and hit "Save and display"

(If you get an error after linking, this is due to server sync, just try again by pressing the back button in your browser)
You should be able to see the new content now

Testserver States
Note
These badges show the state of the test servers.
Green = Currently available, Red = Currently locked
Click on the badges to get to the test servers.
Review Progress
Code Review
Manual Tests
Test Coverage
Client
Server
�
Screenshots
New content selection table:

LTI Lectures:

LTI Competencies:

LTI Learning-paths:

LTI Iris dashboard:

Summary by CodeRabbit
Summary by CodeRabbit
New Features
User Interface Enhancements
Localization