Skip to content

Commit 72fddc0

Browse files
authored
Merge pull request #29 from umbraco/feature/ms-dynamics-integration
Feature/ms dynamics integration
2 parents adfe18b + 9209698 commit 72fddc0

Some content is hidden

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

41 files changed

+1661
-1
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
@using Umbraco.Cms.Integrations.Crm.Dynamics.Models.ViewModels;
2+
3+
@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage<FormViewModel>
4+
5+
@{
6+
var id = Guid.NewGuid();
7+
}
8+
9+
@if (Model.IframeEmbedded)
10+
{
11+
<iframe frameBorder="0" style="width:100%;height:100%;" id=@id></iframe>
12+
<script>
13+
var sandboxSrc = "https://@(Model.Hostname)/t/formsandbox/@(Model.WebsiteId)/@(Model.FormBlockId)?ad="
14+
+ encodeURIComponent(document.location.toString()); document.getElementById('@id').setAttribute('src', sandboxSrc);
15+
</script>
16+
}
17+
else
18+
{
19+
<div data-form-block-id="@Model.FormBlockId"></div>
20+
<script src="https://mktdplp102cdn.azureedge.net/public/latest/js/form-loader.js?v=1.84.2007"></script>
21+
<div id="@Model.ContainerId"></div>
22+
<script src="https://mktdplp102cdn.azureedge.net/public/latest/js/ws-tracking.js?v=1.84.2007"></script>
23+
<div class="@Model.ContainerClass" style="display:none"
24+
data-website-id="@Model.WebsiteId" data-hostname="@Model.Hostname"></div>
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
@using Umbraco.Cms.Integrations.Crm.Dynamics.Models.ViewModels;
2+
3+
@inherits Umbraco.Web.Mvc.UmbracoViewPage<FormViewModel>
4+
5+
@{
6+
var id = Guid.NewGuid();
7+
}
8+
9+
@if (Model.IframeEmbedded)
10+
{
11+
<iframe frameBorder="0" style="width:100%;height:100%;" id=@id></iframe>
12+
<script>
13+
var sandboxSrc = "https://@(Model.Hostname)/t/formsandbox/@(Model.WebsiteId)/@(Model.FormBlockId)?ad="
14+
+ encodeURIComponent(document.location.toString()); document.getElementById('@id').setAttribute('src', sandboxSrc);
15+
</script>
16+
}
17+
else
18+
{
19+
<div data-form-block-id="@Model.FormBlockId"></div>
20+
<script src="https://mktdplp102cdn.azureedge.net/public/latest/js/form-loader.js?v=1.84.2007"></script>
21+
<div id="@Model.ContainerId"></div>
22+
<script src="https://mktdplp102cdn.azureedge.net/public/latest/js/ws-tracking.js?v=1.84.2007"></script>
23+
<div class="@Model.ContainerClass" style="display:none"
24+
data-website-id="@Model.WebsiteId" data-hostname="@Model.Hostname"></div>
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
.dynOverlayGroup {
2+
margin-bottom: 1rem;
3+
}
4+
5+
.dynFormsList {
6+
list-style-type: none;
7+
margin: 0;
8+
margin-top: 10px;
9+
}
10+
11+
.dynFormsList a {
12+
display: block;
13+
position: relative;
14+
padding: .25rem .375rem .25rem 1.5rem;
15+
}
16+
17+
.dynFormsList a:hover {
18+
text-decoration: none;
19+
background-color: #eee;
20+
}
21+
22+
.dynFormsList a i {
23+
position: absolute;
24+
top: .4rem;
25+
left: .25rem;
26+
}
27+
28+
.dynFormsList .formLine {
29+
display: block;
30+
}
31+
32+
.dynSettings {
33+
padding-top: 4px;
34+
}
35+
36+
.dynFormSelected {
37+
background: #fee4e1;
38+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
function configurationController($scope, notificationsService, umbracoCmsIntegrationsCrmDynamicsResource) {
2+
var vm = this;
3+
4+
vm.oauthConfig = {};
5+
6+
umbracoCmsIntegrationsCrmDynamicsResource.checkOAuthConfiguration().then(function (response) {
7+
if (response && response.isAuthorized) {
8+
vm.oauthConfig.isConnected = true;
9+
vm.oauthConfig.fullName = response.fullName;
10+
11+
if (typeof $scope.connected === "function")
12+
$scope.connected();
13+
}
14+
});
15+
16+
vm.onConnectClick = function () {
17+
18+
umbracoCmsIntegrationsCrmDynamicsResource.getAuthorizationUrl().then(function (response) {
19+
vm.authWindow = window.open(response,
20+
"Authorize", "width=900,height=700,modal=yes,alwaysRaised=yes");
21+
});
22+
}
23+
24+
vm.onRevokeToken = function () {
25+
26+
umbracoCmsIntegrationsCrmDynamicsResource.revokeAccessToken().then(function () {
27+
vm.oauthConfig.isConnected = false;
28+
29+
// if directive runs from property editor, the notifications should be hidden, because they will not be displayed properly behind the overlay window.
30+
// if directive runs from data type, the notifications are displayed
31+
if (typeof $scope.connected === "undefined")
32+
notificationsService.success("Dynamics Configuration", "OAuth connection revoked.");
33+
34+
if (typeof $scope.revoked === "function")
35+
$scope.revoked();
36+
});
37+
}
38+
39+
// authorization listener
40+
window.addEventListener("message", function (event) {
41+
if (event.data.type === "hubspot:oauth:success") {
42+
43+
umbracoCmsIntegrationsCrmDynamicsResource.getAccessToken(event.data.code).then(function (response) {
44+
if (response.startsWith("Error:")) {
45+
46+
// if directive runs from property editor, the notifications should be hidden, because they will not be displayed properly behind the overlay window.
47+
// if directive runs from data type, the notifications are displayed
48+
if (typeof $scope.connected === "undefined")
49+
notificationsService.error("Dynamics Configuration", response);
50+
} else {
51+
vm.oauthConfig.isConnected = true;
52+
53+
// if directive runs from property editor, the notifications should be hidden, because they will not be displayed properly behind the overlay window.
54+
// if directive runs from data type, the notifications are displayed
55+
if (typeof $scope.connected === "undefined")
56+
notificationsService.success("Dynamics Configuration", "OAuth connected.");
57+
58+
umbracoCmsIntegrationsCrmDynamicsResource.getSystemUserFullName().then(function(response) {
59+
vm.oauthConfig.fullName = response;
60+
});
61+
62+
if (typeof $scope.connected === "function")
63+
$scope.connected();
64+
}
65+
});
66+
}
67+
}, false);
68+
}
69+
70+
angular.module("umbraco")
71+
.controller("Umbraco.Cms.Integrations.Crm.Dynamics.ConfigurationController", configurationController);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
angular.module('umbraco.resources').factory('umbracoCmsIntegrationsCrmDynamicsResource',
2+
function ($http, umbRequestHelper) {
3+
4+
const apiEndpoint = "backoffice/UmbracoCmsIntegrationsCrmDynamics/Forms";
5+
6+
return {
7+
getAuthorizationUrl: function () {
8+
return umbRequestHelper.resourcePromise(
9+
$http.get(`${apiEndpoint}/GetAuthorizationUrl`),
10+
"Failed");
11+
},
12+
getAccessToken: function (authorizationCode) {
13+
return umbRequestHelper.resourcePromise(
14+
$http.post(`${apiEndpoint}/GetAccessToken`, { code: authorizationCode }),
15+
"Failed");
16+
},
17+
revokeAccessToken: function () {
18+
return umbRequestHelper.resourcePromise(
19+
$http.post(`${apiEndpoint}/RevokeAccessToken`),
20+
"Failed");
21+
},
22+
getSystemUserFullName: function () {
23+
return umbRequestHelper.resourcePromise(
24+
$http.get(`${apiEndpoint}/GetSystemUserFullName`),
25+
"Failed");
26+
},
27+
getForms: function () {
28+
return umbRequestHelper.resourcePromise(
29+
$http.get(`${apiEndpoint}/GetForms`),
30+
"Failed");
31+
},
32+
getEmbedCode: function (formId) {
33+
return umbRequestHelper.resourcePromise(
34+
$http.get(`${apiEndpoint}/GetEmbedCode?formId=${formId}`),
35+
"Failed");
36+
},
37+
checkOAuthConfiguration: function () {
38+
return umbRequestHelper.resourcePromise(
39+
$http.get(`${apiEndpoint}/CheckOAuthConfiguration`),
40+
"Failed");
41+
}
42+
};
43+
}
44+
);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
function formPickerController($scope, editorService, notificationsService, umbracoCmsIntegrationsCrmDynamicsResource) {
2+
3+
var vm = this;
4+
5+
vm.loading = false;
6+
vm.dynamicsFormsList = [];
7+
8+
vm.searchTerm = "";
9+
10+
vm.selectedForm = {};
11+
vm.iframeEmbedded = false;
12+
13+
vm.isConnected = false;
14+
15+
umbracoCmsIntegrationsCrmDynamicsResource.checkOAuthConfiguration().then(function (response) {
16+
if (response.isAuthorized) {
17+
loadForms();
18+
} else {
19+
let error = "Unable to connect to Dynamics. Please review the settings of the form picker property's data type.";
20+
notificationsService.error("Dynamics API", error);
21+
vm.error = error;
22+
}
23+
});
24+
25+
vm.saveForm = function (form) {
26+
27+
umbracoCmsIntegrationsCrmDynamicsResource.getEmbedCode(form.id).then(function (response) {
28+
29+
form.embedCode = response;
30+
31+
$scope.model.value = form;
32+
});
33+
}
34+
35+
vm.removeForm = function () {
36+
$scope.model.value = null;
37+
}
38+
39+
vm.toggleRenderMode = function () {
40+
vm.iframeEmbedded = !vm.iframeEmbedded;
41+
}
42+
43+
vm.openDynamicsFormPickerOverlay = function () {
44+
45+
var options = {
46+
title: "Dynamics - Marketing Forms",
47+
subtitle: "Select a form",
48+
view: "/App_Plugins/UmbracoCms.Integrations/Crm/Dynamics/views/formpickereditor.html",
49+
size: "medium",
50+
selectForm: function (form, iframeEmbedded) {
51+
52+
form.iframeEmbedded = iframeEmbedded;
53+
54+
vm.saveForm(form);
55+
56+
editorService.close();
57+
},
58+
close: function () {
59+
editorService.close();
60+
}
61+
};
62+
63+
editorService.open(options);
64+
};
65+
66+
function loadForms() {
67+
vm.dynamicsFormsList = [];
68+
umbracoCmsIntegrationsCrmDynamicsResource.getForms().then(function (response) {
69+
if (response) {
70+
response.value.forEach(item => {
71+
vm.dynamicsFormsList.push({
72+
id: item.msdyncrm_marketingformid,
73+
name: item.msdyncrm_name,
74+
embedCode: "",
75+
iframeEmbedded: vm.iframeEmbedded
76+
});
77+
});
78+
}
79+
});
80+
}
81+
82+
$scope.connected = function () {
83+
vm.isConnected = true;
84+
loadForms();
85+
};
86+
87+
$scope.revoked = function () {
88+
vm.isConnected = false;
89+
vm.dynamicsFormsList = [];
90+
};
91+
}
92+
93+
angular.module("umbraco")
94+
.controller("Umbraco.Cms.Integrations.Crm.Dynamics.FormPickerController", formPickerController);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
angular.module("umbraco.directives")
2+
.directive("oauthConfiguration", function () {
3+
return {
4+
restrict: "E",
5+
scope: {
6+
"connected": "&onConnected",
7+
"revoked": "&onRevoked"
8+
},
9+
templateUrl: "/App_Plugins/UmbracoCms.Integrations/Crm/Dynamics/views/configuration.html"
10+
}
11+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"javascript": [
3+
"~/App_Plugins/UmbracoCms.Integrations/Crm/Dynamics/js/configuration.controller.js",
4+
"~/App_Plugins/UmbracoCms.Integrations/Crm/Dynamics/js/formpicker.controller.js",
5+
"~/App_Plugins/UmbracoCms.Integrations/Crm/Dynamics/js/dynamics.resource.js",
6+
"~/App_Plugins/UmbracoCms.Integrations/Crm/Dynamics/js/oauthconfiguration.directive.js"
7+
],
8+
"css": [
9+
"~/App_Plugins/UmbracoCms.Integrations/Crm/Dynamics/css/styles.css"
10+
]
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<div ng-controller="Umbraco.Cms.Integrations.Crm.Dynamics.ConfigurationController as vm">
2+
<p ng-if="vm.oauthConfig && vm.oauthConfig.isConnected"><b>Connected:</b> {{ vm.oauthConfig.fullName }} </p>
3+
<p ng-if="!vm.oauthConfig || !vm.oauthConfig.isConnected"><b>Disconnected</b></p>
4+
<div>
5+
<umb-button action="vm.onConnectClick()"
6+
type="button"
7+
button-style="primary"
8+
state="init"
9+
label="Connect"
10+
disabled="vm.oauthConfig.isConnected">
11+
</umb-button>
12+
<umb-button action="vm.onRevokeToken()"
13+
type="button"
14+
button-style="danger"
15+
state="init"
16+
label="Revoke"
17+
disabled="!vm.oauthConfig.isConnected">
18+
</umb-button>
19+
</div>
20+
</div>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<div ng-controller="Umbraco.Cms.Integrations.Crm.Dynamics.FormPickerController as vm">
2+
3+
<umb-load-indicator ng-if="vm.loading">
4+
</umb-load-indicator>
5+
6+
<umb-node-preview ng-if="model.value"
7+
name="model.value.name"
8+
allow-remove="true" ,
9+
on-remove="vm.removeForm()">
10+
</umb-node-preview>
11+
12+
<a ng-if="!model.value && !vm.loading"
13+
class="umb-node-preview-add"
14+
href=""
15+
ng-click="vm.openDynamicsFormPickerOverlay()"
16+
prevent-default>
17+
<localize key="general_add">Add</localize>
18+
</a>
19+
20+
<div ng-if="vm.error" class="alert alert-warning">
21+
{{ vm.error }}
22+
</div>
23+
</div>

0 commit comments

Comments
 (0)