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: Show navbar menu in every student view #8564

Merged
merged 21 commits into from
May 24, 2024

Conversation

rabeatwork
Copy link
Contributor

@rabeatwork rabeatwork commented May 10, 2024

Checklist

General

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.
  • 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 authorities to all new routes and checked the course groups for displaying navigation elements (links, buttons).
  • I added multiple screenshots/screencasts of my UI changes.
  • I translated all newly inserted strings into English and German.

Motivation and Context

The permanently displayed navbar menu allows the user to navigate from any page and quickly identify where they are currently located in Artemis. Additionally, it achieves a consistent design for the student view of Artemis.

Description

The Sidebar is now also visible in nested views.
Exam View and Communication View will be added in other PRs.

Steps for Testing

Prerequisites:

  • 1 Instructor
  • 1 Student
  • 1 Programming Exercise
  • 1 File Upload Exercise
  • 1 Modeling Exercise
  • 1 Quiz Exercise Exercise
  • 1 Text Exercise Exercise
  • Competencies Exercise
  1. Log in to Artemis
  2. Navigate to a Course
  3. Start a Programming Exercise (Online Editor)
  4. Verify that the sidebar is visible
  5. Start a File Upload Exercise
  6. Verify that the sidebar is visible
  7. Start a Modeling Exercise
  8. Verify that the sidebar is visible
  9. Start a Text Exercise
  10. Verify that the sidebar is visible
  11. Start a Quiz Exercise
  12. Verify that the sidebar is visible
  13. Practice a Quiz Exercise
  14. Verify that the sidebar is visible
  15. Go to Competencies and select a specific competency to see the details page
  16. Verify that the sidebar is visible

Testserver States

Note

These badges show the state of the test servers.
Green = Currently available, Red = Currently locked






Review Progress

Performance Review

  • I (as a reviewer) confirm that the client changes (in particular related to REST calls and UI responsiveness) are implemented with a very good performance
  • I (as a reviewer) confirm that the server changes (in particular related to database calls) are implemented with a very good performance

Code Review

  • Code Review 1
  • Code Review 2

Manual Tests

  • Test 1
  • Test 2

Screenshots

Screenshot 2024-05-10 at 09 49 55 Screenshot 2024-05-10 at 09 49 40

@rabeatwork rabeatwork requested a review from a team as a code owner May 10, 2024 08:01
@github-actions github-actions bot added the client Pull requests that update TypeScript code. (Added Automatically!) label May 10, 2024
Copy link

coderabbitai bot commented May 10, 2024

Walkthrough

The recent updates aim to enhance translation support, refine navigation logic, and improve UI consistency across various components. Key changes include adding translation keys, refactoring navigation methods, and updating CSS classes for better styling. Several TypeScript files were modified to remove obsolete subscriptions and streamline route handling. Additionally, new routes and translation entries were added, while some redundant imports and components were removed to optimize the codebase.

Changes

File(s) Change Summary
src/.../course-exercises.component.html,
src/.../course-tutorial-groups.component.html
Updated text content to use translation keys. Changed padding classes from px-3 to p-3.
src/.../course-exercises.component.ts,
src/.../course-lectures.component.ts,
src/.../course-tutorial-groups.component.ts
Removed paramSubscription, added navigateTo... and onSubRouteDeactivate methods, refactored navigation logic.
src/.../course-overview.component.ts Changed parseInt to Number for parsing courseId.
src/.../courses-routing.module.ts Added routes for various exercise types and updated competency routes.
src/.../courses.module.ts Removed HeaderCourseComponent from declarations and exports arrays.
src/.../course-exercise-details.module.ts Simplified route component nesting and conditional component loading based on isOrion.
src/.../exercise-buttons.module.ts,
src/.../shared-component.module.ts,
src/.../metis.module.ts,
src/.../sidebar.module.ts
Removed ArtemisCoursesRoutingModule from imports.
src/.../exercise-details-student-actions.component.html Refactored button elements to use a common template for quiz action buttons.
src/.../header-course.component.html Removed conditional rendering for manage buttons, added a static "student view" button.
src/.../exercise-scores-chart.component.scss Added margin-bottom: 10rem; to .ngx-charts-outer class.
src/.../sidebar-card-*.component.html Changed (click) event handler from emitStoreLastSelectedItem to emitStoreAndRefresh.
src/.../sidebar-card-*.component.ts Renamed methods and adjusted navigation logic. Added Location dependency.
src/.../scss/_artemis-variables.scss Added $enable-negative-margins: true; variable.
src/.../i18n/de/global.json Updated German translations for various exercise types.
src/.../i18n/en/global.json Removed specific exercise types from localization keys under "Entities".
src/.../i18n/en/student-dashboard.json Added new menu items and "Grading System" under the menu section.
src/.../course-competencies.component.spec.ts Nested a new MockActivatedRoute with additional parent parameters.
src/.../course-overview.component.spec.ts Removed HeaderCourseComponent import from mocked components.

Tip

New Features and Improvements

Review Settings

Introduced new personality profiles for code reviews. Users can now select between "Chill" and "Assertive" review tones to tailor feedback styles according to their preferences. The "Assertive" profile posts more comments and nitpicks the code more aggressively, while the "Chill" profile is more relaxed and posts fewer comments.

AST-based Instructions

CodeRabbit offers customizing reviews based on the Abstract Syntax Tree (AST) pattern matching. Read more about AST-based instructions in the documentation.

Community-driven AST-based Rules

We are kicking off a community-driven initiative to create and share AST-based rules. Users can now contribute their AST-based rules to detect security vulnerabilities, code smells, and anti-patterns. Please see the ast-grep-essentials repository for more information.

New Static Analysis Tools

