From 0d0fa7c398df676a7f56038607b4cfdc121db2c3 Mon Sep 17 00:00:00 2001 From: murtaza98 Date: Thu, 13 Jan 2022 16:43:02 +0530 Subject: [PATCH 1/6] [NEW][EE] Introduce `setBusinessUnitIds` Widget API method --- src/lib/hooks.js | 22 ++++++++++++++++++++++ src/lib/main.js | 8 +++++++- src/store/index.js | 1 + src/widget.js | 9 +++++++++ widget-demo.html | 9 +++++++++ 5 files changed, 48 insertions(+), 1 deletion(-) diff --git a/src/lib/hooks.js b/src/lib/hooks.js index 72bc3e457..a6ce19990 100644 --- a/src/lib/hooks.js +++ b/src/lib/hooks.js @@ -27,6 +27,15 @@ const updateIframeGuestData = (data) => { createOrUpdateGuest(guestData); }; +const isBothArraysContentSame = (arr1, arr2) => { + if (arr1.length !== arr2.length) { + return false; + } + const intersection = arr1.filter((x) => arr2.includes(x)); + + return intersection.length === arr1.length; +}; + const api = { pageVisited(info) { if (info.change === 'url') { @@ -69,6 +78,19 @@ const api = { updateIframeGuestData({ department }); }, + async setBusinessUnitIds(value) { + if (!value || !value.businessUnits || !Array.isArray(value.businessUnits)) { + throw new Error('Error! Invalid business ids'); + } + + const { config: { businessUnitIds: existingBusinessUnitIds }, config } = store.state; + if (existingBusinessUnitIds && isBothArraysContentSame(existingBusinessUnitIds, value.businessUnits)) { + return; + } + store.setState({ config: { ...config, businessUnitIds: value.businessUnits } }); + await loadConfig(); + }, + clearDepartment() { updateIframeGuestData({ department: '' }); }, diff --git a/src/lib/main.js b/src/lib/main.js index a38e4def3..f0cadf13a 100644 --- a/src/lib/main.js +++ b/src/lib/main.js @@ -10,6 +10,9 @@ import constants from './constants'; export const loadConfig = async () => { const { token, + config: { + businessUnitIds, + } = { businessUnitIds: [] }, } = store.state; Livechat.credentials.token = token; @@ -21,7 +24,10 @@ export const loadConfig = async () => { resources: { sound: src = null } = {}, queueInfo, ...config - } = await Livechat.config({ token }); + } = await Livechat.config({ + token, + ...businessUnitIds?.length && { businessUnitIds: businessUnitIds.join('-') }, + }); await store.setState({ config, diff --git a/src/store/index.js b/src/store/index.js index 84706a8a1..f1c44b0cf 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -13,6 +13,7 @@ export const initialState = () => ({ triggers: [], departments: [], resources: {}, + businessUnitIds: [], }, messages: [], user: null, diff --git a/src/widget.js b/src/widget.js index e45942ad0..ed112df95 100644 --- a/src/widget.js +++ b/src/widget.js @@ -263,6 +263,10 @@ function setDepartment(department) { callHook('setDepartment', department); } +function setBusinessUnitIds(businessUnits) { + callHook('setBusinessUnitIds', businessUnits); +} + function setGuestToken(token) { callHook('setGuestToken', token); } @@ -334,6 +338,10 @@ function initialize(params) { case 'department': setDepartment(params[method]); continue; + case 'businessUnitIds': { + setBusinessUnitIds(params[method]); + continue; + } case 'guestToken': setGuestToken(params[method]); continue; @@ -436,6 +444,7 @@ window.RocketChat.livechat = { hideWidget, maximizeWidget, minimizeWidget, + setBusinessUnitIds, // callbacks onChatMaximized(fn) { registerCallback('chat-maximized', fn); }, diff --git a/widget-demo.html b/widget-demo.html index 058961f03..9634f6981 100644 --- a/widget-demo.html +++ b/widget-demo.html @@ -51,6 +51,15 @@ j.src = 'build/rocketchat-livechat.min.js?_=' + Math.random(); h.parentNode.insertBefore(j, h); })(window, document, 'script', 'http://localhost:8080'); + RocketChat(function() { + this.setTheme({ + color: '#04436A', // widget title background color + fontColor: '#FFFFFF', // widget title font color + iconColor: '#1d74f5', // widget icon color + title: "Welcome to Rocket.Chat", // default widget title when the status of service is online + offlineTitle: "Service is offline", // default widget title when the status of service is online + }); + }); From 51f9620373fa137c61a5b4a497acb4e953d0cb48 Mon Sep 17 00:00:00 2001 From: murtaza98 Date: Fri, 14 Jan 2022 17:27:32 +0530 Subject: [PATCH 2/6] Apply suggestions from code review --- src/lib/hooks.js | 19 +++++-------------- src/lib/main.js | 6 ++---- src/lib/room.js | 2 +- src/store/index.js | 2 +- src/widget.js | 10 +++++----- 5 files changed, 14 insertions(+), 25 deletions(-) diff --git a/src/lib/hooks.js b/src/lib/hooks.js index a6ce19990..7069366cd 100644 --- a/src/lib/hooks.js +++ b/src/lib/hooks.js @@ -27,15 +27,6 @@ const updateIframeGuestData = (data) => { createOrUpdateGuest(guestData); }; -const isBothArraysContentSame = (arr1, arr2) => { - if (arr1.length !== arr2.length) { - return false; - } - const intersection = arr1.filter((x) => arr2.includes(x)); - - return intersection.length === arr1.length; -}; - const api = { pageVisited(info) { if (info.change === 'url') { @@ -78,16 +69,16 @@ const api = { updateIframeGuestData({ department }); }, - async setBusinessUnitIds(value) { - if (!value || !value.businessUnits || !Array.isArray(value.businessUnits)) { + async setBusinessUnit(newBusinessUnit) { + if (!newBusinessUnit || !newBusinessUnit.trim().length) { throw new Error('Error! Invalid business ids'); } - const { config: { businessUnitIds: existingBusinessUnitIds }, config } = store.state; - if (existingBusinessUnitIds && isBothArraysContentSame(existingBusinessUnitIds, value.businessUnits)) { + const { businessUnit: existingBusinessUnit } = store.state; + if (existingBusinessUnit === newBusinessUnit) { return; } - store.setState({ config: { ...config, businessUnitIds: value.businessUnits } }); + store.setState({ businessUnit: newBusinessUnit }); await loadConfig(); }, diff --git a/src/lib/main.js b/src/lib/main.js index f0cadf13a..d93f17756 100644 --- a/src/lib/main.js +++ b/src/lib/main.js @@ -10,9 +10,7 @@ import constants from './constants'; export const loadConfig = async () => { const { token, - config: { - businessUnitIds, - } = { businessUnitIds: [] }, + businessUnit = null, } = store.state; Livechat.credentials.token = token; @@ -26,7 +24,7 @@ export const loadConfig = async () => { ...config } = await Livechat.config({ token, - ...businessUnitIds?.length && { businessUnitIds: businessUnitIds.join('-') }, + ...businessUnit && { businessUnit }, }); await store.setState({ diff --git a/src/lib/room.js b/src/lib/room.js index 270098fa5..0e97c1022 100644 --- a/src/lib/room.js +++ b/src/lib/room.js @@ -26,7 +26,7 @@ export const closeChat = async ({ transcriptRequested } = {}) => { if (clearLocalStorageWhenChatEnded) { // exclude UI-affecting flags - const { minimized, visible, undocked, expanded, ...initial } = initialState(); + const { minimized, visible, undocked, expanded, businessUnit, ...initial } = initialState(); await store.setState(initial); } diff --git a/src/store/index.js b/src/store/index.js index f1c44b0cf..0d35104d3 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -13,7 +13,6 @@ export const initialState = () => ({ triggers: [], departments: [], resources: {}, - businessUnitIds: [], }, messages: [], user: null, @@ -36,6 +35,7 @@ export const initialState = () => ({ unread: null, incomingCallAlert: null, ongoingCall: null, // TODO: store call info like url, startTime, timeout, etc here + businessUnit: null, }); const dontPersist = ['messages', 'typing', 'loading', 'alerts', 'unread', 'noMoreMessages', 'modal', 'incomingCallAlert', 'ongoingCall']; diff --git a/src/widget.js b/src/widget.js index ed112df95..f56a9c1a1 100644 --- a/src/widget.js +++ b/src/widget.js @@ -263,8 +263,8 @@ function setDepartment(department) { callHook('setDepartment', department); } -function setBusinessUnitIds(businessUnits) { - callHook('setBusinessUnitIds', businessUnits); +function setBusinessUnit(businessUnits) { + callHook('setBusinessUnit', businessUnits); } function setGuestToken(token) { @@ -338,8 +338,8 @@ function initialize(params) { case 'department': setDepartment(params[method]); continue; - case 'businessUnitIds': { - setBusinessUnitIds(params[method]); + case 'businessUnit': { + setBusinessUnit(params[method]); continue; } case 'guestToken': @@ -444,7 +444,7 @@ window.RocketChat.livechat = { hideWidget, maximizeWidget, minimizeWidget, - setBusinessUnitIds, + setBusinessUnit, // callbacks onChatMaximized(fn) { registerCallback('chat-maximized', fn); }, From ecb37d64ad8cabd1aaa1ae4d300a332d37de834b Mon Sep 17 00:00:00 2001 From: murtaza98 Date: Mon, 17 Jan 2022 17:23:03 +0530 Subject: [PATCH 3/6] Adding new method - `clearBusinessUnit` & refactoring --- src/lib/hooks.js | 13 ++++++++++--- src/lib/main.js | 34 ++++++++++++++++++++++++++++++++++ src/widget.js | 5 +++++ 3 files changed, 49 insertions(+), 3 deletions(-) diff --git a/src/lib/hooks.js b/src/lib/hooks.js index 7069366cd..8d8b948b1 100644 --- a/src/lib/hooks.js +++ b/src/lib/hooks.js @@ -2,7 +2,7 @@ import { Livechat } from '../api'; import { store } from '../store'; import CustomFields from './customFields'; import { setWidgetLanguage } from './locale'; -import { loadConfig } from './main'; +import { loadConfig, clearBusinessUnit, setBusinessUnit } from './main'; import { parentCall } from './parentCall'; import { createToken } from './random'; import Triggers from './triggers'; @@ -78,8 +78,15 @@ const api = { if (existingBusinessUnit === newBusinessUnit) { return; } - store.setState({ businessUnit: newBusinessUnit }); - await loadConfig(); + await setBusinessUnit(newBusinessUnit); + }, + + async clearBusinessUnit() { + const { businessUnit } = store.state; + if (!businessUnit) { + return; + } + await clearBusinessUnit(); }, clearDepartment() { diff --git a/src/lib/main.js b/src/lib/main.js index d93f17756..fae268230 100644 --- a/src/lib/main.js +++ b/src/lib/main.js @@ -7,6 +7,40 @@ import I18n from '../i18n'; import store from '../store'; import constants from './constants'; +export const clearBusinessUnit = async () => { + const { + token, + config: existingConfig, + } = store.state; + + Livechat.credentials.token = token; + + const { departments } = await Livechat.config({ + token, + }); + + await store.setState({ config: { ...existingConfig, departments }, businessUnit: undefined }); +}; + +export const setBusinessUnit = async (newBusinessUnit) => { + const { + token, + config: existingConfig, + } = store.state; + if (!token) { + throw new Error('Error! no livechat token found. please make sure you initialize widget first before setting business unit'); + } + + Livechat.credentials.token = token; + + const { departments } = await Livechat.config({ + token, + businessUnit: newBusinessUnit, + }); + + await store.setState({ config: { ...existingConfig, departments }, businessUnit: newBusinessUnit }); +}; + export const loadConfig = async () => { const { token, diff --git a/src/widget.js b/src/widget.js index f56a9c1a1..6ece0b6aa 100644 --- a/src/widget.js +++ b/src/widget.js @@ -267,6 +267,10 @@ function setBusinessUnit(businessUnits) { callHook('setBusinessUnit', businessUnits); } +function clearBusinessUnit() { + callHook('clearBusinessUnit'); +} + function setGuestToken(token) { callHook('setGuestToken', token); } @@ -445,6 +449,7 @@ window.RocketChat.livechat = { maximizeWidget, minimizeWidget, setBusinessUnit, + clearBusinessUnit, // callbacks onChatMaximized(fn) { registerCallback('chat-maximized', fn); }, From 7d5d6804cfd751f27c6efd931c34ffbee28199ff Mon Sep 17 00:00:00 2001 From: murtaza98 Date: Tue, 18 Jan 2022 16:22:44 +0530 Subject: [PATCH 4/6] Apply suggestions from code review --- src/lib/hooks.js | 6 +++--- src/lib/main.js | 39 +++++++++++++++++++-------------------- src/store/Store.js | 8 ++++++++ 3 files changed, 30 insertions(+), 23 deletions(-) diff --git a/src/lib/hooks.js b/src/lib/hooks.js index 8d8b948b1..56c5625c9 100644 --- a/src/lib/hooks.js +++ b/src/lib/hooks.js @@ -2,7 +2,7 @@ import { Livechat } from '../api'; import { store } from '../store'; import CustomFields from './customFields'; import { setWidgetLanguage } from './locale'; -import { loadConfig, clearBusinessUnit, setBusinessUnit } from './main'; +import { loadConfig, updateBusinessUnit } from './main'; import { parentCall } from './parentCall'; import { createToken } from './random'; import Triggers from './triggers'; @@ -78,7 +78,7 @@ const api = { if (existingBusinessUnit === newBusinessUnit) { return; } - await setBusinessUnit(newBusinessUnit); + await updateBusinessUnit(newBusinessUnit); }, async clearBusinessUnit() { @@ -86,7 +86,7 @@ const api = { if (!businessUnit) { return; } - await clearBusinessUnit(); + await updateBusinessUnit(); }, clearDepartment() { diff --git a/src/lib/main.js b/src/lib/main.js index fae268230..55fc79f70 100644 --- a/src/lib/main.js +++ b/src/lib/main.js @@ -7,22 +7,7 @@ import I18n from '../i18n'; import store from '../store'; import constants from './constants'; -export const clearBusinessUnit = async () => { - const { - token, - config: existingConfig, - } = store.state; - - Livechat.credentials.token = token; - - const { departments } = await Livechat.config({ - token, - }); - - await store.setState({ config: { ...existingConfig, departments }, businessUnit: undefined }); -}; - -export const setBusinessUnit = async (newBusinessUnit) => { +export const updateBusinessUnit = async (newBusinessUnit) => { const { token, config: existingConfig, @@ -31,14 +16,28 @@ export const setBusinessUnit = async (newBusinessUnit) => { throw new Error('Error! no livechat token found. please make sure you initialize widget first before setting business unit'); } - Livechat.credentials.token = token; - const { departments } = await Livechat.config({ token, - businessUnit: newBusinessUnit, + ...newBusinessUnit && { businessUnit: newBusinessUnit }, }); - await store.setState({ config: { ...existingConfig, departments }, businessUnit: newBusinessUnit }); + if (newBusinessUnit) { + return store.setState({ + config: { + ...existingConfig, + departments, + }, + businessUnit: newBusinessUnit, + }); + } + + await store.setState({ + config: { + ...existingConfig, + departments, + }, + }); + await store.unsetSinglePropInStateByName('businessUnit'); }; export const loadConfig = async () => { diff --git a/src/store/Store.js b/src/store/Store.js index 0a14c7cd0..3c1061f85 100644 --- a/src/store/Store.js +++ b/src/store/Store.js @@ -78,6 +78,14 @@ export default class Store { this.emit('change', [this._state, prevState, partialState]); } + unsetSinglePropInStateByName(propName) { + const prevState = this._state; + delete prevState[propName]; + this._state = { ...prevState }; + this.persist(); + this.emit('change', [this._state, prevState]); + } + setStoredState(storedState) { const prevState = this._state; From 54592f31a48d58f3be63fecfbb4703a6dad12e8d Mon Sep 17 00:00:00 2001 From: Murtaza Patrawala <34130764+murtaza98@users.noreply.github.com> Date: Thu, 20 Jan 2022 10:18:31 +0530 Subject: [PATCH 5/6] Apply suggestions from code review Co-authored-by: Kevin Aleman Co-authored-by: Renato Becker --- src/lib/hooks.js | 11 +++-------- src/widget.js | 4 ++-- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/src/lib/hooks.js b/src/lib/hooks.js index 56c5625c9..bfef729bf 100644 --- a/src/lib/hooks.js +++ b/src/lib/hooks.js @@ -75,18 +75,13 @@ const api = { } const { businessUnit: existingBusinessUnit } = store.state; - if (existingBusinessUnit === newBusinessUnit) { - return; - } - await updateBusinessUnit(newBusinessUnit); + + return existingBusinessUnit !== newBusinessUnit && await updateBusinessUnit(newBusinessUnit); }, async clearBusinessUnit() { const { businessUnit } = store.state; - if (!businessUnit) { - return; - } - await updateBusinessUnit(); + return businessUnit && updateBusinessUnit(); }, clearDepartment() { diff --git a/src/widget.js b/src/widget.js index 6ece0b6aa..b809faca0 100644 --- a/src/widget.js +++ b/src/widget.js @@ -263,8 +263,8 @@ function setDepartment(department) { callHook('setDepartment', department); } -function setBusinessUnit(businessUnits) { - callHook('setBusinessUnit', businessUnits); +function setBusinessUnit(businessUnit) { + callHook('setBusinessUnit', businessUnit); } function clearBusinessUnit() { From 89ba9631f2ca0d19555262d139859233a17c97b0 Mon Sep 17 00:00:00 2001 From: murtaza98 Date: Thu, 20 Jan 2022 10:24:05 +0530 Subject: [PATCH 6/6] Fix minor issue in previous commit --- src/lib/hooks.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/hooks.js b/src/lib/hooks.js index bfef729bf..59ddeda0c 100644 --- a/src/lib/hooks.js +++ b/src/lib/hooks.js @@ -76,7 +76,7 @@ const api = { const { businessUnit: existingBusinessUnit } = store.state; - return existingBusinessUnit !== newBusinessUnit && await updateBusinessUnit(newBusinessUnit); + return existingBusinessUnit !== newBusinessUnit && updateBusinessUnit(newBusinessUnit); }, async clearBusinessUnit() {