@meetelise/chat 1.25.0 → 1.25.2

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.
Files changed (136) hide show
  1. package/coverage/lcov-report/base.css +224 -0
  2. package/coverage/lcov-report/block-navigation.js +79 -0
  3. package/coverage/lcov-report/favicon.png +0 -0
  4. package/coverage/lcov-report/index.html +111 -0
  5. package/coverage/lcov-report/index.js.html +17093 -0
  6. package/coverage/lcov-report/prettify.css +1 -0
  7. package/coverage/lcov-report/prettify.js +2 -0
  8. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  9. package/coverage/lcov-report/sorter.js +170 -0
  10. package/coverage/lcov.info +9986 -0
  11. package/dist/index.d.ts +1 -0
  12. package/package.json +1 -1
  13. package/.eslintignore +0 -2
  14. package/.eslintrc.cjs +0 -23
  15. package/.github/pull_request_template.md +0 -61
  16. package/.github/workflows/pull.yml +0 -46
  17. package/.github/workflows/release.yml +0 -23
  18. package/.husky/commit-msg +0 -2
  19. package/.husky/pre-commit +0 -4
  20. package/.idea/codeStyles/Project.xml +0 -57
  21. package/.idea/codeStyles/codeStyleConfig.xml +0 -5
  22. package/.idea/inspectionProfiles/Project_Default.xml +0 -6
  23. package/.idea/vcs.xml +0 -6
  24. package/.idea/workspace.xml +0 -67
  25. package/.prettierignore +0 -2
  26. package/.prettierrc.json +0 -1
  27. package/.vscode/settings.json +0 -13
  28. package/CONTRIBUTING.md +0 -36
  29. package/public/demo/index.html +0 -347
  30. package/public/demo/secret.html +0 -63
  31. package/src/MyPubnub.ts +0 -792
  32. package/src/WebComponent/FeeCalculator/components/collapsible-fee-section/collapsible-fee-section-styles.ts +0 -86
  33. package/src/WebComponent/FeeCalculator/components/collapsible-fee-section/collapsible-fee-section.ts +0 -94
  34. package/src/WebComponent/FeeCalculator/components/fee-item/fee-item-styles.ts +0 -47
  35. package/src/WebComponent/FeeCalculator/components/fee-item/fee-item.ts +0 -50
  36. package/src/WebComponent/FeeCalculator/components/floor-plan-selector/floor-plan-selector-styles.ts +0 -46
  37. package/src/WebComponent/FeeCalculator/components/floor-plan-selector/floor-plan-selector.ts +0 -70
  38. package/src/WebComponent/FeeCalculator/components/index.ts +0 -3
  39. package/src/WebComponent/FeeCalculator/components/promo-card/promo-card-styles.ts +0 -39
  40. package/src/WebComponent/FeeCalculator/components/promo-card/promo-card.ts +0 -39
  41. package/src/WebComponent/FeeCalculator/fee-calculator-styles.ts +0 -280
  42. package/src/WebComponent/FeeCalculator/fee-calculator.ts +0 -256
  43. package/src/WebComponent/FeeCalculator/index.ts +0 -4
  44. package/src/WebComponent/FeeCalculator/model/building-fee.ts +0 -83
  45. package/src/WebComponent/FeeCalculator/model/transaction-category.ts +0 -23
  46. package/src/WebComponent/LeadSourceClient.ts +0 -332
  47. package/src/WebComponent/MEChat.css +0 -5
  48. package/src/WebComponent/OfficeHours.ts +0 -73
  49. package/src/WebComponent/Scheduler/date-picker.ts +0 -405
  50. package/src/WebComponent/Scheduler/time-picker.ts +0 -190
  51. package/src/WebComponent/Scheduler/tour-scheduler.ts +0 -1352
  52. package/src/WebComponent/Scheduler/tour-type-option.ts +0 -112
  53. package/src/WebComponent/Scheduler/tourSchedulerStyles.ts +0 -418
  54. package/src/WebComponent/actions/InputStyles.ts +0 -57
  55. package/src/WebComponent/actions/action-confirm-button.ts +0 -125
  56. package/src/WebComponent/actions/call-us-window.ts +0 -445
  57. package/src/WebComponent/actions/collapse-expand-button.ts +0 -65
  58. package/src/WebComponent/actions/details-window.ts +0 -150
  59. package/src/WebComponent/actions/email-us-window.ts +0 -555
  60. package/src/WebComponent/actions/formatPhoneNumber.ts +0 -72
  61. package/src/WebComponent/actions/minimize-expand-button.ts +0 -93
  62. package/src/WebComponent/chat-additional-actions.ts +0 -135
  63. package/src/WebComponent/health-chat.ts +0 -270
  64. package/src/WebComponent/healthchat-styles.ts +0 -119
  65. package/src/WebComponent/icons/ApplyOutlineIcon.ts +0 -22
  66. package/src/WebComponent/icons/BookTourOutlineIcon.ts +0 -13
  67. package/src/WebComponent/icons/CalculatorOutlineIcon.ts +0 -22
  68. package/src/WebComponent/icons/ChatOutlineIcon.ts +0 -10
  69. package/src/WebComponent/icons/ChevronLeftIcon.ts +0 -7
  70. package/src/WebComponent/icons/ChevronRightIcon.ts +0 -7
  71. package/src/WebComponent/icons/ContactResidentIcon.ts +0 -9
  72. package/src/WebComponent/icons/DollarOutlineIcon.ts +0 -18
  73. package/src/WebComponent/icons/EmailOutlineIcon.ts +0 -7
  74. package/src/WebComponent/icons/HeyThereEmojiIcon.ts +0 -12
  75. package/src/WebComponent/icons/PhoneOutlineIcon.ts +0 -7
  76. package/src/WebComponent/icons/SendMessageIcon.ts +0 -17
  77. package/src/WebComponent/icons/TourSelfGuidedIcon.ts +0 -17
  78. package/src/WebComponent/icons/TourVirtuallyIcon.ts +0 -17
  79. package/src/WebComponent/icons/TourWithAgentIcon.ts +0 -17
  80. package/src/WebComponent/icons/XOutlineIcon.ts +0 -8
  81. package/src/WebComponent/index.ts +0 -2
  82. package/src/WebComponent/launcher/Launcher.ts +0 -1193
  83. package/src/WebComponent/launcher/launcherStyles.ts +0 -500
  84. package/src/WebComponent/launcher/mobile-launcher.ts +0 -159
  85. package/src/WebComponent/launcher/typeEmojiStyles.ts +0 -161
  86. package/src/WebComponent/launcher/typeMiniStyles.ts +0 -60
  87. package/src/WebComponent/launcher/typeMobileStyles.ts +0 -50
  88. package/src/WebComponent/leasing-chat-styles.ts +0 -114
  89. package/src/WebComponent/me-chat.ts +0 -1257
  90. package/src/WebComponent/me-select.ts +0 -322
  91. package/src/WebComponent/mini-loader.ts +0 -28
  92. package/src/WebComponent/pubnub-chat-styles.ts +0 -204
  93. package/src/WebComponent/pubnub-chat.ts +0 -928
  94. package/src/WebComponent/pubnub-media.ts +0 -208
  95. package/src/WebComponent/pubnub-message-styles.ts +0 -54
  96. package/src/WebComponent/pubnub-message.ts +0 -431
  97. package/src/WebComponent/simple-launcher/simple-launcher-styles.ts +0 -34
  98. package/src/WebComponent/simple-launcher/simple-launcher.ts +0 -100
  99. package/src/WebComponent/utilities-chat.ts +0 -270
  100. package/src/WebComponent/utilities-styles.ts +0 -110
  101. package/src/WebComponent/utils.ts +0 -82
  102. package/src/analytics.ts +0 -217
  103. package/src/assetUrls.ts +0 -6
  104. package/src/disclaimers.ts +0 -58
  105. package/src/fetchBuildingABTestType.ts +0 -21
  106. package/src/fetchBuildingInfo.ts +0 -87
  107. package/src/fetchBuildingWebchatView.ts +0 -154
  108. package/src/fetchFeatureFlag.ts +0 -250
  109. package/src/fetchLeadSources.ts +0 -98
  110. package/src/fetchPhoneNumberFromSource.ts +0 -31
  111. package/src/fetchWebchatPreferences.ts +0 -54
  112. package/src/getAvailabilities.ts +0 -174
  113. package/src/getBuildingPhoneNumber.ts +0 -26
  114. package/src/getShouldAllowScheduling.ts +0 -16
  115. package/src/getShouldShowWebchat.ts +0 -114
  116. package/src/getTimezoneString.ts +0 -39
  117. package/src/globals.ts +0 -1
  118. package/src/gtm.ts +0 -17
  119. package/src/handleChatId.ts +0 -101
  120. package/src/insertDNIIntoWebsite.ts +0 -146
  121. package/src/insertLeadSourceIntoSchedulerLinks.ts +0 -71
  122. package/src/main/MEChat.test.ts +0 -110
  123. package/src/main/MEChat.ts +0 -404
  124. package/src/main/utils.ts +0 -70
  125. package/src/postLeadSources.ts +0 -44
  126. package/src/rentgrata.ts +0 -74
  127. package/src/replaceSelectButtonsWithNewLink.ts +0 -68
  128. package/src/services/fees/fetchBuildingFees.ts +0 -28
  129. package/src/svgIcons.ts +0 -14
  130. package/src/themes.ts +0 -65
  131. package/src/types/rest-sdk.types.ts +0 -13
  132. package/src/types/webchat-no-show-reason.ts +0 -6
  133. package/src/utils.ts +0 -121
  134. package/tsconfig.json +0 -84
  135. package/web-test-runner.config.js +0 -10
  136. package/webpack.config.cjs +0 -48
