Skip to content

Conversation

@tbouffard
Copy link
Member

@tbouffard tbouffard commented Mar 3, 2025

This facilitates maintenance and enables errors to be detected earlier.
Also display a description at the top of the Graph to help understand what the story is doing.

Summary by CodeRabbit

  • New Features
    • Enhanced the interactive graph events demo with refined visual interactions including improved tooltips, context menus, and connection handling.
    • Upgraded the demo implementation to a TypeScript version for a more robust and maintainable experience.

This facilitates maintenance and enables errors to be detected earlier.
Also display a description at the top of the Graph to help understand what the story is doing.
@tbouffard tbouffard added the refactor Code refactoring label Mar 3, 2025
@coderabbitai
Copy link

coderabbitai bot commented Mar 3, 2025

Walkthrough

This pull request updates the method signature of getTooltipForCell in the Graph interface from a property-style annotation to a standard function declaration in the Tooltip mixin file. Additionally, it removes the JavaScript version of the Events story and introduces a new TypeScript version. The new TS story sets up a Storybook story for graph event handling, including custom tooltips, connection handling, popup menu configuration, and batch model updates.

Changes

File(s) Change Summary
packages/core/.../TooltipMixin.type.ts Changed getTooltipForCell: (cell: Cell) => HTMLElement | string to getTooltipForCell(cell: Cell): HTMLElement | string in the Graph interface.
packages/html/stories/Events.stories.{js,ts} Removed the JS story file and added a new TS story file defining event handling with custom tooltips, connection handler, popup menus, and batch updates.

Sequence Diagram(s)

sequenceDiagram
  participant U as User
  participant T as Template
  participant G as MyCustomGraph
  participant D as DOM

  U->>T: Trigger story execution
  T->>D: Create graph container
  T->>G: Instantiate MyCustomGraph with event settings
  G->>G: Initialize tooltips, connection handler, and popup menu
  G->>D: Render the graph on the DOM
  U->>G: Interact with graph (hover, click)
  G->>G: Handle events (display tooltip, show popup menu)
Loading

Suggested labels

javascript

✨ Finishing Touches
  • 📝 Generate Docstrings

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 generate docstrings to generate docstrings for this 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 anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration 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: 1

🧹 Nitpick comments (2)
packages/html/stories/Events.stories.ts (2)

61-61: Consider using a more specific type definition.

The Record<string, string> type annotation suggests all parameters are strings, but some arguments (like contextMenu and rubberBand) are likely booleans based on their usage in the code.

