Skip to content

Commit 82ff570

Browse files
committed
V14: Integrations (Dynamics)
- Add oauth configuration
1 parent 7429320 commit 82ff570

File tree

6 files changed

+116
-16
lines changed

6 files changed

+116
-16
lines changed

src/Umbraco.Cms.Integrations.Crm.Dynamics/Client/src/context/dynamics.context.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { UmbControllerBase } from "@umbraco-cms/backoffice/class-api";
22
import { UmbContextToken } from "@umbraco-cms/backoffice/context-api";
33
import type { UmbControllerHost } from "@umbraco-cms/backoffice/controller-api";
44
import { DynamicsRepository } from "../repository/dynamics.repository";
5+
import { OAuthRequestDtoModel } from "@umbraco-integrations/dynamics/generated";
56

67
export class DynamicsContext extends UmbControllerBase{
78
#repository: DynamicsRepository;
@@ -33,8 +34,8 @@ export class DynamicsContext extends UmbControllerBase{
3334
return await this.#repository.checkOauthConfiguration();
3435
}
3536

36-
async getAccessToken(){
37-
return await this.#repository.getAccessToken();
37+
async getAccessToken(oAuthRequestDtoModel: OAuthRequestDtoModel){
38+
return await this.#repository.getAccessToken(oAuthRequestDtoModel);
3839
}
3940

4041
async getEmbedCode(formId: string){

src/Umbraco.Cms.Integrations.Crm.Dynamics/Client/src/modal/dynamics-form-modal.element.ts

Lines changed: 94 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,28 @@ import { customElement, html, repeat, state } from "@umbraco-cms/backoffice/exte
22
import { UmbModalBaseElement } from "@umbraco-cms/backoffice/modal";
33
import { DynamicsFormPickerModalData, DynamicsFormPickerModalValue } from "./dynamics.modal-token";
44
import { DYNAMICS_CONTEXT_TOKEN } from "../context/dynamics.context";
5-
import { FormDtoModel } from "@umbraco-integrations/dynamics/generated";
5+
import { FormDtoModel, OAuthConfigurationDtoModel, OAuthRequestDtoModel } from "@umbraco-integrations/dynamics/generated";
6+
import { UMB_NOTIFICATION_CONTEXT, UmbNotificationColor } from "@umbraco-cms/backoffice/notification";
7+
import { DynamicsOAuthSetup } from "../models/dynamics-service.model";
68

79
const elementName = "dynamics-forms-modal";
810

911
@customElement(elementName)
1012
export default class DynamicsFormModalElement extends UmbModalBaseElement<DynamicsFormPickerModalData, DynamicsFormPickerModalValue>{
1113
#dynamicsContext!: typeof DYNAMICS_CONTEXT_TOKEN.TYPE;
1214

15+
@state()
16+
private _loading = false;
1317
@state()
1418
private _forms: Array<FormDtoModel> = [];
19+
@state()
20+
private _oAuthConfig: OAuthConfigurationDtoModel | undefined;
21+
@state()
22+
private _oauthSetup: DynamicsOAuthSetup = {
23+
isConnected: false,
24+
isAccessTokenExpired: false,
25+
isAccessTokenValid: false
26+
};
1527

1628
constructor() {
1729
super();
@@ -24,25 +36,96 @@ export default class DynamicsFormModalElement extends UmbModalBaseElement<Dynami
2436

2537
async connectedCallback() {
2638
super.connectedCallback();
27-
await this.getForms();
39+
await this.#checkOAuthConfiguration();
40+
}
41+
42+
async #checkOAuthConfiguration(){
43+
const {data} = await this.#dynamicsContext.checkOauthConfiguration();
44+
if(!data) return;
45+
if(!data.isAuthorized) this._showError("Unable to connect to Dynamics. Please review the settings of the form picker property's data type.");
46+
47+
this._oAuthConfig = data;
48+
49+
await this.#getForms();
2850
}
2951

30-
async getForms(){
52+
async #getForms(){
53+
this._loading = true;
3154
const { data } = await this.#dynamicsContext.getForms("Both");
3255
if(!data) return;
3356

3457
this._forms = data;
58+
this._loading = false;
3559
}
3660

3761
_onSelect(form: FormDtoModel){
3862
this.value = { selectedForm: form };
3963
this._submitModal();
4064
}
4165

66+
async #connectButtonClick(){
67+
window.addEventListener("message", async (event: MessageEvent) => {
68+
if (event.data.type === "dynamics:oauth:success") {
69+
70+
const oauthRequestDtoModel: OAuthRequestDtoModel = {
71+
code: event.data.code
72+
};
73+
74+
const { data } = await this.#dynamicsContext.getAccessToken(oauthRequestDtoModel);
75+
if (!data) return;
76+
77+
if (data.startsWith("Error:")) {
78+
this._showError(data);
79+
} else {
80+
this._oauthSetup = {
81+
isConnected: true
82+
};
83+
this._showSuccess("OAuth Connected");
84+
85+
}
86+
87+
}
88+
}, false);
89+
90+
const { data } = await this.#dynamicsContext.getAuthorizationUrl();
91+
if (!data) return;
92+
93+
window.open(data, "Authorize", "width=900,height=700,modal=yes,alwaysRaised=yes");
94+
}
95+
96+
async #revokeButtonClick(){
97+
await this.#dynamicsContext.revokeAccessToken();
98+
99+
this._oauthSetup = {
100+
isConnected: false
101+
};
102+
this._showSuccess("OAuth connection revoked.");
103+
104+
this.dispatchEvent(new CustomEvent("revoke"));
105+
}
106+
107+
private async _showSuccess(message: string) {
108+
await this._showMessage(message, "positive");
109+
}
110+
111+
private async _showError(message: string) {
112+
await this._showMessage(message, "danger");
113+
}
114+
115+
private async _showMessage(message: string, color: UmbNotificationColor) {
116+
const notificationContext = await this.getContext(UMB_NOTIFICATION_CONTEXT);
117+
notificationContext?.peek(color, {
118+
data: { message },
119+
});
120+
}
121+
42122
render(){
43123
return html`
44124
<umb-body-layout>
45-
<uui-box headline="Dynamics Marketing Forms">
125+
126+
${this._loading ? html`<div class="center loader"><uui-loader></uui-loader></div>` : ""}
127+
128+
<uui-box headline=${this.data!.headline}>
46129
<div slot="header">Select a form</div>
47130
48131
${repeat(this._forms, (form) => html`
@@ -57,16 +140,20 @@ export default class DynamicsFormModalElement extends UmbModalBaseElement<Dynami
57140
<uui-box headline="Dynamics - OAuth Status">
58141
<div slot="header">Please connect with your Microsoft account.</div>
59142
<div>
60-
<p><b>Connected</b>: Thanhnd</p>
143+
<p><b>Connected</b>: ${this._oAuthConfig?.fullName}</p>
61144
</div>
62145
<div>
63146
<uui-button
64147
look="primary"
65-
label="Connect"></uui-button>
148+
label="Connect"
149+
?disabled=${this._oauthSetup?.isConnected}
150+
@click=${this.#connectButtonClick}></uui-button>
66151
<uui-button
67152
color="danger"
68153
look="secondary"
69-
label="Revoke"></uui-button>
154+
label="Revoke"
155+
?disabled=${!this._oauthSetup?.isConnected}
156+
@click=${this.#revokeButtonClick}></uui-button>
70157
</div>
71158
</uui-box>
72159

src/Umbraco.Cms.Integrations.Crm.Dynamics/Client/src/modal/dynamics.modal-token.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import { DynamicsFormPickerConfiguration } from "../types/types";
44

55
export type DynamicsFormPickerModalData = {
66
headline: string;
7-
selectedFormId: string | null;
87
config: DynamicsFormPickerConfiguration | undefined;
98
}
109

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export type DynamicsOAuthSetup = {
2+
isConnected?: boolean;
3+
isAccessTokenExpired?: boolean;
4+
isAccessTokenValid?: boolean;
5+
}

src/Umbraco.Cms.Integrations.Crm.Dynamics/Client/src/property-editor/dynamics-form-picker-property-editor.element.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,20 @@ export class DynamicsFormPickerPropertyEditor extends UmbLitElement implements U
5656

5757
if (this.value == null || this.value.length == 0) return;
5858

59-
await this.#getForms();
59+
await this.#checkOAuthConfiguration();
6060
}
6161

62-
async #getForms(){
62+
async #checkOAuthConfiguration(){
63+
const {data} = await this.#dynamicsContext.checkOauthConfiguration();
64+
if(!data) return;
65+
if(!data.isAuthorized) this._showError("Unable to connect to Dynamics. Please review the settings of the form picker property's data type.");
6366

67+
await this.#getForm();
68+
}
69+
70+
async #getForm(){
71+
const model: FormDtoModel = JSON.parse(JSON.stringify(this.value));
72+
this.selectedForm = model;
6473
}
6574

6675
deleteForm(formId: string){
@@ -71,7 +80,6 @@ export class DynamicsFormPickerPropertyEditor extends UmbLitElement implements U
7180
const pickerContext = this.#modalManagerContext?.open(this, DYNAMICS_MODAL_TOKEN, {
7281
data: {
7382
headline: "Dynamics Forms",
74-
selectedFormId: "1",
7583
config: this._config
7684
},
7785
});

src/Umbraco.Cms.Integrations.Crm.Dynamics/Client/src/repository/dynamics.repository.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { UmbControllerBase } from "@umbraco-cms/backoffice/class-api";
22
import type { UmbControllerHost } from "@umbraco-cms/backoffice/controller-api";
33
import { tryExecuteAndNotify } from "@umbraco-cms/backoffice/resources";
4-
import { DynamicsService } from "@umbraco-integrations/dynamics/generated";
4+
import { DynamicsService, OAuthRequestDtoModel } from "@umbraco-integrations/dynamics/generated";
55

66
export class DynamicsRepository extends UmbControllerBase {
77
constructor(host: UmbControllerHost) {
@@ -50,8 +50,8 @@ export class DynamicsRepository extends UmbControllerBase {
5050
return { data };
5151
}
5252

53-
async getAccessToken(){
54-
const { data, error } = await tryExecuteAndNotify(this, DynamicsService.getAccessToken());
53+
async getAccessToken(oAuthRequestDtoModel: OAuthRequestDtoModel){
54+
const { data, error } = await tryExecuteAndNotify(this, DynamicsService.getAccessToken({requestBody: oAuthRequestDtoModel}));
5555

5656
if (error || !data) {
5757
return { error };

0 commit comments

Comments
 (0)