We are continually expanding our support for static analysis tools. We have added support for biome, hadolint, and ast-grep. Update the settings in your .coderabbit.yaml file or head over to the settings page to enable or disable the tools you want to use.

Tone Settings

Users can now customize CodeRabbit to review code in the style of their favorite characters or personalities. Here are some of our favorite examples:

  • Mr. T: "You must talk like Mr. T in all your code reviews. I pity the fool who doesn't!"
  • Pirate: "Arr, matey! Ye must talk like a pirate in all yer code reviews. Yarrr!"
  • Snarky: "You must be snarky in all your code reviews. Snark, snark, snark!"

Revamped Settings Page

We have redesigned the settings page for a more intuitive layout, enabling users to find and adjust settings quickly. This change was long overdue; it not only improves the user experience but also allows our development team to add more settings in the future with ease. Going forward, the changes to .coderabbit.yaml will be reflected in the settings page, and vice versa.

Miscellaneous

  • Turn off free summarization: You can switch off free summarization of PRs opened by users not on a paid plan using the enable_free_tier setting.
  • Knowledge-base scope: You can now set the scope of the knowledge base to either the repository (local) or the organization (global) level using the knowledge_base setting. In addition, you can specify Jira project keys and Linear team keys to limit the knowledge base scope for those integrations.
  • High-level summary placement: You can now customize the location of the high-level summary in the PR description using the high_level_summary_placeholder setting (default @coderabbitai summary).
  • Revamped request changes workflow: You can now configure CodeRabbit to auto-approve or request changes on PRs based on the review feedback using the request_changes_workflow setting.

Recent Review Details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits Files that changed from the base of the PR and between d756fc6 and 9f6ed6f.
Files selected for processing (11)
  • src/main/webapp/app/shared/sidebar/sidebar-card-large/sidebar-card-large.component.html (1 hunks)
  • src/main/webapp/app/shared/sidebar/sidebar-card-medium/sidebar-card-medium.component.html (1 hunks)
  • src/main/webapp/app/shared/sidebar/sidebar-card-small/sidebar-card-small.component.html (1 hunks)
  • src/test/cypress/support/pageobjects/course/CourseOverviewPage.ts (1 hunks)
  • src/test/cypress/support/pageobjects/exercises/ExerciseResultPage.ts (1 hunks)
  • src/test/javascript/spec/component/shared/sidebar/sidebar-card-large.component.spec.ts (2 hunks)
  • src/test/javascript/spec/component/shared/sidebar/sidebar-card-medium.component.spec.ts (1 hunks)
  • src/test/javascript/spec/component/shared/sidebar/sidebar-card-small.component.spec.ts (2 hunks)
  • src/test/playwright/e2e/course/CourseExercise.spec.ts (1 hunks)
  • src/test/playwright/support/pageobjects/course/CourseOverviewPage.ts (1 hunks)
  • src/test/playwright/support/pageobjects/exercises/ExerciseResultPage.ts (1 hunks)
Files skipped from review as they are similar to previous changes (3)
  • src/main/webapp/app/shared/sidebar/sidebar-card-large/sidebar-card-large.component.html
  • src/main/webapp/app/shared/sidebar/sidebar-card-medium/sidebar-card-medium.component.html
  • src/main/webapp/app/shared/sidebar/sidebar-card-small/sidebar-card-small.component.html
Additional Context Used
Biome (31)
src/test/cypress/support/pageobjects/course/CourseOverviewPage.ts (5)

14-14: Template literals are preferred over string concatenation.


15-15: Template literals are preferred over string concatenation.


19-19: Template literals are preferred over string concatenation.


20-20: Template literals are preferred over string concatenation.


46-46: Template literals are preferred over string concatenation.

src/test/cypress/support/pageobjects/exercises/ExerciseResultPage.ts (2)

22-22: Template literals are preferred over string concatenation.


27-27: Template literals are preferred over string concatenation.

src/test/javascript/spec/component/shared/sidebar/sidebar-card-large.component.spec.ts (2)

24-34: Disallow duplicate setup and teardown hooks.


1-1: Some named imports are only used as types.

src/test/javascript/spec/component/shared/sidebar/sidebar-card-medium.component.spec.ts (5)

25-35: Disallow duplicate setup and teardown hooks.


42-42: The comma operator is disallowed.


49-49: The comma operator is disallowed.


56-56: The comma operator is disallowed.


1-1: Some named imports are only used as types.

src/test/javascript/spec/component/shared/sidebar/sidebar-card-small.component.spec.ts (2)

24-34: Disallow duplicate setup and teardown hooks.


1-1: Some named imports are only used as types.

src/test/playwright/e2e/course/CourseExercise.spec.ts (11)

30-30: Forbidden non-null assertion.


31-31: Forbidden non-null assertion.


32-32: Forbidden non-null assertion.


34-34: Forbidden non-null assertion.


35-35: Forbidden non-null assertion.


36-36: Forbidden non-null assertion.


40-40: Forbidden non-null assertion.


41-41: Forbidden non-null assertion.


42-42: Forbidden non-null assertion.


1-2: All these imports are only used as types.


3-4: All these imports are only used as types.

src/test/playwright/support/pageobjects/course/CourseOverviewPage.ts (3)

28-28: Template literals are preferred over string concatenation.


36-36: Template literals are preferred over string concatenation.


1-2: All these imports are only used as types.

src/test/playwright/support/pageobjects/exercises/ExerciseResultPage.ts (1)

1-1: All these imports are only used as types.

Path-based Instructions (3)
src/test/javascript/spec/component/shared/sidebar/sidebar-card-small.component.spec.ts (1)

