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

fix(web): option and tag field validation enhancement #1306

Merged
merged 6 commits into from
Nov 13, 2024

Conversation

caichi-t
Copy link
Contributor

@caichi-t caichi-t commented Nov 12, 2024

Overview

This PR enhances option and tag field validation.

What I've done

  • Showing required mark on form item to set option and tag.
  • Fixing the way to show error input field of option and tag field.

Memo

This PR includes small fixes regarding Reference field creation modal.

Summary by CodeRabbit

Summary by CodeRabbit

Release Notes

  • New Features

    • Enhanced error handling for option and tag fields, displaying specific messages for empty and duplicate entries.
    • Updated UI components to visually indicate error states for input fields and tags.
    • Localization improvements with new translation keys for user prompts and error messages in English and Japanese.
  • Bug Fixes

    • Improved validation logic for form fields, ensuring users receive clear feedback on input requirements.

These updates enhance the overall usability and robustness of the application, particularly in form interactions.

@caichi-t caichi-t requested a review from nourbalaha as a code owner November 12, 2024 08:26
Copy link

coderabbitai bot commented Nov 12, 2024

Walkthrough

The pull request introduces enhancements to various components and test cases within the application, focusing on error handling and validation for user inputs in forms. Key changes include the addition of assertions in test cases to verify error messages for invalid inputs, modifications to components to visually indicate error states, and updates to translation files to support new validation messages. Overall, the changes improve the robustness and user experience of the application by ensuring proper feedback is provided during form interactions.

Changes

File Change Summary
web/e2e/project/item/fields/option.spec.ts Added assertions to test cases for creating/updating option fields to check for error messages when invalid input is provided (e.g., duplicate values, empty values).
web/e2e/project/item/metadata/tag.spec.ts Enhanced test cases for tag metadata creation/editing with new assertions for error handling related to empty and duplicate tag values.
web/src/components/molecules/Common/MultiValueField/MultValueColoredTag/index.tsx Introduced errorIndexes prop to indicate error states visually in the StyledInput and StyledTagContainer.
web/src/components/molecules/Common/MultiValueField/index.tsx Added errorIndexes prop to manage error states for specific input fields.
web/src/components/molecules/Schema/FieldModal/FieldCreationModalWithSteps/index.tsx Changed selectedType prop type to accept only "Reference" and removed conditional rendering for "Select" options.
web/src/components/molecules/Schema/FieldModal/hooks.ts Simplified handleFieldKeyUnique function, enhanced validation logic with new state variables for empty and duplicated entries, and added new validation functions.
web/src/components/molecules/Schema/FieldModal/index.tsx Updated validation logic for form fields, added errorIndexes prop to related components, and improved feedback mechanisms for users.
web/src/components/molecules/Schema/types.ts Changed Tag type to be exported for broader usability across modules.
web/src/components/organisms/Project/Schema/hooks.ts Modified keyUniqueCheck function to incorporate conditional logic based on isMeta state for flexible field handling.
web/src/i18n/translations/en.yml Added new translation keys for validation messages related to form inputs.
web/src/i18n/translations/ja.yml Added new translation entries and updated existing ones for clarity in user feedback regarding form inputs.
web/src/components/atoms/Input/index.tsx Modified Input component to include status prop in destructuring and introduced new logic for determining input status based on maxLength and external status.
web/src/components/molecules/Schema/FieldModal/FieldDefaultInputs/URLField/index.tsx Updated label text for localization in URLField component while retaining existing validation logic.

Possibly related PRs

Suggested reviewers

  • nourbalaha

🐰 "In the fields where options play,
Error messages now lead the way.
With tags and inputs, clear and bright,
Validation shines, a guiding light.
Hop along, let forms be free,
With feedback clear, for you and me!" 🐇

Warning

Rate limit exceeded

@caichi-t has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 21 minutes and 37 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 6198b11 and 60a2340.


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 6198b11 and 60a2340.

