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

feat: add functionality to handle user inputs (part 1) #268

Merged
merged 16 commits into from
Dec 19, 2024
Merged

Conversation

RohitR311
Copy link
Collaborator

@RohitR311 RohitR311 commented Dec 18, 2024

Adding functionality to handle different user inputs:

  1. Date Fields
  2. Dropdowns
  3. Range
  4. Time
  5. Checkboxes
  6. Radios
  7. Drag and Drop

closes: #159

Copy link

coderabbitai bot commented Dec 18, 2024

Caution

Review failed

The pull request is closed.

Walkthrough

This pull request introduces enhanced functionalities for handling date, dropdown, and time selection events across multiple components. It includes the addition of new functions and interfaces for managing these events on the server side, as well as the creation of React components for user interaction. The implementation facilitates dynamic interactions through socket-based communication, ensuring proper event handling and state management for date and time inputs.

Changes

File Change Summary
server/src/types/index.ts Added DatePickerEventData interface with coordinates, selector, and value properties
server/src/browser-management/inputHandlers.ts Added functions for handling date, dropdown, and time selection events; registered new socket event listeners for "input:date", "input:dropdown", and "input:time"
server/src/workflow-management/classes/Generator.ts Added methods for handling date, dropdown, and time selections; modified onClick to emit events for these inputs
src/components/atoms/DatePicker.tsx Created new DatePicker React component for date selection with socket event emission
src/components/atoms/Dropdown.tsx Created new Dropdown React component for dropdown selection with socket event emission
src/components/atoms/TimePicker.tsx Created new TimePicker React component for time selection with socket event emission
src/components/atoms/canvas.tsx Added state variables and socket listeners for managing DatePicker, Dropdown, and TimePicker components

Sequence Diagram

sequenceDiagram
    participant Client
    participant Canvas
    participant Socket
    participant Server
    participant WorkflowGenerator
    participant Browser

    Client->>Canvas: Trigger Date Selection
    Canvas->>Socket: Emit showDatePicker
    Socket->>Server: Broadcast Event
    Server->>WorkflowGenerator: Trigger onClick
    WorkflowGenerator->>Browser: Show Date Picker
    Client->>DatePicker: Select Date
    DatePicker->>Socket: Emit input:date
    Socket->>Server: Send Date Event
    Server->>WorkflowGenerator: onDateSelection
    WorkflowGenerator->>Browser: Fill Date Input
Loading

Possibly related PRs

Poem

🐰 A rabbit's tale of dates so bright,
Clicking, picking with pure delight!
Sockets dance, events take flight,
From client's click to browser's might,
Date and time, a joyous sight! 📅✨

Tip

CodeRabbit's docstrings feature is now available as part of our Early Access Program! Simply use the command @coderabbitai generate docstrings to have CodeRabbit automatically generate docstrings for your pull request. We would love to hear your feedback on Discord.


📜 Recent review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 2e30192 and a97837d.

📒 Files selected for processing (5)
  • server/src/browser-management/inputHandlers.ts (3 hunks)
  • server/src/workflow-management/classes/Generator.ts (3 hunks)
  • src/components/atoms/Dropdown.tsx (1 hunks)
  • src/components/atoms/TimePicker.tsx (1 hunks)
  • src/components/atoms/canvas.tsx (4 hunks)

🪧 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. (Beta)
  • @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.

@RohitR311 RohitR311 marked this pull request as draft December 18, 2024 14:44
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: 4

🧹 Nitpick comments (5)
server/src/types/index.ts (1)

27-31: Consider using a more specific type for the value property

The value property could benefit from a more specific type to ensure date string format consistency.

export interface DatePickerEventData {
    coordinates: Coordinates;
    selector: string;
-    value: string;
+    value: `${number}-${number}-${number}`; // YYYY-MM-DD format
}
src/components/atoms/DatePicker.tsx (1)

29-41: Consider handling window boundaries for positioning

