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

General: Add LTI integration for Atlas, Iris, and Lectures #10338

Open
wants to merge 135 commits into
base: develop
Choose a base branch
from

Conversation

raffifasaro
Copy link
Contributor

@raffifasaro raffifasaro commented Feb 16, 2025

Checklist

General

Server

  • Important: I implemented the changes with a very good performance and prevented too many (unnecessary) and too complex database calls.
  • I strictly followed the principle of data economy for all database calls.
  • I strictly followed the server coding and design guidelines.
  • I added multiple integration tests (Spring) related to the features (with a high test coverage).
  • I added pre-authorization annotations according to the guidelines and checked the course groups for all new REST Calls (security).
  • I documented the Java code using JavaDoc style.

Client

  • Important: I implemented the changes with a very good performance, prevented too many (unnecessary) REST calls and made sure the UI is responsive, even with large data (e.g. using paging).
  • I strictly followed the principle of data economy for all client-server REST calls.
  • I strictly followed the client coding and design guidelines.
  • Following the theming guidelines, I specified colors only in the theming variable files and checked that the changes look consistent in both the light and the dark theme.
  • I added multiple integration tests (Jest) related to the features (with a high test coverage), while following the test guidelines.
  • I documented the TypeScript code using JSDoc style.
  • I added multiple screenshots/screencasts of my UI changes.
  • I translated all newly inserted strings into English and German.

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:

  • Access to Moodle
  • Testserver 3
  1. Make sure you are logged in to Artemis with a Test User 16)

  2. Navigate to Moodle and login with the same test user (Test User 16}, same PW as for the Artemis Test Server)

  3. Go to My Courses and open the lti test course

  4. Activate Edit mode in top right corner

  5. Add a learning activity by clicking on the blue + in "Test Topic"
    image

  6. Select Linhuber TS3
    image

  7. Click on "Select content"
    image

  8. Select the LTI test course
    image

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

  10. If the content was selected successfully, scroll down and hit "Save and display"
    image
    (If you get an error after linking, this is due to server sync, just try again by pressing the back button in your browser)

  11. You should be able to see the new content now
    image

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

  • Code Review 1
  • Code Review 2

Manual Tests

  • Test 1
  • Test 2

Test Coverage

Client

Class/File Line Coverage Confirmation (assert/expect)
course-management.service.ts 86.66%
lti13-deep-linking.component.ts 92.45%
lti13-exercise-launch.component.ts 85.33%

Server

Class/File Line Coverage Confirmation (assert/expect)
CourseResource.java 25%
LtiResourceLaunch.java 76%
DeepLinkingType.java 53%
Lti13Service.java 74%
LtiDeepLinkingService.java 46%
LtiResource.java 52%
PublicLtiResource.java 94%

Screenshots

New content selection table:
image

LTI Lectures:
image

LTI Competencies:
image

LTI Learning-paths:
image

LTI Iris dashboard:
image

Summary by CodeRabbit

Summary by CodeRabbit

  • New Features

    • Course retrieval now provides complete details including exercises, lectures, and competencies.
    • Deep linking has been expanded to support additional content types such as lectures, competencies, learning paths, and IRIS.
  • User Interface Enhancements

    • The deep linking interface has been redesigned with dropdown menus for a more organized and interactive content selection.
    • Improved validation and selection feedback ensure a smoother linking process.
  • Localization

    • New German and English translations enhance user guidance with updated labels and error messages.

sawys777
sawys777 previously approved these changes Feb 19, 2025
Copy link

@sawys777 sawys777 left a comment

Choose a reason for hiding this comment

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

Tested on TS3, everything works as expected
moodle

@raffifasaro raffifasaro changed the title Development: Enhance LTI features General: Enhance LTI features Feb 19, 2025
@raffifasaro raffifasaro changed the title General: Enhance LTI features 'General': Enhance LTI features Feb 19, 2025
@raffifasaro raffifasaro changed the title 'General': Enhance LTI features General: Enhance LTI features Feb 19, 2025
@MaximilianAnzinger MaximilianAnzinger changed the title General: Enhance LTI features General: Add LTI integration for Atlas, Iris, and Lectures Feb 19, 2025
Copy link
Collaborator

@MaximilianAnzinger MaximilianAnzinger left a 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.

Copy link

@coderabbitai coderabbitai bot left a 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 of 2. 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

📥 Commits

Reviewing files that changed from the base of the PR and between 1f2ebcb and a83ec9e.

⛔ 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

Comment on lines +15 to +20
for (DeepLinkingType deepLinkingType : values()) {
if (deepLinkingType.name().equalsIgnoreCase(type)) {
return deepLinkingType;
}
}
throw new IllegalArgumentException("Invalid deep linking type: " + type);
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
for (DeepLinkingType deepLinkingType : values()) {
if (deepLinkingType.name().equalsIgnoreCase(type)) {
return deepLinkingType;
}
}
throw new IllegalArgumentException("Invalid deep linking type: " + type);
return DeepLinkingType.valueOf(type.toUpperCase());

Copy link
Member

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) {
Copy link
Member

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) {
Copy link
Member

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) {
Copy link
Member

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) {
Copy link
Member

@krusche krusche Feb 19, 2025

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

Copy link
Member

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) {
Copy link
Member

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,
Copy link
Member

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) {
Copy link
Member

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);
Copy link
Member

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)) {
Copy link
Member

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

@helios-aet helios-aet bot temporarily deployed to artemis-test3.artemis.cit.tum.de February 20, 2025 05:59 Inactive
Copy link

@HawKhiem HawKhiem left a comment

Choose a reason for hiding this comment

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

Tested on TS3. Works as described
Screenshot 2025-02-20 071440
Screenshot 2025-02-20 071506

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
client Pull requests that update TypeScript code. (Added Automatically!) core Pull requests that affect the corresponding module database Pull requests that update the database. (Added Automatically!). Require a CRITICAL deployment. lti Pull requests that affect the corresponding module ready for review server Pull requests that update Java code. (Added Automatically!) tests
Projects
Status: Ready For Review
Status: In review
Development

Successfully merging this pull request may close these issues.

Link and view Competencies Rework of the LTI content selection table