@@ -1,928 +0,0 @@
1
- import { html, LitElement, TemplateResult } from "lit";
2
- import { customElement, property, query, state } from "lit/decorators.js";
3
- import { classMap } from "lit/directives/class-map.js";
4
- import { styleMap } from "lit/directives/style-map.js";
5
- import { Building } from "../fetchBuildingInfo";
6
- import MyPubnub, {
7
- SimpleMessageTypes,
8
- SimpleChatMessage,
9
- isSimpleMediaChatMessage,
10
- isSimpleTextChatMessage,
11
- } from "../MyPubnub";
12
- import { CheckboxEmpty } from "../svgIcons";
13
- import {
14
- defaultPrimaryColor,
15
- hexToAlmostWhite,
16
- defaultBackgroundColor,
17
- shouldUsePrimaryColorForChatFooter,
18
- } from "../themes";
19
- import { isMobile } from "../utils";
20
- import { InputStyles } from "./actions/InputStyles";
21
- import { healthChatStyles } from "./healthchat-styles";
22
- import { leasingChatStyles } from "./leasing-chat-styles";
23
- import { pubnubChatStyles } from "./pubnub-chat-styles";
24
- import "./pubnub-message";
25
- import "./pubnub-media";
26
- import classNames from "classnames";
27
- import { differenceInDays } from "date-fns";
28
- import { WidgetType } from "../main/MEChat";
29
- import { utiltiesChatStyles } from "./utilities-styles";
30
- import { XOutlineIcon } from "./icons/XOutlineIcon";
31
- import { HeyThereEmoji } from "./icons/HeyThereEmojiIcon";
32
- import {
33
- SendMessageLargeIcon,
34
- SendMessageMediumIcon,
35
- } from "./icons/SendMessageIcon";
36
-
37
- @customElement("pubnub-chat")
38
- export class PubnubChat extends LitElement {
39
- static styles = [
40
- InputStyles,
41
- pubnubChatStyles,
42
- leasingChatStyles,
43
- healthChatStyles,
44
- utiltiesChatStyles,
45
- ];
46
-
47
- @property({ type: Number })
48
- private right = undefined;
49
-
50
- @property({ type: Number })
51
- private bottom = undefined;
52
-
53
- @property({ type: Number })
54
- private top = undefined;
55
-
56
- @property({ type: Number })
57
- private left = undefined;
58
-
59
- @property({ attribute: true })
60
- onMount: () => void = () => ({});
61
-
62
- @property({ attribute: true })
63
- channel: string | undefined;
64
-
65
- @property({ attribute: true })
66
- isHealthChat = false;
67
-
68
- @property({ attribute: true })
69
- myPubnub: MyPubnub | undefined;
70
-
71
- @property({ attribute: true })
72
- orgSlug: string | undefined;
73
-
74
- @property({ attribute: true })
75
- buildingSlug: string | undefined;
76
-
77
- @property({ attribute: true })
78
- widgetType: WidgetType = WidgetType.Default;
79
-
80
- @property({ attribute: true })
81
- building: Building | undefined;
82
-
83
- @property({ attribute: true })
84
- primaryColor: string = defaultPrimaryColor;
85
-
86
- @property({ attribute: true })
87
- backgroundColor: string = defaultBackgroundColor;
88
-
89
- @property({ attribute: true })
90
- onClickExit: () => void = () => {
91
- localStorage.setItem("isChatOpen", "false");
92
- };
93
-
94
- @property({ attribute: true })
95
- requiresConsent = false;
96
-
97
- @query("#message-input", true)
98
- messageInput!: HTMLTextAreaElement;
99
-
100
- @query("#conversation-body", true)
101
- messageBody!: HTMLDivElement;
102
-
103
- @state()
104
- messages: SimpleChatMessage[] = [];
105
-
106
- @state()
107
- isLoadingMessages = false;
108
-
109
- @state()
110
- hasReceivedConsent = false;
111
-
112
- @state()
113
- privacyPolicyUrl = "http://bit.ly/me_privacy_policy";
114
-
115
- @state()
116
- websitePreviewMapping: {
117
- [messageId: string]: {
118
- title: string | null;
119
- description: string | null;
120
- image: string | null;
121
- favicon: string | null;
122
- isLoading: boolean;
123
- }[];
124
- } = {};
125
-
126
- get consentKey(): string {
127
- return `${this.orgSlug}Consent`;
128
- }
129
-
130
- sendMessage = async (message: string): Promise<void> => {
131
- if (message.length === 0) {
132
- return;
133
- }
134
- this.messageInput.value = "";
135
- this.autoResizeMessageInput();
136
-
137
- // The first message triggers a channel creation which can take a few seconds,
138
- // so we immediately add the message to the UI to avoid a delay.
139
- if (this.messages.length === 0) {
140
- this.messages = [
141
- {
142
- timestamp: 0,
143
- message,
144
- isLeadMessage: true,
145
- chunks: [{ text: message, order: 0, isDone: true }],
146
- type: SimpleMessageTypes.text,
147
- },
148
- ];
149
- }
150
- await this.myPubnub?.sendMessage(message);
151
- };
152
-
153
- firstUpdated(): void {
154
- this.messages = this.myPubnub?.simpleChatMessages || [];
155
- this.myPubnub?.addChatListener(
156
- (response: { messages: SimpleChatMessage[]; isLoading: boolean }) => {
157
- this.messages = response.messages;
158
- this.isLoadingMessages = response.isLoading;
159
- }
160
- );
161
- this.onMount();
162
-
163
- const rawConsentData = localStorage.getItem(this.consentKey);
164
- if (!rawConsentData) {
165
- this.hasReceivedConsent = false;
166
- return;
167
- }
168
- const parsedConsentData = JSON.parse(rawConsentData);
169
- const { timestamp, consentId } = parsedConsentData;
170
- const ageInDays = differenceInDays(new Date(), new Date(timestamp));
171
- const isConsentValid = ageInDays < 7;
172
- const isConsentIdCurrent = consentId === CURRENT_CONSENT_ID;
173
- if (isConsentValid && isConsentIdCurrent) {
174
- this.hasReceivedConsent = true;
175
- } else {
176
- this.hasReceivedConsent = false;
177
- localStorage.removeItem(this.consentKey);
178
- }
179
- }
180
-
181
- scrollToChatBottom = (): void => {
182
- this.messageBody.scrollTo({
183
- top: this.messageBody.scrollHeight - this.messageBody.clientHeight,
184
- behavior: "smooth",
185
- });
186
- };
187
-
188
- async updated(): Promise<void> {
189
- this.scrollToChatBottom();
190
- try {
191
- const modal = document.getElementById("#healthchat-container");
192
- if (!modal) return;
193
- modal.focus();
194
- } catch (e) {
195
- // eslint-disable-next-line no-console
196
- console.error(e);
197
- }
198
- }
199
-
200
- autoResizeMessageInput = (): void => {
201
- this.messageInput.style.height = "auto";
202
- this.messageInput.style.height = this.messageInput.scrollHeight + "px";
203
- };
204
-
205
- needsConsent = (): boolean => {
206
- return this.requiresConsent && !this.hasReceivedConsent;
207
- };
208
-
209
- render(): TemplateResult {
210
- if (!this.buildingSlug) {
211
- return html``; // error should be here
212
- }
213
-
214
- const buildingId = this.building?.id;
215
- let styles = {};
216
- if (isMobile()) {
217
- styles = {
218
- top: undefined,
219
- bottom: 0,
220
- left: undefined,
221
- right: 0,
222
- };
223
- } else {
224
- styles = {
225
- top:
226
- this.top !== undefined && !isNaN(this.top)
227
- ? `${this.top}px`
228
- : undefined,
229
- bottom:
230
- this.bottom !== undefined && !isNaN(this.bottom)
231
- ? `${this.bottom}px`
232
- : "130px",
233
- left:
234
- this.left !== undefined && !isNaN(this.left)
235
- ? `${this.left}px`
236
- : undefined,
237
- right:
238
- this.right !== undefined && !isNaN(this.right)
239
- ? `${this.right}px`
240
- : "18px",
241
- };
242
- }
243
- /**
244
- * This chat window uses 'Poppins' as its font, but https://www.120ninthst.com/ seemingly installs a 'Poppins' font that is
245
- * not the same as the Google Font 'Poppins'. This causes the chat window to look different from the rest of the website. This
246
- * is a special case/hack to just change to a system default font for this building.
247
- */
248
- if (buildingId === 22320) {
249
- styles = {
250
- ...styles,
251
- fontFamily: `"Helvetica Neue", Arial`,
252
- };
253
- }
254
-
255
- if (this.widgetType === WidgetType.Utilities) {
256
- return html`
257
- <div
258
- id="utilities-container"
259
- class=${classMap({
260
- ["pubnub-container__mobile"]: isMobile(),
261
- ["utilities-container__desktop"]: !isMobile(),
262
- })}
263
- style=${styleMap(styles)}
264
- >
265
- <div id="utilities-header">
266
- <div>
267
- <div id="header-text">Utilities Chat</div>
268
- </div>
269
- <button
270
- id="exit-chat-bttn"
271
- @click=${this.onClickExit}
272
- aria-label="Close chat"
273
- >
274
- ${XOutlineIcon("black")}
275
- </button>
276
- </div>
277
- <div
278
- class=${classMap({
279
- ["hidden"]: !this.needsConsent(),
280
- ["legal-confirmation-container"]: true,
281
- })}
282
- >
283
- ${getConsentPreChatDisclaimer(
284
- this.orgSlug ?? null,
285
- this.privacyPolicyUrl,
286
- this.consentKey,
287
- (hasConsent: boolean) => {
288
- this.hasReceivedConsent = hasConsent;
289
- }
290
- )}
291
- </div>
292
- <div
293
- id="conversation-body"
294
- class=${classMap({
295
- ["hidden"]: this.needsConsent(),
296
- ["utilities-conversation-body-backdrop"]: true,
297
- })}
298
- >
299
- <ul
300
- id="message-thread-list"
301
- class=${classMap({
302
- ["hidden"]: this.needsConsent(),
303
- })}
304
- >
305
- <li class="utilities-disclaimer-message">
306
- <p class="utilities-disclaimer-inner">
307
- This conversation may be monitored and recorded. By replying,
308
- you consent to
309
- <a
310
- href="https://www.eliseai.com/privacyrights"
311
- target="_blank"
312
- rel="noopener noreferrer"
313
- >
314
- this privacy policy</a
315
- >
316
- and to being contacted by a bot.
317
- </p>
318
- </li>
319
- <li class="message-container ai-message">
320
- <p
321
- class=${classMap({
322
- ["message-text-large"]: true,
323
- ["webchat-font__desktop"]: !isMobile(),
324
- ["webchat-font__mobile"]: isMobile(),
325
- })}
326
- >
327
- Hi I'm Elise. How can I assist you today?
328
- </p>
329
- </li>
330
- ${this.messages.map((message) => {
331
- return html`
332
- <li
333
- class=${message.isLeadMessage
334
- ? "message-container lead-message"
335
- : "message-container ai-message"}
336
- key=${message.timestamp}
337
- >
338
- ${isSimpleMediaChatMessage(message)
339
- ? html` <pubnub-media
340
- .message=${message}
341
- .myPubnub=${this.myPubnub}
342
- .onMount=${() => this.scrollToChatBottom()}
343
- >
344
- </pubnub-media>`
345
- : ""}
346
- ${isSimpleTextChatMessage(message)
347
- ? html` <pubnub-message
348
- .message=${message}
349
- .myPubnub=${this.myPubnub}
350
- .onMount=${() => this.scrollToChatBottom()}
351
- .isLeadMessage=${message.isLeadMessage}
352
- .buildingSlug=${this.buildingSlug}
353
- .widgetType=${this.widgetType}
354
- >
355
- </pubnub-message>`
356
- : ""}
357
- </li>
358
- `;
359
- })}
360
- ${this.isLoadingMessages
361
- ? html`
362
- <li
363
- id="loading-message"
364
- class="message-container ai-message"
365
- >
366
- <div class="loading-dot dot-1"></div>
367
- <div class="loading-dot dot-2"></div>
368
- <div class="loading-dot dot-3"></div>
369
- </li>
370
- `
371
- : ""}
372
- </ul>
373
- </div>
374
-
375
- <div
376
- id="utilities-footer"
377
- class=${classMap({
378
- ["hidden"]: this.needsConsent(),
379
- })}
380
- >
381
- <div id="utilities-inner-footer">
382
- <textarea
383
- id="message-input"
384
- class=${classMap({
385
- ["webchat-font__desktop"]: !isMobile(),
386
- ["webchat-font__mobile"]: isMobile(),
387
- })}
388
- placeholder="Ask a Question..."
389
- @keydown=${(e: KeyboardEvent) => {
390
- if (e.key === "Enter") {
391
- e.preventDefault();
392
- this.sendMessage(this.messageInput.value);
393
- }
394
- }}
395
- @input=${() => this.autoResizeMessageInput()}
396
- rows="1"
397
- tabindex="0"
398
- ></textarea>
399
- <button
400
- id="utilities-send-message-bttn"
401
- class=${classMap({
402
- ["health-bttn-allow-access"]: isMobile(),
403
- })}
404
- @click=${() => this.sendMessage(this.messageInput.value)}
405
- >
406
- ${SendMessageLargeIcon("black")}
407
- </button>
408
- </div>
409
- </div>
410
- </div>
411
- `;
412
- }
413
-
414
- if (this.widgetType === WidgetType.Healthcare) {
415
- return html`
416
- <div
417
- id="healthchat-container"
418
- class=${classMap({
419
- ["pubnub-container__mobile"]: isMobile(),
420
- ["healthchat-container__desktop"]: !isMobile(),
421
- })}
422
- style=${styleMap(styles)}
423
- >
424
- <div id="healthchat-header">
425
- ${this.buildingSlug === "6a9e65e5-9699-4c96-af75-1741d0df79aa"
426
- ? html` <div>
427
- <div id="header-text">Premier Dematology</div>
428
- <div id="healthchat-header-subtext">
429
- Recorded by Forefront Dermatology and our vendors.
430
- </div>
431
- </div>`
432
- : html``}
433
-
434
- <button
435
- id="exit-chat-bttn"
436
- @click=${this.onClickExit}
437
- aria-label="Close chat"
438
- >
439
- ${XOutlineIcon("black")}
440
- </button>
441
- </div>
442
- <div
443
- class=${classMap({
444
- ["hidden"]: !this.needsConsent(),
445
- ["legal-confirmation-container"]: true,
446
- })}
447
- >
448
- ${getConsentPreChatDisclaimer(
449
- this.orgSlug ?? null,
450
- this.privacyPolicyUrl,
451
- this.consentKey,
452
- (hasConsent: boolean) => {
453
- this.hasReceivedConsent = hasConsent;
454
- }
455
- )}
456
- </div>
457
- <div
458
- id="conversation-body"
459
- class=${classMap({
460
- ["hidden"]: this.needsConsent(),
461
- ["healthcare-conversation-body-backdrop"]: true,
462
- })}
463
- >
464
- <ul
465
- id="message-thread-list"
466
- class=${classMap({
467
- ["hidden"]: this.needsConsent(),
468
- })}
469
- >
470
- <li class="healthcare-disclaimer-message">
471
- <p class="healthcare-disclaimer-inner">
472
- By interacting with this system, you consent to
473
- <a
474
- href="http://bit.ly/me_privacy_policy"
475
- target="_blank"
476
- rel="noopener noreferrer"
477
- >
478
- this privacy policy</a
479
- >
480
- , including being contacted by AI or a human & having your
481
- conversation recorded and used by a third party.
482
- </p>
483
- </li>
484
- <li class="message-container ai-message">
485
- <p
486
- class=${classMap({
487
- ["message-text"]: true,
488
- ["webchat-font__desktop"]: !isMobile(),
489
- ["webchat-font__mobile"]: isMobile(),
490
- })}
491
- >
492
- Hi I'm Elise. If this is a medical emergency, please call 911.
493
- How can I assist you today?
494
- </p>
495
- </li>
496
- ${this.messages.map((message) => {
497
- return html`
498
- <li
499
- class=${message.isLeadMessage
500
- ? "message-container lead-message"
501
- : "message-container ai-message"}
502
- key=${message.timestamp}
503
- >
504
- ${isSimpleMediaChatMessage(message)
505
- ? html` <pubnub-media
506
- .message=${message}
507
- .myPubnub=${this.myPubnub}
508
- .onMount=${() => this.scrollToChatBottom()}
509
- >
510
- </pubnub-media>`
511
- : ""}
512
- ${isSimpleTextChatMessage(message)
513
- ? html` <pubnub-message
514
- .message=${message}
515
- .myPubnub=${this.myPubnub}
516
- .onMount=${() => this.scrollToChatBottom()}
517
- .isLeadMessage=${message.isLeadMessage}
518
- .buildingSlug=${this.buildingSlug}
519
- .widgetType=${this.widgetType}
520
- >
521
- </pubnub-message>`
522
- : ""}
523
- </li>
524
- `;
525
- })}
526
- ${this.isLoadingMessages
527
- ? html`
528
- <li
529
- id="loading-message"
530
- class="message-container ai-message"
531
- >
532
- <div class="loading-dot dot-1"></div>
533
- <div class="loading-dot dot-2"></div>
534
- <div class="loading-dot dot-3"></div>
535
- </li>
536
- `
537
- : ""}
538
- </ul>
539
- </div>
540
-
541
- <div
542
- id="healthcare-footer"
543
- class=${classMap({
544
- ["hidden"]: this.needsConsent(),
545
- })}
546
- >
547
- <div id="healthcare-inner-footer">
548
- <textarea
549
- id="message-input"
550
- class=${classMap({
551
- ["webchat-font__desktop"]: !isMobile(),
552
- ["webchat-font__mobile"]: isMobile(),
553
- })}
554
- placeholder="Ask a Question..."
555
- @keydown=${(e: KeyboardEvent) => {
556
- if (e.key === "Enter") {
557
- e.preventDefault();
558
- this.sendMessage(this.messageInput.value);
559
- }
560
- }}
561
- @input=${() => this.autoResizeMessageInput()}
562
- rows="1"
563
- tabindex="0"
564
- ></textarea>
565
- <button
566
- id="healthcare-send-message-bttn"
567
- class=${classMap({
568
- ["health-bttn-allow-access"]: isMobile(),
569
- })}
570
- @click=${() => this.sendMessage(this.messageInput.value)}
571
- >
572
- ${isMobile()
573
- ? SendMessageLargeIcon("black")
574
- : SendMessageMediumIcon("black")}
575
- </button>
576
- </div>
577
- </div>
578
- </div>
579
- `;
580
- }
581
-
582
- if (!this.building) {
583
- return html``;
584
- }
585
-
586
- const orgId = this.building.orgId;
587
- return html`
588
- <div
589
- id="pubnub-chat-container"
590
- class=${classMap({
591
- ["pubnub-container__mobile"]: isMobile(),
592
- ["pubnub-container__desktop"]: !isMobile(),
593
- })}
594
- style=${styleMap(styles)}
595
- @keydown=${(e: KeyboardEvent) => e.stopPropagation()}
596
- @keyup=${(e: KeyboardEvent) => e.stopPropagation()}
597
- >
598
- <div
599
- id="leasing-header"
600
- style=${styleMap({
601
- background:
602
- this.primaryColor !== defaultPrimaryColor
603
- ? hexToAlmostWhite(this.primaryColor, 0.6)
604
- : undefined,
605
- })}
606
- >
607
- <div id="header-text">${this.building.name}</div>
608
- <button
609
- id="exit-chat-bttn"
610
- @click=${this.onClickExit}
611
- aria-label="Close chat"
612
- >
613
- ${XOutlineIcon("black")}
614
- </button>
615
- </div>
616
- <div
617
- class=${classMap({
618
- ["hidden"]: !this.needsConsent(),
619
- ["legal-confirmation-container"]: true,
620
- })}
621
- >
622
- ${getConsentPreChatDisclaimer(
623
- this.orgSlug ?? null,
624
- this.privacyPolicyUrl,
625
- this.consentKey,
626
- (hasConsent: boolean) => {
627
- this.hasReceivedConsent = hasConsent;
628
- }
629
- )}
630
- </div>
631
- <div
632
- id="conversation-body"
633
- style=${styleMap({
634
- background:
635
- this.building.orgId === 444
636
- ? "rgba(229, 229, 229, 1);"
637
- : undefined,
638
- })}
639
- class=${classMap({
640
- ["hidden"]: this.needsConsent(),
641
- ["leasing-conversation-body-backdrop"]: true,
642
- })}
643
- >
644
- <ul
645
- id="message-thread-list"
646
- class=${classMap({
647
- ["hidden"]: this.needsConsent(),
648
- })}
649
- >
650
- ${getChatDisclaimer(this.orgSlug ?? "")}
651
- ${this.building.welcomeMessage
652
- ? html` <li
653
- class=${classMap({
654
- "message-container": true,
655
- "ai-message": true,
656
- "with-box-shadow": orgId === 444,
657
- })}
658
- >
659
- <p
660
- class=${classMap({
661
- ["message-text"]: true,
662
- ["webchat-font__desktop"]: !isMobile(),
663
- ["webchat-font__mobile"]: isMobile(),
664
- })}
665
- >
666
- ${this.building.welcomeMessage
667
- .split("\n")
668
- .map((line) => html`${line}<br />`)}
669
- </p>
670
- </li>`
671
- : ""}
672
- ${this.messages.map((message) => {
673
- return html`
674
- <li
675
- class=${classNames("message-container", {
676
- "lead-message": message.isLeadMessage,
677
- "ai-message": !message.isLeadMessage,
678
- "with-box-shadow": orgId === 444,
679
- })}
680
- key=${message.timestamp}
681
- >
682
- ${isSimpleMediaChatMessage(message)
683
- ? html` <pubnub-media
684
- .message=${message}
685
- .myPubnub=${this.myPubnub}
686
- .onMount=${() => this.scrollToChatBottom()}
687
- >
688
- </pubnub-media>`
689
- : ""}
690
- ${isSimpleTextChatMessage(message)
691
- ? html` <pubnub-message
692
- .message=${message}
693
- .myPubnub=${this.myPubnub}
694
- .onMount=${() => this.scrollToChatBottom()}
695
- .isLeadMessage=${message.isLeadMessage}
696
- .buildingSlug=${this.buildingSlug}
697
- .widgetType=${this.widgetType}
698
- >
699
- </pubnub-message>`
700
- : ""}
701
- </li>
702
- `;
703
- })}
704
- ${this.isLoadingMessages
705
- ? html`
706
- <li id="loading-message" class="message-container ai-message">
707
- <div class="loading-dot dot-1"></div>
708
- <div class="loading-dot dot-2"></div>
709
- <div class="loading-dot dot-3"></div>
710
- </li>
711
- `
712
- : ""}
713
- </ul>
714
- </div>
715
- <div
716
- id="footer"
717
- class=${classMap({
718
- ["hidden"]: this.needsConsent(),
719
- })}
720
- style=${styleMap({
721
- background:
722
- shouldUsePrimaryColorForChatFooter(
723
- this.building.orgId,
724
- this.building.id
725
- ) && this.primaryColor !== defaultPrimaryColor
726
- ? hexToAlmostWhite(this.primaryColor, 0.6)
727
- : undefined,
728
- })}
729
- >
730
- <textarea
731
- id="message-input"
732
- class=${classMap({
733
- ["webchat-font__desktop"]: !isMobile(),
734
- ["webchat-font__mobile"]: isMobile(),
735
- })}
736
- style=${styleMap({
737
- color:
738
- shouldUsePrimaryColorForChatFooter(
739
- this.building.orgId,
740
- this.building.id
741
- ) && this.primaryColor !== defaultPrimaryColor
742
- ? "black"
743
- : undefined,
744
- })}
745
- placeholder="Ask a question..."
746
- @keydown=${(e: KeyboardEvent) => {
747
- if (
748
- e.key === "Enter" &&
749
- !this.myPubnub?.isCurrentlyStreamingMessage
750
- ) {
751
- e.preventDefault();
752
- this.sendMessage(this.messageInput.value);
753
- }
754
- }}
755
- @input=${() => this.autoResizeMessageInput()}
756
- rows="1"
757
- tabindex="0"
758
- ></textarea>
759
- <button
760
- tabindex="0"
761
- id="send-message-bttn"
762
- @click=${() => this.sendMessage(this.messageInput.value)}
763
- ?disabled=${this.myPubnub?.isCurrentlyStreamingMessage}
764
- aria-label="Send message"
765
- aria-describedby="Send message"
766
- >
767
- ${shouldUsePrimaryColorForChatFooter(
768
- this.building.orgId,
769
- this.building.id
770
- ) && this.primaryColor !== defaultPrimaryColor
771
- ? SendMessageMediumIcon("black")
772
- : SendMessageMediumIcon("white")}
773
- </button>
774
- </div>
775
- </div>
776
- `;
777
- }
778
- }
779
-
780
- export const CURRENT_CONSENT_ID = "currentConsentId";
781
-
782
- const getChatDisclaimer = (orgSlug: string) => {
783
- if (orgSlug === "avb") {
784
- return html`
785
- <li class="message-container disclaimer-message">
786
- <p class="disclaimer-inner">
787
- Chats may be recorded by us and our vendors.
788
- </p>
789
- </li>
790
- `;
791
- }
792
- return html`<li class="message-container disclaimer-message">
793
- <p class="disclaimer-inner">
794
- By interacting with this system, you consent to
795
- <a
796
- href="http://bit.ly/me_privacy_policy"
797
- target="_blank"
798
- rel="noopener noreferrer"
799
- >
800
- this privacy policy</a
801
- >, including being contacted by AI or a human & having your conversation
802
- recorded and used by a third party.
803
- </p>
804
- </li>`;
805
- };
806
-
807
- const getConsentPreChatDisclaimer = (
808
- orgSlug: string | null,
809
- privacyPolicyUrl: string,
810
- consentKey: string,
811
- changeConsent: (hasConsent: boolean) => void
812
- ): TemplateResult => {
813
- if (orgSlug === "avb" && !localStorage.getItem(consentKey ?? "")) {
814
- return html`
815
- <div class="legal-confirmation-inner-container">
816
- <div>${HeyThereEmoji()}</div>
817
- <div>
818
- <span style="font-weight: 600">Confirm to continue</span>
819
- <p>
820
- By using this feature you accept our
821
- <a
822
- href="https://www.avaloncommunities.com/terms-of-use"
823
- target="_blank"
824
- rel="noopener noreferrer"
825
- class="privacy-policy-link"
826
- >Terms</a
827
- >,
828
- <a
829
- href="https://www.avaloncommunities.com/privacy-policy"
830
- target="_blank"
831
- rel="noopener noreferrer"
832
- class="privacy-policy-link"
833
- >Privacy Policy</a
834
- >,
835
- <a
836
- href="https://www.avaloncommunities.com/us-state-privacy-notice"
837
- target="_blank"
838
- rel="noopener noreferrer"
839
- class="privacy-policy-link"
840
- >U.S. State Privacy Notice</a
841
- >, and that chats may use automated or AI responses from a bot and
842
- may be recorded and used by us and our vendors.
843
- </p>
844
- </div>
845
-
846
- <button
847
- class="agreeButton"
848
- @click=${() => {
849
- changeConsent(true);
850
- const consentData = {
851
- consentGiven: true,
852
- timestamp: new Date().getTime(),
853
- consentId: CURRENT_CONSENT_ID,
854
- };
855
- localStorage.setItem(consentKey ?? "", JSON.stringify(consentData));
856
- }}
857
- >
858
- I agree
859
- </button>
860
- </div>
861
- `;
862
- }
863
- if (orgSlug === "mill-creek") {
864
- return html`<div class="legal-confirmation-inner-container">
865
- <div>${HeyThereEmoji()}</div>
866
- <div>
867
- <span style="font-weight: 600">Confirm to continue</span>
868
- <p>
869
- Hello! I'm your virtual assistant, Milly, and I am here to help you
870
- today. Before I can answer any questions, it is important that you
871
- know I am a third-party bot, and I will be collecting our
872
- communications and other information you provide, consistent with our
873
- privacy policy.
874
- </p>
875
- <div class="confirmation-with-checkbox">
876
- <div
877
- class="checkbox"
878
- @click=${() => {
879
- changeConsent(true);
880
- }}
881
- >
882
- ${CheckboxEmpty}
883
- </div>
884
- <p>
885
- I agree to the
886
- <a
887
- href=${privacyPolicyUrl}
888
- target="_blank"
889
- rel="noopener noreferrer"
890
- class="privacy-policy-link"
891
- >
892
- privacy policy</a
893
- >
894
- and terms and conditions, Let's go!
895
- </p>
896
- </div>
897
- </div>
898
- </div>`;
899
- }
900
- return html` <div class="legal-confirmation-inner-container">
901
- <div>${HeyThereEmoji()}</div>
902
- <div>
903
- <span style="font-weight: 600">Confirm to continue</span>
904
- <p>
905
- Hello, before I can answer questions for you, it's important that I let
906
- you know that I am a third-party AI Assistant that will collect our
907
- conversation and other information you provide, consistent with our
908
- <a
909
- href=${privacyPolicyUrl}
910
- target="_blank"
911
- rel="noopener noreferrer"
912
- class="privacy-policy-link"
913
- >
914
- privacy policy</a
915
- >.
916
- </p>
917
- </div>
918
-
919
- <button
920
- class="agreeButton"
921
- @click=${() => {
922
- changeConsent(true);
923
- }}
924
- >
925
- I agree
926
- </button>
927
- </div>`;
928
- };