The absolute positioning might cause the date picker to render outside viewport bounds.

  <div 
    style={{
      position: 'absolute',
      left: `${coordinates.x}px`,
      top: `${coordinates.y}px`,
      zIndex: 1000,
      backgroundColor: 'white',
      boxShadow: '0 2px 10px rgba(0,0,0,0.1)',
      padding: '10px',
-     borderRadius: '4px'
+     borderRadius: '4px',
+     maxWidth: '300px',
+     maxHeight: '400px',
+     overflow: 'auto'
    }}
+   role="dialog"
+   aria-modal="true"
  >
server/src/browser-management/inputHandlers.ts (2)

226-241: Consider enhancing error handling in handleDateSelection.

The implementation follows the established patterns and is well-documented. However, the error handling could be improved by:

  1. Using the logger instead of console.error
  2. Propagating the error to allow proper handling upstream
 const handleDateSelection = async (generator: WorkflowGenerator, page: Page, data: DatePickerEventData) => {
     const { selector, value } = data;
 
     try {
         await page.fill(selector, value);
     } catch (error) {
-        console.error("Failed to fill date value:", error);
+        logger.log('error', `Failed to fill date value: ${error}`);
+        throw error;
     }
     
     const pair: WhereWhatPair = {
         where: { url: this.getBestUrl(page.url()) },
         what: [{
             action: 'fill',
             args: [selector, value],
         }],
     };
 
     await this.addPairToWorkflowAndNotifyClient(pair, page);
 };

Line range hint 289-302: Consider using type predicates for better type safety.

The implementation correctly handles date input detection and event emission. However, the type checking could be more explicit using TypeScript type predicates.

-    const isDateInput = await page.evaluate(({x, y}) => {
-      const element = document.elementFromPoint(x, y);
-      return element instanceof HTMLInputElement && element.type === 'date';
-    }, coordinates);
+    const isDateInput = await page.evaluate(({x, y}): boolean => {
+      const element = document.elementFromPoint(x, y);
+      function isDateInputElement(el: Element | null): el is HTMLInputElement {
+        return el instanceof HTMLInputElement && el.type === 'date';
+      }
+      return isDateInputElement(element);
+    }, coordinates);
server/src/workflow-management/classes/Generator.ts (1)

258-276: Consider adding retry logic for resilience.

The implementation is solid but could benefit from retry logic for intermittent failures during date filling operations, which are common in browser automation.

 public onDateSelection = async (page: Page, data: DatePickerEventData) => {
     const { selector, value } = data;
 
+    const maxRetries = 3;
+    let lastError: Error | null = null;
+
+    for (let attempt = 1; attempt <= maxRetries; attempt++) {
         try {
             await page.fill(selector, value);
+            break;
         } catch (error) {
-            console.error("Failed to fill date value:", error);
+            lastError = error as Error;
+            logger.log('warn', `Failed to fill date value (attempt ${attempt}/${maxRetries}): ${error}`);
+            if (attempt === maxRetries) {
+                logger.log('error', `All attempts to fill date value failed: ${error}`);
+                throw lastError;
+            }
+            await page.waitForTimeout(1000 * attempt); // Exponential backoff
         }
     }
     
     const pair: WhereWhatPair = {
         where: { url: this.getBestUrl(page.url()) },
         what: [{
             action: 'fill',
             args: [selector, value],
         }],
     };
 
     await this.addPairToWorkflowAndNotifyClient(pair, page);
 };
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between c25975b and 2e30192.

📒 Files selected for processing (5)
  • server/src/browser-management/inputHandlers.ts (3 hunks)
  • server/src/types/index.ts (1 hunks)
  • server/src/workflow-management/classes/Generator.ts (3 hunks)
  • src/components/atoms/DatePicker.tsx (1 hunks)
  • src/components/atoms/canvas.tsx (4 hunks)
🔇 Additional comments (1)
server/src/browser-management/inputHandlers.ts (1)

9-9: LGTM!

The import of DatePickerEventData type is correctly added to support the new date picker functionality.

Comment on lines +43 to +49
<input
type="date"
onChange={handleDateChange}
value={selectedDate}
className="p-2 border rounded"
autoFocus
/>
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Enhance date input validation and accessibility

