| @@ -3,8 +3,9 @@ | ||
| 3 | 3 | |
| 4 | 4 | import { |
| 5 | 5 | accountName, |
| 6 | 6 | adminUrl, |
| 7 | + connectionStatus, | |
| 7 | 8 | deviceId, |
| 8 | 9 | hubspotBaseUrl, |
| 9 | 10 | leadinQueryParams, |
| 10 | 11 | locale, |
| @@ -12,22 +13,83 @@ | ||
| 12 | 13 | portalDomain, |
| 13 | 14 | portalEmail, |
| 14 | 15 | portalId, |
| 15 | 16 | reviewSkippedDate, |
| 16 | - refreshToken, | |
| 17 | 17 | impactLink, |
| 18 | 18 | theme, |
| 19 | + lastAuthorizeTime, | |
| 20 | + lastDeauthorizeTime, | |
| 21 | + lastDisconnectTime, | |
| 19 | 22 | leadinPluginVersion, |
| 20 | 23 | phpVersion, |
| 21 | 24 | wpVersion, |
| 22 | 25 | contentEmbed, |
| 23 | 26 | requiresContentEmbedScope, |
| 27 | + decryptError, | |
| 28 | + LeadinConfig, | |
| 24 | 29 | } from '../constants/leadinConfig'; |
| 30 | +import { fetchAccessToken } from '../api/wordpressApiClient'; | |
| 25 | 31 | import { App, AppIframe } from './constants'; |
| 26 | 32 | import { messageMiddleware } from './messageMiddleware'; |
| 27 | 33 | import { resizeWindow, useIframeNotRendered } from '../utils/iframe'; |
| 28 | 34 | |
| 29 | -const getLeadinConfig = () => { | |
| 35 | +type PartialLeadinConfig = Pick< | |
| 36 | + LeadinConfig, | |
| 37 | + | 'accountName' | |
| 38 | + | 'adminUrl' | |
| 39 | + | 'connectionStatus' | |
| 40 | + | 'deviceId' | |
| 41 | + | 'plugins' | |
| 42 | + | 'portalDomain' | |
| 43 | + | 'portalEmail' | |
| 44 | + | 'portalId' | |
| 45 | + | 'reviewSkippedDate' | |
| 46 | + | 'refreshToken' | |
| 47 | + | 'impactLink' | |
| 48 | + | 'theme' | |
| 49 | + | 'trackConsent' | |
| 50 | + | 'lastAuthorizeTime' | |
| 51 | + | 'lastDeauthorizeTime' | |
| 52 | + | 'lastDisconnectTime' | |
| 53 | + | 'leadinPluginVersion' | |
| 54 | + | 'phpVersion' | |
| 55 | + | 'wpVersion' | |
| 56 | + | 'contentEmbed' | |
| 57 | + | 'requiresContentEmbedScope' | |
| 58 | + | 'decryptError' | |
| 59 | +>; | |
| 60 | + | |
| 61 | +type AppIntegrationConfig = Pick<LeadinConfig, 'adminUrl'>; | |
| 62 | + | |
| 63 | +const getIntegrationConfig = (): AppIntegrationConfig => { | |
| 64 | + return { | |
| 65 | + adminUrl: leadinQueryParams.adminUrl, | |
| 66 | + }; | |
| 67 | +}; | |
| 68 | + | |
| 69 | +/** | |
| 70 | + * A modified version of the original leadinConfig that is passed to some integrated apps. | |
| 71 | + * | |
| 72 | + * Important: | |
| 73 | + * Try not to add new fields here. | |
| 74 | + * This config is already too large and broad in scope. | |
| 75 | + * It tightly couples the apps that use it with the WordPress plugin. | |
| 76 | + * Consider instead passing new required fields as new entry to PluginAppOptions or app-specific options. | |
| 77 | + */ | |
| 78 | +type AppLeadinConfig = { | |
| 79 | + admin: string; | |
| 80 | + company: string; | |
| 81 | + email: string; | |
| 82 | + firstName: string; | |
| 83 | + irclickid: string; | |
| 84 | + justConnected: string; | |
| 85 | + lastName: string; | |
| 86 | + mpid: string; | |
| 87 | + nonce: string; | |
| 88 | + websiteName: string; | |
| 89 | +} & PartialLeadinConfig; | |
| 90 | + | |
| 91 | +const getLeadinConfig = (): AppLeadinConfig => { | |
| 30 | 92 | const utm_query_params = Object.keys(leadinQueryParams) |
| 31 | 93 | .filter(x => /^utm/.test(x)) |
| 32 | 94 | .reduce( |
| 33 | 95 | (p: { [key: string]: string }, c: string) => ({ |
| @@ -40,8 +102,9 @@ | ||
| 40 | 102 | accountName, |
| 41 | 103 | admin: leadinQueryParams.admin, |
| 42 | 104 | adminUrl, |
| 43 | 105 | company: leadinQueryParams.company, |
| 106 | + connectionStatus, | |
| 44 | 107 | deviceId, |
| 45 | 108 | email: leadinQueryParams.email, |
| 46 | 109 | firstName: leadinQueryParams.firstName, |
| 47 | 110 | irclickid: leadinQueryParams.irclickid, |
| @@ -46,8 +109,11 @@ | ||
| 46 | 109 | firstName: leadinQueryParams.firstName, |
| 47 | 110 | irclickid: leadinQueryParams.irclickid, |
| 48 | 111 | justConnected: leadinQueryParams.justConnected, |
| 49 | 112 | lastName: leadinQueryParams.lastName, |
| 113 | + lastAuthorizeTime, | |
| 114 | + lastDeauthorizeTime, | |
| 115 | + lastDisconnectTime, | |
| 50 | 116 | leadinPluginVersion, |
| 51 | 117 | mpid: leadinQueryParams.mpid, |
| 52 | 118 | nonce: leadinQueryParams.nonce, |
| 53 | 119 | phpVersion, |
| @@ -61,8 +127,9 @@ | ||
| 61 | 127 | websiteName: leadinQueryParams.websiteName, |
| 62 | 128 | wpVersion, |
| 63 | 129 | contentEmbed, |
| 64 | 130 | requiresContentEmbedScope, |
| 131 | + decryptError, | |
| 65 | 132 | ...utm_query_params, |
| 66 | 133 | }; |
| 67 | 134 | }; |
| 68 | 135 | |
| @@ -75,17 +142,17 @@ | ||
| 75 | 142 | }: any = window; |
| 76 | 143 | let options; |
| 77 | 144 | switch (app) { |
| 78 | 145 | case App.Plugin: |
| 79 | - options = new PluginAppOptions().setLeadinConfig(getLeadinConfig()); | |
| 146 | + options = new PluginAppOptions(); | |
| 80 | 147 | break; |
| 81 | 148 | case App.PluginSettings: |
| 82 | - options = new PluginAppOptions() | |
| 83 | - .setLeadinConfig(getLeadinConfig()) | |
| 84 | - .setPluginSettingsInit(); | |
| 149 | + options = new PluginAppOptions().setPluginSettingsInit(); | |
| 85 | 150 | break; |
| 86 | 151 | case App.Forms: |
| 87 | - options = new FormsAppOptions(); | |
| 152 | + options = new FormsAppOptions().setIntegratedAppConfig( | |
| 153 | + getIntegrationConfig() | |
| 154 | + ); | |
| 88 | 155 | if (createRoute) { |
| 89 | 156 | options = options.setCreateFormAppInit(); |
| 90 | 157 | } |
| 91 | 158 | break; |
| @@ -116,13 +183,18 @@ | ||
| 116 | 183 | |
| 117 | 184 | useEffect(() => { |
| 118 | 185 | const { IntegratedAppEmbedder }: any = window; |
| 119 | 186 | |
| 120 | - if (IntegratedAppEmbedder) { | |
| 187 | + if (!IntegratedAppEmbedder) { | |
| 188 | + return; | |
| 189 | + } | |
| 190 | + | |
| 191 | + const createEmbedder = (accessToken = '', expiresIn = 0) => { | |
| 121 | 192 | const options = getAppOptions(app, createRoute) |
| 122 | 193 | .setLocale(locale) |
| 123 | 194 | .setDeviceId(deviceId) |
| 124 | - .setRefreshToken(refreshToken); | |
| 195 | + .setAccessToken(accessToken, expiresIn) | |
| 196 | + .setLeadinConfig(getLeadinConfig()); | |
| 125 | 197 | |
| 126 | 198 | const embedder = new IntegratedAppEmbedder( |
| 127 | 199 | AppIframe[app], |
| 128 | 200 | portalId, |
| @@ -127,16 +199,38 @@ | ||
| 127 | 199 | AppIframe[app], |
| 128 | 200 | portalId, |
| 129 | 201 | hubspotBaseUrl, |
| 130 | 202 | resizeWindow, |
| 131 | - refreshToken ? '' : impactLink | |
| 203 | + accessToken ? '' : impactLink | |
| 132 | 204 | ).setOptions(options); |
| 133 | 205 | |
| 134 | - embedder.subscribe(messageMiddleware(embedder)); | |
| 206 | + embedder.subscribe((message: any) => { | |
| 207 | + messageMiddleware(embedder)(message); | |
| 208 | + }); | |
| 209 | + embedder.setTokenRenewalCallback(fetchAccessToken); | |
| 210 | + | |
| 135 | 211 | embedder.attachTo(container, true); |
| 136 | 212 | embedder.postStartAppMessage(); // lets the app know all all data has been passed to it |
| 137 | 213 | |
| 138 | 214 | (window as any).embedder = embedder; |
| 215 | + }; | |
| 216 | + | |
| 217 | + if (connectionStatus === 'Connected') { | |
| 218 | + fetchAccessToken() | |
| 219 | + .then( | |
| 220 | + ({ | |
| 221 | + accessToken, | |
| 222 | + expiresIn, | |
| 223 | + }: { | |
| 224 | + accessToken: string; | |
| 225 | + expiresIn: number; | |
| 226 | + }) => { | |
| 227 | + createEmbedder(accessToken, expiresIn); | |
| 228 | + } | |
| 229 | + ) | |
| 230 | + .catch(() => {}); | |
| 231 | + } else { | |
| 232 | + createEmbedder(); | |
| 139 | 233 | } |
| 140 | 234 | }, []); |
| 141 | 235 | |
| 142 | 236 | if (iframeNotRendered) { |
| @@ -154,9 +248,9 @@ | ||
| 154 | 248 | app, |
| 155 | 249 | hubspotBaseUrl, |
| 156 | 250 | impactLink, |
| 157 | 251 | appName: AppIframe[app], |
| 158 | - hasRefreshToken: !!refreshToken, | |
| 252 | + isConnected: connectionStatus === 'Connected', | |
| 159 | 253 | }, |
| 160 | 254 | }); |
| 161 | 255 | } |
| 162 | 256 | |