diff --git a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Api/Management/Controllers/Contacts/AuthorizeController.cs b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Api/Management/Controllers/Contacts/AuthorizeController.cs index cfcb8ed..42f0903 100644 --- a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Api/Management/Controllers/Contacts/AuthorizeController.cs +++ b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Api/Management/Controllers/Contacts/AuthorizeController.cs @@ -1,10 +1,5 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using Umbraco.Forms.Integrations.Crm.Hubspot.Models.Dtos; using Umbraco.Forms.Integrations.Crm.Hubspot.Services; @@ -17,7 +12,7 @@ public AuthorizeController(IContactService contactService) : base(contactService } [HttpPost("authorize")] - [ProducesResponseType(typeof(Task), StatusCodes.Status200OK)] - public async Task Authorize([FromBody] AuthorizationRequest request) => Ok(await ContactService.AuthorizeAsync(request.Code)); + [ProducesResponseType(typeof(AuthorizationResult), StatusCodes.Status200OK)] + public async Task Authorize([FromBody]AuthorizationRequest request) => Ok(await ContactService.AuthorizeAsync(request.Code)); } } diff --git a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Api/Management/Controllers/Contacts/ContactControllerBase.cs b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Api/Management/Controllers/Contacts/ContactControllerBase.cs index 6634181..097a8ec 100644 --- a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Api/Management/Controllers/Contacts/ContactControllerBase.cs +++ b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Api/Management/Controllers/Contacts/ContactControllerBase.cs @@ -1,10 +1,5 @@ using Asp.Versioning; using Microsoft.AspNetCore.Mvc; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using Umbraco.Cms.Web.Common.Routing; using Umbraco.Forms.Integrations.Crm.Hubspot.Services; diff --git a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Api/Management/Controllers/Contacts/DeauthorizeController.cs b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Api/Management/Controllers/Contacts/DeauthorizeController.cs index 2868958..5c06f8f 100644 --- a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Api/Management/Controllers/Contacts/DeauthorizeController.cs +++ b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Api/Management/Controllers/Contacts/DeauthorizeController.cs @@ -1,10 +1,5 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using Umbraco.Forms.Integrations.Crm.Hubspot.Models.Dtos; using Umbraco.Forms.Integrations.Crm.Hubspot.Services; diff --git a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Api/Management/Controllers/Contacts/GetAllPropertiesController.cs b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Api/Management/Controllers/Contacts/GetAllPropertiesController.cs index 897a379..56a513e 100644 --- a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Api/Management/Controllers/Contacts/GetAllPropertiesController.cs +++ b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Api/Management/Controllers/Contacts/GetAllPropertiesController.cs @@ -1,11 +1,5 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Umbraco.Cms.Web.Common.Attributes; using Umbraco.Forms.Integrations.Crm.Hubspot.Models.Responses; using Umbraco.Forms.Integrations.Crm.Hubspot.Services; diff --git a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Api/Management/Controllers/Contacts/GetAuthenticationUrlController.cs b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Api/Management/Controllers/Contacts/GetAuthenticationUrlController.cs index 1c1a30e..a51f409 100644 --- a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Api/Management/Controllers/Contacts/GetAuthenticationUrlController.cs +++ b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Api/Management/Controllers/Contacts/GetAuthenticationUrlController.cs @@ -1,10 +1,5 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using Umbraco.Forms.Integrations.Crm.Hubspot.Services; namespace Umbraco.Forms.Integrations.Crm.Hubspot.Api.Management.Controllers.Contacts diff --git a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Api/Management/Controllers/Contacts/IsAuthorizationConfiguredController.cs b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Api/Management/Controllers/Contacts/IsAuthorizationConfiguredController.cs index 71b6437..ece49a8 100644 --- a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Api/Management/Controllers/Contacts/IsAuthorizationConfiguredController.cs +++ b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Api/Management/Controllers/Contacts/IsAuthorizationConfiguredController.cs @@ -1,10 +1,5 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using Umbraco.Forms.Integrations.Crm.Hubspot.Services; namespace Umbraco.Forms.Integrations.Crm.Hubspot.Api.Management.Controllers.Contacts diff --git a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Api/Management/Controllers/Forms/FormControllerBase.cs b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Api/Management/Controllers/Forms/FormControllerBase.cs new file mode 100644 index 0000000..de9babb --- /dev/null +++ b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Api/Management/Controllers/Forms/FormControllerBase.cs @@ -0,0 +1,20 @@ +using Asp.Versioning; +using Microsoft.AspNetCore.Mvc; +using Umbraco.Cms.Web.Common.Routing; +using Umbraco.Forms.Core.Services; + +namespace Umbraco.Forms.Integrations.Crm.Hubspot.Api.Management.Controllers.Forms +{ + [ApiVersion("1.0")] + [BackOfficeRoute($"{Constants.ManagementApi.RootPath}/v{{version:apiVersion}}/forms")] + [ApiExplorerSettings(GroupName = Constants.ManagementApi.FormGroupName)] + public class FormControllerBase : HubspotControllerBase + { + protected readonly IFormService FormService; + + public FormControllerBase(IFormService formService) + { + FormService = formService; + } + } +} diff --git a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Api/Management/Controllers/Forms/GetFormFieldsController.cs b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Api/Management/Controllers/Forms/GetFormFieldsController.cs new file mode 100644 index 0000000..4cb17fb --- /dev/null +++ b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Api/Management/Controllers/Forms/GetFormFieldsController.cs @@ -0,0 +1,27 @@ +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Umbraco.Forms.Core.Services; +using Umbraco.Forms.Integrations.Crm.Hubspot.Models.Dtos; + +namespace Umbraco.Forms.Integrations.Crm.Hubspot.Api.Management.Controllers.Forms +{ + public class GetFormFieldsController : FormControllerBase + { + public GetFormFieldsController(IFormService formService) : base(formService) + { + } + + [HttpGet("fields")] + [ProducesResponseType(typeof(List), StatusCodes.Status200OK)] + public IActionResult GetFormFields(string formId) + { + List formFields = new List(); + var result = FormService.Get(new Guid(formId)); + if (result != null) + { + formFields = result.AllFields.Select(s => new HubspotWorkflowFormFieldDto{ Caption = s.Caption, Id = s.Id }).ToList(); + } + return Ok(formFields); + } + } +} diff --git a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Api/Management/Controllers/HubspotControllerBase.cs b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Api/Management/Controllers/HubspotControllerBase.cs index e8f0291..b6b0dd0 100644 --- a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Api/Management/Controllers/HubspotControllerBase.cs +++ b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Api/Management/Controllers/HubspotControllerBase.cs @@ -1,14 +1,7 @@ -using Asp.Versioning; -using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using Umbraco.Cms.Api.Common.Attributes; using Umbraco.Cms.Web.Common.Authorization; -using Umbraco.Cms.Web.Common.Routing; namespace Umbraco.Forms.Integrations.Crm.Hubspot.Api.Management.Controllers { diff --git a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Client/config.outputPath.js b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Client/config.outputPath.js index af43f9b..ebdac79 100644 --- a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Client/config.outputPath.js +++ b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Client/config.outputPath.js @@ -1 +1 @@ -export const outputPath = 'Debug' !== 'Release' ? '../wwwroot' : '../obj/Debug/net8.0/clientassets' \ No newline at end of file +export const outputPath = 'Debug' !== 'Release' ? '../wwwroot' : '../obj/Debug/net8.0/clientassets' diff --git a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Client/generated/services.gen.ts b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Client/generated/services.gen.ts index 7b58f15..db02f2f 100644 --- a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Client/generated/services.gen.ts +++ b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Client/generated/services.gen.ts @@ -3,7 +3,7 @@ import type { CancelablePromise } from './core/CancelablePromise'; import { OpenAPI } from './core/OpenAPI'; import { request as __request } from './core/request'; -import type { IsAuthorizationConfiguredResponse, GetAuthenticationUrlResponse, AuthorizeData, AuthorizeResponse, DeauthorizeResponse, GetAllResponse } from './types.gen'; +import type { IsAuthorizationConfiguredResponse, GetAuthenticationUrlResponse, AuthorizeData, AuthorizeResponse, DeauthorizeResponse, GetAllResponse, GetFormFieldsData, GetFormFieldsResponse } from './types.gen'; export class ContactsService { /** @@ -65,4 +65,23 @@ export class ContactsService { }); } +} + +export class FormsService { + /** + * @param data The data for the request. + * @param data.formId + * @returns unknown OK + * @throws ApiError + */ + public static getFormFields(data: GetFormFieldsData = {}): CancelablePromise { + return __request(OpenAPI, { + method: 'GET', + url: '/umbraco/hubspot/management/api/v1/forms/fields', + query: { + formId: data.formId + } + }); + } + } \ No newline at end of file diff --git a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Client/generated/types.gen.ts b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Client/generated/types.gen.ts index 0006be4..726f04c 100644 --- a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Client/generated/types.gen.ts +++ b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Client/generated/types.gen.ts @@ -1,49 +1,5 @@ // This file is auto-generated by @hey-api/openapi-ts -export type AggregateException = { - readonly targetSite?: MethodBase | null; - readonly data: { - [key: string]: unknown; - }; - readonly innerException?: Exception | null; - helpLink?: string | null; - source?: string | null; - hResult: number; - readonly stackTrace?: string | null; - readonly innerExceptions: Array<(Exception)>; - readonly message: string; -}; - -export type Assembly = { - readonly definedTypes: Array<(TypeInfo)>; - readonly exportedTypes: Array<(Type)>; - /** - * @deprecated - */ - readonly codeBase?: string | null; - readonly entryPoint?: MethodInfo | null; - readonly fullName?: string | null; - readonly imageRuntimeVersion: string; - readonly isDynamic: boolean; - readonly location: string; - readonly reflectionOnly: boolean; - readonly isCollectible: boolean; - readonly isFullyTrusted: boolean; - readonly customAttributes: Array<(CustomAttributeData)>; - /** - * @deprecated - */ - readonly escapedCodeBase: string; - readonly manifestModule: Module; - readonly modules: Array<(Module)>; - /** - * @deprecated - */ - readonly globalAssemblyCache: boolean; - readonly hostContext: number; - securityRuleSet: SecurityRuleSet; -}; - export type AuthorizationRequest = { code: string; }; @@ -53,93 +9,6 @@ export type AuthorizationResult = { readonly errorMessage: string; }; -export enum CallingConventions { - STANDARD = 'Standard', - VAR_ARGS = 'VarArgs', - ANY = 'Any', - HAS_THIS = 'HasThis', - EXPLICIT_THIS = 'ExplicitThis' -} - -export type ConstructorInfo = { - readonly name: string; - readonly declaringType?: Type | null; - readonly reflectedType?: Type | null; - readonly module: Module; - readonly customAttributes: Array<(CustomAttributeData)>; - readonly isCollectible: boolean; - readonly metadataToken: number; - attributes: MethodAttributes; - methodImplementationFlags: MethodImplAttributes; - callingConvention: CallingConventions; - readonly isAbstract: boolean; - readonly isConstructor: boolean; - readonly isFinal: boolean; - readonly isHideBySig: boolean; - readonly isSpecialName: boolean; - readonly isStatic: boolean; - readonly isVirtual: boolean; - readonly isAssembly: boolean; - readonly isFamily: boolean; - readonly isFamilyAndAssembly: boolean; - readonly isFamilyOrAssembly: boolean; - readonly isPrivate: boolean; - readonly isPublic: boolean; - readonly isConstructedGenericMethod: boolean; - readonly isGenericMethod: boolean; - readonly isGenericMethodDefinition: boolean; - readonly containsGenericParameters: boolean; - readonly methodHandle: RuntimeMethodHandle; - readonly isSecurityCritical: boolean; - readonly isSecuritySafeCritical: boolean; - readonly isSecurityTransparent: boolean; - memberType: MemberTypes; -}; - -export type CustomAttributeData = { - readonly attributeType: Type; - readonly constructor: ConstructorInfo; - readonly constructorArguments: Array<(CustomAttributeTypedArgument)>; - readonly namedArguments: Array<(CustomAttributeNamedArgument)>; -}; - -export type CustomAttributeNamedArgument = { - memberInfo: MemberInfo; - readonly typedValue: CustomAttributeTypedArgument; - readonly memberName: string; - readonly isField: boolean; -}; - -export type CustomAttributeTypedArgument = { - argumentType: Type; - value?: unknown; -}; - -export enum EventAttributes { - NONE = 'None', - SPECIAL_NAME = 'SpecialName', - RTSPECIAL_NAME = 'RTSpecialName', - RESERVED_MASK = 'ReservedMask' -} - -export type EventInfo = { - readonly name: string; - readonly declaringType?: Type | null; - readonly reflectedType?: Type | null; - readonly module: Module; - readonly customAttributes: Array<(CustomAttributeData)>; - readonly isCollectible: boolean; - readonly metadataToken: number; - memberType: MemberTypes; - attributes: EventAttributes; - readonly isSpecialName: boolean; - readonly addMethod?: MethodInfo | null; - readonly removeMethod?: MethodInfo | null; - readonly raiseMethod?: MethodInfo | null; - readonly isMulticast: boolean; - readonly eventHandlerType?: Type | null; -}; - export enum EventMessageTypeModel { DEFAULT = 'Default', INFO = 'Info', @@ -148,255 +17,9 @@ export enum EventMessageTypeModel { WARNING = 'Warning' } -export type Exception = { - readonly targetSite?: MethodBase | null; - readonly message: string; - readonly data: { - [key: string]: unknown; - }; - readonly innerException?: Exception | null; - helpLink?: string | null; - source?: string | null; - hResult: number; - readonly stackTrace?: string | null; -}; - -export enum FieldAttributes { - PRIVATE_SCOPE = 'PrivateScope', - PRIVATE = 'Private', - FAM_ANDASSEM = 'FamANDAssem', - ASSEMBLY = 'Assembly', - FAMILY = 'Family', - FAM_ORASSEM = 'FamORAssem', - PUBLIC = 'Public', - FIELD_ACCESS_MASK = 'FieldAccessMask', - STATIC = 'Static', - INIT_ONLY = 'InitOnly', - LITERAL = 'Literal', - NOT_SERIALIZED = 'NotSerialized', - HAS_FIELD_RVA = 'HasFieldRVA', - SPECIAL_NAME = 'SpecialName', - RTSPECIAL_NAME = 'RTSpecialName', - HAS_FIELD_MARSHAL = 'HasFieldMarshal', - PINVOKE_IMPL = 'PinvokeImpl', - HAS_DEFAULT = 'HasDefault', - RESERVED_MASK = 'ReservedMask' -} - -export type FieldInfo = { - readonly name: string; - readonly declaringType?: Type | null; - readonly reflectedType?: Type | null; - readonly module: Module; - readonly customAttributes: Array<(CustomAttributeData)>; - readonly isCollectible: boolean; - readonly metadataToken: number; - memberType: MemberTypes; - attributes: FieldAttributes; - readonly fieldType: Type; - readonly isInitOnly: boolean; - readonly isLiteral: boolean; - /** - * @deprecated - */ - readonly isNotSerialized: boolean; - readonly isPinvokeImpl: boolean; - readonly isSpecialName: boolean; - readonly isStatic: boolean; - readonly isAssembly: boolean; - readonly isFamily: boolean; - readonly isFamilyAndAssembly: boolean; - readonly isFamilyOrAssembly: boolean; - readonly isPrivate: boolean; - readonly isPublic: boolean; - readonly isSecurityCritical: boolean; - readonly isSecuritySafeCritical: boolean; - readonly isSecurityTransparent: boolean; - readonly fieldHandle: RuntimeFieldHandle; -}; - -export enum GenericParameterAttributes { - NONE = 'None', - COVARIANT = 'Covariant', - CONTRAVARIANT = 'Contravariant', - VARIANCE_MASK = 'VarianceMask', - REFERENCE_TYPE_CONSTRAINT = 'ReferenceTypeConstraint', - NOT_NULLABLE_VALUE_TYPE_CONSTRAINT = 'NotNullableValueTypeConstraint', - DEFAULT_CONSTRUCTOR_CONSTRAINT = 'DefaultConstructorConstraint', - SPECIAL_CONSTRAINT_MASK = 'SpecialConstraintMask' -} - -export type ICustomAttributeProvider = { - [key: string]: unknown; -}; - -export type IntPtr = { - [key: string]: unknown; -}; - -export enum LayoutKind { - SEQUENTIAL = 'Sequential', - EXPLICIT = 'Explicit', - AUTO = 'Auto' -} - -export type MemberInfo = { - memberType: MemberTypes; - readonly name: string; - readonly declaringType?: Type | null; - readonly reflectedType?: Type | null; - readonly module: Module; - readonly customAttributes: Array<(CustomAttributeData)>; - readonly isCollectible: boolean; - readonly metadataToken: number; -}; - -export enum MemberTypes { - CONSTRUCTOR = 'Constructor', - EVENT = 'Event', - FIELD = 'Field', - METHOD = 'Method', - PROPERTY = 'Property', - TYPE_INFO = 'TypeInfo', - CUSTOM = 'Custom', - NESTED_TYPE = 'NestedType', - ALL = 'All' -} - -export enum MethodAttributes { - PRIVATE_SCOPE = 'PrivateScope', - REUSE_SLOT = 'ReuseSlot', - PRIVATE = 'Private', - FAM_ANDASSEM = 'FamANDAssem', - ASSEMBLY = 'Assembly', - FAMILY = 'Family', - FAM_ORASSEM = 'FamORAssem', - PUBLIC = 'Public', - MEMBER_ACCESS_MASK = 'MemberAccessMask', - UNMANAGED_EXPORT = 'UnmanagedExport', - STATIC = 'Static', - FINAL = 'Final', - VIRTUAL = 'Virtual', - HIDE_BY_SIG = 'HideBySig', - NEW_SLOT = 'NewSlot', - VTABLE_LAYOUT_MASK = 'VtableLayoutMask', - CHECK_ACCESS_ON_OVERRIDE = 'CheckAccessOnOverride', - ABSTRACT = 'Abstract', - SPECIAL_NAME = 'SpecialName', - RTSPECIAL_NAME = 'RTSpecialName', - PINVOKE_IMPL = 'PinvokeImpl', - HAS_SECURITY = 'HasSecurity', - REQUIRE_SEC_OBJECT = 'RequireSecObject', - RESERVED_MASK = 'ReservedMask' -} - -export type MethodBase = { - memberType: MemberTypes; - readonly name: string; - readonly declaringType?: Type | null; - readonly reflectedType?: Type | null; - readonly module: Module; - readonly customAttributes: Array<(CustomAttributeData)>; - readonly isCollectible: boolean; - readonly metadataToken: number; - attributes: MethodAttributes; - methodImplementationFlags: MethodImplAttributes; - callingConvention: CallingConventions; - readonly isAbstract: boolean; - readonly isConstructor: boolean; - readonly isFinal: boolean; - readonly isHideBySig: boolean; - readonly isSpecialName: boolean; - readonly isStatic: boolean; - readonly isVirtual: boolean; - readonly isAssembly: boolean; - readonly isFamily: boolean; - readonly isFamilyAndAssembly: boolean; - readonly isFamilyOrAssembly: boolean; - readonly isPrivate: boolean; - readonly isPublic: boolean; - readonly isConstructedGenericMethod: boolean; - readonly isGenericMethod: boolean; - readonly isGenericMethodDefinition: boolean; - readonly containsGenericParameters: boolean; - readonly methodHandle: RuntimeMethodHandle; - readonly isSecurityCritical: boolean; - readonly isSecuritySafeCritical: boolean; - readonly isSecurityTransparent: boolean; -}; - -export enum MethodImplAttributes { - IL = 'IL', - MANAGED = 'Managed', - NATIVE = 'Native', - OPTIL = 'OPTIL', - CODE_TYPE_MASK = 'CodeTypeMask', - RUNTIME = 'Runtime', - MANAGED_MASK = 'ManagedMask', - UNMANAGED = 'Unmanaged', - NO_INLINING = 'NoInlining', - FORWARD_REF = 'ForwardRef', - SYNCHRONIZED = 'Synchronized', - NO_OPTIMIZATION = 'NoOptimization', - PRESERVE_SIG = 'PreserveSig', - AGGRESSIVE_INLINING = 'AggressiveInlining', - AGGRESSIVE_OPTIMIZATION = 'AggressiveOptimization', - INTERNAL_CALL = 'InternalCall', - MAX_METHOD_IMPL_VAL = 'MaxMethodImplVal' -} - -export type MethodInfo = { - readonly name: string; - readonly declaringType?: Type | null; - readonly reflectedType?: Type | null; - readonly module: Module; - readonly customAttributes: Array<(CustomAttributeData)>; - readonly isCollectible: boolean; - readonly metadataToken: number; - attributes: MethodAttributes; - methodImplementationFlags: MethodImplAttributes; - callingConvention: CallingConventions; - readonly isAbstract: boolean; - readonly isConstructor: boolean; - readonly isFinal: boolean; - readonly isHideBySig: boolean; - readonly isSpecialName: boolean; - readonly isStatic: boolean; - readonly isVirtual: boolean; - readonly isAssembly: boolean; - readonly isFamily: boolean; - readonly isFamilyAndAssembly: boolean; - readonly isFamilyOrAssembly: boolean; - readonly isPrivate: boolean; - readonly isPublic: boolean; - readonly isConstructedGenericMethod: boolean; - readonly isGenericMethod: boolean; - readonly isGenericMethodDefinition: boolean; - readonly containsGenericParameters: boolean; - readonly methodHandle: RuntimeMethodHandle; - readonly isSecurityCritical: boolean; - readonly isSecuritySafeCritical: boolean; - readonly isSecurityTransparent: boolean; - memberType: MemberTypes; - readonly returnParameter: ParameterInfo; - readonly returnType: Type; - returnTypeCustomAttributes: ICustomAttributeProvider; -}; - -export type Module = { - readonly assembly: Assembly; - readonly fullyQualifiedName: string; - readonly name: string; - readonly mdStreamVersion: number; - readonly moduleVersionId: string; - readonly scopeName: string; - readonly moduleHandle: ModuleHandle; - readonly customAttributes: Array<(CustomAttributeData)>; - readonly metadataToken: number; -}; - -export type ModuleHandle = { - readonly mdStreamVersion: number; +export type HubspotWorkflowFormFieldDto = { + caption: string; + id: string; }; export type NotificationHeaderModel = { @@ -405,332 +28,12 @@ export type NotificationHeaderModel = { type: EventMessageTypeModel; }; -export enum ParameterAttributes { - NONE = 'None', - IN = 'In', - OUT = 'Out', - LCID = 'Lcid', - RETVAL = 'Retval', - OPTIONAL = 'Optional', - HAS_DEFAULT = 'HasDefault', - HAS_FIELD_MARSHAL = 'HasFieldMarshal', - RESERVED3 = 'Reserved3', - RESERVED4 = 'Reserved4', - RESERVED_MASK = 'ReservedMask' -} - -export type ParameterInfo = { - attributes: ParameterAttributes; - readonly member: MemberInfo; - readonly name?: string | null; - readonly parameterType: Type; - readonly position: number; - readonly isIn: boolean; - readonly isLcid: boolean; - readonly isOptional: boolean; - readonly isOut: boolean; - readonly isRetval: boolean; - readonly defaultValue?: unknown; - readonly rawDefaultValue?: unknown; - readonly hasDefaultValue: boolean; - readonly customAttributes: Array<(CustomAttributeData)>; - readonly metadataToken: number; -}; - export type Property = { name: string; label: string; description: string; }; -export enum PropertyAttributes { - NONE = 'None', - SPECIAL_NAME = 'SpecialName', - RTSPECIAL_NAME = 'RTSpecialName', - HAS_DEFAULT = 'HasDefault', - RESERVED2 = 'Reserved2', - RESERVED3 = 'Reserved3', - RESERVED4 = 'Reserved4', - RESERVED_MASK = 'ReservedMask' -} - -export type PropertyInfo = { - readonly name: string; - readonly declaringType?: Type | null; - readonly reflectedType?: Type | null; - readonly module: Module; - readonly customAttributes: Array<(CustomAttributeData)>; - readonly isCollectible: boolean; - readonly metadataToken: number; - memberType: MemberTypes; - readonly propertyType: Type; - attributes: PropertyAttributes; - readonly isSpecialName: boolean; - readonly canRead: boolean; - readonly canWrite: boolean; - readonly getMethod?: MethodInfo | null; - readonly setMethod?: MethodInfo | null; -}; - -export type RuntimeFieldHandle = { - readonly value: IntPtr; -}; - -export type RuntimeMethodHandle = { - readonly value: IntPtr; -}; - -export type RuntimeTypeHandle = { - readonly value: IntPtr; -}; - -export enum SecurityRuleSet { - NONE = 'None', - LEVEL1 = 'Level1', - LEVEL2 = 'Level2' -} - -export type StructLayoutAttribute = { - readonly typeId: unknown; - value: LayoutKind; -}; - -export enum TaskCreationOptions { - NONE = 'None', - PREFER_FAIRNESS = 'PreferFairness', - LONG_RUNNING = 'LongRunning', - ATTACHED_TO_PARENT = 'AttachedToParent', - DENY_CHILD_ATTACH = 'DenyChildAttach', - HIDE_SCHEDULER = 'HideScheduler', - RUN_CONTINUATIONS_ASYNCHRONOUSLY = 'RunContinuationsAsynchronously' -} - -export enum TaskStatus { - CREATED = 'Created', - WAITING_FOR_ACTIVATION = 'WaitingForActivation', - WAITING_TO_RUN = 'WaitingToRun', - RUNNING = 'Running', - WAITING_FOR_CHILDREN_TO_COMPLETE = 'WaitingForChildrenToComplete', - RAN_TO_COMPLETION = 'RanToCompletion', - CANCELED = 'Canceled', - FAULTED = 'Faulted' -} - -export type Task_1 = { - readonly id: number; - readonly exception?: AggregateException | null; - status: TaskStatus; - readonly isCanceled: boolean; - readonly isCompleted: boolean; - readonly isCompletedSuccessfully: boolean; - creationOptions: TaskCreationOptions; - readonly asyncState?: unknown; - readonly isFaulted: boolean; - readonly result: AuthorizationResult; -}; - -export type Type = { - readonly name: string; - readonly customAttributes: Array<(CustomAttributeData)>; - readonly isCollectible: boolean; - readonly metadataToken: number; - readonly isInterface: boolean; - memberType: MemberTypes; - readonly namespace?: string | null; - readonly assemblyQualifiedName?: string | null; - readonly fullName?: string | null; - readonly assembly: Assembly; - readonly module: Module; - readonly isNested: boolean; - readonly declaringType?: Type | null; - readonly declaringMethod?: MethodBase | null; - readonly reflectedType?: Type | null; - readonly underlyingSystemType: Type; - readonly isTypeDefinition: boolean; - readonly isArray: boolean; - readonly isByRef: boolean; - readonly isPointer: boolean; - readonly isConstructedGenericType: boolean; - readonly isGenericParameter: boolean; - readonly isGenericTypeParameter: boolean; - readonly isGenericMethodParameter: boolean; - readonly isGenericType: boolean; - readonly isGenericTypeDefinition: boolean; - readonly isSZArray: boolean; - readonly isVariableBoundArray: boolean; - readonly isByRefLike: boolean; - readonly isFunctionPointer: boolean; - readonly isUnmanagedFunctionPointer: boolean; - readonly hasElementType: boolean; - readonly genericTypeArguments: Array<(Type)>; - readonly genericParameterPosition: number; - genericParameterAttributes: GenericParameterAttributes; - attributes: TypeAttributes; - readonly isAbstract: boolean; - readonly isImport: boolean; - readonly isSealed: boolean; - readonly isSpecialName: boolean; - readonly isClass: boolean; - readonly isNestedAssembly: boolean; - readonly isNestedFamANDAssem: boolean; - readonly isNestedFamily: boolean; - readonly isNestedFamORAssem: boolean; - readonly isNestedPrivate: boolean; - readonly isNestedPublic: boolean; - readonly isNotPublic: boolean; - readonly isPublic: boolean; - readonly isAutoLayout: boolean; - readonly isExplicitLayout: boolean; - readonly isLayoutSequential: boolean; - readonly isAnsiClass: boolean; - readonly isAutoClass: boolean; - readonly isUnicodeClass: boolean; - readonly isCOMObject: boolean; - readonly isContextful: boolean; - readonly isEnum: boolean; - readonly isMarshalByRef: boolean; - readonly isPrimitive: boolean; - readonly isValueType: boolean; - readonly isSignatureType: boolean; - readonly isSecurityCritical: boolean; - readonly isSecuritySafeCritical: boolean; - readonly isSecurityTransparent: boolean; - readonly structLayoutAttribute?: StructLayoutAttribute | null; - readonly typeInitializer?: ConstructorInfo | null; - readonly typeHandle: RuntimeTypeHandle; - readonly guid: string; - readonly baseType?: Type | null; - /** - * @deprecated - */ - readonly isSerializable: boolean; - readonly containsGenericParameters: boolean; - readonly isVisible: boolean; -}; - -export enum TypeAttributes { - NOT_PUBLIC = 'NotPublic', - AUTO_LAYOUT = 'AutoLayout', - ANSI_CLASS = 'AnsiClass', - CLASS = 'Class', - PUBLIC = 'Public', - NESTED_PUBLIC = 'NestedPublic', - NESTED_PRIVATE = 'NestedPrivate', - NESTED_FAMILY = 'NestedFamily', - NESTED_ASSEMBLY = 'NestedAssembly', - NESTED_FAM_ANDASSEM = 'NestedFamANDAssem', - VISIBILITY_MASK = 'VisibilityMask', - NESTED_FAM_ORASSEM = 'NestedFamORAssem', - SEQUENTIAL_LAYOUT = 'SequentialLayout', - EXPLICIT_LAYOUT = 'ExplicitLayout', - LAYOUT_MASK = 'LayoutMask', - INTERFACE = 'Interface', - CLASS_SEMANTICS_MASK = 'ClassSemanticsMask', - ABSTRACT = 'Abstract', - SEALED = 'Sealed', - SPECIAL_NAME = 'SpecialName', - RTSPECIAL_NAME = 'RTSpecialName', - IMPORT = 'Import', - SERIALIZABLE = 'Serializable', - WINDOWS_RUNTIME = 'WindowsRuntime', - UNICODE_CLASS = 'UnicodeClass', - AUTO_CLASS = 'AutoClass', - STRING_FORMAT_MASK = 'StringFormatMask', - CUSTOM_FORMAT_CLASS = 'CustomFormatClass', - HAS_SECURITY = 'HasSecurity', - RESERVED_MASK = 'ReservedMask', - BEFORE_FIELD_INIT = 'BeforeFieldInit', - CUSTOM_FORMAT_MASK = 'CustomFormatMask' -} - -export type TypeInfo = { - readonly name: string; - readonly customAttributes: Array<(CustomAttributeData)>; - readonly isCollectible: boolean; - readonly metadataToken: number; - readonly isInterface: boolean; - memberType: MemberTypes; - readonly namespace?: string | null; - readonly assemblyQualifiedName?: string | null; - readonly fullName?: string | null; - readonly assembly: Assembly; - readonly module: Module; - readonly isNested: boolean; - readonly declaringType?: Type | null; - readonly declaringMethod?: MethodBase | null; - readonly reflectedType?: Type | null; - readonly underlyingSystemType: Type; - readonly isTypeDefinition: boolean; - readonly isArray: boolean; - readonly isByRef: boolean; - readonly isPointer: boolean; - readonly isConstructedGenericType: boolean; - readonly isGenericParameter: boolean; - readonly isGenericTypeParameter: boolean; - readonly isGenericMethodParameter: boolean; - readonly isGenericType: boolean; - readonly isGenericTypeDefinition: boolean; - readonly isSZArray: boolean; - readonly isVariableBoundArray: boolean; - readonly isByRefLike: boolean; - readonly isFunctionPointer: boolean; - readonly isUnmanagedFunctionPointer: boolean; - readonly hasElementType: boolean; - readonly genericTypeArguments: Array<(Type)>; - readonly genericParameterPosition: number; - genericParameterAttributes: GenericParameterAttributes; - attributes: TypeAttributes; - readonly isAbstract: boolean; - readonly isImport: boolean; - readonly isSealed: boolean; - readonly isSpecialName: boolean; - readonly isClass: boolean; - readonly isNestedAssembly: boolean; - readonly isNestedFamANDAssem: boolean; - readonly isNestedFamily: boolean; - readonly isNestedFamORAssem: boolean; - readonly isNestedPrivate: boolean; - readonly isNestedPublic: boolean; - readonly isNotPublic: boolean; - readonly isPublic: boolean; - readonly isAutoLayout: boolean; - readonly isExplicitLayout: boolean; - readonly isLayoutSequential: boolean; - readonly isAnsiClass: boolean; - readonly isAutoClass: boolean; - readonly isUnicodeClass: boolean; - readonly isCOMObject: boolean; - readonly isContextful: boolean; - readonly isEnum: boolean; - readonly isMarshalByRef: boolean; - readonly isPrimitive: boolean; - readonly isValueType: boolean; - readonly isSignatureType: boolean; - readonly isSecurityCritical: boolean; - readonly isSecuritySafeCritical: boolean; - readonly isSecurityTransparent: boolean; - readonly structLayoutAttribute?: StructLayoutAttribute | null; - readonly typeInitializer?: ConstructorInfo | null; - readonly typeHandle: RuntimeTypeHandle; - readonly guid: string; - readonly baseType?: Type | null; - /** - * @deprecated - */ - readonly isSerializable: boolean; - readonly containsGenericParameters: boolean; - readonly isVisible: boolean; - readonly genericTypeParameters: Array<(Type)>; - readonly declaredConstructors: Array<(ConstructorInfo)>; - readonly declaredEvents: Array<(EventInfo)>; - readonly declaredFields: Array<(FieldInfo)>; - readonly declaredMembers: Array<(MemberInfo)>; - readonly declaredMethods: Array<(MethodInfo)>; - readonly declaredNestedTypes: Array<(TypeInfo)>; - readonly declaredProperties: Array<(PropertyInfo)>; - readonly implementedInterfaces: Array<(Type)>; -}; - export type IsAuthorizationConfiguredResponse = string; export type GetAuthenticationUrlResponse = string; @@ -739,12 +42,18 @@ export type AuthorizeData = { requestBody?: AuthorizationRequest; }; -export type AuthorizeResponse = Task_1; +export type AuthorizeResponse = AuthorizationResult; export type DeauthorizeResponse = AuthorizationResult; export type GetAllResponse = Array<(Property)>; +export type GetFormFieldsData = { + formId?: string; +}; + +export type GetFormFieldsResponse = Array<(HubspotWorkflowFormFieldDto)>; + export type $OpenApiTs = { '/umbraco/hubspot/management/api/v1/contacts/auth/configured': { get: { @@ -773,7 +82,7 @@ export type $OpenApiTs = { /** * OK */ - 200: Task_1; + 200: AuthorizationResult; }; }; }; @@ -797,4 +106,15 @@ export type $OpenApiTs = { }; }; }; + '/umbraco/hubspot/management/api/v1/forms/fields': { + get: { + req: GetFormFieldsData; + res: { + /** + * OK + */ + 200: Array<(HubspotWorkflowFormFieldDto)>; + }; + }; + }; }; \ No newline at end of file diff --git a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Client/package-lock.json b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Client/package-lock.json index 1b90c9e..96a75f0 100644 --- a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Client/package-lock.json +++ b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Client/package-lock.json @@ -1,11 +1,11 @@ { - "name": "hubspot", + "name": "hubspot-crm", "version": "0.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "hubspot", + "name": "hubspot-crm", "version": "0.0.0", "dependencies": { "lit": "^3.2.0" diff --git a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Client/package.json b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Client/package.json index e05a534..ae9b190 100644 --- a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Client/package.json +++ b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Client/package.json @@ -1,5 +1,5 @@ { - "name": "hubspot", + "name": "hubspot-crm", "private": true, "version": "0.0.0", "type": "module", diff --git a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Client/public/umbraco-package.json b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Client/public/umbraco-package.json index a389b0b..5f18b74 100644 --- a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Client/public/umbraco-package.json +++ b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Client/public/umbraco-package.json @@ -6,7 +6,8 @@ { "name": "Umbraco EntryPoint", "alias": "Umb.Hubspot.EntryPoint", - "type": "entryPoint" + "type": "entryPoint", + "js": "/App_Plugins/HubSpot/hubspot-crm.js" } ] } \ No newline at end of file diff --git a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Client/public/vite.svg b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Client/public/vite.svg deleted file mode 100644 index e7b8dfb..0000000 --- a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Client/public/vite.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Client/src/assets/lit.svg b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Client/src/assets/lit.svg deleted file mode 100644 index 4a9c1fe..0000000 --- a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Client/src/assets/lit.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Client/src/context/hubspot.context.ts b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Client/src/context/hubspot.context.ts index 5f6e447..9adfc3a 100644 --- a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Client/src/context/hubspot.context.ts +++ b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Client/src/context/hubspot.context.ts @@ -3,10 +3,14 @@ import { UmbContextToken } from "@umbraco-cms/backoffice/context-api"; import type { UmbControllerHost } from "@umbraco-cms/backoffice/controller-api"; import { HubspotRepository } from "../repository/hubspot.repository"; import { type AuthorizeData } from "@umbraco-integrations/hubspot/generated"; +import { UmbObjectState } from "@umbraco-cms/backoffice/observable-api"; export class HubspotContext extends UmbControllerBase{ #repository: HubspotRepository; + #settingsModel = new UmbObjectState(undefined); + settingsModel = this.#settingsModel.asObservable(); + constructor(host: UmbControllerHost) { super(host); @@ -16,18 +20,20 @@ export class HubspotContext extends UmbControllerBase{ async hostConnected() { super.hostConnected(); + this.isAuthorizationConfigured(); } async isAuthorizationConfigured() { - return await this.#repository.isAuthorizationConfigured(); + const { data } = await this.#repository.isAuthorizationConfigured(); + this.#settingsModel.setValue(data); } async getAuthenticationUrl() { return await this.#repository.getAuthenticationUrl(); } - async authorize(authData: AuthorizeData) { - return await this.#repository.authorize(authData); + async authorize(code: string) { + return await this.#repository.authorize(code); } async deauthorize() { @@ -37,6 +43,10 @@ export class HubspotContext extends UmbControllerBase{ async getAll() { return await this.#repository.getAll(); } + + async getFormFields(formId : string) { + return await this.#repository.getFormFields(formId); + } } export default HubspotContext; diff --git a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Client/src/index.ts b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Client/src/index.ts index 62cc97e..184adc0 100644 --- a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Client/src/index.ts +++ b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Client/src/index.ts @@ -6,8 +6,6 @@ import { manifests as localizationManifests } from "./lang/manifests.js"; import { OpenAPI } from "@umbraco-integrations/hubspot/generated"; -// export * from "./property-editor/index.js"; - export const onInit: UmbEntryPointOnInit = (host, extensionRegistry) => { extensionRegistry.registerMany([ hubspotContext, diff --git a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Client/src/lang/en.ts b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Client/src/lang/en.ts index f2b01e4..21b0f91 100644 --- a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Client/src/lang/en.ts +++ b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Client/src/lang/en.ts @@ -3,5 +3,9 @@ export default { formProviderWorkflows:{ FieldMappingsLabel : `Field Mappings`, FieldMappingsDescription: `Map Umbraco Form fields to Hubspot contact fields`, - } + }, + hubspotFormWorkflow:{ + SelectHubspotField : `Select HubSpot field`, + SelectFormField: `Select Form field`, + }, } as UmbLocalizationDictionary; \ No newline at end of file diff --git a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Client/src/lang/manifests.ts b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Client/src/lang/manifests.ts index 072c062..e7e0f49 100644 --- a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Client/src/lang/manifests.ts +++ b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Client/src/lang/manifests.ts @@ -3,83 +3,13 @@ import type { ManifestLocalization } from "@umbraco-cms/backoffice/extension-reg const localizationManifests: Array = [ { type: "localization", - alias: "Forms.Localization.En", + alias: "Hubspot.Localization.En", weight: -100, name: "English (US)", meta: { culture: "en", }, js: () => import("./en.js"), - // }, - // { - // type: "localization", - // alias: "Forms.Localization.Cs_CZ", - // weight: -100, - // name: "Czech", - // meta: { - // culture: "cs-cz", - // }, - // js: () => import("./cs-cz.js"), - // }, - // { - // type: "localization", - // alias: "Forms.Localization.Da_DK", - // weight: -100, - // name: "Danish", - // meta: { - // culture: "da-dk", - // }, - // js: () => import("./da-dk.js"), - // }, - // { - // type: "localization", - // alias: "Forms.Localization.En_GB", - // weight: -100, - // name: "English (UK)", - // meta: { - // culture: "en-gb", - // }, - // js: () => import("./en-gb.js"), - // }, - // { - // type: "localization", - // alias: "Forms.Localization.Es_ES", - // weight: -100, - // name: "Spanish", - // meta: { - // culture: "es-es", - // }, - // js: () => import("./es-es.js"), - // }, - // { - // type: "localization", - // alias: "Forms.Localization.Fr_FR", - // weight: -100, - // name: "French", - // meta: { - // culture: "fr-fr", - // }, - // js: () => import("./fr-fr.js"), - // }, - // { - // type: "localization", - // alias: "Forms.Localization.It_IT", - // weight: -100, - // name: "French", - // meta: { - // culture: "it-it", - // }, - // js: () => import("./it-it.js"), - // }, - // { - // type: "localization", - // alias: "Forms.Localization.Pl_PL", - // weight: -100, - // name: "Polish", - // meta: { - // culture: "pl-pl", - // }, - // js: () => import("./pl-pl.js"), }, ]; export const manifests = [...localizationManifests]; \ No newline at end of file diff --git a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Client/src/models/hubspot.model.ts b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Client/src/models/hubspot.model.ts new file mode 100644 index 0000000..0a5524e --- /dev/null +++ b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Client/src/models/hubspot.model.ts @@ -0,0 +1,5 @@ +export interface HubspotMappingValue { + formField: string; + hubspotField: string; + appendValue: boolean; +} \ No newline at end of file diff --git a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Client/src/property-editor/hubspot-mapping.property-editor.ts b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Client/src/property-editor/hubspot-mapping.property-editor.ts index 496c2b0..5a10ae0 100644 --- a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Client/src/property-editor/hubspot-mapping.property-editor.ts +++ b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Client/src/property-editor/hubspot-mapping.property-editor.ts @@ -1,15 +1,331 @@ -import { html, customElement, property, css, when } from '@umbraco-cms/backoffice/external/lit'; +import { html, customElement, property, css, when, state, map } from '@umbraco-cms/backoffice/external/lit'; import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import { HUBSPOT_CONTEXT_TOKEN } from '@umbraco-integrations/hubspot/context'; +import { HubspotWorkflowFormFieldDto, Property } from '@umbraco-integrations/hubspot/generated'; +import { UUIInputEvent, UUISelectEvent } from '@umbraco-cms/backoffice/external/uui'; +import { HubspotMappingValue } from '../models/hubspot.model'; +import { UMB_NOTIFICATION_CONTEXT, UmbNotificationColor } from '@umbraco-cms/backoffice/notification'; +import { umbConfirmModal } from '@umbraco-cms/backoffice/modal'; const elementName = "hubspot-mapping-property-editor"; @customElement(elementName) export class HubspotMappingPropertyUiElement extends UmbLitElement implements UmbPropertyEditorUiElement { - render() { - return html`
ABCD
`; + #hubspotContext!: typeof HUBSPOT_CONTEXT_TOKEN.TYPE; + #settingsModel?: string; + + @property({ type: String }) + public value = ""; + + @state() + public hubspotMappingArray : Array = []; + + @state() + private hubspotFields: Array | undefined = []; + + @state() + private formdFields: Array | undefined = []; + + @state() + private authorizationCode: string = ""; + + @state() + private authorizationStatus: string = "Unauthenticated"; + + @state() + private authenticationUrl: string | undefined = ""; + + constructor() { + super(); + this.consumeContext(HUBSPOT_CONTEXT_TOKEN, (context) => { + if (!context) return; + this.#hubspotContext = context; + + this.observe(context.settingsModel, (settingsModel) => { + this.#settingsModel = settingsModel; + }); + }); + } + + async connectedCallback() { + super.connectedCallback(); + + if (!this.#settingsModel || this.#settingsModel === "Unauthenticated"){ + const { data } = await this.#hubspotContext.getAuthenticationUrl(); + this.authenticationUrl = data; + } else{ + this.authorizationStatus = this.#settingsModel!; + + await this.loadData(); } } + + async #getHubspotFields(){ + var result = await this.#hubspotContext.getAll(); + if (!result) return; + + this.hubspotFields = result.data; + } + + async #getFormFields(){ + var formId = window.location.pathname.split("/")[7]; //Get the formid based on current url. + var result = await this.#hubspotContext.getFormFields(formId); + + if (!result) return; + + this.formdFields = result.data; + } + + async #openAuth(){ + window.open(this.authenticationUrl); + window.addEventListener("message", async (event: MessageEvent) => { + if (event.data.type === "hubspot:oauth:success") { + this.authorizationCode = event.data.code; + + await this.#onConnect(); + } + }, false); + } + + async #onConnect(){ + const { data } = await this.#hubspotContext.authorize(this.authorizationCode); + + if (!data) return; + + if (data.success){ + this.authorizationStatus = "OAuth"; + this.authorizationCode = ""; + + await this.loadData(); + + this.requestUpdate(); + this.dispatchEvent(new CustomEvent("authorizationStatus")); + this._showSuccess("Your Umbraco Forms installation is now connected to your HubSpot account"); + } else{ + this._showError(data.errorMessage); + } + } + + async loadData(){ + await this.#getHubspotFields(); + await this.#getFormFields(); + + if (this.value){ + this.hubspotMappingArray = JSON.parse(this.value); + } + } + + async #deauthorize(){ + await umbConfirmModal(this, { + color: "danger", + headline: "Confirmation", + content: "Are you sure you wish to disconnect your Hubspot account?", + confirmLabel: 'Disconnect', + }); + + const { data } = await this.#hubspotContext.deauthorize(); + + if(!data) return; + + if (data.success){ + this.authorizationStatus = "Unauthenticated"; + this.authorizationCode = ""; + + const { data } = await this.#hubspotContext.getAuthenticationUrl(); + if (data){ + this.authenticationUrl = data; + } + + this._showSuccess("Your Umbraco Forms installation is no longer connected to your HubSpot account"); + } else{ + this._showError(data.errorMessage!); + } + + this.dispatchEvent(new CustomEvent("authorizationStatus")); + } + + private async _showSuccess(message: string) { + await this._showMessage(message, "positive"); + } + + private async _showError(message: string) { + await this._showMessage(message, "danger"); + } + + private async _showMessage(message: string, color: UmbNotificationColor) { + const notificationContext = await this.getContext(UMB_NOTIFICATION_CONTEXT); + notificationContext?.peek(color, { + data: { message }, + }); + } + + #onDeleteClick(idx: number){ + this.hubspotMappingArray.splice(idx, 1); + + this.value = JSON.stringify(this.hubspotMappingArray); + this.requestUpdate(); + this.dispatchEvent(new CustomEvent('property-value-change')); + } + + #addButtonClick(){ + this.hubspotMappingArray.push({ + formField: "", + hubspotField: "", + appendValue: false + }); + + this.value = JSON.stringify(this.hubspotMappingArray); + this.requestUpdate(); + this.dispatchEvent(new CustomEvent('property-value-change')); + } + + #onHubspotSelectChange(e: UUISelectEvent, idx: number){ + this.hubspotMappingArray[idx].hubspotField = e.target.value.toString(); + + this.value = JSON.stringify(this.hubspotMappingArray); + this.requestUpdate(); + this.dispatchEvent(new CustomEvent('property-value-change')); + } + + #onFormFieldSelectChange(e: UUISelectEvent, idx: number){ + this.hubspotMappingArray[idx].formField = e.target.value.toString(); + + this.value = JSON.stringify(this.hubspotMappingArray); + this.requestUpdate(); + this.dispatchEvent(new CustomEvent('property-value-change')); + } + + #onInputChange(e: UUIInputEvent){ + this.authorizationCode = e.target.value.toString(); + } + + #getHubspotDescription(name: string){ + if (!this.hubspotFields) return; + var result = this.hubspotFields.find(h => h.name == name); + if (!result) return; + return result.description; + } + + render() { + return html` + ${this.authorizationStatus === "Unauthenticated" + ? html` +
+

Umbraco Forms is not configured with a HubSpot CRM account.

+

To do this you can either create and save an API key or a Private Access Token into the appsettings.json file.

+

Or you can click here to complete an OAuth connection.

+

If your browser is unable to process the automated connection, paste the provided authorization code below and click to complete the authentication.

+ this.#onInputChange(e)}> + +
+ ` + : html` +
+ Umbraco Forms is configured with a HubSpot CRM account using: + ${this.authorizationStatus}

+
+ +
+ + + + + +
+ + + +
+
+ +
+ ${this.hubspotMappingArray.length > 0 + ? html` + + + + + + + + + + ${map(this.hubspotMappingArray, (mapping, idx) => html` + + + + + + + + + `)} + +
Form FieldHubspot Field
+ this.#onFormFieldSelectChange(e, idx)} + .options=${ + this.formdFields?.map((ft) => ({ + name: ft.caption, + value: ft.id, + selected: ft.id === mapping.formField, + })) ?? []}> + + this.#onHubspotSelectChange(e, idx)} + .options=${ + this.hubspotFields?.map((ft) => ({ + name: ft.label, + value: ft.name, + selected: ft.name === mapping.hubspotField, + })) ?? []}> + + this.#onDeleteClick(idx)}> + + +
+ Description: ${this.#getHubspotDescription(mapping.hubspotField)} +
+ ` + : html``} +
+ `} + `; + } + + static styles = [ + css` + .hubspot-wf-status{ + margin-top: 10px; + padding: 10px; + background-color: #202454; + color: #ffffff; + } + + .hubspot-wf-auth-link{ + cursor: pointer; + } + + .hubspot-wf-button, .hubspot-wf-table { + margin-top: 10px; + } + + .hubspot-wf-table th{ + text-align: justify; + } + + .hubspot-wf-table td.description{ + padding-bottom: 15px; + } + `]; +} export default HubspotMappingPropertyUiElement; diff --git a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Client/src/repository/hubspot.repository.ts b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Client/src/repository/hubspot.repository.ts index 6d7737b..4e2457b 100644 --- a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Client/src/repository/hubspot.repository.ts +++ b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Client/src/repository/hubspot.repository.ts @@ -1,7 +1,7 @@ import { UmbControllerBase } from "@umbraco-cms/backoffice/class-api"; import type { UmbControllerHost } from "@umbraco-cms/backoffice/controller-api"; import { tryExecuteAndNotify } from "@umbraco-cms/backoffice/resources"; -import { ContactsService, type AuthorizeData } from "@umbraco-integrations/hubspot/generated"; +import { ContactsService, FormsService, type AuthorizeData } from "@umbraco-integrations/hubspot/generated"; export class HubspotRepository extends UmbControllerBase{ constructor(host: UmbControllerHost) { @@ -28,8 +28,8 @@ export class HubspotRepository extends UmbControllerBase{ return { data }; } - async authorize(authData: AuthorizeData) { - const { data, error } = await tryExecuteAndNotify(this, ContactsService.authorize(authData)); + async authorize(code: string) { + const { data, error } = await tryExecuteAndNotify(this, ContactsService.authorize({requestBody: {code: code}})); if (error || !data) { return { error }; @@ -57,4 +57,14 @@ export class HubspotRepository extends UmbControllerBase{ return { data }; } + + async getFormFields(formId: string) { + const { data, error } = await tryExecuteAndNotify(this, FormsService.getFormFields({formId: formId})); + + if (error || !data) { + return { error }; + } + + return { data }; + } } \ No newline at end of file diff --git a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Client/tsconfig.json b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Client/tsconfig.json index 09ecf4d..5836535 100644 --- a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Client/tsconfig.json +++ b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Client/tsconfig.json @@ -17,7 +17,7 @@ /* Linting */ "strict": true, "noUnusedLocals": false, - "noUnusedParameters": true, + "noUnusedParameters": false, "noFallthroughCasesInSwitch": true, "paths": { diff --git a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Configuration/AppSettings.cs b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Configuration/AppSettings.cs deleted file mode 100644 index e64fb03..0000000 --- a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Configuration/AppSettings.cs +++ /dev/null @@ -1,19 +0,0 @@ -namespace Umbraco.Forms.Integrations.Crm.Hubspot.Configuration -{ - public class AppSettings - { - public string HubspotClientSecret { get; set; } - - public string HubspotFormsClientSecret { get; set; } - - public string SemrushClientSecret { get; set; } - - public string ShopifyClientSecret { get; set; } - - public string GoogleClientSecret { get; set; } - - public string DynamicsClientSecret { get; set; } - - public string this[string propertyName] => (string)GetType().GetProperty(propertyName)?.GetValue(this, null); - } -} diff --git a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Configuration/ServiceConfiguration.cs b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Configuration/ServiceConfiguration.cs deleted file mode 100644 index ff032aa..0000000 --- a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Configuration/ServiceConfiguration.cs +++ /dev/null @@ -1,51 +0,0 @@ -using System; -using System.Collections.Generic; - -using Microsoft.Extensions.DependencyInjection; - -namespace Umbraco.Forms.Integrations.Crm.Hubspot.Configuration -{ - public static class ServiceConfiguration - { - /// - /// Integrated services with their token URIs - /// - public static Dictionary ServiceProviders = new() - { - { "Hubspot", "oauth/v1/token" }, - { "HubspotForms", "oauth/v1/token" }, - { "Semrush", "oauth2/access_token" }, - { "Shopify", "oauth/access_token" }, - { "Google", "token"}, - { "Dynamics", "oauth2/v2.0/token" } - }; - - public static void AddServiceClients(this IServiceCollection services) - { - services.AddHttpClient("HubspotToken", c => - { - c.BaseAddress = new Uri("https://api.hubapi.com/"); - }); - services.AddHttpClient("HubspotFormsToken", c => - { - c.BaseAddress = new Uri("https://api.hubapi.com/"); - }); - services.AddHttpClient("SemrushToken", c => - { - c.BaseAddress = new Uri("https://oauth.semrush.com/"); - }); - services.AddHttpClient("ShopifyToken", c => - { - c.BaseAddress = new Uri("https://shop-replace.myshopify.com/admin/"); - }); - services.AddHttpClient("GoogleToken", c => - { - c.BaseAddress = new Uri("https://oauth2.googleapis.com/"); - }); - services.AddHttpClient("DynamicsToken", c => - { - c.BaseAddress = new Uri("https://login.microsoftonline.com/common/"); - }); - } - } -} diff --git a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Constants.cs b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Constants.cs index b406801..7c2b253 100644 --- a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Constants.cs +++ b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Constants.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Umbraco.Forms.Integrations.Crm.Hubspot +namespace Umbraco.Forms.Integrations.Crm.Hubspot { public class Constants { @@ -14,9 +8,11 @@ public static class ManagementApi public const string ApiName = "hubspot-management"; - public const string ApiTitle = "Hubspot Management API"; + public const string ApiTitle = "HubSpot Management API"; public const string ContactGroupName = "Contacts"; + + public const string FormGroupName = "Forms"; } } } diff --git a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Extensions/ObjectExtensions.cs b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Extensions/ObjectExtensions.cs deleted file mode 100644 index d358aea..0000000 --- a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Extensions/ObjectExtensions.cs +++ /dev/null @@ -1,56 +0,0 @@ -using Newtonsoft.Json; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; - -namespace Umbraco.Forms.Integrations.Crm.Hubspot.Extensions -{ - public static class ObjectExtensions - { - /// - /// Converts an object to a dictionary of it's properties. - /// - /// - /// Hat-tip: https://stackoverflow.com/a/4944547 - /// - public static T ToObject(this IDictionary source) - where T : class, new() - { - var obj = new T(); - var type = obj.GetType(); - - foreach (var item in source) - { - type - .GetProperty(item.Key) - .SetValue(obj, item.Value, null); - } - - return obj; - } - - /// - /// Converts an dictionary of properties to an object. - /// - /// - /// Hat-tip: https://stackoverflow.com/a/4944547 - /// - public static IDictionary AsDictionary(this object source, BindingFlags bindingAttr = BindingFlags.Public | BindingFlags.Instance) => - source.GetType().GetProperties(bindingAttr).ToDictionary - ( - propInfo => GetPropertyName(propInfo), - propInfo => (propInfo.GetValue(source, null)?.ToString()) - ); - - private static string GetPropertyName(PropertyInfo propInfo) - { - var jsonPropertyAttribute = ((JsonPropertyAttribute[])propInfo.GetCustomAttributes(typeof(JsonPropertyAttribute), true)).SingleOrDefault(); - if (jsonPropertyAttribute == null) - { - return propInfo.Name; - } - - return jsonPropertyAttribute.PropertyName; - } - } -} diff --git a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Filters/SignatureValidationAttribute.cs b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Filters/SignatureValidationAttribute.cs deleted file mode 100644 index 6ad90ee..0000000 --- a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Filters/SignatureValidationAttribute.cs +++ /dev/null @@ -1,47 +0,0 @@ -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.Filters; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Options; -using System; -using System.IO; -using System.Linq; -using System.Security.Cryptography; -using System.Text; -using System.Threading.Tasks; -using Umbraco.Forms.Integrations.Crm.Hubspot.Configuration; - -namespace Umbraco.Forms.Integrations.Crm.Hubspot.Filters -{ - public class SignatureValidationAttribute : ActionFilterAttribute - { - private const string HeaderKey = "X-Shopify-Hmac-Sha256"; - - public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) - { - var appSettings = context.HttpContext.RequestServices.GetService>().Value; - - var hmacHeaderValues = context.HttpContext.Request.Headers - .FirstOrDefault(kvp => kvp.Key.Equals(HeaderKey, StringComparison.OrdinalIgnoreCase)).Value; - - if (hmacHeaderValues.Count == 0) - { - context.Result = new UnauthorizedResult(); - return; - } - - string hmacHeader = hmacHeaderValues.First(); - - HMACSHA256 hmac = new HMACSHA256(Encoding.UTF8.GetBytes(appSettings.ShopifyClientSecret)); - - var bodyStream = new StreamReader(context.HttpContext.Request.Body); - string requestBody = await bodyStream.ReadToEndAsync(); - string hash = Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(requestBody))); - - if (hash != hmacHeader) - { - context.Result = new UnauthorizedResult(); - return; - } - } - } -} diff --git a/src/Umbraco.Forms.Integrations.Crm.Hubspot/HubspotComposer.cs b/src/Umbraco.Forms.Integrations.Crm.Hubspot/HubspotComposer.cs index f226a6a..bd78c26 100644 --- a/src/Umbraco.Forms.Integrations.Crm.Hubspot/HubspotComposer.cs +++ b/src/Umbraco.Forms.Integrations.Crm.Hubspot/HubspotComposer.cs @@ -3,7 +3,6 @@ using Swashbuckle.AspNetCore.SwaggerGen; using Umbraco.Cms.Core.Composing; using Umbraco.Cms.Core.DependencyInjection; -using Umbraco.Cms.Core.Notifications; using Umbraco.Forms.Core.Providers; using Umbraco.Forms.Integrations.Crm.Hubspot.Configuration; using Umbraco.Forms.Integrations.Crm.Hubspot.Services; @@ -19,8 +18,6 @@ public void Compose(IUmbracoBuilder builder) builder.Services.AddSingleton(); - builder.AddNotificationHandler(); - builder.WithCollectionBuilder() .Add(); @@ -33,7 +30,7 @@ public void Compose(IUmbracoBuilder builder) { Title = Constants.ManagementApi.ApiTitle, Version = "Latest", - Description = $"Describes the {Constants.ManagementApi.ApiTitle} available for handling Hubspot automation and configuration." + Description = $"Describes the {Constants.ManagementApi.ApiTitle} available for handling HubSpot CRM automation and configuration." }); options.CustomOperationIds(e => $"{e.ActionDescriptor.RouteValues["action"]}"); diff --git a/src/Umbraco.Forms.Integrations.Crm.Hubspot/HubspotServerVariablesParsingHandler.cs b/src/Umbraco.Forms.Integrations.Crm.Hubspot/HubspotServerVariablesParsingHandler.cs deleted file mode 100644 index b21d57c..0000000 --- a/src/Umbraco.Forms.Integrations.Crm.Hubspot/HubspotServerVariablesParsingHandler.cs +++ /dev/null @@ -1,76 +0,0 @@ -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Routing; -using Microsoft.Extensions.Options; -using System; -using System.Collections.Generic; -using System.Runtime.Serialization; -using Umbraco.Cms.Core.Events; -using Umbraco.Cms.Core.Notifications; -using Umbraco.Extensions; -using Umbraco.Forms.Integrations.Crm.Hubspot.Api.Management.Controllers; -using Umbraco.Forms.Integrations.Crm.Hubspot.Configuration; - -namespace Umbraco.Forms.Integrations.Crm.Hubspot -{ - public class HubspotServerVariablesParsingHandler : INotificationHandler - { - private readonly IHttpContextAccessor _httpContextAccessor; - private readonly LinkGenerator _linkGenerator; - private readonly HubspotSettings _settings; - - public HubspotServerVariablesParsingHandler(IHttpContextAccessor httpContextAccessor, LinkGenerator linkGenerator, IOptions options) - { - _httpContextAccessor = httpContextAccessor; - - _linkGenerator = linkGenerator; - - _settings = options.Value; - } - - public void Handle(ServerVariablesParsingNotification notification) - { - IDictionary serverVars = notification.ServerVariables; - - if (!serverVars.ContainsKey("umbracoUrls")) - { - throw new ArgumentException("Missing umbracoUrls"); - } - - var umbracoUrlsObject = serverVars["umbracoUrls"]; - if (umbracoUrlsObject == null) - { - throw new ArgumentException("Null umbracoUrls"); - } - - if (!(umbracoUrlsObject is Dictionary umbracoUrls)) - { - throw new ArgumentException("Invalid umbracoUrls"); - } - - if(_httpContextAccessor.HttpContext == null) - { - throw new InvalidOperationException("HttpContext is null"); - } - - //umbracoUrls["umbracoFormsIntegrationsCrmHubspotBaseUrl"] = - // _linkGenerator.GetUmbracoApiServiceBaseUrl(controller => controller.GetAll()); - - if (serverVars.ContainsKey("umbracoPlugins")) - { - var umbracoPlugins = (Dictionary)serverVars["umbracoPlugins"]; - umbracoPlugins.Add("umbracoFormsIntegrationsCrmHubspot", new ClientSideConfiguration - { - AllowContactUpdate = _settings.AllowContactUpdate - }); - } - - } - - [DataContract] - internal sealed class ClientSideConfiguration - { - [DataMember(Name = "allowContactUpdate")] - public bool AllowContactUpdate { get; set; } - } - } -} diff --git a/src/Umbraco.Forms.Integrations.Crm.Hubspot/HubspotWorkflow.cs b/src/Umbraco.Forms.Integrations.Crm.Hubspot/HubspotWorkflow.cs index f40afba..2af79c5 100644 --- a/src/Umbraco.Forms.Integrations.Crm.Hubspot/HubspotWorkflow.cs +++ b/src/Umbraco.Forms.Integrations.Crm.Hubspot/HubspotWorkflow.cs @@ -1,15 +1,8 @@ using Microsoft.Extensions.Logging; - -using Newtonsoft.Json; - -using System; -using System.Collections.Generic; -using System.Reflection; +using System.Text.Json; using Umbraco.Forms.Core; using Umbraco.Forms.Core.Attributes; using Umbraco.Forms.Core.Enums; -using Umbraco.Forms.Core.Interfaces; -using Umbraco.Forms.Core.Models; using Umbraco.Forms.Integrations.Crm.Hubspot.Models; using Umbraco.Forms.Integrations.Crm.Hubspot.Services; @@ -39,28 +32,24 @@ public HubspotWorkflow(ILogger logger, IContactService contactS [Setting("Field Mappings", Description = "Map Umbraco Form fields to HubSpot contact fields", View = "Hubspot.PropertyEditorUi.Mapping")] public string FieldMappings { get; set; } - public WorkflowExecutionStatus Execute(WorkflowExecutionContext context) + public override async Task ExecuteAsync(WorkflowExecutionContext context) { - var workflowName = GetWorkflowName(); - var fieldMappingsRawJson = FieldMappings; - var fieldMappings = JsonConvert.DeserializeObject>(fieldMappingsRawJson); + var fieldMappings = JsonSerializer.Deserialize>(fieldMappingsRawJson); if (fieldMappings.Count == 0) { - _logger.LogWarning("Workflow {WorkflowName}: Missing HubSpot field mappings for workflow for the form {FormName} ({FormId})", - workflowName, context.Form.Name, context.Form.Id); + _logger.LogWarning("Save Contact to HubSpot: Missing HubSpot field mappings for workflow for the form {FormName} ({FormId})", context.Form.Name, context.Form.Id); return WorkflowExecutionStatus.NotConfigured; } - var commandResult = _contactService.PostContactAsync(context.Record, fieldMappings, null).GetAwaiter().GetResult(); + var commandResult = await _contactService.PostContactAsync(context.Record, fieldMappings, null); switch (commandResult) { case CommandResult.NotConfigured: - _logger.LogWarning("Workflow {WorkflowName}: Could not complete contact request for {FormName} ({FormId}) as the workflow is not correctly configured.", - workflowName, context.Form.Name, context.Form.Id); + _logger.LogWarning("Save Contact to HubSpot: Could not complete contact request for {FormName} ({FormId}) as the workflow is not correctly configured.", context.Form.Name, context.Form.Id); return WorkflowExecutionStatus.NotConfigured; case CommandResult.Failed: - _logger.LogWarning("Workflow {WorkflowName}: Failed for {FormName} ({FormId}).", workflowName, context.Form.Name, context.Form.Id); + _logger.LogWarning("Save Contact to HubSpot: Failed for {FormName} ({FormId}).", context.Form.Name, context.Form.Id); return WorkflowExecutionStatus.Failed; case CommandResult.Success: return WorkflowExecutionStatus.Completed; @@ -69,23 +58,6 @@ public WorkflowExecutionStatus Execute(WorkflowExecutionContext context) } } - public override Task ExecuteAsync(WorkflowExecutionContext context) - { - throw new NotImplementedException(); - } - public override List ValidateSettings() => new List(); - - /// - /// Get workflow's name using reflection in regards to breaking changes between Forms 11 and 12. - /// - /// - private string GetWorkflowName() - { - var workflow = typeof(WorkflowType).GetProperty(nameof(Workflow)).GetValue(this); - var name = workflow.GetType().GetProperty(nameof(Workflow.Name)).GetValue(workflow).ToString(); - - return name; - } } } diff --git a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Models/Dtos/AuthorizationRequest.cs b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Models/Dtos/AuthorizationRequest.cs index b272442..7d95e18 100644 --- a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Models/Dtos/AuthorizationRequest.cs +++ b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Models/Dtos/AuthorizationRequest.cs @@ -1,10 +1,10 @@ -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Umbraco.Forms.Integrations.Crm.Hubspot.Models.Dtos { public class AuthorizationRequest { - [JsonProperty("code")] + [JsonPropertyName("code")] public string Code { get; set; } } } diff --git a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Models/Dtos/AuthorizationResult.cs b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Models/Dtos/AuthorizationResult.cs index f7506a2..46fdbbd 100644 --- a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Models/Dtos/AuthorizationResult.cs +++ b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Models/Dtos/AuthorizationResult.cs @@ -1,4 +1,4 @@ -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Umbraco.Forms.Integrations.Crm.Hubspot.Models.Dtos { @@ -8,10 +8,10 @@ private AuthorizationResult() { } - [JsonProperty("success")] + [JsonPropertyName("success")] public bool Success { get; private set; } - [JsonProperty("errorMessage")] + [JsonPropertyName("errorMessage")] public string ErrorMessage { get; private set; } public static AuthorizationResult AsSuccess() => diff --git a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Models/Dtos/HubspotWorkflowFormFieldDto.cs b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Models/Dtos/HubspotWorkflowFormFieldDto.cs new file mode 100644 index 0000000..e8283ce --- /dev/null +++ b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Models/Dtos/HubspotWorkflowFormFieldDto.cs @@ -0,0 +1,13 @@ +using System.Runtime.Serialization; + +namespace Umbraco.Forms.Integrations.Crm.Hubspot.Models.Dtos +{ + public class HubspotWorkflowFormFieldDto + { + [DataMember(Name = "caption")] + public string Caption { get; set; } = string.Empty; + + [DataMember(Name = "id")] + public Guid Id { get; set; } + } +} diff --git a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Models/MappedProperty.cs b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Models/MappedProperty.cs index 70b8189..dd96d5e 100644 --- a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Models/MappedProperty.cs +++ b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Models/MappedProperty.cs @@ -1,16 +1,16 @@ -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Umbraco.Forms.Integrations.Crm.Hubspot.Models { public class MappedProperty { - [JsonProperty(PropertyName = "formField")] + [JsonPropertyName("formField")] public string FormField { get; set; } - [JsonProperty(PropertyName = "hubspotField")] + [JsonPropertyName("hubspotField")] public string HubspotField { get; set; } - [JsonProperty(PropertyName = "appendValue")] + [JsonPropertyName("appendValue")] public bool AppendValue { get; set; } } } diff --git a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Models/Requests/PropertiesRequestV1.cs b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Models/Requests/PropertiesRequestV1.cs index e230a25..ee2c6db 100644 --- a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Models/Requests/PropertiesRequestV1.cs +++ b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Models/Requests/PropertiesRequestV1.cs @@ -1,11 +1,10 @@ -using Newtonsoft.Json; -using System.Collections.Generic; +using System.Text.Json.Serialization; namespace Umbraco.Forms.Integrations.Crm.Hubspot { internal class PropertiesRequestV1 { - [JsonProperty(PropertyName = "properties")] + [JsonPropertyName("properties")] public IList Properties { get; set; } = new List(); internal class PropertyValue @@ -16,10 +15,10 @@ public PropertyValue(string property, string value) Value = value; } - [JsonProperty(PropertyName = "property")] + [JsonPropertyName("property")] public string Property { get; } - [JsonProperty(PropertyName = "value")] + [JsonPropertyName("value")] public string Value { get; } } } diff --git a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Models/Requests/PropertiesRequestV3.cs b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Models/Requests/PropertiesRequestV3.cs index 12a4337..4d2b443 100644 --- a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Models/Requests/PropertiesRequestV3.cs +++ b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Models/Requests/PropertiesRequestV3.cs @@ -1,11 +1,11 @@ -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; +using System.Text.Json.Nodes; +using System.Text.Json.Serialization; namespace Umbraco.Forms.Integrations.Crm.Hubspot { internal class PropertiesRequestV3 { - [JsonProperty(PropertyName = "properties")] - public JObject Properties { get; set; } = new JObject(); + [JsonPropertyName("properties")] + public JsonObject Properties { get; set; } = new JsonObject(); } } diff --git a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Models/Responses/ErrorResponse.cs b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Models/Responses/ErrorResponse.cs index 7eff2d1..4997f30 100644 --- a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Models/Responses/ErrorResponse.cs +++ b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Models/Responses/ErrorResponse.cs @@ -1,10 +1,10 @@ -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Umbraco.Forms.Integrations.Crm.Hubspot.Models.Responses { public class ErrorResponse { - [JsonProperty(PropertyName = "message")] + [JsonPropertyName("message")] public string Message { get; set; } } } diff --git a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Models/Responses/PropertiesResponse.cs b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Models/Responses/PropertiesResponse.cs index 0ae0231..c466a41 100644 --- a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Models/Responses/PropertiesResponse.cs +++ b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Models/Responses/PropertiesResponse.cs @@ -1,11 +1,10 @@ -using Newtonsoft.Json; -using System.Collections.Generic; +using System.Text.Json.Serialization; namespace Umbraco.Forms.Integrations.Crm.Hubspot.Models.Responses { public class PropertiesResponse { - [JsonProperty(PropertyName = "results")] + [JsonPropertyName("results")] public List Results { get; set; } } -} +} \ No newline at end of file diff --git a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Models/Responses/Property.cs b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Models/Responses/Property.cs index 35f0cf7..461d4c9 100644 --- a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Models/Responses/Property.cs +++ b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Models/Responses/Property.cs @@ -1,16 +1,16 @@ -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Umbraco.Forms.Integrations.Crm.Hubspot.Models.Responses { public class Property { - [JsonProperty(PropertyName = "name")] + [JsonPropertyName("name")] public string Name { get; set; } - [JsonProperty(PropertyName = "label")] + [JsonPropertyName("label")] public string Label { get; set; } - [JsonProperty(PropertyName = "description")] + [JsonPropertyName("description")] public string Description { get; set; } } } diff --git a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Services/BaseTokenRequest.cs b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Services/BaseTokenRequest.cs index c1cce7e..87cbb0a 100644 --- a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Services/BaseTokenRequest.cs +++ b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Services/BaseTokenRequest.cs @@ -1,4 +1,4 @@ -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Umbraco.Forms.Integrations.Crm.Hubspot.Services { @@ -6,10 +6,10 @@ internal abstract class BaseTokenRequest { public abstract string GrantType { get; } - [JsonProperty("client_id")] + [JsonPropertyName("client_id")] public string ClientId { get; set; } - [JsonProperty("redirect_uri")] + [JsonPropertyName("redirect_uri")] public string RedirectUrl { get; set; } } } diff --git a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Services/GetTokenRequest.cs b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Services/GetTokenRequest.cs index 7a4bbd3..2dec747 100644 --- a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Services/GetTokenRequest.cs +++ b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Services/GetTokenRequest.cs @@ -1,13 +1,13 @@ -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Umbraco.Forms.Integrations.Crm.Hubspot.Services { internal class GetTokenRequest : BaseTokenRequest { - [JsonProperty("grant_type")] + [JsonPropertyName("grant_type")] public override string GrantType => "authorization_code"; - [JsonProperty("code")] + [JsonPropertyName("code")] public string AuthorizationCode { get; set; } } } diff --git a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Services/HubspotContactService.cs b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Services/HubspotContactService.cs index 8ec3024..3bcb96b 100644 --- a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Services/HubspotContactService.cs +++ b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Services/HubspotContactService.cs @@ -1,18 +1,12 @@ -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; -using Newtonsoft.Json; -using System; -using System.Collections.Generic; -using System.Linq; using System.Net; -using System.Net.Http; using System.Net.Http.Headers; using System.Text; -using System.Threading.Tasks; - +using System.Text.Json; using Umbraco.Cms.Core.Cache; using Umbraco.Cms.Core.Services; +using Umbraco.Extensions; using Umbraco.Forms.Core.Persistence.Dtos; using Umbraco.Forms.Integrations.Crm.Hubspot.Configuration; using Umbraco.Forms.Integrations.Crm.Hubspot.Extensions; @@ -74,11 +68,11 @@ public async Task AuthorizeAsync(string code) AuthorizationCode = code, }; var response = await GetResponse(OAuthTokenProxyUrl, - HttpMethod.Post, content: tokenRequest, contentType: "application/x-www-form-urlencoded").ConfigureAwait(false); + HttpMethod.Post, content: tokenRequest, contentType: "application/x-www-form-urlencoded"); if (response.IsSuccessStatusCode) { var responseContent = await response.Content.ReadAsStringAsync(); - var tokenResponse = JsonConvert.DeserializeObject(responseContent); + var tokenResponse = JsonSerializer.Deserialize(responseContent); // Add the access token details to the cache. _appCaches.RuntimeCache.Insert(AccessTokenCacheKey, () => tokenResponse.AccessToken); @@ -114,7 +108,7 @@ public async Task> GetContactPropertiesAsync() var requestUrl = $"{CrmV3ApiBaseUrl}properties/contacts"; var httpMethod = HttpMethod.Get; - var response = await GetResponse(requestUrl, httpMethod, authenticationDetails).ConfigureAwait(false); + var response = await GetResponse(requestUrl, httpMethod, authenticationDetails); if (response.IsSuccessStatusCode == false) { var retryResult = await HandleFailedRequest(response.StatusCode, requestUrl, httpMethod, authenticationDetails); @@ -132,7 +126,7 @@ public async Task> GetContactPropertiesAsync() // Map the properties to our simpler object, as we don't need all the fields in the response. var properties = new List(); var responseContent = await response.Content.ReadAsStringAsync(); - var responseContentAsJson = JsonConvert.DeserializeObject(responseContent); + var responseContentAsJson = JsonSerializer.Deserialize(responseContent); properties.AddRange(responseContentAsJson.Results); return properties.OrderBy(x => x.Label); } @@ -196,7 +190,7 @@ public async Task PostContactAsync(Record record, List UpdateContactAsync(Record record, Authenticati // It uses the V1 API but support suggests it will be added to V3 before being depreciated so we can use safely: // https://community.hubspot.com/t5/APIs-Integrations/Get-Contacts-from-contact-list-using-email/m-p/419493/highlight/true#M41567 var requestUrl = $"{CrmApiHost}/contacts/v1/contact/email/{email}/profile"; - var response = await GetResponse(requestUrl, HttpMethod.Post, authenticationDetails, postData, JsonContentType).ConfigureAwait(false); + var response = await GetResponse(requestUrl, HttpMethod.Post, authenticationDetails, postData, JsonContentType); if (response.IsSuccessStatusCode == false) { var retryResult = await HandleFailedRequest(response.StatusCode, requestUrl, HttpMethod.Post, authenticationDetails, postData, JsonContentType); @@ -314,7 +308,7 @@ private async Task GetOAuthAccessTokenFromCacheOrRefreshToken(string ref if (accessToken != null) { // No access token in the cache, so get a new one from the refresh token. - await RefreshOAuthAccessToken(refreshToken).ConfigureAwait(false); + await RefreshOAuthAccessToken(refreshToken); accessToken = _appCaches.RuntimeCache.Get(AccessTokenCacheKey).ToString(); } @@ -329,11 +323,11 @@ private async Task RefreshOAuthAccessToken(string refreshToken) RedirectUrl = OAuthRedirectUrl, RefreshToken = refreshToken, }; - var response = await GetResponse(OAuthTokenProxyUrl, HttpMethod.Post, content: tokenRequest, contentType: "application/x-www-form-urlencoded").ConfigureAwait(false); + var response = await GetResponse(OAuthTokenProxyUrl, HttpMethod.Post, content: tokenRequest, contentType: "application/x-www-form-urlencoded"); if (response.IsSuccessStatusCode) { var responseContent = await response.Content.ReadAsStringAsync(); - var tokenResponse = JsonConvert.DeserializeObject(responseContent); + var tokenResponse = JsonSerializer.Deserialize(responseContent); // Update the token details in the cache. _appCaches.RuntimeCache.Insert(AccessTokenCacheKey, () => tokenResponse.AccessToken); @@ -365,7 +359,7 @@ private async Task GetResponse( string contentType = null) { var httpClient = _httpClientFactory.CreateClient(); - + var requestMessage = new HttpRequestMessage { Method = httpMethod, @@ -388,12 +382,12 @@ private async Task GetResponse( case AuthenticationMode.OAuth: requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", - await GetOAuthAccessTokenFromCacheOrRefreshToken(authenticationDetails.RefreshToken).ConfigureAwait(false)); + await GetOAuthAccessTokenFromCacheOrRefreshToken(authenticationDetails.RefreshToken)); break; } } - return await httpClient.SendAsync(requestMessage).ConfigureAwait(false); + return await httpClient.SendAsync(requestMessage); } private static HttpContent CreateRequestContent(object data, string contentType) @@ -406,10 +400,12 @@ private static HttpContent CreateRequestContent(object data, string contentType) switch (contentType) { case JsonContentType: - var serializedData = JsonConvert.SerializeObject(data); + var serializedData = JsonSerializer.Serialize(data); return new StringContent(serializedData, Encoding.UTF8, contentType); case "application/x-www-form-urlencoded": - return new FormUrlEncodedContent(data.AsDictionary()); + var json = JsonSerializer.Serialize(data); + var dictionary = JsonSerializer.Deserialize>(json); + return new FormUrlEncodedContent(dictionary); default: throw new InvalidOperationException($"Unexpected content type: {contentType}"); } @@ -434,7 +430,7 @@ private async Task HandleFailedRequest( await RefreshOAuthAccessToken(authenticationDetails.RefreshToken); // Repeat the operation using the refreshed token. - var response = await GetResponse(requestUrl, httpMethod, authenticationDetails, content, contentType).ConfigureAwait(false); + var response = await GetResponse(requestUrl, httpMethod, authenticationDetails, content, contentType); if (response.IsSuccessStatusCode) { result.Success = true; diff --git a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Services/IContactService.cs b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Services/IContactService.cs index ba8113f..f9af375 100644 --- a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Services/IContactService.cs +++ b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Services/IContactService.cs @@ -1,7 +1,4 @@ -using System.Collections.Generic; -using System.Threading.Tasks; - -using Umbraco.Forms.Core.Persistence.Dtos; +using Umbraco.Forms.Core.Persistence.Dtos; using Umbraco.Forms.Integrations.Crm.Hubspot.Models; using Umbraco.Forms.Integrations.Crm.Hubspot.Models.Dtos; using Umbraco.Forms.Integrations.Crm.Hubspot.Models.Responses; diff --git a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Services/RefreshTokenRequest.cs b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Services/RefreshTokenRequest.cs index f149bb0..f59a5f5 100644 --- a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Services/RefreshTokenRequest.cs +++ b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Services/RefreshTokenRequest.cs @@ -1,13 +1,13 @@ -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Umbraco.Forms.Integrations.Crm.Hubspot.Services { internal class RefreshTokenRequest : BaseTokenRequest { - [JsonProperty("grant_type")] + [JsonPropertyName("grant_type")] public override string GrantType => "refresh_token"; - [JsonProperty("refresh_token")] + [JsonPropertyName("refresh_token")] public string RefreshToken { get; set; } } } diff --git a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Services/TokenResponse.cs b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Services/TokenResponse.cs index 9eb8bc7..926b412 100644 --- a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Services/TokenResponse.cs +++ b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Services/TokenResponse.cs @@ -1,16 +1,16 @@ -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Umbraco.Forms.Integrations.Crm.Hubspot.Services { internal class TokenResponse { - [JsonProperty("refresh_token")] + [JsonPropertyName("refresh_token")] public string RefreshToken { get; set; } - [JsonProperty("access_token")] + [JsonPropertyName("access_token")] public string AccessToken { get; set; } - [JsonProperty("expires_in")] + [JsonPropertyName("expires_in")] public int ExpiresInSeconds { get; set; } } } diff --git a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Umbraco.Forms.Integrations.Crm.Hubspot.csproj b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Umbraco.Forms.Integrations.Crm.Hubspot.csproj index 51e6c95..a224fed 100644 --- a/src/Umbraco.Forms.Integrations.Crm.Hubspot/Umbraco.Forms.Integrations.Crm.Hubspot.csproj +++ b/src/Umbraco.Forms.Integrations.Crm.Hubspot/Umbraco.Forms.Integrations.Crm.Hubspot.csproj @@ -6,6 +6,7 @@ enable true false + /App_Plugins/HubSpot @@ -36,13 +37,6 @@ - - - True - buildTransitive - - - true @@ -59,7 +53,7 @@ - + true diff --git a/src/Umbraco.Forms.Integrations.Crm.Hubspot/build/Microsoft.AspNetCore.ClientAssets.targets b/src/Umbraco.Forms.Integrations.Crm.Hubspot/build/Microsoft.AspNetCore.ClientAssets.targets new file mode 100644 index 0000000..5a3af6b --- /dev/null +++ b/src/Umbraco.Forms.Integrations.Crm.Hubspot/build/Microsoft.AspNetCore.ClientAssets.targets @@ -0,0 +1,61 @@ + + + + Client\ + $(ClientAssetsDirectory)\package-lock.json;$(ClientAssetsDirectory)\package.json + $(ClientAssetsDirectory)node_modules\.package-lock.json + npm ci --no-fund --no-audit --prefer-offline + npm run build + + + $(MSBuildProjectFile);$(ClientAssetsRestoreInputs) + + DispatchToInnerBuilds + + true + + + + + + + + + + + + + + <_ClientAssetsOutputFullPath>$([System.IO.Path]::GetFullPath('$(IntermediateOutputPath)clientassets')) + + + + + + + + + <_ClientAssetsBuildOutput Include="$(IntermediateOutputPath)clientassets\**"> + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Umbraco.Forms.Integrations.Crm.Hubspot/build/Umbraco.Forms.Integrations.Crm.Hubspot.targets b/src/Umbraco.Forms.Integrations.Crm.Hubspot/build/Umbraco.Forms.Integrations.Crm.Hubspot.targets deleted file mode 100644 index e7d6ae4..0000000 --- a/src/Umbraco.Forms.Integrations.Crm.Hubspot/build/Umbraco.Forms.Integrations.Crm.Hubspot.targets +++ /dev/null @@ -1,29 +0,0 @@ - - - - $(MSBuildThisFileDirectory)..\App_Plugins\UmbracoForms.Integrations\Crm\Hubspot\**\*.* - - - - - - - - - - - - - - - - - - - - diff --git a/src/Umbraco.Forms.Integrations.Testsite.V14/Umbraco.Forms.Integrations.Testsite.V14.csproj b/src/Umbraco.Forms.Integrations.Testsite.V14/Umbraco.Forms.Integrations.Testsite.V14.csproj index 796e334..ac6c694 100644 --- a/src/Umbraco.Forms.Integrations.Testsite.V14/Umbraco.Forms.Integrations.Testsite.V14.csproj +++ b/src/Umbraco.Forms.Integrations.Testsite.V14/Umbraco.Forms.Integrations.Testsite.V14.csproj @@ -11,12 +11,6 @@ - - - - - - true diff --git a/src/Umbraco.Forms.Integrations.sln b/src/Umbraco.Forms.Integrations.sln index ba7147d..02bad23 100644 --- a/src/Umbraco.Forms.Integrations.sln +++ b/src/Umbraco.Forms.Integrations.sln @@ -37,6 +37,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Umbraco.Forms.Integrations. EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Umbraco.Forms.Integrations.Testsite.V14", "Umbraco.Forms.Integrations.Testsite.V14\Umbraco.Forms.Integrations.Testsite.V14.csproj", "{8595CB83-F6E1-485D-A776-E4EB5DA13436}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Umbraco.Cms.Integrations.OAuthProxy", "Umbraco.Cms.Integrations.OAuthProxy\Umbraco.Cms.Integrations.OAuthProxy.csproj", "{221D3F2B-0373-478B-9266-7ADE09E77F5B}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -67,6 +69,10 @@ Global {8595CB83-F6E1-485D-A776-E4EB5DA13436}.Debug|Any CPU.Build.0 = Debug|Any CPU {8595CB83-F6E1-485D-A776-E4EB5DA13436}.Release|Any CPU.ActiveCfg = Release|Any CPU {8595CB83-F6E1-485D-A776-E4EB5DA13436}.Release|Any CPU.Build.0 = Release|Any CPU + {221D3F2B-0373-478B-9266-7ADE09E77F5B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {221D3F2B-0373-478B-9266-7ADE09E77F5B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {221D3F2B-0373-478B-9266-7ADE09E77F5B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {221D3F2B-0373-478B-9266-7ADE09E77F5B}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -81,6 +87,7 @@ Global {104D2677-6B53-4FF9-BB62-A68BD1D2884E} = {B068CD05-EA88-4457-B8D9-6DB899E7EBE1} {084CA526-1E5D-4AD7-8715-C5D6342CB3A0} = {104D2677-6B53-4FF9-BB62-A68BD1D2884E} {B437434B-2A95-4C8E-AF6E-4B55D4781C70} = {B05E7FB6-2403-4971-AB34-4BE43A69FBE2} + {221D3F2B-0373-478B-9266-7ADE09E77F5B} = {621A30D4-2251-43FF-BB4A-A4808C6A67D6} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {24944114-049F-4C44-95C5-E50600988018}