Pattern src/test/javascript/spec/**/*.ts: jest: true; mock: NgMocks; bad_practices: avoid_full_module_import; perf_improvements: mock_irrelevant_deps; service_testing: mock_http_for_logic; no_schema: avoid_NO_ERRORS_SCHEMA; expectation_specificity: true; solutions: {boolean: toBeTrue/False, reference: toBe, existence: toBeNull/NotNull, undefined: toBeUndefined, class_obj: toContainEntries/toEqual, spy_calls: {not_called: not.toHaveBeenCalled, once: toHaveBeenCalledOnce, with_value: toHaveBeenCalledWith|toHaveBeenCalledExactlyOnceWith}}

src/test/javascript/spec/component/shared/sidebar/sidebar-card-large.component.spec.ts (1)

Pattern src/test/javascript/spec/**/*.ts: jest: true; mock: NgMocks; bad_practices: avoid_full_module_import; perf_improvements: mock_irrelevant_deps; service_testing: mock_http_for_logic; no_schema: avoid_NO_ERRORS_SCHEMA; expectation_specificity: true; solutions: {boolean: toBeTrue/False, reference: toBe, existence: toBeNull/NotNull, undefined: toBeUndefined, class_obj: toContainEntries/toEqual, spy_calls: {not_called: not.toHaveBeenCalled, once: toHaveBeenCalledOnce, with_value: toHaveBeenCalledWith|toHaveBeenCalledExactlyOnceWith}}

src/test/javascript/spec/component/shared/sidebar/sidebar-card-medium.component.spec.ts (1)

Pattern src/test/javascript/spec/**/*.ts: jest: true; mock: NgMocks; bad_practices: avoid_full_module_import; perf_improvements: mock_irrelevant_deps; service_testing: mock_http_for_logic; no_schema: avoid_NO_ERRORS_SCHEMA; expectation_specificity: true; solutions: {boolean: toBeTrue/False, reference: toBe, existence: toBeNull/NotNull, undefined: toBeUndefined, class_obj: toContainEntries/toEqual, spy_calls: {not_called: not.toHaveBeenCalled, once: toHaveBeenCalledOnce, with_value: toHaveBeenCalledWith|toHaveBeenCalledExactlyOnceWith}}

Additional comments not posted (8)
src/test/cypress/support/pageobjects/exercises/ExerciseResultPage.ts (1)

16-16: Consider using template literals for string concatenation to improve readability.

- cy.contains('.tab-bar-exercise-details', `${percentage}%`).should('be.visible');
+ cy.contains(`.tab-bar-exercise-details ${percentage}%`).should('be.visible');

Likely invalid or redundant comment.

src/test/cypress/support/pageobjects/course/CourseOverviewPage.ts (1)

32-32: Consider using template literals for string concatenation to improve readability.

- return cy.get('#test-sidebar-card-medium');
+ return cy.get(`#test-sidebar-card-medium`);

Likely invalid or redundant comment.

src/test/playwright/support/pageobjects/course/CourseOverviewPage.ts (2)

53-53: Consider using template literals for string concatenation to improve readability.

- return this.page.locator('#test-sidebar-card-medium');
+ return this.page.locator(`#test-sidebar-card-medium`);

Likely invalid or redundant comment.


45-45: Consider using template literals for string concatenation to improve readability.

- return this.page.locator('#test-sidebar-card-medium').getByText(exerciseName);
+ return this.page.locator(`#test-sidebar-card-medium ${exerciseName}`);

Likely invalid or redundant comment.

src/test/javascript/spec/component/shared/sidebar/sidebar-card-large.component.spec.ts (2)

41-47: Ensure that the new methods emitStoreAndRefresh and refreshChildComponent are tested adequately.

The test verifies that both methods are called as expected when the sidebar card is clicked. This aligns well with the changes made in the component.


52-52: Address the inconsistency in navigation logic.

The navigation logic in both click handlers is similar but uses different relative paths. Consider refactoring to use a common method or ensure consistency in the navigation strategy.

- expect(navigationArray).toBe('../testId');
+ expect(navigationArray).toBe('./testId');

Also applies to: 66-66

src/test/javascript/spec/component/shared/sidebar/sidebar-card-medium.component.spec.ts (2)

63-69: Ensure that the new methods emitStoreAndRefresh and refreshChildComponent are tested adequately.

The test verifies that both methods are called as expected when the sidebar card is clicked. This aligns well with the changes made in the component.


74-74: Address the inconsistency in navigation logic.

The navigation logic in both click handlers is similar but uses different relative paths. Consider refactoring to use a common method or ensure consistency in the navigation strategy.

- expect(navigationArray).toBe('../testId');
+ expect(navigationArray).toBe('./testId');

Also applies to: 88-88


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

