@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/src/themes.ts CHANGED
@@ -1,164 +1,54 @@
1
- import { hexToAlmostWhite } from "./utils";
1
+ export const defaultBrandColor = "#636889"; // we have a brand color defined in the BE too, but this is a fallback
2
2
 
3
- const white = "#FFFFFF";
4
- const darkGray = "#202020";
5
- const lightGray = "#83818E";
6
- const lightBlue = "#1990FF";
7
- const offBlack = "#1E1E1E";
3
+ export const tintColor = (
4
+ originalColor: string,
5
+ tintOpacity: number
6
+ ): string => {
7
+ const originalRgb = hexToRgb(originalColor);
8
+ const tintRgb = { r: 0, g: 0, b: 0 };
8
9
 
9
- export const defaultBrandColor = "#636889";
10
-
11
- export const enum ThemeId {
12
- Light = "Light",
13
- Dark = "Dark",
14
- Purple = "Purple",
15
- Blue = "Blue",
16
- Teal = "Teal",
17
- Green = "Green",
18
- Yellow = "Yellow",
19
- Orange = "Orange",
20
- Pink = "Pink",
21
- Glass = "Glass",
22
- }
23
- export type ThemeIdString = `${ThemeId}`;
24
-
25
- export interface Theme {
26
- chatHeader: {
27
- backgroundColor: string;
28
- textColor: string;
10
+ const newRgb = {
11
+ r: originalRgb.r + Math.round((tintRgb.r - originalRgb.r) * tintOpacity),
12
+ g: originalRgb.g + Math.round((tintRgb.g - originalRgb.g) * tintOpacity),
13
+ b: originalRgb.b + Math.round((tintRgb.b - originalRgb.b) * tintOpacity),
29
14
  };
30
- chatPaneBackgroundColor: string;
31
- message: {
32
- user: {
33
- textColor: string;
34
- backgroundColor: string;
35
- };
36
- agent: {
37
- textColor: string;
38
- backgroundColor: string;
39
- };
40
- };
41
- }
42
-
43
- export const defaultThemeId = ThemeId.Light;
44
15
 
45
- export const lightMessage = {
46
- user: { textColor: white, backgroundColor: lightBlue },
47
- agent: { textColor: white, backgroundColor: offBlack },
16
+ return rgbToHex(newRgb.r, newRgb.g, newRgb.b);
48
17
  };
49
- export const darkMessage = {
50
- user: { textColor: white, backgroundColor: lightGray },
51
- agent: { textColor: white, backgroundColor: darkGray },
18
+
19
+ const hexToRgb = (hex: string): { r: number; g: number; b: number } => {
20
+ const r = parseInt(hex.substring(1, 3), 16);
21
+ const g = parseInt(hex.substring(3, 5), 16);
22
+ const b = parseInt(hex.substring(5, 7), 16);
23
+ return { r, g, b };
52
24
  };
53
- const themesById = {
54
- [ThemeId.Light]: {
55
- chatHeader: {
56
- backgroundColor: white,
57
- textColor: darkGray,
58
- },
59
- chatPaneBackgroundColor: "rgba(255, 255, 255, 0.9)",
60
- message: lightMessage,
61
- },
62
- [ThemeId.Dark]: {
63
- chatHeader: {
64
- backgroundColor: darkGray,
65
- textColor: white,
66
- },
67
- chatPaneBackgroundColor: "rgba(32, 32, 32, 0.9)",
68
- message: lightMessage,
69
- },
70
- [ThemeId.Purple]: {
71
- chatHeader: {
72
- backgroundColor: "#550098",
73
- textColor: white,
74
- },
75
- chatPaneBackgroundColor: "rgba(85, 0, 152, 0.6)",
76
- message: lightMessage,
77
- },
78
- [ThemeId.Blue]: {
79
- chatHeader: {
80
- backgroundColor: "#0814E5",
81
- textColor: white,
82
- },
83
- chatPaneBackgroundColor: "rgba(4, 17, 245, 0.6)",
84
- message: lightMessage,
85
- },
86
- [ThemeId.Teal]: {
87
- chatHeader: {
88
- backgroundColor: "#6EE7ED",
89
- textColor: darkGray,
90
- },
91
- chatPaneBackgroundColor: "rgba(115, 247, 253, 0.8)",
92
- message: darkMessage,
93
- },
94
- [ThemeId.Green]: {
95
- chatHeader: {
96
- backgroundColor: "#147B0E",
97
- textColor: white,
98
- },
99
- chatPaneBackgroundColor: "rgba(13, 141, 5, 0.6)",
100
- message: lightMessage,
101
- },
102
- [ThemeId.Yellow]: {
103
- chatHeader: {
104
- backgroundColor: "#F1E54F",
105
- textColor: darkGray,
106
- },
107
- chatPaneBackgroundColor: "rgba(251, 239, 80, 0.9)",
108
- message: darkMessage,
109
- },
110
- [ThemeId.Orange]: {
111
- chatHeader: {
112
- backgroundColor: "#C06C31",
113
- textColor: white,
114
- },
115
- chatPaneBackgroundColor: "rgba(238, 126, 49, 0.7)",
116
- message: lightMessage,
117
- },
118
- [ThemeId.Pink]: {
119
- chatHeader: {
120
- backgroundColor: "#A24599",
121
- textColor: white,
122
- },
123
- chatPaneBackgroundColor: "rgba(167, 70, 157, 0.8)",
124
- message: lightMessage,
125
- },
126
- [ThemeId.Glass]: {
127
- chatHeader: {
128
- backgroundColor: white,
129
- textColor: darkGray,
130
- },
131
- chatPaneBackgroundColor: "rgba(193, 193, 193, 0.5)",
132
- message: {
133
- user: {
134
- textColor: "#FFFFFF",
135
- backgroundColor: "#000000",
136
- },
137
- agent: {
138
- textColor: "#000000",
139
- backgroundColor: "#FFFFFF",
140
- },
141
- },
142
- },
25
+
26
+ const rgbToHex = (r: number, g: number, b: number): string => {
27
+ return (
28
+ "#" +
29
+ [r, g, b]
30
+ .map((c) => {
31
+ const hex = c.toString(16);
32
+ return hex.length === 1 ? "0" + hex : hex;
33
+ })
34
+ .join("")
35
+ );
143
36
  };
144
37
 
145
- /** If `themeId` is a valid `ThemeId`, returns the corresponding theme. Otherwise returns the default theme. */
146
- export const getTheme = ({
147
- themeId,
148
- brandColor,
149
- }: {
150
- themeId?: ThemeId | string;
151
- brandColor?: string | null;
152
- }): Theme => {
153
- const theme =
154
- themesById[
155
- themeId && Object.keys(themesById).includes(themeId)
156
- ? (themeId as ThemeIdString)
157
- : defaultThemeId
158
- ];
159
- if (brandColor && brandColor !== defaultBrandColor) {
160
- theme.message.user.backgroundColor = brandColor;
161
- theme.chatHeader.backgroundColor = hexToAlmostWhite(brandColor, 0.6);
162
- }
163
- return theme;
38
+ export const hexToAlmostWhite = (hexColor: string, ratio: number): string => {
39
+ let r = parseInt(hexColor.substr(1, 2), 16);
40
+ let g = parseInt(hexColor.substr(3, 2), 16);
41
+ let b = parseInt(hexColor.substr(5, 2), 16);
42
+
43
+ // the ratio of white to add (1 = white, 0 = no change)
44
+ r = Math.round(r * (1 - ratio) + 255 * ratio);
45
+ g = Math.round(g * (1 - ratio) + 255 * ratio);
46
+ b = Math.round(b * (1 - ratio) + 255 * ratio);
47
+
48
+ return (
49
+ "#" +
50
+ r.toString(16).padStart(2, "0") +
51
+ g.toString(16).padStart(2, "0") +
52
+ b.toString(16).padStart(2, "0")
53
+ );
164
54
  };
package/src/utils.ts CHANGED
@@ -49,56 +49,3 @@ export function useInterval(callback: () => void, delay: number | null): void {
49
49
 
50
50
  export const isMobile = (): boolean =>
51
51
  window.matchMedia("(max-width: 767px)").matches;
52
-
53
- export const tintColor = (
54
- originalColor: string,
55
- tintOpacity: number
56
- ): string => {
57
- const originalRgb = hexToRgb(originalColor);
58
- const tintRgb = { r: 0, g: 0, b: 0 };
59
-
60
- const newRgb = {
61
- r: originalRgb.r + Math.round((tintRgb.r - originalRgb.r) * tintOpacity),
62
- g: originalRgb.g + Math.round((tintRgb.g - originalRgb.g) * tintOpacity),
63
- b: originalRgb.b + Math.round((tintRgb.b - originalRgb.b) * tintOpacity),
64
- };
65
-
66
- return rgbToHex(newRgb.r, newRgb.g, newRgb.b);
67
- };
68
-
69
- const hexToRgb = (hex: string): { r: number; g: number; b: number } => {
70
- const r = parseInt(hex.substring(1, 3), 16);
71
- const g = parseInt(hex.substring(3, 5), 16);
72
- const b = parseInt(hex.substring(5, 7), 16);
73
- return { r, g, b };
74
- };
75
-
76
- const rgbToHex = (r: number, g: number, b: number): string => {
77
- return (
78
- "#" +
79
- [r, g, b]
80
- .map((c) => {
81
- const hex = c.toString(16);
82
- return hex.length === 1 ? "0" + hex : hex;
83
- })
84
- .join("")
85
- );
86
- };
87
-
88
- export const hexToAlmostWhite = (hexColor: string, ratio: number): string => {
89
- let r = parseInt(hexColor.substr(1, 2), 16);
90
- let g = parseInt(hexColor.substr(3, 2), 16);
91
- let b = parseInt(hexColor.substr(5, 2), 16);
92
-
93
- // the ratio of white to add (1 = white, 0 = no change)
94
- r = Math.round(r * (1 - ratio) + 255 * ratio);
95
- g = Math.round(g * (1 - ratio) + 255 * ratio);
96
- b = Math.round(b * (1 - ratio) + 255 * ratio);
97
-
98
- return (
99
- "#" +
100
- r.toString(16).padStart(2, "0") +
101
- g.toString(16).padStart(2, "0") +
102
- b.toString(16).padStart(2, "0")
103
- );
104
- };
@@ -1,286 +0,0 @@
1
- import { css, html, LitElement, TemplateResult } from "lit";
2
- import { customElement, property, state } from "lit/decorators.js";
3
- import { createRef, ref, Ref } from "lit/directives/ref.js";
4
- import { installActionConfirmButton } from "./action-confirm-button";
5
- import { installDetailsWindow } from "./details-window";
6
- import {
7
- formatToPhoneInput,
8
- isModifierKey,
9
- isNumericInput,
10
- } from "./formatPhoneNumber";
11
- import { InputStyles } from "./InputStyles";
12
- import axios from "axios";
13
- import { pushGtmEvent } from "../../gtm";
14
-
15
- @customElement("text-us-window")
16
- export class TextUsWindow extends LitElement {
17
- static styles = [
18
- css`
19
- .text-us-wrapper {
20
- margin-top: 33px;
21
- color: #202020;
22
- }
23
- .text-us-window__header {
24
- font-family: "Helvetica Neue", Arial;
25
- font-style: normal;
26
- font-weight: 700;
27
- line-height: 140%;
28
- font-size: 14px;
29
- margin: 0;
30
- }
31
-
32
- .text-us-window__input-container {
33
- margin-top: 8px;
34
- margin-bottom: 8px;
35
- width: -webkit-fill-available;
36
- position: relative;
37
- }
38
- .text-us-window__submit-text {
39
- position: absolute;
40
- top: 14px;
41
- right: 6px;
42
- }
43
- .text-us-window__vertical-spacer {
44
- height: 20px;
45
- }
46
- .text-us-window__description,
47
- .text-us-window__error {
48
- font-family: "Helvetica Neue", Arial;
49
- font-style: normal;
50
- font-weight: 400;
51
- font-size: 10px;
52
- line-height: 14px;
53
- }
54
-
55
- .text-us-window__error {
56
- color: rgb(255, 49, 3);
57
- }
58
- `,
59
- InputStyles,
60
- ];
61
-
62
- @property({ attribute: false })
63
- onCloseClicked?: (e: MouseEvent) => void;
64
-
65
- @property({ attribute: false })
66
- buildingId = 0;
67
- @property({ attribute: true })
68
- buildingSlug = "";
69
- @property({ attribute: true })
70
- orgSlug = "";
71
- @property({ attribute: true })
72
- inPopup = false;
73
-
74
- phoneNumberInputRef: Ref<HTMLInputElement> = createRef();
75
-
76
- @state()
77
- phoneNumber = "";
78
- @state()
79
- hasSubmittedForm = false;
80
- @state()
81
- hasPhoneNumberError = false;
82
- @state()
83
- hasSubmissionError = false;
84
- @state()
85
- isSubmitting = false;
86
-
87
- @property({ attribute: true })
88
- currentLeadSource = "";
89
-
90
- onChangePhoneNumber = (e: Event): void => {
91
- if (!e.target || !this.phoneNumberInputRef.value) {
92
- return;
93
- }
94
- if (isModifierKey(e as KeyboardEvent)) {
95
- return;
96
- }
97
- const inputElement = e.target as HTMLInputElement;
98
-
99
- this.phoneNumber = formatToPhoneInput(inputElement.value);
100
-
101
- this.phoneNumberInputRef.value.value = this.phoneNumber;
102
- };
103
-
104
- enforceFormat = (e: KeyboardEvent): void => {
105
- if (!isNumericInput(e) && !isModifierKey(e)) {
106
- e.preventDefault();
107
- }
108
- };
109
-
110
- validateFormFields = (): void => {
111
- this.hasPhoneNumberError = false;
112
- this.hasSubmissionError = false;
113
- if (!this.phoneNumber || this.phoneNumber.length !== 14) {
114
- this.hasPhoneNumberError = true;
115
- }
116
- };
117
-
118
- onClick = async (): Promise<void> => {
119
- this.validateFormFields();
120
- if (this.hasPhoneNumberError) {
121
- return;
122
- }
123
- try {
124
- this.isSubmitting = true;
125
- await createTextWithUs(
126
- this.phoneNumber,
127
- this.buildingId,
128
- this.orgSlug,
129
- this.buildingSlug,
130
- [
131
- ...new Set(
132
- this.currentLeadSource
133
- ? [this.currentLeadSource, "property-website"]
134
- : ["property-website"]
135
- ),
136
- ]
137
- );
138
- this.hasSubmittedForm = true;
139
- this.isSubmitting = false;
140
- } catch (e) {
141
- this.isSubmitting = false;
142
- this.hasSubmissionError = true;
143
- }
144
- };
145
-
146
- renderTextUs = (): TemplateResult => {
147
- return html` <div class="text-us-wrapper">
148
- <h1 class="text-us-window__header">Send Us a Text</h1>
149
- <div class="text-us-window__input-container">
150
- <input
151
- ${ref(this.phoneNumberInputRef)}
152
- maxlength="14"
153
- type="text"
154
- placeholder="Enter phone"
155
- inputmode="tel"
156
- class="webchat-input text-us-window__input-container"
157
- .value=${this.phoneNumber}
158
- @keydown=${this.enforceFormat}
159
- @keyup=${this.onChangePhoneNumber}
160
- />
161
- <div class="text-us-window__submit-text">
162
- <action-confirm-button
163
- .onClick=${this.onClick}
164
- .isLoading=${this.isSubmitting}
165
- text="SEND"
166
- ></action-confirm-button>
167
- </div>
168
- ${this.hasPhoneNumberError
169
- ? html`
170
- <div class="text-us-window__error">
171
- Enter a valid phone number
172
- </div>
173
- `
174
- : ""}
175
- </div>
176
-
177
- <div class="text-us-window__description">
178
- By entering your number and selecting Send, you consent to be contacted
179
- by our AI Leasing Assistant. Your consent to this process is not a
180
- requirement for leasing at our property.
181
- <div class="text-us-window__description">
182
- Message and data rates may apply.
183
- </div>
184
- </div>
185
- </div>`;
186
- };
187
-
188
- renderSubmitted = (): TemplateResult => {
189
- return html`
190
- <div class="text-us-wrapper">
191
- <div class="text-us-window__vertical-spacer"></div>
192
- <svg
193
- width="20"
194
- height="20"
195
- viewBox="0 0 20 20"
196
- fill="none"
197
- xmlns="http://www.w3.org/2000/svg"
198
- >
199
- <path
200
- 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"
201
- fill="#202020"
202
- />
203
- </svg>
204
- <div class="text-us-window__description">
205
- Thank you!<br />Look for a text message from our team. We can answer
206
- questions and help you book a tour through text.
207
- </div>
208
- <div class="text-us-window__description">
209
- Opt out at anytime by texting “Stop”
210
- </div>
211
- </div>
212
- `;
213
- };
214
-
215
- render = (): TemplateResult => {
216
- installDetailsWindow();
217
- installActionConfirmButton();
218
- if (this.inPopup) {
219
- if (this.hasSubmittedForm) return this.renderSubmitted();
220
- else return this.renderTextUs();
221
- }
222
- if (this.hasSubmittedForm) {
223
- return html`
224
- <details-window
225
- headerText="Text us"
226
- .onCloseClick=${this.onCloseClicked}
227
- >
228
- ${this.renderSubmitted}
229
- </details-window>
230
- `;
231
- }
232
- return html`
233
- <details-window headerText="Text us" .onCloseClick=${this.onCloseClicked}>
234
- ${this.renderTextUs}
235
- </details-window>
236
- `;
237
- };
238
- }
239
-
240
- export const installTextUsWindow = (): void => {
241
- if (!window.customElements.get("text-us-window")) {
242
- window.customElements.define("text-us-window", TextUsWindow);
243
- }
244
- };
245
-
246
- const createTextWithUs = async (
247
- rawPhoneNumber: string,
248
- buildingId: number,
249
- orgSlug: string,
250
- buildingSlug: string,
251
- leadSources: string[]
252
- ) => {
253
- const formattedPhoneNumber =
254
- "+1" +
255
- rawPhoneNumber
256
- .replace("(", "")
257
- .replace(")", "")
258
- .replace(" ", "")
259
- .replace("-", "");
260
- const queryParams = new URLSearchParams(window.location.search);
261
- const requestBody = {
262
- building_id: buildingId,
263
- lead_sources: leadSources,
264
- phone_number: formattedPhoneNumber,
265
- referrer: document.referrer,
266
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
267
- // @ts-ignore
268
- query_params: Object.fromEntries(queryParams.entries()),
269
- };
270
- pushGtmEvent("textUsSubmitted", {
271
- phone: formattedPhoneNumber,
272
- originatingSource:
273
- leadSources.find((i) => i !== "property-website") || null,
274
- });
275
- await axios.post(
276
- "https://app.meetelise.com/platformApi/state/create/textMe",
277
- requestBody,
278
- {
279
- headers: {
280
- ["building-slug"]: buildingSlug,
281
- ["org-slug"]: orgSlug,
282
- ["X-SecurityKey"]: "JRL8jV4VcSCwOSir5gWkpgNLfKghmhBG",
283
- },
284
- }
285
- );
286
- };
package/src/chatID.ts DELETED
@@ -1,64 +0,0 @@
1
- import { v4 as uuid } from "uuid";
2
-
3
- const localStorageNamespacingPrefix = "com.meetelise";
4
- const chatIdKeyPrefix = `${localStorageNamespacingPrefix}.chatID`;
5
- const chatIdIssueTimeKeyPrefix = `${localStorageNamespacingPrefix}.chatIDIssueTime`;
6
- const chatIdTimeToLiveInMilliseconds = 6 * 60 * 60 * 1000; // 6 hours
7
-
8
- /**
9
- * Get or create a UUID that is the same between browser sessions.
10
- * If the UUID is past its expiration time, create a new one.
11
- *
12
- * @returns the chat ID.
13
- */
14
- export function getChatID(org: string, building: string): string {
15
- const key = getChatIdKey(org, building);
16
- const existingID = localStorage.getItem(key);
17
- if (existingID && !existingChatIdIsExpired(org, building)) return existingID;
18
- else return createChatID(org, building);
19
- }
20
-
21
- /**
22
- * Create a new chat ID, discard any old one, and record the time it was issued.
23
- */
24
- export function createChatID(org: string, building: string): string {
25
- const chatIdKey = getChatIdKey(org, building);
26
- const chatId = uuid();
27
- localStorage.setItem(chatIdKey, chatId);
28
-
29
- setIssueTime(org, building);
30
-
31
- return chatId;
32
- }
33
-
34
- function setIssueTime(org: string, building: string): string {
35
- const issueTimeKey = getChatIdIssueTimeKey(org, building);
36
- const issueTimeString = new Date().toISOString();
37
- localStorage.setItem(issueTimeKey, issueTimeString);
38
- return issueTimeString;
39
- }
40
-
41
- function getChatIdKey(org: string, building: string): string {
42
- return `${chatIdKeyPrefix}-${org}-${building}`;
43
- }
44
-
45
- function getChatIdIssueTimeKey(org: string, building: string): string {
46
- return `${chatIdIssueTimeKeyPrefix}-${org}-${building}`;
47
- }
48
-
49
- /**
50
- * Check if the existing chat ID is expired.
51
- *
52
- * If the issue time is missing, set the issue time to the current time.
53
- * (This will be the case for chat IDs created before the expiration functionality was added.)
54
- */
55
- function existingChatIdIsExpired(org: string, building: string): boolean {
56
- const issueTimeKey = getChatIdIssueTimeKey(org, building);
57
- const existingIdIssueTimeString =
58
- localStorage.getItem(issueTimeKey) || setIssueTime(org, building);
59
- const existingIdExpiration = new Date(
60
- new Date(existingIdIssueTimeString).getTime() +
61
- chatIdTimeToLiveInMilliseconds
62
- );
63
- return new Date() > existingIdExpiration;
64
- }
@@ -1,57 +0,0 @@
1
- import Talk from "talkjs";
2
- import { Building } from "./fetchBuildingInfo";
3
- import { Theme } from "./themes";
4
- import { darkMessage } from "./themes";
5
-
6
- const defaultAvatarUrl =
7
- "https://eliseusercontent.meetelise.com/webchat/looping-gradient.gif";
8
-
9
- export default function createConversation(
10
- session: Talk.Session,
11
- building: Building,
12
- theme: Theme,
13
- avatarSrc: Building["avatarSrc"],
14
- chatID: string,
15
- isMobile: boolean
16
- ): Talk.ConversationBuilder {
17
- const agent = new Talk.User({
18
- id: `building_${building.id}`,
19
- name: building.userFirstName,
20
- email: null,
21
- role: "Default",
22
- welcomeMessage: building.welcomeMessage,
23
- availabilityText: building.systemWelcomeMessage,
24
- });
25
- const conversation = session.getOrCreateConversation(chatID);
26
- conversation.setParticipant(session.me);
27
- conversation.setParticipant(agent);
28
- conversation.subject =
29
- building.orgId === 16
30
- ? "Leasing team" // by AVB request
31
- : building.chatTitle ?? building.userFirstName;
32
- conversation.custom = {
33
- buildingId: building.id.toString(),
34
- userId: building.userId.toString(),
35
- orgId: building.orgId.toString(),
36
- subtitle: building.chatSubtitle,
37
- url: location.href,
38
- buildingName: building.name,
39
- isMobile: isMobile.toString(),
40
- chatHeaderBackgroundColor: theme.chatHeader.backgroundColor,
41
- chatHeaderTextColor: theme.chatHeader.textColor,
42
- chatPaneBackgroundColor: theme.chatPaneBackgroundColor,
43
- userMessageTextColor: theme.message.user.textColor,
44
- userMessageBackgroundColor: theme.message.user.backgroundColor,
45
- agentMessageTextColor: theme.message.agent.textColor,
46
- agentMessageBackgroundColor: theme.message.agent.backgroundColor,
47
- // it is sometimes helpful to know inside TalkJS if the theme is a light theme (examples: Light, Teal, Yellow) or a dark theme (Dark, Purple, Green)
48
- isLightTheme: (theme.message === darkMessage).toString(),
49
- avatarUrl:
50
- building.avatarType === "image" && building.avatarSrc
51
- ? avatarSrc
52
- : defaultAvatarUrl,
53
- // uncomment the following line to test changes to the default avatar if your test building has its own avatar
54
- // avatarUrl: defaultAvatarUrl,
55
- };
56
- return conversation;
57
- }