Skip to content

Commit dc84283

Browse files
joaquincasalFBanfiJuliRossi
authored
Hubspot app [INTEG-2766] (#10035)
* Hubspot: organizing structure and removing locations [INTEG-2802] (#9914) * removing some locations and moving tests files * adding cursor to gitignore * Hubspot: Config screen base structure [INTEG-2769] (#9924) * adding base config structure and basic tests * changing ConfigScreen.spec.tsx * pr comments corrections * Add sidebar (#9932) * Hubspot: adding app to content type through config screen [INTEG-2770] (#9929) * wip * adding content type through config screen first version * making ContentTypeMultiSelect component and tests * refactor in config screen organization * refactor using multiselect component * fix prettier format * refactor in tests + removing app through config screen * refactor and creation of tests * adding autocomplete option in the multiselect component * removing redundant test * removing unnecessary useCallBack * Add fields selection step (#9940) * Hubspot: Create modules [INTEG-2776] (#9944) * Add function to create modules * Update apps/hubspot/test/functions/createModules.spec.ts Co-authored-by: JuliRossi <juliana.rossi@external.contentful.com> * Update apps/hubspot/test/functions/createModules.spec.ts Co-authored-by: JuliRossi <juliana.rossi@external.contentful.com> --------- Co-authored-by: JuliRossi <juliana.rossi@external.contentful.com> * FieldSelection UI adjustments * Update type import * Hubspot: Config screen validations with a function [INTEG-2771] (#9945) * first version of config screen validation function and tests * correction of PR comments and refactor in config screen and validateHubspotToken function * Hubspot: Add support for other field types [INTEG-2776] (#9948) * Add support for more field types * Fix tests warnings * Add support for images + refactor * Modules function refactor * Remove casting * Use find* instead of waitFor in tests * Fix entry title * Fix nummer displayed in the 'select all' checkbox * Hubspot: Setup custom content type for configuration [INTEG-2784] (#9952) * adding creation of config entry when installing the app * refactor extract constant * removing unused code * changing description in createContentType from utils * changing notifier error from config screen * Hubspot: update copy [] (#9949) * Copy updates * Add gif to config screen * Replace gif with video * add warning so the user doesn't modify the config entry (#9954) * Hubspot: adding config entry service [INTEG-2785] (#9953) * adding a config entry service * changing ConnectedField type * lazy get for config entry service * removing getDefaultLocale function since it is not used anymore * PR comments * Hubspot: Allow to change modules name [INTEG-2775] (#9956) * Add second dialog step * Add Dialog styles file * Show results after module creation * Show error for unsupported characters in modules * Disable inputs when sending * Hubspot: validations update [] (#9962) * Move token validation from config screen to dialog * Update config screen instructions and video * Hubspot: add sync info to sidebar [INTEG-2773] (#9963) * Show last synced time in sidebar * Display error note in sidebar * Update apps/hubspot/src/locations/Sidebar.tsx Co-authored-by: Franco Banfi <62450599+FBanfi@users.noreply.github.com> * Fix linter --------- Co-authored-by: Franco Banfi <62450599+FBanfi@users.noreply.github.com> * Hubspot: Trim whitespace from access token input on config screen (#9965) * Hubspot: handle other events [INTEG-2786] (#9966) * first version of app event handler function * tests for appEventHandler.spec.ts * adding test for ConfigEntryService file * changing ConfigEntryService tests structure * adding tests for ConfigEntryService and removing uninstall event * removing old function from manifest * PR corrections * making default locale optional in ConfigEntryService * Hubspot: Persist error in sidebar [] (#9967) * Persist error in sidebar * Refactor Dialog.showResults * Hubspot: storage on module creation [INTEG-2785] (#9972) * WIP save connected fields + config entry service refactor * adding + fix in createModules.ts --------- Co-authored-by: joaquin <joaquin.casal@10pines.com> * Hubspot: Update modules on entry save [INTEG-2785] (#9975) * first version of update on save event + some tests * adding refactor to the appEventHandler tests * rename from test * Fix linter * changin place of call and retry * refactor: passing only the hubspot token to function * early return if entry is not synced + new test * fix test --------- Co-authored-by: joaquin <joaquin.casal@10pines.com> * Hubspot: Fix long text issue [INTEG-2907] (#9977) * Hubspot: Enhance text field handling in module creation [INTEG-2785] * Added support for long text fields in createModules.ts * Introduced LONG_TEXT_MODULE_TEMPLATE in templates.ts * Updated logic to format text field values as HTML paragraphs * Hubspot: Update module templates for rich text handling * Add tests * fix rebase * Hubspot: Refactor module creation by extracting createModuleFile and error classes * Hubspot: Update appEventHandler test to use rich text field template for module creation * Hubspot: Address QA comments [INTEG-2907] (#9978) * Hubspot: Update configuration screen instructions for clarity * Add tooltip to FieldCheckbox for unsupported syncing indication * Remove audio from hubspot.mp4 * Remove isVisible prop from Tooltip in FieldCheckbox component * Update title in ConfigEntryService to include warning against deletion * Hubspot: page location table [INTEG-2780] (#9979) * page location table * adding styles * removing property from mock in test * refactors in styles and types * modifying tests and page components * fix localization issue (#9990) * Hubspot: adding modal in page location [INTEG-2781] (#9989) * wip adding test * Fix tests * wip adding types for the connected entry modal * wip fixing tests * Refactoring and polishing page * Modal refactor * Fix typos in messages and update test assertions for connected fields * Refactor displayType function to use FieldItems type for better type safety * refactor to fix warning * changing modal header title and content to match the figma * reducing the padding of the modal to match the figma * refactor in the page empty and error cases * adding test for empty and error table cases --------- Co-authored-by: Juli Rossi <juliana.rossi@external.contentful.com> * Hubspot: adding and displaying error in Page location [INTEG-2783] (#9997) * adding error badges in Page table and modal * removing warning oct component + styles changes * move tooltip (#9993) * Hubspot disconnect - [INTEG-2782] (#10000) * Disconnect functionality * remove unused import * re-adding tests * Removing unused parameter * Fix rebase * Prettier * Hubspot: Avoid duplicated module creation [INTEG-2935] (#10013) * Enhance FieldSelection component to include connected field IDs and update tooltip behavior. Fetch connected fields in Dialog component and pass them to FieldSelection. Update tests to verify checkbox states for connected fields. * remove parameter * Hubspot: fixing update method in createModule function [INTEG-2941] (#9996) * fixing update method in config entry service * changing createModules function to send all the fields to the update * adding test for updateConnectedFields * Update connected fields handling in Page component and enhance test descriptions (#10014) * Hubspot: changing displaying field and content type id for name [INTEG-2971] (#10015) * changing page table to display content type name * changing page modal to display field name instead of id * inlining content type name in page table * formating prettier * Hubspot getting started - [INTEG-2927] (#10016) * Add getting started images and enhance ConfigScreen layout * Enhance ConfigScreen by adding alt text for images in GettingStartedStep component * Add test for Getting Started section in ConfigScreen with image alt text checks * Fixes per comments * Add periods (#10028) * Delete custom content type when uninstalling the app (#10030) * Hubspot add events scripts [INTEG-2970] (#10031) * Update dependencies and add event subscription script for Hubspot integration * Testing first approach * Remove dotenv/config from setupFiles in vitest configuration * Refactor tests for createAppEventSubscription to improve type safety and error handling * Hubspot: no duplicated names in module selection [INTEG-2967] (#10029) * adding error handling for duplicated names * prettier * Refactor FieldModuleNameMapping to improve validation handling and error management * removing useEffect * refactor removing useEffect --------- Co-authored-by: Juli Rossi <juliana.rossi@external.contentful.com> * Add error message for empty module name --------- Co-authored-by: Franco Banfi <62450599+FBanfi@users.noreply.github.com> Co-authored-by: JuliRossi <juliana.rossi@external.contentful.com>
1 parent 8de8598 commit dc84283

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

66 files changed

+6788
-351
lines changed

apps/hubspot/.env.example

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
CONTENTFUL_ORG_ID=contentful-org-id
2+
CONTENTFUL_APP_DEF_ID=contentful-app-id
3+
ENVIRONMENT_ID=master
4+
SPACE_ID=space-id
5+
CONTENTFUL_ACCESS_TOKEN=access-token

apps/hubspot/.env.test

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CONTENTFUL_ACCESS_TOKEN=test-access-token
2+
CONTENTFUL_HOST=api.contentful.com
3+
CONTENTFUL_FUNCTION_ID=appEventHandler
4+
CONTENTFUL_ORG_ID=test-org-id
5+
CONTENTFUL_APP_DEF_ID=test-app-def-id
6+
ENVIRONMENT_ID=master
7+
SPACE_ID=space-id

apps/hubspot/.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,14 @@
1515
.env
1616
.env.*
1717
!.env*.example
18+
!.env.test
1819

1920
# misc
2021
.DS_Store
2122

2223
npm-debug.log*
2324
yarn-debug.log*
2425
yarn-error.log*
26+
/.cursor/
27+
/.cursor/rules/
28+
/.cursor/rules/cursorrules
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
{
2+
"functions": [
3+
{
4+
"id": "createModulesFunction",
5+
"name": "Create Hubspot modules function",
6+
"description": "Function to create Hubspot modules from an App Action",
7+
"path": "functions/createModules.js",
8+
"entryFile": "functions/createModules.ts",
9+
"allowNetworks": ["https://api.hubapi.com"],
10+
"accepts": ["appaction.call"]
11+
},
12+
{
13+
"id": "appEventHandler",
14+
"name": "App event handler function",
15+
"description": "Function to handle App Events.",
16+
"path": "functions/appEventHandler.js",
17+
"entryFile": "functions/appEventHandler.ts",
18+
"allowNetworks": ["https://api.hubapi.com"],
19+
"accepts": ["appevent.handler"]
20+
}
21+
],
22+
"actions": [
23+
{
24+
"id": "createModulesAction",
25+
"name": "Create Hubspot modules",
26+
"type": "function-invocation",
27+
"functionId": "createModulesFunction",
28+
"category": "Custom",
29+
"parameters": [
30+
{
31+
"id": "fields",
32+
"name": "Fields",
33+
"type": "Symbol",
34+
"required": true
35+
},
36+
{
37+
"id": "entryId",
38+
"name": "EntryId",
39+
"type": "Symbol",
40+
"required": true
41+
}
42+
]
43+
}
44+
]
45+
}
Lines changed: 266 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,266 @@
1+
# App Action Function Template
2+
3+
App Action functions enable communication between apps by providing serverless endpoints that can be invoked through app actions. This template provides a starting point with skeleton code—you must add your custom action logic to meet your specific use case.
4+
5+
## What is an App Action Function?
6+
7+
App Action functions are serverless workloads that run on Contentful's infrastructure to provide enhanced flexibility and customization. Unlike event-based functions that respond to system events, App Actions are explicitly invoked by an app or external system with specific parameters to perform an operation.
8+
9+
Common use cases for App Action functions include:
10+
11+
- Bulk content operations
12+
- Data synchronization between environments or spaces
13+
- Integration with external services and APIs
14+
- Content transformation and migration
15+
- Custom content validation or enrichment
16+
17+
## Getting Started
18+
19+
### 1. Adding the Function to a Contentful App
20+
21+
#### Creating a New App with the Function
22+
23+
If you want to create a new app that includes the function template, run:
24+
25+
```bash
26+
npx create-contentful-app@latest --function appaction-call
27+
```
28+
29+
This command will generate a basic app template that includes:
30+
31+
- A `functions` folder that contains the template, instructions, and relevant config files.
32+
- All necessary scripts for building and deploying your function
33+
- App manifest file
34+
- This file ensures that Contentful can properly identify, configure, and run your function.
35+
- For more information see: [Working with Functions](https://www.contentful.com/developers/docs/extensibility/app-framework/working-with-functions/)
36+
37+
#### Adding the Function to an Existing App
38+
39+
If you prefer to add the function to an existing app, you can run the following CLI commands from inside your app directory:
40+
41+
**Interactive Mode**
42+
43+
Run the CLI in interactive mode, which will prompt you for the necessary options:
44+
45+
```bash
46+
npx --no-install @contentful/app-scripts generate-function
47+
```
48+
49+
The interactive process will guide you through:
50+
51+
1. Selecting a function name
52+
2. Choosing from available function examples
53+
3. Selecting your preferred language (JavaScript or TypeScript)
54+
55+
**Non-interactive Mode**
56+
57+
For automated workflows or CI/CD pipelines, use the `--ci` flag with required parameters:
58+
59+
```bash
60+
npx --no-install @contentful/app-scripts generate-function --ci --name <name> --example appaction-call --language typescript
61+
```
62+
63+
**Available Parameters:**
64+
65+
- `--name <name>`: Your function name (any value except 'example')
66+
- `--example <example>`: Template to use (e.g., 'appaction-call', 'external-references')
67+
- `--language <language>`: 'javascript' or 'typescript' (defaults to typescript if invalid)
68+
- `--ci`: Enables non-interactive mode
69+
70+
**Example:**
71+
72+
```bash
73+
npx --no-install @contentful/app-scripts generate-function --ci --name content-processor --example appaction-call --language typescript
74+
```
75+
76+
When executed, this command:
77+
78+
- Creates a `functions` directory if one doesn't exist
79+
- Adds the selected function template with your specified name
80+
- Creates or updates the `contentful-app-manifest.json` file
81+
- Updates your `package.json` to include function build commands
82+
83+
> **Note**: All function examples are sourced from the `contentful/apps/function-examples` repository.
84+
85+
### 2. Connect to an App Definition
86+
87+
If you haven't already created an app definition in Contentful, choose one of the options below.
88+
89+
#### Manually via the Web UI
90+
91+
- [Navigate to the Apps section in your organization](https://app.contentful.com/deeplink?link=app-definition-list)
92+
93+
- Click the "Create App" button
94+
95+
- Fill in the required fields. If you want to test your App Action function using a UI, be sure to select **Page Location** and check the toggle for `Show app in main navigation`.
96+
97+
- Proceed to the [Set Up Your Environment](#3-set-up-your-environment) step.
98+
99+
> **Note**: If you are unfamiliar with how to create a custom app definition in Contentful, please review the documentation here: [Create a Custom App - Tutorial](https://www.contentful.com/developers/docs/extensibility/app-framework/tutorial/?utm_source=webapp&utm_medium=app-listing&utm_campaign=in-app-help)
100+
101+
#### Via CLI
102+
103+
- Run: `npm run create-app-definition`
104+
- Answer the prompted questions. Feel free to proceed with the default options provided.
105+
106+
1. **Name of your application**.
107+
- This is how your app will be named and it will be displayed in a few places throughout the UI. The default is the name of the folder you created.
108+
2. **Select where your app can be rendered**.
109+
- For testing App Actions, select **Page Location**, as this is where you will be able to test your app actions. Select `y` for showing your app in the main navigation, and then provide a name for the link.
110+
- If your app is **frontendless** you can skip selecting a location.
111+
3. **Contentful CMA endpoint URL**.
112+
- This refers to the URL used to interact with Contentful's Management APIs.
113+
4. **App Parameters**.
114+
- These are configurable values that can be used to set default values or define custom validation rules.
115+
5. The next steps will lead you through the process of providing a Contentful access token to the application and specifying the organization to which the application should be assigned.
116+
- This will automatically create a `.env` file with these fields for you
117+
6. Proceed to [Customize the App Action Function](#4-customize-the-app-action-function)
118+
119+
### 3. Set Up Your Environment
120+
121+
If you created your app definition manually through the web UI, or the CLI did not create one for you, create a `.env` file in the root of your application with your Contentful credentials:
122+
123+
```env
124+
CONTENTFUL_ORG_ID=your-organization-id
125+
CONTENTFUL_APP_DEF_ID=your-app-definition-id
126+
CONTENTFUL_ACCESS_TOKEN=your-access-token
127+
```
128+
129+
These variables authenticate your function with Contentful and link it to your app definition.
130+
131+
> **Note**: You can generate an access token from your Space Settings menu. For the other values, you can find them in your Contentful organization and app settings.
132+
133+
### 4. Customize the App Action Function
134+
135+
Open `functions/appaction-call-template.ts` and add your custom logic based on your specific requirements.
136+
137+
#### App Action Function Example
138+
139+
Here's an example that creates a new entry of a specific content type:
140+
141+
```ts
142+
// Define your App Action parameters
143+
type CreateEntryParams = {
144+
contentTypeId: string;
145+
fields: Record<string, any>;
146+
};
147+
148+
export const handler: FunctionEventHandler<FunctionTypeEnum.AppActionCall> = async (
149+
event: AppActionRequest<'Custom', CreateEntryParams>,
150+
context: FunctionEventContext
151+
) => {
152+
// Access the CMA client
153+
const cma = context.cma!;
154+
155+
try {
156+
// Extract parameters from the request
157+
const { contentTypeId, fields } = event.body;
158+
159+
// Get the space and environment from the context
160+
const spaceId = context.spaceId;
161+
const environmentId = context.environmentId;
162+
163+
if (!contentTypeId || !fields) {
164+
return {
165+
error: 'Missing required parameters: contentTypeId and fields are required',
166+
};
167+
}
168+
169+
// Create an entry using the CMA client
170+
const entry = await cma.entry.create({
171+
spaceId,
172+
environmentId,
173+
contentTypeId,
174+
fields: Object.entries(fields).reduce((acc, [key, value]) => {
175+
acc[key] = { 'en-US': value };
176+
return acc;
177+
}, {}),
178+
});
179+
180+
return {
181+
success: true,
182+
entry: {
183+
id: entry.sys.id,
184+
contentType: entry.sys.contentType.sys.id,
185+
createdAt: entry.sys.createdAt,
186+
},
187+
};
188+
} catch (error) {
189+
console.error('Error executing App Action:', error);
190+
return {
191+
success: false,
192+
error: error.message || 'An error occurred while processing your request',
193+
};
194+
}
195+
};
196+
```
197+
198+
### 5. Build and Upload Your Function
199+
200+
Currently, the only way to deploy a function is through the CLI. To do so, run the following commands:
201+
202+
```bash
203+
# Build your function
204+
npm run build
205+
206+
# Upload your function to Contentful
207+
npm run upload
208+
```
209+
210+
The build step is essential since the upload process relies on the compiled code. The CLI may prompt for additional details (e.g., the CMA endpoint URL) and offer to activate the bundle post-upload.
211+
212+
> **Note**: For more information on the differences between `upload` and `upload-ci`, see the [Create Contentful App Documentation](https://www.contentful.com/developers/docs/extensibility/app-framework/create-contentful-app/)
213+
214+
### 6. Create an App Action
215+
216+
To make your function accessible, you need to create an App Action that links to it. There are two ways to do this:
217+
218+
#### Via the Contentful Web App
219+
220+
1. Open your app definition in the Contentful web app
221+
2. Navigate to the "App Actions" tab
222+
3. Click "Create App Action" and fill in the required information:
223+
- Name: A descriptive name for your action
224+
- App Action ID: A unique identifier for this action
225+
- Type: Select "Function Invocation"
226+
- Function: Select your uploaded function
227+
4. Click "Create"
228+
229+
#### Via the Command Line
230+
231+
You can programmatically create an App Action using the following command:
232+
233+
```bash
234+
npm run upsert-actions
235+
```
236+
237+
You will need to have set the environment variables described in the [Set Up Your Environment](#3-set-up-your-environment) step.
238+
239+
Alternatively, you can pass them as arguments:
240+
241+
```bash
242+
npm run upsert-actions -- --organizationId=<your_org_id> --definitionId=<your_app_id> --token=<your_token>
243+
```
244+
245+
The `upsert-actions` command will create the App Action if it doesn't exist, or update it if it does, linking it to your function.
246+
247+
If you're adding actions programmatically, you must update the `actions` array in your `contentful-app-manifest.json` file:
248+
249+
```json
250+
"actions": [
251+
{
252+
"id": "yourCustomActionId", // Unique identifier for your action, No Hyphens Allowed
253+
"name": "Your Custom Action Name", // Display name shown in the UI
254+
"type": "function-invocation", // Keep this as is for function-based actions
255+
"functionId": "appactionCall", // Must match the function ID in the functions array
256+
"category": "Custom", // Action category
257+
"parameters": [] // Parameters needed by the action
258+
}
259+
]
260+
```
261+
262+
## Additional Resources
263+
264+
- [Contentful App Functions Documentation](https://www.contentful.com/developers/docs/extensibility/app-framework/functions/)
265+
- [Working with Functions](https://www.contentful.com/developers/docs/extensibility/app-framework/working-with-functions/)
266+
- [App Actions Overview](https://www.contentful.com/developers/docs/extensibility/app-framework/app-actions/)

0 commit comments

Comments
 (0)