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

Development: Improve performance of programming exercise details view #9785

Merged

Conversation

florian-glombik
Copy link
Contributor

@florian-glombik florian-glombik commented Nov 14, 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 (e.g. using paging).
  • I strictly followed the client coding and design guidelines.
  • I added multiple integration tests (Jest) related to the features (with a high test coverage), while following the test guidelines.
  • I added multiple screenshots/screencasts of my UI changes.

Motivation and Context

The programming exercise details page sent unnecessary requests to the server, which was caused by poor coordination of subscriptions in programming-exercise-detail.component.ts, leading to multiple instantiations and renderings of subcomponents.
Self-contained components (e.g. programming-exercise-instructions.component.ts and programming-exercise-repository-and-build-plan-details.component.ts), therefore, sent multiple requests to the server to retrieve unchanged information (initialized up to 3 times), in other words, unnecessary requests.

Description

  • Introduced signals and adhered to client guidelines in detail-overview-list.component.ts
  • Made sure getExerciseDetails() is only called once after all subscriptions are finished onInit, preventing unnecessary rendering steps (this is ensured by using switchMap()
  • Refactored loadGitDiffReport() to be able to use processGitDiffReport() it in switchMap()
  • Refactored loadGitDiffReport() to reduce code duplication

Steps for Testing

Prerequisites:

  • 1 Instructor
  1. Create a programming exercise
  2. Open the dev tools and the network tab of your preferred browser (filter for Fetch/XHR)
  3. Go to the details view of the programming exercise
  4. Verify that no requests are sent twice on the initial loading to he page (e.g. test-cases, repository-checkout-directories - will be send out twice right now and will not be addressed further in this PR (still 2 requests less than before), details - exception: it is okay for time to be there multiple times)
  5. Verify that the details view works as expected (e.g. try out the diff view etc.)

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

Performance Review

Code Review

  • Code Review 1
  • Code Review 2

Manual Tests

  • Test 1
  • Test 2

Test Coverage

Screenshots

Duplicated requests before the fix ⚡

image

With the fix ✅

image

Summary by CodeRabbit

Release Notes

  • New Features

    • Enhanced detail rendering logic for various detail types in the overview list.
    • Improved handling of Git diff reports for programming exercises, including centralized processing logic.
  • Bug Fixes

    • Enhanced error handling during data retrieval, ensuring better user feedback.
  • Tests

    • Updated test cases for DetailOverviewListComponent and ProgrammingExerciseDetailComponent to align with new input handling and participation changes.
  • Refactor

    • Streamlined dependency injection and component initialization for better maintainability.

@florian-glombik florian-glombik self-assigned this Nov 14, 2024
@florian-glombik florian-glombik requested a review from a team as a code owner November 14, 2024 23:58
@florian-glombik florian-glombik added this to the 7.7.2 milestone Nov 14, 2024
@github-actions github-actions bot added the client Pull requests that update TypeScript code. (Added Automatically!) label Nov 14, 2024
Copy link

coderabbitai bot commented Nov 15, 2024

Walkthrough

The pull request introduces modifications to the DetailOverviewListComponent and ProgrammingExerciseDetailComponent. Key changes include updating the syntax for iterating over sections in the HTML template, refactoring dependency injection to use Angular's inject function, and enhancing asynchronous data handling with RxJS in the programming exercise component. The test suites for both components have been adjusted to align with these changes, particularly in how inputs are set and how tests are structured. The overall structure and functionality of the components remain consistent.

Changes

File Change Summary
src/main/webapp/app/detail-overview-list/detail-overview-list.component.html Updated iteration syntax for sections from @for (section of sections; track section) to @for (section of sections(); track section).
src/main/webapp/app/detail-overview-list/detail-overview-list.component.ts Refactored dependency injection using inject, updated sections input handling, and removed unused imports.
src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts Refactored async data handling with RxJS, added processGitDiffReport method, and improved error handling.
src/test/javascript/spec/component/detail-overview-list.component.spec.ts Updated test input handling for sections and adjusted tests to align with new input setting methods.
src/test/javascript/spec/component/programming-exercise/programming-exercise-detail.component.spec.ts Updated test suite description, added tests for participation changes, and refined testing strategy.

Possibly related PRs

Suggested labels

performance, programming

Suggested reviewers

  • SimonEntholzer
  • JohannesStoehr
  • BBesrour
  • pzdr7
  • krusche
  • HawKhiem

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>, please review it.
    • 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 gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @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.
    • @coderabbitai help me debug CodeRabbit configuration file.

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 using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai or @coderabbitai title anywhere in the PR title to generate the title automatically.

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.

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

🧹 Outside diff range and nitpick comments (4)
src/main/webapp/app/detail-overview-list/detail-overview-list.component.ts (1)

53-53: LGTM! Consider documenting the required input.

The changes follow modern Angular patterns. Consider adding JSDoc to document the required sections input for better maintainability.

+/** The sections to be displayed in the overview list. */
 sections = input.required<DetailOverviewSection[]>();

Also applies to: 59-59

src/main/webapp/app/detail-overview-list/detail-overview-list.component.html (1)

Line range hint 1-124: Consider breaking down the template for better maintainability

While the template follows good practices with semantic HTML and consistent patterns, its complexity suggests some potential improvements:

  1. Consider extracting complex switch cases into separate components, particularly for:

    • Programming exercise related cases
    • Modeling editor case
    • Build statistics table
  2. The repeated pattern of detail-value-{{ detail.title }} could be moved to a reusable directive

This would improve:

  • Code maintainability
  • Component testing
  • Reusability

Example refactor for the build statistics case:

// programming-build-statistics.component.ts
@Component({
  selector: 'jhi-programming-build-statistics',
  template: `
    <table class="table table-striped">
      <!-- Move the build statistics table template here -->
    </table>
  `
})
export class ProgrammingBuildStatisticsComponent {
  @Input() statistics!: BuildLogStatistics;
}

Then in the main template:

 @case (DetailType.ProgrammingBuildStatistics) {
     <dd id="detail-value-{{ detail.title }}">
-        <table class="table table-striped">
-            <!-- ... table content ... -->
-        </table>
+        <jhi-programming-build-statistics [statistics]="detail.data.buildLogStatistics" />
     </dd>
 }
src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts (2)

786-801: Optimize calculateLineCount function placement

The calculateLineCount function inside processGitDiffReport is defined every time the method is called. To improve performance and readability, consider moving this utility function outside of processGitDiffReport as a private method of the class. This avoids redefining the function on each invocation and makes the code cleaner.

Here's how you can refactor the code:

+ private calculateLineCount(entries: { lineCount?: number; previousLineCount?: number }[] = [], key: 'lineCount' | 'previousLineCount'): number {
+     return entries.map((entry) => entry[key] ?? 0).reduce((sum, count) => sum + count, 0);
+ }

private processGitDiffReport(gitDiffReport: ProgrammingExerciseGitDiffReport | undefined): void {
    if (
        gitDiffReport &&
        (this.programmingExercise.gitDiffReport?.templateRepositoryCommitHash !== gitDiffReport.templateRepositoryCommitHash ||
            this.programmingExercise.gitDiffReport?.solutionRepositoryCommitHash !== gitDiffReport.solutionRepositoryCommitHash)
    ) {
        this.programmingExercise.gitDiffReport = gitDiffReport;
        gitDiffReport.programmingExercise = this.programmingExercise;

-       const calculateLineCount = (entries: { lineCount?: number; previousLineCount?: number }[] = [], key: 'lineCount' | 'previousLineCount') =>
-           entries.map((entry) => entry[key] ?? 0).reduce((sum, count) => sum + count, 0);

-       this.addedLineCount = calculateLineCount(gitDiffReport.entries, 'lineCount');
-       this.removedLineCount = calculateLineCount(gitDiffReport.entries, 'previousLineCount');
+       this.addedLineCount = this.calculateLineCount(gitDiffReport.entries, 'lineCount');
+       this.removedLineCount = this.calculateLineCount(gitDiffReport.entries, 'previousLineCount');
    }
}

241-252: Ensure comprehensive error handling in the observable chain

While you have added an error handler in the subscribe block starting at line 241, consider handling errors at each asynchronous operation if they require specific error handling logic. This can provide more granular control over error messages and improve the user experience by displaying more relevant feedback.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between bcce67b and 4f9d814.

📒 Files selected for processing (3)
  • src/main/webapp/app/detail-overview-list/detail-overview-list.component.html (1 hunks)
  • src/main/webapp/app/detail-overview-list/detail-overview-list.component.ts (3 hunks)
  • src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts (4 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
src/main/webapp/app/detail-overview-list/detail-overview-list.component.html (1)

Pattern src/main/webapp/**/*.html: @if and @for are new and valid Angular syntax replacing *ngIf and *ngFor. They should always be used over the old style.

src/main/webapp/app/detail-overview-list/detail-overview-list.component.ts (1)

Pattern src/main/webapp/**/*.ts: angular_style:https://angular.io/guide/styleguide;methods_in_html:false;lazy_loading:true;code_reuse:true;tests:meaningful;types:PascalCase;enums:PascalCase;funcs:camelCase;props:camelCase;no_priv_prefix:true;strings:single_quotes;localize:true;btns:functionality;links:navigation;icons_text:newline;labels:associate;code_style:arrow_funcs,curly_braces,open_braces_same_line,indent_4;memory_leak_prevention:true;routes:naming_schema;chart_framework:ngx-charts;responsive_layout:true

src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts (1)

Pattern src/main/webapp/**/*.ts: angular_style:https://angular.io/guide/styleguide;methods_in_html:false;lazy_loading:true;code_reuse:true;tests:meaningful;types:PascalCase;enums:PascalCase;funcs:camelCase;props:camelCase;no_priv_prefix:true;strings:single_quotes;localize:true;btns:functionality;links:navigation;icons_text:newline;labels:associate;code_style:arrow_funcs,curly_braces,open_braces_same_line,indent_4;memory_leak_prevention:true;routes:naming_schema;chart_framework:ngx-charts;responsive_layout:true

🔇 Additional comments (4)
src/main/webapp/app/detail-overview-list/detail-overview-list.component.ts (3)

1-1: LGTM! Modern Angular dependency injection pattern applied.

The switch to using inject() function and making services readonly is a good improvement that:

  • Enables better tree-shaking
  • Prevents accidental service reassignment
  • Reduces boilerplate code by removing the constructor

Also applies to: 55-57


Line range hint 70-77: LGTM! Proper handling of the new input signal.

The code correctly adapts to the new input signal syntax by using sections() as a function call. The mapping logic is clean and efficient.


Line range hint 78-91: Verify subscription cleanup.

The subscription cleanup looks good, but let's verify there are no other subscriptions in the component that might need cleanup.

✅ Verification successful

Let me analyze the subscriptions in the component based on the search results:

  1. There's a profileSubscription that is:

    • Created: this.profileSubscription = this.profileService.getProfileInfo().subscribe(...)
    • Cleaned up: this.profileSubscription?.unsubscribe();
  2. There's a subscription in downloadApollonDiagramAsPDf method:

    • This is a one-time subscription that completes after the PDF conversion
    • It doesn't need cleanup as it's not stored and will auto-complete

Let me verify if there are any other potential subscriptions we might have missed by checking for observables or async patterns.


Subscription cleanup is properly implemented

The component has only two subscriptions:

  1. A stored profileSubscription that is properly cleaned up in the component's destruction
  2. A one-time subscription in downloadApollonDiagramAsPDf that auto-completes and doesn't require cleanup

No other subscriptions or potential memory leaks were found in the component.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for any missed subscriptions in the component
rg -A 2 "subscribe\(" "src/main/webapp/app/detail-overview-list"

Length of output: 1250


Script:

#!/bin/bash
# Search for Observable imports and declarations
rg "Observable|Subject|BehaviorSubject" "src/main/webapp/app/detail-overview-list/detail-overview-list.component.ts"

# Search for async pipe usage which might indicate subscriptions
ast-grep --pattern 'async'

Length of output: 833

src/main/webapp/app/detail-overview-list/detail-overview-list.component.html (1)

4-4: Verify reactive implementation of sections()

The change from sections to sections() suggests a reactive pattern implementation. This aligns with modern Angular practices, but we should ensure:

  1. The implementation in the component uses either Signals or RxJS properly
  2. Memory management (unsubscribe/cleanup) is handled correctly
✅ Verification successful

Let me try a different search pattern to find the sections implementation.


Change to sections() is correct and properly implemented

The code shows that sections is implemented as an Angular input using the new input syntax (sections = input.required<DetailOverviewSection[]>()). The function call syntax in the template is correct as this is how required inputs are accessed in the new Angular syntax. The component also properly handles cleanup with ngOnDestroy unsubscribing from profileSubscription.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for the sections implementation in the component
ast-grep --pattern 'class DetailOverviewListComponent {
  $$$
  sections$_() {
    $$$
  }
  $$$
}'

# Check for proper cleanup
rg -A 5 'ngOnDestroy|takeUntil|pipe' src/main/webapp/app/detail-overview-list/detail-overview-list.component.ts

Length of output: 416


Script:

#!/bin/bash
# Search for sections property/method in the component file
rg -A 10 "sections" src/main/webapp/app/detail-overview-list/detail-overview-list.component.ts

# Check if it's using signals
rg "signal|computed|effect" src/main/webapp/app/detail-overview-list/detail-overview-list.component.ts

Length of output: 1125

@github-actions github-actions bot added the tests label Nov 15, 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: 1

🧹 Outside diff range and nitpick comments (2)
src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts (2)

235-237: Improve type safety for build log statistics.

The type assertion [] as BuildLogStatisticsDTO might not be safe. Consider using a proper empty array type.

-                        this.programmingExercise.isAtLeastEditor ? this.programmingExerciseService.getBuildLogStatistics(exerciseId!) : of([] as BuildLogStatisticsDTO),
+                        this.programmingExercise.isAtLeastEditor ? this.programmingExerciseService.getBuildLogStatistics(exerciseId!) : of<BuildLogStatisticsDTO[]>([]),

798-800: Improve type safety in line count calculation helper.

The helper function uses generic parameter names. Consider using more specific types and names.

-            const calculateLineCount = (entries: { lineCount?: number; previousLineCount?: number }[] = [], key: 'lineCount' | 'previousLineCount') =>
+            const calculateLineCount = (diffEntries: { lineCount?: number; previousLineCount?: number }[] = [], countType: 'lineCount' | 'previousLineCount'): number =>
-                entries.map((entry) => entry[key] ?? 0).reduce((sum, count) => sum + count, 0);
+                diffEntries.map((entry) => entry[countType] ?? 0).reduce((sum, count) => sum + count, 0);
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 4f9d814 and ffbb6b6.

📒 Files selected for processing (1)
  • src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts (5 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts (1)

Pattern src/main/webapp/**/*.ts: angular_style:https://angular.io/guide/styleguide;methods_in_html:false;lazy_loading:true;code_reuse:true;tests:meaningful;types:PascalCase;enums:PascalCase;funcs:camelCase;props:camelCase;no_priv_prefix:true;strings:single_quotes;localize:true;btns:functionality;links:navigation;icons_text:newline;labels:associate;code_style:arrow_funcs,curly_braces,open_braces_same_line,indent_4;memory_leak_prevention:true;routes:naming_schema;chart_framework:ngx-charts;responsive_layout:true

🔇 Additional comments (2)
src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts (2)

190-196: LGTM! Improved error handling and state management.

The refactored subscription chain properly handles state updates and error cases.


789-804: LGTM! Well-structured Git diff report processing.

The method properly handles undefined input and efficiently calculates line counts.

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

🧹 Outside diff range and nitpick comments (3)
src/test/javascript/spec/component/detail-overview-list.component.spec.ts (3)

Line range hint 59-65: Enhance subscription cleanup verification.

While the test correctly uses setInput for input properties and verifies basic cleanup, consider strengthening the subscription cleanup test.

-expect(component.profileSubscription?.closed).toBeTruthy();
+expect(component.profileSubscription?.closed).toBeTrue();

This change aligns with the coding guidelines for boolean expectations using toBeTrue() instead of toBeTruthy().


Line range hint 70-93: Improve test robustness and assertion specificity.

The test has several areas for improvement:

  1. Avoid type assertions with as any
  2. Use more specific DOM element queries
  3. Use more specific existence assertions

Apply these improvements:

-null as any as Detail,
+null as unknown as Detail,

-expect(titleDetailTitle).toBeDefined();
-expect(titleDetailValue).toBeDefined();
+expect(titleDetailTitle).not.toBeNull();
+expect(titleDetailValue).not.toBeNull();

-fixture.nativeElement.querySelectorAll('dt[id^=detail-title]')
+fixture.nativeElement.querySelectorAll('[data-testid="detail-title"]')

Also consider adding test data attributes to your component template:

<dt [attr.data-testid]="'detail-title-' + detail.title">

Line range hint 1-108: Consider adding tests for additional scenarios.

While the current test coverage is good, consider adding tests for:

  1. Input validation when sections are empty
  2. Edge cases with malformed section data
  3. Accessibility attributes in the rendered output

Example test structure:

it('should handle empty sections gracefully', () => {
    fixture.componentRef.setInput('sections', []);
    fixture.detectChanges();
    expect(fixture.nativeElement.querySelector('[data-testid="no-sections"]')).not.toBeNull();
});

it('should validate section structure', () => {
    fixture.componentRef.setInput('sections', [{ headline: 'invalid' }]);
    fixture.detectChanges();
    // Verify error handling or fallback behavior
});

it('should include proper aria labels', () => {
    fixture.componentRef.setInput('sections', sections);
    fixture.detectChanges();
    const headings = fixture.nativeElement.querySelectorAll('[role="heading"]');
    expect(headings.length).toBeGreaterThan(0);
});
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between ffbb6b6 and fd45565.

📒 Files selected for processing (1)
  • src/test/javascript/spec/component/detail-overview-list.component.spec.ts (3 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
src/test/javascript/spec/component/detail-overview-list.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}}

coderabbitai[bot]
coderabbitai bot previously approved these changes Nov 15, 2024
@florian-glombik florian-glombik modified the milestones: 7.7.2, 7.7.1 Nov 15, 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: 1

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between fd45565 and 78679a2.

📒 Files selected for processing (1)
  • src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts (3 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts (1)

Pattern src/main/webapp/**/*.ts: angular_style:https://angular.io/guide/styleguide;methods_in_html:false;lazy_loading:true;code_reuse:true;tests:meaningful;types:PascalCase;enums:PascalCase;funcs:camelCase;props:camelCase;no_priv_prefix:true;strings:single_quotes;localize:true;btns:functionality;links:navigation;icons_text:newline;labels:associate;code_style:arrow_funcs,curly_braces,open_braces_same_line,indent_4;memory_leak_prevention:true;routes:naming_schema;chart_framework:ngx-charts;responsive_layout:true

🔇 Additional comments (3)
src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts (3)

60-61: LGTM: Imports are correctly added.

The new imports for RxJS tap operator and ProgrammingExerciseGitDiffReport model are necessary for the refactored code.


790-805: LGTM: Well-structured Git diff report processing.

The implementation:

  • Properly handles undefined input
  • Efficiently calculates line counts using functional programming
  • Avoids unnecessary updates by comparing commit hashes

808-810: Skip: Error handling comment already exists.

A previous review comment already addresses the need for error handling in this code segment.

Copy link
Contributor

@cremertim cremertim left a comment

Choose a reason for hiding this comment

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

Reapprove latest changes

Copy link
Contributor

@az108 az108 left a comment

Choose a reason for hiding this comment

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

Code 👍

Copy link

@sachmii sachmii 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

@magaupp
Copy link
Contributor

magaupp commented Nov 24, 2024

Tested on Firefox. repository-checkout-directories seems to be fetched 2 times, with the first time canceled. What's happening there?

grafik

@florian-glombik
Copy link
Contributor Author

florian-glombik commented Nov 24, 2024

@magaupp #9785 (comment)
Thanks for your test, I have now added it to the testing description - I am not sure why this happens but I will not investigate it further as I have already way too much time on this issue and even for the repository-checkout-directories it is still an improvement from 4 requests going down to 2 requests, where one is even cancelled.

Do you think we should create an issue for it once the PR is merged? (Beforehand it might be confusing as there are way more requests send out on the current develop state?)

Copy link
Contributor

@magaupp magaupp left a comment

Choose a reason for hiding this comment

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

The other requests are only sent once, so this is definitely an improvement.
The details view also works as expected without issues.

requests

@magaupp
Copy link
Contributor

magaupp commented Nov 24, 2024

@florian-glombik

Do you think we should create an issue for it once the PR is merged? (Beforehand it might be confusing as there are way more requests send out on the current develop state?)

I don't think it's performance critical. Nothing could wait on it because it's always canceled before it finishes.
Unless this causes any noticeable problems it's purely cosmetic and I wouldn't call it a real issue.

Copy link
Member

@krusche krusche left a comment

Choose a reason for hiding this comment

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

Great improvements, thank you 👍

@krusche krusche merged commit 4dde77f into develop Nov 24, 2024
17 of 20 checks passed
@krusche krusche deleted the chore/programming-exercises/reduce-api-calls-in-details-view branch November 24, 2024 22:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
chore client Pull requests that update TypeScript code. (Added Automatically!) code quality ready for review ready to merge refactoring tests
Projects
Status: Merged
Development

Successfully merging this pull request may close these issues.

7 participants