@meetelise/chat 1.20.113 → 1.20.115
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/demo/index.html +4 -0
- package/public/dist/index.js +376 -389
- package/public/dist/index.js.LICENSE.txt +6 -0
- package/src/MEChat.ts +2 -23
- package/src/MyPubnub.ts +4 -1
- package/src/WebComponent/actions/call-us-window.ts +282 -44
- package/src/WebComponent/launcher/Launcher.ts +69 -113
- package/src/WebComponent/me-chat.ts +76 -321
- package/src/WebComponent/pubnub-chat.ts +4 -5
- package/src/fetchWebchatPreferences.ts +1 -0
- package/src/themes.ts +45 -155
- package/src/utils.ts +0 -53
- package/src/WebComponent/actions/text-us-window.ts +0 -286
- package/src/chatID.ts +0 -64
- package/src/createConversation.ts +0 -57
package/src/MEChat.ts
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import axios from "axios";
|
|
2
2
|
import { StyleInfo } from "lit/directives/style-map";
|
|
3
|
-
import { ThemeIdString } from "./themes";
|
|
4
|
-
import { tintColor } from "./utils";
|
|
5
3
|
import "./WebComponent/me-chat";
|
|
6
4
|
import { MEChat as MEChatLitElement } from "./WebComponent/me-chat";
|
|
7
5
|
import fetchBuildingInfo from "./fetchBuildingInfo";
|
|
8
6
|
import { fetchFeatureFlagUseOverrideContactUsForm } from "./fetchFeatureFlag";
|
|
9
7
|
import fetchCurrentParsedLeadSource from "./fetchCurrentParsedLeadSource";
|
|
8
|
+
import { tintColor } from "./themes";
|
|
10
9
|
|
|
11
10
|
/**
|
|
12
11
|
* The interface to MeetElise chat.
|
|
@@ -42,7 +41,6 @@ export default class MEChat {
|
|
|
42
41
|
this.hasBuildingSlug = !!opts.building;
|
|
43
42
|
}
|
|
44
43
|
installFont();
|
|
45
|
-
installTalkjsMobileStyleFix();
|
|
46
44
|
const meChat = document.createElement("me-chat");
|
|
47
45
|
meChat.setAttribute("orgSlug", opts.organization);
|
|
48
46
|
this.handleBuildingslug(meChat, opts.building);
|
|
@@ -51,15 +49,6 @@ export default class MEChat {
|
|
|
51
49
|
meChat.setAttribute("aria-label", "EliseAI Widget");
|
|
52
50
|
meChat.setAttribute("aria-describedby", "aria-describe-info");
|
|
53
51
|
meChat.setAttribute("aria-modal", "true");
|
|
54
|
-
if (opts.themeId) {
|
|
55
|
-
meChat.setAttribute("themeId", opts.themeId);
|
|
56
|
-
}
|
|
57
|
-
if (opts.avatarSrc) {
|
|
58
|
-
meChat.setAttribute("avatarSrc", opts.avatarSrc);
|
|
59
|
-
}
|
|
60
|
-
if (opts.mini !== undefined) {
|
|
61
|
-
meChat.useMiniWidget = opts.mini;
|
|
62
|
-
}
|
|
63
52
|
if (opts.launcherStyles) {
|
|
64
53
|
meChat.launcherStyles = opts.launcherStyles;
|
|
65
54
|
}
|
|
@@ -154,7 +143,6 @@ export default class MEChat {
|
|
|
154
143
|
export interface Options {
|
|
155
144
|
building: string;
|
|
156
145
|
organization: string;
|
|
157
|
-
themeId?: ThemeIdString;
|
|
158
146
|
avatarSrc?: string;
|
|
159
147
|
mini?: boolean;
|
|
160
148
|
launcherStyles?: StyleInfo;
|
|
@@ -169,16 +157,6 @@ const installFont = () => {
|
|
|
169
157
|
document.head.appendChild(link);
|
|
170
158
|
};
|
|
171
159
|
|
|
172
|
-
const installTalkjsMobileStyleFix = () => {
|
|
173
|
-
const metaTag = document.createElement("meta");
|
|
174
|
-
metaTag.setAttribute("name", "viewport");
|
|
175
|
-
metaTag.setAttribute(
|
|
176
|
-
"content",
|
|
177
|
-
"width=device-width, initial-scale=1, maximum-scale=2"
|
|
178
|
-
);
|
|
179
|
-
document.head.appendChild(metaTag);
|
|
180
|
-
};
|
|
181
|
-
|
|
182
160
|
const findElementById = (priorityIds: string[]): HTMLElement | null => {
|
|
183
161
|
for (const id of priorityIds) {
|
|
184
162
|
const element = document.getElementById(id);
|
|
@@ -392,6 +370,7 @@ const logContactUsFormError = (
|
|
|
392
370
|
orgSlug,
|
|
393
371
|
buildingSlug,
|
|
394
372
|
reason,
|
|
373
|
+
url: window.location.href,
|
|
395
374
|
});
|
|
396
375
|
|
|
397
376
|
fetch(url, {
|
package/src/MyPubnub.ts
CHANGED
|
@@ -439,7 +439,10 @@ class MyPubnub {
|
|
|
439
439
|
return false;
|
|
440
440
|
}
|
|
441
441
|
|
|
442
|
-
const expirationDate = addHours(
|
|
442
|
+
const expirationDate = addHours(
|
|
443
|
+
storageValueDeconstructed.timestamp,
|
|
444
|
+
this.ttlHours
|
|
445
|
+
);
|
|
443
446
|
return isBefore(storageValueDeconstructed.timestamp, expirationDate);
|
|
444
447
|
};
|
|
445
448
|
}
|
|
@@ -1,12 +1,22 @@
|
|
|
1
|
+
import axios from "axios";
|
|
1
2
|
import { css, html, LitElement, TemplateResult } from "lit";
|
|
2
|
-
import { customElement, property } from "lit/decorators.js";
|
|
3
|
+
import { customElement, property, state } from "lit/decorators.js";
|
|
4
|
+
import { createRef, ref, Ref } from "lit/directives/ref.js";
|
|
5
|
+
import { pushGtmEvent } from "../../gtm";
|
|
3
6
|
import { PhoneBlackStrokeIcon } from "../../svgIcons";
|
|
4
7
|
|
|
5
8
|
import { getOfficeHourText } from "../OfficeHours";
|
|
9
|
+
import {
|
|
10
|
+
formatToPhoneInput,
|
|
11
|
+
isModifierKey,
|
|
12
|
+
isNumericInput,
|
|
13
|
+
} from "./formatPhoneNumber";
|
|
14
|
+
import { InputStyles } from "./InputStyles";
|
|
6
15
|
|
|
7
16
|
@customElement("call-us-window")
|
|
8
17
|
export class CallUsWindow extends LitElement {
|
|
9
18
|
static styles = [
|
|
19
|
+
InputStyles,
|
|
10
20
|
css`
|
|
11
21
|
#call-us-window__content-wrapper {
|
|
12
22
|
font-family: "Helvetica Neue", Arial;
|
|
@@ -73,30 +83,88 @@ export class CallUsWindow extends LitElement {
|
|
|
73
83
|
text-transform: lowercase;
|
|
74
84
|
text-align: right;
|
|
75
85
|
}
|
|
86
|
+
|
|
87
|
+
.text-us-wrapper {
|
|
88
|
+
margin-top: 33px;
|
|
89
|
+
color: #202020;
|
|
90
|
+
}
|
|
91
|
+
.text-us-window__header {
|
|
92
|
+
font-family: "Helvetica Neue", Arial;
|
|
93
|
+
font-style: normal;
|
|
94
|
+
font-weight: 700;
|
|
95
|
+
line-height: 140%;
|
|
96
|
+
font-size: 14px;
|
|
97
|
+
margin: 0;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.text-us-window__input-container {
|
|
101
|
+
margin-top: 8px;
|
|
102
|
+
margin-bottom: 8px;
|
|
103
|
+
width: -webkit-fill-available;
|
|
104
|
+
position: relative;
|
|
105
|
+
}
|
|
106
|
+
.text-us-window__submit-text {
|
|
107
|
+
position: absolute;
|
|
108
|
+
top: 14px;
|
|
109
|
+
right: 6px;
|
|
110
|
+
}
|
|
111
|
+
.text-us-window__vertical-spacer {
|
|
112
|
+
height: 20px;
|
|
113
|
+
}
|
|
114
|
+
.text-us-window__description,
|
|
115
|
+
.text-us-window__error {
|
|
116
|
+
font-family: "Helvetica Neue", Arial;
|
|
117
|
+
font-style: normal;
|
|
118
|
+
font-weight: 400;
|
|
119
|
+
font-size: 10px;
|
|
120
|
+
line-height: 14px;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.text-us-window__error {
|
|
124
|
+
color: rgb(255, 49, 3);
|
|
125
|
+
}
|
|
76
126
|
`,
|
|
77
127
|
];
|
|
78
128
|
|
|
129
|
+
@property({ attribute: true })
|
|
130
|
+
buildingSlug = "";
|
|
131
|
+
@property({ attribute: true })
|
|
132
|
+
orgSlug = "";
|
|
133
|
+
|
|
79
134
|
@property({ attribute: false })
|
|
80
135
|
onCloseClicked?: (e: MouseEvent) => void;
|
|
81
136
|
|
|
82
137
|
@property()
|
|
83
|
-
|
|
138
|
+
phoneNumberToCall = "1-855-531-5131";
|
|
139
|
+
|
|
140
|
+
@property()
|
|
141
|
+
phoneNumberToText = "";
|
|
142
|
+
|
|
84
143
|
@property({ attribute: false })
|
|
85
144
|
buildingId = 0;
|
|
86
145
|
@property({ attribute: true })
|
|
87
146
|
chatCallUsHeader = "";
|
|
147
|
+
|
|
148
|
+
@property({ attribute: true })
|
|
149
|
+
hasCallUsEnabled = "";
|
|
150
|
+
|
|
88
151
|
@property({ attribute: true })
|
|
89
152
|
hasTextUsEnabled = "";
|
|
90
153
|
|
|
91
154
|
@property({ attribute: true })
|
|
92
155
|
currentLeadSource = "";
|
|
93
156
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
157
|
+
phoneNumberInputRef: Ref<HTMLInputElement> = createRef();
|
|
158
|
+
|
|
159
|
+
@state()
|
|
160
|
+
hasSubmittedForm = false;
|
|
161
|
+
@state()
|
|
162
|
+
hasPhoneNumberError = false;
|
|
163
|
+
@state()
|
|
164
|
+
hasSubmissionError = false;
|
|
165
|
+
|
|
166
|
+
@state()
|
|
167
|
+
submittingTextUsOption = false;
|
|
100
168
|
|
|
101
169
|
@property({ attribute: false })
|
|
102
170
|
officeHoursTextInfo: (
|
|
@@ -104,6 +172,11 @@ export class CallUsWindow extends LitElement {
|
|
|
104
172
|
| { dayOfWeek: string; startTime: string; endTime: string }
|
|
105
173
|
)[] = [];
|
|
106
174
|
|
|
175
|
+
firstUpdated = async (): Promise<void> => {
|
|
176
|
+
if (!this.buildingId || !this.hasCallUsEnabled) return;
|
|
177
|
+
this.officeHoursTextInfo = await getOfficeHourText(this.buildingId);
|
|
178
|
+
};
|
|
179
|
+
|
|
107
180
|
getCallLink = (phoneNumber: string): TemplateResult => {
|
|
108
181
|
const rawNumber = (phoneNumber.match(/\d+/g) || []).join("");
|
|
109
182
|
const rawInternationalNumber =
|
|
@@ -119,6 +192,126 @@ export class CallUsWindow extends LitElement {
|
|
|
119
192
|
>`;
|
|
120
193
|
};
|
|
121
194
|
|
|
195
|
+
enforcePhoneFormat = (e: KeyboardEvent): void => {
|
|
196
|
+
if (!isNumericInput(e) && !isModifierKey(e)) {
|
|
197
|
+
e.preventDefault();
|
|
198
|
+
}
|
|
199
|
+
};
|
|
200
|
+
onSubmitTextUs = async (): Promise<void> => {
|
|
201
|
+
this.hasPhoneNumberError = false;
|
|
202
|
+
this.hasSubmissionError = false;
|
|
203
|
+
if (!this.phoneNumberToText || this.phoneNumberToText.length !== 14) {
|
|
204
|
+
this.hasPhoneNumberError = true;
|
|
205
|
+
}
|
|
206
|
+
if (this.hasPhoneNumberError) {
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
try {
|
|
210
|
+
this.submittingTextUsOption = true;
|
|
211
|
+
await createTextWithUs(
|
|
212
|
+
this.phoneNumberToText,
|
|
213
|
+
this.buildingId,
|
|
214
|
+
this.orgSlug,
|
|
215
|
+
this.buildingSlug,
|
|
216
|
+
[
|
|
217
|
+
...new Set(
|
|
218
|
+
this.currentLeadSource
|
|
219
|
+
? [this.currentLeadSource, "property-website"]
|
|
220
|
+
: ["property-website"]
|
|
221
|
+
),
|
|
222
|
+
]
|
|
223
|
+
);
|
|
224
|
+
this.hasSubmittedForm = true;
|
|
225
|
+
this.submittingTextUsOption = false;
|
|
226
|
+
} catch (e) {
|
|
227
|
+
this.submittingTextUsOption = false;
|
|
228
|
+
this.hasSubmissionError = true;
|
|
229
|
+
}
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
onChangePhoneNumber = (e: Event): void => {
|
|
233
|
+
if (!e.target || !this.phoneNumberInputRef.value) {
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
if (isModifierKey(e as KeyboardEvent)) {
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
const inputElement = e.target as HTMLInputElement;
|
|
240
|
+
|
|
241
|
+
this.phoneNumberToText = formatToPhoneInput(inputElement.value);
|
|
242
|
+
|
|
243
|
+
this.phoneNumberInputRef.value.value = this.phoneNumberToText;
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
private renderFormTextUsOption = (): TemplateResult => {
|
|
247
|
+
return html` <div class="text-us-wrapper">
|
|
248
|
+
<h1 class="text-us-window__header">Send Us a Text</h1>
|
|
249
|
+
<div class="text-us-window__input-container">
|
|
250
|
+
<input
|
|
251
|
+
${ref(this.phoneNumberInputRef)}
|
|
252
|
+
maxlength="14"
|
|
253
|
+
type="text"
|
|
254
|
+
placeholder="Enter phone"
|
|
255
|
+
inputmode="tel"
|
|
256
|
+
class="webchat-input text-us-window__input-container"
|
|
257
|
+
.value=${this.phoneNumberToText}
|
|
258
|
+
@keydown=${this.enforcePhoneFormat}
|
|
259
|
+
@keyup=${this.onChangePhoneNumber}
|
|
260
|
+
/>
|
|
261
|
+
<div class="text-us-window__submit-text">
|
|
262
|
+
<action-confirm-button
|
|
263
|
+
.onClick=${this.onSubmitTextUs}
|
|
264
|
+
.isLoading=${this.submittingTextUsOption}
|
|
265
|
+
text="SEND"
|
|
266
|
+
></action-confirm-button>
|
|
267
|
+
</div>
|
|
268
|
+
${this.hasPhoneNumberError
|
|
269
|
+
? html`
|
|
270
|
+
<div class="text-us-window__error">
|
|
271
|
+
Enter a valid phone number
|
|
272
|
+
</div>
|
|
273
|
+
`
|
|
274
|
+
: ""}
|
|
275
|
+
</div>
|
|
276
|
+
|
|
277
|
+
<div class="text-us-window__description">
|
|
278
|
+
By entering your number and selecting Send, you consent to be contacted
|
|
279
|
+
by our AI Leasing Assistant. Your consent to this process is not a
|
|
280
|
+
requirement for leasing at our property.
|
|
281
|
+
<div class="text-us-window__description">
|
|
282
|
+
Message and data rates may apply.
|
|
283
|
+
</div>
|
|
284
|
+
</div>
|
|
285
|
+
</div>`;
|
|
286
|
+
};
|
|
287
|
+
|
|
288
|
+
private renderSubmittedTextUsOption = (): TemplateResult => {
|
|
289
|
+
return html`
|
|
290
|
+
<div class="text-us-wrapper">
|
|
291
|
+
<div class="text-us-window__vertical-spacer"></div>
|
|
292
|
+
<svg
|
|
293
|
+
width="20"
|
|
294
|
+
height="20"
|
|
295
|
+
viewBox="0 0 20 20"
|
|
296
|
+
fill="none"
|
|
297
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
298
|
+
>
|
|
299
|
+
<path
|
|
300
|
+
d="M4.455 16L0 19.5V1C0 0.734784 0.105357 0.48043 0.292893 0.292893C0.48043 0.105357 0.734784 0 1 0H19C19.2652 0 19.5196 0.105357 19.7071 0.292893C19.8946 0.48043 20 0.734784 20 1V15C20 15.2652 19.8946 15.5196 19.7071 15.7071C19.5196 15.8946 19.2652 16 19 16H4.455ZM2 15.385L3.763 14H18V2H2V15.385ZM10 7V4L14 8L10 12V9H6V7H10Z"
|
|
301
|
+
fill="#202020"
|
|
302
|
+
/>
|
|
303
|
+
</svg>
|
|
304
|
+
<div class="text-us-window__description">
|
|
305
|
+
Thank you!<br />Look for a text message from our team. We can answer
|
|
306
|
+
questions and help you book a tour through text.
|
|
307
|
+
</div>
|
|
308
|
+
<div class="text-us-window__description">
|
|
309
|
+
Opt out at anytime by texting “Stop”
|
|
310
|
+
</div>
|
|
311
|
+
</div>
|
|
312
|
+
`;
|
|
313
|
+
};
|
|
314
|
+
|
|
122
315
|
render = (): TemplateResult => {
|
|
123
316
|
return html`
|
|
124
317
|
<details-window
|
|
@@ -126,43 +319,46 @@ export class CallUsWindow extends LitElement {
|
|
|
126
319
|
headerText="${this.chatCallUsHeader}"
|
|
127
320
|
.onCloseClick=${this.onCloseClicked}
|
|
128
321
|
>
|
|
129
|
-
|
|
130
|
-
<
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
322
|
+
${this.hasCallUsEnabled
|
|
323
|
+
? html` <div id="call-us-window__content-wrapper">
|
|
324
|
+
<h1 class="call-us-window__call-us-text call-us-window__header">
|
|
325
|
+
Contact Our Leasing Team
|
|
326
|
+
</h1>
|
|
327
|
+
<div class="call-us-window__phone-redirect">
|
|
328
|
+
${PhoneBlackStrokeIcon}
|
|
329
|
+
${this.getCallLink(this.phoneNumberToCall)}
|
|
330
|
+
</div>
|
|
331
|
+
<div class="call-us-window__office-hours-wrapper">
|
|
332
|
+
<h1 class="call-us-window__oh-header call-us-window__header">
|
|
333
|
+
Office Hours
|
|
334
|
+
</h1>
|
|
335
|
+
${this.officeHoursTextInfo.map((oh) => {
|
|
336
|
+
if (typeof oh === "string") {
|
|
337
|
+
return html`
|
|
338
|
+
<div class="call-us-window__day-of-week-wrapper">
|
|
339
|
+
<div class="call-us-window__day-of-week">${oh}</div>
|
|
340
|
+
<div class="call-us-window__closed">Closed</div>
|
|
341
|
+
</div>
|
|
342
|
+
`;
|
|
343
|
+
}
|
|
344
|
+
return html`
|
|
345
|
+
<div class="call-us-window__day-of-week-wrapper">
|
|
346
|
+
<div class="call-us-window__day-of-week">
|
|
347
|
+
${oh.dayOfWeek}
|
|
348
|
+
</div>
|
|
349
|
+
<div class="call-us-window__open-times">
|
|
350
|
+
${oh.startTime} – ${oh.endTime}
|
|
351
|
+
</div>
|
|
352
|
+
</div>
|
|
353
|
+
`;
|
|
354
|
+
})}
|
|
355
|
+
</div>
|
|
356
|
+
</div>`
|
|
357
|
+
: ""}
|
|
160
358
|
${this.hasTextUsEnabled
|
|
161
|
-
?
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
currentLeadSource="${this.currentLeadSource}"
|
|
165
|
-
></text-us-window>`
|
|
359
|
+
? this.hasSubmittedForm
|
|
360
|
+
? this.renderSubmittedTextUsOption()
|
|
361
|
+
: this.renderFormTextUsOption()
|
|
166
362
|
: ""}
|
|
167
363
|
</details-window>
|
|
168
364
|
`;
|
|
@@ -174,3 +370,45 @@ export const installCallUsWindow = (): void => {
|
|
|
174
370
|
window.customElements.define("call-us-window", CallUsWindow);
|
|
175
371
|
}
|
|
176
372
|
};
|
|
373
|
+
|
|
374
|
+
const createTextWithUs = async (
|
|
375
|
+
rawPhoneNumber: string,
|
|
376
|
+
buildingId: number,
|
|
377
|
+
orgSlug: string,
|
|
378
|
+
buildingSlug: string,
|
|
379
|
+
leadSources: string[]
|
|
380
|
+
) => {
|
|
381
|
+
const formattedPhoneNumber =
|
|
382
|
+
"+1" +
|
|
383
|
+
rawPhoneNumber
|
|
384
|
+
.replace("(", "")
|
|
385
|
+
.replace(")", "")
|
|
386
|
+
.replace(" ", "")
|
|
387
|
+
.replace("-", "");
|
|
388
|
+
const queryParams = new URLSearchParams(window.location.search);
|
|
389
|
+
const requestBody = {
|
|
390
|
+
building_id: buildingId,
|
|
391
|
+
lead_sources: leadSources,
|
|
392
|
+
phone_number: formattedPhoneNumber,
|
|
393
|
+
referrer: document.referrer,
|
|
394
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
395
|
+
// @ts-ignore
|
|
396
|
+
query_params: Object.fromEntries(queryParams.entries()),
|
|
397
|
+
};
|
|
398
|
+
pushGtmEvent("textUsSubmitted", {
|
|
399
|
+
phone: formattedPhoneNumber,
|
|
400
|
+
originatingSource:
|
|
401
|
+
leadSources.find((i) => i !== "property-website") || null,
|
|
402
|
+
});
|
|
403
|
+
await axios.post(
|
|
404
|
+
"https://app.meetelise.com/platformApi/state/create/textMe",
|
|
405
|
+
requestBody,
|
|
406
|
+
{
|
|
407
|
+
headers: {
|
|
408
|
+
["building-slug"]: buildingSlug,
|
|
409
|
+
["org-slug"]: orgSlug,
|
|
410
|
+
["X-SecurityKey"]: "JRL8jV4VcSCwOSir5gWkpgNLfKghmhBG",
|
|
411
|
+
},
|
|
412
|
+
}
|
|
413
|
+
);
|
|
414
|
+
};
|