Share
Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai generate interesting stats about this repository and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (invoked as PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger a review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai help to get help.

Additionally, you can add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Configration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

coderabbitai[bot]
coderabbitai bot previously approved these changes May 10, 2024
coderabbitai[bot]
coderabbitai bot previously approved these changes May 13, 2024
coderabbitai[bot]
coderabbitai bot previously approved these changes May 13, 2024
edkaya
edkaya previously approved these changes May 14, 2024
Copy link
Contributor

@edkaya edkaya left a comment

Choose a reason for hiding this comment

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

Code looks good to me

@rabeatwork rabeatwork dismissed stale reviews from edkaya and coderabbitai via e052cb7 May 14, 2024 13:49
@rabeatwork rabeatwork force-pushed the chore/show-navbar-in-every-student-view branch from bd1d20d to e052cb7 Compare May 14, 2024 13:49
coderabbitai[bot]
coderabbitai bot previously requested changes May 14, 2024
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: 3

Copy link

⚠️ Unable to deploy to test servers ⚠️

The docker build needs to run through before deploying.

@github-actions github-actions bot added the deployment-error Added by deployment workflows if an error occured label May 17, 2024
@rabeatwork rabeatwork removed the deployment-error Added by deployment workflows if an error occured label May 17, 2024
@rabeatwork rabeatwork force-pushed the chore/show-navbar-in-every-student-view branch 2 times, most recently from c9ecee1 to 6edc760 Compare May 21, 2024 18:46
coderabbitai[bot]
coderabbitai bot previously requested changes May 24, 2024
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: 15

Outside diff range and nitpick comments (38)
src/test/javascript/spec/component/shared/sidebar/sidebar-card-small.component.spec.ts (2)

Line range hint 24-34: Avoid duplicate setup and teardown hooks.

Consider consolidating the repeated setup logic in beforeEach into a single block to improve code maintainability and reduce redundancy.


Line range hint 1-1: Optimize imports.

Some imports are only used as types and should be imported using import type { Type } from 'module'; to clarify their usage and potentially improve build optimization.

src/test/javascript/spec/component/shared/sidebar/sidebar-card-large.component.spec.ts (2)

Line range hint 24-34: Avoid duplicate setup and teardown hooks.

Consider consolidating the repeated setup logic in beforeEach into a single block to improve code maintainability and reduce redundancy.


Line range hint 1-1: Optimize imports.

Some imports are only used as types and should be imported using import type { Type } from 'module'; to clarify their usage and potentially improve build optimization.

src/main/webapp/app/app.module.ts (1)

Line range hint 26-27: Optimize imports.

Some imports are only used as types and should be imported using import type { Type } from 'module'; to clarify their usage and potentially improve build optimization.

src/main/webapp/app/overview/course-competencies/course-competencies.component.ts (2)

Line range hint 68-68: Use strict equality for comparisons.

Always use strict equality (===) for comparisons to avoid unexpected type coercion.

- return competency.userProgress.first()!.progress == 100 && competency.userProgress.first()!.confidence! >= competency.masteryThreshold!;
+ return competency.userProgress.first()!.progress === 100 && competency.userProgress.first()!.confidence! >= competency.masteryThreshold!;

Line range hint 85-86: Avoid non-null assertions.

Using non-null assertions (!) can lead to runtime errors if the assumptions about data presence are incorrect. Consider adding checks or using optional chaining.

src/test/javascript/spec/component/shared/sidebar/sidebar-card-medium.component.spec.ts (2)

Line range hint 25-35: Avoid duplicate setup and teardown hooks.

Consider consolidating the repeated setup logic in beforeEach into a single block to improve code maintainability and reduce redundancy.


Line range hint 1-1: Optimize imports.

Some imports are only used as types and should be imported using import type { Type } from 'module'; to clarify their usage and potentially improve build optimization.

src/test/javascript/spec/component/course/header-course.component.spec.ts (4)

Line range hint 40-40: Simplify the computed expression.

Consider using a direct assignment or a simpler method to achieve the same result without concatenation.


Line range hint 49-49: Use template literals for string concatenation.

Replace string concatenation with template literals for better readability and performance:

- 'a'.repeat(564) + '…'
+ `a`.repeat(564) + '…'

Also applies to: 59-60, 73-75


Line range hint 70-70: Simplify the computed expression.

Consider using a direct assignment or a simpler method to achieve the same result without concatenation.


Line range hint 1-1: Optimize import statements.

Some imports are only used as types and should be imported using import type. This can help with tree shaking and potentially reduce bundle sizes:

- import { ComponentFixture, TestBed } from '@angular/core/testing';
+ import type { ComponentFixture, TestBed } from '@angular/core/testing';

Also applies to: 3-4

src/main/webapp/app/overview/course-exercises/course-exercises.component.ts (2)

Line range hint 34-34: Remove unnecessary type annotations.

Type annotations on properties initialized with values are inferred by TypeScript and can be omitted for cleaner code:

- sidebarData: SidebarData;
- sidebarExercises: SidebarCardElement[] = [];
+ sidebarData;
+ sidebarExercises = [];

Also applies to: 38-38


Line range hint 90-90: Use template literals for string concatenation.

Replace string concatenation with template literals for better readability and performance:

- 'sidebar.lastSelectedItem.exercise.byCourse.' + this.courseId
+ `sidebar.lastSelectedItem.exercise.byCourse.${this.courseId}`
src/main/webapp/app/overview/exercise-details/course-exercise-details.module.ts (1)

Line range hint 2-3: Optimize import statements.

Some imports are only used as types and should be imported using import type. This can help with tree shaking and potentially reduce bundle sizes:

- import { RouterModule, Routes } from '@angular/router';
+ import type { RouterModule, Routes } from '@angular/router';
src/main/webapp/app/app-routing.module.ts (1)

Line range hint 1-2: Optimize import statements.

Some imports are only used as types and should be imported using import type. This can help with tree shaking and potentially reduce bundle sizes:

- import { NgModule } from '@angular/core';
- import { RouterModule, Routes } from '@angular/router';
+ import type { NgModule } from '@angular/core';
+ import type { RouterModule, Routes } from '@angular/router';

Also applies to: 4-5

src/main/webapp/app/overview/course-competencies/course-competencies-details.component.ts (2)

Line range hint 58-58: Avoid using non-null assertions.

Using non-null assertions can lead to runtime errors if the values are actually null. Consider checking for null or undefined before usage or using optional chaining.

Also applies to: 60-60, 61-61, 88-88, 119-119, 123-123, 125-125


Line range hint 81-81: Avoid assignments within expressions.

Assignments within expressions can lead to less readable and potentially error-prone code. Consider separating the assignment from the expression:

- setTimeout(() => (this.showFireworks = true), 1000);
+ setTimeout(() => {
+   this.showFireworks = true;
+ }, 1000);

Also applies to: 82-82

src/test/javascript/spec/component/competencies/course-competencies.component.spec.ts (2)

Line range hint 22-22: Specify explicit types instead of any.

Using any can lead to less type-safe code. Specify explicit types for better type checking and code clarity:

- parent: any;
- params: any;
+ parent: ActivatedRoute | null;
+ params: Observable<Params>;

Also applies to: 23-23, 25-25


Line range hint 1-1: Optimize import statements.

Some imports are only used as types and should be imported using import type. This can help with tree shaking and potentially reduce bundle sizes:

- import { ComponentFixture, TestBed } from '@angular/core/testing';
- import { Competency, CompetencyProgress } from 'app/entities/competency.model';
+ import type { ComponentFixture, TestBed } from '@angular/core/testing';
+ import type { Competency, CompetencyProgress } from 'app/entities/competency.model';

Also applies to: 5-6

src/test/javascript/spec/component/course/course-overview.component.spec.ts (6)

Line range hint 116-116: Specify explicit types instead of using any.

- const course = {
-     id: 1,
-     courseInformationSharingConfiguration: CourseInformationSharingConfiguration.COMMUNICATION_AND_MESSAGING,
- } as Course;
+ const course: Course = {
+     id: 1,
+     courseInformationSharingConfiguration: CourseInformationSharingConfiguration.COMMUNICATION_AND_MESSAGING,
+ };

Also applies to: 118-118


Line range hint 122-122: Avoid using non-null assertions.

- this.controlConfiguration.subject!.next(this.controls);
+ if (this.controlConfiguration.subject) {
+     this.controlConfiguration.subject.next(this.controls);
+ }

Line range hint 280-285: Prefer for...of loop for better readability and performance in modern JavaScript.

- tabs.forEach((tab) => {
-     route.snapshot.firstChild!.routeConfig!.path = tab;
-     component.onSubRouteActivate({ controlConfiguration: undefined });
-     expect(metisConversationServiceStub).toHaveBeenCalledOnce();
- });
+ for (const tab of tabs) {
+     route.snapshot.firstChild!.routeConfig!.path = tab;
+     component.onSubRouteActivate({ controlConfiguration: undefined });
+     expect(metisConversationServiceStub).toHaveBeenCalledOnce();
+ }

Line range hint 301-306: Prefer for...of loop for iterating over arrays.

- tabs.forEach((tab) => {
-     route.snapshot.firstChild!.routeConfig!.path = tab;
-     component.onSubRouteActivate({ controlConfiguration: undefined });
-     expect(spy).toHaveBeenCalledOnce();
- });
+ for (const tab of tabs) {
+     route.snapshot.firstChild!.routeConfig!.path = tab;
+     component.onSubRouteActivate({ controlConfiguration: undefined });
+     expect(spy).toHaveBeenCalledOnce();
+ }

Line range hint 316-319: Use for...of loop instead of forEach for consistency and performance.

- tabs.forEach((tab) => {
-     route.snapshot.firstChild!.routeConfig!.path = tab;
-     component.onSubRouteActivate({ controlConfiguration: undefined });
- });
+ for (const tab of tabs) {
+     route.snapshot.firstChild!.routeConfig!.path = tab;
+     component.onSubRouteActivate({ controlConfiguration: undefined });
+ }

Line range hint 3-4: Optimize imports by removing unused ones and ensuring that imports used only as types are imported correctly.

- import { Observable, Subject, of, throwError } from 'rxjs';
+ import { Observable, Subject, of } from 'rxjs';
- import { ComponentFixture, TestBed, fakeAsync, tick } from '@angular/core/testing';
+ import { ComponentFixture, TestBed, fakeAsync } from '@angular/core/testing';
- import { HttpHeaders, HttpResponse } from '@angular/common/http';
+ import { HttpResponse } from '@angular/common/http';
- import { ActivatedRoute, Params, Router } from '@angular/router';
+ import { ActivatedRoute, Router } from '@angular/router';
- import { Course, CourseInformationSharingConfiguration } from 'app/entities/course.model';
+ import { Course } from 'app/entities/course.model';
- import { Exercise } from 'app/entities/exercise.model';
+ import { Exercise, QuizExercise } from 'app/entities/exercise.model';
- import { Exam } from 'app/entities/exam.model';
+ import { Exam, CourseInformationSharingConfiguration } from 'app/entities/exam.model';
- import { TutorialGroup } from 'app/entities/tutorial-group/tutorial-group.model';
+ import { TutorialGroup, TutorialGroupsConfiguration } from 'app/entities/tutorial-group/tutorial-group.model';

Also applies to: 7-8, 8-9, 18-19, 19-20, 25-26

src/test/javascript/spec/component/shared/navbar.component.spec.ts (4)

Line range hint 137-137: Use template literals for string concatenation.

- .mockImplementation((type) => of('Test ' + type.substring(0, 1) + type.substring(1).toLowerCase()));
+ .mockImplementation((type) => of(`Test ${type.charAt(0)}${type.slice(1).toLowerCase()}`));

Line range hint 261-261: Specify a more precise type instead of any.

Please replace the any type with a more specific type to enhance type safety and code maintainability.


Line range hint 676-676: Simplify the computed expression.

- window['innerWidth'] = width;
+ window.innerWidth = width;

Line range hint 1-1: Optimize import statements by using type-only imports where applicable.

- import { HttpResponse } from '@angular/common/http';
+ import type { HttpResponse } from '@angular/common/http';

- import { ProfileInfo } from 'app/shared/layouts/profiles/profile-info.model';
+ import type { ProfileInfo } from 'app/shared/layouts/profiles/profile-info.model';

- import { Exercise, ExerciseType } from 'app/entities/exercise.model';
+ import type { Exercise, ExerciseType } from 'app/entities/exercise.model';

- import { Authority } from 'app/shared/constants/authority.constants';
- import { User } from 'app/core/user/user.model';
+ import type { Authority } from 'app/shared/constants/authority.constants';
+ import type { User } from 'app/core/user/user.model';

This change ensures that these imports are used for type checking only and not included in the JavaScript output, optimizing the bundle size.

Also applies to: 6-7, 23-24, 30-31, 33-34

src/main/webapp/app/shared/layouts/navbar/navbar.component.ts (7)

Line range hint 95-95: Consider removing the explicit type annotation where TypeScript can infer it.

- private standardizedCompetencySubscription: Subscription;
+ private standardizedCompetencySubscription;

Line range hint 405-405: Use for...of instead of forEach for better readability and performance in modern JavaScript.

- this.breadcrumbSubscriptions?.forEach((subscription) => subscription.unsubscribe());
+ for (const subscription of this.breadcrumbSubscriptions) {
+     subscription.unsubscribe();
+ }

Line range hint 433-433: Use template literals for string concatenation to improve readability.

- currentPath += segment + '/';
+ currentPath += `${segment}/`;

Line range hint 547-554: These case clauses are redundant and can be removed to clean up the code.

case 'mc-question-statistic':
case 'dnd-question-statistic':
case 'sa-question-statistic':
case 'test-exam':
case 'participate':
case 'overview':
-    break;

Line range hint 568-568: Use strict equality === for comparisons to avoid unexpected type coercion.

- this.isBuildAgentDetails = currentPath.startsWith('/admin/build-agents/') && segment == 'details';
+ this.isBuildAgentDetails = currentPath.startsWith('/admin/build-agents/') && segment === 'details';

Line range hint 582-582: Simplify the computed expression without using a string literal.

- this.agentName = params['agentName'];
+ this.agentName = params.agentName;

Line range hint 626-647: These else clauses are unnecessary as the previous branches break early. Simplify the control flow by removing them.

if (this.lastRouteUrlSegment === 'user-management') {
    this.addBreadcrumb(currentPath, segment, false);
- } else if (this.lastRouteUrlSegment === 'example-submissions') {
+ } else if (this.lastRouteUrlSegment === 'example-submissions') {
    this.addTranslationAsCrumb(currentPath, 'example-submission-editor');
- } else if (this.lastRouteUrlSegment === 'grading') {
+ } else if (this.lastRouteUrlSegment === 'grading') {
    this.addTranslationAsCrumb(currentPath, 'grading');
- } else if (this.lastRouteUrlSegment === 'code-editor' && segment === 'new') {
+ } else if (this.lastRouteUrlSegment === 'code-editor' && segment === 'new') {
    // This route is bogus and needs to be replaced in the future, display no crumb
- } else if (this.lastRouteUrlSegment?.endsWith('-exercises') && segment === 'import') {
+ } else if (this.lastRouteUrlSegment?.endsWith('-exercises') && segment === 'import') {
    // This route is bogus and needs to be replaced in the future, display no crumb
- } else if (this.lastRouteUrlSegment === 'exercise-groups') {
+ } else if (this.lastRouteUrlSegment === 'exercise-groups') {
    // Don't display '<type>-exercises' because it has no associated route
- } else if (this.lastRouteUrlSegment === 'exams' && segment === 'import') {
+ } else if (this.lastRouteUrlSegment === 'exams' && segment === 'import') {
    // This route is only used internally when opening the exam import modal and therefore shouldn't be displayed.
    // When opening the exam-update.component, the id of the to be imported exam is appended (-> case `import`).
}

@@ -468,7 +468,7 @@ export class NavbarComponent implements OnInit, OnDestroy {
default:
const exercisesMatcher = this.lastRouteUrlSegment?.match(/.+-exercises/);
Copy link

Choose a reason for hiding this comment

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

Wrap the variable declaration in a block to restrict its scope to the switch clause, preventing potential bugs.

case 'exercises':
+ {
    const exercisesMatcher = this.lastRouteUrlSegment?.match(/.+-exercises/);
    if (exercisesMatcher) {
        this.addResolvedTitleAsCrumb(EntityType.EXERCISE, [Number(segment)], currentPath.replace(`exercises/${exercisesMatcher[0]}`, 'exercises'), 'exercises');
        return;
    }
+ }

Also applies to: 506-506, 617-617


Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
const exercisesMatcher = this.lastRouteUrlSegment?.match(/.+-exercises/);
case 'exercises':
{
const exercisesMatcher = this.lastRouteUrlSegment?.match(/.+-exercises/);
if (exercisesMatcher) {
this.addResolvedTitleAsCrumb(EntityType.EXERCISE, [Number(segment)], currentPath.replace(`exercises/${exercisesMatcher[0]}`, 'exercises'), 'exercises');
return;
}
}

this.itemSelected
? this.router.navigate(['../' + this.sidebarItem.id], { relativeTo: this.route })
: this.router.navigate(['./' + this.sidebarItem.id], { relativeTo: this.route });
? this.router.navigate(['./' + this.sidebarItem?.id], { relativeTo: this.route })
Copy link

Choose a reason for hiding this comment

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

Consider using template literals for better readability and consistency in string operations.

- this.router.navigate(['./' + this.sidebarItem?.id], { relativeTo: this.route })
+ this.router.navigate([`./${this.sidebarItem?.id}`], { relativeTo: this.route })

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
? this.router.navigate(['./' + this.sidebarItem?.id], { relativeTo: this.route })
? this.router.navigate([`./${this.sidebarItem?.id}`], { relativeTo: this.route })

this.itemSelected
? this.router.navigate(['../' + this.sidebarItem.id], { relativeTo: this.route })
: this.router.navigate(['./' + this.sidebarItem.id], { relativeTo: this.route });
? this.router.navigate(['./' + this.sidebarItem?.id], { relativeTo: this.route })
Copy link

Choose a reason for hiding this comment

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

Use template literals for string operations to maintain consistency and improve readability.

- this.router.navigate(['./' + this.sidebarItem?.id], { relativeTo: this.route })
+ this.router.navigate([`./${this.sidebarItem?.id}`], { relativeTo: this.route })

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
? this.router.navigate(['./' + this.sidebarItem?.id], { relativeTo: this.route })
? this.router.navigate([`./${this.sidebarItem?.id}`], { relativeTo: this.route })

const manageButton = fixture.nativeElement.querySelector('#manage-button');
expect(manageButton).toBeTruthy();
});

