Skip to content

Commit 9eede5d

Browse files
committed
Added reference to project from test site.
Moved API key into UmbracoForms.config. Various minor tidy-ups.
1 parent 4948041 commit 9eede5d

File tree

9 files changed

+67
-76
lines changed

9 files changed

+67
-76
lines changed

src/Umbraco.Forms.Extensions.Crm.Hubspot/App_Plugins/UmbracoFormsExtensions/Hubspot/hubspot-field-mapper-template.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
<div>
2+
<!--
23
<pre>{{ vm.setting | json }}</pre>
34
<pre>{{ vm.mappings | json }}</pre>
5+
-->
46

57
<div class="umb-forms-mappings" ng-if="vm.mappings.length > 0 && vm.hubspotFields.length > 0">
68

@@ -18,7 +20,6 @@
1820
ng-options="field.id as field.value for field in vm.fields"
1921
ng-model="mapping.formField"
2022
ng-change="vm.stringifyValue()">
21-
<option value="">Map form field</option>
2223
</select>
2324
</div>
2425

@@ -27,7 +28,6 @@
2728
ng-options="field.value as field.name for field in vm.hubspotFields track by field.value"
2829
ng-model="mapping.hubspotField"
2930
ng-change="vm.stringifyValue()">
30-
<option value="">Map hubspot field</option>
3131
</select>
3232
</div>
3333

src/Umbraco.Forms.Extensions.Crm.Hubspot/App_Plugins/UmbracoFormsExtensions/Hubspot/hubspot.resource.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,12 @@
1010
[{ packageGuid: id }])),
1111
'Failed to download package with guid ' + id);
1212
},
13-
getAllProperties: function (apiKey) {
13+
getAllProperties: function () {
1414
return umbRequestHelper.resourcePromise(
1515
$http.get(
1616
umbRequestHelper.getApiUrl(
1717
"umbracoFormsExtensionsHubspotBaseUrl",
18-
"GetAllProperties",
19-
[{ apiKey: apiKey }])),
18+
"GetAllProperties")),
2019
'Failed to get Hubspot Properties');
2120
},
2221
};

src/Umbraco.Forms.Extensions.Crm.Hubspot/App_Plugins/UmbracoFormsExtensions/Hubspot/hubspotfields.component.js

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,8 @@ function HubSpotFieldsController($scope, $compile, $element, $routeParams, hubsp
3838
vm.fields = response.data;
3939
});
4040

