@meetelise/chat 1.43.41 → 1.44.0
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/dist/src/WebComponent/Scheduler/tour-scheduler.d.ts +4 -0
- package/dist/src/WebComponent/launcher/Launcher.d.ts +2 -0
- package/dist/src/replaceOutdatedApplicationLinks.d.ts +8 -0
- package/package.json +1 -1
- package/public/dist/index.js +185 -176
- package/src/WebComponent/Scheduler/tour-scheduler.ts +38 -0
- package/src/WebComponent/launcher/Launcher.ts +5 -1
- package/src/WebComponent/me-chat.ts +13 -1
- package/src/replaceOutdatedApplicationLinks.ts +57 -0
|
@@ -29,6 +29,7 @@ import { DatePicker } from "./date-picker";
|
|
|
29
29
|
import { MESelect } from "../me-select";
|
|
30
30
|
import { TimePicker } from "./time-picker";
|
|
31
31
|
import { LabeledOption } from "../../fetchBuildingInfo";
|
|
32
|
+
import { LayoutOption } from "../../fetchBuildingWebchatView";
|
|
32
33
|
import {
|
|
33
34
|
isMobile,
|
|
34
35
|
isValidEmail,
|
|
@@ -79,6 +80,8 @@ export class TourScheduler extends LitElement {
|
|
|
79
80
|
|
|
80
81
|
@property({ attribute: false })
|
|
81
82
|
tourTypeOptions: LabeledOption[] = [];
|
|
83
|
+
@property({ attribute: false })
|
|
84
|
+
layoutOptions: LayoutOption[] = [];
|
|
82
85
|
@property({ attribute: true })
|
|
83
86
|
chatId = "";
|
|
84
87
|
@property({ type: Number })
|
|
@@ -191,6 +194,8 @@ export class TourScheduler extends LitElement {
|
|
|
191
194
|
phoneInput!: HTMLInputElement;
|
|
192
195
|
@query("me-select#leadSource")
|
|
193
196
|
selectedLeadSource!: MESelect;
|
|
197
|
+
@query("me-select#layout")
|
|
198
|
+
selectedLayoutEl?: MESelect;
|
|
194
199
|
|
|
195
200
|
@state()
|
|
196
201
|
firstNameInputValue = "";
|
|
@@ -198,6 +203,8 @@ export class TourScheduler extends LitElement {
|
|
|
198
203
|
lastNameInputValue = "";
|
|
199
204
|
@state()
|
|
200
205
|
leadSourceInputValue = "";
|
|
206
|
+
@state()
|
|
207
|
+
selectedLayoutValue = "";
|
|
201
208
|
|
|
202
209
|
@state()
|
|
203
210
|
errorGettingAvailabilities = false;
|
|
@@ -643,6 +650,8 @@ export class TourScheduler extends LitElement {
|
|
|
643
650
|
this.lastNameInputValue = this.lastNameInput.value;
|
|
644
651
|
}
|
|
645
652
|
this.leadSourceInputValue = parsedLeadSource;
|
|
653
|
+
const selectedLayout =
|
|
654
|
+
this.selectedLayoutEl?.value || this.selectedLayoutValue || null;
|
|
646
655
|
pushGtmEvent("scheduleTourSubmitted", {
|
|
647
656
|
email: this.email,
|
|
648
657
|
phone: `+1${this.phoneNumber.match(/\d/g)?.join("")}`,
|
|
@@ -652,6 +661,7 @@ export class TourScheduler extends LitElement {
|
|
|
652
661
|
tourTime: `${this.selectedTime.datetime}${this.selectedTime.offset}`,
|
|
653
662
|
originatingSource:
|
|
654
663
|
leadSources.find((i) => i !== "property-website") || null,
|
|
664
|
+
layout: selectedLayout,
|
|
655
665
|
});
|
|
656
666
|
const data = {
|
|
657
667
|
referrer: document.referrer,
|
|
@@ -672,6 +682,7 @@ export class TourScheduler extends LitElement {
|
|
|
672
682
|
],
|
|
673
683
|
query_params: Object.fromEntries(queryParams.entries()),
|
|
674
684
|
conversation_tracking_id: this.leadSourceClient?.chatId,
|
|
685
|
+
layouts: selectedLayout ? [selectedLayout] : undefined,
|
|
675
686
|
lead_sources_with_timestamps: (
|
|
676
687
|
this.leadSourceMultitouchClient?.getSafeLeadSourceTouchpointsWithDefault(
|
|
677
688
|
{
|
|
@@ -1225,6 +1236,27 @@ export class TourScheduler extends LitElement {
|
|
|
1225
1236
|
? html`<p class="error-message">Invalid phone number</p>`
|
|
1226
1237
|
: ""}
|
|
1227
1238
|
</div>
|
|
1239
|
+
${this.layoutOptions.length > 0
|
|
1240
|
+
? html` <me-select
|
|
1241
|
+
id="layout"
|
|
1242
|
+
placeholder="Bedroom preference (optional)"
|
|
1243
|
+
.options="${this.layoutOptions.map((o) => ({
|
|
1244
|
+
label: o.label,
|
|
1245
|
+
value: layoutValueToCanonical(o.value),
|
|
1246
|
+
}))}"
|
|
1247
|
+
@change=${() => {
|
|
1248
|
+
const v = this.selectedLayoutEl?.value || "";
|
|
1249
|
+
this.selectedLayoutValue = v;
|
|
1250
|
+
if (v) {
|
|
1251
|
+
pushGtmEvent("tourLayoutSelected", {
|
|
1252
|
+
layout: v,
|
|
1253
|
+
buildingId: this.buildingId,
|
|
1254
|
+
});
|
|
1255
|
+
}
|
|
1256
|
+
}}
|
|
1257
|
+
>
|
|
1258
|
+
</me-select>`
|
|
1259
|
+
: ""}
|
|
1228
1260
|
${this.leadSources.length > 0 &&
|
|
1229
1261
|
(this.featureFlagShowDropdown === FeatureFlagsShowDropdown.always ||
|
|
1230
1262
|
(this.featureFlagShowDropdown ===
|
|
@@ -1678,3 +1710,9 @@ const tourTypeForSubmission = {
|
|
|
1678
1710
|
[TourType.Self]: "self-guided-tour",
|
|
1679
1711
|
[TourType.Virtual]: "live-virtual-tour",
|
|
1680
1712
|
};
|
|
1713
|
+
|
|
1714
|
+
// LayoutOption.value is bedrooms * 10; EliseAI classifier expects `studio` / `Nbr`.
|
|
1715
|
+
function layoutValueToCanonical(value: number): string {
|
|
1716
|
+
const bedrooms = Math.round(value / 10);
|
|
1717
|
+
return bedrooms === 0 ? "studio" : `${bedrooms}br`;
|
|
1718
|
+
}
|
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
} from "../../themes";
|
|
22
22
|
import "./mobile-launcher";
|
|
23
23
|
import "../actions/collapse-expand-button";
|
|
24
|
-
import { DesignConcepts } from "../../fetchBuildingWebchatView";
|
|
24
|
+
import { DesignConcepts, LayoutOption } from "../../fetchBuildingWebchatView";
|
|
25
25
|
import { isMobile, onMobileChange } from "../../utils";
|
|
26
26
|
import classNames from "classnames";
|
|
27
27
|
import LeadSourceClient from "../LeadSourceClient";
|
|
@@ -141,6 +141,9 @@ export class Launcher extends LitElement {
|
|
|
141
141
|
|
|
142
142
|
@property({ attribute: false })
|
|
143
143
|
tourTypeOptions: LabeledOption[] = [];
|
|
144
|
+
|
|
145
|
+
@property({ attribute: false })
|
|
146
|
+
layoutOptions: LayoutOption[] = [];
|
|
144
147
|
@property({ attribute: true })
|
|
145
148
|
hasDynamicSchedulingEnabled = false;
|
|
146
149
|
|
|
@@ -1299,6 +1302,7 @@ export class Launcher extends LitElement {
|
|
|
1299
1302
|
.hasDynamicSchedulingEnabled=${this.hasDynamicSchedulingEnabled}
|
|
1300
1303
|
.leadSources="${this.leadSources}"
|
|
1301
1304
|
.tourTypeOptions=${this.tourTypeOptions}
|
|
1305
|
+
.layoutOptions=${this.layoutOptions}
|
|
1302
1306
|
.orgLegalName=${this.orgLegalName}
|
|
1303
1307
|
buildingId=${this.buildingId}
|
|
1304
1308
|
featureFlagShowDropdown="${this.featureFlagShowDropdown}"
|
|
@@ -59,6 +59,7 @@ import { updateRentgrataToken } from "../rentgrata";
|
|
|
59
59
|
import { WidgetType } from "../main/MEChat";
|
|
60
60
|
import { logCdnVersion } from "../logCdnVersion";
|
|
61
61
|
import { replaceSelectButtonsWithNewLink } from "../replaceSelectButtonsWithNewLink";
|
|
62
|
+
import { replaceOutdatedApplicationLinks } from "../replaceOutdatedApplicationLinks";
|
|
62
63
|
import {
|
|
63
64
|
overwriteCheckAvail,
|
|
64
65
|
shouldOverwriteCheckAvail,
|
|
@@ -524,7 +525,7 @@ export class MEChat extends LitElement {
|
|
|
524
525
|
this.buildingWebchatView?.isLiveOnApplications
|
|
525
526
|
) {
|
|
526
527
|
const totalReplacements = replaceSelectButtonsWithNewLink(
|
|
527
|
-
`https://applications.eliseai.com/building/${this.buildingSlug}`,
|
|
528
|
+
`https://applications.eliseai.com/building/${this.buildingSlug}/units`,
|
|
528
529
|
this.orgSlug,
|
|
529
530
|
this.buildingSlug
|
|
530
531
|
);
|
|
@@ -543,6 +544,15 @@ export class MEChat extends LitElement {
|
|
|
543
544
|
}
|
|
544
545
|
}
|
|
545
546
|
|
|
547
|
+
if (this.buildingSlug && this.orgSlug) {
|
|
548
|
+
try {
|
|
549
|
+
replaceOutdatedApplicationLinks(this.buildingSlug);
|
|
550
|
+
} catch {
|
|
551
|
+
// eslint-disable-next-line no-console
|
|
552
|
+
console.warn("Error replacing outdated application links");
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
|
|
546
556
|
if (
|
|
547
557
|
this.buildingSlug &&
|
|
548
558
|
!!this.buildingWebchatView?.isLiveOnApplications &&
|
|
@@ -995,6 +1005,8 @@ export class MEChat extends LitElement {
|
|
|
995
1005
|
.orgLegalName=${this.buildingWebchatView?.orgLegalName ?? ""}
|
|
996
1006
|
.tourTypeOptions=${this.buildingWebchatView
|
|
997
1007
|
?.tourTypeOptions ?? []}
|
|
1008
|
+
.layoutOptions=${this.buildingWebchatView?.layoutOptions ??
|
|
1009
|
+
[]}
|
|
998
1010
|
.launcherStyles=${this.launcherStyles}
|
|
999
1011
|
.primaryColor=${this.primaryColor}
|
|
1000
1012
|
.backgroundColor=${this.backgroundColor}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Some property websites embed hard-coded `applications.eliseai.com/building/<slug>/units`
|
|
3
|
+
* links whose slug has since been re-keyed in the backend. When the widget loads for the
|
|
4
|
+
* new slug, find those links on the host page and rewrite the slug to the current one,
|
|
5
|
+
* preserving query strings/hashes.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// Keys: current/correct building slug.
|
|
9
|
+
// Values: outdated slug that may still appear in URLs on the host page.
|
|
10
|
+
export const OUTDATED_APPLICATION_BUILDING_SLUGS: Record<string, string> = {
|
|
11
|
+
"95ae958e-95db-11ed-9862-6f4db5533d3f":
|
|
12
|
+
"8008db60-45b7-11f1-88ac-635f686365da",
|
|
13
|
+
"95ae96b0-95db-11ed-9863-a7aa664fd985":
|
|
14
|
+
"72ed27c4-45b7-11f1-82d9-37b7db547687",
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const APPLICATIONS_HOST = "https://applications.eliseai.com";
|
|
18
|
+
|
|
19
|
+
export const replaceOutdatedApplicationLinks = (
|
|
20
|
+
currentBuildingSlug: string
|
|
21
|
+
): number => {
|
|
22
|
+
const outdatedSlug = OUTDATED_APPLICATION_BUILDING_SLUGS[currentBuildingSlug];
|
|
23
|
+
if (!outdatedSlug) return 0;
|
|
24
|
+
|
|
25
|
+
const outdatedBase = `${APPLICATIONS_HOST}/building/${outdatedSlug}/units`;
|
|
26
|
+
const newBase = `${APPLICATIONS_HOST}/building/${currentBuildingSlug}/units`;
|
|
27
|
+
const pattern = new RegExp(
|
|
28
|
+
`https://applications\\.eliseai\\.com/building/${outdatedSlug}/units`,
|
|
29
|
+
"g"
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
let totalReplacements = 0;
|
|
33
|
+
|
|
34
|
+
const anchors = document.body.getElementsByTagName("a");
|
|
35
|
+
for (let i = 0; i < anchors.length; i++) {
|
|
36
|
+
const a = anchors[i];
|
|
37
|
+
const href = a.getAttribute("href");
|
|
38
|
+
if (!href || !href.includes(outdatedBase)) continue;
|
|
39
|
+
const newHref = href.replace(pattern, newBase);
|
|
40
|
+
if (newHref === href) continue;
|
|
41
|
+
a.setAttribute("href", newHref);
|
|
42
|
+
totalReplacements++;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const onclickElements =
|
|
46
|
+
document.body.querySelectorAll<HTMLElement>("[onclick]");
|
|
47
|
+
onclickElements.forEach((el) => {
|
|
48
|
+
const onclick = el.getAttribute("onclick");
|
|
49
|
+
if (!onclick || !onclick.includes(outdatedBase)) return;
|
|
50
|
+
const newOnclick = onclick.replace(pattern, newBase);
|
|
51
|
+
if (newOnclick === onclick) return;
|
|
52
|
+
el.setAttribute("onclick", newOnclick);
|
|
53
|
+
totalReplacements++;
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
return totalReplacements;
|
|
57
|
+
};
|