@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/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
+ };