Skip to content

[Components] attractwell #14793

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Merged
merged 1 commit into from
Dec 4, 2024
Merged

[Components] attractwell #14793

merged 1 commit into from
Dec 4, 2024

Conversation

jcortes
Copy link
Collaborator

@jcortes jcortes commented Nov 29, 2024

WHY

Resolves #14354

WIP

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced actions for creating/updating contacts and lesson approvals within the AttractWell application.
    • Added support for managing webhooks, including activation and deactivation.
    • New modules for handling events when contacts join a vault and for new event registrations.
    • Enhanced metadata generation for new leads from landing pages.
  • Improvements

    • Expanded API interaction capabilities with new properties and methods for various entities.
    • Added constants for trigger contexts and names to streamline event handling.
    • Introduced a utility function for parsing input values into arrays.
  • Dependencies

    • Updated package dependencies to include @pipedream/platform version 3.0.3.

@jcortes jcortes added action New Action Request trigger / source New trigger / source request labels Nov 29, 2024
@jcortes jcortes self-assigned this Nov 29, 2024
Copy link

vercel bot commented Nov 29, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

3 Skipped Deployments
Name Status Preview Comments Updated (UTC)
docs-v2 ⬜️ Ignored (Inspect) Visit Preview Dec 3, 2024 9:28pm
pipedream-docs ⬜️ Ignored (Inspect) Dec 3, 2024 9:28pm
pipedream-docs-redirect-do-not-edit ⬜️ Ignored (Inspect) Dec 3, 2024 9:28pm

Copy link
Contributor

coderabbitai bot commented Nov 29, 2024

Walkthrough

This pull request introduces multiple new modules and enhancements to the AttractWell application. Key additions include actions for creating or updating contacts, managing lesson approvals, and emitting events for various triggers such as new leads and event registrations. The modifications also expand the API interaction capabilities, including new methods for making requests and handling webhooks. Additionally, constants for API configurations are defined, and the package.json file is updated to include a new dependency.

Changes

File Change Summary
components/attractwell/actions/create-update-contact/create-update-contact.mjs New action for creating/updating contacts with methods for handling API requests and validations.
components/attractwell/actions/lesson-approval/lesson-approval.mjs New module for lesson approval with properties for approval status and methods for API interaction.
components/attractwell/attractwell.app.mjs Enhanced propDefinitions and added methods for API interaction, including error handling.
components/attractwell/common/constants.mjs New module defining constants for API configurations.
components/attractwell/package.json Updated to include a new dependency on @pipedream/platform version 3.0.3.
components/attractwell/sources/common/trigger-contexts.mjs New module exporting string constants for various trigger contexts.
components/attractwell/sources/common/trigger-names.mjs New module exporting trigger names as key-value pairs.
components/attractwell/sources/common/webhook.mjs New module for managing webhooks with methods for activation and deactivation.
components/attractwell/sources/contact-joins-vault-instant/contact-joins-vault-instant.mjs New source for emitting events when a contact joins a vault.
components/attractwell/sources/new-event-registration-instant/new-event-registration-instant.mjs New source for emitting events upon new event registrations.
components/attractwell/sources/new-lead-from-landing-page-instant/new-lead-from-landing-page-instant.mjs New source for emitting events when a new lead is acquired from a landing page.

Assessment against linked issues

