@meetelise/chat 1.20.150 → 1.20.151
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/public/dist/index.js +3 -3
- package/src/MEChat.ts +0 -242
- package/src/WebComponent/me-chat.ts +246 -0
package/src/MEChat.ts
CHANGED
|
@@ -2,9 +2,6 @@ import axios from "axios";
|
|
|
2
2
|
import { StyleInfo } from "lit/directives/style-map";
|
|
3
3
|
import "./WebComponent/me-chat";
|
|
4
4
|
import { MEChat as MEChatLitElement } from "./WebComponent/me-chat";
|
|
5
|
-
import fetchBuildingInfo from "./fetchBuildingInfo";
|
|
6
|
-
import { fetchFeatureFlagUseOverrideContactUsForm } from "./fetchFeatureFlag";
|
|
7
|
-
import fetchCurrentParsedLeadSource from "./fetchCurrentParsedLeadSource";
|
|
8
5
|
import { tintColor } from "./themes";
|
|
9
6
|
|
|
10
7
|
/**
|
|
@@ -60,10 +57,6 @@ export default class MEChat {
|
|
|
60
57
|
}
|
|
61
58
|
document.body.appendChild(meChat);
|
|
62
59
|
MEChat.meChat = meChat;
|
|
63
|
-
|
|
64
|
-
if (opts.building && opts.organization) {
|
|
65
|
-
overrideContactUsForm(opts.organization, opts.building);
|
|
66
|
-
}
|
|
67
60
|
}
|
|
68
61
|
|
|
69
62
|
static async restartConversation(): Promise<void> {
|
|
@@ -156,238 +149,3 @@ const installFont = () => {
|
|
|
156
149
|
link.setAttribute("type", "text/css");
|
|
157
150
|
document.head.appendChild(link);
|
|
158
151
|
};
|
|
159
|
-
|
|
160
|
-
const findElementById = (priorityIds: string[]): HTMLElement | null => {
|
|
161
|
-
for (const id of priorityIds) {
|
|
162
|
-
const element = document.getElementById(id);
|
|
163
|
-
if (element) {
|
|
164
|
-
return element;
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
return null;
|
|
168
|
-
};
|
|
169
|
-
|
|
170
|
-
const overrideContactUsForm = async (
|
|
171
|
-
orgSlug: string,
|
|
172
|
-
buildingSlug?: string
|
|
173
|
-
): Promise<void> => {
|
|
174
|
-
if (!buildingSlug || !orgSlug) return;
|
|
175
|
-
const shouldUseOverrideContactUsForm =
|
|
176
|
-
await fetchFeatureFlagUseOverrideContactUsForm(buildingSlug);
|
|
177
|
-
if (!shouldUseOverrideContactUsForm) return;
|
|
178
|
-
|
|
179
|
-
const form = findElementById(["myContactForm", "contactus"]);
|
|
180
|
-
let btn = undefined;
|
|
181
|
-
|
|
182
|
-
if (!form || !(form instanceof HTMLFormElement)) {
|
|
183
|
-
const foundForm = document.querySelector("form");
|
|
184
|
-
if (window.location.pathname.toLowerCase().includes("contactus")) {
|
|
185
|
-
logContactUsFormError(
|
|
186
|
-
buildingSlug,
|
|
187
|
-
orgSlug,
|
|
188
|
-
"Could not find form",
|
|
189
|
-
foundForm ? { id: foundForm.id } : undefined
|
|
190
|
-
);
|
|
191
|
-
}
|
|
192
|
-
return;
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
// Loop through the elements of the form
|
|
196
|
-
for (let i = 0; i < form.elements.length; i++) {
|
|
197
|
-
const element = form.elements[i];
|
|
198
|
-
if (
|
|
199
|
-
element.tagName.toLowerCase() === "button" &&
|
|
200
|
-
element.getAttribute("data-selenium-id") === "fakebutton"
|
|
201
|
-
) {
|
|
202
|
-
btn = element;
|
|
203
|
-
break;
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
if (!btn) {
|
|
208
|
-
return logContactUsFormError(
|
|
209
|
-
buildingSlug,
|
|
210
|
-
orgSlug,
|
|
211
|
-
"Could not find submit button"
|
|
212
|
-
);
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
const eliseUrl =
|
|
216
|
-
"https://app.meetelise.com/platformApi/state/create/contactMe";
|
|
217
|
-
|
|
218
|
-
const getFormElements = () => {
|
|
219
|
-
const firstName = findElementById([
|
|
220
|
-
"firstname",
|
|
221
|
-
"txtName",
|
|
222
|
-
]) as HTMLInputElement | null;
|
|
223
|
-
const lastName = findElementById([
|
|
224
|
-
"lastname",
|
|
225
|
-
"txtName2",
|
|
226
|
-
]) as HTMLInputElement | null;
|
|
227
|
-
const email = findElementById([
|
|
228
|
-
"email",
|
|
229
|
-
"txtEmail",
|
|
230
|
-
]) as HTMLInputElement | null;
|
|
231
|
-
const phone = findElementById([
|
|
232
|
-
"phonenumber",
|
|
233
|
-
"txtPhone",
|
|
234
|
-
]) as HTMLInputElement | null;
|
|
235
|
-
const message = findElementById([
|
|
236
|
-
"message",
|
|
237
|
-
"txtComments",
|
|
238
|
-
]) as HTMLTextAreaElement | null;
|
|
239
|
-
|
|
240
|
-
const formElements = { firstName, lastName, email, phone, message };
|
|
241
|
-
|
|
242
|
-
return formElements;
|
|
243
|
-
};
|
|
244
|
-
|
|
245
|
-
const isMissingFormElements = () => {
|
|
246
|
-
if (Object.values(getFormElements()).some((el) => el === null)) {
|
|
247
|
-
return true;
|
|
248
|
-
}
|
|
249
|
-
return false;
|
|
250
|
-
};
|
|
251
|
-
|
|
252
|
-
const validateFormElements = () => {
|
|
253
|
-
Object.values(getFormElements()).forEach((el) => {
|
|
254
|
-
if (el?.getAttribute("aria-required") === "true" && !el.value) {
|
|
255
|
-
el.className = "form-control required is-invalid";
|
|
256
|
-
}
|
|
257
|
-
});
|
|
258
|
-
};
|
|
259
|
-
|
|
260
|
-
const isValid = () => {
|
|
261
|
-
return Object.values(getFormElements()).every((el) => {
|
|
262
|
-
if (el === null) return false;
|
|
263
|
-
if (el.getAttribute("aria-required") === "true" && !el.value) {
|
|
264
|
-
return false;
|
|
265
|
-
}
|
|
266
|
-
if (
|
|
267
|
-
(el.id === "email" || el.id === "phonenumber") &&
|
|
268
|
-
el.getAttribute("aria-invalid") === "true"
|
|
269
|
-
) {
|
|
270
|
-
return false;
|
|
271
|
-
}
|
|
272
|
-
return true;
|
|
273
|
-
});
|
|
274
|
-
};
|
|
275
|
-
|
|
276
|
-
if (isMissingFormElements()) {
|
|
277
|
-
const missingElements = Object.entries(getFormElements())
|
|
278
|
-
.filter(([, val]) => val === null)
|
|
279
|
-
.map(([key]) => key);
|
|
280
|
-
return logContactUsFormError(
|
|
281
|
-
buildingSlug,
|
|
282
|
-
orgSlug,
|
|
283
|
-
"Missing the following form elements: " + missingElements.join(", ")
|
|
284
|
-
);
|
|
285
|
-
}
|
|
286
|
-
const originalButtonText = btn.textContent;
|
|
287
|
-
|
|
288
|
-
// Replace the original form element with the cloned one
|
|
289
|
-
const clonedButton = btn.cloneNode(true) as HTMLButtonElement;
|
|
290
|
-
btn.parentNode?.replaceChild(clonedButton, btn);
|
|
291
|
-
|
|
292
|
-
clonedButton.onclick = async function (event) {
|
|
293
|
-
validateFormElements();
|
|
294
|
-
|
|
295
|
-
if (!isValid()) return;
|
|
296
|
-
event.preventDefault();
|
|
297
|
-
|
|
298
|
-
clonedButton.textContent = "Processing request...";
|
|
299
|
-
clonedButton.disabled = true;
|
|
300
|
-
|
|
301
|
-
const formValues: { [key: string]: string | undefined } = {};
|
|
302
|
-
Object.entries(getFormElements()).forEach(
|
|
303
|
-
([key, val]) => (formValues[key] = val?.value)
|
|
304
|
-
);
|
|
305
|
-
|
|
306
|
-
const building = await fetchBuildingInfo(orgSlug, buildingSlug);
|
|
307
|
-
const currentLeadSource = await fetchCurrentParsedLeadSource(
|
|
308
|
-
buildingSlug,
|
|
309
|
-
document.referrer
|
|
310
|
-
);
|
|
311
|
-
|
|
312
|
-
if (!building) {
|
|
313
|
-
logContactUsFormError(buildingSlug, orgSlug, "Could not find building");
|
|
314
|
-
return null;
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
const data = {
|
|
318
|
-
email_address: formValues.email,
|
|
319
|
-
first_name: formValues.firstName,
|
|
320
|
-
last_name: formValues.lastName,
|
|
321
|
-
phone_number: formValues.phone,
|
|
322
|
-
first_message: formValues.message,
|
|
323
|
-
building_id: building.id,
|
|
324
|
-
is_external_form: true,
|
|
325
|
-
lead_sources: [
|
|
326
|
-
...new Set(
|
|
327
|
-
currentLeadSource
|
|
328
|
-
? [currentLeadSource, "property-website"]
|
|
329
|
-
: ["property-website"]
|
|
330
|
-
),
|
|
331
|
-
],
|
|
332
|
-
};
|
|
333
|
-
|
|
334
|
-
const jsonData = JSON.stringify(data);
|
|
335
|
-
|
|
336
|
-
fetch(eliseUrl, {
|
|
337
|
-
method: "POST",
|
|
338
|
-
headers: {
|
|
339
|
-
"Content-Type": "application/json",
|
|
340
|
-
"building-slug": buildingSlug,
|
|
341
|
-
"org-slug": orgSlug,
|
|
342
|
-
},
|
|
343
|
-
body: jsonData,
|
|
344
|
-
})
|
|
345
|
-
.then((response) => {
|
|
346
|
-
if (!response.ok) {
|
|
347
|
-
throw new Error(`HTTP error ${response.status}`);
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
if (form) {
|
|
351
|
-
form.reset();
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
Object.values(getFormElements()).forEach((el) => {
|
|
355
|
-
if (!el) return;
|
|
356
|
-
el.disabled = true;
|
|
357
|
-
});
|
|
358
|
-
clonedButton.textContent = "Submitted";
|
|
359
|
-
clonedButton.disabled = true;
|
|
360
|
-
|
|
361
|
-
return response.json();
|
|
362
|
-
})
|
|
363
|
-
.catch(() => {
|
|
364
|
-
clonedButton.textContent = originalButtonText;
|
|
365
|
-
});
|
|
366
|
-
};
|
|
367
|
-
};
|
|
368
|
-
|
|
369
|
-
const logContactUsFormError = (
|
|
370
|
-
buildingSlug: string,
|
|
371
|
-
orgSlug: string,
|
|
372
|
-
reason?: string,
|
|
373
|
-
formIdInfo?: Record<string, unknown>
|
|
374
|
-
) => {
|
|
375
|
-
const url = `https://app.meetelise.com/platformApi/webchat/form-override-error`;
|
|
376
|
-
const body = JSON.stringify({
|
|
377
|
-
orgSlug,
|
|
378
|
-
buildingSlug,
|
|
379
|
-
reason,
|
|
380
|
-
url: window.location.href,
|
|
381
|
-
formIdInfo,
|
|
382
|
-
});
|
|
383
|
-
|
|
384
|
-
fetch(url, {
|
|
385
|
-
method: "POST",
|
|
386
|
-
headers: {
|
|
387
|
-
"Content-Type": "application/json",
|
|
388
|
-
"building-slug": buildingSlug,
|
|
389
|
-
"org-slug": orgSlug,
|
|
390
|
-
},
|
|
391
|
-
body,
|
|
392
|
-
});
|
|
393
|
-
};
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
FeatureFlagsShowDropdown,
|
|
11
11
|
fetchFeatureFlagInsertDNIWebsite,
|
|
12
12
|
fetchFeatureFlagShowMarketingSourceDropdown,
|
|
13
|
+
fetchFeatureFlagUseOverrideContactUsForm,
|
|
13
14
|
fetchFeatureFlagUsePhoneNumberBySource,
|
|
14
15
|
} from "../fetchFeatureFlag";
|
|
15
16
|
import fetchWebchatPreferences, {
|
|
@@ -191,9 +192,19 @@ export class MEChat extends LitElement {
|
|
|
191
192
|
return;
|
|
192
193
|
}
|
|
193
194
|
const building = await fetchBuildingInfo(this.orgSlug, this.buildingSlug);
|
|
195
|
+
if (building.conversationMaintenanceMode) {
|
|
196
|
+
// eslint-disable-next-line no-console
|
|
197
|
+
console.warn(
|
|
198
|
+
"MeetElise Chat is in maintenance mode. Chat icon will not appear."
|
|
199
|
+
);
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
194
202
|
if (building.active !== 1) {
|
|
195
203
|
return;
|
|
196
204
|
}
|
|
205
|
+
if (building && this.orgSlug) {
|
|
206
|
+
overrideContactUsForm(this.orgSlug, this.buildingSlug);
|
|
207
|
+
}
|
|
197
208
|
|
|
198
209
|
const [
|
|
199
210
|
buildingABTest,
|
|
@@ -653,3 +664,238 @@ declare global {
|
|
|
653
664
|
RCTPCampaign?: { CampaignDetails: { Source: string } };
|
|
654
665
|
}
|
|
655
666
|
}
|
|
667
|
+
|
|
668
|
+
const findElementById = (priorityIds: string[]): HTMLElement | null => {
|
|
669
|
+
for (const id of priorityIds) {
|
|
670
|
+
const element = document.getElementById(id);
|
|
671
|
+
if (element) {
|
|
672
|
+
return element;
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
return null;
|
|
676
|
+
};
|
|
677
|
+
|
|
678
|
+
const overrideContactUsForm = async (
|
|
679
|
+
orgSlug: string,
|
|
680
|
+
buildingSlug?: string
|
|
681
|
+
): Promise<void> => {
|
|
682
|
+
if (!buildingSlug || !orgSlug) return;
|
|
683
|
+
const shouldUseOverrideContactUsForm =
|
|
684
|
+
await fetchFeatureFlagUseOverrideContactUsForm(buildingSlug);
|
|
685
|
+
if (!shouldUseOverrideContactUsForm) return;
|
|
686
|
+
|
|
687
|
+
const form = findElementById(["myContactForm", "contactus"]);
|
|
688
|
+
let btn = undefined;
|
|
689
|
+
|
|
690
|
+
if (!form || !(form instanceof HTMLFormElement)) {
|
|
691
|
+
const foundForm = document.querySelector("form");
|
|
692
|
+
if (window.location.pathname.toLowerCase().includes("contactus")) {
|
|
693
|
+
logContactUsFormError(
|
|
694
|
+
buildingSlug,
|
|
695
|
+
orgSlug,
|
|
696
|
+
"Could not find form",
|
|
697
|
+
foundForm ? { id: foundForm.id } : undefined
|
|
698
|
+
);
|
|
699
|
+
}
|
|
700
|
+
return;
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
// Loop through the elements of the form
|
|
704
|
+
for (let i = 0; i < form.elements.length; i++) {
|
|
705
|
+
const element = form.elements[i];
|
|
706
|
+
if (
|
|
707
|
+
element.tagName.toLowerCase() === "button" &&
|
|
708
|
+
element.getAttribute("data-selenium-id") === "fakebutton"
|
|
709
|
+
) {
|
|
710
|
+
btn = element;
|
|
711
|
+
break;
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
if (!btn) {
|
|
716
|
+
return logContactUsFormError(
|
|
717
|
+
buildingSlug,
|
|
718
|
+
orgSlug,
|
|
719
|
+
"Could not find submit button"
|
|
720
|
+
);
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
const eliseUrl =
|
|
724
|
+
"https://app.meetelise.com/platformApi/state/create/contactMe";
|
|
725
|
+
|
|
726
|
+
const getFormElements = () => {
|
|
727
|
+
const firstName = findElementById([
|
|
728
|
+
"firstname",
|
|
729
|
+
"txtName",
|
|
730
|
+
]) as HTMLInputElement | null;
|
|
731
|
+
const lastName = findElementById([
|
|
732
|
+
"lastname",
|
|
733
|
+
"txtName2",
|
|
734
|
+
]) as HTMLInputElement | null;
|
|
735
|
+
const email = findElementById([
|
|
736
|
+
"email",
|
|
737
|
+
"txtEmail",
|
|
738
|
+
]) as HTMLInputElement | null;
|
|
739
|
+
const phone = findElementById([
|
|
740
|
+
"phonenumber",
|
|
741
|
+
"txtPhone",
|
|
742
|
+
]) as HTMLInputElement | null;
|
|
743
|
+
const message = findElementById([
|
|
744
|
+
"message",
|
|
745
|
+
"txtComments",
|
|
746
|
+
]) as HTMLTextAreaElement | null;
|
|
747
|
+
|
|
748
|
+
const formElements = { firstName, lastName, email, phone, message };
|
|
749
|
+
|
|
750
|
+
return formElements;
|
|
751
|
+
};
|
|
752
|
+
|
|
753
|
+
const isMissingFormElements = () => {
|
|
754
|
+
if (Object.values(getFormElements()).some((el) => el === null)) {
|
|
755
|
+
return true;
|
|
756
|
+
}
|
|
757
|
+
return false;
|
|
758
|
+
};
|
|
759
|
+
|
|
760
|
+
const validateFormElements = () => {
|
|
761
|
+
Object.values(getFormElements()).forEach((el) => {
|
|
762
|
+
if (el?.getAttribute("aria-required") === "true" && !el.value) {
|
|
763
|
+
el.className = "form-control required is-invalid";
|
|
764
|
+
}
|
|
765
|
+
});
|
|
766
|
+
};
|
|
767
|
+
|
|
768
|
+
const isValid = () => {
|
|
769
|
+
return Object.values(getFormElements()).every((el) => {
|
|
770
|
+
if (el === null) return false;
|
|
771
|
+
if (el.getAttribute("aria-required") === "true" && !el.value) {
|
|
772
|
+
return false;
|
|
773
|
+
}
|
|
774
|
+
if (
|
|
775
|
+
(el.id === "email" || el.id === "phonenumber") &&
|
|
776
|
+
el.getAttribute("aria-invalid") === "true"
|
|
777
|
+
) {
|
|
778
|
+
return false;
|
|
779
|
+
}
|
|
780
|
+
return true;
|
|
781
|
+
});
|
|
782
|
+
};
|
|
783
|
+
|
|
784
|
+
if (isMissingFormElements()) {
|
|
785
|
+
const missingElements = Object.entries(getFormElements())
|
|
786
|
+
.filter(([, val]) => val === null)
|
|
787
|
+
.map(([key]) => key);
|
|
788
|
+
return logContactUsFormError(
|
|
789
|
+
buildingSlug,
|
|
790
|
+
orgSlug,
|
|
791
|
+
"Missing the following form elements: " + missingElements.join(", ")
|
|
792
|
+
);
|
|
793
|
+
}
|
|
794
|
+
const originalButtonText = btn.textContent;
|
|
795
|
+
|
|
796
|
+
// Replace the original form element with the cloned one
|
|
797
|
+
const clonedButton = btn.cloneNode(true) as HTMLButtonElement;
|
|
798
|
+
btn.parentNode?.replaceChild(clonedButton, btn);
|
|
799
|
+
|
|
800
|
+
clonedButton.onclick = async function (event) {
|
|
801
|
+
validateFormElements();
|
|
802
|
+
|
|
803
|
+
if (!isValid()) return;
|
|
804
|
+
event.preventDefault();
|
|
805
|
+
|
|
806
|
+
clonedButton.textContent = "Processing request...";
|
|
807
|
+
clonedButton.disabled = true;
|
|
808
|
+
|
|
809
|
+
const formValues: { [key: string]: string | undefined } = {};
|
|
810
|
+
Object.entries(getFormElements()).forEach(
|
|
811
|
+
([key, val]) => (formValues[key] = val?.value)
|
|
812
|
+
);
|
|
813
|
+
|
|
814
|
+
const building = await fetchBuildingInfo(orgSlug, buildingSlug);
|
|
815
|
+
const currentLeadSource = await fetchCurrentParsedLeadSource(
|
|
816
|
+
buildingSlug,
|
|
817
|
+
document.referrer
|
|
818
|
+
);
|
|
819
|
+
|
|
820
|
+
if (!building) {
|
|
821
|
+
logContactUsFormError(buildingSlug, orgSlug, "Could not find building");
|
|
822
|
+
return null;
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
const data = {
|
|
826
|
+
email_address: formValues.email,
|
|
827
|
+
first_name: formValues.firstName,
|
|
828
|
+
last_name: formValues.lastName,
|
|
829
|
+
phone_number: formValues.phone,
|
|
830
|
+
first_message: formValues.message,
|
|
831
|
+
building_id: building.id,
|
|
832
|
+
is_external_form: true,
|
|
833
|
+
lead_sources: [
|
|
834
|
+
...new Set(
|
|
835
|
+
currentLeadSource
|
|
836
|
+
? [currentLeadSource, "property-website"]
|
|
837
|
+
: ["property-website"]
|
|
838
|
+
),
|
|
839
|
+
],
|
|
840
|
+
};
|
|
841
|
+
|
|
842
|
+
const jsonData = JSON.stringify(data);
|
|
843
|
+
|
|
844
|
+
fetch(eliseUrl, {
|
|
845
|
+
method: "POST",
|
|
846
|
+
headers: {
|
|
847
|
+
"Content-Type": "application/json",
|
|
848
|
+
"building-slug": buildingSlug,
|
|
849
|
+
"org-slug": orgSlug,
|
|
850
|
+
},
|
|
851
|
+
body: jsonData,
|
|
852
|
+
})
|
|
853
|
+
.then((response) => {
|
|
854
|
+
if (!response.ok) {
|
|
855
|
+
throw new Error(`HTTP error ${response.status}`);
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
if (form) {
|
|
859
|
+
form.reset();
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
Object.values(getFormElements()).forEach((el) => {
|
|
863
|
+
if (!el) return;
|
|
864
|
+
el.disabled = true;
|
|
865
|
+
});
|
|
866
|
+
clonedButton.textContent = "Submitted";
|
|
867
|
+
clonedButton.disabled = true;
|
|
868
|
+
|
|
869
|
+
return response.json();
|
|
870
|
+
})
|
|
871
|
+
.catch(() => {
|
|
872
|
+
clonedButton.textContent = originalButtonText;
|
|
873
|
+
});
|
|
874
|
+
};
|
|
875
|
+
};
|
|
876
|
+
|
|
877
|
+
const logContactUsFormError = (
|
|
878
|
+
buildingSlug: string,
|
|
879
|
+
orgSlug: string,
|
|
880
|
+
reason?: string,
|
|
881
|
+
formIdInfo?: Record<string, unknown>
|
|
882
|
+
) => {
|
|
883
|
+
const url = `https://app.meetelise.com/platformApi/webchat/form-override-error`;
|
|
884
|
+
const body = JSON.stringify({
|
|
885
|
+
orgSlug,
|
|
886
|
+
buildingSlug,
|
|
887
|
+
reason,
|
|
888
|
+
url: window.location.href,
|
|
889
|
+
formIdInfo,
|
|
890
|
+
});
|
|
891
|
+
|
|
892
|
+
fetch(url, {
|
|
893
|
+
method: "POST",
|
|
894
|
+
headers: {
|
|
895
|
+
"Content-Type": "application/json",
|
|
896
|
+
"building-slug": buildingSlug,
|
|
897
|
+
"org-slug": orgSlug,
|
|
898
|
+
},
|
|
899
|
+
body,
|
|
900
|
+
});
|
|
901
|
+
};
|