it('should not display manage button but go to student view button in course management', () => {
component.course = courseWithShortDescription;
component.course!.isAtLeastTutor = true;
Copy link

Choose a reason for hiding this comment

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

Avoid using non-null assertions.

Using non-null assertions can lead to runtime errors if the values are actually null. Consider checking for null or undefined before usage or using optional chaining.

Also applies to: 104-104

this.itemSelected
? this.router.navigate(['../' + this.sidebarItem.id], { relativeTo: this.route })
: this.router.navigate(['./' + this.sidebarItem.id], { relativeTo: this.route });
? this.router.navigate(['./' + this.sidebarItem?.id], { relativeTo: this.route })
Copy link

Choose a reason for hiding this comment

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

Adopt template literals for string operations to enhance readability and maintain coding standards.

- this.router.navigate(['./' + this.sidebarItem?.id], { relativeTo: this.route })
+ this.router.navigate([`./${this.sidebarItem?.id}`], { relativeTo: this.route })

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
? this.router.navigate(['./' + this.sidebarItem?.id], { relativeTo: this.route })
? this.router.navigate([`./${this.sidebarItem?.id}`], { relativeTo: this.route })

});

it('should navigate to the item URL on click', async () => {
const mockFn = jest.fn();
component.emitStoreLastSelectedItem = mockFn;
component.emitStoreAndRefresh = mockFn;
Copy link

Choose a reason for hiding this comment

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

Consistency in navigation logic.

The navigation logic in both click handlers is similar but uses different relative paths. Consider refactoring to use a common method or ensure consistency in the navigation strategy.

- expect(navigationArray).toBe('../testId');
+ expect(navigationArray).toBe('./testId');

Also applies to: 66-66

Committable suggestion was skipped due low confidence.

@@ -43,7 +42,7 @@ export class CourseLecturesComponent implements OnInit, OnDestroy {
ngOnInit() {
this.isCollapsed = this.courseOverviewService.getSidebarCollapseStateFromStorage('lecture');
this.parentParamSubscription = this.route.parent!.params.subscribe((params) => {
Copy link

Choose a reason for hiding this comment

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

Avoid non-null assertions.

Using non-null assertions (!) can lead to runtime errors if the assumptions about data presence are incorrect. Consider adding checks or using optional chaining.

@@ -96,9 +97,15 @@
return sessionStorage.getItem('sidebar.lastSelectedItem.lecture.byCourse.' + this.courseId);
Copy link

Choose a reason for hiding this comment

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

Prefer template literals over string concatenation.

Use template literals for better readability and performance.

- return sessionStorage.getItem('sidebar.lastSelectedItem.lecture.byCourse.' + this.courseId);
+ return sessionStorage.getItem(`sidebar.lastSelectedItem.lecture.byCourse.${this.courseId}`);

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
return sessionStorage.getItem('sidebar.lastSelectedItem.lecture.byCourse.' + this.courseId);
return sessionStorage.getItem(`sidebar.lastSelectedItem.lecture.byCourse.${this.courseId}`);

} else if (!lectureId && upcomingLecture) {
this.router.navigate([upcomingLecture.id], { relativeTo: this.route, replaceUrl: true });
} else {
this.lectureSelected = lectureId ? true : false;
Copy link

Choose a reason for hiding this comment

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

Simplify conditional expressions.

Use direct boolean evaluation instead of ternary operations for boolean values.

- this.lectureSelected = lectureId ? true : false;
+ this.lectureSelected = !!lectureId;

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
this.lectureSelected = lectureId ? true : false;
this.lectureSelected = !!lectureId;

});

it('should navigate to the item URL on click', async () => {
const mockFn = jest.fn();
component.emitStoreLastSelectedItem = mockFn;
component.emitStoreAndRefresh = mockFn;
Copy link

Choose a reason for hiding this comment

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

Consistency in navigation logic.

The navigation logic in both click handlers is similar but uses different relative paths. Consider refactoring to use a common method or ensure consistency in the navigation strategy.

- expect(navigationArray).toBe('../testId');
+ expect(navigationArray).toBe('./testId');

Also applies to: 88-88

Committable suggestion was skipped due low confidence.

Copy link
Contributor

@florian-glombik florian-glombik left a comment

Choose a reason for hiding this comment

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

Re-approve code

egekurt123
egekurt123 previously approved these changes May 24, 2024
Copy link
Contributor

@egekurt123 egekurt123 left a comment

Choose a reason for hiding this comment

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

Reapprove

edkaya
edkaya previously approved these changes May 24, 2024
Copy link
Contributor

@edkaya edkaya left a comment

Choose a reason for hiding this comment

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

Reapprove

pzdr7
pzdr7 previously approved these changes May 24, 2024
Copy link
Contributor

@pzdr7 pzdr7 left a comment

Choose a reason for hiding this comment

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

LGTM

@krusche krusche added this to the 7.1.0 milestone May 24, 2024
@github-actions github-actions bot added the cypress Pull requests that update cypress tests. (Added Automatically!) label May 24, 2024
coderabbitai[bot]
coderabbitai bot previously requested changes May 24, 2024
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: 5

Outside diff range and nitpick comments (2)
src/test/javascript/spec/component/shared/sidebar/sidebar-card-large.component.spec.ts (1)

Line range hint 24-34: Consider consolidating duplicate setup and teardown hooks.

To improve the maintainability and reduce redundancy, you might want to consolidate the repeated setup logic in beforeEach into a single block or a helper function.

src/test/javascript/spec/component/shared/sidebar/sidebar-card-medium.component.spec.ts (1)

Line range hint 25-35: Consider consolidating duplicate setup and teardown hooks.

To improve the maintainability and reduce redundancy, you might want to consolidate the repeated setup logic in beforeEach into a single block or a helper function.

@@ -40,55 +40,55 @@ describe('SidebarCardMediumComponent', () => {

it('should have success border class for easy difficulty', () => {
(component.sidebarItem.difficulty = DifficultyLevel.EASY), fixture.detectChanges();
const element: HTMLElement = fixture.nativeElement.querySelector('#test-sidebar-card');
const element: HTMLElement = fixture.nativeElement.querySelector('#test-sidebar-card-medium');
Copy link

Choose a reason for hiding this comment

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

Correct the misuse of the comma operator in test descriptions.

The comma operator is used incorrectly in the test setup, which might lead to unexpected behavior. Consider using semicolons or separate statements instead.

- (component.sidebarItem.difficulty = DifficultyLevel.EASY), fixture.detectChanges();
+ component.sidebarItem.difficulty = DifficultyLevel.EASY;
+ fixture.detectChanges();

Also applies to: 50-50, 57-57


Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
const element: HTMLElement = fixture.nativeElement.querySelector('#test-sidebar-card-medium');
const element: HTMLElement = fixture.nativeElement.querySelector('#test-sidebar-card-medium');
component.sidebarItem.difficulty = DifficultyLevel.EASY;
fixture.detectChanges();

@@ -21,15 +21,15 @@ export class CourseOverviewPage {
}

getExercise(exerciseTitle: string) {
return cy.contains('#test-sidebar-card', exerciseTitle);
return cy.contains('#test-sidebar-card-medium', exerciseTitle);
Copy link

Choose a reason for hiding this comment

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

Consider using template literals for string concatenation to improve readability.

- return cy.contains('#test-sidebar-card-medium', exerciseTitle);
+ return cy.contains(`#test-sidebar-card-medium ${exerciseTitle}`);

Committable suggestion was skipped due low confidence.

@@ -26,7 +26,7 @@ export class ExerciseResultPage {
}

async shouldShowScore(percentage: number) {
await Commands.reloadUntilFound(this.page, this.page.locator('#submission-result-graded'));
await Commands.reloadUntilFound(this.page, this.page.locator('jhi-course-exercise-details #submission-result-graded'));
Copy link

Choose a reason for hiding this comment

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

Consider using template literals for string concatenation to improve readability.

- await expect(this.page.locator('.tab-bar-exercise-details').getByText(`${percentage}%`)).toBeVisible();
+ await expect(this.page.locator(`.tab-bar-exercise-details ${percentage}%`)).toBeVisible();

Committable suggestion was skipped due low confidence.

await expect(courseOverview.getExercise(exercise2.title!)).toBeVisible();
await expect(courseOverview.getExercise(exercise3.title!)).toBeVisible();
// All quiz exercises should be hidden initially, as the default accordion status is collapsed when there is no due date.
await expect(courseOverview.getExercise(exercise1.title!)).toBeHidden();
Copy link

Choose a reason for hiding this comment

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

Consider avoiding non-null assertions to prevent potential runtime errors.

- await expect(courseOverview.getExercise(exercise1.title!)).toBeHidden();
- await expect(courseOverview.getExercise(exercise2.title!)).toBeHidden();
- await expect(courseOverview.getExercise(exercise3.title!)).toBeHidden();
- await expect(courseOverview.getExercise(exercise1.title!)).toBeVisible();
- await expect(courseOverview.getExercise(exercise2.title!)).toBeVisible();
- await expect(courseOverview.getExercise(exercise3.title!)).toBeHidden();

Also applies to: 31-31, 32-32, 34-34, 35-35, 36-36, 40-40, 41-41, 42-42

Committable suggestion was skipped due low confidence.

});

it('should navigate to the item URL on click', async () => {
const mockFn = jest.fn();
component.emitStoreLastSelectedItem = mockFn;
component.emitStoreAndRefresh = mockFn;
Copy link

Choose a reason for hiding this comment

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

Consistency in navigation logic.

The navigation logic in both click handlers is similar but uses different relative paths. Consider refactoring to use a common method or ensure consistency in the navigation strategy.

- expect(navigationArray).toBe('../testId');
+ expect(navigationArray).toBe('./testId');

Also applies to: 65-65


Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
component.emitStoreAndRefresh = mockFn;
component.emitStoreAndRefresh = mockFn;
expect(navigationArray).toBe('./testId');

@florian-glombik florian-glombik temporarily deployed to artemis-test1.artemis.cit.tum.de May 24, 2024 17:35 — with GitHub Actions Inactive
@krusche krusche merged commit 99bcef5 into develop May 24, 2024
35 of 38 checks passed
@krusche krusche deleted the chore/show-navbar-in-every-student-view branch May 24, 2024 17:58
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!) cypress Pull requests that update cypress tests. (Added Automatically!) tests
Projects
Status: Merged
Development

Successfully merging this pull request may close these issues.

None yet

7 participants