41-
// TODO: Remove hard coded API key & remember to revoke it later on
42-
// Need to get API key from other field
43-
// May need to do parent.parent scope traversal - YUK :S
44-
45-
// Niels recommendation that this is a component & be able to get the data from a parent item
46-
// Using require (but finding which one it is I have no idea)
47-
48-
hubspotResource.getAllProperties('6a488b25-b7e7-489d-ad45-2da52a878ff9').then(function (response) {
49-
vm.hubspotFields = response.map(x =>{
41+
hubspotResource.getAllProperties().then(function (response) {
42+
vm.hubspotFields = response.map(x => {
5043
return {
5144
value: x.name,
5245
name: x.label,
@@ -62,7 +55,7 @@ function HubSpotFieldsController($scope, $compile, $element, $routeParams, hubsp
6255
return x.value === value;
6356
});
6457

65-
if(item){
58+
if (item) {
6659
return item.description;
6760
}
6861

src/Umbraco.Forms.Extensions.Crm.Hubspot/HubspotComponent.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ private void ServerVariablesParser_Parsing(object sender, Dictionary<string, obj
3333
if (HttpContext.Current == null) throw new InvalidOperationException("HttpContext is null");
3434
var urlHelper = new UrlHelper(new RequestContext(new HttpContextWrapper(HttpContext.Current), new RouteData()));
3535

36-
umbracoUrls["umbracoFormsExtensionsHubspotBaseUrl"] = urlHelper.GetUmbracoApiServiceBaseUrl<HubspotController>(controller => controller.GetAllProperties(null));
36+
umbracoUrls["umbracoFormsExtensionsHubspotBaseUrl"] = urlHelper.GetUmbracoApiServiceBaseUrl<HubspotController>(controller => controller.GetAllProperties());
3737
}
3838

3939
public void Terminate()

src/Umbraco.Forms.Extensions.Crm.Hubspot/HubspotController.cs

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
using Newtonsoft.Json;
22
using System;
33
using System.Collections.Generic;
4+
using System.Linq;
45
using System.Net.Http;
6+
using System.Threading.Tasks;
57
using Umbraco.Core.Composing;
68
using Umbraco.Core.Logging;
9+
using Umbraco.Forms.Core;
710
using Umbraco.Web.Editors;
811
using Umbraco.Web.Mvc;
912

@@ -13,17 +16,25 @@ namespace Umbraco.Forms.Extensions.Crm.Hubspot
1316
public class HubspotController : UmbracoAuthorizedJsonController
1417
{
1518
static readonly HttpClient client = new HttpClient();
19+
20+
private readonly IFacadeConfiguration _configuration;
21+
22+
public HubspotController(IFacadeConfiguration configuration)
23+
{
24+
_configuration = configuration;
25+
}
1626

1727
/// <summary>
1828
/// ~/Umbraco/[YourAreaName]/[YourControllerName]
19-
/// ~/Umbraco/FormsExtensions/Hubspot/GetAllProperties?apiKey=123
29+
/// ~/Umbraco/FormsExtensions/Hubspot/GetAllProperties
2030
/// </summary>
21-
/// <param name="apiKey"></param>
2231
/// <returns></returns>
23-
public List<Property> GetAllProperties(string apiKey)
32+
public async Task<IEnumerable<Property>> GetAllProperties()
2433
{
2534
var properties = new List<Property>();
26-
var propertiesApiUrl = new Uri($"https://api.hubapi.com/crm/v3/properties/contacts?hapikey={apiKey}");
35+
var apiKey = _configuration.GetSetting("HubSpotApiKey");
36+
var url = $"https://api.hubapi.com/crm/v3/properties/contacts?hapikey={apiKey}";
37+
var propertiesApiUrl = new Uri(url);
2738

2839
// Map fields we have in settings to these fields/properties in Hubspot
2940
var propertiesResponse = client.GetAsync(propertiesApiUrl).Result;
@@ -33,12 +44,12 @@ public List<Property> GetAllProperties(string apiKey)
3344
Current.Logger.Error<HubspotWorkflow>("Failed to fetch contact properties from HubSpot API for mapping. {StatusCode} {ReasonPhrase}", propertiesResponse.StatusCode, propertiesResponse.ReasonPhrase);
3445
}
3546

36-
// Map Properties back to our simplier object
47+
// Map Properties back to our simpler object
3748
// Don't need all the fields in the response
38-
var rawResult = propertiesResponse.Content.ReadAsStringAsync().Result;
49+
var rawResult = await propertiesResponse.Content.ReadAsStringAsync();
3950
var json = JsonConvert.DeserializeObject<PropertyResult>(rawResult);
4051
properties.AddRange(json.Results);
41-
return properties;
52+
return properties.OrderBy(x => x.Label);
4253
}
4354

4455
public class PropertyResult

src/Umbraco.Forms.Extensions.Crm.Hubspot/HubspotWorkflow.cs

Lines changed: 19 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -15,39 +15,33 @@ namespace Umbraco.Forms.Extensions.Crm.Hubspot
1515
{
1616
public class HubspotWorkflow : WorkflowType
1717
{
18-
public HubspotWorkflow()
18+
static readonly HttpClient client = new HttpClient();
19+
20+
private readonly IFacadeConfiguration _configuration;
21+
22+
public HubspotWorkflow(IFacadeConfiguration configuration)
1923
{
24+
_configuration = configuration;
25+
2026
Id = new Guid("c47ef1ef-22b1-4b9d-acf6-f57cb8961550");
21-
Name = "Hubspot";
22-
Description = "Form submissions are sent to CRM Hubspot";
27+
Name = "Save Contact to Hubspot";
28+
Description = "Form submissions are sent to Hubspot CRM";
2329
Icon = "icon-handshake";
2430
Group = "CRM";
2531
}
2632

27-
[Setting("Hubspot API Key", Description = "Enter the API Key from your HubSpot account", View = "TextField")]
28-
public string HubspotApiKey { get; set; }
29-
3033
[Setting("Field Mappings", Description = "Map Umbraco Form fields to HubSpot contact fields", View = "~/App_Plugins/UmbracoFormsExtensions/Hubspot/hubspotfields.html")]
3134
public string FieldMappings { get; set; }
3235

33-
private Uri HubspotContactApiUrl
34-
{
35-
get
36-
{
37-
return new Uri($"https://api.hubapi.com/crm/v3/objects/contacts?hapikey={HubspotApiKey}");
38-
}
39-
}
40-
41-
static readonly HttpClient client = new HttpClient();
42-
4336
public override WorkflowExecutionStatus Execute(Record record, RecordEventArgs e)
4437
{
4538
// Check Hubspot key is not empty
46-
if (string.IsNullOrWhiteSpace(HubspotApiKey))
39+
var apiKey = _configuration.GetSetting("HubSpotApiKey");
40+
if (string.IsNullOrWhiteSpace(apiKey))
4741
{
4842
// Missing an API Key
4943
// TODO: Can I bubble up a specific message as to why
50-
Current.Logger.Warn<HubspotWorkflow>("Workflow {WorkflowName}: No API key has been set for the Hubspot workflow for the form {FormName} ({FormId})", Workflow.Name, e.Form.Name, e.Form.Id);
44+
Current.Logger.Warn<HubspotWorkflow>("Workflow {WorkflowName}: No API key has been configurated for the 'Save Contact to HubSpot' the form {FormName} ({FormId})", Workflow.Name, e.Form.Name, e.Form.Id);
5145
return WorkflowExecutionStatus.NotConfigured;
5246
}
5347

@@ -87,10 +81,11 @@ public override WorkflowExecutionStatus Execute(Record record, RecordEventArgs e
8781

8882
// POST data to hubspot
8983
// https://api.hubapi.com/crm/v3/objects/contacts?hapikey=YOUR_HUBSPOT_API_KEY
90-
var postResponse = client.PostAsync(HubspotContactApiUrl, content).Result;
84+
var url = $"https://api.hubapi.com/crm/v3/objects/contacts?hapikey={apiKey}";
85+
var postResponse = client.PostAsync(url, content).GetAwaiter().GetResult();
9186

9287
// Depending on POST status fail or mark workflow as completed
93-
if(postResponse.IsSuccessStatusCode == false)
88+
if (postResponse.IsSuccessStatusCode == false)
9489
{
9590
// LOG THE ERROR
9691
Current.Logger.Warn<HubspotWorkflow>("Workflow {WorkflowName}: Error submitting data to Hubspot for the form {FormName} ({FormId})", Workflow.Name, e.Form.Name, e.Form.Id);
@@ -99,48 +94,19 @@ public override WorkflowExecutionStatus Execute(Record record, RecordEventArgs e
9994

10095
// TODO:
10196
// Is it worth logging the success that it got created in HubSpot with its ID etc in response
102-
var rawResult = postResponse.Content.ReadAsStringAsync().Result;
103-
97+
// Can get full response with: postResponse.Content.ReadAsStringAsync().GetAwaiter().GetResult();
10498

10599
return WorkflowExecutionStatus.Completed;
106100
}
107101

108102
public override List<Exception> ValidateSettings()
109103
{
110104
var errors = new List<Exception>();
111-
112-
// Verify API key is not empty
113-
if (string.IsNullOrWhiteSpace(HubspotApiKey))
114-
{
115-
errors.Add(new Exception("Hubspot API key is missing"));
116-
return errors;
117-
}
118-
119-
// Make a super simple GET request to fetch contacts in HubSpot
120-
// This way with we can verify that the API key is valid
121-
// https://developers.hubspot.com/docs/api/crm/contacts
122-
var testResponse = client.GetAsync(HubspotContactApiUrl).Result;
123-
124-
if (testResponse.IsSuccessStatusCode == false)
125-
{
126-
// Invalid key will return a 401
127-
// Message property of response contains useful message
128-
// The API key provided is invalid. View or manage your API key here: https://app.hubspot.com/l/api-key/
129-
var errorResponse = testResponse.Content.ReadAsStringAsync().Result;
130-
var errorObj = JsonConvert.DeserializeObject<ErrorResponse>(errorResponse);
131-
var ex = new Exception(errorObj.message);
132-
errors.Add(ex);
133-
134-
// Log the error
135-
// TODO: Unable to get Form Name & Form ID for logging context properties
136-
Current.Logger.Error<HubspotWorkflow>(ex, "Workflow {WorkflowName}: Error checking HubSpot Connection for {FormName} ({FormId})", Workflow.Name);
137-
}
138-
139105
return errors;
140106
}
141107
}
142108

143-
public class PropertiesPost
109+
internal class PropertiesPost
144110
{
145111
public PropertiesPost()
146112
{
@@ -152,7 +118,7 @@ public PropertiesPost()
152118
public JObject Properties { get; set; }
153119
}
154120

155-
public class MappedProperty
121+
internal class MappedProperty
156122
{
157123
[JsonProperty(PropertyName = "formField")]
158124
public string FormField { get; set; }
@@ -161,7 +127,7 @@ public class MappedProperty
161127
public string HubspotField { get; set; }
162128
}
163129

164-
public class ErrorResponse
130+
internal class ErrorResponse
165131
{
166132
public string message { get; set; }
167133
}

src/Umbraco.Forms.Extensions.Crm.Hubspot/Umbraco.Forms.Extensions.Crm.Hubspot.csproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,8 @@
2222
<PackageReference Include="UmbracoForms.Core" Version="8.7.4" />
2323
</ItemGroup>
2424

25+
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
26+
<Exec Command="xcopy /E /Y /I &quot;$(ProjectDir)App_Plugins\UmbracoFormsExtensions&quot; &quot;$(SolutionDir)\Umbraco.Forms.Extensions.TestSite\App_Plugins\UmbracoFormsExtensions&quot;&#xD;&#xA;EXIT 0" />
27+
</Target>
28+
2529
</Project>

src/Umbraco.Forms.Extensions.Crm.Hubspot/readme.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,18 @@
11
# Umbraco.Forms.Extensions.Crm.Hubspot
22
This adds a Hubspot extension to your Umbraco Forms installation
33

4+
## How To Use
5+
6+
Log into your HubSpot account, go to _Settings > Integrations > API Key_ and create an API key.
7+
8+
Add this to a setting in `UmbracoForms.config`:
9+
10+
```
11+
<setting key="HubSpotApiKey" value="[your API key]" />
12+
```
13+
14+
Add the "Save Contact to Hubspot" workflow to a form and configure the mappings between the form and Hubspot fields.
15+
416
## Research
517
Hubspot allows you to add additional fields to a Contact but they seem you can only choose from a pre-determined list
618
This UI can also set required fields, so what should the workflow do if it does not provide the data required

src/Umbraco.Forms.Extensions.TestSite/Umbraco.Forms.Extensions.TestSite.csproj

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -567,6 +567,12 @@
567567
<DependentUpon>Web.config</DependentUpon>
568568
</None>
569569
</ItemGroup>
570+
<ItemGroup>
571+
<ProjectReference Include="..\Umbraco.Forms.Extensions.Crm.Hubspot\Umbraco.Forms.Extensions.Crm.Hubspot.csproj">
572+
<Project>{e7f3f2cc-dcb6-4158-aaba-d2ea9e1b9fa8}</Project>
573+
<Name>Umbraco.Forms.Extensions.Crm.Hubspot</Name>
574+
</ProjectReference>
575+
</ItemGroup>
570576
<PropertyGroup>
571577
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
572578
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>

0 commit comments

Comments
 (0)