@meetelise/chat 1.12.1 → 1.12.4
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 +2 -2
- package/public/demo/index.html +4 -2
- package/public/dist/index.js +545 -279
- package/src/WebComponent/InHouseLauncher.ts +56 -7
- package/src/WebComponent/MEChat.ts +8 -0
- package/src/WebComponent/Scheduler/date-picker.ts +90 -21
- package/src/WebComponent/Scheduler/me-select.ts +8 -13
- package/src/WebComponent/Scheduler/time-picker.ts +105 -58
- package/src/WebComponent/Scheduler/tour-scheduler.ts +728 -179
- package/src/WebComponent/Scheduler/tour-type-option.ts +0 -3
- package/src/WebComponent/actions/ActionConfirmButton.ts +0 -1
- package/src/WebComponent/actions/CallUsWindow.ts +23 -1
- package/src/WebComponent/actions/DetailsWindow.ts +0 -1
- package/src/WebComponent/actions/EmailUsWindow.ts +0 -1
- package/src/WebComponent/actions/InputStyles.ts +0 -1
- package/src/WebComponent/actions/TextUsWindow.ts +0 -1
- package/src/WebComponent/actions/formatPhoneNumber.ts +26 -10
- package/src/WebComponent/inHouseLauncherStyles.ts +1 -2
- package/src/fetchBuildingInfo.ts +7 -0
- package/src/getAvailabilities.ts +10 -0
- package/src/getRegisteredPhoneNumbers.ts +56 -0
|
@@ -18,8 +18,6 @@ export class TourTypeOption extends LitElement {
|
|
|
18
18
|
|
|
19
19
|
static styles = [
|
|
20
20
|
css`
|
|
21
|
-
@import url("https://fonts.googleapis.com/css2?family=Poppins:wght@400;600;700;900&display=swap");
|
|
22
|
-
|
|
23
21
|
.tour-type-option {
|
|
24
22
|
height: 90px;
|
|
25
23
|
width: 200px;
|
|
@@ -40,7 +38,6 @@ export class TourTypeOption extends LitElement {
|
|
|
40
38
|
display: flex;
|
|
41
39
|
align-items: center;
|
|
42
40
|
justify-content: center;
|
|
43
|
-
/* TODO: may need to use grid, or something else, to get the icons/text to align */
|
|
44
41
|
gap: 15px;
|
|
45
42
|
width: 100%;
|
|
46
43
|
position: absolute;
|
|
@@ -5,7 +5,6 @@ import { customElement, property } from "lit/decorators.js";
|
|
|
5
5
|
export class ActionConfirmButton extends LitElement {
|
|
6
6
|
static styles = [
|
|
7
7
|
css`
|
|
8
|
-
@import url("https://fonts.googleapis.com/css2?family=Poppins:wght@400;600;700;900&display=swap");
|
|
9
8
|
.action-confirm-button {
|
|
10
9
|
background: #1e1e1e;
|
|
11
10
|
border: 2px solid #ffffff;
|
|
@@ -20,6 +20,11 @@ export class CallUsWindow extends LitElement {
|
|
|
20
20
|
line-height: 24px;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
+
.call-us-window__call-us-text > a {
|
|
24
|
+
color: unset;
|
|
25
|
+
text-decoration: none;
|
|
26
|
+
}
|
|
27
|
+
|
|
23
28
|
.call-us-window__office-hours-header {
|
|
24
29
|
text-decoration: underline;
|
|
25
30
|
font-size: 12px;
|
|
@@ -65,6 +70,21 @@ export class CallUsWindow extends LitElement {
|
|
|
65
70
|
| { dayOfWeek: string; startTime: string; endTime: string }
|
|
66
71
|
)[] = [];
|
|
67
72
|
|
|
73
|
+
getCallLink = (phoneNumber: string): TemplateResult => {
|
|
74
|
+
const rawNumber = (phoneNumber.match(/\d+/g) || []).join("");
|
|
75
|
+
const rawInternationalNumber =
|
|
76
|
+
rawNumber.length < 11 ? `1${rawNumber}` : rawNumber;
|
|
77
|
+
const formattedInternationalNumber = `+${
|
|
78
|
+
rawInternationalNumber[0]
|
|
79
|
+
}-${rawInternationalNumber.slice(1, 4)}-${rawInternationalNumber.slice(
|
|
80
|
+
4,
|
|
81
|
+
7
|
|
82
|
+
)}-${rawInternationalNumber.slice(7)}`;
|
|
83
|
+
return html`<a href="tel:${formattedInternationalNumber}"
|
|
84
|
+
>${phoneNumber}</a
|
|
85
|
+
>`;
|
|
86
|
+
};
|
|
87
|
+
|
|
68
88
|
render = (): TemplateResult => {
|
|
69
89
|
return html`
|
|
70
90
|
<details-window
|
|
@@ -74,7 +94,9 @@ export class CallUsWindow extends LitElement {
|
|
|
74
94
|
>
|
|
75
95
|
<div class="call-us-window__content-wrapper">
|
|
76
96
|
<div class="call-us-window__call-us-text">
|
|
77
|
-
Contact our leasing team at <br />${this.
|
|
97
|
+
Contact our leasing team at <br />${this.getCallLink(
|
|
98
|
+
this.phoneNumber
|
|
99
|
+
)}
|
|
78
100
|
</div>
|
|
79
101
|
<div class="call-us-window__office-hours-wrapper">
|
|
80
102
|
<div class="call-us-window__office-hours-header">Office hours</div>
|
|
@@ -6,7 +6,6 @@ import { isMobile } from "../../utils";
|
|
|
6
6
|
@customElement("details-window")
|
|
7
7
|
export class DetailsWindow extends LitElement {
|
|
8
8
|
static styles = css`
|
|
9
|
-
@import url("https://fonts.googleapis.com/css2?family=Poppins:wght@400;600;700;900&display=swap");
|
|
10
9
|
.details-window-wrapper {
|
|
11
10
|
background: rgba(255, 255, 255, 0.75);
|
|
12
11
|
box-shadow: 0px 0px 14px 5px rgba(0, 0, 0, 0.25);
|
|
@@ -16,7 +16,6 @@ import axios from "axios";
|
|
|
16
16
|
export class EmailUsWindow extends LitElement {
|
|
17
17
|
static styles = [
|
|
18
18
|
css`
|
|
19
|
-
@import url("https://fonts.googleapis.com/css2?family=Poppins:wght@400;600;700;900&display=swap");
|
|
20
19
|
.email-us__name-input {
|
|
21
20
|
width: 134px;
|
|
22
21
|
height: 49px;
|
|
@@ -16,7 +16,6 @@ import axios from "axios";
|
|
|
16
16
|
export class TextUsWindow extends LitElement {
|
|
17
17
|
static styles = [
|
|
18
18
|
css`
|
|
19
|
-
@import url("https://fonts.googleapis.com/css2?family=Poppins:wght@400;600;700;900&display=swap");
|
|
20
19
|
.text-us-wrapper {
|
|
21
20
|
font-family: "Poppins";
|
|
22
21
|
color: #202020;
|
|
@@ -3,18 +3,18 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export const formatToPhone = (phoneNumber: string): string => {
|
|
5
5
|
const input = phoneNumber.replace(/\D/g, "").substring(0, 10);
|
|
6
|
-
const
|
|
6
|
+
const areaCode = input.substring(0, 3);
|
|
7
7
|
const middle = input.substring(3, 6);
|
|
8
8
|
const last = input.substring(6, 10);
|
|
9
9
|
|
|
10
|
-
if (input.length >
|
|
11
|
-
return `(${
|
|
10
|
+
if (input.length > 5) {
|
|
11
|
+
return `(${areaCode}) ${middle}-${last}`;
|
|
12
12
|
}
|
|
13
|
-
if (input.length >
|
|
14
|
-
return `(${
|
|
13
|
+
if (input.length > 2) {
|
|
14
|
+
return `(${areaCode}) ${middle}`;
|
|
15
15
|
}
|
|
16
16
|
if (input.length > 0) {
|
|
17
|
-
return `(${
|
|
17
|
+
return `(${areaCode}`;
|
|
18
18
|
}
|
|
19
19
|
return "";
|
|
20
20
|
};
|
|
@@ -24,11 +24,22 @@ export const isNumericInput = (event: KeyboardEvent): boolean => {
|
|
|
24
24
|
return (key >= 48 && key <= 57) || (key >= 96 && key <= 105);
|
|
25
25
|
};
|
|
26
26
|
|
|
27
|
+
export const isPrintableCharacter = (event: KeyboardEvent): boolean =>
|
|
28
|
+
event.key.length === 1;
|
|
29
|
+
|
|
30
|
+
/** Returns true if any key is pressed whose only function when typing text would be as part of a keyboard shortcut.
|
|
31
|
+
* For example, `Shift` or `f` would not suffice, because these are used for typing text.
|
|
32
|
+
* But `Command` or `Control` would.
|
|
33
|
+
*/
|
|
34
|
+
export const shortcutKeyIsPressed = (event: KeyboardEvent): boolean =>
|
|
35
|
+
event.altKey || event.ctrlKey || event.metaKey;
|
|
36
|
+
|
|
27
37
|
export const isModifierKey = (event: KeyboardEvent): boolean => {
|
|
28
38
|
const key = event.keyCode;
|
|
29
|
-
//
|
|
39
|
+
// TODO: whitelisting specific keyboard shortcuts is brittle (e.g. this is missing Cmd + R to reload)
|
|
40
|
+
// Allow left, up, right, down, Backspace, Tab, Enter, Delete, Ctrl/Command + A,C,L,V,X,Z, Shift, Home, End
|
|
30
41
|
return (
|
|
31
|
-
event.shiftKey
|
|
42
|
+
event.shiftKey ||
|
|
32
43
|
key === 35 ||
|
|
33
44
|
key === 36 || // Allow
|
|
34
45
|
key === 8 ||
|
|
@@ -36,7 +47,12 @@ export const isModifierKey = (event: KeyboardEvent): boolean => {
|
|
|
36
47
|
key === 13 ||
|
|
37
48
|
key === 46 ||
|
|
38
49
|
(key > 36 && key < 41) ||
|
|
39
|
-
((event.ctrlKey
|
|
40
|
-
(key === 65 ||
|
|
50
|
+
((event.ctrlKey || event.metaKey) &&
|
|
51
|
+
(key === 65 ||
|
|
52
|
+
key === 67 ||
|
|
53
|
+
key === 76 ||
|
|
54
|
+
key === 86 ||
|
|
55
|
+
key === 88 ||
|
|
56
|
+
key === 90))
|
|
41
57
|
);
|
|
42
58
|
};
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { css } from "lit";
|
|
2
2
|
|
|
3
|
-
export const
|
|
4
|
-
@import url("https://fonts.googleapis.com/css2?family=Poppins:wght@400;600;700;900&display=swap");
|
|
3
|
+
export const inHouseLauncherStyles = css`
|
|
5
4
|
:host {
|
|
6
5
|
--glowBarHeight: 11.2px;
|
|
7
6
|
--enterAnimationDuration: 0.5s;
|
package/src/fetchBuildingInfo.ts
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
export interface LabeledOption {
|
|
2
|
+
label: string;
|
|
3
|
+
value: string | number;
|
|
4
|
+
}
|
|
5
|
+
|
|
1
6
|
/**
|
|
2
7
|
* The response from the API.
|
|
3
8
|
*/
|
|
@@ -15,6 +20,8 @@ export interface Building {
|
|
|
15
20
|
conversationMaintenanceMode: boolean;
|
|
16
21
|
orgId: number;
|
|
17
22
|
phoneNumber: string;
|
|
23
|
+
layoutOptions: LabeledOption[];
|
|
24
|
+
tourTypeOptions: LabeledOption[];
|
|
18
25
|
}
|
|
19
26
|
|
|
20
27
|
/**
|
package/src/getAvailabilities.ts
CHANGED
|
@@ -69,3 +69,13 @@ export const getAvailabilitiesGroupedByDay = async (
|
|
|
69
69
|
(startTime) => format(startTime, "yyyy-MM-dd")
|
|
70
70
|
);
|
|
71
71
|
};
|
|
72
|
+
|
|
73
|
+
// TODO: if cache is empty, observe it and wait for it to be filled in.
|
|
74
|
+
// TODO: alternative to this: cache the building id when getRawAvailabilities is called. Then I can call the normal methods.
|
|
75
|
+
export const getAvailabilitiesGroupedByDayCached = async (
|
|
76
|
+
tourType: TourAvailabilityResponseRankOrderedSupportedTourTypesEnum
|
|
77
|
+
): ReturnType<typeof getAvailabilitiesGroupedByDay> =>
|
|
78
|
+
getAvailabilitiesGroupedByDay(
|
|
79
|
+
Object.keys(availabilitiesCache).map(Number)[0],
|
|
80
|
+
tourType
|
|
81
|
+
);
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import axios from "axios";
|
|
2
|
+
|
|
3
|
+
export interface ManagementSmsNumber {
|
|
4
|
+
id: number;
|
|
5
|
+
userId: number;
|
|
6
|
+
timeCreated: string;
|
|
7
|
+
active: number;
|
|
8
|
+
phoneNumber: string;
|
|
9
|
+
phoneNumberType: string;
|
|
10
|
+
description: string;
|
|
11
|
+
api: string;
|
|
12
|
+
buildingIds: number[];
|
|
13
|
+
source: string;
|
|
14
|
+
deleted: number;
|
|
15
|
+
buildingGroupId: number;
|
|
16
|
+
ivrRecordLink: number;
|
|
17
|
+
ivrFlowType: number;
|
|
18
|
+
numberToForwardTo: string | null;
|
|
19
|
+
customTimeout: number;
|
|
20
|
+
customOptionsRecording: string | null;
|
|
21
|
+
customOptionsUrl: string | null;
|
|
22
|
+
voiceMailRecipient: string | null;
|
|
23
|
+
callCenterNumber: string | null;
|
|
24
|
+
initialPauseInSeconds: number;
|
|
25
|
+
voiceUrl: string;
|
|
26
|
+
alternativeBuildingId: string | null;
|
|
27
|
+
timezone: string | null;
|
|
28
|
+
buildingId: number;
|
|
29
|
+
ivrFlowConfiguration: {
|
|
30
|
+
flowName: string;
|
|
31
|
+
callCenterNumber: string;
|
|
32
|
+
leasingOfficeNumber: string;
|
|
33
|
+
marketingSourceCallCenterNumber: string | null;
|
|
34
|
+
globalCallCenterNumber: string | null;
|
|
35
|
+
buildingIntroMp3Url: string | null;
|
|
36
|
+
buildingOptionsMp3Url: string | null;
|
|
37
|
+
textYouShortlyMp3Url: string | null;
|
|
38
|
+
};
|
|
39
|
+
v2Number: boolean;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const registeredPhoneNumbersCache: {
|
|
43
|
+
[buildingId: number]: ManagementSmsNumber[];
|
|
44
|
+
} = {};
|
|
45
|
+
|
|
46
|
+
export const getRegisteredPhoneNumbers = async (
|
|
47
|
+
buildingId: number
|
|
48
|
+
): Promise<ManagementSmsNumber[]> => {
|
|
49
|
+
if (registeredPhoneNumbersCache[buildingId]) {
|
|
50
|
+
return registeredPhoneNumbersCache[buildingId];
|
|
51
|
+
}
|
|
52
|
+
const url = `http://ivr.internal-meetelise.com/sms_management_numbers/webchat/building/${buildingId}/numbers`;
|
|
53
|
+
const result = await axios.get<ManagementSmsNumber[]>(url);
|
|
54
|
+
registeredPhoneNumbersCache[buildingId] = result.data;
|
|
55
|
+
return result.data;
|
|
56
|
+
};
|