📒 Files selected for processing (3)
  • web/src/components/organisms/Project/Schema/hooks.ts (1 hunks)
  • web/src/i18n/translations/en.yml (1 hunks)
  • web/src/i18n/translations/ja.yml (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • web/src/components/organisms/Project/Schema/hooks.ts
  • web/src/i18n/translations/en.yml
🔇 Additional comments (2)
web/src/i18n/translations/ja.yml (2)

350-353: LGTM! Clear and consistent option field validation messages.

The translations for option field validation messages are clear, accurate, and follow consistent Japanese language conventions.


355-356: LGTM! Clear and consistent tag field validation messages.

The translations for tag field validation messages maintain consistency with the option field messages and provide clear user feedback.


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.

@github-actions github-actions bot added the web label Nov 12, 2024
Copy link

netlify bot commented Nov 12, 2024

Deploy Preview for reearth-cms ready!

Name Link
🔨 Latest commit 60a2340
🔍 Latest deploy log https://app.netlify.com/sites/reearth-cms/deploys/67342b9347ed19000882f628
😎 Deploy Preview https://deploy-preview-1306--reearth-cms.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

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

🧹 Outside diff range and nitpick comments (15)
web/src/components/molecules/Common/MultiValueField/index.tsx (2)

96-96: Consider enhancing accessibility and error feedback.

While the error status implementation is functional, consider these improvements for better accessibility and user experience:

  1. Add aria-invalid attribute for screen readers
  2. Implement error message display mechanism
 <FieldInput
   style={{ flex: 1 }}
   {...props}
   onChange={(e: ChangeEvent<HTMLInputElement>) => handleInput(e, key)}
   onBlur={() => onBlur?.()}
   value={valueItem}
-  status={errorIndexes?.has(key) ? "error" : undefined}
+  status={errorIndexes?.has(key) ? "error" : undefined}
+  aria-invalid={errorIndexes?.has(key)}
+  aria-errormessage={errorIndexes?.has(key) ? `field-error-${key}` : undefined}

Line range hint 24-31: Consider memoizing the component for better performance.

Since this component handles multiple inputs and array operations, it could benefit from memoization to prevent unnecessary re-renders, especially when used in a list of form fields.

-const MultiValueField: React.FC<Props> = ({
+const MultiValueField: React.FC<Props> = React.memo(({
   value = [],
   onChange,
   onBlur,
   FieldInput,
   errorIndexes,
   ...props
-}) => {
+}) => {
   // ... component implementation
-};
+});
web/src/components/molecules/Common/MultiValueField/MultValueColoredTag/index.tsx (3)

149-149: Consider adding error tooltip for better UX

While the error state is correctly implemented, consider adding a tooltip or helper text to explain why the field is in an error state.

 <StyledInput
   {...props}
   onChange={(e: ChangeEvent<HTMLInputElement>) => handleInput(e, key)}
   value={valueItem.name}
   onBlur={() => handleInputBlur()}
-  status={errorIndexes?.has(key) ? "error" : undefined}
+  status={errorIndexes?.has(key) ? "error" : undefined}
+  title={errorIndexes?.has(key) ? t("Please enter a valid tag name") : undefined}
 />

154-155: Enhance accessibility for tag interaction

While the click handling works, consider adding keyboard accessibility for better user experience.

 <StyledTagContainer
   hidden={focusedTagIndex === key}
-  onClick={() => handleTagClick(key)}
+  onClick={() => handleTagClick(key)}
+  onKeyDown={(e) => e.key === 'Enter' && handleTagClick(key)}
+  role="button"
+  tabIndex={0}
   isError={errorIndexes?.has(key)}>

199-201: Consider using theme tokens for colors

The hardcoded color values could be moved to theme tokens for better maintainability and consistency.

 const StyledTagContainer = styled.div<{ isError?: boolean }>`
   cursor: pointer;
-  border: 1px solid ${({ isError }) => (isError ? "#ff4d4f" : "#d9d9d9")};
+  border: 1px solid ${({ isError, theme }) => (isError ? theme.colors.error : theme.colors.border)};
   padding: 4px 11px;
web/e2e/project/item/metadata/tag.spec.ts (1)

33-35: LGTM: Good duplicate tag validation test with room for enhancement

The test effectively validates duplicate tag handling. Consider enhancing it by also verifying that the error state is cleared and the OK button becomes enabled when a valid, non-duplicate value is entered after the error.

Add these assertions after line 35:

  await expect(page.getByText("Labels must be unique")).toBeVisible();
  await expect(page.getByRole("button", { name: "OK" })).toBeDisabled();
+ await page.locator("#tags").nth(1).fill("UniqueTag");
+ await expect(page.getByText("Labels must be unique")).not.toBeVisible();
+ await expect(page.getByRole("button", { name: "OK" })).toBeEnabled();
web/e2e/project/item/fields/option.spec.ts (3)

28-29: LGTM! Consider enhancing test coverage.

Good addition of assertions to verify empty value validation. The test properly checks both the error message visibility and the disabled state of the OK button.

Consider adding test cases for:

  • Whitespace-only values
  • Values with special characters

31-33: LGTM! Consider case sensitivity testing.

Good addition of assertions to verify duplicate value validation. The test properly checks both the error message visibility and the disabled state of the OK button.

Consider adding test cases for:

  • Case-sensitive duplicates (e.g., "First" vs "first")
  • Duplicates with leading/trailing spaces

Line range hint 1-186: Well-structured test file with good coverage.

The test file demonstrates good practices:

  • Clear test organization with setup/teardown
  • Comprehensive coverage of field operations
  • Good mix of positive and negative test cases

Consider organizing the validation-related test cases into a separate test block for better maintainability, e.g.:

test("Option field validation shows appropriate error messages", async ({ page }) => {
  // Setup code...
  
  // Test empty values
  await page.getByRole("button", { name: "plus New" }).click();
  await expect(page.getByText("Empty values are not allowed")).toBeVisible();
  await expect(page.getByRole("button", { name: "OK" })).toBeDisabled();
  
  // Test duplicates
  await page.locator("#values").nth(0).fill("first");
  await page.locator("#values").nth(1).fill("first");
  await expect(page.getByText("Option must be unique")).toBeVisible();
  await expect(page.getByRole("button", { name: "OK" })).toBeDisabled();
  
  // Additional validation cases...
});
web/src/components/molecules/Schema/FieldModal/hooks.ts (2)

238-242: Simplify validation conditions

The nested validation conditions could be flattened for better readability and maintainability.

-      if (
-        form.getFieldValue("values")?.length === 0 ||
-        form.getFieldValue("supportedTypes")?.length === 0 ||
-        form.getFieldValue("tags")?.length === 0
-      ) {
-        setButtonDisabled(true);
-      } else {
-        form
-          .validateFields()
-          .then(() => setButtonDisabled(changedKeys.current.size === 0))
-          .catch(() => setButtonDisabled(true));
-      }
+      const hasEmptyArrays = [
+        form.getFieldValue("values"),
+        form.getFieldValue("supportedTypes"),
+        form.getFieldValue("tags")
+      ].some(array => array?.length === 0);
+      
+      if (hasEmptyArrays) {
+        setButtonDisabled(true);
+        return;
+      }
+      
+      form
+        .validateFields()
+        .then(() => setButtonDisabled(changedKeys.current.size === 0))
+        .catch(() => setButtonDisabled(true));

383-416: LGTM! Comprehensive validation implementation with a minor type safety suggestion

The validation implementation effectively handles both empty and duplicate value checks. Consider adding type safety for the array indices.

-        .map((value: string, index: number) => value.length === 0 && index)
-        .filter(value => typeof value === "number");
+        .map((value: string, index: number): number | false => 
+          value.length === 0 ? index : false)
+        .filter((value): value is number => value !== false);
web/src/components/molecules/Schema/FieldModal/index.tsx (1)

251-262: Optimize tag validation logic

The current implementation extracts names multiple times. Consider simplifying the validation logic.

-validator: async (_, values?: Tag[]) => {
-  const names = values?.map(value => value.name);
-  return emptyValidator(names);
-},
+validator: async (_, values?: Tag[]) => 
+  emptyValidator(values?.map(value => value.name)),

-validator: async (_, values?: Tag[]) => {
-  const names = values?.map(value => value.name);
-  return duplicatedValidator(names);
-},
+validator: async (_, values?: Tag[]) => 
+  duplicatedValidator(values?.map(value => value.name)),
web/src/i18n/translations/en.yml (1)

347-348: Consider consistent terminology for tag-related messages

While the messages are clear, consider using consistent terminology. The error message uses "Labels" while the feature is referred to as "tags" elsewhere. Consider changing "Labels must be unique" to "Tags must be unique" for consistency.

-Labels must be unique: ''
+Tags must be unique: ''
web/src/components/organisms/Project/Schema/hooks.ts (1)

137-144: Consider adding type annotations for better type safety

The function logic is correct and handles both metadata and regular schema fields appropriately. Consider adding TypeScript type annotations to improve type safety:

  const keyUniqueCheck = useCallback(
-   (key: string, fieldId?: string, model?: Model) => {
+   (key: string, fieldId?: string, model?: Model): boolean => {
      const schema = isMeta ? model?.metadataSchema : model?.schema;
      const sameKeyField = schema?.fields?.find(field => field.key === key);
      return !sameKeyField || sameKeyField.id === fieldId;
    },
    [isMeta],
  );
web/src/components/molecules/Schema/FieldModal/FieldCreationModalWithSteps/index.tsx (1)

Line range hint 196-202: Consider refactoring the requiredMark function for better reusability

The requiredMark function is used across multiple Form components. Consider these improvements:

  1. Move it to a shared utility file to avoid duplication
  2. Make the isShow parameter's default value consistent across all Form components
- const requiredMark = (
-   label: React.ReactNode,
-   { required }: { required: boolean },
-   isShow = true,
- ) => (
-   <>
-     {required && <Required>*</Required>}
-     {label}
-     {isShow && !required && <Optional>{`(${t("optional")})`}</Optional>}
-   </>
- );

Create a new file web/src/components/molecules/Common/Form/RequiredMark.tsx:

import { useT } from "@reearth-cms/i18n";

interface RequiredMarkProps {
  label: React.ReactNode;
  required: boolean;
  showOptional?: boolean;
}

export const RequiredMark: React.FC<RequiredMarkProps> = ({ 
  label, 
  required, 
  showOptional = true 
}) => {
  const t = useT();
  return (
    <>
      {required && <Required>*</Required>}
      {label}
      {showOptional && !required && <Optional>{`(${t("optional")})`}</Optional>}
    </>
  );
};
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 4c24a9c and 3d9b7ee.

📒 Files selected for processing (11)
  • web/e2e/project/item/fields/option.spec.ts (1 hunks)
  • web/e2e/project/item/metadata/tag.spec.ts (1 hunks)
  • web/src/components/molecules/Common/MultiValueField/MultValueColoredTag/index.tsx (3 hunks)
  • web/src/components/molecules/Common/MultiValueField/index.tsx (3 hunks)
  • web/src/components/molecules/Schema/FieldModal/FieldCreationModalWithSteps/index.tsx (1 hunks)
  • web/src/components/molecules/Schema/FieldModal/hooks.ts (6 hunks)
  • web/src/components/molecules/Schema/FieldModal/index.tsx (4 hunks)
  • web/src/components/molecules/Schema/types.ts (1 hunks)
  • web/src/components/organisms/Project/Schema/hooks.ts (1 hunks)
  • web/src/i18n/translations/en.yml (1 hunks)
  • web/src/i18n/translations/ja.yml (1 hunks)
🔇 Additional comments (15)
web/src/components/molecules/Schema/types.ts (1)

Line range hint 46-50: LGTM! The Tag type export enhances type safety across components.

The export of the Tag type is a good improvement that enables proper type checking for tag-related validations across the application. The type structure with id, name, and color fields is well-defined.

Let's verify the usage of this exported type:

✅ Verification successful

Based on the search results, I can now provide a final response since I have gathered sufficient evidence about the Tag type usage across the codebase:

The Tag type export is being used correctly and serves as a crucial shared type definition.

The exported Tag type is actively used throughout the codebase:

  • In form validation components (FieldModal, TagField)
  • In schema field type definitions and GraphQL types
  • In content rendering components (RenderField, MultiValueColoredTag)
  • In form field components for tag input/display

The type export enables proper type checking and consistent tag handling across these components, making it a well-justified change.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check how the Tag type is being imported and used across the codebase
# Expected: Find imports of the Tag type in form validation components

# Search for Tag type imports
rg -t typescript "import.*Tag.*from.*Schema/types"

# Search for Tag type usage in validation logic
ast-grep --pattern 'const $_ = ($x: Tag)'

Length of output: 131


Script:

#!/bin/bash
# Let's try different approaches to find Tag type usage

# Search for imports from Schema/types
rg "import.*from ['\"].*Schema/types['\"]" --type ts

# Search for Tag type usage in type annotations
rg ":\s*Tag[\[\]\s{},]" --type ts

# Search for files that might use Tag
rg "Tag" --type ts -C 2

# Find all TypeScript files in the web directory
fd "\.tsx?$" web/src

Length of output: 125664

web/src/components/molecules/Common/MultiValueField/index.tsx (2)

19-19: LGTM! Well-typed error tracking implementation.

The Set<number> type is an efficient choice for tracking error states with O(1) lookup performance.


28-28: LGTM! Clean prop destructuring.

The errorIndexes prop is properly destructured following the component's existing patterns.

web/src/components/molecules/Common/MultiValueField/MultValueColoredTag/index.tsx (3)

33-33: LGTM: Efficient error tracking with Set

The use of Set<number> for errorIndexes is an excellent choice, providing efficient O(1) lookups for error state checking.


37-42: LGTM: Clean component signature update

The component signature is well-structured with proper prop destructuring and defaults.


37-42: Verify error handling edge cases

Let's ensure the error handling works correctly in all scenarios.

✅ Verification successful

Let me gather more information about the error handling in the MultiValueColoredTag component by checking its test files and related components.


Based on the code analysis, I can now provide a final response about the error handling in the MultiValueColoredTag component.

Error handling implementation is appropriate

The error handling in MultiValueColoredTag is well-implemented:

  • The component properly accepts an errorIndexes prop of type Set<number> to track which tags have errors
  • Error states are correctly applied in two places:
    • Input field: status={errorIndexes?.has(key) ? "error" : undefined}
    • Tag container: isError={errorIndexes?.has(key)}
  • The error handling is consistent with the parent MultiValueField component's pattern
  • The implementation is used appropriately in the FieldModal component where errors are tracked for empty and duplicate values

The error handling approach using a Set of indexes is an efficient way to mark multiple erroneous fields, and the visual feedback is properly implemented through the status prop and isError styling.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for comprehensive error handling test coverage

# Look for test files related to this component
fd -e test.tsx -e spec.tsx -e test.ts -e spec.ts . | grep -i "MultiValueColoredTag"

# Check for error handling test cases
rg -A 5 "test|describe|it" $(fd -e test.tsx -e spec.tsx -e test.ts -e spec.ts . | grep -i "MultiValueColoredTag") | grep -i "error"

Length of output: 459890


Script:

#!/bin/bash
# Search for test files related to MultiValueColoredTag
fd -e test.tsx -e spec.tsx . | grep -i "MultiValueColoredTag"

# Search for error handling tests in MultiValueColoredTag and related components
rg -A 5 "errorIndexes" web/src/components/molecules/Common/MultiValueField/

# Check usage of errorIndexes prop
rg -A 5 "errorIndexes" web/src/components/

Length of output: 11771

web/e2e/project/item/metadata/tag.spec.ts (1)

30-32: LGTM: Well-structured empty tag validation test

The test properly validates empty tag handling by checking both the error message visibility and button disabled state.

web/src/components/molecules/Schema/FieldModal/hooks.ts (4)

256-271: LGTM! Robust change detection implementation

The implementation correctly handles both array and primitive value comparisons, with proper sorting for arrays to ensure consistent comparison regardless of order.


326-334: LGTM! Well-structured validation chain

The key validation implementation effectively combines syntax validation (validateKey) with uniqueness check (handleFieldKeyUnique), while caching results for better performance.


371-378: LGTM! Comprehensive field initialization

The initialization logic properly handles all field types, ensuring arrays are initialized correctly when creating new fields.


30-30: Verify the removal of fieldId parameter's impact

The handleFieldKeyUnique function signature has been simplified to remove the optional fieldId parameter. While this makes the API cleaner, we should ensure this doesn't affect field key validation when editing existing fields.

✅ Verification successful

No impact from removing fieldId parameter

The implementation of handleFieldKeyUnique in Project/Schema/hooks.ts already handles the field ID context internally through the selectedField?.id dependency in its useCallback hook. The function is correctly implemented to consider the current field's ID during uniqueness validation, making the parameter removal in the interface safe and appropriate.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for usages of handleFieldKeyUnique to verify if fieldId was used
rg "handleFieldKeyUnique.*fieldId" -A 2

Length of output: 41


Script:

#!/bin/bash
# Let's first find all usages of handleFieldKeyUnique
rg "handleFieldKeyUnique" -A 3

# Also search for the implementation
ast-grep --pattern 'const handleFieldKeyUnique = $_'

Length of output: 6582

web/src/components/molecules/Schema/FieldModal/index.tsx (1)

27-27: LGTM: Type-level improvements enhance type safety

The changes improve type safety by adding the Tag type and simplifying the handleFieldKeyUnique prop signature.

Also applies to: 41-41

web/src/i18n/translations/en.yml (1)

342-345: LGTM: Option field validation messages are clear and consistent

The new translation keys for option field validation follow the established pattern and provide clear error messages.

web/src/components/organisms/Project/Schema/hooks.ts (1)

137-144: Verify the usage in field validation contexts

Let's verify how this function is used in field validation contexts, particularly for option and tag fields mentioned in the PR objectives.

✅ Verification successful

Let me gather more specific information about how this function is used.


Let me gather one more piece of information to specifically check for Option and Tag field types.


Based on the gathered information, I can now provide the final response:

The keyUniqueCheck function is correctly implemented for field validation

The function is properly used in the schema management context:

  • It's used in field key validation through handleFieldKeyUnique and handleCorrespondingFieldKeyUnique
  • The validation system includes both Option and Tag fields, with proper type checking
  • The function correctly handles both regular schema and metadata schema fields through the isMeta flag
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check how keyUniqueCheck is used in field validation contexts

# Search for files that import and use keyUniqueCheck
rg -l "keyUniqueCheck|handleFieldKeyUnique|handleCorrespondingFieldKeyUnique" --type ts

# Search for option and tag field validation logic
rg -A 5 "type.*[\"'](?:Option|Tag)[\"'].*=.*{" --type ts

# Search for field validation components that might use this function
ast-grep --pattern 'const $_ = $$$; $_?.type === "Option" || $_?.type === "Tag"'

Length of output: 672


Script:

#!/bin/bash
# Check the actual usage of keyUniqueCheck in the identified files
rg -A 5 "keyUniqueCheck" web/src/components/organisms/Project/Schema/hooks.ts web/src/components/organisms/Project/Schema/index.tsx web/src/components/molecules/Schema/FieldModal/hooks.ts web/src/components/molecules/Schema/FieldModal/index.tsx web/src/components/molecules/Schema/FieldModal/FieldCreationModalWithSteps/index.tsx

# Look for field validation related code in these files
rg -A 5 "validateField|validation" web/src/components/molecules/Schema/FieldModal/hooks.ts web/src/components/molecules/Schema/FieldModal/index.tsx

# Check for type definitions and interfaces related to field validation
rg -A 3 "interface.*Field|type.*Field" web/src/components/molecules/Schema/FieldModal/

Length of output: 8975


Script:

#!/bin/bash
# Check for Option and Tag field type handling
rg -B 2 -A 5 "type === [\"'](?:Option|Tag)[\"']" web/src/components/organisms/Project/Schema/ web/src/components/molecules/Schema/

# Check the field validation component
rg -B 2 -A 5 "FieldValidationInputs" web/src/components/molecules/Schema/

Length of output: 4012

web/src/i18n/translations/ja.yml (1)

342-345: LGTM! The translations for option and tag field validation messages are well-structured.

The Japanese translations are clear, concise, and effectively convey the validation requirements:

  • Option field validations (最低一つのオプション, 空の値, 一意である)
  • Tag field validations (最低一つのタグ, 一意である)

Also applies to: 347-348

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)
web/src/components/atoms/Input/index.tsx (1)

12-18: Consider enhancing status computation logic

While the current implementation works, there are opportunities for improvement:

  1. The error status completely overrides external status. Consider preserving external error states even when length is valid.
  2. The computation could be more efficient by checking conditions earlier.

Consider this alternative implementation:

  const _status = useMemo(() => {
+   if (!maxLength || !value) return status;
+   return runes(value).length > maxLength ? "error" : status;
-   if (maxLength && value && runes(value).length > maxLength) {
-     return "error";
-   } else {
-     return status;
-   }
  }, [maxLength, status, value]);
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 3d9b7ee and 3be14c6.

📒 Files selected for processing (1)
  • web/src/components/atoms/Input/index.tsx (2 hunks)
🔇 Additional comments (3)
web/src/components/atoms/Input/index.tsx (3)

11-11: LGTM: Clean signature update

The addition of the status prop maintains type safety while enabling external status control.


Line range hint 1-34: Verify integration with form validation system

The component handles individual input validation well, but we should ensure it integrates properly with the form-level validation system.

#!/bin/bash
# Check for form validation integration patterns
ast-grep --pattern 'const $form = useForm($$$)' 
rg -A 5 'validateFields|validateStatus|onFieldsChange'

28-28: Verify error state styling

The status prop is correctly applied, but we should verify that error states are visually distinct and meet accessibility standards.

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)
web/src/components/atoms/Input/index.tsx (1)

12-17: Implementation looks good with room for enhancement

The error handling logic is correctly implemented, but consider enhancing it to distinguish between different types of errors.

Consider this enhancement to provide more granular error handling:

-const status = useMemo(() => {
-  if (isError || (maxLength && value && runes(value).length > maxLength)) {
-    return "error";
-  }
-}, [isError, maxLength, value]);
+const status = useMemo(() => {
+  if (isError) return "error";
+  if (maxLength && value && runes(value).length > maxLength) return "warning";
+  return undefined;
+}, [isError, maxLength, value]);

This would allow:

  • "error" status for validation errors (isError)
  • "warning" status for length violations
  • Better visual distinction between different types of issues
web/src/components/molecules/Schema/FieldModal/FieldDefaultInputs/URLField/index.tsx (4)

18-19: Consider emphasizing HTTPS usage in the help text

While the help text correctly indicates URL format requirements, consider encouraging secure practices by recommending HTTPS over HTTP.

-      extra={t("Default value must be a valid URL and start with 'http://' or 'https://'.")}
+      extra={t("Default value must be a valid URL and start with 'https://' (recommended) or 'http://'.")}

Line range hint 20-35: Enhance validation implementation

Several improvements could make the validation more robust and user-friendly:

  1. The error message should be translated
  2. Empty string handling could be more explicit
  3. URL validation could be strengthened
       rules={[
         {
-          message: "URL is not valid",
+          message: t("URL is not valid"),
           validator: async (_, value) => {
             if (value) {
+              const validateValue = (url: string) => {
+                if (!url.trim()) return true; // Skip empty strings
+                return validateURL(url);
+              };
+
               if (
                 multiple &&
-                value.some((valueItem: string) => !validateURL(valueItem) && valueItem.length > 0)
+                value.some((valueItem: string) => !validateValue(valueItem))
               )
                 return Promise.reject();
-              else if (!multiple && !validateURL(value) && value?.length > 0)
+              else if (!multiple && !validateValue(value))
                 return Promise.reject();
             }
             return Promise.resolve();
           },
         },
       ]}>

Line range hint 36-37: Improve accessibility and error handling

Consider enhancing the input components with better accessibility support and more specific error states.

-      {multiple ? <MultiValueField FieldInput={Input} /> : <Input />}
+      {multiple ? (
+        <MultiValueField
+          FieldInput={Input}
+          aria-label={t("Multiple URL input field")}
+          data-testid="url-input-multiple"
+        />
+      ) : (
+        <Input
+          aria-label={t("URL input field")}
+          data-testid="url-input-single"
+        />
+      )}

Inconsistent use of internationalization in validation messages

  • The URLField component uses a hard-coded validation message instead of the t function.
🔗 Analysis chain

Line range hint 1-42: Verify integration with form validation enhancements

Since this PR focuses on validation enhancement, let's verify how this component integrates with other form components and their error handling patterns.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for consistent validation patterns across form components
echo "Checking validation patterns in form components..."
rg -l "Form\.Item.*rules=\[" "web/src/components" | while read -r file; do
  echo "=== $file ==="
  rg "Form\.Item.*rules=\[" "$file" -A 5
done

# Check for consistent error message handling
echo "Checking error message patterns..."
rg "message: t\(" "web/src/components"

Length of output: 27397

web/src/components/molecules/Schema/FieldModal/FieldCreationModalWithSteps/index.tsx (3)

Line range hint 532-550: Enhance field key validation feedback

The validation implementation is good but could be improved:

  1. Consider making the error message more specific by indicating which validation rule failed (format, uniqueness, etc.)
  2. Consider memoizing the validation function to prevent unnecessary recreations
 rules={[
   {
-    message: t("Key is not valid"),
+    message: ({ pattern, required }) =>
+      required ? t("Field key is required") :
+      !pattern ? t("Field key can only contain letters, numbers, underscores and dashes") :
+      t("Field key must be unique"),
     required: true,
     validator: async (_, value) => {
       await keyValidate(
         value,
         prevCorrespondingKey,
         handleCorrespondingFieldKeyUnique,
       );
     },
   },
 ]}

Line range hint 532-550: Consider enhancing validation error visibility

The current implementation could benefit from improved error state visibility:

  1. Consider adding a visual indicator on the "Validation" tab when there are validation errors
  2. Consider adding an error summary at the top of the form when there are multiple validation errors

Line range hint 1-650: Consider refactoring for better maintainability

The component is quite large and handles multiple responsibilities. Consider:

  1. Extracting the form validation logic into a custom hook (e.g., useFieldValidation)
  2. Breaking down the component into smaller, focused components:
    • ReferenceSettingStep
    • FieldSettingStep
    • CorrespondingFieldStep
  3. Moving form-related callbacks into a custom hook (e.g., useFieldForm)

This would improve maintainability, testability, and reusability.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 3be14c6 and b084419.

📒 Files selected for processing (4)
  • web/src/components/atoms/Input/index.tsx (1 hunks)
  • web/src/components/molecules/Common/MultiValueField/index.tsx (3 hunks)
  • web/src/components/molecules/Schema/FieldModal/FieldCreationModalWithSteps/index.tsx (2 hunks)
  • web/src/components/molecules/Schema/FieldModal/FieldDefaultInputs/URLField/index.tsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • web/src/components/molecules/Common/MultiValueField/index.tsx
🔇 Additional comments (3)
web/src/components/atoms/Input/index.tsx (2)

9-9: LGTM: Type definition is well-structured

The isError prop is correctly typed as an optional boolean, following TypeScript best practices.


Line range hint 1-31: Verify consistent error handling patterns

Let's ensure this error handling pattern is consistently applied across related components.

✅ Verification successful

✅ Error handling is consistently applied across related components.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for consistent error handling patterns in related components

# Look for similar Input components that might need the same error handling
ast-grep --pattern 'const $_ = forwardRef<$_, $_>(' 

# Check for other uses of antd Input to ensure consistent error handling
rg -l "from 'antd'.*Input" | xargs rg "status.*=.*error"

Length of output: 270

web/src/components/molecules/Schema/FieldModal/FieldCreationModalWithSteps/index.tsx (1)

33-33: ⚠️ Potential issue

Verify the restriction of selectedType to "Reference"

The prop type has been restricted to only accept "Reference", which seems to contradict:

  1. The PR objectives mentioning "option and tag field validation"
  2. The component name suggesting it handles multiple field types
  3. The presence of field type selection logic in the component

Consider keeping the generic FieldType type to maintain support for all field types.

✅ Verification successful

Restriction of selectedType to "Reference" Verified

No usages of selectedType with types other than "Reference" found.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for other field type usages
rg -A 2 "selectedType.*=.*['\"](?!Reference)[^'\"]+['\"]" --type ts

Length of output: 344


Script:

#!/bin/bash
# Check for other field type usages with PCRE2 enabled
rg --pcre2 -A 2 'selectedType\s*:\s*"(?!Reference")[^"]+"' --type ts

Length of output: 70

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants