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

[Nu-7231] Add possibility for generic types in fragment input definition #7242

Merged
merged 1 commit into from
Nov 29, 2024

Conversation

DeamonDev
Copy link
Contributor

@DeamonDev DeamonDev commented Nov 26, 2024

Describe your changes

I changed <Select> component in TypeSelect isnide FragmentInputDefinition to <CreatableSelect> which allows to type own type:

image

Checklist before merge

  • Related issue ID is placed at the beginning of PR title in [brackets] (can be GH issue or Nu Jira issue)
  • Code is cleaned from temporary changes and commented out lines
  • Parts of the code that are not easy to understand are documented in the code
  • Changes are covered by automated tests
  • Showcase in dev-application.conf added to demonstrate the feature
  • Documentation added or updated
  • Added entry in Changelog.md describing the change from the perspective of a public distribution user
  • Added MigrationGuide.md entry in the appropriate subcategory if introducing a breaking change
  • Verify that PR will be squashed during merge

Summary by CodeRabbit

  • New Features

    • Introduced a new input parameter type "generic_type" in the Fragment feature.
    • Updated the TypeSelect component to allow users to create new options in addition to selecting existing ones.
  • Bug Fixes

    • Enhanced error handling for the TypeSelect component to provide more specific error messages.
  • Tests

    • Added new test cases to validate the handling of generic types in FragmentInputDefinition parameters.
    • Improved test coverage for the Fragment feature regarding the new input parameter type.

@github-actions github-actions bot added client client main fe ui labels Nov 26, 2024
@DeamonDev DeamonDev force-pushed the nu-7231-fragment-input-definitions-second-phase branch from e0e7664 to 2127b3d Compare November 26, 2024 15:57
@DeamonDev DeamonDev self-assigned this Nov 26, 2024
@DeamonDev DeamonDev linked an issue Nov 26, 2024 that may be closed by this pull request
Copy link
Contributor

github-actions bot commented Nov 26, 2024

created: #7266
⚠️ Be careful! Snapshot changes are not necessarily the cause of the error. Check the logs.

@DeamonDev DeamonDev changed the title [Nu-7231] Add possibility for generic types [Nu-7231] Add possibility for generic types in fragment input definition Nov 27, 2024
@DeamonDev DeamonDev force-pushed the nu-7231-fragment-input-definitions-second-phase branch from 0e77a13 to d0308b5 Compare November 27, 2024 10:39
@DeamonDev DeamonDev marked this pull request as ready for review November 27, 2024 10:42
Copy link

coderabbitai bot commented Nov 27, 2024

📝 Walkthrough
📝 Walkthrough

Walkthrough

The pull request introduces several changes primarily focused on enhancing the functionality and testing of the "Fragment" feature within the application. A new test case has been added to the Cypress end-to-end testing suite to handle a new input parameter type, specifically "generic_type" with the format "List[String]". This test simulates user interactions to ensure the input is processed correctly and includes additional assertions for visibility and correctness.

In the TypeSelect component, the Select component from react-select has been replaced with CreatableSelect, allowing users to create new options. The handling of the value prop has been adjusted to accommodate this change, while the overall structure and styling remain consistent.

A new function, resolveRefClazzName, has been introduced in the Item.tsx file to simplify class name representation, while error handling for the TypeSelect component has been refined. Additionally, the logic in the isPermittedTypeVariant function has been modified for clarity. Lastly, the FragmentParameterTypingParser class has updated its regex for parsing Map types to allow optional whitespace, and new test cases have been added to validate the handling of generic types in FragmentInputDefinition.

Possibly related PRs

Suggested labels

docs, submodules

Suggested reviewers

  • Dzuming
  • arkadius
  • mslabek

📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 1e0408d and e109cb3.

⛔ Files ignored due to path filters (1)
  • designer/client/cypress/e2e/__image_snapshots__/electron/Linux/Fragment should allow adding input parameters and display used fragment graph in modal #4.png is excluded by !**/*.png
📒 Files selected for processing (7)
  • designer/client/cypress/e2e/fragment.cy.ts (2 hunks)
  • designer/client/src/components/graph/node-modal/fragment-input-definition/TypeSelect.tsx (2 hunks)
  • designer/client/src/components/graph/node-modal/fragment-input-definition/item/Item.tsx (3 hunks)
  • designer/client/src/components/graph/node-modal/fragment-input-definition/item/types.ts (2 hunks)
  • designer/client/src/components/graph/node-modal/fragment-input-definition/item/utils.ts (1 hunks)
  • scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/definition/fragment/FragmentParameterTypingParser.scala (1 hunks)
  • scenario-compiler/src/test/scala/pl/touk/nussknacker/engine/compile/NodeDataValidatorSpec.scala (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (7)
  • designer/client/cypress/e2e/fragment.cy.ts
  • designer/client/src/components/graph/node-modal/fragment-input-definition/TypeSelect.tsx
  • designer/client/src/components/graph/node-modal/fragment-input-definition/item/Item.tsx
  • designer/client/src/components/graph/node-modal/fragment-input-definition/item/types.ts
  • designer/client/src/components/graph/node-modal/fragment-input-definition/item/utils.ts
  • scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/definition/fragment/FragmentParameterTypingParser.scala
  • scenario-compiler/src/test/scala/pl/touk/nussknacker/engine/compile/NodeDataValidatorSpec.scala

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

🧹 Outside diff range and nitpick comments (8)
scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/definition/fragment/FragmentParameterTypingParser.scala (1)

Line range hint 8-24: Consider implementing a proper parser for better generic type handling.

While the current regex-based approach is functional and accepted (as per previous discussions), given that this PR aims to enhance generic type support, it might be worth considering implementing the TODO suggestion for a proper AST-based parser. This would enable:

  1. Handling of nested generic types (e.g., Map[String, List[Int]])
  2. More robust parsing of complex type expressions
  3. Better error reporting for malformed type expressions

Some suggestions for future implementation:

  • Consider using parser combinators (e.g., Scala's scala-parser-combinators library)
  • Build a proper AST for type expressions
  • Implement a visitor pattern for type resolution

Would you like me to create a GitHub issue to track this technical debt?

designer/client/src/components/graph/node-modal/fragment-input-definition/TypeSelect.tsx (3)

Line range hint 71-71: Fix value handling in onChange handler

The current implementation discards custom input by returning an empty string when the option is a string type. This prevents users from entering custom generic types.

-onChange={(option) => onChange(typeof option === "string" ? "" : option.value)}
+onChange={(option) => onChange(typeof option === "string" ? option : option.value)}

Line range hint 64-104: Add validation for generic type inputs

Consider adding validation to ensure custom type inputs follow the correct format (e.g., List[String], Map[String, Int]). This will prevent invalid type definitions from being created.

<CreatableSelect
    {...props}
+   isValidNewOption={(inputValue) => {
+     const genericTypeRegex = /^[A-Z][a-zA-Z0-9]*(\[[A-Z][a-zA-Z0-9]*(\s*,\s*[A-Z][a-zA-Z0-9]*)?\])?$/;
+     return genericTypeRegex.test(inputValue);
+   }}
+   formatCreateLabel={(inputValue) => `Use custom type: ${inputValue}`}
    {...rest}
/>

Line range hint 38-38: Add documentation for generic types support

Please add JSDoc comments to document:

  1. The format expected for generic type inputs
  2. Examples of valid generic types
  3. Any limitations or restrictions
+/**
+ * TypeSelect component that supports both predefined and custom generic types.
+ * Custom types should follow the format: SimpleType or GenericType[TypeParam]
+ * Examples:
+ * - String
+ * - List[String]
+ * - Map[String, Int]
+ */
interface RowSelectProps extends Omit<HTMLProps<HTMLSelectElement>, "value" | "options" | "onBlur" | "onChange"> {
designer/client/src/components/graph/node-modal/fragment-input-definition/item/Item.tsx (2)

29-33: Consider handling edge cases in resolveSimpleClassName

While the function works for the happy path, it should handle edge cases to be more robust.

Consider this improved implementation:

 function resolveSimpleClassName(className: string): string {
+    if (!className) return "";
     const parts = className.split(".");
-    return parts[parts.length - 1];
+    return parts[parts.length - 1] || className;
 }

Line range hint 16-28: Consider enhancing TypeScript types for generic parameters

Since we're adding support for generic types in fragment input definitions, consider updating the TypeScript interfaces to properly type these generic parameters.

Some suggestions:

  1. Add JSDoc comments explaining generic type support in the FragmentInputParameter interface
  2. Consider creating a dedicated type for generic parameter definitions
  3. Add type guards or validation utilities for generic type syntax
designer/client/cypress/e2e/fragment.cy.ts (1)

161-165: Consider enhancing generic type test coverage

The test case for generic type input is well-integrated with the existing test suite. However, consider enhancing the test coverage:

  1. Add validation checks for the generic type format
  2. Verify the persistence of the generic type after saving
  3. Include negative test cases for invalid generic type formats
  4. Test different generic type variations (e.g., Map[String, Int], Option[T])

Example addition:

 cy.get("[data-testid='fieldsRow:8']").find("[placeholder='Field name']").type("generic_type");
 cy.get("[data-testid='fieldsRow:8']").contains("String").click().type("List[String]{enter}");
+
+// Verify generic type persistence
+cy.contains(/^apply$/i).click();
+cy.contains(/^save\*$/i).click();
+cy.contains(/^ok$/i).click();
+cy.get("[model-id=input]").trigger("dblclick");
+cy.get("[data-testid='fieldsRow:8']").should("contain", "List[String]");
+
+// Test invalid generic type format
+cy.get("@window").contains("+").click();
+cy.get("[data-testid='fieldsRow:9']").find("[placeholder='Field name']").type("invalid_generic");
+cy.get("[data-testid='fieldsRow:9']").contains("String").click().type("List<String>{enter}");
+cy.get("[data-testid='fieldsRow:9']").should("contain", "Invalid generic type format");
scenario-compiler/src/test/scala/pl/touk/nussknacker/engine/compile/NodeDataValidatorSpec.scala (1)

1163-1192: LGTM! Consider adding more test coverage.

The test case correctly validates the error handling for invalid generic types. Consider adding more test cases to cover:

  • Nested generic types (e.g., List[Map[String, Int]])
  • Multiple type parameters (e.g., Either[String, Int])
  • Bounded type parameters (e.g., List[T <: Number])
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 1a4c2d0 and d0308b5.

📒 Files selected for processing (6)
  • designer/client/cypress/e2e/fragment.cy.ts (1 hunks)
  • designer/client/src/components/graph/node-modal/fragment-input-definition/TypeSelect.tsx (2 hunks)
  • designer/client/src/components/graph/node-modal/fragment-input-definition/item/Item.tsx (3 hunks)
  • designer/client/src/components/graph/node-modal/fragment-input-definition/item/types.ts (1 hunks)
  • scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/definition/fragment/FragmentParameterTypingParser.scala (1 hunks)
  • scenario-compiler/src/test/scala/pl/touk/nussknacker/engine/compile/NodeDataValidatorSpec.scala (1 hunks)
🧰 Additional context used
📓 Learnings (1)
scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/definition/fragment/FragmentParameterTypingParser.scala (1)
Learnt from: DeamonDev
PR: TouK/nussknacker#7167
File: scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/definition/fragment/FragmentParameterTypingParser.scala:26-28
Timestamp: 2024-11-20T12:20:09.673Z
Learning: In the `FragmentParameterTypingParser`, it's acceptable to use shallow parsing with regex patterns, even if it doesn't handle nested generic types, as the team is currently okay with this approach.
🔇 Additional comments (7)
scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/definition/fragment/FragmentParameterTypingParser.scala (1)

26-26: LGTM! The whitespace handling improvement is a good addition.

The updated regex pattern now properly handles optional whitespace after the comma in Map type definitions, making it more flexible with different formatting styles while maintaining the existing functionality.

designer/client/src/components/graph/node-modal/fragment-input-definition/item/types.ts (1)

84-84: ⚠️ Potential issue

Simplify type checking logic and add generic type support

The current implementation has several issues:

  1. It's unnecessarily verbose and less performant as it creates an array of boolean results and performs an additional includes check
  2. It doesn't support generic types (e.g., "List[String]") mentioned in the PR objectives

Consider this simpler and more extensible implementation:

-    return [item.typ.refClazzName === "String", item.typ.refClazzName === "Boolean", item.typ.refClazzName === "Long"].includes(true);
+    const { refClazzName } = item.typ;
+    // Direct primitive type check
+    if (["String", "Boolean", "Long"].includes(refClazzName)) {
+        return true;
+    }
+    // Generic type check (e.g., "List[String]")
+    const genericMatch = refClazzName.match(/^(\w+)\[(String|Boolean|Long)\]$/);
+    return !!genericMatch;

This implementation:

  1. Simplifies the primitive type check using a single includes
  2. Adds support for generic types like "List[String]"
  3. Is more maintainable and easier to extend with additional type patterns

Let's verify the current usage of generic types in the codebase:

designer/client/src/components/graph/node-modal/fragment-input-definition/TypeSelect.tsx (2)

2-2: LGTM: Appropriate component selection for generic types support

The switch to CreatableSelect is a good choice as it enables users to input custom generic types while maintaining the ability to select from predefined options.


Line range hint 1-104: Verify test coverage for generic types functionality

Please ensure adequate test coverage for:

  1. Custom type input validation
  2. Generic type format handling
  3. Edge cases with complex generic types
designer/client/src/components/graph/node-modal/fragment-input-definition/item/Item.tsx (2)

45-45: LGTM! Clean implementation of simple class name resolution

The change correctly implements simple class name display for both label and value, maintaining consistency with the backward compatibility requirements.


79-79: Verify error path structure with backend validation

The error path has been updated to be more specific to each parameter. Let's verify that this matches the backend validation structure.

✅ Verification successful

The search results show that the error path pattern $param.{paramName}.$typ is consistently used in the backend codebase, particularly in validation-related files. The test files (UIProcessValidatorSpec.scala and BaseFlowTest.scala) and the API endpoint file (MigrationApiEndpoints.scala) all demonstrate the same pattern being used for parameter type validation errors.

Error path structure matches backend validation pattern

The updated error path $param.${item.name}.$typ in the frontend code aligns perfectly with the backend's validation structure, as evidenced by multiple occurrences of the same pattern in the backend codebase.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for validation error path patterns in backend code
rg -A 2 '\$param\.\$typ|\$param\.[^.]+\.\$typ' 

Length of output: 1258

scenario-compiler/src/test/scala/pl/touk/nussknacker/engine/compile/NodeDataValidatorSpec.scala (1)

1134-1161: LGTM! Well-structured test for valid generic type.

The test case properly validates that a Map[String, Double] is accepted as a valid generic type in FragmentInputDefinition parameter.

@DeamonDev DeamonDev force-pushed the nu-7231-fragment-input-definitions-second-phase branch from d0308b5 to 1924ecd Compare November 27, 2024 13:38
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 (4)
designer/client/src/components/graph/node-modal/fragment-input-definition/TypeSelect.tsx (2)

Line range hint 71-72: Improve type safety in the onChange handler.

The current implementation could be more type-safe and handle edge cases better.

Consider this improvement:

-onChange={(option) => onChange(typeof option === "string" ? "" : option.value)}
+onChange={(option) => {
+  if (!option) return onChange("");
+  if (typeof option === "string") return onChange(option);
+  return onChange(option.value);
+}}

Line range hint 31-41: Update RowSelectProps interface for CreatableSelect.

The interface should be adjusted to better match CreatableSelect's expectations.

Consider updating the interface:

 interface RowSelectProps extends Omit<HTMLProps<HTMLSelectElement>, "value" | "options" | "onBlur" | "onChange"> {
     onChange: (value: string) => void;
     onBlur?: (value: string) => void;
     options: Option[];
     readOnly?: boolean;
     isMarked?: boolean;
-    value: Option;
+    value: Option | null;
     placeholder?: string;
     fieldErrors?: FieldError[];
 }
designer/client/cypress/e2e/fragment.cy.ts (2)

161-164: Add assertions to verify generic type handling

While the test successfully adds a generic type parameter, it would be more robust with explicit assertions to verify:

  1. The type is correctly saved
  2. The UI properly displays the generic type
  3. The type selector accepts and validates the generic type format

Consider adding these assertions after line 164:

 cy.get("[data-testid='fieldsRow:8']").contains("String").click().type("List[String]{enter}");
+// Verify the type is correctly saved
+cy.get("[data-testid='fieldsRow:8']").find("[aria-label='type-select']").should("have.value", "List[String]");
+// Verify the UI displays the generic type
+cy.get("[data-testid='fieldsRow:8']").contains("List[String]").should("be.visible");

161-164: Consider adding test cases for error handling

To ensure robust generic type support, consider adding test cases for:

  1. Invalid generic type formats (e.g., "List[" or "List]")
  2. Nested generic types (e.g., "List[List[String]]")
  3. Error messages for invalid formats

Example test cases to add:

// Test invalid generic type format
cy.get("@window").contains("+").click();
cy.get("[data-testid='fieldsRow:9']").find("[placeholder='Field name']").type("invalid_generic");
cy.get("[data-testid='fieldsRow:9']").contains("String").click().type("List[{enter}");
// Verify error message
cy.get("[data-testid='fieldsRow:9']").find("[data-testid='form-helper-text']").should("contain", "Invalid generic type format");

// Test nested generic type
cy.get("@window").contains("+").click();
cy.get("[data-testid='fieldsRow:10']").find("[placeholder='Field name']").type("nested_generic");
cy.get("[data-testid='fieldsRow:10']").contains("String").click().type("List[List[String]]{enter}");
// Verify nested type is accepted
cy.get("[data-testid='fieldsRow:10']").find("[aria-label='type-select']").should("have.value", "List[List[String]]");
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between d0308b5 and 1924ecd.

📒 Files selected for processing (6)
  • designer/client/cypress/e2e/fragment.cy.ts (1 hunks)
  • designer/client/src/components/graph/node-modal/fragment-input-definition/TypeSelect.tsx (2 hunks)
  • designer/client/src/components/graph/node-modal/fragment-input-definition/item/Item.tsx (3 hunks)
  • designer/client/src/components/graph/node-modal/fragment-input-definition/item/types.ts (1 hunks)
  • scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/definition/fragment/FragmentParameterTypingParser.scala (1 hunks)
  • scenario-compiler/src/test/scala/pl/touk/nussknacker/engine/compile/NodeDataValidatorSpec.scala (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • designer/client/src/components/graph/node-modal/fragment-input-definition/item/Item.tsx
  • designer/client/src/components/graph/node-modal/fragment-input-definition/item/types.ts
  • scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/definition/fragment/FragmentParameterTypingParser.scala
🔇 Additional comments (5)
designer/client/src/components/graph/node-modal/fragment-input-definition/TypeSelect.tsx (2)

Line range hint 64-74: LGTM! The CreatableSelect implementation aligns with the PR objective.

The switch to CreatableSelect successfully enables users to input custom generic types, which is the main goal of this PR.


Line range hint 70-70: Consider validating empty value handling.

The value={value || ""} expression might need validation to ensure proper handling of null/undefined cases.

Let's verify the value handling in the codebase:

✅ Verification successful

The null/undefined handling is already properly implemented

The TypeSelect component already has proper handling for null/undefined cases:

  1. The value prop is typed as Option in the interface, making it a required prop that must be provided
  2. The value={value || ""} expression is used within the CreatableSelect component which is designed to handle empty string values correctly
  3. The component includes proper type checking in the onChange handler: typeof option === "string" ? "" : option.value
  4. The component is used with a ValidationLabels component that can display field errors if validation fails
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for TypeSelect usage to understand value handling patterns
rg -A 5 "TypeSelect" --type typescript

Length of output: 73


Script:

#!/bin/bash
# Search for TypeSelect usage and implementation with ripgrep
rg -l "TypeSelect"

# Get the content of TypeSelect component
cat designer/client/src/components/graph/node-modal/fragment-input-definition/TypeSelect.tsx

Length of output: 5203

designer/client/cypress/e2e/fragment.cy.ts (1)

161-164: Implementation looks good!

The test case follows the established patterns and successfully verifies the basic functionality of generic type support in fragment input definition.

scenario-compiler/src/test/scala/pl/touk/nussknacker/engine/compile/NodeDataValidatorSpec.scala (2)

1134-1161: LGTM! Well-structured test for valid generic type.

The test case effectively verifies that valid generic types (e.g., Map[String, Double]) are accepted in FragmentInputDefinition parameters. The test structure and assertions are clear and follow the established patterns.


1163-1192: LGTM! Good negative test case for invalid generic type.

The test case properly verifies that invalid generic types (using non-existent types) are rejected with appropriate error messages. The test complements the positive test case and ensures robust type validation.

@Dzuming
Copy link
Contributor

Dzuming commented Nov 27, 2024

@DeamonDev is it a correct Jira number? I can't find it

@DeamonDev
Copy link
Contributor Author

@DeamonDev is it a correct Jira number? I can't find it

No, but it is correct issue number: #7231

@DeamonDev DeamonDev force-pushed the nu-7231-fragment-input-definitions-second-phase branch from 126ced6 to d561de9 Compare November 27, 2024 14:23
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 (1)
designer/client/src/components/graph/node-modal/fragment-input-definition/item/utils.ts (1)

5-9: Add input validation and improve documentation

While the function works for the basic case, it could benefit from better error handling and documentation.

Consider this improved implementation:

-//This projection is used for backward-compatibility reasons, since previously fragment input definition type options display part contained full class name
+/**
+ * Extracts the simple class name from a fully qualified class name.
+ * Used for backward compatibility with legacy fragment input definition type options
+ * that displayed the full class name.
+ * 
+ * @example
+ * resolveSimpleClassName("java.util.List") // returns "List"
+ * 
+ * @param refClazzName - The fully qualified class name
+ * @returns The simple class name
+ * @throws If the input is empty or invalid
+ */
 export function resolveSimpleClassName(refClazzName: string): string {
+    if (!refClazzName?.trim()) {
+        throw new Error("Class name cannot be empty");
+    }
     const parts = refClazzName.split(".");
-    return parts[parts.length - 1];
+    const simpleName = parts[parts.length - 1];
+    if (!simpleName) {
+        throw new Error("Invalid class name format");
+    }
+    return simpleName;
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between d561de9 and d24d8d1.

📒 Files selected for processing (3)
  • designer/client/src/components/graph/node-modal/fragment-input-definition/item/Item.tsx (3 hunks)
  • designer/client/src/components/graph/node-modal/fragment-input-definition/item/types.ts (2 hunks)
  • designer/client/src/components/graph/node-modal/fragment-input-definition/item/utils.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • designer/client/src/components/graph/node-modal/fragment-input-definition/item/Item.tsx
  • designer/client/src/components/graph/node-modal/fragment-input-definition/item/types.ts
🔇 Additional comments (1)
designer/client/src/components/graph/node-modal/fragment-input-definition/item/utils.ts (1)

Line range hint 11-24: Verify the usage of resolveSimpleClassName

Let's verify that the new resolveSimpleClassName function is properly integrated with components consuming these utilities.

✅ Verification successful

Let me gather more specific information about the usage context.


No issues found with resolveSimpleClassName integration

The verification shows that resolveSimpleClassName is properly integrated in the codebase:

  • It's used in isPermittedTypeVariant function which validates parameter types
  • getDefaultFields is correctly consumed by FragmentInputDefinition.tsx which handles the fragment input parameters
  • The type system ensures type safety through the FragmentInputParameter interface
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for usages of resolveSimpleClassName to ensure proper integration
rg -A 3 "resolveSimpleClassName" --type ts --type tsx

# Search for direct usage of refClazzName to ensure we haven't missed any places that should use resolveSimpleClassName
ast-grep --pattern 'refClazzName'

Length of output: 6445


Script:

#!/bin/bash
# Search for files that import and use getDefaultFields
rg -A 5 "getDefaultFields" --type ts

# Search for files that might be using the type information
rg -A 3 "FragmentInputParameter" --type ts

Length of output: 12178

@DeamonDev DeamonDev force-pushed the nu-7231-fragment-input-definitions-second-phase branch 2 times, most recently from c42e24a to 0b7d6b5 Compare November 28, 2024 13:04
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)
designer/client/src/components/graph/node-modal/fragment-input-definition/TypeSelect.tsx (2)

Line range hint 64-102: Enhance type safety and error handling

The implementation could benefit from more robust type handling and explicit fallbacks.

Consider these improvements:

- value={value || ""}
- onChange={(option) => onChange(typeof option === "string" ? "" : option.value)}
+ value={value ?? { value: "", label: "" }}
+ onChange={(option) => {
+   if (!option) {
+     onChange("");
+     return;
+   }
+   onChange(typeof option === "string" ? option : option.value);
+ }}

This change:

  1. Provides a more explicit fallback for the value prop
  2. Handles null/undefined cases in onChange
  3. Preserves string input capability for custom values

Line range hint 102-103: Enhance error feedback accessibility

Consider adding ARIA attributes to improve screen reader feedback for validation errors.

- <ValidationLabels fieldErrors={fieldErrors} />
+ <ValidationLabels 
+   fieldErrors={fieldErrors}
+   aria-live="polite"
+   role="alert"
+ />
scenario-compiler/src/test/scala/pl/touk/nussknacker/engine/compile/NodeDataValidatorSpec.scala (1)

1163-1192: LGTM! Consider adding a clarifying comment.

The test case correctly verifies that invalid generic types are rejected. Consider adding a brief comment explaining that Foo is intentionally used as a non-existent type to test the error handling.

  test(
    "should not allow usage of generic type in FragmentInputDefinition parameter when occurring type is not on classpath"
  ) {
+   // Using 'Foo' as a non-existent type to verify that the validator correctly handles missing types in generic parameters
    val nodeId: String = "in"
    val paramName      = "param1"
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 455def4 and 0b7d6b5.

⛔ Files ignored due to path filters (1)
  • designer/client/cypress/e2e/__image_snapshots__/electron/Linux/Fragment should allow adding input parameters and display used fragment graph in modal #4.png is excluded by !**/*.png
📒 Files selected for processing (7)
  • designer/client/cypress/e2e/fragment.cy.ts (2 hunks)
  • designer/client/src/components/graph/node-modal/fragment-input-definition/TypeSelect.tsx (2 hunks)
  • designer/client/src/components/graph/node-modal/fragment-input-definition/item/Item.tsx (3 hunks)
  • designer/client/src/components/graph/node-modal/fragment-input-definition/item/types.ts (2 hunks)
  • designer/client/src/components/graph/node-modal/fragment-input-definition/item/utils.ts (1 hunks)
  • scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/definition/fragment/FragmentParameterTypingParser.scala (1 hunks)
  • scenario-compiler/src/test/scala/pl/touk/nussknacker/engine/compile/NodeDataValidatorSpec.scala (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
  • designer/client/cypress/e2e/fragment.cy.ts
  • designer/client/src/components/graph/node-modal/fragment-input-definition/item/Item.tsx
  • designer/client/src/components/graph/node-modal/fragment-input-definition/item/types.ts
  • designer/client/src/components/graph/node-modal/fragment-input-definition/item/utils.ts
  • scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/definition/fragment/FragmentParameterTypingParser.scala
🔇 Additional comments (3)
designer/client/src/components/graph/node-modal/fragment-input-definition/TypeSelect.tsx (2)

2-2: LGTM: CreatableSelect import addition

The addition of CreatableSelect is appropriate for enabling user-defined generic types in fragment input definitions.


Line range hint 35-43: Verify all TypeSelect consumers are updated

The change of value prop type from string to Option in RowSelectProps interface is a breaking change that requires updates in all consuming components.

scenario-compiler/src/test/scala/pl/touk/nussknacker/engine/compile/NodeDataValidatorSpec.scala (1)

1134-1161: LGTM! Well-structured test for valid generic type.

The test case effectively verifies that valid generic types like Map[String, Double] are accepted in FragmentInputDefinition parameters.

@DeamonDev DeamonDev force-pushed the nu-7231-fragment-input-definitions-second-phase branch 3 times, most recently from dedef4d to 1e0408d Compare November 29, 2024 09:15
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 (2)
designer/client/src/components/graph/node-modal/fragment-input-definition/TypeSelect.tsx (2)

Line range hint 64-102: Enhance error messaging for custom type validation

The current error handling is good but could be more specific for custom types. Consider adding descriptive error messages when users attempt to create invalid types.

 <CreatableSelect
   ...
+  formatCreateLabel={(inputValue) => {
+    const typePattern = /^(List|Set)\[(String|Boolean|Int)\]$/;
+    if (!typePattern.test(inputValue)) {
+      return `Invalid format. Expected: List[Type] or Set[Type]`;
+    }
+    return `Create type "${inputValue}"`;
+  }}
   ...
 />

Line range hint 1-102: Consider implementing a type registry or validation service

While the current implementation enables generic types, consider implementing a centralized type registry or validation service to:

  1. Maintain consistency in custom type definitions across the application
  2. Provide reusable type validation logic
  3. Enable type suggestions based on existing usage patterns

This could be implemented as a separate service that:

  • Maintains a registry of valid custom types
  • Provides validation rules and type suggestions
  • Ensures consistency across different parts of the application
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between d1036ea and 1e0408d.

⛔ Files ignored due to path filters (1)
  • designer/client/cypress/e2e/__image_snapshots__/electron/Linux/Fragment should allow adding input parameters and display used fragment graph in modal #4.png is excluded by !**/*.png
📒 Files selected for processing (7)
  • designer/client/cypress/e2e/fragment.cy.ts (2 hunks)
  • designer/client/src/components/graph/node-modal/fragment-input-definition/TypeSelect.tsx (2 hunks)
  • designer/client/src/components/graph/node-modal/fragment-input-definition/item/Item.tsx (3 hunks)
  • designer/client/src/components/graph/node-modal/fragment-input-definition/item/types.ts (2 hunks)
  • designer/client/src/components/graph/node-modal/fragment-input-definition/item/utils.ts (1 hunks)
  • scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/definition/fragment/FragmentParameterTypingParser.scala (1 hunks)
  • scenario-compiler/src/test/scala/pl/touk/nussknacker/engine/compile/NodeDataValidatorSpec.scala (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (6)
  • designer/client/cypress/e2e/fragment.cy.ts
  • designer/client/src/components/graph/node-modal/fragment-input-definition/item/Item.tsx
  • designer/client/src/components/graph/node-modal/fragment-input-definition/item/types.ts
  • designer/client/src/components/graph/node-modal/fragment-input-definition/item/utils.ts
  • scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/definition/fragment/FragmentParameterTypingParser.scala
  • scenario-compiler/src/test/scala/pl/touk/nussknacker/engine/compile/NodeDataValidatorSpec.scala
🔇 Additional comments (2)
designer/client/src/components/graph/node-modal/fragment-input-definition/TypeSelect.tsx (2)

2-2: LGTM: Import change aligns with feature requirements

The switch to CreatableSelect is appropriate for enabling user-defined generic types in fragment input definitions.


Line range hint 64-102: Verify type creation behavior and add input validation

While the implementation is generally good, consider these improvements:

  1. The onChange handler returns an empty string when option is a string type. Verify if this is the intended behavior for custom type creation.
  2. Consider adding validation for user-created types to ensure they follow the expected format (e.g., "List[String]").
  3. Add a placeholder or helper text to guide users on the expected format for custom types.

Consider adding type validation:

 <CreatableSelect
   ...
+  formatCreateLabel={(inputValue) => `Create type "${inputValue}"`}
+  isValidNewOption={(inputValue) => {
+    const typePattern = /^(List|Set)\[(String|Boolean|Int)\]$/;
+    return typePattern.test(inputValue);
+  }}
+  placeholder="Select or enter type (e.g., List[String])"
   ...
 />

@DeamonDev DeamonDev force-pushed the nu-7231-fragment-input-definitions-second-phase branch from 1e0408d to e109cb3 Compare November 29, 2024 11:15
Copy link
Contributor

@Dzuming Dzuming left a comment

Choose a reason for hiding this comment

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

LGTM, but merge only if CI is green, or you are sure that it's flaky tests and your code didn't break anything

@DeamonDev DeamonDev merged commit 13e570b into staging Nov 29, 2024
18 checks passed
@DeamonDev DeamonDev deleted the nu-7231-fragment-input-definitions-second-phase branch November 29, 2024 11:55
lciolecki pushed a commit that referenced this pull request Nov 29, 2024
lciolecki pushed a commit that referenced this pull request Dec 3, 2024
lciolecki pushed a commit that referenced this pull request Dec 4, 2024
lciolecki pushed a commit that referenced this pull request Dec 6, 2024
lciolecki pushed a commit that referenced this pull request Dec 10, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
client client main fe ui
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Possibility to type own nested types in fragment input definition
2 participants