The date input field needs validation and additional accessibility attributes.

  <input
    type="date"
    onChange={handleDateChange}
    value={selectedDate}
-   className="p-2 border rounded"
+   className="p-2 border rounded focus:ring-2 focus:ring-blue-500"
    autoFocus
+   aria-label="Select date"
+   min="1900-01-01"
+   max="2100-12-31"
+   required
  />
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<input
type="date"
onChange={handleDateChange}
value={selectedDate}
className="p-2 border rounded"
autoFocus
/>
<input
type="date"
onChange={handleDateChange}
value={selectedDate}
className="p-2 border rounded focus:ring-2 focus:ring-blue-500"
autoFocus
aria-label="Select date"
min="1900-01-01"
max="2100-12-31"
required
/>

Comment on lines +19 to +27
const handleConfirm = () => {
if (socket && selectedDate) {
socket.emit('input:date', {
selector,
value: selectedDate
});
onClose();
}
};
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add error handling for socket emission

The socket event emission should include error handling to manage connection issues.

  const handleConfirm = () => {
    if (socket && selectedDate) {
+     try {
        socket.emit('input:date', {
          selector,
          value: selectedDate
        });
        onClose();
+     } catch (error) {
+       console.error('Failed to emit date selection:', error);
+       // Consider adding user feedback for failed submission
+     }
    }
  };

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines 53 to 63
useEffect(() => {
if (socket) {
socket.on('showDatePicker', (info: {coordinates: Coordinates, selector: string}) => {
setDatePickerInfo(info);
});

return () => {
socket.off('showDatePicker');
};
}
}, [socket]);
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Prevent potential memory leaks in socket effect

The socket effect should clean up properly when the component unmounts.

  useEffect(() => {
+   let isSubscribed = true;
    if (socket) {
      socket.on('showDatePicker', (info: {coordinates: Coordinates, selector: string}) => {
+       if (isSubscribed) {
          setDatePickerInfo(info);
+       }
      });

      return () => {
+       isSubscribed = false;
        socket.off('showDatePicker');
      };
    }
  }, [socket]);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
useEffect(() => {
if (socket) {
socket.on('showDatePicker', (info: {coordinates: Coordinates, selector: string}) => {
setDatePickerInfo(info);
});
return () => {
socket.off('showDatePicker');
};
}
}, [socket]);
useEffect(() => {
let isSubscribed = true;
if (socket) {
socket.on('showDatePicker', (info: {coordinates: Coordinates, selector: string}) => {
if (isSubscribed) {
setDatePickerInfo(info);
}
});
return () => {
isSubscribed = false;
socket.off('showDatePicker');
};
}
}, [socket]);

Comment on lines +167 to +173
{datePickerInfo && (
<DatePicker
coordinates={datePickerInfo.coordinates}
selector={datePickerInfo.selector}
onClose={() => setDatePickerInfo(null)}
/>
)}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add error boundary for DatePicker component

Wrap the DatePicker in an error boundary to prevent crashes from affecting the canvas.

+ class DatePickerErrorBoundary extends React.Component {
+   state = { hasError: false };
+   static getDerivedStateFromError(error) {
+     return { hasError: true };
+   }
+   render() {
+     if (this.state.hasError) {
+       return null;
+     }
+     return this.props.children;
+   }
+ }

  {datePickerInfo && (
+   <DatePickerErrorBoundary>
      <DatePicker
        coordinates={datePickerInfo.coordinates}
        selector={datePickerInfo.selector}
        onClose={() => setDatePickerInfo(null)}
      />
+   </DatePickerErrorBoundary>
  )}

Committable suggestion skipped: line range outside the PR's diff.

@amhsirak amhsirak changed the title feat: add functionality to handle user inputs feat: add functionality to handle user inputs (part 1) Dec 19, 2024
@amhsirak amhsirak marked this pull request as ready for review December 19, 2024 17:31
@amhsirak amhsirak merged commit e823e7b into develop Dec 19, 2024
1 check was pending
@amhsirak amhsirak added the Type: Feature New features label Dec 20, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Type: Feature New features
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Feat: allow inputs
2 participants