-const Template = ({ label, ...args }: Record<string, string>) => {
+const Template = ({ label, ...args }: { 
+  label?: string;
+  contextMenu?: boolean;
+  rubberBand?: boolean;
+  [key: string]: any;
+}) => {

155-175: Consider replacing alerts with a more modern notification approach.

Using alert() for notifications is generally not recommended in modern web applications as it blocks the UI thread and provides a poor user experience.

Consider replacing the alerts with a more modern notification system that is non-blocking, such as toast notifications or a custom feedback component within the Storybook interface:

-    menu.addItem('Cell Item', `${Client.imageBasePath}/image.gif`, () => {
-      alert('MenuItem1');
-    });
+    menu.addItem('Cell Item', `${Client.imageBasePath}/image.gif`, () => {
+      // Use a non-blocking notification or logging for Storybook
+      console.log('MenuItem1 clicked');
+      // Alternatively, update a status element in the DOM
+      const statusEl = document.getElementById('status-message') || document.createElement('div');
+      statusEl.id = 'status-message';
+      statusEl.textContent = 'MenuItem1 clicked';
+      statusEl.style.cssText = 'position: fixed; bottom: 10px; right: 10px; background: #333; color: white; padding: 8px; border-radius: 4px;';
+      document.body.appendChild(statusEl);
+      setTimeout(() => statusEl.remove(), 3000);
+    });

Apply similar changes to the other alert calls.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 18755d6 and afef299.

📒 Files selected for processing (3)
  • packages/core/src/view/mixins/TooltipMixin.type.ts (1 hunks)
  • packages/html/stories/Events.stories.js (0 hunks)
  • packages/html/stories/Events.stories.ts (1 hunks)
💤 Files with no reviewable changes (1)
  • packages/html/stories/Events.stories.js
✅ Files skipped from review due to trivial changes (1)
  • packages/core/src/view/mixins/TooltipMixin.type.ts
🧰 Additional context used
🪛 Biome (1.9.4)
packages/html/stories/Events.stories.ts

[error] 119-119: Comparing to itself is potentially pointless.

(lint/suspicious/noSelfCompare)

⏰ Context from checks skipped due to timeout of 90000ms (4)
  • GitHub Check: build
  • GitHub Check: build (windows-2022)
  • GitHub Check: build (macos-14)
  • GitHub Check: build (ubuntu-22.04)
🔇 Additional comments (11)
packages/html/stories/Events.stories.ts (11)

1-16: License information is properly included.

The standard Apache 2.0 license header is correctly included at the top of the file, indicating proper licensing compliance.


18-45: Good organization of imports.

The imports are well-organized, separated between external dependencies from '@maxgraph/core' and internal imports from shared modules. The CSS import at the end is also properly documented with a comment explaining its purpose for RubberBand.


47-59: Story configuration follows best practices.

The Storybook configuration follows best practices by properly defining title, argTypes, and args. The use of spread operators for including shared argument definitions promotes DRY (Don't Repeat Yourself) principles.


66-76: Good user guidance with descriptive text.

Adding a description at the top of the graph helps users understand the functionality of the story, which aligns with the PR objective to "display a description at the top of the Graph."


82-82: Conditionally disabling context menu is a good practice.

Using the argument to conditionally disable the context menu gives users control over the behavior and demonstrates best practices in configuration.


84-93: Custom Graph class correctly implements tooltip functionality.

The MyCustomGraph class properly extends the base Graph class and correctly overrides the getTooltipForCell method with the appropriate TypeScript override keyword.


95-100: Good plugin management based on user configuration.

The code correctly uses the default plugins and conditionally adds the RubberBandHandler based on the provided arguments, demonstrating good practices for configurable components.


103-108: Custom connection handler properly configured.

The connection handler is correctly obtained using the plugin system and configured with a custom image for creating new connections.


133-137: Factory method correctly implements popup menu.

The popup menu handler is properly configured with a factory method that delegates to the createPopupMenu function, following good separation of concerns.


143-150: Efficient batch update for adding graph elements.

Using batchUpdate for adding multiple vertices and edges in a single operation is a good practice for performance optimization.


177-177: Story export follows Storybook conventions.

The export of the default story using Template.bind({}) follows Storybook conventions correctly.

@sonarqubecloud
Copy link

sonarqubecloud bot commented Mar 3, 2025

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (4)
packages/html/stories/Events.stories.ts (4)

61-61: Consider using a more specific type for the Template function parameters.

The current type Record<string, string> is too restrictive as some arguments might be booleans or numbers coming from Storybook controls.

-const Template = ({ label, ...args }: Record<string, string>) => {
+const Template = ({ label, ...args }: {label?: string, [key: string]: any}) => {

64-76: Consider extracting the description to a separate component or constant.

The current implementation directly manipulates DOM elements and sets inline HTML, which works but isn't the most maintainable approach. Consider:

  1. Extracting this to a separate component
  2. Or at minimum, moving the HTML content to a constant

This would improve code organization and readability.

+const DESCRIPTION_HTML = `
+  Creating a graph container and using interaction on the graph, including marquee selection, custom tooltips, context menu.
+  <p>
+  It also demonstrates how to use an edge style in the default stylesheet, and handle the double click on the adjustment point.
+  <br>
+   See also the <code>Overlays</code> Story for click event handling.
+  `;

const Template = ({ label, ...args }: Record<string, string>) => {
  configureImagesBasePath();

  const div = document.createElement('div');

  const divMessage = document.createElement('div');
-  divMessage.innerHTML = `
-  Creating a graph container and using interaction on the graph, including marquee selection, custom tooltips, context menu.
-  <p>
-  It also demonstrates how to use an edge style in the default stylesheet, and handle the double click on the adjustment point.
-  <br>
-   See also the <code>Overlays</code> Story for click event handling.
-  `;
+  divMessage.innerHTML = DESCRIPTION_HTML;
  divMessage.style.fontFamily = 'Arial,Helvetica,sans-serif';
  divMessage.style.marginBottom = '1rem';
  div.appendChild(divMessage);

143-150: Consider using more descriptive variable names for vertices.

The variables v1, v2, v3 don't convey the purpose of each vertex. Using more descriptive names would improve code readability and maintainability.

-    const v1 = graph.insertVertex(parent, null, 'Double-click', 20, 20, 80, 30);
-    const v2 = graph.insertVertex(parent, null, 'Right-/Shift-click', 200, 150, 120, 30);
-    const v3 = graph.insertVertex(parent, null, 'Connect/Reconnect', 200, 20, 120, 30);
+    const doubleClickVertex = graph.insertVertex(parent, null, 'Double-click', 20, 20, 80, 30);
+    const rightShiftClickVertex = graph.insertVertex(parent, null, 'Right-/Shift-click', 200, 150, 120, 30);
+    const connectReconnectVertex = graph.insertVertex(parent, null, 'Connect/Reconnect', 200, 20, 120, 30);
     graph.insertVertex(parent, null, 'Control-Drag', 20, 150, 100, 30);
-    graph.insertEdge(parent, null, 'Tooltips', v1, v2);
-    graph.insertEdge(parent, null, '', v2, v3);
+    graph.insertEdge(parent, null, 'Tooltips', doubleClickVertex, rightShiftClickVertex);
+    graph.insertEdge(parent, null, '', rightShiftClickVertex, connectReconnectVertex);

155-175: Replace alert() with a more user-friendly notification mechanism.

Using alert() for notifications in the context menu handlers is functional but disruptive to the user experience. Consider using a more modern notification approach like toast messages or an overlay that doesn't block the UI.

function createPopupMenu(
  graph: Graph,
  menu: MaxPopupMenu,
  cell: Cell | null,
  _evt: MouseEvent
) {
  // Function to create the entries in the popupmenu
  if (cell != null) {
    menu.addItem('Cell Item', `${Client.imageBasePath}/image.gif`, () => {
-     alert('MenuItem1');
+     // Consider a non-blocking notification approach
+     showNotification('MenuItem1 selected');
    });
  } else {
    menu.addItem('No-Cell Item', `${Client.imageBasePath}/image.gif`, () => {
-     alert('MenuItem2');
+     showNotification('MenuItem2 selected');
    });
  }
  menu.addSeparator();
  menu.addItem('MenuItem3', `${Client.imageBasePath}/warning.gif`, () => {
-   alert(`MenuItem3: ${graph.getSelectionCount()} selected`);
+   showNotification(`MenuItem3: ${graph.getSelectionCount()} selected`);
  });
}

+// Example implementation of a non-blocking notification
+function showNotification(message: string) {
+  const notification = document.createElement('div');
+  notification.textContent = message;
+  notification.style.position = 'fixed';
+  notification.style.bottom = '20px';
+  notification.style.right = '20px';
+  notification.style.padding = '10px 20px';
+  notification.style.backgroundColor = '#333';
+  notification.style.color = 'white';
+  notification.style.borderRadius = '4px';
+  notification.style.zIndex = '1000';
+  document.body.appendChild(notification);
+  
+  setTimeout(() => {
+    notification.style.opacity = '0';
+    notification.style.transition = 'opacity 0.5s ease';
+    setTimeout(() => document.body.removeChild(notification), 500);
+  }, 3000);
+}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between afef299 and 2596a0c.

📒 Files selected for processing (1)
  • packages/html/stories/Events.stories.ts (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: build (windows-2022)
  • GitHub Check: build (macos-14)
  • GitHub Check: build (ubuntu-22.04)
🔇 Additional comments (7)
packages/html/stories/Events.stories.ts (7)

1-16: License headers correctly implemented.

The file includes the proper license header for both the maxGraph project contributors and JGraph Ltd, with the Apache License 2.0 terms clearly specified.


18-46: Clean and comprehensive imports.

The imports are well-organized and properly typed, distinguishing between:

  1. Core components from @maxgraph/core
  2. Shared configuration and arguments from local modules
  3. Required CSS import for the RubberBand functionality

This provides good clarity about the dependencies of the component.


47-59: Story configuration follows best practices.

The export default configuration correctly sets up the Storybook story with appropriate title and combines multiple argument types, making it configurable through the Storybook UI.


84-93: Well-structured graph customization.

The custom graph class correctly extends the base Graph class and properly overrides the getTooltipForCell method with appropriate TypeScript overriding syntax and types.


95-100: Good practice for conditional plugin usage.

The code correctly retrieves default plugins and conditionally adds the RubberBandHandler based on the Storybook args, demonstrating a clean approach to configurable functionality.


118-123: Fixed self-comparison issue as recommended.

The code now uses parentheses to explicitly define the order of operations for the nullish coalescing operator and comparison, which fixes the potential self-comparison issue flagged by static analysis.


177-177: Proper story export.

The Default story export is correctly defined using Template.bind({}), following Storybook best practices for story creation.

@tbouffard tbouffard merged commit b73fc2a into main Mar 3, 2025
7 checks passed
@tbouffard tbouffard deleted the refactor/story_Events_to_TS branch March 3, 2025 10:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

refactor Code refactoring

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant