diff --git a/.sync b/.sync index b8b451d0e1..c77e608356 100644 --- a/.sync +++ b/.sync @@ -1 +1 @@ -7698f1018c89580fc352022f2b6da694f5533b77 +57d170a1333473bf028801ec050850f3251a68b1 diff --git a/packages/phone-number/lib/detect/index.js b/packages/phone-number/lib/detect/index.js index e6539feca1..a1fdd9cf5d 100644 --- a/packages/phone-number/lib/detect/index.js +++ b/packages/phone-number/lib/detect/index.js @@ -1,5 +1,5 @@ -import { findPhoneNumbers } from 'libphonenumber-js'; -import { forEach, find } from 'ramda'; +import { findNumbers } from 'libphonenumber-js'; +import { forEach, find, map } from 'ramda'; import parse from '../parse'; function find7DigitNumbers(input, countryCode) { @@ -17,7 +17,7 @@ function find7DigitNumbers(input, countryCode) { if (isValid && !hasPlus && phoneNumber.length === 7) { output.push({ country: countryCode, - phone: phoneNumber, + phoneNumber, startsAt: match.index, endsAt: match.index + match[0].length, }); @@ -32,7 +32,19 @@ function byStartsAt(a, b) { } export default function detect({ input, countryCode = 'US', areaCode = '' }) { - const output = findPhoneNumbers(input, countryCode); + const output = map( + (item) => ({ + phoneNumber: item.number.number, + country: item.number.country, + nationalNumber: item.number.nationalNumber, + ext: item.number.ext, + startsAt: item.startsAt, + endsAt: item.endsAt, + }), + findNumbers(input, countryCode, { + v2: true, + }), + ); if ((countryCode === 'US' || countryCode === 'CA') && areaCode.length === 3) { const sevenDigits = find7DigitNumbers(input, countryCode); if (sevenDigits.length) { diff --git a/packages/phone-number/package.json b/packages/phone-number/package.json index 10a43c484f..0986e82876 100644 --- a/packages/phone-number/package.json +++ b/packages/phone-number/package.json @@ -1,6 +1,6 @@ { "name": "@ringcentral-integration/phone-number", - "version": "1.0.3", + "version": "1.0.4", "description": "Wrapper around libphonenumber-js to provide RingCentral specific phone handling.", "main": "index.js", "repository": { @@ -15,7 +15,7 @@ "homepage": "https://github.com/ringcentral/ringcentral-js-widgets#readme", "private": false, "dependencies": { - "libphonenumber-js": "^1.7.24", + "libphonenumber-js": "^1.7.29", "ramda": "^0.26.1" }, "peerDependencies": {}, diff --git a/packages/ringcentral-integration/enums/activeCallControlStatus.js b/packages/ringcentral-integration/enums/activeCallControlStatus.js deleted file mode 100644 index 5eb5c4c253..0000000000 --- a/packages/ringcentral-integration/enums/activeCallControlStatus.js +++ /dev/null @@ -1,7 +0,0 @@ -import HashMap from '../lib/HashMap'; - -export default new HashMap({ - hold: 'Hold', - setUp: 'Setup', - proceeding: 'Proceeding', -}); diff --git a/packages/ringcentral-integration/enums/activeCallControlStatus.ts b/packages/ringcentral-integration/enums/activeCallControlStatus.ts new file mode 100644 index 0000000000..ebc60966b3 --- /dev/null +++ b/packages/ringcentral-integration/enums/activeCallControlStatus.ts @@ -0,0 +1,7 @@ +import { createHashMap } from '../lib/HashMap'; + +export default createHashMap({ + hold: 'Hold', + setUp: 'Setup', + proceeding: 'Proceeding', +}); diff --git a/packages/ringcentral-integration/enums/availabilityTypes.js b/packages/ringcentral-integration/enums/availabilityTypes.js deleted file mode 100644 index 9b876dbb86..0000000000 --- a/packages/ringcentral-integration/enums/availabilityTypes.js +++ /dev/null @@ -1,7 +0,0 @@ -import HashMap from '../lib/HashMap'; - -export default new HashMap({ - alive: 'Alive', - deleted: 'Deleted', - purged: 'Purged', -}); diff --git a/packages/ringcentral-integration/enums/availabilityTypes.ts b/packages/ringcentral-integration/enums/availabilityTypes.ts new file mode 100644 index 0000000000..86c304e42e --- /dev/null +++ b/packages/ringcentral-integration/enums/availabilityTypes.ts @@ -0,0 +1,7 @@ +import { createHashMap } from '../lib/HashMap'; + +export default createHashMap({ + alive: 'Alive', + deleted: 'Deleted', + purged: 'Purged', +}); diff --git a/packages/ringcentral-integration/enums/callActions.js b/packages/ringcentral-integration/enums/callActions.ts similarity index 87% rename from packages/ringcentral-integration/enums/callActions.js rename to packages/ringcentral-integration/enums/callActions.ts index 5d59769b7d..09e8b85a89 100644 --- a/packages/ringcentral-integration/enums/callActions.js +++ b/packages/ringcentral-integration/enums/callActions.ts @@ -1,6 +1,6 @@ -import HashMap from '../lib/HashMap'; +import { createHashMap } from '../lib/HashMap'; -export default new HashMap({ +export default createHashMap({ '411Info': '411 Info', acceptCall: 'Accept Call', callReturn: 'Call Return', diff --git a/packages/ringcentral-integration/enums/callLogMessages.js b/packages/ringcentral-integration/enums/callLogMessages.ts similarity index 53% rename from packages/ringcentral-integration/enums/callLogMessages.js rename to packages/ringcentral-integration/enums/callLogMessages.ts index 7f6444dd66..28cc25ce64 100644 --- a/packages/ringcentral-integration/enums/callLogMessages.js +++ b/packages/ringcentral-integration/enums/callLogMessages.ts @@ -1,6 +1,6 @@ -import Enum from '../lib/Enum'; +import { createEnum } from '../lib/Enum'; -export default new Enum( +export default createEnum( ['logCallLogFailed', 'logFailed', 'fieldRequired'], 'callLogMessages', ); diff --git a/packages/ringcentral-integration/enums/callLoggerTriggerTypes.js b/packages/ringcentral-integration/enums/callLoggerTriggerTypes.ts similarity index 53% rename from packages/ringcentral-integration/enums/callLoggerTriggerTypes.js rename to packages/ringcentral-integration/enums/callLoggerTriggerTypes.ts index fdcd70bb49..3120a95292 100644 --- a/packages/ringcentral-integration/enums/callLoggerTriggerTypes.js +++ b/packages/ringcentral-integration/enums/callLoggerTriggerTypes.ts @@ -1,6 +1,6 @@ -import HashMap from '../lib/HashMap'; +import { createHashMap } from '../lib/HashMap'; -export default new HashMap({ +export default createHashMap({ manual: 'manual', presenceUpdate: 'presenceUpdate', callLogSync: 'callLogSync', diff --git a/packages/ringcentral-integration/enums/callResults.js b/packages/ringcentral-integration/enums/callResults.ts similarity index 94% rename from packages/ringcentral-integration/enums/callResults.js rename to packages/ringcentral-integration/enums/callResults.ts index 1bf6ac8a07..9b2235381c 100644 --- a/packages/ringcentral-integration/enums/callResults.js +++ b/packages/ringcentral-integration/enums/callResults.ts @@ -1,6 +1,6 @@ -import HashMap from '../lib/HashMap'; +import { createHashMap } from '../lib/HashMap'; -export default new HashMap({ +export default createHashMap({ IPPhoneOffline: 'IP Phone offline', abandoned: 'Abandoned', account: 'Account', diff --git a/packages/ringcentral-integration/enums/calleeTypes.js b/packages/ringcentral-integration/enums/calleeTypes.js deleted file mode 100644 index 55173d913d..0000000000 --- a/packages/ringcentral-integration/enums/calleeTypes.js +++ /dev/null @@ -1,3 +0,0 @@ -import Enum from '../lib/Enum'; - -export default new Enum(['unknown', 'contacts', 'conference'], 'calleeTypes'); diff --git a/packages/ringcentral-integration/enums/calleeTypes.ts b/packages/ringcentral-integration/enums/calleeTypes.ts new file mode 100644 index 0000000000..d5d5296df2 --- /dev/null +++ b/packages/ringcentral-integration/enums/calleeTypes.ts @@ -0,0 +1,3 @@ +import { createEnum } from '../lib/Enum'; + +export default createEnum(['unknown', 'contacts', 'conference'], 'calleeTypes'); diff --git a/packages/ringcentral-integration/enums/conversationLogStatus.js b/packages/ringcentral-integration/enums/conversationLogStatus.js deleted file mode 100644 index b0d25d904e..0000000000 --- a/packages/ringcentral-integration/enums/conversationLogStatus.js +++ /dev/null @@ -1,6 +0,0 @@ -import Enum from 'ringcentral-integration/lib/Enum'; - -export default new Enum( - ['loggedSuccess', 'loggedFailure'], - 'conversationLogStatus', -); diff --git a/packages/ringcentral-integration/enums/conversationLogStatus.ts b/packages/ringcentral-integration/enums/conversationLogStatus.ts new file mode 100644 index 0000000000..7ae9bfba92 --- /dev/null +++ b/packages/ringcentral-integration/enums/conversationLogStatus.ts @@ -0,0 +1,6 @@ +import { createEnum } from '../lib/Enum'; + +export default createEnum( + ['loggedSuccess', 'loggedFailure'], + 'conversationLogStatus', +); diff --git a/packages/ringcentral-integration/enums/extensionStatusTypes.js b/packages/ringcentral-integration/enums/extensionStatusTypes.ts similarity index 73% rename from packages/ringcentral-integration/enums/extensionStatusTypes.js rename to packages/ringcentral-integration/enums/extensionStatusTypes.ts index f65ceb0281..73b3598f2f 100644 --- a/packages/ringcentral-integration/enums/extensionStatusTypes.js +++ b/packages/ringcentral-integration/enums/extensionStatusTypes.ts @@ -1,4 +1,4 @@ -import HashMap from '../lib/HashMap'; +import { createHashMap } from '../lib/HashMap'; /** * @typedef ExtensionStatusTypes @@ -11,7 +11,7 @@ import HashMap from '../lib/HashMap'; /** * @type {ExtensionStatusTypes} */ -export const extensionStatusTypes = new HashMap({ +export const extensionStatusTypes = createHashMap({ enabled: 'Enabled', notActivated: 'NotActivated', disabled: 'Disabled', diff --git a/packages/ringcentral-integration/enums/extensionTypes.js b/packages/ringcentral-integration/enums/extensionTypes.ts similarity index 91% rename from packages/ringcentral-integration/enums/extensionTypes.js rename to packages/ringcentral-integration/enums/extensionTypes.ts index 7109c4a85f..8e1338fae7 100644 --- a/packages/ringcentral-integration/enums/extensionTypes.js +++ b/packages/ringcentral-integration/enums/extensionTypes.ts @@ -1,4 +1,4 @@ -import HashMap from '../lib/HashMap'; +import { createHashMap } from '../lib/HashMap'; /** * @typedef ExtensionTypes @@ -22,7 +22,7 @@ import HashMap from '../lib/HashMap'; /** * @type {ExtensionTypes} */ -const extensionTypes = new HashMap({ +const extensionTypes = createHashMap({ announcement: 'Announcement', applicationExtension: 'ApplicationExtension', bot: 'Bot', diff --git a/packages/ringcentral-integration/enums/messageDirection.js b/packages/ringcentral-integration/enums/messageDirection.js deleted file mode 100644 index 7e3b8fa4ba..0000000000 --- a/packages/ringcentral-integration/enums/messageDirection.js +++ /dev/null @@ -1,6 +0,0 @@ -import HashMap from '../lib/HashMap'; - -export default new HashMap({ - inbound: 'Inbound', - outbound: 'Outbound', -}); diff --git a/packages/ringcentral-integration/enums/messageDirection.ts b/packages/ringcentral-integration/enums/messageDirection.ts new file mode 100644 index 0000000000..f0f62e0a09 --- /dev/null +++ b/packages/ringcentral-integration/enums/messageDirection.ts @@ -0,0 +1,6 @@ +import { createHashMap } from '../lib/HashMap'; + +export default createHashMap({ + inbound: 'Inbound', + outbound: 'Outbound', +}); diff --git a/packages/ringcentral-integration/enums/moduleActionTypes.ts b/packages/ringcentral-integration/enums/moduleActionTypes.ts index 1e5e6a42b8..3aa4599c74 100644 --- a/packages/ringcentral-integration/enums/moduleActionTypes.ts +++ b/packages/ringcentral-integration/enums/moduleActionTypes.ts @@ -14,9 +14,4 @@ export const moduleActionTypes = createEnum([ 'resetSuccess', ]); -export interface ModuleActionTypes { - init: string; - initSuccess: string; - reset: string; - resetSuccess: string; -} +export type ModuleActionTypes = Record; diff --git a/packages/ringcentral-integration/enums/moduleStatuses.js b/packages/ringcentral-integration/enums/moduleStatuses.ts similarity index 50% rename from packages/ringcentral-integration/enums/moduleStatuses.js rename to packages/ringcentral-integration/enums/moduleStatuses.ts index 32921972b3..39cd46f890 100644 --- a/packages/ringcentral-integration/enums/moduleStatuses.js +++ b/packages/ringcentral-integration/enums/moduleStatuses.ts @@ -1,6 +1,6 @@ -import Enum from '../lib/Enum'; +import { createEnum } from '../lib/Enum'; -export default new Enum( +export default createEnum( ['pending', 'initializing', 'ready', 'resetting'], 'module', ); diff --git a/packages/ringcentral-integration/enums/phoneTypes.js b/packages/ringcentral-integration/enums/phoneTypes.ts similarity index 64% rename from packages/ringcentral-integration/enums/phoneTypes.js rename to packages/ringcentral-integration/enums/phoneTypes.ts index 126bd9da5c..02cd256976 100644 --- a/packages/ringcentral-integration/enums/phoneTypes.js +++ b/packages/ringcentral-integration/enums/phoneTypes.ts @@ -1,6 +1,6 @@ -import Enum from '../lib/Enum'; +import { createEnum } from '../lib/Enum'; -export default new Enum([ +export default createEnum([ 'business', 'extension', 'home', diff --git a/packages/ringcentral-integration/enums/presenceStatus.enum.ts b/packages/ringcentral-integration/enums/presenceStatus.enum.ts new file mode 100644 index 0000000000..0499140f6c --- /dev/null +++ b/packages/ringcentral-integration/enums/presenceStatus.enum.ts @@ -0,0 +1,7 @@ +import { createHashMap } from '../lib/HashMap'; + +export const presenceStatus = createHashMap({ + offline: 'Offline', + busy: 'Busy', + available: 'Available', +}); diff --git a/packages/ringcentral-integration/enums/proxyActionTypes.js b/packages/ringcentral-integration/enums/proxyActionTypes.js deleted file mode 100644 index a0b3c9c6b0..0000000000 --- a/packages/ringcentral-integration/enums/proxyActionTypes.js +++ /dev/null @@ -1,3 +0,0 @@ -import Enum from '../lib/Enum'; - -export default new Enum(['proxyInit', 'proxyInitSuccess']); diff --git a/packages/ringcentral-integration/enums/proxyActionTypes.ts b/packages/ringcentral-integration/enums/proxyActionTypes.ts new file mode 100644 index 0000000000..a463145e6b --- /dev/null +++ b/packages/ringcentral-integration/enums/proxyActionTypes.ts @@ -0,0 +1,3 @@ +import { createEnum } from '../lib/Enum'; + +export default createEnum(['proxyInit', 'proxyInitSuccess']); diff --git a/packages/ringcentral-integration/enums/proxyStatuses.js b/packages/ringcentral-integration/enums/proxyStatuses.js deleted file mode 100644 index 3fd8ce6dee..0000000000 --- a/packages/ringcentral-integration/enums/proxyStatuses.js +++ /dev/null @@ -1,3 +0,0 @@ -import Enum from '../lib/Enum'; - -export default new Enum(['pending', 'initializing', 'ready'], 'module'); diff --git a/packages/ringcentral-integration/enums/proxyStatuses.ts b/packages/ringcentral-integration/enums/proxyStatuses.ts new file mode 100644 index 0000000000..f4faa75c8a --- /dev/null +++ b/packages/ringcentral-integration/enums/proxyStatuses.ts @@ -0,0 +1,3 @@ +import { createEnum } from '../lib/Enum'; + +export default createEnum(['pending', 'initializing', 'ready'], 'module'); diff --git a/packages/ringcentral-integration/enums/subscriptionFilters.js b/packages/ringcentral-integration/enums/subscriptionFilters.ts similarity index 79% rename from packages/ringcentral-integration/enums/subscriptionFilters.js rename to packages/ringcentral-integration/enums/subscriptionFilters.ts index 88b346a93b..6afb58c9a8 100644 --- a/packages/ringcentral-integration/enums/subscriptionFilters.js +++ b/packages/ringcentral-integration/enums/subscriptionFilters.ts @@ -1,6 +1,6 @@ -import HashMap from '../lib/HashMap'; +import { createHashMap } from '../lib/HashMap'; -export default new HashMap({ +export default createHashMap({ presence: '/account/~/extension/~/presence', detailedPresence: '/account/~/extension/~/presence?detailedTelephonyState=true&sipData=true&totalActiveCalls', diff --git a/packages/ringcentral-integration/enums/subscriptionHints.js b/packages/ringcentral-integration/enums/subscriptionHints.ts similarity index 79% rename from packages/ringcentral-integration/enums/subscriptionHints.js rename to packages/ringcentral-integration/enums/subscriptionHints.ts index d17ebb77f6..3e4a97259a 100644 --- a/packages/ringcentral-integration/enums/subscriptionHints.js +++ b/packages/ringcentral-integration/enums/subscriptionHints.ts @@ -1,6 +1,6 @@ -import HashMap from '../lib/HashMap'; +import { createHashMap } from '../lib/HashMap'; -const hints = new HashMap({ +const hints = createHashMap({ limits: 'Limits', features: 'Features', accountStatus: 'AccountStatus', diff --git a/packages/ringcentral-integration/enums/syncTypes.js b/packages/ringcentral-integration/enums/syncTypes.js deleted file mode 100644 index 55cd353bdb..0000000000 --- a/packages/ringcentral-integration/enums/syncTypes.js +++ /dev/null @@ -1,6 +0,0 @@ -import HashMap from '../lib/HashMap'; - -export default new HashMap({ - fSync: 'FSync', - iSync: 'ISync', -}); diff --git a/packages/ringcentral-integration/enums/syncTypes.ts b/packages/ringcentral-integration/enums/syncTypes.ts new file mode 100644 index 0000000000..5c779c4c97 --- /dev/null +++ b/packages/ringcentral-integration/enums/syncTypes.ts @@ -0,0 +1,6 @@ +import { createHashMap } from '../lib/HashMap'; + +export default createHashMap({ + fSync: 'FSync', + iSync: 'ISync', +}); diff --git a/packages/ringcentral-integration/enums/telephonyStatus.js b/packages/ringcentral-integration/enums/telephonyStatus.ts similarity index 100% rename from packages/ringcentral-integration/enums/telephonyStatus.js rename to packages/ringcentral-integration/enums/telephonyStatus.ts diff --git a/packages/ringcentral-integration/enums/terminationTypes.js b/packages/ringcentral-integration/enums/terminationTypes.js deleted file mode 100644 index 60b97b66cf..0000000000 --- a/packages/ringcentral-integration/enums/terminationTypes.js +++ /dev/null @@ -1,6 +0,0 @@ -import HashMap from '../lib/HashMap'; - -export default new HashMap({ - final: 'final', - intermediate: 'intermediate', -}); diff --git a/packages/ringcentral-integration/enums/terminationTypes.ts b/packages/ringcentral-integration/enums/terminationTypes.ts new file mode 100644 index 0000000000..b530de5833 --- /dev/null +++ b/packages/ringcentral-integration/enums/terminationTypes.ts @@ -0,0 +1,6 @@ +import { createHashMap } from '../lib/HashMap'; + +export default createHashMap({ + final: 'final', + intermediate: 'intermediate', +}); diff --git a/packages/ringcentral-integration/gulpfile.js b/packages/ringcentral-integration/gulpfile.js index 14a69b8432..551ad97696 100644 --- a/packages/ringcentral-integration/gulpfile.js +++ b/packages/ringcentral-integration/gulpfile.js @@ -104,7 +104,6 @@ export function compile() { .src([ './**/*.js', './**/*.ts', - './**/*.tsx', '!./**/*.d.ts', '!./**/*.test.js', '!./*.js', diff --git a/packages/ringcentral-integration/helpers/meetingHelper.ts b/packages/ringcentral-integration/helpers/meetingHelper.ts index e538b4226f..cf967c8afc 100644 --- a/packages/ringcentral-integration/helpers/meetingHelper.ts +++ b/packages/ringcentral-integration/helpers/meetingHelper.ts @@ -28,6 +28,7 @@ const UTC_TIMEZONE_ID = '1'; const MeetingType = { SCHEDULED: 'Scheduled', RECURRING: 'Recurring', + SCHEDULED_RECURRING: 'ScheduledRecurring', INSTANT: 'Instant', }; diff --git a/packages/ringcentral-integration/integration-test/commons/Phone/index.js b/packages/ringcentral-integration/integration-test/commons/Phone/index.js index 89b042a624..52612eebe7 100644 --- a/packages/ringcentral-integration/integration-test/commons/Phone/index.js +++ b/packages/ringcentral-integration/integration-test/commons/Phone/index.js @@ -14,7 +14,6 @@ import Brand from '../../../modules/Brand'; import Call from '../../../modules/Call'; import CallingSettings from '../../../modules/CallingSettings'; import Contacts from '../../../modules/Contacts'; -import ContactDetails from '../../../modules/ContactDetails'; import ConnectivityMonitor from '../../../modules/ConnectivityMonitor'; import DialingPlan from '../../../modules/DialingPlan'; import ExtensionDevice from '../../../modules/ExtensionDevice'; @@ -121,7 +120,6 @@ import BlockedNumber from '../../../modules/BlockedNumber'; accountContacts, ], }, - { provide: 'ContactDetails', useClass: ContactDetails }, { provide: 'ContactMatcher', useClass: ContactMatcher }, { provide: 'RecentMessages', useClass: RecentMessages }, { provide: 'RecentCalls', useClass: RecentCalls }, diff --git a/packages/ringcentral-integration/lib/MessageTransport/MessageTransport.ts b/packages/ringcentral-integration/lib/MessageTransport/MessageTransport.ts new file mode 100644 index 0000000000..d6a083cbd9 --- /dev/null +++ b/packages/ringcentral-integration/lib/MessageTransport/MessageTransport.ts @@ -0,0 +1,142 @@ +import uuid from 'uuid'; +import TransportBase from '../TransportBase'; + +const DEFAULT_DEVICE = { + addReceiver(receiveMessage, { useCapture = false } = {}) { + window.addEventListener('message', receiveMessage, useCapture); + }, + createEmitter(sendTarget) { + // Always specify an exact target origin, not *, + // when you use postMessage to send data to other windows. + // A malicious site can change the location of the window without your knowledge, + // and therefore it can intercept the data sent using postMessage. + return (message, { targetOrigin = '*', callback } = {} as any) => { + sendTarget.postMessage(message, targetOrigin); + if (typeof callback === 'function') callback(); + }; + }, +}; +export default class MessageTransport extends TransportBase { + private _addReceiver: Function; + private _createEmitter: Function; + private _targetWindow: Window; + private _origin: any; + private _myRequests: Map; + private _othersRequests: Map; + private _postMessage: any; + + constructor({ + addReceiver = DEFAULT_DEVICE.addReceiver, + createEmitter = DEFAULT_DEVICE.createEmitter, + targetWindow = window, + origin, + ...options + }) { + super({ + ...options, + name: 'MessageTransport', + } as any); + this._addReceiver = addReceiver; + this._createEmitter = createEmitter; + this._targetWindow = targetWindow; + this._origin = origin; + this._myRequests = new Map(); + this._othersRequests = new Map(); + this._postMessage = this._createEmitter(this._targetWindow); + this._addReceiver(this._onMessage.bind(this)); + } + + _onMessage = (event) => { + // TODO: confirm if the message is from iframe + if (this._origin && event.origin !== this._origin) { + return; + } + const { type, payload, requestId, result, error } = event.data; + switch (type) { + case this._events.push: + if (payload) { + this.emit(this._events.push, payload); + } + break; + case this._events.response: + if (requestId && this._myRequests.has(requestId)) { + if (error) { + this._myRequests.get(requestId).reject(new Error(error)); + } else { + this._myRequests.get(requestId).resolve(result); + } + } + break; + case this._events.request: + if (requestId && payload) { + this._othersRequests.set(requestId, payload); + this.emit(this._events.request, { + requestId, + payload, + }); + } + break; + default: + break; + } + }; + + addListeners({ push, response, request }) { + if (typeof push === 'function') { + this.on(this._events.push, push); + } + if (typeof response === 'function') { + this.on(this._events.response, response); + } + if (typeof request === 'function') { + this.on(this._events.request, request); + } + } + + async request({ payload }) { + const requestId = uuid.v4(); + let promise = new Promise((resolve, reject) => { + this._myRequests.set(requestId, { + resolve, + reject, + }); + this._postMessage({ + type: this._events.request, + requestId, + payload, + }); + }); + let timeout = setTimeout(() => { + timeout = null; + this._myRequests.get(requestId).reject(new Error(this._events.timeout)); + }, this._timeout); + promise = promise + .then((result) => { + if (timeout) clearTimeout(timeout); + this._myRequests.delete(requestId); + return Promise.resolve(result); + }) + .catch((error) => { + if (timeout) clearTimeout(timeout); + this._myRequests.delete(requestId); + return Promise.reject(error); + }); + return promise; + } + + response({ requestId, result, error }) { + const request = this._othersRequests.get(requestId); + if (request) { + this._othersRequests.delete(requestId); + if (error instanceof Error) { + error = error.message; + } + this._postMessage({ + type: this._events.response, + requestId, + result, + error, + }); + } + } +} diff --git a/packages/ringcentral-integration/lib/MessageTransport/index.ts b/packages/ringcentral-integration/lib/MessageTransport/index.ts index 2977c1166d..f3488bca47 100644 --- a/packages/ringcentral-integration/lib/MessageTransport/index.ts +++ b/packages/ringcentral-integration/lib/MessageTransport/index.ts @@ -1,134 +1,3 @@ -import uuid from 'uuid'; -import TransportBase from '../TransportBase'; +import MessageTransport from './MessageTransport'; -const DEFAULT_DEVICE = { - addReceiver(receiveMessage, { useCapture = false } = {}) { - window.addEventListener('message', receiveMessage, useCapture); - }, - createEmitter(sendTarget) { - // Always specify an exact target origin, not *, - // when you use postMessage to send data to other windows. - // A malicious site can change the location of the window without your knowledge, - // and therefore it can intercept the data sent using postMessage. - return (message, { targetOrigin = '*', callback } = {}) => { - sendTarget.postMessage(message, targetOrigin); - if (typeof callback === 'function') callback(); - }; - }, -}; -export default class MessageTransport extends TransportBase { - constructor({ - addReceiver = DEFAULT_DEVICE.addReceiver, - createEmitter = DEFAULT_DEVICE.createEmitter, - targetWindow = window, - origin, - ...options - }) { - super({ - ...options, - name: 'MessageTransport', - }); - this._addReceiver = addReceiver; - this._createEmitter = createEmitter; - this._targetWindow = targetWindow; - this._origin = origin; - this._myRequests = new Map(); - this._othersRequests = new Map(); - this._postMessage = this._createEmitter(this._targetWindow); - this._addReceiver(this._onMessage.bind(this)); - } - - _onMessage = (event) => { - // TODO: confirm if the message is from iframe - if (this._origin && event.origin !== this._origin) { - return; - } - const { type, payload, requestId, result, error } = event.data; - switch (type) { - case this._events.push: - if (payload) { - this.emit(this._events.push, payload); - } - break; - case this._events.response: - if (requestId && this._myRequests.has(requestId)) { - if (error) { - this._myRequests.get(requestId).reject(new Error(error)); - } else { - this._myRequests.get(requestId).resolve(result); - } - } - break; - case this._events.request: - if (requestId && payload) { - this._othersRequests.set(requestId, payload); - this.emit(this._events.request, { - requestId, - payload, - }); - } - break; - default: - break; - } - }; - - addListeners({ push, response, request }) { - if (typeof push === 'function') { - this.on(this._events.push, push); - } - if (typeof response === 'function') { - this.on(this._events.response, response); - } - if (typeof request === 'function') { - this.on(this._events.request, request); - } - } - - async request({ payload }) { - const requestId = uuid.v4(); - let promise = new Promise((resolve, reject) => { - this._myRequests.set(requestId, { - resolve, - reject, - }); - this._postMessage({ - type: this._events.request, - requestId, - payload, - }); - }); - let timeout = setTimeout(() => { - timeout = null; - this._myRequests.get(requestId).reject(new Error(this._events.timeout)); - }, this._timeout); - promise = promise - .then((result) => { - if (timeout) clearTimeout(timeout); - this._myRequests.delete(requestId); - return Promise.resolve(result); - }) - .catch((error) => { - if (timeout) clearTimeout(timeout); - this._myRequests.delete(requestId); - return Promise.reject(error); - }); - return promise; - } - - response({ requestId, result, error }) { - const request = this._othersRequests.get(requestId); - if (request) { - this._othersRequests.delete(requestId); - if (error instanceof Error) { - error = error.message; - } - this._postMessage({ - type: this._events.response, - requestId, - result, - error, - }); - } - } -} +export default MessageTransport; diff --git a/packages/ringcentral-integration/lib/getIntlDateTimeFormatter/getIntlDateTimeFormatter.ts b/packages/ringcentral-integration/lib/getIntlDateTimeFormatter/getIntlDateTimeFormatter.ts index d322023fd4..d1d6d2a6e7 100644 --- a/packages/ringcentral-integration/lib/getIntlDateTimeFormatter/getIntlDateTimeFormatter.ts +++ b/packages/ringcentral-integration/lib/getIntlDateTimeFormatter/getIntlDateTimeFormatter.ts @@ -49,7 +49,6 @@ export default function getIntlDateTimeFormatter({ case 'time': return getFormatter(locale, timeOptions).format(new Date(utcTimestamp)); default: - console.log('data time'); return getFormatter(locale, dateTimeOptions).format( new Date(utcTimestamp), ); diff --git a/packages/ringcentral-integration/lib/phoneTypeHelper.js b/packages/ringcentral-integration/lib/phoneTypeHelper.ts similarity index 61% rename from packages/ringcentral-integration/lib/phoneTypeHelper.js rename to packages/ringcentral-integration/lib/phoneTypeHelper.ts index b119730bb0..cd70c98524 100644 --- a/packages/ringcentral-integration/lib/phoneTypeHelper.js +++ b/packages/ringcentral-integration/lib/phoneTypeHelper.ts @@ -1,5 +1,7 @@ -import { sort, reduce } from 'ramda'; +import { sort, reduce, filter, addIndex } from 'ramda'; +import Enum from './Enum'; import phoneTypes from '../enums/phoneTypes'; +import { PhoneNumberModel } from '../models/PhoneNumber.model'; export const phoneTypeOrder = Object.freeze([ phoneTypes.extension, @@ -17,7 +19,7 @@ export const phoneTypeOrder = Object.freeze([ ]); export const phoneTypeOrderMap = Object.freeze( - reduce( + addIndex(reduce)( (acc, item, idx) => { acc[item] = idx; return acc; @@ -27,6 +29,10 @@ export const phoneTypeOrderMap = Object.freeze( ), ); -export const sortByPhoneTypes = sort( +export const filterByPhoneTypes = filter((item) => + Enum.hasValue(phoneTypes, item.phoneType), +); + +export const sortByPhoneTypes = sort( (a, b) => phoneTypeOrderMap[a.phoneType] - phoneTypeOrderMap[b.phoneType], ); diff --git a/packages/ringcentral-integration/lib/time.ts b/packages/ringcentral-integration/lib/time.ts new file mode 100644 index 0000000000..a5f362bba1 --- /dev/null +++ b/packages/ringcentral-integration/lib/time.ts @@ -0,0 +1,23 @@ +import sleep from './sleep'; + +export const polling = async (fn, interval) => { + if (typeof fn !== 'function') return; + if (await fn()) return; + await sleep(interval); + await polling(fn, interval); +}; + +export const waitWithCheck = async ( + fn, + { interval = 100, timeout = 1000 * 5 } = {}, +) => { + if (typeof fn !== 'function') return; + await Promise.race([ + polling(fn, interval), + new Promise((_, reject) => setTimeout(reject, timeout)), + ]); +}; + +export const waitForSubscribe = async () => { + await sleep(2.5 * 1000); +}; diff --git a/packages/ringcentral-integration/models/Contact.model.ts b/packages/ringcentral-integration/models/Contact.model.ts new file mode 100644 index 0000000000..8e5e782d3c --- /dev/null +++ b/packages/ringcentral-integration/models/Contact.model.ts @@ -0,0 +1,15 @@ +import { PhoneNumberModel } from './PhoneNumber.model'; +import { PresenceModel } from './Presence.model'; + +// TODO: Define the generic contact type +export interface ContactModel { + name: string; + type: string; + status: string; + phoneNumbers: PhoneNumberModel[]; + emails?: string[]; + presence?: PresenceModel; + profileImageUrl?: string; + company?: string; + jobTitle?: string; +} diff --git a/packages/ringcentral-integration/models/PhoneNumber.model.ts b/packages/ringcentral-integration/models/PhoneNumber.model.ts new file mode 100644 index 0000000000..168cffdb47 --- /dev/null +++ b/packages/ringcentral-integration/models/PhoneNumber.model.ts @@ -0,0 +1,5 @@ +export interface PhoneNumberModel { + phoneNumber: string; + phoneType: string; + rawPhoneNumber?: string; +} diff --git a/packages/ringcentral-integration/models/Presence.model.ts b/packages/ringcentral-integration/models/Presence.model.ts new file mode 100644 index 0000000000..dc2c62f5af --- /dev/null +++ b/packages/ringcentral-integration/models/Presence.model.ts @@ -0,0 +1,6 @@ +export interface PresenceModel { + dndStatus: string; + // meetingStatus is optional as our app does not use it + meetingStatus?: string; + presenceStatus: string; +} diff --git a/packages/ringcentral-integration/models/basePhone.model.ts b/packages/ringcentral-integration/models/basePhone.model.ts index 692334d429..5cfde487b3 100644 --- a/packages/ringcentral-integration/models/basePhone.model.ts +++ b/packages/ringcentral-integration/models/basePhone.model.ts @@ -1,3 +1,4 @@ +import { EvManualDialSettingsUI } from '../../../packages/engage-voice-widget/modules/EvManualDialSettingsUI'; import AlertUI from '../../ringcentral-widgets/modules/AlertUI'; import ConnectivityBadgeUI from '../../ringcentral-widgets/modules/ConnectivityBadgeUI'; import ConnectivityManager from '../../ringcentral-widgets/modules/ConnectivityManager'; @@ -43,12 +44,13 @@ export interface BasePhone { storage: Storage; availabilityMonitor: AvailabilityMonitor; oAuth: OAuth; - settingsUI: SettingsUI; + routerInteraction: RouterInteraction; connectivityManager: ConnectivityManager; + settingsUI: SettingsUI; connectivityBadgeUI: ConnectivityBadgeUI; - routerInteraction: RouterInteraction; loginUI: LoginUI; alertUI: AlertUI; regionSettingsUI: RegionSettingsUI; + evManualDialSettingsUI: EvManualDialSettingsUI; [P: string]: any; } diff --git a/packages/ringcentral-integration/modules/ActiveCallControl/index.js b/packages/ringcentral-integration/modules/ActiveCallControl/index.js index 69294f4077..d30297154f 100644 --- a/packages/ringcentral-integration/modules/ActiveCallControl/index.js +++ b/packages/ringcentral-integration/modules/ActiveCallControl/index.js @@ -121,7 +121,7 @@ export default class ActiveCallControl extends Pollable { }); } else if (this._shouldReset()) { this._resetModuleStatus(); - } else if (this.ready) { + } else if (this.ready && this._hasPermission) { this._subscriptionHandler(); this._checkConnectivity(); this._checkTabActive(); diff --git a/packages/ringcentral-integration/modules/Analytics/index.js b/packages/ringcentral-integration/modules/Analytics/index.js index ddb5dff2c4..58505923ab 100644 --- a/packages/ringcentral-integration/modules/Analytics/index.js +++ b/packages/ringcentral-integration/modules/Analytics/index.js @@ -16,7 +16,8 @@ export const INIT_TRACK_LIST = [ '_callConnected', '_webRTCRegistration', '_smsAttempt', - '_smsSent', + '_smsSentOver', + '_smsSentError', '_logCall', '_logSMS', '_clickToDial', @@ -59,6 +60,9 @@ export const INIT_TRACK_LIST = [ '_callControlClickParticipantArea', '_accountInfoReady', '_schedule', + '_clickToDialPlaceRingOutCall', + '_inboundCallConnectedTrack', + '_outboundCallConnectedTrack', ]; // TODO: refactoring the module against `https://docs.google.com/spreadsheets/d/1xufV6-C-RJR6OJgwFYHYzNQwhIdN4BXXCo8ABs7RT-8/edit#gid=1480480736` @@ -74,7 +78,7 @@ export const INIT_TRACK_LIST = [ { dep: 'Contacts', optional: true }, { dep: 'MessageSender', optional: true }, { dep: 'MessageStore', optional: true }, - { dep: 'ContactDetails', optional: true }, + { dep: 'ContactDetailsUI', optional: true }, { dep: 'CallHistory', optional: true }, { dep: 'Conference', optional: true }, { dep: 'RouterInteraction', optional: true }, @@ -106,7 +110,7 @@ export default class Analytics extends RcModule { callMonitor, conference, conferenceCall, - contactDetails, + contactDetailsUI, contacts, messageSender, messageStore, @@ -141,7 +145,7 @@ export default class Analytics extends RcModule { this._callMonitor = callMonitor; this._conference = conference; this._conferenceCall = conferenceCall; - this._contactDetails = contactDetails; + this._contactDetailsUI = contactDetailsUI; this._contacts = contacts; this._messageSender = messageSender; this._messageStore = messageStore; @@ -174,13 +178,14 @@ export default class Analytics extends RcModule { } track(event, { ...properties }) { + if (!this.analytics) { + return; + } const trackProps = { ...this.trackProps, ...properties, }; - if (this.analytics) { - this.analytics.track(event, trackProps); - } + this.analytics.track(event, trackProps); if (this._useLog) { this._logs.push({ timeStamp: new Date().toISOString(), @@ -222,17 +227,14 @@ export default class Analytics extends RcModule { this.track(`Navigation: View/${eventPostfix}`, trackProps); } - trackSchedule({ router, eventPostfix }) { + trackSchedule({ router }) { const trackProps = { router, appName: this._appName, appVersion: this._appVersion, brand: this._brandCode, }; - this.track( - `Meeting: Click Schedule/${eventPostfix} schedule page`, - trackProps, - ); + this.track('Meeting: Click Schedule/Meeting schedule page', trackProps); } async _onStateChange() { @@ -349,12 +351,21 @@ export default class Analytics extends RcModule { } } - _smsSent(action) { + _smsSentOver(action) { if ( this._messageSender && this._messageSender.actionTypes.sendOver === action.type ) { - this.track('SMS Sent'); + this.track('SMS: SMS sent succesfully'); + } + } + + _smsSentError(action) { + if ( + this._messageSender && + this._messageSender.actionTypes.sendError === action.type + ) { + this.track('SMS: SMS sent failed'); } } @@ -385,6 +396,16 @@ export default class Analytics extends RcModule { } } + _clickToDialPlaceRingOutCall(action) { + if ( + this._adapter && + this._adapter.actionTypes.clickToDial === action.type && + action.callSettingMode !== callingModes.webphone + ) { + this.track('Call: Place RingOut call/Click to Dial '); + } + } + _clickToSMS(action) { if (this._adapter && this._adapter.actionTypes.clickToSMS === action.type) { this.track('Click To SMS'); @@ -517,8 +538,8 @@ export default class Analytics extends RcModule { _contactDetailClickToDial(action) { if ( - this._contactDetails && - this._contactDetails.actionTypes.clickToCall === action.type + this._contactDetailsUI && + this._contactDetailsUI.actionTypes.clickToCall === action.type ) { this.track('Click To Dial (Contact Details)'); } @@ -526,8 +547,8 @@ export default class Analytics extends RcModule { _contactDetailClickToSMS(action) { if ( - this._contactDetails && - this._contactDetails.actionTypes.clickToSMS === action.type + this._contactDetailsUI && + this._contactDetailsUI.actionTypes.clickToSMS === action.type ) { this.track('Click To SMS (Contact Details)'); } @@ -656,6 +677,24 @@ export default class Analytics extends RcModule { } } + _inboundCallConnectedTrack(action) { + if ( + this._callMonitor && + this._callMonitor.actionTypes.inboundCallConnectedTrack === action.type + ) { + this.track('Call: Inbound call connected'); + } + } + + _outboundCallConnectedTrack(action) { + if ( + this._callMonitor && + this._callMonitor.actionTypes.outboundCallConnectedTrack === action.type + ) { + this.track('Call: Outbound RingOut Call connected'); + } + } + _callsOnHoldClickAdd(action) { if ( this._callMonitor && @@ -777,7 +816,7 @@ export default class Analytics extends RcModule { router: '/history', }, { - eventPostfix: 'Call List', + eventPostfix: 'All calls page', router: '/calls', }, { @@ -804,6 +843,18 @@ export default class Analytics extends RcModule { eventPostfix: 'Transfer', router: '/transfer', }, + { + eventPostfix: 'Small call control', + router: '/simplifycallctrl', + }, + { + eventPostfix: 'Flip', + router: '/flip', + }, + { + eventPostfix: 'Add', + router: '/conferenceCall', + }, ]; return targets.find((target) => formatRoute === target.router); } @@ -844,9 +895,9 @@ export default class Analytics extends RcModule { get trackProps() { return { - 'App Name': this._appName, - 'App Version': this._appVersion, - Brand: this._brandCode, + appName: this._appName, + appVersion: this._appVersion, + brand: this._brandCode, 'App Language': this._locale ? this._locale.currentLocale : '', 'Browser Language': this._locale ? this._locale.browserLocale : '', 'Extension Type': this._extensionInfo diff --git a/packages/ringcentral-integration/modules/Call/actionTypes.js b/packages/ringcentral-integration/modules/Call/actionTypes.ts similarity index 80% rename from packages/ringcentral-integration/modules/Call/actionTypes.js rename to packages/ringcentral-integration/modules/Call/actionTypes.ts index 389cd8ca98..299c8505c4 100644 --- a/packages/ringcentral-integration/modules/Call/actionTypes.js +++ b/packages/ringcentral-integration/modules/Call/actionTypes.ts @@ -1,7 +1,7 @@ -import Enum from '../../lib/Enum'; +import { createEnum } from '../../lib/Enum'; import { moduleActionTypes } from '../../enums/moduleActionTypes'; -export default new Enum( +export default createEnum( [ ...Object.keys(moduleActionTypes), 'toNumberChanged', diff --git a/packages/ringcentral-integration/modules/Call/callErrors.js b/packages/ringcentral-integration/modules/Call/callErrors.ts similarity index 75% rename from packages/ringcentral-integration/modules/Call/callErrors.js rename to packages/ringcentral-integration/modules/Call/callErrors.ts index d0aca02096..bfad973567 100644 --- a/packages/ringcentral-integration/modules/Call/callErrors.js +++ b/packages/ringcentral-integration/modules/Call/callErrors.ts @@ -1,6 +1,6 @@ -import Enum from '../../lib/Enum'; +import { createEnum } from '../../lib/Enum'; -export default new Enum( +export default createEnum( [ 'noToNumber', 'noAreaCode', diff --git a/packages/ringcentral-integration/modules/Call/callStatus.js b/packages/ringcentral-integration/modules/Call/callStatus.js deleted file mode 100644 index 9f3cfc0664..0000000000 --- a/packages/ringcentral-integration/modules/Call/callStatus.js +++ /dev/null @@ -1,3 +0,0 @@ -import Enum from '../../lib/Enum'; - -export default new Enum(['idle', 'connecting'], 'callStatus'); diff --git a/packages/ringcentral-integration/modules/Call/callStatus.ts b/packages/ringcentral-integration/modules/Call/callStatus.ts new file mode 100644 index 0000000000..72ebfe8ac8 --- /dev/null +++ b/packages/ringcentral-integration/modules/Call/callStatus.ts @@ -0,0 +1,3 @@ +import { createEnum } from '../../lib/Enum'; + +export default createEnum(['idle', 'connecting'], 'callStatus'); diff --git a/packages/ringcentral-integration/modules/Call/getCallReducer.js b/packages/ringcentral-integration/modules/Call/getCallReducer.ts similarity index 100% rename from packages/ringcentral-integration/modules/Call/getCallReducer.js rename to packages/ringcentral-integration/modules/Call/getCallReducer.ts diff --git a/packages/ringcentral-integration/modules/CallMonitor/actionTypes.js b/packages/ringcentral-integration/modules/CallMonitor/actionTypes.js index a245fdf668..f2e68fb952 100644 --- a/packages/ringcentral-integration/modules/CallMonitor/actionTypes.js +++ b/packages/ringcentral-integration/modules/CallMonitor/actionTypes.js @@ -19,6 +19,8 @@ export default new Enum( 'callsOnHoldClickHangupTrack', 'callControlClickParticipantAreaClickTrack', 'mergeControlClickHangupTrack', + 'inboundCallConnectedTrack', + 'outboundCallConnectedTrack', ], 'callMonitorAcionTypes', ); diff --git a/packages/ringcentral-integration/modules/CallMonitor/index.js b/packages/ringcentral-integration/modules/CallMonitor/index.js index 5680bc0c7a..bf21be3da2 100644 --- a/packages/ringcentral-integration/modules/CallMonitor/index.js +++ b/packages/ringcentral-integration/modules/CallMonitor/index.js @@ -22,6 +22,7 @@ import { selector } from '../../lib/selector'; import { isRinging, + isInbound, hasRingingCalls, sortByStartTime, isRingingInboundCall, @@ -259,12 +260,24 @@ export default class CallMonitor extends RcModule { const oldCall = oldCalls[oldCallIndex]; oldCalls.splice(oldCallIndex, 1); if ( - (call.telephonyStatus !== oldCall.telephonyStatus || - (oldCall.from && oldCall.from.phoneNumber) !== - (call.from && call.from.phoneNumber)) && - typeof this._onCallUpdated === 'function' + call.telephonyStatus !== oldCall.telephonyStatus || + (oldCall.from && oldCall.from.phoneNumber) !== + (call.from && call.from.phoneNumber) ) { - this._onCallUpdated(call); + if (typeof this._onCallUpdated === 'function') { + this._onCallUpdated(call); + } + if (call.telephonyStatus === 'CallConnected') { + if (isInbound(call)) { + this.store.dispatch({ + type: this.actionTypes.inboundCallConnectedTrack, + }); + } else { + this.store.dispatch({ + type: this.actionTypes.outboundCallConnectedTrack, + }); + } + } } } find((entity, index) => { diff --git a/packages/ringcentral-integration/modules/ContactDetails/actionTypes.js b/packages/ringcentral-integration/modules/ContactDetails/actionTypes.js deleted file mode 100644 index a3e0750052..0000000000 --- a/packages/ringcentral-integration/modules/ContactDetails/actionTypes.js +++ /dev/null @@ -1,13 +0,0 @@ -import Enum from '../../lib/Enum'; -import { moduleActionTypes } from '../../enums/moduleActionTypes'; - -export default new Enum( - [ - ...Object.keys(moduleActionTypes), - 'updateCondition', - 'resetCondition', - 'clickToSMS', - 'clickToCall', - ], - 'contactDetails', -); diff --git a/packages/ringcentral-integration/modules/ContactDetails/getContactDetailsReducer.js b/packages/ringcentral-integration/modules/ContactDetails/getContactDetailsReducer.js deleted file mode 100644 index bfa9c0b620..0000000000 --- a/packages/ringcentral-integration/modules/ContactDetails/getContactDetailsReducer.js +++ /dev/null @@ -1,23 +0,0 @@ -import { combineReducers } from 'redux'; -import getModuleStatusReducer from '../../lib/getModuleStatusReducer'; - -export function getContactSearchConditions(types) { - return (state = null, { type, condition }) => { - switch (type) { - case types.updateCondition: - if (condition) return condition; - return state; - case types.resetCondition: - return null; - default: - return state; - } - }; -} - -export default function getContactDetailsReducer(types) { - return combineReducers({ - status: getModuleStatusReducer(types), - condition: getContactSearchConditions(types), - }); -} diff --git a/packages/ringcentral-integration/modules/ContactDetails/index.js b/packages/ringcentral-integration/modules/ContactDetails/index.js deleted file mode 100644 index 49ec4f6e2f..0000000000 --- a/packages/ringcentral-integration/modules/ContactDetails/index.js +++ /dev/null @@ -1,146 +0,0 @@ -import { filter, reduce } from 'ramda'; -import RcModule from '../../lib/RcModule'; -import { Module } from '../../lib/di'; -import { selector } from '../../lib/selector'; -import actionTypes from './actionTypes'; -import getContactDetailsReducer from './getContactDetailsReducer'; -import proxify from '../../lib/proxy/proxify'; -import background from '../../lib/background'; -import phoneTypes from '../../enums/phoneTypes'; -import { phoneTypeOrder } from '../../lib/phoneTypeHelper'; - -@Module({ - deps: ['Contacts', { dep: 'ContactDetailsOptions', optional: true }], -}) -export default class ContactDetails extends RcModule { - constructor({ contacts, ...options }) { - super({ ...options, actionTypes }); - - this._contacts = contacts; - this._reducer = getContactDetailsReducer(this.actionTypes); - } - - initialize() { - this.store.subscribe(() => this._onStateChange()); - } - - _onStateChange() { - if (this._shouldInit()) { - this.store.dispatch({ - type: this.actionTypes.initSuccess, - }); - } else if (this._shouldReset()) { - this.store.dispatch({ - type: this.actionTypes.resetSuccess, - }); - } - } - - _shouldInit() { - return this._contacts.ready && this.pending; - } - - _shouldReset() { - return !this._contacts.ready && this.ready; - } - - /** - * Find contact from all contacts by given conditions. - * Stores search conditions to reducers. - */ - @background - find({ id, type }) { - this.store.dispatch({ - type: this.actionTypes.updateCondition, - condition: { - id, - type, - }, - }); - } - - @background - clear() { - this.store.dispatch({ - type: this.actionTypes.resetCondition, - }); - } - - @background - getProfileImage(contact) { - return this._contacts.getProfileImage(contact, false); - } - - @background - getPresence(contact) { - return this._contacts.getPresence(contact, false); - } - - // for track click to sms in contact detail - @proxify - onClickToSMS() { - this.store.dispatch({ - type: this.actionTypes.clickToSMS, - }); - } - - // for track click to call in contact detail - @proxify - onClickToCall() { - this.store.dispatch({ - type: this.actionTypes.clickToCall, - }); - } - - @selector - currentContact = [ - () => this.condition, - () => this._contacts.allContacts, - (condition) => { - if (condition) { - return this._contacts.find(condition); - } - return null; - }, - ]; - - @selector - contact = [ - () => this.currentContact, - (currentContact) => { - if (!currentContact) return null; - let phoneNumbers; - if ( - currentContact.rawPhoneNumbers && - currentContact.rawPhoneNumbers.length > 0 - ) { - phoneNumbers = currentContact.rawPhoneNumbers; - } else { - phoneNumbers = currentContact.phoneNumbers; - } - const phoneMaps = reduce( - (acc, phoneNumberElm) => { - acc[phoneNumberElm.phoneType] = acc[phoneNumberElm.phoneType] || []; - acc[phoneNumberElm.phoneType].push(phoneNumberElm); - return acc; - }, - {}, - phoneNumbers, - ); - - const schema = filter( - (key) => !!phoneTypes[key] && Array.isArray(phoneMaps[key]), - phoneTypeOrder, - ); - return { ...currentContact, schema, phoneMaps }; - }, - ]; - - get condition() { - return this.state.condition; - } - - get status() { - return this.state.status; - } -} diff --git a/packages/ringcentral-integration/modules/ConversationLogger/index.js b/packages/ringcentral-integration/modules/ConversationLogger/index.js index 147820dcd2..9358644ce1 100644 --- a/packages/ringcentral-integration/modules/ConversationLogger/index.js +++ b/packages/ringcentral-integration/modules/ConversationLogger/index.js @@ -92,8 +92,8 @@ export default class ConversationLogger extends LoggerBase { this._isAutoUpdate = isAutoUpdate; this._accordWithLogRequirement = accordWithLogRequirement; this._storageKey = `${this._name}Data`; - this._messageStore.onMessageUpdated(() => { - this._processConversationLogMap(); + this._messageStore.onMessageUpdated((record) => { + this._processConversationLogMap(record); }); this._storage.registerReducer({ key: this._storageKey, diff --git a/packages/ringcentral-integration/modules/Meeting/meeting.ts b/packages/ringcentral-integration/modules/Meeting/meeting.ts index f687f0be89..5960e1727a 100644 --- a/packages/ringcentral-integration/modules/Meeting/meeting.ts +++ b/packages/ringcentral-integration/modules/Meeting/meeting.ts @@ -396,6 +396,7 @@ export class Meeting extends RcModule { audioOptions, password, schedule, + recurrence, } = meeting; const formatted: ScheduleMeetingModel = { topic, @@ -405,6 +406,7 @@ export class Meeting extends RcModule { startParticipantsVideo, audioOptions, password, + recurrence, }; // Recurring meetings do not have schedule info if (meetingType !== MeetingType.RECURRING) { @@ -418,6 +420,10 @@ export class Meeting extends RcModule { _schedule.startTime = moment.utc(schedule.startTime).format(); } formatted.schedule = _schedule; + + if(recurrence && recurrence.until) { + formatted.recurrence.until = moment.utc(recurrence.until).format(); + } } return formatted; } @@ -501,6 +507,13 @@ export interface ScheduleModel { startTime?: string; } +export interface RecurrenceOptions { + frequency: string; + interval: string | number; + count?: number; + until?: string; // "2030-12-21T12:00:00Z" +} + export interface ScheduleMeetingModel { topic: string; meetingType: any; @@ -510,4 +523,5 @@ export interface ScheduleMeetingModel { audioOptions: any; password: any; schedule?: ScheduleModel; + recurrence?: RecurrenceOptions; } diff --git a/packages/ringcentral-integration/modules/Presence/index.js b/packages/ringcentral-integration/modules/Presence/index.js index 792309eae2..f3434eadef 100644 --- a/packages/ringcentral-integration/modules/Presence/index.js +++ b/packages/ringcentral-integration/modules/Presence/index.js @@ -9,7 +9,7 @@ import debounce from '../../lib/debounce'; import { getDataReducer } from './getPresenceReducer'; import subscriptionFilters from '../../enums/subscriptionFilters'; import dndStatus from './dndStatus'; -import presenceStatus from './presenceStatus'; +import { presenceStatus } from '../../enums/presenceStatus.enum'; import proxify from '../../lib/proxy/proxify'; import ensureExist from '../../lib/ensureExist'; diff --git a/packages/ringcentral-integration/modules/Presence/presenceStatus.js b/packages/ringcentral-integration/modules/Presence/presenceStatus.js deleted file mode 100644 index 130c0a12e1..0000000000 --- a/packages/ringcentral-integration/modules/Presence/presenceStatus.js +++ /dev/null @@ -1,7 +0,0 @@ -import HashMap from '../../lib/HashMap'; - -export default new HashMap({ - offline: 'Offline', - busy: 'Busy', - available: 'Available', -}); diff --git a/packages/ringcentral-integration/package.json b/packages/ringcentral-integration/package.json index 38a5c5ba13..86b413e3d1 100644 --- a/packages/ringcentral-integration/package.json +++ b/packages/ringcentral-integration/package.json @@ -86,7 +86,7 @@ "json-mask": "^0.3.8", "localforage": "^1.7.3", "moment": "^2.24.0", - "prettier": "^1.7.0", + "prettier": "^1.19.1", "ramda": "^0.26.1", "redux": "^4.0.4", "reselect": "^2.5.4", diff --git a/packages/ringcentral-widgets-demo/dev-server/Phone.js b/packages/ringcentral-widgets-demo/dev-server/Phone.js index 9a078e9522..386573a309 100644 --- a/packages/ringcentral-widgets-demo/dev-server/Phone.js +++ b/packages/ringcentral-widgets-demo/dev-server/Phone.js @@ -17,7 +17,6 @@ import Call from 'ringcentral-integration/modules/Call'; import CallingSettings from 'ringcentral-integration/modules/CallingSettings'; import CallCtrlUI from 'ringcentral-widgets/modules/CallCtrlUI'; import Contacts from 'ringcentral-integration/modules/Contacts'; -import ContactDetails from 'ringcentral-integration/modules/ContactDetails'; import ConnectivityMonitor from 'ringcentral-integration/modules/ConnectivityMonitor'; import DialingPlan from 'ringcentral-integration/modules/DialingPlan'; import ExtensionDevice from 'ringcentral-integration/modules/ExtensionDevice'; @@ -67,7 +66,7 @@ import DialerUI from 'ringcentral-widgets/modules/DialerUI'; import ConferenceDialerUI from 'ringcentral-widgets/modules/ConferenceDialerUI'; import ConferenceUI from 'ringcentral-widgets/modules/ConferenceUI'; import MeetingUI from 'ringcentral-widgets/modules/MeetingUI'; -import ContactDetailsUI from 'ringcentral-widgets/modules/ContactDetailsUI'; +import { ContactDetailsUI } from 'ringcentral-widgets/modules/ContactDetailsUI'; import ProxyFrameOAuth from 'ringcentral-widgets/modules/ProxyFrameOAuth'; import AudioSettingsUI from 'ringcentral-widgets/modules/AudioSettingsUI'; import RegionSettingsUI from 'ringcentral-widgets/modules/RegionSettingsUI'; @@ -92,6 +91,7 @@ import UserGuideUI from 'ringcentral-widgets/modules/UserGuideUI'; import { hashHistory } from 'react-router'; import AlertUI from 'ringcentral-widgets/modules/AlertUI'; import FlipUI from 'ringcentral-widgets/modules/FlipUI'; +import TransferUI from 'ringcentral-widgets/modules/TransferUI'; const history = global.process && @@ -170,7 +170,6 @@ const history = accountContacts, ], }, - { provide: 'ContactDetails', useClass: ContactDetails }, { provide: 'ContactMatcher', useClass: ContactMatcher }, { provide: 'RecentMessages', useClass: RecentMessages }, { provide: 'RecentCalls', useClass: RecentCalls }, @@ -193,6 +192,7 @@ const history = { provide: 'FlipUI', useClass: FlipUI }, { provide: 'CallBadgeUI', useClass: CallBadgeUI }, { provide: 'CallHistoryUI', useClass: CallHistoryUI }, + { provide: 'TransferUI', useClass: TransferUI }, { provide: 'Feedback', useClass: Feedback }, { provide: 'UserGuide', useClass: UserGuide }, { provide: 'ActiveCallControl', useClass: ActiveCallControl }, diff --git a/packages/ringcentral-widgets-demo/dev-server/containers/App/index.js b/packages/ringcentral-widgets-demo/dev-server/containers/App/index.js index d76db62064..d0ab6f98d1 100644 --- a/packages/ringcentral-widgets-demo/dev-server/containers/App/index.js +++ b/packages/ringcentral-widgets-demo/dev-server/containers/App/index.js @@ -285,7 +285,10 @@ export default function App({ phone, icon }) { navigateTo={(path) => { phone.routerInteraction.push(path); }} - contact={phone.contactDetails.contact} + contact={phone.contactDetailsUI.getContact({ + id: routerProps.params.contactId, + type: routerProps.params.contactType, + })} useContact /> diff --git a/packages/ringcentral-widgets-test/test/integration-test/Meeting/ScheduleMeeting.spec.js b/packages/ringcentral-widgets-test/test/integration-test/Meeting/ScheduleMeeting.spec.js index 375061b60e..d4fb6fe43f 100644 --- a/packages/ringcentral-widgets-test/test/integration-test/Meeting/ScheduleMeeting.spec.js +++ b/packages/ringcentral-widgets-test/test/integration-test/Meeting/ScheduleMeeting.spec.js @@ -97,9 +97,11 @@ describe('Schedule Meeting', () => { MeetingType.SCHEDULED, ); typeField.props().onChange(true); - expect(app.props().phone.meeting.meeting.meetingType).toBe( - MeetingType.RECURRING, - ); + const meetingType = app.props().phone.meeting.meeting.meetingType; + expect( + meetingType === MeetingType.RECURRING || + meetingType === MeetingType.SCHEDULED_RECURRING, + ).toBe(true); }); test('