Objective Addressed Explanation
Emit new event when a new registration for an event takes place (#14354)
Emit new event when a lead is gained from a landing page (#14354)
Emit new event when a contact becomes a new member of a vault (#14354)
Creates or updates a contact using provided identification (#14354)
Approves, rejects, or unapproves a lesson in the system (#14354)

Possibly related issues

  • [Components] attractwell #13638: The PR's functionality for emitting events when a new lead is acquired aligns with the prompt for new leads from a contact form.

Possibly related PRs

  • New Components - specific #12926: The update-create-contact action in the retrieved PR allows for updating or creating a contact, which is directly related to the createOrUpdateContact method in the main PR that handles creating or updating a contact.
  • New Components - krispcall #13867: The createOrUpdateContact method in the main PR and the create-contact action in this PR both deal with contact management, specifically creating or updating contact details.
  • New Components - copper #14294: The create-update-person action in this PR is similar to the createOrUpdateContact method in the main PR, as both involve managing contact information.
  • [Components]: heyy #14430: The create-contact action in this PR aligns with the createOrUpdateContact method in the main PR, focusing on creating new contacts.
  • New Components - openphone #14505: The create-contact action in this PR is related to the createOrUpdateContact method in the main PR, as both are concerned with contact creation.

Suggested reviewers

  • michelle0927

Poem

🐰 In the AttractWell garden, new paths we weave,
With contacts and lessons, oh, what we achieve!
Events bloom like flowers, each trigger a delight,
With webhooks and constants, our future is bright!
So hop along, friends, let’s dance and create,
In this world of connections, we celebrate fate! 🌼


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
Contributor

@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: 15

🧹 Outside diff range and nitpick comments (11)
components/attractwell/sources/contact-joins-vault-instant/contact-joins-vault-instant.mjs (1)

21-27: Consider using event timestamp if available

The current implementation uses the current timestamp, which might not reflect the actual time when the contact joined the vault. If the webhook payload includes the event timestamp, consider using that instead.

Example implementation:

    generateMeta(resource) {
      return {
        id: resource.contact_id,
        summary: `New Contact: ${resource.contact_name}`,
-       ts: Date.now(),
+       ts: resource.timestamp || Date.now(), // Use event timestamp if available
      };
    },
components/attractwell/actions/lesson-approval/lesson-approval.mjs (2)

9-48: Consider reorganizing props for better maintainability.

Consider grouping required props first, followed by optional props. This makes it clearer which props are necessary for the action to function.

   props: {
     app,
+    approvalStatus: {
+      type: "string",
+      label: "Approval Status",
+      description: "The approval status to set for the lesson.",
+      optional: false,
+      options: ["approved", "rejected", "unapproved"],
+    },
+    contactEmail: {
+      type: "string",
+      label: "Contact Email",
+      description: "The email address of the contact.",
+      optional: false,
+    },
+    vaultId: {
+      optional: false,
+      propDefinition: [app, "vaultId"],
+    },
+    onlineClassLessonId: {
+      label: "Online Class Lesson ID",
+      description: "The ID of the online class lesson.",
+      optional: false,
+      propDefinition: [app, "lessonId"],
+    },
     instructorComment: {
       type: "string",
       label: "Instructor Comment",
       description: "The comment from the instructor.",
       optional: true,
     },
   },

50-55: Consider moving API path to constants.

The API endpoint path should be moved to a constants file for better maintainability and reusability.

+    // Move to constants.mjs
+    const LESSONS_APPROVE_PATH = "/classes/lessons/approve";
+
     lessonApproval(args = {}) {
       return this.app.post({
-        path: "/classes/lessons/approve",
+        path: LESSONS_APPROVE_PATH,
         ...args,
       });
     },
components/attractwell/sources/common/webhook.mjs (2)

28-28: Use a more robust unique identifier for triggerContextId

Using Date.now() for triggerContextId may not guarantee uniqueness if activate() is called multiple times within the same millisecond. Consider using a UUID or another method to ensure uniqueness.


82-82: Review the usage of debug: true in API requests

The debug: true option is enabled in the createWebhook and deleteWebhook methods. If this is not intended for production, consider removing it or making it configurable to avoid exposing sensitive information.

Also applies to: 89-89

components/attractwell/attractwell.app.mjs (3)

124-127: Maintain consistent header casing in getHeaders method

HTTP header field names are case-insensitive, but it's a good practice to use a consistent casing style. Consider using lowercase for all header keys to maintain consistency.

Apply this diff to update the headers:

 return {
   ...headers,
-  "Authorization": `Bearer ${this.$auth.oauth_access_token}`,
-  "Content-Type": "application/json",
-  "Accept": "application/json",
+  "authorization": `Bearer ${this.$auth.oauth_access_token}`,
+  "content-type": "application/json",
+  "accept": "application/json",
 };

83-95: Implement pagination handling in classId options

The options function for classId currently fetches a single page of classes. If there are more classes than fit on one page, they won't be included in the options.

Consider implementing pagination to retrieve all classes. Here's an example modification:

 async options() {
-  const classes = await this.listClasses({
-    params: {
-      page,
-    },
-  });
+  const results = [];
+  let page = 1;
+  let hasMore = true;
+  while (hasMore) {
+    const classes = await this.listClasses({
+      params: { page },
+    });
+    results.push(...classes);
+    hasMore = classes.length > 0;
+    page += 1;
+  }
   return results.map(({
     name: label, id: value,
   }) => ({
     label,
     value,
   }));
 },

102-115: Implement pagination handling in lessonId options

Similar to the classId options, the lessonId options function should handle pagination to ensure all lessons are fetched.

Consider updating the code to handle multiple pages:

 async options() {
-  const classLessons = await this.listClassLessons({
-    params: {
-      page,
-    },
-  });
+  const results = [];
+  let page = 1;
+  let hasMore = true;
+  while (hasMore) {
+    const classLessons = await this.listClassLessons({
+      params: { page },
+    });
+    results.push(...classLessons);
+    hasMore = classLessons.length > 0;
+    page += 1;
+  }
   return results.map(({
     name: label, id: value,
   }) => ({
     label,
     value,
   }));
 },
components/attractwell/actions/create-update-contact/create-update-contact.mjs (3)

335-337: Refine Error Message Formatting

In the error message, the use of asterisks in Either **Email** or **Mobile Phone** is required. may not render as intended. Consider removing the asterisks or using appropriate formatting to ensure the message displays correctly.


128-175: Consider Using Boolean Types for Yes/No Options

The properties campaignContactEmail, campaignContactText, receiveMarketingEmail, and receiveMarketingText are defined as integer types with options 1 (Yes) and 0 (No). Consider using the boolean type for these properties to enhance clarity and user experience, unless the API specifically requires integer values.


301-333: Remove Unused Destructured Variables

Ensure that all variables destructured from this are used within the run method. Unused variables should be removed to improve code readability and maintainability.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 72b131c and c2a0b62.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (11)
  • components/attractwell/actions/create-update-contact/create-update-contact.mjs (1 hunks)
  • components/attractwell/actions/lesson-approval/lesson-approval.mjs (1 hunks)
  • components/attractwell/attractwell.app.mjs (1 hunks)
  • components/attractwell/common/constants.mjs (1 hunks)
  • components/attractwell/package.json (1 hunks)
  • components/attractwell/sources/common/trigger-contexts.mjs (1 hunks)
  • components/attractwell/sources/common/trigger-names.mjs (1 hunks)
  • components/attractwell/sources/common/webhook.mjs (1 hunks)
  • components/attractwell/sources/contact-joins-vault-instant/contact-joins-vault-instant.mjs (1 hunks)
  • components/attractwell/sources/new-event-registration-instant/new-event-registration-instant.mjs (1 hunks)
  • components/attractwell/sources/new-lead-from-landing-page-instant/new-lead-from-landing-page-instant.mjs (1 hunks)
✅ Files skipped from review due to trivial changes (3)
  • components/attractwell/common/constants.mjs
  • components/attractwell/sources/common/trigger-contexts.mjs
  • components/attractwell/sources/common/trigger-names.mjs
🧰 Additional context used
🪛 GitHub Check: Lint Code Base
components/attractwell/sources/contact-joins-vault-instant/contact-joins-vault-instant.mjs

[warning] 8-8:
Source names should start with "New". See https://pipedream.com/docs/components/guidelines/#source-name

🔇 Additional comments (13)
components/attractwell/package.json (2)

Line range hint 1-18: LGTM! Package structure follows best practices

The package.json is well-structured with all necessary fields:

  • Appropriate initial version (0.0.1)
  • Clear description and metadata
  • Correct main entry point
  • Public access configuration

15-17: Verify @pipedream/platform version

The package depends on a fixed version of @pipedream/platform. Let's ensure v3.0.3 is the latest stable version without known vulnerabilities.

✅ Verification successful

@pipedream/platform version 3.0.3 is up-to-date and secure

The package uses the latest stable version (3.0.3) of @pipedream/platform, and no security advisories were found for this version.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check latest version and security advisories for @pipedream/platform

# Check latest version from npm registry
echo "Latest version from npm:"
curl -s https://registry.npmjs.org/@pipedream/platform/latest | jq '.version'

# Check for any security advisories
echo -e "\nSecurity advisories:"
npm audit --json "@pipedream/platform@3.0.3" 2>/dev/null | jq '.advisories'

Length of output: 268

components/attractwell/sources/contact-joins-vault-instant/contact-joins-vault-instant.mjs (2)

1-3: LGTM! Imports are well-organized

The imports are logically structured, importing necessary common modules for webhook handling and trigger configurations.


5-12: LGTM! Configuration is well-structured

The component configuration is well-defined with appropriate:

  • Unique key for the source
  • Clear description
  • Initial version
  • Correct source type
  • Proper deduplication strategy
🧰 Tools
🪛 GitHub Check: Lint Code Base

[warning] 8-8:
Source names should start with "New". See https://pipedream.com/docs/components/guidelines/#source-name

components/attractwell/sources/new-event-registration-instant/new-event-registration-instant.mjs (2)

5-12: LGTM! Module configuration is well-structured.

The configuration is appropriate for a webhook source:

  • Key follows the naming convention
  • Description accurately reflects the functionality
  • Version is correctly set for a new module
  • Type and dedupe settings are correct

1-3: Verify the imported modules exist and export the required entities.

The imports look correct, but let's ensure the referenced modules exist and export the required entities.

✅ Verification successful

All imported modules exist and export the required entities

The verification confirms that:

  • All three imported modules exist in the correct location
  • webhook.mjs exports a default object
  • trigger-names.mjs exports the trigger names including NEW_LEAD_OR_SALE
  • trigger-contexts.mjs exports the contexts including EVENT_REGISTRATION
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the existence and exports of imported modules

# Check if the imported files exist
echo "Checking for imported files..."
fd -e mjs "webhook.mjs|trigger-names.mjs|trigger-contexts.mjs" components/attractwell/sources/common/

# Check the exports from trigger-names.mjs
echo "Checking trigger-names.mjs exports..."
rg -A 1 "export.*NEW_LEAD_OR_SALE" components/attractwell/sources/common/trigger-names.mjs

# Check the exports from trigger-contexts.mjs
echo "Checking trigger-contexts.mjs exports..."
rg -A 1 "export.*EVENT_REGISTRATION" components/attractwell/sources/common/trigger-contexts.mjs

Length of output: 706


Script:

#!/bin/bash
# Let's check the actual content of these files to verify exports

# Check webhook.mjs exports
echo "=== webhook.mjs exports ==="
rg "export" components/attractwell/sources/common/webhook.mjs

# Check trigger-names.mjs content
echo -e "\n=== trigger-names.mjs content ==="
cat components/attractwell/sources/common/trigger-names.mjs

# Check trigger-contexts.mjs content
echo -e "\n=== trigger-contexts.mjs content ==="
cat components/attractwell/sources/common/trigger-contexts.mjs

Length of output: 820

components/attractwell/sources/new-lead-from-landing-page-instant/new-lead-from-landing-page-instant.mjs (3)

1-3: LGTM! Imports are properly structured.

The imports correctly utilize ES module syntax and maintain consistency with .mjs extensions.


5-12: Verify webhook configuration inheritance

The configuration looks good, but let's verify the common webhook implementation.

✅ Verification successful

Webhook configuration inheritance is properly implemented

The common webhook implementation provides all necessary base functionality:

  • Required props (app, db, http, vaultId)
  • Lifecycle hooks (activate, deactivate)
  • Core webhook methods (createWebhook, deleteWebhook, processResource)
  • Abstract methods that child components must implement (generateMeta, getTriggerName, getTriggerContext)

The key "attractwell-new-lead-from-landing-page-instant" is unique across the codebase.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the common webhook implementation and its properties
# Expected: Find the common webhook implementation and verify it has the necessary base properties

# Check the common webhook implementation
cat components/attractwell/sources/common/webhook.mjs

# Verify no other sources are using the same key
rg -l "attractwell-new-lead-from-landing-page-instant"

Length of output: 2523


21-28: 🛠️ Refactor suggestion

Add error handling for resource properties

The generateMeta method should validate the resource object and its properties before usage.

Consider adding validation:

  generateMeta(resource) {
+   if (!resource?.lead_source_id) {
+     throw new Error("Missing required field: lead_source_id");
+   }
    const ts = Date.now();
    return {
      id: `${resource.lead_source_id}_${ts}`,
      summary: `New Lead: ${resource.lead_source_id}`,
      ts,
    };
  },
components/attractwell/actions/lesson-approval/lesson-approval.mjs (2)

1-8: LGTM! Module metadata is well-defined.

The module definition follows the component standards with clear naming, description, and proper versioning.


1-81: Verify integration with AttractWell API.

The implementation appears to satisfy the PR objectives for lesson approval functionality. Let's verify the API endpoint and response format.

✅ Verification successful

Based on the search results, I can see that the /classes/lessons/approve endpoint is only used in the lesson-approval action component, and there are no similar approval status handling patterns found in other files. Let me verify the error handling patterns to ensure proper implementation.


Based on the analysis of the code, I can now provide a final response:

Implementation correctly handles API interaction and error cases

The implementation is well-structured and follows proper patterns for API interaction:

  • The app has proper error handling in attractwell.app.mjs that throws errors for API failures
  • The action uses the standard pattern of making API requests through the app's post method
  • The response handling follows the established pattern with proper summary export
  • The endpoint /classes/lessons/approve is consistently implemented
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the API endpoint and related code

# Check if the API endpoint is consistently used across the codebase
rg -l "/classes/lessons/approve"

# Look for similar approval status handling in other files
ast-grep --pattern 'approval_status: $STATUS'

# Check for any existing error handling patterns
rg -A 3 'throw new Error\('

Length of output: 112400


Script:

#!/bin/bash
# Check for error handling in the attractwell app and related files
rg -A 5 "throw new Error|return this.app" components/attractwell/

# Look for any existing response validation patterns
ast-grep --pattern 'response = await $FUNC({$$$})'

Length of output: 47045

components/attractwell/attractwell.app.mjs (2)

170-175: Verify the correctness of the listVaults API endpoint

Ensure that the /vaults endpoint used in the listVaults method is correct and returns the expected data. Mistyped or incorrect endpoints can lead to runtime errors or unexpected results.

Would you like me to assist in verifying the API endpoint and updating it if necessary?


184-187: Confirm the availability of the /automations endpoint

The listAutomations method uses the /automations endpoint. Please verify that this endpoint exists in the AttractWell API and returns the correct data structure.

Run the following script to check the endpoint:

Replace YOUR_ACCESS_TOKEN with a valid access token.

✅ Verification successful

Based on the search results, I can now generate a final response since we have sufficient evidence about the /automations endpoint usage in the codebase.

The /automations endpoint is correctly implemented and used in the AttractWell API

The codebase shows that the /automations endpoint is actively used in the AttractWell app (components/attractwell/attractwell.app.mjs) through the listAutomations method. This method is used to fetch automation data and is referenced in the app's prop options, indicating it's a core part of the API functionality for retrieving automation records.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the /automations endpoint

curl -X GET \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  "https://api.attractwell.com/v1/automations"

Length of output: 497


Script:

#!/bin/bash
# Let's check the API documentation or related files for the /automations endpoint
fd -e md -e txt . | xargs rg -i "automations?.*(endpoint|api|route)" -A 3 -B 3

# Also search for any test files or documentation related to automations
fd -e test.js -e spec.js -e md . | xargs rg -i "automations" -A 3 -B 3

# Check if there are any API client implementations using this endpoint
ast-grep --pattern 'path: "/automations"'

Length of output: 156705


Script:

#!/bin/bash
# Let's check for any tests or implementation files related to the /automations endpoint
rg -i "listAutomations|/automations" -A 5 -B 5

# Also search for any API documentation or schema files
fd -e json -e yaml -e yml . | xargs rg -i "automations?.*(endpoint|api|route|schema)" -A 3 -B 3

# Look for any related test files specifically
fd -e test.js -e spec.js . | xargs rg -i "/automations" -A 3 -B 3

Length of output: 30680

@jcortes jcortes force-pushed the attractwell-new-components branch from c2a0b62 to 41e54a5 Compare December 2, 2024 20:53
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Outside diff range and nitpick comments (2)
components/attractwell/actions/create-update-contact/create-update-contact.mjs (1)

314-317: Remove commented-out code in request headers

The headers X-TAGS-TO-ADD and X-AUTOMATIONS-TO-RUN are commented out in the request. If these headers are no longer needed, consider removing the commented code to keep the code clean.

components/attractwell/attractwell.app.mjs (1)

83-115: Ensure consistent handling of pagination in 'options' methods

Some options methods, such as classId and lessonId, accept a page parameter and handle pagination, while others do not. For consistency and to ensure all options can handle large data sets, consider implementing pagination handling in all options methods where applicable.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between c2a0b62 and 41e54a5.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (11)
  • components/attractwell/actions/create-update-contact/create-update-contact.mjs (1 hunks)
  • components/attractwell/actions/lesson-approval/lesson-approval.mjs (1 hunks)
  • components/attractwell/attractwell.app.mjs (1 hunks)
  • components/attractwell/common/constants.mjs (1 hunks)
  • components/attractwell/package.json (1 hunks)
  • components/attractwell/sources/common/trigger-contexts.mjs (1 hunks)
  • components/attractwell/sources/common/trigger-names.mjs (1 hunks)
  • components/attractwell/sources/common/webhook.mjs (1 hunks)
  • components/attractwell/sources/contact-joins-vault-instant/contact-joins-vault-instant.mjs (1 hunks)
  • components/attractwell/sources/new-event-registration-instant/new-event-registration-instant.mjs (1 hunks)
  • components/attractwell/sources/new-lead-from-landing-page-instant/new-lead-from-landing-page-instant.mjs (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (7)
  • components/attractwell/package.json
  • components/attractwell/sources/common/trigger-contexts.mjs
  • components/attractwell/sources/common/trigger-names.mjs
  • components/attractwell/common/constants.mjs
  • components/attractwell/sources/new-event-registration-instant/new-event-registration-instant.mjs
  • components/attractwell/sources/new-lead-from-landing-page-instant/new-lead-from-landing-page-instant.mjs
  • components/attractwell/sources/contact-joins-vault-instant/contact-joins-vault-instant.mjs
🔇 Additional comments (5)
components/attractwell/sources/common/webhook.mjs (1)

62-70: Ensure that abstract methods are implemented in derived components

The methods generateMeta(), getTriggerName(), and getTriggerContext() are currently not implemented and throw a ConfigurationError. Ensure these methods are properly implemented in the derived components to prevent runtime errors when they are invoked in activate(), deactivate(), and processResource().

components/attractwell/actions/create-update-contact/create-update-contact.mjs (1)

12-23: Clarify Required Fields: 'Email' and 'Mobile Phone'

The properties Email and Mobile Phone are both marked as optional, but at least one of them is required as per the validation in the run method. Consider updating the property definitions or adding custom validation to reflect that at least one of these fields must be provided.

components/attractwell/actions/lesson-approval/lesson-approval.mjs (1)

57-80: Enhance error handling and success message

Consider adding error handling in the run method to catch exceptions from the API call. Also, validate the response and make the success message more informative by including the approval status.

components/attractwell/attractwell.app.mjs (2)

15-16: Ensure consistent options format across properties

The options function for the tag property returns an array of string values, while other properties return an array of objects with label and value keys. This inconsistency might cause issues with how the options are rendered in the UI. Consider updating the options function to return objects with label and value for consistency.

Apply this diff to make the change:

-            return tags.map(({ tag: value }) => value);
+            return tags.map(({ tag }) => ({
+              label: tag,
+              value: tag,
+            }));

139-142: Improve error handling in the _makeRequest method

The current error handling checks if the response is a string, which may not reliably detect errors from the API. It's better to catch exceptions thrown by axios and handle HTTP error responses explicitly.

Refactor the error handling by wrapping the request in a try...catch block:

 async _makeRequest({
   $ = this, path, headers, ...args
 } = {}) {
+  try {
     const response = await axios($, {
       ...args,
       debug: true,
       url: this.getUrl(path),
       headers: this.getHeaders(headers),
     });
 
-    if (typeof(response) === "string") {
-      console.log("Error:", response);
-      throw new Error("Error in response from AttractWell API.");
-    }
 
     return response;
+  } catch (error) {
+    console.error("Error in response from AttractWell API:", error);
+    throw error;
+  }
 },

Copy link
Contributor

@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

🧹 Outside diff range and nitpick comments (5)
components/attractwell/common/utils.mjs (1)

21-23: Consider providing more specific error messages

The current error message doesn't indicate what went wrong (e.g., JSON parsing error vs. non-array result). Including the original error message would help users debug issues more effectively.

-    throw new ConfigurationError("Make sure the custom expression contains a valid array object");
+    throw new ConfigurationError(`Invalid array input: ${e.message}`);
components/attractwell/actions/create-update-contact/create-update-contact.mjs (4)

9-9: Consider starting with version 1.0.0

The version is set to "0.0.1" which typically indicates a pre-release version. Since this is a production component being added to the main repository, consider starting with version "1.0.0" to indicate a stable release.


129-152: Consider using native boolean values in the API

The boolean properties (campaignContactEmail, campaignContactText, receiveMarketingEmail, receiveMarketingText) are being converted to integers (0/1) before sending to the API. Consider updating the API to accept native boolean values for better type safety and cleaner code.

- campaign_contact_email: fromBooleanToInt(campaignContactEmail),
+ campaign_contact_email: campaignContactEmail,

265-270: Add input validation to createOrUpdateContact method

The method accepts arbitrary arguments without validation. Consider adding type checking and validation for the expected arguments to catch potential issues early.

 createOrUpdateContact(args = {}) {
+  const { path, ...rest } = args;
+  if (path !== "/contacts") {
+    throw new Error("Invalid path for createOrUpdateContact");
+  }
   return this.app.post({
     path: "/contacts",
-    ...args,
+    ...rest,
   });
 },

309-311: Enhance error message with validation details

The error message could be more informative by including the actual values received.

 if (!email && !mobilePhone) {
-  throw new ConfigurationError("Either **Email** or **Mobile Phone** is required.");
+  throw new ConfigurationError(
+    `Either **Email** or **Mobile Phone** is required. Received: email=${email}, mobilePhone=${mobilePhone}`
+  );
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 41e54a5 and 32f1a34.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (12)
  • components/attractwell/actions/create-update-contact/create-update-contact.mjs (1 hunks)
  • components/attractwell/actions/lesson-approval/lesson-approval.mjs (1 hunks)
  • components/attractwell/attractwell.app.mjs (1 hunks)
  • components/attractwell/common/constants.mjs (1 hunks)
  • components/attractwell/common/utils.mjs (1 hunks)
  • components/attractwell/package.json (2 hunks)
  • components/attractwell/sources/common/trigger-contexts.mjs (1 hunks)
  • components/attractwell/sources/common/trigger-names.mjs (1 hunks)
  • components/attractwell/sources/common/webhook.mjs (1 hunks)
  • components/attractwell/sources/contact-joins-vault-instant/contact-joins-vault-instant.mjs (1 hunks)
  • components/attractwell/sources/new-event-registration-instant/new-event-registration-instant.mjs (1 hunks)
  • components/attractwell/sources/new-lead-from-landing-page-instant/new-lead-from-landing-page-instant.mjs (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (8)
  • components/attractwell/sources/common/trigger-names.mjs
  • components/attractwell/package.json
  • components/attractwell/common/constants.mjs
  • components/attractwell/sources/common/trigger-contexts.mjs
  • components/attractwell/sources/new-event-registration-instant/new-event-registration-instant.mjs
  • components/attractwell/sources/new-lead-from-landing-page-instant/new-lead-from-landing-page-instant.mjs
  • components/attractwell/sources/contact-joins-vault-instant/contact-joins-vault-instant.mjs
  • components/attractwell/actions/lesson-approval/lesson-approval.mjs
🔇 Additional comments (5)
components/attractwell/common/utils.mjs (1)

3-24: LGTM! Well-structured array parsing utility

The implementation handles all edge cases properly:

  • Falsy value handling
  • Direct array pass-through
  • JSON string parsing
  • Type validation
  • Error handling
components/attractwell/sources/common/webhook.mjs (1)

63-71: Implement required methods to avoid runtime errors

The methods generateMeta(), getTriggerName(), and getTriggerContext() currently throw a ConfigurationError because they are not implemented. Ensure these methods are properly implemented in the derived components.

components/attractwell/attractwell.app.mjs (2)

14-16: Ensure consistent options format across properties

The options function for the tag property returns an array of string values, while other properties return an array of objects with label and value keys.


129-137: ⚠️ Potential issue

Enhance error handling in _makeRequest

The current implementation lacks proper error handling for API responses and network errors.

 _makeRequest({
   $ = this, path, headers, ...args
 } = {}) {
+  try {
     return axios($, {
       ...args,
       url: this.getUrl(path),
       headers: this.getHeaders(headers),
     });
+  } catch (error) {
+    console.error(`API request failed for ${path}:`, error.response?.data || error.message);
+    throw error;
+  }
 },

Likely invalid or redundant comment.

components/attractwell/actions/create-update-contact/create-update-contact.mjs (1)

13-24: Clarify Required Fields: 'Email' and 'Mobile Phone'

The properties Email and Mobile Phone are both marked as optional, but at least one of them is required as per the validation in the run method. Consider updating the property definitions or adding custom validation messages to reflect that at least one of these fields must be provided.

Copy link
Collaborator

@michelle0927 michelle0927 left a comment

Choose a reason for hiding this comment

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

The package.json version should be 0.1.0. Other than that, looks good!

@jcortes jcortes force-pushed the attractwell-new-components branch from 32f1a34 to 0255315 Compare December 3, 2024 21:28
Copy link
Contributor

@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)
components/attractwell/actions/lesson-approval/lesson-approval.mjs (1)

50-55: Add input validation to lessonApproval method.

Consider validating the required fields before making the API call.

   lessonApproval(args = {}) {
+    const { data } = args;
+    if (!data?.approval_status || !data?.contact_email) {
+      throw new Error("approval_status and contact_email are required");
+    }
     return this.app.post({
       path: "/classes/lessons/approve",
       ...args,
     });
   },
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 32f1a34 and 0255315.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (12)
  • components/attractwell/actions/create-update-contact/create-update-contact.mjs (1 hunks)
  • components/attractwell/actions/lesson-approval/lesson-approval.mjs (1 hunks)
  • components/attractwell/attractwell.app.mjs (1 hunks)
  • components/attractwell/common/constants.mjs (1 hunks)
  • components/attractwell/common/utils.mjs (1 hunks)
  • components/attractwell/package.json (2 hunks)
  • components/attractwell/sources/common/trigger-contexts.mjs (1 hunks)
  • components/attractwell/sources/common/trigger-names.mjs (1 hunks)
  • components/attractwell/sources/common/webhook.mjs (1 hunks)
  • components/attractwell/sources/contact-joins-vault-instant/contact-joins-vault-instant.mjs (1 hunks)
  • components/attractwell/sources/new-event-registration-instant/new-event-registration-instant.mjs (1 hunks)
  • components/attractwell/sources/new-lead-from-landing-page-instant/new-lead-from-landing-page-instant.mjs (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (10)
  • components/attractwell/sources/common/trigger-names.mjs
  • components/attractwell/sources/common/trigger-contexts.mjs
  • components/attractwell/common/constants.mjs
  • components/attractwell/package.json
  • components/attractwell/sources/new-event-registration-instant/new-event-registration-instant.mjs
  • components/attractwell/common/utils.mjs
  • components/attractwell/sources/contact-joins-vault-instant/contact-joins-vault-instant.mjs
  • components/attractwell/sources/new-lead-from-landing-page-instant/new-lead-from-landing-page-instant.mjs
  • components/attractwell/actions/create-update-contact/create-update-contact.mjs
  • components/attractwell/sources/common/webhook.mjs
🔇 Additional comments (7)
components/attractwell/actions/lesson-approval/lesson-approval.mjs (3)

1-8: LGTM! Action metadata is well-defined.

The action is properly configured with appropriate key, name, description, and type.


11-25: ⚠️ Potential issue

Mark approvalStatus and contactEmail as required.

These props are essential for the API call but not explicitly marked as required.

Apply this diff:

   approvalStatus: {
     type: "string",
     label: "Approval Status",
     description: "The approval status to set for the lesson.",
+    optional: false,
     options: [
       "approved",
       "rejected",
       "unapproved",
     ],
   },
   contactEmail: {
     type: "string",
     label: "Contact Email",
     description: "The email address of the contact.",
+    optional: false,
   },

57-80: ⚠️ Potential issue

Enhance error handling and success message.

The run method needs improvements in error handling and response validation.

Apply this diff:

   async run({ $ }) {
     const {
       lessonApproval,
       approvalStatus,
       contactEmail,
       vaultId,
       onlineClassLessonId,
       instructorComment,
     } = this;

+    try {
       const response = await lessonApproval({
         $,
         data: {
           approval_status: approvalStatus,
           contact_email: contactEmail,
           vault_id: vaultId,
           online_class_lesson_id: onlineClassLessonId,
           instructor_comment: instructorComment,
         },
       });

+      if (!response?.success) {
+        throw new Error("Failed to update lesson approval status");
+      }

-      $.export("$summary", "Successfully updated lesson approval status.");
+      $.export("$summary", `Successfully ${approvalStatus} the lesson.`);
       return response;
+    } catch (error) {
+      throw new Error(`Failed to update lesson approval status: ${error.message}`);
+    }
   },
components/attractwell/attractwell.app.mjs (4)

138-190: LGTM! API methods are well-implemented.

The API methods are consistently implemented using _makeRequest and follow a clear pattern.


13-16: 🛠️ Refactor suggestion

Ensure consistent options format across properties.

The tag property's options function returns an inconsistent format compared to other properties.

Apply this diff:

   async options() {
     const tags = await this.listContactTags();
-    return tags.map(({ tag: value }) => value);
+    return tags.map(({ tag }) => ({
+      label: tag,
+      value: tag,
+    }));
   },

83-95: 🛠️ Refactor suggestion

Implement proper pagination handling.

The options methods for classId and lessonId need proper pagination handling.

Apply this diff to both methods:

   async options({ page }) {
     const items = await this.listClasses({
       params: {
         page,
+        per_page: 100,
       },
     });
+    const hasMore = items.length === 100;
     return items.map(({
       name: label, id: value,
     }) => ({
       label,
       value,
+      hasMore,
     }));
   },

Also applies to: 102-114


129-137: ⚠️ Potential issue

Improve error handling in the _makeRequest method.

The current implementation lacks proper error handling for API responses.

Apply this diff:

   _makeRequest({
     $ = this, path, headers, ...args
   } = {}) {
+    try {
       return axios($, {
         ...args,
         url: this.getUrl(path),
         headers: this.getHeaders(headers),
       });
+    } catch (error) {
+      console.error("Error in response from AttractWell API:", error);
+      throw error;
+    }
   },

@malexanderlim malexanderlim merged commit 2e50568 into master Dec 4, 2024
11 checks passed
@malexanderlim malexanderlim deleted the attractwell-new-components branch December 4, 2024 03:57
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
action New Action Request trigger / source New trigger / source request
Projects
Development

Successfully merging this pull request may close these issues.

[Components] attractwell
3 participants