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

Programming exercises: Change the problem statement editor to Monaco #8856

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

Conversation

pzdr7
Copy link
Contributor

@pzdr7 pzdr7 commented Jun 23, 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 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.

Changes affecting Programming Exercises

  • High priority: I tested all changes and their related features with all corresponding user types on a test server configured with the integrated lifecycle setup (LocalVC and LocalCI).

Motivation and Context

We want to replace the Ace code editor in Artemis. The largest and most-used component using Ace is the Markdown editor (used in several cases, e.g. programming exercises).

Description

  • Replaced the Ace editor with Monaco for the problem statement editor in programming exercises
  • Defined an Action hierarchy akin to the command hierarchy implemented in the Ace-based markdown editor
  • Fixed a few visual bugs, e.g. the content of the editor being cut off when in "Edit in Editor"

Known issues:

  • The save button may overlap with the action bar buttons in the. This was already the case before this change and will be solved in a follow-up.

Regarding the security warnings: This is code we would have used indirectly anyway (it's taken from the Monaco editor source code). DoS is unlikely to be an issue for the problem statements we have and HTML parsing is not supposed to be a big part of our custom markdown language.

Steps for Testing

Prerequisites:

  • 1 Instructor
  • 1 Programming exercise
  1. Log in to Artemis
  2. Navigate to Course Management > Your course > Your programming exercise

Edit in editor

  1. Go to "Edit in Editor" and see if the markdown editor displays correctly.
  2. Drag the drag handles around to test if the layout works correctly.
  3. Try the markdown commands and see if they work (reasonably) well. Suggestions may be resolved in this PR or in a follow-up/stacked pr depending on the scope. Switch between preview and editor.
  4. When editing, you can use the following shortcuts: CTRL + B (Bold), CTRL + I (Italic), CTRL + U (Underline), CTRL + S (Save) -- (on MacOs you should use Cmd instead of CTRL)
  5. Check if you can drag & drop files into the editor. PDFs should result in a link; images should be embedded
  6. Save the problem statement, then leave the page. Verify that the problem statement saved correctly

Edit (regular)

  1. Go to the normal "Edit" view
  2. Repeat the previous steps and see if the problem statement is saved correctly. Make sure to drag the resize handle to resize the editor vertically

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

  • 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

Test Coverage

Client

Class/File Line Coverage Confirmation (assert/expect)
code-editor-instructor-and-editor-container.component.ts 100%
programming-exercise-editable-instruction.component.ts 94.3%
programming-exercise-problem.component.ts 100%
code-editor-instructor-and-editor-orion-container.component.ts 100%
markdown-editor-monaco.component.ts 97.36%
monaco-attachment.action.ts 100%
monaco-bold.action.ts 100%
monaco-code-block.action.ts 100%
monaco-code.action.ts 100%
monaco-color.action.ts 100%
monaco-editor-action-group.model.ts 100%
monaco-editor-action.model.ts 97.82%
monaco-editor-domain-action-with-options.model.ts 100%
monaco-editor-domain-action.model.ts 100%
monaco-formula.action.ts 100%
monaco-fullscreen.action.ts 100%
monaco-heading.action.ts 100%
monaco-italic.action.ts 100%
monaco-ordered-list.action.ts 100%
monaco-quote.action.ts 100%
monaco-task.action.ts 100%
monaco-test-case.action.ts 100%
monaco-underline.action.ts 100%
monaco-unordered-list.action.ts 100%
monaco-url.action.ts 100%
monaco-custom-markdown.language.ts 100%
monaco-editor.component.ts 92.92%

Screenshots

image

image

Summary by CodeRabbit

  • New Features
    • Introduced various editor actions for the Monaco editor, including toggling text styles (italic, underline, heading), inserting lists (ordered, unordered), and adding specific elements (quotes, tasks, test cases, URLs).
    • Added fullscreen and formula toggle actions for enhanced editing capabilities.

pzdr7 added 30 commits May 12, 2024 22:50
Copy link

coderabbitai bot commented Jun 25, 2024

Walkthrough

The changes introduce a range of new actions for the Monaco editor in Artemis, enhancing its functionality for text formatting, inserting elements, and managing editor modes. These actions include toggling text styles (italic, underline, heading), handling list types (ordered, unordered), inserting specific elements (URLs, tasks, test cases), and adjusting the editor's display mode (fullscreen). Each new action is encapsulated in its own class and builds on a shared base of domain action models.

Changes

File Path Summary
src/.../monaco-editor-domain-action-with-options.model.ts Introduces MonacoEditorDomainActionWithOptions class and DomainActionWithOptionsArguments interface.
src/.../monaco-editor-domain-action.model.ts Adds MonacoEditorDomainAction abstract class for domain-specific actions.
src/.../monaco-formula.action.ts Adds MonacoFormulaAction class for toggling formula text.
src/.../monaco-fullscreen.action.ts Adds MonacoFullscreenAction class for toggling fullscreen mode.
src/.../monaco-heading.action.ts Adds MonacoHeadingAction class for toggling heading text.
src/.../monaco-italic.action.ts Adds MonacoItalicAction class for toggling italic text.
src/.../monaco-ordered-list.action.ts Adds MonacoOrderedListAction class for toggling ordered list.
src/.../monaco-quote.action.ts Adds MonacoQuoteAction class for toggling quote text.
src/.../monaco-task.action.ts Adds MonacoTaskAction class for inserting tasks.
src/.../monaco-test-case.action.ts Adds MonacoTestCaseAction class for inserting test cases and providing completion items.
src/.../monaco-underline.action.ts Adds MonacoUnderlineAction class for toggling underline text.
src/.../monaco-unordered-list.action.ts Adds MonacoUnorderedListAction class for toggling unordered list.
src/.../monaco-url.action.ts Adds MonacoUrlAction class for inserting URLs in markdown format, including associated methods and constants.

Recent review details

Configuration used: .coderabbit.yaml
Review profile: ASSERTIVE

Commits

Files that changed from the base of the PR and between 9badefb and dfd874a.

Files selected for processing (1)
  • src/main/webapp/app/shared/monaco-editor/monaco-editor.component.ts (10 hunks)
Additional context used
Path-based instructions (1)
src/main/webapp/app/shared/monaco-editor/monaco-editor.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

Biome
src/main/webapp/app/shared/monaco-editor/monaco-editor.component.ts

[error] 88-88: This type annotation is trivially inferred from its initialization. (lint/style/noInferrableTypes)

Safe fix: Remove the type annotation.


[error] 272-272: This type annotation is trivially inferred from its initialization. (lint/style/noInferrableTypes)

Safe fix: Remove the type annotation.


[error] 308-308: Template literals are preferred over string concatenation. (lint/style/useTemplate)

Unsafe fix: Use a template literal.

Additional comments not posted (10)
src/main/webapp/app/shared/monaco-editor/monaco-editor.component.ts (10)

10-11: Good use of centralized translation service

It's positive to see the use of TranslateService from @ngx-translate/core, which adheres to the Angular style guide's recommendation for localization. This is crucial for maintaining the internationalization capability of the Artemis platform.


32-35: Consistent use of readonly qualifiers enhances immutability

The use of readonly for themeService, renderer, and translateService is a good practice as it ensures these injected services do not get reassigned, aligning with immutability principles in TypeScript.


51-54: Good handling of editor scroll behavior

Setting alwaysConsumeMouseWheel: false is a thoughtful touch, ensuring that unintentional editor scrolls do not hinder the user experience by allowing the mouse wheel event to propagate. This is especially useful in nested scrolling scenarios.


139-141: Correct implementation of text selection

The method setSelection correctly uses the Monaco Editor's API to set text selection. This is crucial for user interactions such as copy-paste or selective editing.


148-150: Efficient text setting with change check

The condition checking if the current text is different from the new text before setting it is a good practice. It prevents unnecessary operations and potential re-renderings.


239-244: Proper disposal of actions to prevent memory leaks

The method disposeActions is crucial for cleaning up and preventing memory leaks, especially in a complex SPA where components can be dynamically created and destroyed. Ensure that all disposals are triggered appropriately during component lifecycle events.


332-335: Register action method correctly integrates with editor lifecycle

The registerAction method integrates actions into the editor's lifecycle effectively. It's important that these actions are also unregistered or disposed of correctly to prevent memory leaks or stale references.


338-341: Word wrap option toggle implemented correctly

The implementation of toggling the word wrap option based on a boolean value is straightforward and effective. This feature enhances the readability of the code within the editor.


74-78: Validate the effect of sticky scroll feature

The implementation of the stickyScroll feature should be tested thoroughly to ensure it behaves as expected across different browsers and devices, especially since scrolling behaviors can vary significantly.


161-163: Ensure focus method is accessible and effective

The focus method is crucial for user interaction, ensuring the editor can programmatically receive focus. Verify its accessibility implications and ensure it behaves consistently across all usage scenarios.


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.
    • @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 as 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.

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.

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: 16

Outside diff range comments (20)
src/test/javascript/spec/jest-test-setup.ts (1)

Line range hint 9-75: Mock Implementations and Global Assignments

The setup file for Jest tests includes various mocks and global assignments to ensure the tests run smoothly with the Monaco editor. These setups are necessary but ensure that they do not interfere with other tests or global settings.

However, consider isolating these mocks to specific test suites where they are needed to avoid potential side effects in unrelated tests.

src/main/webapp/app/exercises/programming/manage/code-editor/code-editor-instructor-and-editor-container.component.ts (1)

Line range hint 1-47: Unnecessary Constructor

The constructor in CodeEditorInstructorAndEditorContainerComponent does not perform any custom logic and merely calls the superclass constructor. This could be omitted for cleaner code.

- constructor(
-     router: Router,
-     exerciseService: ProgrammingExerciseService,
-     courseExerciseService: CourseExerciseService,
-     domainService: DomainService,
-     programmingExerciseParticipationService: ProgrammingExerciseParticipationService,
-     location: Location,
-     participationService: ParticipationService,
-     route: ActivatedRoute,
-     alertService: AlertService,
- ) {
-     super(router, exerciseService, courseExerciseService, domainService, programmingExerciseParticipationService, location, participationService, route, alertService);
- }
src/main/webapp/app/exercises/shared/feedback-suggestion/exercise-feedback-suggestion-options.component.ts (3)

Line range hint 16-16: Remove unnecessary type annotation.

The type annotation on line 16 is inferred and thus redundant. Simplifying this can improve code readability.

- protected readonly AssessmentType = AssessmentType;
+ protected readonly AssessmentType;

Line range hint 55-55: Use strict equality checks.

Using == can lead to unexpected type coercion. It is safer to use === for comparisons to ensure type safety.

- this.exercise.dueDate == undefined
+ this.exercise.dueDate === undefined

Also applies to: 56-56


Line range hint 71-71: Specify a more explicit type than any.

Using any disables TypeScript's type checking. For better code safety and maintainability, specify a more explicit type.

src/main/webapp/app/orion/management/code-editor-instructor-and-editor-orion-container.component.ts (2)

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

Assignments within expressions can lead to code that is hard to read and maintain. Consider separating this assignment to enhance clarity.

- this.orionConnectorService.state().subscribe((state) => (this.orionState = state));
+ this.orionConnectorService.state().subscribe((state) => {
+    this.orionState = state;
+ });

Line range hint 58-58: Use more specific types instead of any.

The use of any can lead to potential bugs and less maintainable code by bypassing TypeScript's type system. Consider defining a more specific type.

src/main/webapp/app/orion/management/code-editor-instructor-and-editor-orion-container.component.html (1)

Line range hint 1-86: Ensure usage of new Angular syntax and check for accessibility enhancements.

The file uses the new @if directive correctly. However, consider adding aria-live attributes to dynamically updated regions to improve accessibility, especially where loading states and errors are displayed.

Enhancing accessibility can improve the usability of the platform for all users, including those using assistive technologies.

src/main/webapp/app/exercises/programming/shared/code-editor/layout/code-editor-grid.scss (1)

Line range hint 22-299: Review and optimize grid and flexbox usage for editor layout.

The CSS for the editor layout uses grid and flexbox effectively. However, consider using CSS variables for repeated values like margins and padding to enhance maintainability.

Using CSS variables can help in making the stylesheet easier to maintain and update. For example:

- .editor-sidebar-right {
-     width: 500px;
- }
+ :root {
+     --sidebar-right-width: 500px;
+ }
+ .editor-sidebar-right {
+     width: var(--sidebar-right-width);
+ }
src/main/webapp/app/exercises/programming/shared/instructions-render/extensions/programming-exercise-task.extension.ts (1)

[!TIP]
Codebase Verification

Address type safety and improve null handling in TypeScript file.

The use of non-null assertions (!) can lead to runtime errors if not handled properly. Consider using optional chaining or proper checks before accessing properties.

  • Replace this.exercise.id! with this.exercise?.id to ensure type safety.
  • Ensure that testCases is properly initialized before use to prevent runtime errors.

Locations to review:

  • src/main/webapp/app/exercises/programming/shared/instructions-render/extensions/programming-exercise-task.extension.ts
Analysis chain

Line range hint 25-143: Address type safety and improve null handling in TypeScript file.

The use of non-null assertions (!) can lead to runtime errors if not handled properly. Consider using optional chaining or proper checks before accessing properties.

- this.exercise.id!
+ this.exercise?.id

Also, ensure that variables like testCases are initialized before use to prevent runtime errors.

Scripts executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Verify initialization of `testCases` before use.

# Test: Search for the initialization of `testCases`. Expect: Initialization before use.
rg --type typescript $'this.testCases ='

Length of output: 76



Script:

#!/bin/bash
# Description: Verify initialization of `testCases` before use.

# Test: Search for the initialization of `testCases`. Expect: Initialization before use.
rg 'this.testCases ='

Length of output: 1802

src/main/webapp/app/exercises/programming/manage/code-editor/code-editor-instructor-and-editor-container.component.html (1)

Line range hint 1-136: Ensure proper use of Angular directives and improve error handling in HTML template.

The use of @if and other directives is consistent with Angular best practices. However, consider adding more descriptive error messages and handling for edge cases in repository selection and participation management.

Improving error handling and user feedback can greatly enhance the user experience. For example, adding timeouts or retries for loading states could prevent the UI from being stuck in an error state.

src/test/javascript/spec/component/shared/monaco-editor/monaco-editor.component.spec.ts (1)

Line range hint 96-96: Avoid Non-Null Assertions

Non-null assertions can lead to runtime errors if the assumed non-null values are actually null. It's better to handle these cases explicitly.

- const button: MonacoEditorGlyphMarginHoverButton = comp.glyphMarginHoverButton!;
- const fullscreenElement = element ?? editor.getDomNode()!;
- const modelDisposeSpy = jest.spyOn(model!, 'dispose');
+ // Add checks to ensure values are not null before using them
+ const button = comp.glyphMarginHoverButton;
+ if (!button) throw new Error('Glyph margin hover button is not initialized.');
+ const fullscreenElement = element ?? editor.getDomNode();
+ if (!fullscreenElement) throw new Error('Fullscreen element is not available.');
+ const modelDisposeSpy = model ? jest.spyOn(model, 'dispose') : undefined;
+ if (!modelDisposeSpy) throw new Error('Model is not initialized.');

Also applies to: 190-190, 216-216

src/main/webapp/app/exercises/programming/manage/instructions-editor/programming-exercise-editable-instruction.component.ts (4)

Line range hint 141-141: Type specification needed instead of 'any'.

Using 'any' type can lead to potential bugs and less maintainable code by bypassing TypeScript's static typing. It's advisable to specify a more explicit type.

- let someVariable: any;
+ let someVariable: SpecificType; // Replace 'SpecificType' with the actual expected type

Line range hint 145-145: Avoid using non-null assertion operators.

Non-null assertions may lead to runtime errors if not handled carefully. It's safer to handle potential nulls gracefully using conditional checks or optional chaining.

- this.someNullableProperty!.someMethod();
+ this.someNullableProperty?.someMethod();

Also applies to: 200-200, 207-207, 212-212, 238-238


Line range hint 210-213: Redundant else clause detected.

The 'else' clause here is unnecessary as the previous branches of conditionals use 'return' statements, which already exit the function scope when met. Removing it can simplify the code flow and improve readability.

- else {
-   // some code
- }

Line range hint 261-261: Use template literals for string operations.

Template literals provide a more readable and concise way to handle complex string operations compared to traditional string concatenation.

- const message = 'Error: ' + error.message;
+ const message = `Error: ${error.message}`;
src/main/webapp/app/exercises/programming/shared/code-editor/container/code-editor-container.component.ts (2)

Line range hint 200-200: Avoid non-null assertion operator.

Using non-null assertion operators can lead to runtime errors if the value is null or undefined. Consider checking for nullity before usage or using optional chaining.

- this.selectedFile = this.fileService.updateFileReference(this.selectedFile!, fileChange);
+ const updatedFile = this.fileService.updateFileReference(this.selectedFile, fileChange);
+ if (updatedFile) {
+     this.selectedFile = updatedFile;
+ }

Line range hint 258-258: Specify a more accurate type than any.

Using any can lead to errors that TypeScript's type system could otherwise prevent. Specify a more detailed type for error to enhance code robustness and maintainability.

- onError(error: any) {
+ onError(error: string | ConnectionError) {

Also applies to: 297-297

src/main/webapp/app/shared/monaco-editor/monaco-editor.component.ts (1)

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

Template literals provide a more readable and concise syntax compared to traditional string concatenation.

- this.glyphMarginHoverButton = new MonacoEditorGlyphMarginHoverButton(this._editor, 'glyph-margin-hover-button-' + this._editor.getId(), domNode, clickCallback);
+ this.glyphMarginHoverButton = new MonacoEditorGlyphMarginHoverButton(this._editor, `glyph-margin-hover-button-${this._editor.getId()}`, domNode, clickCallback);
src/test/javascript/spec/component/programming-exercise/programming-exercise-editable-instruction.component.spec.ts (1)

Line range hint 175-175: Replace non-null assertion with optional chaining.

Non-null assertions can lead to runtime errors if the value is null. Use optional chaining to safely access properties of potentially null objects.

- getLatestResultWithFeedbacksStub.mockReturnValue(subject);
+ getLatestResultWithFeedbacksStub?.mockReturnValue(subject);

coderabbitai[bot]
coderabbitai bot previously approved these changes Jun 25, 2024
Copy link
Contributor

@Jan-Thurner Jan-Thurner left a comment

Choose a reason for hiding this comment

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

The code looks great overall. I just left one tiny comment.

Jan-Thurner
Jan-Thurner previously approved these changes Jun 25, 2024
Copy link
Contributor

@Jan-Thurner Jan-Thurner left a comment

Choose a reason for hiding this comment

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

code lgtm

Copy link
Contributor

@JohannesWt JohannesWt 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 - just two small comments

@pzdr7 pzdr7 dismissed stale reviews from Jan-Thurner and coderabbitai via dfd874a June 25, 2024 16:25
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: 2

@pzdr7 pzdr7 requested a review from JohannesWt June 25, 2024 20:38
Copy link
Contributor

@JohannesWt JohannesWt 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
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.

Tested on TS5, works as expected.

Adding an autosave function could be helpful, since for example adding a link and clicking on it results on navigating to the page and losing unsaved progress

@az108
Copy link
Contributor

az108 commented Jun 28, 2024

Tested on TS6 and everything works as expected but I found this small visual issue while navigating trough the repositories.
Hovering over TEMPLATE marks the first option and if you try to navigate with the mouse the TEMPLATE text dissapears and no other option is marked (only the Template Repository stays blue even if i hover over the other options).
image
image

@pzdr7
Copy link
Contributor Author

pzdr7 commented Jun 28, 2024

@az108 Thanks for testing & reporting 😃. I was able to reproduce this on TS1 without this PR deployed.

I'd say we can solve this in a follow-up as I didn't change this 👍

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 LGTM

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!) ready for review tests
Projects
Status: Ready For Review
Development

Successfully merging this pull request may close these issues.

None yet

5 participants