diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 660720d34c..09a99623b5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,11 +3,11 @@ name: CI Pipeline on: [push, pull_request] jobs: - phone-number-test: + tests: runs-on: ubuntu-latest strategy: matrix: - node-version: [10.x] + node-version: [14.x] steps: - name: Checkout uses: actions/checkout@v2 @@ -19,137 +19,35 @@ jobs: node-version: ${{ matrix.node-version }} - run: yarn - run: yarn workspace @ringcentral-integration/phone-number test - i18n-test: - runs-on: ubuntu-latest - strategy: - matrix: - node-version: [10.x] - steps: - - name: Checkout - uses: actions/checkout@v2 - with: - persist-credentials: false - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v1 - with: - node-version: ${{ matrix.node-version }} - - run: yarn - run: yarn workspace @ringcentral-integration/i18n test - locale-loader-test: - runs-on: ubuntu-latest - strategy: - matrix: - node-version: [10.x] - steps: - - name: Checkout - uses: actions/checkout@v2 - with: - persist-credentials: false - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v1 - with: - node-version: ${{ matrix.node-version }} - - run: yarn - run: yarn workspace @ringcentral-integration/locale-loader test - core-test: - runs-on: ubuntu-latest - strategy: - matrix: - node-version: [10.x] - steps: - - name: Checkout - uses: actions/checkout@v2 - with: - persist-credentials: false - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v1 - with: - node-version: ${{ matrix.node-version }} - - run: yarn - run: yarn workspace @ringcentral-integration/core test - integration-test: - runs-on: ubuntu-latest - strategy: - matrix: - node-version: [10.x] - steps: - - name: Checkout - uses: actions/checkout@v2 - with: - persist-credentials: false - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v1 - with: - node-version: ${{ matrix.node-version }} - - run: yarn - run: yarn workspace @ringcentral-integration/commons test - commons-branch-release: - needs: integration-test - if: ${{ github.ref == 'refs/heads/master' && github.event_name == 'push' }} - runs-on: ubuntu-latest - strategy: - matrix: - node-version: [10.x] - steps: - - name: Checkout - uses: actions/checkout@v2 - with: - persist-credentials: false - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v1 - with: - node-version: ${{ matrix.node-version }} - - run: yarn - - run: yarn workspace @ringcentral-integration/commons release - - name: Commons Branch Release - uses: JamesIves/github-pages-deploy-action@3.7.1 - with: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - BRANCH: commons-release - FOLDER: release/ringcentral-integration - CLEAN: true - widgets-branch-release: - needs: integration-test + - run: yarn workspace @ringcentral-integration/widgets test + - run: yarn workspace ringcentral-widgets-test test:jest + + branch-release: + needs: tests if: ${{ github.ref == 'refs/heads/master' && github.event_name == 'push' }} runs-on: ubuntu-latest - strategy: - matrix: - node-version: [10.x] steps: - name: Checkout uses: actions/checkout@v2 with: persist-credentials: false - - name: Use Node.js ${{ matrix.node-version }} + - name: Use Node.js 14.x uses: actions/setup-node@v1 with: - node-version: ${{ matrix.node-version }} + node-version: 14.x - run: yarn - - run: yarn workspace @ringcentral-integration/widgets release - - name: Widgets Branch Release + - run: yarn workspace @ringcentral-integration/core release + - name: Core Branch Release uses: JamesIves/github-pages-deploy-action@3.7.1 with: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - BRANCH: widgets-release - FOLDER: release/ringcentral-widgets + BRANCH: core-release + FOLDER: release/core CLEAN: true - i18n-branch-release: - needs: i18n-test - if: ${{ github.ref == 'refs/heads/master' && github.event_name == 'push' }} - runs-on: ubuntu-latest - strategy: - matrix: - node-version: [10.x] - steps: - - name: Checkout - uses: actions/checkout@v2 - with: - persist-credentials: false - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v1 - with: - node-version: ${{ matrix.node-version }} - - run: yarn - run: yarn workspace @ringcentral-integration/i18n release - name: I18n Branch Release uses: JamesIves/github-pages-deploy-action@3.7.1 @@ -158,23 +56,6 @@ jobs: BRANCH: i18n-release FOLDER: release/i18n CLEAN: true - locale-loader-branch-release: - needs: locale-loader-test - if: ${{ github.ref == 'refs/heads/master' && github.event_name == 'push' }} - runs-on: ubuntu-latest - strategy: - matrix: - node-version: [10.x] - steps: - - name: Checkout - uses: actions/checkout@v2 - with: - persist-credentials: false - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v1 - with: - node-version: ${{ matrix.node-version }} - - run: yarn - run: yarn workspace @ringcentral-integration/locale-loader release - name: Locale Loader Branch Release uses: JamesIves/github-pages-deploy-action@3.7.1 @@ -183,23 +64,6 @@ jobs: BRANCH: locale-loader-release FOLDER: release/locale-loader CLEAN: true - phone-number-branch-release: - needs: phone-number-test - if: ${{ github.ref == 'refs/heads/master' && github.event_name == 'push' }} - runs-on: ubuntu-latest - strategy: - matrix: - node-version: [10.x] - steps: - - name: Checkout - uses: actions/checkout@v2 - with: - persist-credentials: false - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v1 - with: - node-version: ${{ matrix.node-version }} - - run: yarn - run: yarn workspace @ringcentral-integration/phone-number release - name: Phone Number Branch Release uses: JamesIves/github-pages-deploy-action@3.7.1 @@ -208,73 +72,22 @@ jobs: BRANCH: phone-number-release FOLDER: release/phone-number CLEAN: true - glip-widgets-branch-release: - needs: integration-test - if: ${{ github.ref == 'refs/heads/master' && github.event_name == 'push' }} - runs-on: ubuntu-latest - strategy: - matrix: - node-version: [10.x] - steps: - - name: Checkout - uses: actions/checkout@v2 - with: - persist-credentials: false - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v1 - with: - node-version: ${{ matrix.node-version }} - - run: yarn - - run: yarn workspace @ringcentral-integration/glip-widgets release - - name: Glip Widgets Branch Release + - run: yarn workspace @ringcentral-integration/commons release + - name: Commons Branch Release uses: JamesIves/github-pages-deploy-action@3.7.1 with: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - BRANCH: glip-widgets-release - FOLDER: release/glip-widgets + BRANCH: commons-release + FOLDER: release/ringcentral-integration CLEAN: true - core-branch-release: - needs: core-test - if: ${{ github.ref == 'refs/heads/master' && github.event_name == 'push' }} - runs-on: ubuntu-latest - strategy: - matrix: - node-version: [10.x] - steps: - - name: Checkout - uses: actions/checkout@v2 - with: - persist-credentials: false - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v1 - with: - node-version: ${{ matrix.node-version }} - - run: yarn - - run: yarn workspace @ringcentral-integration/core release - - name: Core Branch Release + - run: yarn workspace @ringcentral-integration/widgets release + - name: Widgets Branch Release uses: JamesIves/github-pages-deploy-action@3.7.1 with: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - BRANCH: core-release - FOLDER: release/core + BRANCH: widgets-release + FOLDER: release/ringcentral-widgets CLEAN: true - engage-voice-widgets-branch-release: - needs: integration-test - if: ${{ github.ref == 'refs/heads/master' && github.event_name == 'push' }} - runs-on: ubuntu-latest - strategy: - matrix: - node-version: [10.x] - steps: - - name: Checkout - uses: actions/checkout@v2 - with: - persist-credentials: false - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v1 - with: - node-version: ${{ matrix.node-version }} - - run: yarn - run: yarn workspace @ringcentral-integration/engage-voice-widgets release - name: Engage Voice-widgets Release uses: JamesIves/github-pages-deploy-action@3.7.1 @@ -283,3 +96,11 @@ jobs: BRANCH: engage-voice-widgets-release FOLDER: release/engage-voice-widgets CLEAN: true + - run: yarn workspace @ringcentral-integration/glip-widgets release + - name: Glip Widgets Branch Release + uses: JamesIves/github-pages-deploy-action@3.7.1 + with: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + BRANCH: glip-widgets-release + FOLDER: release/glip-widgets + CLEAN: true diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1740500481..d0a09bbf54 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -16,7 +16,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v1 with: - node-version: '10.x' + node-version: '14.x' registry-url: 'https://registry.npmjs.org' - name: Get the version id: get_version @@ -39,7 +39,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v1 with: - node-version: '10.x' + node-version: '14.x' registry-url: 'https://registry.npmjs.org' - name: Get the version id: get_version @@ -62,7 +62,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v1 with: - node-version: '10.x' + node-version: '14.x' registry-url: 'https://registry.npmjs.org' - name: Get the version id: get_version @@ -85,7 +85,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v1 with: - node-version: '10.x' + node-version: '14.x' registry-url: 'https://registry.npmjs.org' - name: Get the version id: get_version @@ -108,7 +108,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v1 with: - node-version: '10.x' + node-version: '14.x' - run: yarn - run: yarn workspace ringcentral-widgets-docs build - name: Widgets Docs Release diff --git a/.gitignore b/.gitignore index 85a14018d9..9feb53a0dc 100644 --- a/.gitignore +++ b/.gitignore @@ -61,3 +61,5 @@ alias.json */**/gh-pages */**/junit.xml + +*/**/html-report diff --git a/.sync b/.sync index 5290df3110..94f2eedf6a 100644 --- a/.sync +++ b/.sync @@ -1 +1 @@ -3acdd2ba8063150decb73c3ba2accf04da2c8f5e +3bc468af3daaeb57779ea6e6fe239e75a4d45cfa diff --git a/packages/babel-settings/lib/crius.js b/packages/babel-settings/lib/crius.js index c3189723d0..3e6dad74d5 100644 --- a/packages/babel-settings/lib/crius.js +++ b/packages/babel-settings/lib/crius.js @@ -1,4 +1,4 @@ -module.exports = require('babel-jest').createTransformer({ +module.exports = require('babel-jest').default.createTransformer({ presets: [['@babel/preset-env'], ['babel-preset-crius']], plugins: [['@babel/plugin-proposal-decorators', { legacy: true }]], ignore: [/node_modules/], diff --git a/packages/babel-settings/package.json b/packages/babel-settings/package.json index 56f98b1384..fca8dbd362 100644 --- a/packages/babel-settings/package.json +++ b/packages/babel-settings/package.json @@ -27,7 +27,7 @@ "@babel/register": "^7.10.5", "babel-plugin-const-enum": "^1.0.1", "core-js": "^2.6.11", - "typescript": "^4.2.3" + "typescript": "^4.3.5" }, "peerDependencies": { "@babel/polyfill": "^7.10.4", diff --git a/packages/core/README.md b/packages/core/README.md index 1bc892e711..cfbd91bbec 100644 --- a/packages/core/README.md +++ b/packages/core/README.md @@ -103,6 +103,67 @@ class Auth extends RcModuleV2 { `@action` is used to decorate a method that changes the state of the module (Executing it will dispatch a Redux action), and it does **NOT** support asynchronous methods. + +- The @action decorated method should have **no side effects**. + +```ts +class ContactsList extends RcModuleV2 { + constructor(deps: Deps) { + super({ + deps, + }); + } + + @state + contacts: Contact[] = []; + + @action + addContacts(contacts: Contact[]) { // ❌ bad practice + contacts.forEach(() => { + // fetch avatar + }) + // .... + } + + onInitOnce() { // ✅ good practice + watch( + this, + () => this.contacts, + () => { + // fetch avatar + } + ) + } +} +``` + +- The state operations in the methods decorated by @action should be **mutation updates* as possible to ensure patch minimization. + +```ts +class ContactsList extends RcModuleV2 { + constructor(deps: Deps) { + super({ + deps, + }); + } + + @state + contacts: Contact[] = []; + + @action + addContact(contact: Contact) { + // ❌ bad practice + this.contacts = [...this.contacts, contact]; + } + + @action + addContact(contact: Contact) { + // ✅ good practice + this.contacts.push(contact); + } +} +``` + #### computed Use `@computed(callback)`, you should make sure that the return value of its callback function is an `Array` of dependency collections. diff --git a/packages/core/lib/RcModule/RcModule.ts b/packages/core/lib/RcModule/RcModule.ts index 881bdd58ef..c4569111db 100644 --- a/packages/core/lib/RcModule/RcModule.ts +++ b/packages/core/lib/RcModule/RcModule.ts @@ -1,27 +1,27 @@ import { combineReducers, ReducersMapObject } from 'redux'; import { - state, action, - subscribe, + Action, + applyPatches, computed, createStore, - watch, - watchEffect, - Service, - storeKey, - identifierKey, - Action, - stateKey, - getStagedState, + enableES5, enablePatches, + getStagedState, + identifierKey, + Service, + setAutoFreeze, setPatchesToggle, - subscriptionsKey, - Subscription, + state, + stateKey, Store, - setAutoFreeze, - applyPatches, + storeKey, + subscribe, + Subscription, + subscriptionsKey, usm as usmAction, - enableES5, + watch, + watchEffect, } from '../usm-redux'; setAutoFreeze(false); @@ -37,7 +37,7 @@ export const enum ModuleStatus { export const onceKey: unique symbol = Symbol('once'); export const onInitOnceKey: unique symbol = Symbol('onInitOnce'); -export const noReadyModulesKey: unique symbol = Symbol('noReadyModules'); +export const notReadyModulesKey: unique symbol = Symbol('notReadyModules'); export const checkStatusChangeKey: unique symbol = Symbol('checkStatusChange'); export const enableCacheKey: unique symbol = Symbol('enableCache'); export const enableGlobalCacheKey: unique symbol = Symbol('enableGlobalCache'); @@ -50,6 +50,9 @@ export const spawnReducersKey: unique symbol = Symbol('spawnReducers'); export const spawnStorageReducersKey: unique symbol = Symbol( 'spawnStorageReducers', ); +export const ignoreReadyModulesKey: unique symbol = Symbol( + 'ignoreReadyModules', +); export interface RcModuleOptions { deps?: T & { @@ -81,6 +84,12 @@ abstract class RcModuleV2 { private [enableGlobalCacheKey]: boolean; + /** + * background/client transport for browser extension + */ + protected _transport?: any; // TODO: add transport type + private [ignoreReadyModulesKey] = new Set(); + protected initializeProxy?(): Promise | void; /** * `onInit` life cycle for current initialization before all deps modules are all ready. @@ -176,21 +185,28 @@ abstract class RcModuleV2 { } } - private get [noReadyModulesKey]() { + protected _ignoreModuleReadiness(dep: RcModuleV2) { + this[ignoreReadyModulesKey].add(dep); + } + + private get [notReadyModulesKey]() { const modules = Object.values(this._deps || {}).filter( // In order to be compatible with RcModuleV1 (module: RcModuleV2) => module && typeof module.ready !== 'undefined', ); - return modules.filter((module: RcModuleV2) => !module.ready); + return modules.filter( + (module: RcModuleV2) => + !module.ready && !this[ignoreReadyModulesKey].has(module), + ); } _shouldInit() { - const areAllReady = this[noReadyModulesKey].length === 0; + const areAllReady = this[notReadyModulesKey].length === 0; return areAllReady && this.pending; } _shouldReset() { - const areNotReady = this[noReadyModulesKey].length > 0; + const areNotReady = this[notReadyModulesKey].length > 0; return areNotReady && this.ready; } diff --git a/packages/core/lib/usm-redux/checkPatches.ts b/packages/core/lib/usm-redux/checkPatches.ts new file mode 100644 index 0000000000..31cb341fc7 --- /dev/null +++ b/packages/core/lib/usm-redux/checkPatches.ts @@ -0,0 +1,31 @@ +import { Action } from './interface'; + +export const checkPatches = ( + oldStateTree: Record, + options: Action, +) => { + const patches = options._patches ?? []; + for (const patch of patches) { + const { op, path, value } = patch; + if ( + op === 'replace' && + ((toString.call(value) === '[object Object]' && + !!Object.keys(value).length) || + (Array.isArray(value) && !!value.length)) + ) { + const oldState = path.reduce( + (state, _path) => state?.[_path], + oldStateTree, + ); + if (oldState && typeof oldState === 'object') { + const length = Array.isArray(oldState) + ? oldState.length + : Object.keys(oldState).length; + if (length > 0) { + return true; + } + } + } + } + return false; +}; diff --git a/packages/core/lib/usm-redux/decorators/action.ts b/packages/core/lib/usm-redux/decorators/action.ts index b28eeed65b..909726d3c9 100644 --- a/packages/core/lib/usm-redux/decorators/action.ts +++ b/packages/core/lib/usm-redux/decorators/action.ts @@ -4,6 +4,7 @@ import { Service, Action } from '../interface'; import { storeKey, identifierKey, usm } from '../constant'; import { getPatchesToggle } from '../createStore'; import { getStagedState, setStagedState } from '../utils/index'; +import { checkPatches } from '../checkPatches'; export const action = ( target: object, @@ -63,7 +64,7 @@ export const action = ( } if (changed) { - this[storeKey].dispatch({ + const action: Action = { type: this[identifierKey], method: key, params: args, @@ -75,7 +76,18 @@ export const action = ( _inversePatches: inversePatches, } : {}), - } as Action); + }; + if (process.env.NODE_ENV === 'development') { + const requiredWarning = checkPatches(lastState, action); + if (requiredWarning) { + console.warn( + `The state update operation in the method '${this[ + identifierKey + ].toString()}.${key.toString()}' is a replacement update operation. If there is a performance issue, be sure to use mutation updates to ensure the minimum set of update patches.`, + ); + } + } + this[storeKey].dispatch(action); } } finally { setStagedState(undefined); diff --git a/packages/core/test/features/checkPatches.test.tsx b/packages/core/test/features/checkPatches.test.tsx new file mode 100644 index 0000000000..c05a53db0f --- /dev/null +++ b/packages/core/test/features/checkPatches.test.tsx @@ -0,0 +1,173 @@ +import { + autorun, + title, + Scenario, + Given, + When, + Then, + Step, + examples, +} from '@ringcentral-integration/test-utils'; +import { produceWithPatches, enablePatches } from 'immer'; +import { checkPatches } from '../../lib/usm-redux/checkPatches'; + +enablePatches(); + +const checkFunction: ( + ...args: Parameters +) => boolean = (state, changes) => { + const [nextState, patches] = produceWithPatches(state, changes); + return checkPatches(state, { + _patches: patches, + method: '', + type: '', + params: undefined, + _state: nextState, + _usm: 'USM-REDUX', + }); +}; + +@autorun(test) +@title('CheckPatches::basic') +export class CheckPatches extends Step { + @examples([ + { + data: { field: {} }, + change: (data: any) => { + data.field.x = []; + data.field.x1 = 0; + data.field.x2 = 'str'; + data.field.x3 = {}; + data.field.x4 = false; + data.field.x5 = true; + data.field.x6 = null; + }, + expectWarning: false, + }, + { + data: { field: {} }, + change: (data: any) => { + Object.assign(data.field, { x: 0 }); + }, + expectWarning: false, + }, + { + data: { field: null }, + change: (data: any) => { + data.field = { x: 0 }; + }, + expectWarning: false, + }, + { + data: { field: {} }, + change: (data: any) => { + data.field = { x: 0 }; + }, + expectWarning: false, + }, + { + data: { field: { x: 0 } }, + change: (data: any) => { + data.field = {}; + }, + expectWarning: false, + }, + { + data: { field: { y: 1 } }, + change: (data: any) => { + data.field = { x: 0 }; + }, + expectWarning: true, + }, + { + data: { field: { y: 1 } }, + change: (data: any) => { + data.field = null; + data.field = { x: 0 }; + }, + expectWarning: true, + }, + { + data: { field: { y: 0 } }, + change: (data: any) => { + Object.keys(data.field).forEach((key) => { + delete data.field[key]; + }); + Object.assign(data.field, { x: 0, z: 0 }); + }, + expectWarning: false, + }, + { + data: { field: [] }, + change: (data: any) => { + data.field.push('1'); + }, + expectWarning: false, + }, + { + data: { field: [] }, + change: (data: any) => { + data.field = ['1']; + }, + expectWarning: false, + }, + { + data: { field: ['1'] }, + change: (data: any) => { + data.field = []; + }, + expectWarning: false, + }, + { + data: { field: null }, + change: (data: any) => { + data.field = ['1']; + }, + expectWarning: false, + }, + { + data: { field: ['0'] }, + change: (data: any) => { + data.field = data.field.concat(['1']); + }, + expectWarning: true, + }, + { + data: { field: ['0'] }, + change: (data: any) => { + const old = data.field; + data.field = null; + data.field = old.concat(['1']); + }, + expectWarning: true, + }, + { + data: { field: ['0'] }, + change: (data: any) => { + data.field.length = 0; + data.field.push('1'); + }, + expectWarning: false, + }, + ]) + run() { + const { data, change, expectWarning } = this.context.example; + let requiredWarning: boolean; + return ( + + { + requiredWarning = checkFunction(data, change); + }} + /> + { + expect(requiredWarning).toBe(expectWarning); + }} + /> + + ); + } +} diff --git a/packages/engage-voice-widget/components/ActivityCallLogPanel/ActivityCallLogPanel.spec.tsx b/packages/engage-voice-widget/components/ActivityCallLogPanel/ActivityCallLogPanel.spec.tsx index deab56b129..5fde486350 100644 --- a/packages/engage-voice-widget/components/ActivityCallLogPanel/ActivityCallLogPanel.spec.tsx +++ b/packages/engage-voice-widget/components/ActivityCallLogPanel/ActivityCallLogPanel.spec.tsx @@ -359,9 +359,6 @@ describe('', () => { expect(wrapper.find('ActiveCallButton')).toHaveLength(1); expect(getControlButton('HangUpButton').isExist).toBe(false); - expect( - wrapper.find('ActiveCallButton').find('button').hasClass('buttonActive'), - ).toBe(true); wrapper.find('ActiveCallButton').find('button').simulate('click'); expect(onActive).toBeCalled(); diff --git a/packages/engage-voice-widget/components/ActivityCallLogPanel/IvrInfo/IvrInfo.tsx b/packages/engage-voice-widget/components/ActivityCallLogPanel/IvrInfo/IvrInfo.tsx index 8e52e39d59..906ee251d4 100644 --- a/packages/engage-voice-widget/components/ActivityCallLogPanel/IvrInfo/IvrInfo.tsx +++ b/packages/engage-voice-widget/components/ActivityCallLogPanel/IvrInfo/IvrInfo.tsx @@ -1,7 +1,7 @@ import { RcAccordion } from '@ringcentral/juno/components/Accordion'; import { RcAccordionDetails } from '@ringcentral/juno/components/Accordion/AccordionDetails'; import { RcAccordionSummary } from '@ringcentral/juno/components/Accordion/AccordionSummary'; -import arrowDownSvg from '@ringcentral/juno/icon/ArrowDown2'; +import { ArrowDown2 } from '@ringcentral/juno/icon'; import classNames from 'classnames'; import React, { FunctionComponent, useEffect, useState } from 'react'; @@ -54,7 +54,7 @@ export const IvrInfo: FunctionComponent = ({ IconButtonProps={{ size: 'small', }} - expandIcon={arrowDownSvg} + expandIcon={ArrowDown2} > ` position: relative; width: 100%; height: ${({ open }) => (open ? '0' : '32px')}; - z-index: ${zIndex('popup')}; + z-index: ${zIndex('drawer')}; `; export const Backdrop = styled.div<{ open?: boolean }>` @@ -26,7 +26,7 @@ export const Backdrop = styled.div<{ open?: boolean }>` top: ${({ open }) => (open ? `calc(-100vh - 64px)` : '0')}; right: 0; bottom: 0; - background: ${setOpacity(palette2('bg', 'transparentDark'), '72')}; + background: ${setOpacity(palette2('neutral', 'b05'), '72')}; `; export const StyledCollapse = styled(RcCollapse)<{ open?: boolean }>` diff --git a/packages/engage-voice-widget/components/ActivityCallLogPanel/utils/getButtonText.tsx b/packages/engage-voice-widget/components/ActivityCallLogPanel/utils/getButtonText.tsx index e2c5de1078..37ac9ab4cc 100644 --- a/packages/engage-voice-widget/components/ActivityCallLogPanel/utils/getButtonText.tsx +++ b/packages/engage-voice-widget/components/ActivityCallLogPanel/utils/getButtonText.tsx @@ -1,5 +1,5 @@ import { RcIcon } from '@ringcentral/juno'; -import checkSvg from '@ringcentral/juno/icon/Check'; +import { Check } from '@ringcentral/juno/icon'; import React from 'react'; import { EvActivityCallUIProps } from '../../../interfaces'; @@ -11,11 +11,12 @@ export function getButtonText( ) { switch (status) { case 'saved': - return ; + return ; case 'saving': return null; case 'create': return i18n.getString('create', currentLocale); + // TODO: should check type case 'update': return i18n.getString('update', currentLocale); case 'submit': diff --git a/packages/engage-voice-widget/components/AlertRenderer/EvCallDispositionAlert/EvCallDispositionAlert.tsx b/packages/engage-voice-widget/components/AlertRenderer/EvCallDispositionAlert/EvCallDispositionAlert.tsx index 404d043823..47cd90e944 100644 --- a/packages/engage-voice-widget/components/AlertRenderer/EvCallDispositionAlert/EvCallDispositionAlert.tsx +++ b/packages/engage-voice-widget/components/AlertRenderer/EvCallDispositionAlert/EvCallDispositionAlert.tsx @@ -16,10 +16,12 @@ interface HandleMessage { } export default function EvCallDispositionAlert({ - message: { message }, + message: { message, payload }, currentLocale, }: EvCallDispositionAlertProps) { - return i18n.getString(message, currentLocale); + return typeof payload === 'string' + ? payload + : i18n.getString(message, currentLocale); } EvCallDispositionAlert.handleMessage = ({ message }: HandleMessage): boolean => diff --git a/packages/engage-voice-widget/components/CircleIconButton/CircleIconButton.tsx b/packages/engage-voice-widget/components/CircleIconButton/CircleIconButton.tsx deleted file mode 100644 index e3dfe0ac90..0000000000 --- a/packages/engage-voice-widget/components/CircleIconButton/CircleIconButton.tsx +++ /dev/null @@ -1,74 +0,0 @@ -import { RcFabIconButton, RcFabIconButtonProps } from '@ringcentral/juno'; -import classNames from 'classnames'; -import React, { FunctionComponent } from 'react'; -import { - Tooltip, - TooltipProps, -} from '@ringcentral-integration/widgets/components/Rcui/Tooltip'; - -import styles from './styles.scss'; - -export type CircleIconButtonProps = { - active?: boolean; - normal?: boolean; - className?: string; - dataSign?: string; -} & Pick< - RcFabIconButtonProps, - | 'color' - | 'symbol' - | 'size' - | 'className' - | 'disabled' - | 'onClick' - | 'innerRef' -> & - Pick; - -export const CircleIconButton: FunctionComponent = ({ - symbol, - color, - title, - size, - disabled, - onClick, - innerRef, - active, - normal, - className, - placement, - dataSign, -}) => { - // this div provides ref for RcTooltip because RcFabIconButton can't - return ( - -
- -
-
- ); -}; - -CircleIconButton.defaultProps = { - active: false, - normal: false, - className: undefined, - placement: 'bottom', - dataSign: undefined, -}; diff --git a/packages/engage-voice-widget/components/CircleIconButton/index.ts b/packages/engage-voice-widget/components/CircleIconButton/index.ts deleted file mode 100644 index dfae94acf8..0000000000 --- a/packages/engage-voice-widget/components/CircleIconButton/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './CircleIconButton'; diff --git a/packages/engage-voice-widget/components/CircleIconButton/styles.scss b/packages/engage-voice-widget/components/CircleIconButton/styles.scss deleted file mode 100644 index 04c1787648..0000000000 --- a/packages/engage-voice-widget/components/CircleIconButton/styles.scss +++ /dev/null @@ -1,13 +0,0 @@ -@import '~@ringcentral-integration/widgets/lib/commonStyles/colors.scss'; - -button.buttonNormal { - background-color: rgb(245, 246, 251) !important; - color: $primary-color !important; -} -button.buttonActive { - background-color: $primary-color !important; - color: $snow !important; -} -button.buttonDisable { - color: rgba(0, 0, 0, 0.26) !important; -} diff --git a/packages/engage-voice-widget/components/DialerPanel/Dialer/Dialer.tsx b/packages/engage-voice-widget/components/DialerPanel/Dialer/Dialer.tsx index fe99f3796d..2f6a37161f 100644 --- a/packages/engage-voice-widget/components/DialerPanel/Dialer/Dialer.tsx +++ b/packages/engage-voice-widget/components/DialerPanel/Dialer/Dialer.tsx @@ -55,7 +55,11 @@ export const Dialer: FunctionComponent = ({ /> - + ({ 'data-dial-button': `${v}` })} + /> {children} diff --git a/packages/engage-voice-widget/components/DialerPanel/Dialer/styles/DialerWrapper.tsx b/packages/engage-voice-widget/components/DialerPanel/Dialer/styles/DialerWrapper.tsx index a36dfa5d42..209c4bdc29 100644 --- a/packages/engage-voice-widget/components/DialerPanel/Dialer/styles/DialerWrapper.tsx +++ b/packages/engage-voice-widget/components/DialerPanel/Dialer/styles/DialerWrapper.tsx @@ -38,4 +38,9 @@ export const DialPadWrapper = styled.div` [sf-classic] & { width: 90%; } + + button > span { + width: 100%; + height: 100%; + } `; diff --git a/packages/engage-voice-widget/components/DialerPanel/DialerPanel.tsx b/packages/engage-voice-widget/components/DialerPanel/DialerPanel.tsx index 58a8ed09cd..2733b97b53 100644 --- a/packages/engage-voice-widget/components/DialerPanel/DialerPanel.tsx +++ b/packages/engage-voice-widget/components/DialerPanel/DialerPanel.tsx @@ -30,7 +30,7 @@ const dialoutStatusMapping: Record< const LinkSizeMapping: Record = { small: 'caption1', medium: 'body1', - large: 'headline', + large: 'headline1', }; export type DialerPanelProps = EvDialerUIProps & EvDialerUIFunctions; diff --git a/packages/engage-voice-widget/components/EvSmallCallControl/components/ActiveCallButton.tsx b/packages/engage-voice-widget/components/EvSmallCallControl/components/ActiveCallButton.tsx index 6281547b3c..ff6b15e77e 100644 --- a/packages/engage-voice-widget/components/EvSmallCallControl/components/ActiveCallButton.tsx +++ b/packages/engage-voice-widget/components/EvSmallCallControl/components/ActiveCallButton.tsx @@ -1,7 +1,7 @@ +import { RcIconButton } from '@ringcentral/juno'; import activeCallSvg from '@ringcentral/juno/icon/ActiveCall'; import React, { FunctionComponent } from 'react'; -import { CircleIconButton } from '../../CircleIconButton'; import { CallButtonsProps } from '../../SmallCallControl'; import i18n from '../i18n'; @@ -19,14 +19,14 @@ export const ActiveCallButton: FunctionComponent = ({ dataSign, }) => { return ( - ); }; diff --git a/packages/engage-voice-widget/components/EvSmallCallControl/components/CountDownButton.tsx b/packages/engage-voice-widget/components/EvSmallCallControl/components/CountDownButton.tsx index da992f4f6f..cee63fe2b5 100644 --- a/packages/engage-voice-widget/components/EvSmallCallControl/components/CountDownButton.tsx +++ b/packages/engage-voice-widget/components/EvSmallCallControl/components/CountDownButton.tsx @@ -11,11 +11,7 @@ type CountDownProps = { export const CountDown: FunctionComponent = ({ data }) => { const count = data > 99 ? '99+' : data; return ( - + {count} ); diff --git a/packages/engage-voice-widget/components/EvSmallCallControl/components/CountDownButton.ut.tsx b/packages/engage-voice-widget/components/EvSmallCallControl/components/CountDownButton.ut.tsx index b3b713bb4c..ab0bbb5fb5 100644 --- a/packages/engage-voice-widget/components/EvSmallCallControl/components/CountDownButton.ut.tsx +++ b/packages/engage-voice-widget/components/EvSmallCallControl/components/CountDownButton.ut.tsx @@ -29,7 +29,9 @@ function setup({ export const CheckCountDownButtonTooltip: StepFunction = () => { const { container } = setup({}); - const node = container.querySelector('[data-sign="CountDown"]'); + const node = container.querySelector( + '[data-sign="CountDown"]', + ); expect(node).toBeTruthy; expect(node.title).toBe('Restart timer'); }; diff --git a/packages/engage-voice-widget/components/EvSmallCallControl/components/RecordControlButton.ut.tsx b/packages/engage-voice-widget/components/EvSmallCallControl/components/RecordControlButton.ut.tsx index dea827e25c..0aa509a12e 100644 --- a/packages/engage-voice-widget/components/EvSmallCallControl/components/RecordControlButton.ut.tsx +++ b/packages/engage-voice-widget/components/EvSmallCallControl/components/RecordControlButton.ut.tsx @@ -29,7 +29,9 @@ function setup({ export const CheckPauseRecordingTooltip: StepFunction = () => { const { container } = setup({ disablePauseRecord: false }); - const node = container.querySelector('[data-sign="PauseRecording"]'); + const node = container.querySelector( + '[data-sign="PauseRecording"]', + ); expect(node).toBeTruthy; expect(node.title).toBe('Pause recording'); }; diff --git a/packages/engage-voice-widget/components/EvSmallCallControl/components/RecordingButton.tsx b/packages/engage-voice-widget/components/EvSmallCallControl/components/RecordingButton.tsx index da653fc865..3ce4b27da8 100644 --- a/packages/engage-voice-widget/components/EvSmallCallControl/components/RecordingButton.tsx +++ b/packages/engage-voice-widget/components/EvSmallCallControl/components/RecordingButton.tsx @@ -1,4 +1,4 @@ -import { RcIconButton, RcTooltip } from '@ringcentral/juno'; +import { RcIconButton } from '@ringcentral/juno'; import React, { FunctionComponent } from 'react'; import RecordingSvg from '../../../assets/icons/icon-recording.svg'; import styles from './styles.scss'; diff --git a/packages/engage-voice-widget/components/SessionConfigPanel/styles.scss b/packages/engage-voice-widget/components/SessionConfigPanel/styles.scss index 09cc57ecec..c36a9ef31c 100644 --- a/packages/engage-voice-widget/components/SessionConfigPanel/styles.scss +++ b/packages/engage-voice-widget/components/SessionConfigPanel/styles.scss @@ -13,11 +13,7 @@ } .goBackBg { - background: rc-palette( - bg, - primaryLightest - /* !!!This token not exist! CONFIRM with Designer which one should use */ - ); + background: rc-palette('neutral', 'b03'); } .hideGoBack { diff --git a/packages/engage-voice-widget/components/SmallCallControl/components/CallButtons.interface.ts b/packages/engage-voice-widget/components/SmallCallControl/components/CallButtons.interface.ts index 73608d3fc8..99ef7520a6 100644 --- a/packages/engage-voice-widget/components/SmallCallControl/components/CallButtons.interface.ts +++ b/packages/engage-voice-widget/components/SmallCallControl/components/CallButtons.interface.ts @@ -1,6 +1,6 @@ -import { CircleIconButtonProps } from '../../CircleIconButton'; +import { RcIconButtonProps } from '@ringcentral/juno'; export type CallButtonsProps = { currentLocale?: string; dataSign?: string; -} & Pick; +} & RcIconButtonProps; diff --git a/packages/engage-voice-widget/components/SmallCallControl/components/HangUpButton.tsx b/packages/engage-voice-widget/components/SmallCallControl/components/HangUpButton.tsx index 3ca643d5c8..2304979f53 100644 --- a/packages/engage-voice-widget/components/SmallCallControl/components/HangUpButton.tsx +++ b/packages/engage-voice-widget/components/SmallCallControl/components/HangUpButton.tsx @@ -28,6 +28,7 @@ export const HangUpButton: FunctionComponent = ({ const { endTitle } = getCircleIconButtonTitle({ isInComingCall, }); + return ( = ({ isOnHold, }); - let color = disableHold ? 'icon.disabled' : 'icon.dark'; - if (isOnHold) { - color = 'icon.primary'; - } + const color = getIconColor({ + active: isOnHold, + disable: disableHold, + }); return ( = ({ isOnMute, }); - let color = disableMute ? 'icon.disabled' : 'icon.dark'; - if (isOnMute) { - color = 'icon.primary'; - } + const color = getIconColor({ + active: isOnMute, + disable: disableMute, + }); return ( = ({ className, dataSign, }) => { + const color = getIconColor({ + active: false, + disable: disableTransfer, + }); + return ( = ({ data-sign={dataSign} data-icon="transfer-call" title={i18n.getString('transfer', currentLocale)} - color={disableTransfer ? 'icon.disabled' : 'icon.dark'} + color={color} className={className} shouldPersistBg={disableTransfer} /> diff --git a/packages/engage-voice-widget/components/SmallCallControl/components/getIconColor.tsx b/packages/engage-voice-widget/components/SmallCallControl/components/getIconColor.tsx new file mode 100644 index 0000000000..37ec30e5c2 --- /dev/null +++ b/packages/engage-voice-widget/components/SmallCallControl/components/getIconColor.tsx @@ -0,0 +1,16 @@ +import { RcPaletteProp } from '@ringcentral/juno'; + +type GetIconColorParams = { + disable: boolean; + active: boolean; +}; + +export function getIconColor({ + disable, + active, +}: GetIconColorParams): RcPaletteProp { + if (active) { + return 'interactive.f01'; + } + return disable ? 'disabled.f02' : 'neutral.f06'; +} diff --git a/packages/engage-voice-widget/interfaces/EvActivityCallUI.interface.ts b/packages/engage-voice-widget/interfaces/EvActivityCallUI.interface.ts index b906c32f21..7933724f9e 100644 --- a/packages/engage-voice-widget/interfaces/EvActivityCallUI.interface.ts +++ b/packages/engage-voice-widget/interfaces/EvActivityCallUI.interface.ts @@ -61,7 +61,7 @@ export type EvActivityCallUIProps = { disableInternalTransfer: boolean; showMuteButton: boolean; ivrAlertData: EvIvrData[]; - agentScriptData: EvAgentScriptData; + agentScriptData?: EvAgentScriptData; referenceFieldOptions?: CallLogFieldsProps['referenceFieldOptions']; recordPauseCount: number; timeStamp: number; diff --git a/packages/engage-voice-widget/modules/EvActiveCallListUI/EvActiveCallListUI.interface.ts b/packages/engage-voice-widget/modules/EvActiveCallListUI/EvActiveCallListUI.interface.ts index 564bf093e0..6ef0526ab6 100644 --- a/packages/engage-voice-widget/modules/EvActiveCallListUI/EvActiveCallListUI.interface.ts +++ b/packages/engage-voice-widget/modules/EvActiveCallListUI/EvActiveCallListUI.interface.ts @@ -1,4 +1,4 @@ -import Locale from '@ringcentral-integration/commons/modules/Locale'; +import { Locale } from '@ringcentral-integration/commons/modules/Locale'; import RouterInteraction from '@ringcentral-integration/widgets/modules/RouterInteraction'; import { EvClient } from '../../lib/EvClient'; diff --git a/packages/engage-voice-widget/modules/EvActivityCallUI/EvActivityCallUI.interface.ts b/packages/engage-voice-widget/modules/EvActivityCallUI/EvActivityCallUI.interface.ts index 5826cc14c9..2ba9360756 100644 --- a/packages/engage-voice-widget/modules/EvActivityCallUI/EvActivityCallUI.interface.ts +++ b/packages/engage-voice-widget/modules/EvActivityCallUI/EvActivityCallUI.interface.ts @@ -1,6 +1,6 @@ import Alert from '@ringcentral-integration/commons/modules/Alert'; import ConnectivityMonitor from '@ringcentral-integration/commons/modules/ConnectivityMonitor'; -import Locale from '@ringcentral-integration/commons/modules/Locale'; +import { Locale } from '@ringcentral-integration/commons/modules/Locale'; import RateLimiter from '@ringcentral-integration/commons/modules/RateLimiter'; import RouterInteraction from '@ringcentral-integration/widgets/modules/RouterInteraction'; import { EvTabManager } from '../EvTabManager'; diff --git a/packages/engage-voice-widget/modules/EvActivityCallUI/EvActivityCallUI.ts b/packages/engage-voice-widget/modules/EvActivityCallUI/EvActivityCallUI.ts index afb737e8bf..8ca46c5a7f 100644 --- a/packages/engage-voice-widget/modules/EvActivityCallUI/EvActivityCallUI.ts +++ b/packages/engage-voice-widget/modules/EvActivityCallUI/EvActivityCallUI.ts @@ -721,9 +721,11 @@ class EvActivityCallUI this._deps.alert.danger({ message: logTypesEventFailure, ttl: 0, + payload: e?.error?.status === false ? e?.error?.message : undefined, }); this.changeSavingStatus(initSaveStatus); - throw e; + console.error(e); + throw new Error(`Failed to save log.`); } } diff --git a/packages/engage-voice-widget/modules/EvAgentSession/EvAgentSession.interface.ts b/packages/engage-voice-widget/modules/EvAgentSession/EvAgentSession.interface.ts index 7f48944c64..bc46141ac2 100644 --- a/packages/engage-voice-widget/modules/EvAgentSession/EvAgentSession.interface.ts +++ b/packages/engage-voice-widget/modules/EvAgentSession/EvAgentSession.interface.ts @@ -1,6 +1,6 @@ import Alert from '@ringcentral-integration/commons/modules/Alert'; import { Auth } from '@ringcentral-integration/commons/modules/AuthV2'; -import Locale from '@ringcentral-integration/commons/modules/Locale'; +import { Locale } from '@ringcentral-integration/commons/modules/Locale'; import { Beforeunload } from '@ringcentral-integration/widgets/modules/Beforeunload'; import { Block } from '@ringcentral-integration/widgets/modules/Block'; import { ModalUI } from '@ringcentral-integration/widgets/modules/ModalUIV2'; diff --git a/packages/engage-voice-widget/modules/EvAgentSessionUI/EvAgentSessionUI.interface.ts b/packages/engage-voice-widget/modules/EvAgentSessionUI/EvAgentSessionUI.interface.ts index ee5811b24b..967ad917ec 100644 --- a/packages/engage-voice-widget/modules/EvAgentSessionUI/EvAgentSessionUI.interface.ts +++ b/packages/engage-voice-widget/modules/EvAgentSessionUI/EvAgentSessionUI.interface.ts @@ -1,4 +1,4 @@ -import Locale from '@ringcentral-integration/commons/modules/Locale'; +import { Locale } from '@ringcentral-integration/commons/modules/Locale'; import { ModalUI } from '@ringcentral-integration/widgets/modules/ModalUIV2'; import { Block } from '@ringcentral-integration/widgets/modules/Block'; import RouterInteraction from '@ringcentral-integration/widgets/modules/RouterInteraction'; diff --git a/packages/engage-voice-widget/modules/EvAuth/EvAuth.interface.ts b/packages/engage-voice-widget/modules/EvAuth/EvAuth.interface.ts index 6621553423..fad2eefe21 100644 --- a/packages/engage-voice-widget/modules/EvAuth/EvAuth.interface.ts +++ b/packages/engage-voice-widget/modules/EvAuth/EvAuth.interface.ts @@ -1,6 +1,6 @@ import Alert from '@ringcentral-integration/commons/modules/Alert'; import { Auth as RcAuth } from '@ringcentral-integration/commons/modules/AuthV2'; -import Locale from '@ringcentral-integration/commons/modules/Locale'; +import { Locale } from '@ringcentral-integration/commons/modules/Locale'; import { Block } from '@ringcentral-integration/widgets/modules/Block'; import RouterInteraction from '@ringcentral-integration/widgets/modules/RouterInteraction'; diff --git a/packages/engage-voice-widget/modules/EvCallHistory/EvCallHistory.interface.ts b/packages/engage-voice-widget/modules/EvCallHistory/EvCallHistory.interface.ts index c51592fa7b..79b8099076 100644 --- a/packages/engage-voice-widget/modules/EvCallHistory/EvCallHistory.interface.ts +++ b/packages/engage-voice-widget/modules/EvCallHistory/EvCallHistory.interface.ts @@ -1,6 +1,6 @@ import { ActivityMatcher } from '@ringcentral-integration/commons/modules/ActivityMatcherV2'; import { ContactMatcher } from '@ringcentral-integration/commons/modules/ContactMatcherV2'; -import { Locale } from '@ringcentral-integration/commons/modules/LocaleV2'; +import { Locale } from '@ringcentral-integration/commons/modules/Locale'; import { EvAgentSession } from '../EvAgentSession'; import { EvCallMonitor } from '../EvCallMonitor'; import { EvSubscription } from '../EvSubscription'; diff --git a/packages/engage-voice-widget/modules/EvChooseAccountUI/EvChooseAccountUI.interface.ts b/packages/engage-voice-widget/modules/EvChooseAccountUI/EvChooseAccountUI.interface.ts index 9e24093acb..5b45156939 100644 --- a/packages/engage-voice-widget/modules/EvChooseAccountUI/EvChooseAccountUI.interface.ts +++ b/packages/engage-voice-widget/modules/EvChooseAccountUI/EvChooseAccountUI.interface.ts @@ -1,4 +1,4 @@ -import Locale from '@ringcentral-integration/commons/modules/Locale'; +import { Locale } from '@ringcentral-integration/commons/modules/Locale'; import { Block } from '@ringcentral-integration/widgets/modules/Block'; import RouterInteraction from '@ringcentral-integration/widgets/modules/RouterInteraction'; diff --git a/packages/engage-voice-widget/modules/EvDialerUI/EvDialerUI.interface.ts b/packages/engage-voice-widget/modules/EvDialerUI/EvDialerUI.interface.ts index f86d3125dc..04d41fa683 100644 --- a/packages/engage-voice-widget/modules/EvDialerUI/EvDialerUI.interface.ts +++ b/packages/engage-voice-widget/modules/EvDialerUI/EvDialerUI.interface.ts @@ -1,4 +1,4 @@ -import Locale from '@ringcentral-integration/commons/modules/Locale'; +import { Locale } from '@ringcentral-integration/commons/modules/Locale'; import RouterInteraction from '@ringcentral-integration/widgets/modules/RouterInteraction'; diff --git a/packages/engage-voice-widget/modules/EvIntegratedSoftphone/EvIntegratedSoftphone.interface.ts b/packages/engage-voice-widget/modules/EvIntegratedSoftphone/EvIntegratedSoftphone.interface.ts index 4d7512c9e2..46bff912eb 100644 --- a/packages/engage-voice-widget/modules/EvIntegratedSoftphone/EvIntegratedSoftphone.interface.ts +++ b/packages/engage-voice-widget/modules/EvIntegratedSoftphone/EvIntegratedSoftphone.interface.ts @@ -1,6 +1,6 @@ import Alert from '@ringcentral-integration/commons/modules/Alert'; import { Auth } from '@ringcentral-integration/commons/modules/AuthV2'; -import Locale from '@ringcentral-integration/commons/modules/Locale'; +import { Locale } from '@ringcentral-integration/commons/modules/Locale'; import { Beforeunload } from '@ringcentral-integration/widgets/modules/Beforeunload'; import { Block } from '@ringcentral-integration/widgets/modules/Block'; import { ModalUI } from '@ringcentral-integration/widgets/modules/ModalUIV2'; diff --git a/packages/engage-voice-widget/modules/EvIntegratedSoftphone/EvIntegratedSoftphone.ts b/packages/engage-voice-widget/modules/EvIntegratedSoftphone/EvIntegratedSoftphone.ts index 70a10008ed..29adeaaa34 100644 --- a/packages/engage-voice-widget/modules/EvIntegratedSoftphone/EvIntegratedSoftphone.ts +++ b/packages/engage-voice-widget/modules/EvIntegratedSoftphone/EvIntegratedSoftphone.ts @@ -779,16 +779,21 @@ class EvIntegratedSoftphone this._sendTabManager( tabManagerEvents.NOTIFY_ACTIVE_TAB_CALL_ACTIVE, ); - // eslint-disable-next-line no-alert - alert( - i18n.getString('activeCallTip', this._deps.locale.currentLocale), - ); - reject(null); + if ( + // eslint-disable-next-line no-alert + window.confirm( + i18n.getString( + 'activeCallTip', + this._deps.locale.currentLocale, + ), + ) + ) { + resolve(null); + } }, }, ); } - this._deps.evClient.sipAnswer(); } diff --git a/packages/engage-voice-widget/modules/EvManualDialSettingsUI/EvManualDialSettingsUI.interface.ts b/packages/engage-voice-widget/modules/EvManualDialSettingsUI/EvManualDialSettingsUI.interface.ts index f29c78a0e4..502644a438 100644 --- a/packages/engage-voice-widget/modules/EvManualDialSettingsUI/EvManualDialSettingsUI.interface.ts +++ b/packages/engage-voice-widget/modules/EvManualDialSettingsUI/EvManualDialSettingsUI.interface.ts @@ -1,5 +1,5 @@ import { FunctionComponent } from 'react'; -import Locale from '@ringcentral-integration/commons/modules/Locale'; +import { Locale } from '@ringcentral-integration/commons/modules/Locale'; import RouterInteraction from '@ringcentral-integration/widgets/modules/RouterInteraction'; import { EvAuth } from '../EvAuth'; diff --git a/packages/engage-voice-widget/modules/EvSettingsUI/EvSettingsUI.interface.ts b/packages/engage-voice-widget/modules/EvSettingsUI/EvSettingsUI.interface.ts index 5ceeb85dd1..7b0a366123 100644 --- a/packages/engage-voice-widget/modules/EvSettingsUI/EvSettingsUI.interface.ts +++ b/packages/engage-voice-widget/modules/EvSettingsUI/EvSettingsUI.interface.ts @@ -1,4 +1,4 @@ -import Locale from '@ringcentral-integration/commons/modules/Locale'; +import { Locale } from '@ringcentral-integration/commons/modules/Locale'; import RouterInteraction from '@ringcentral-integration/widgets/modules/RouterInteraction'; import { EvClient } from '../../lib/EvClient'; diff --git a/packages/engage-voice-widget/modules/EvStorage/EvStorage.interface.ts b/packages/engage-voice-widget/modules/EvStorage/EvStorage.interface.ts index 942df0265e..6a1f9e0f76 100644 --- a/packages/engage-voice-widget/modules/EvStorage/EvStorage.interface.ts +++ b/packages/engage-voice-widget/modules/EvStorage/EvStorage.interface.ts @@ -1,6 +1,6 @@ import { Auth } from '@ringcentral-integration/commons/modules/AuthV2'; import { StorageOptions } from '@ringcentral-integration/commons/modules/StorageV2'; -import { TabManager } from '@ringcentral-integration/commons/modules/TabManagerV2'; +import { TabManager } from '@ringcentral-integration/commons/modules/TabManager'; import { EvAuth } from '../EvAuth'; export type EvStorageOptions = StorageOptions; diff --git a/packages/engage-voice-widget/modules/EvTabManager/EvTabManager.ts b/packages/engage-voice-widget/modules/EvTabManager/EvTabManager.ts index 46e3b6082a..7748643591 100644 --- a/packages/engage-voice-widget/modules/EvTabManager/EvTabManager.ts +++ b/packages/engage-voice-widget/modules/EvTabManager/EvTabManager.ts @@ -1,6 +1,6 @@ import { action, state, globalStorage } from '@ringcentral-integration/core'; import { Module } from '@ringcentral-integration/commons/lib/di'; -import { TabManager } from '@ringcentral-integration/commons/modules/TabManagerV2'; +import { TabManager } from '@ringcentral-integration/commons/modules/TabManager'; import { EventEmitter } from 'events'; import { tabManagerEvents } from '../../enums'; diff --git a/packages/engage-voice-widget/modules/EvTransferCall/EvTransferCall.interface.ts b/packages/engage-voice-widget/modules/EvTransferCall/EvTransferCall.interface.ts index 6597448d95..441adb98ec 100644 --- a/packages/engage-voice-widget/modules/EvTransferCall/EvTransferCall.interface.ts +++ b/packages/engage-voice-widget/modules/EvTransferCall/EvTransferCall.interface.ts @@ -1,5 +1,5 @@ import Alert from '@ringcentral-integration/commons/modules/Alert'; -import Locale from '@ringcentral-integration/commons/modules/Locale'; +import { Locale } from '@ringcentral-integration/commons/modules/Locale'; import { ModalUI } from '@ringcentral-integration/widgets/modules/ModalUIV2'; import { DirectTransferTypes } from '../../enums/directTransferTypes'; diff --git a/packages/engage-voice-widget/modules/EvTransferCallUI/EvTransferCallUI.interface.ts b/packages/engage-voice-widget/modules/EvTransferCallUI/EvTransferCallUI.interface.ts index 7616ba8b7b..30cb0972c7 100644 --- a/packages/engage-voice-widget/modules/EvTransferCallUI/EvTransferCallUI.interface.ts +++ b/packages/engage-voice-widget/modules/EvTransferCallUI/EvTransferCallUI.interface.ts @@ -1,4 +1,4 @@ -import Locale from '@ringcentral-integration/commons/modules/Locale'; +import { Locale } from '@ringcentral-integration/commons/modules/Locale'; import RouterInteraction from '@ringcentral-integration/widgets/modules/RouterInteraction'; import { EvEnvironment } from '../../interfaces/Environment.interface'; diff --git a/packages/engage-voice-widget/modules/MainViewUI/MainViewUI.interface.ts b/packages/engage-voice-widget/modules/MainViewUI/MainViewUI.interface.ts index 905c25825a..20f38483dc 100644 --- a/packages/engage-voice-widget/modules/MainViewUI/MainViewUI.interface.ts +++ b/packages/engage-voice-widget/modules/MainViewUI/MainViewUI.interface.ts @@ -1,4 +1,4 @@ -import Locale from '@ringcentral-integration/commons/modules/Locale'; +import { Locale } from '@ringcentral-integration/commons/modules/Locale'; import RouterInteraction from '@ringcentral-integration/widgets/modules/RouterInteraction'; import { EvEnvironment } from '../../interfaces/Environment.interface'; diff --git a/packages/engage-voice-widget/package.json b/packages/engage-voice-widget/package.json index 61e2bc452b..ce768955b1 100644 --- a/packages/engage-voice-widget/package.json +++ b/packages/engage-voice-widget/package.json @@ -36,22 +36,23 @@ "@ringcentral-integration/commons": "^0.13.0", "@ringcentral-integration/core": "^0.13.0", "@ringcentral-integration/phone-number": "^1.0.4", - "@ringcentral/juno": "^1.8.5-beta.5034-128a9f16", + "@ringcentral/juno": "^1.11.2", "@ringcentral-integration/widgets": "^0.13.0" }, "devDependencies": { "@ringcentral-integration/test-utils": "*", "@ringcentral-integration/babel-settings": "*", "@ringcentral-integration/commons": "*", + "@ringcentral-integration/widgets": "*", "@ringcentral-integration/core": "*", "@ringcentral-integration/locale-loader": "*", "@ringcentral-integration/locale-settings": "*", "@ringcentral-integration/phone-number": "*", - "@ringcentral/juno": "^1.8.5-beta.5034-128a9f16", + "@ringcentral/juno": "^1.11.2", "@testing-library/react": "^11.2.6", "crius-test": "^1.2.0", "enzyme": "^3.7.0", - "enzyme-adapter-react-16": "^1.15.1", + "@wojtekmaj/enzyme-adapter-react-17": "^0.6.3", "execa": "^5.0.0", "fs-extra": "^9.0.1", "gulp": "^4.0.2", @@ -59,7 +60,7 @@ "gulp-istanbul": "^1.1.1", "gulp-sourcemaps": "^2.6.5", "jest-html-reporters": "2.0.3", - "@ringcentral-integration/widgets": "*" + "dotenv": "^6.2.0" }, "dependencies": { "classnames": "^2.2.6", @@ -69,8 +70,8 @@ "moment-timezone": "^0.5.27", "prop-types": "^15.7.2", "ramda": "^0.27.0", - "react": "^16.14.0", - "react-dom": "^16.14.0", + "react": "^17.0.2", + "react-dom": "^17.0.2", "react-redux": "^5.1.1", "react-router": "^3.0.0", "redux": "^4.0.5", @@ -92,12 +93,8 @@ "/test/support/shim.js", "/test/support/setup.js" ], - "snapshotSerializers": [ - "enzyme-to-json/serializer" - ], - "setupFilesAfterEnv": [ - "./test/jest.setup.js" - ], + "snapshotSerializers": ["enzyme-to-json/serializer"], + "setupFilesAfterEnv": ["./test/jest.setup.js"], "reporters": [ "default", [ diff --git a/packages/engage-voice-widget/test/support/setup.js b/packages/engage-voice-widget/test/support/setup.js index f0f484c9c2..f76ab08327 100644 --- a/packages/engage-voice-widget/test/support/setup.js +++ b/packages/engage-voice-widget/test/support/setup.js @@ -1,7 +1,6 @@ -import path from 'path'; +import Adapter from '@wojtekmaj/enzyme-adapter-react-17'; import { configure } from 'enzyme'; -import Adapter from 'enzyme-adapter-react-16'; -import LocalStorage from './localStorage'; +import path from 'path'; configure({ adapter: new Adapter() }); diff --git a/packages/eslint-settings/.eslintrc.js b/packages/eslint-settings/.eslintrc.js index 63e4bef01d..d210212396 100644 --- a/packages/eslint-settings/.eslintrc.js +++ b/packages/eslint-settings/.eslintrc.js @@ -147,7 +147,14 @@ module.exports = { }, overrides: [ { - files: ['*.test.js', '*.spec.js', '**/test/**/*.js', '**/test/**/*.ts'], + files: [ + '*.test.js', + '*.spec.js', + '**/test/**/*.js', + '**/test/**/*.ts', + '**/__test__/**/*.js', + '**/__test__/**/*.ts', + ], env: { jest: true, jasmine: true, diff --git a/packages/glip-widgets/package.json b/packages/glip-widgets/package.json index 00ddfce689..bcf1f10866 100644 --- a/packages/glip-widgets/package.json +++ b/packages/glip-widgets/package.json @@ -22,8 +22,8 @@ "peerDependencies": { "@ringcentral-integration/core": "^0.13.0", "@ringcentral-integration/commons": "^0.13.0", - "react": "^16.14.0", - "react-dom": "^16.14.0", + "react": "^17.0.2", + "react-dom": "^17.0.2", "react-redux": "^5.1.1", "react-router": "^3.0.0", "react-router-redux": "^4.0.7", @@ -45,7 +45,7 @@ "react-svg-loader": "^3.0.3", "redux-logger": "^3.0.6", "redux-thunk": "^2.2.0", - "yargs": "^14.0.0" + "yargs": "^17.1.1" }, "dependencies": { "classnames": "^2.2.5", diff --git a/packages/locale-loader/lib/generateLoaderContent/index.js b/packages/locale-loader/lib/generateLoaderContent/index.js index 64642664ea..c0db52c757 100644 --- a/packages/locale-loader/lib/generateLoaderContent/index.js +++ b/packages/locale-loader/lib/generateLoaderContent/index.js @@ -4,6 +4,50 @@ import formatLocale from '@ringcentral-integration/i18n/lib/formatLocale'; function getBaseName(f) { return f.replace(/\.(js|json|ts)$/i, ''); } + +function returnLoadLocaleCode(chunk, locale, basename) { + const padding = chunk ? ' ' : ' '; + let code = ` + ${padding}const data = require('./${basename}'); + ${padding}return resolve(data.__esModule === true ? data.default : data);`; + if (chunk) { + code = ` + if (typeof require.ensure === 'function') { + return require.ensure(['./${basename}'], (require) => {${code} + }, '${locale}'); + } else {${code} + }`; + } + return code; +} + +export function handleSpecialLocale(chunk, files) { + const codeMaps = new Map([ + [ + files.find((file) => /^es-419/.test(file)), + { + condition: `locale.indexOf('es') === 0 && locale !== 'es-ES'`, + loadFileBasename: 'es-419', + }, + ], + ]); + + let code = ''; + for (const [ + needHandleLocale, + { condition, loadFileBasename: basename }, + ] of codeMaps.entries()) { + const locale = basename; + if (needHandleLocale) { + code += ` + if (${condition}) { + ${returnLoadLocaleCode(chunk, locale, basename)} + } + `; + } + } + return code; +} /** * @typedef GLCOptions * @property {String[]} files @@ -38,23 +82,13 @@ export default function generateLoaderContent( // smaller index has priority return aIdx > bIdx ? 1 : -1; }; + const usedLang = {}; const cases = files.sort(byLocale).map((f) => { const basename = getBaseName(f); const locale = formatLocale(basename); const lang = locale.split('-')[0]; - const padding = chunk ? ' ' : ''; - let code = ` - ${padding}const data = require('./${basename}'); - ${padding}resolve(data.__esModule === true ? data.default : data);`; - if (chunk) { - code = ` - if (typeof require.ensure === 'function') { - require.ensure(['./${basename}'], (require) => {${code} - }, '${locale}'); - } else {${code} - }`; - } + const returnCode = returnLoadLocaleCode(chunk, locale, basename); let langDefaultCase = ''; if (!usedLang[lang]) { usedLang[lang] = true; @@ -63,16 +97,16 @@ export default function generateLoaderContent( `; } return `${langDefaultCase} - case '${locale}': {${code} - break; + case '${locale}': {${returnCode} }`; }); + return dedent`export default function loadLocale(locale) { return new Promise((resolve) => { + ${handleSpecialLocale(chunk, files)} switch (locale) {${cases.join('')} default: - resolve({}); - break; + return resolve({}); } }); }\n`; diff --git a/packages/ringcentral-crius/babel-crius.js b/packages/ringcentral-crius/babel-crius.js index c3189723d0..3e6dad74d5 100644 --- a/packages/ringcentral-crius/babel-crius.js +++ b/packages/ringcentral-crius/babel-crius.js @@ -1,4 +1,4 @@ -module.exports = require('babel-jest').createTransformer({ +module.exports = require('babel-jest').default.createTransformer({ presets: [['@babel/preset-env'], ['babel-preset-crius']], plugins: [['@babel/plugin-proposal-decorators', { legacy: true }]], ignore: [/node_modules/], diff --git a/packages/ringcentral-crius/package.json b/packages/ringcentral-crius/package.json index 79e419122c..22f58c4b53 100644 --- a/packages/ringcentral-crius/package.json +++ b/packages/ringcentral-crius/package.json @@ -7,6 +7,7 @@ "test": "echo \"Error: no test specified\" && exit 1" }, "dependencies": { + "babel-jest": "^27.0.1", "crius-is": "^1.2.0", "crius-test": "^1.2.0" }, diff --git a/packages/ringcentral-integration/README.md b/packages/ringcentral-integration/README.md index c7b816d927..999e74cf94 100644 --- a/packages/ringcentral-integration/README.md +++ b/packages/ringcentral-integration/README.md @@ -67,7 +67,7 @@ There are three kind of modules: All needed common modules which are provided by `@ringcentral-integration/commons` can be listed here. And also other modules composed by you. ```javascript import { Alert } from '@ringcentral-integration/commons/modules/AlertV2'; -import { Brand } from '@ringcentral-integration/commons/modules/BrandV2'; +import { Brand } from '@ringcentral-integration/commons/modules/Brand'; // import other libs // other variables initialized here @@ -434,48 +434,6 @@ This decorator can be used on any kind modules, no matter it's root module or no ## Dependency Injection Please refer to [Dependency Injection](docs/dependency-injection.md) for more details. -## Modules ---- - -- [x] AccountInfo -- [x] AddressBook -- [x] Alert -- [x] Auth -- [x] BlockedNumber -- [x] Brand -- [x] Call -- [x] CallingSettings -- [x] CompanyContacts -- [x] ComposeText -- [x] ConnectivityMonitor -- [x] Contacts -- [x] ContactSearch -- [x] Conversation -- [x] Presence -- [x] DialingPlan -- [x] Environment -- [x] ExtensionDevice -- [x] ExtensionInfo -- [x] ExtensionPhoneNumber -- [x] GlobalStorage -- [x] Locale -- [x] Messages -- [x] MessageSender -- [x] MessageStore -- [x] NumberValidate -- [x] RateLimiter -- [x] RecentCalls -- [x] RecentMessages -- [x] RegionSettings -- [x] Ringout -- [x] RolesAndPermissions -- [x] Softphone -- [x] Storage -- [x] Subscription -- [x] TabManager -- [x] Webphone -- more... - ## Contribution --- diff --git a/packages/ringcentral-integration/docs/background-client-proxy.md b/packages/ringcentral-integration/docs/background-client-proxy.md new file mode 100644 index 0000000000..126fef7dcb --- /dev/null +++ b/packages/ringcentral-integration/docs/background-client-proxy.md @@ -0,0 +1,64 @@ +# Background/Client proxy mechanism + +It's an Integrations applications architecture for browser expansion, and one background server port shared to multiple render-only clients. + +## APIs + +- `@proxify` ringcentral-js-widgets/ringcentral-integration/lib/proxy/proxify.ts +- `@action` ringcentral-js-widgets/core/lib/usm-redux/decorators/action.ts +- `initializeProxy` ringcentral-js-widgets/core/lib/RcModule/RcModule.ts + +## How it works + +user trigger UI event -> method by `@proxify` -> transfer to background -> exec method by `@proxify` -> call stack -> call method by `@action` -> dispatch action -> transfer to clients with patches -> update clients UI + +## Practice + +### @proxify + +- The method decorated by @proxify must be asynchronous. + +```ts +class Call extends RcModuleV2 { + constructor(deps: Deps) { + super({ + deps, + }); + } + + @proxify + makeCall(phoneNumber: string) { // ❌ bad practice + // .... + } + + @proxify + async makeCall(phoneNumber: string) { // ✅ good practice + // .... + } +} +``` + +- The closer to UI call the method is decorated with @proxify. + +- The parameters of the method decorated by @proxify must be serializable. + +```ts +class ContactsList extends RcModuleV2 { + constructor(deps: Deps) { + super({ + deps, + }); + } + + @proxify + async addContactSources(contacts: Set) { // ❌ bad practice + // .... + } + + @proxify + async addContactSources(contacts: ContactSources[]) { // ✅ good practice + // .... + } +} +``` + diff --git a/packages/ringcentral-integration/enums/callResults.ts b/packages/ringcentral-integration/enums/callResults.ts index f9325e7ca7..2ed5ecffb4 100644 --- a/packages/ringcentral-integration/enums/callResults.ts +++ b/packages/ringcentral-integration/enums/callResults.ts @@ -50,5 +50,6 @@ export const callResults = ObjectMap.fromObject({ } as const); export type CallResultsKey = ObjectMapKey; +export type CallResultsValue = typeof callResults[CallResultsKey]; export default callResults; diff --git a/packages/ringcentral-integration/enums/phoneTypes.ts b/packages/ringcentral-integration/enums/phoneTypes.ts index 430ebe138b..88a53daae8 100644 --- a/packages/ringcentral-integration/enums/phoneTypes.ts +++ b/packages/ringcentral-integration/enums/phoneTypes.ts @@ -11,6 +11,7 @@ export const phoneTypes = ObjectMap.fromKeys([ 'phone', 'unknown', 'company', + 'contact', 'direct', 'fax', 'other', diff --git a/packages/ringcentral-widgets-test/html-report/crius-report.html b/packages/ringcentral-integration/html-report/crius-report.html similarity index 95% rename from packages/ringcentral-widgets-test/html-report/crius-report.html rename to packages/ringcentral-integration/html-report/crius-report.html index 41870eef9d..86b8b071f8 100644 --- a/packages/ringcentral-widgets-test/html-report/crius-report.html +++ b/packages/ringcentral-integration/html-report/crius-report.html @@ -16,7 +16,7 @@
- - diff --git a/packages/ringcentral-widgets-test/package.json b/packages/ringcentral-widgets-test/package.json index 06d3672b7c..86492180e3 100644 --- a/packages/ringcentral-widgets-test/package.json +++ b/packages/ringcentral-widgets-test/package.json @@ -22,15 +22,16 @@ "test:updateSnapshot": "jest --updateSnapshot", "test:debug": "node --inspect node_modules/.bin/jest --runInBand" }, + "testPaths": ["crius.config.js", "."], "dependencies": { - "@rc-ex/core": "^0.8.1", + "@rc-ex/core": "^0.9.3", "@ringcentral-integration/commons": "*", "@ringcentral-integration/babel-settings": "*", "@ringcentral-integration/core": "*", "@ringcentral-integration/i18n": "*", "@ringcentral-integration/locale-loader": "*", "@ringcentral-integration/phone-number": "*", - "@ringcentral/juno": "^1.8.5-beta.5034-128a9f16", + "@ringcentral/juno": "^1.11.2", "@ringcentral-integration/test-utils": "*", "@ringcentral/sdk": "^4.5.0", "@ringcentral/subscriptions": "^4.5.0", @@ -39,19 +40,20 @@ "coveralls": "^3.0.4", "dotenv": "^6.2.0", "enzyme": "^3.7.0", - "enzyme-adapter-react-16": "^1.6.0", + "@wojtekmaj/enzyme-adapter-react-17": "^0.6.3", "enzyme-to-json": "^3.3.4", "format-message": "^6.2.3", "fs-extra": "^9.0.1", "identity-obj-proxy": "^3.0.0", "jest-html-reporters": "2.0.3", + "mock-socket": "^9.0.3", "moment": "^2.24.0", "normalize-css": "^2.3.1", "pubnub": "^4.20.1", "ramda": "^0.27.0", "rc-tooltip": "^3.7.2", - "react": "^16.14.0", - "react-dom": "^16.14.0", + "react": "^17.0.2", + "react-dom": "^17.0.2", "react-redux": "^5.1.1", "react-router": "^3.0.0", "react-router-redux": "^4.0.7", @@ -61,7 +63,7 @@ "ringcentral-client": "^1.0.0-beta.2", "@ringcentral-integration/widgets": "*", "@ringcentral-integration/widgets-demo": "*", - "yargs": "^14.0.0" + "yargs": "^17.1.1" }, "jest": { "roots": ["/test"], @@ -80,12 +82,8 @@ "/test/support/shim.js", "/test/support/setup.js" ], - "snapshotSerializers": [ - "enzyme-to-json/serializer" - ], - "setupFilesAfterEnv": [ - "./jest.setup.js" - ], + "snapshotSerializers": ["enzyme-to-json/serializer"], + "setupFilesAfterEnv": ["./jest.setup.js"], "reporters": [ "default", [ @@ -101,7 +99,7 @@ "devDependencies": { "@types/jest": "^26.0.23", "jest": "^27.0.1", - "react-test-renderer": "^16.8.3" + "react-test-renderer": "^17.0.2" }, "ci": { "ringcentral-js-widgets": "**" diff --git a/packages/ringcentral-widgets-test/test/__mocks__/ringcentral-web-phone.js b/packages/ringcentral-widgets-test/test/__mocks__/ringcentral-web-phone.js index 332f2fcf3d..f432b96ad1 100644 --- a/packages/ringcentral-widgets-test/test/__mocks__/ringcentral-web-phone.js +++ b/packages/ringcentral-widgets-test/test/__mocks__/ringcentral-web-phone.js @@ -1,5 +1,6 @@ import Session from '../support/session'; +const webphoneCache = []; class Transport { constructor() { this._events = {}; @@ -60,7 +61,8 @@ class UserAgent { const sessionId = `${toNumber}-${Math.round( Math.random() * 1000000000, ).toString()}`; - const session = new Session({ + const session = new Session( + { id: sessionId, direction: 'Outbound', to: toNumber, @@ -88,6 +90,8 @@ class UserAgent { this._events = {}; } + removeListener() {} + get audioHelper() { return { setVolume() {}, @@ -107,12 +111,20 @@ class UserAgent { } } -export default class RingCentralWebphone { +class RingCentralWebphone { constructor() { this._userAgent = new UserAgent(); + + webphoneCache.push(this); } get userAgent() { return this._userAgent; } } + +RingCentralWebphone.getLastWebphone = function getLastWebphone() { + return webphoneCache[webphoneCache.length - 1]; +}; + +export default RingCentralWebphone; diff --git a/packages/ringcentral-widgets-test/test/__mocks__/ws.js b/packages/ringcentral-widgets-test/test/__mocks__/ws.js new file mode 100644 index 0000000000..62df1506df --- /dev/null +++ b/packages/ringcentral-widgets-test/test/__mocks__/ws.js @@ -0,0 +1,7 @@ +/* + * mock nodejs "ws" module + */ + +const { WebSocket } = require('mock-socket'); + +module.exports = WebSocket; diff --git a/packages/ringcentral-widgets-test/test/integration-test/messages/FaxMessages.spec.js b/packages/ringcentral-widgets-test/test/integration-test/messages/FaxMessages.spec.js index d5b6533c09..942984996e 100644 --- a/packages/ringcentral-widgets-test/test/integration-test/messages/FaxMessages.spec.js +++ b/packages/ringcentral-widgets-test/test/integration-test/messages/FaxMessages.spec.js @@ -49,7 +49,7 @@ describe('fax messages', () => { test('when have no fax permission should not show fax sub tab', async () => { wrapper = await getWrapper(); phone = wrapper.props().phone; - Object.defineProperty(phone.extensionFeatures, 'hasReadFaxPermission', { + Object.defineProperty(phone.appFeatures, 'hasReadFaxPermission', { value: false, }); wrapper.setProps({ phone }); @@ -67,7 +67,7 @@ describe('fax messages', () => { test('when have fax permission should show fax sub tab', async () => { wrapper = await getWrapper(); phone = wrapper.props().phone; - Object.defineProperty(phone.extensionFeatures, 'hasReadFexPermission', { + Object.defineProperty(phone.appFeatures, 'hasReadFexPermission', { value: true, }); wrapper.setProps({ phone }); @@ -538,7 +538,7 @@ describe('fax messages', () => { // Object.defineProperty(phone.tabManager, 'active', { // value: true, // }); - Object.defineProperty(phone.extensionFeatures, 'hasReadFaxPermission', { + Object.defineProperty(phone.appFeatures, 'hasReadFaxPermission', { value: true, }); await ensureLogin(phone.auth, { diff --git a/packages/ringcentral-widgets-test/test/integration-test/messages/SearchMessages.spec.js b/packages/ringcentral-widgets-test/test/integration-test/messages/SearchMessages.spec.js index 832c5f4e1e..74bd7c9cc5 100644 --- a/packages/ringcentral-widgets-test/test/integration-test/messages/SearchMessages.spec.js +++ b/packages/ringcentral-widgets-test/test/integration-test/messages/SearchMessages.spec.js @@ -18,7 +18,7 @@ beforeEach(async () => { wrapper.update(); panel = wrapper.find(ConversationsPanel).first(); const phone = wrapper.props().phone; - Object.defineProperty(phone.extensionFeatures, 'hasReadFaxPermission', { + Object.defineProperty(phone.appFeatures, 'hasReadFaxPermission', { value: true, }); // Object.defineProperty(phone.tabManager, 'active', { diff --git a/packages/ringcentral-widgets-test/test/integration-test/navigation/DynamicNavigations.spec.js b/packages/ringcentral-widgets-test/test/integration-test/navigation/DynamicNavigations.spec.js index 4ec13c478a..f8069b748e 100644 --- a/packages/ringcentral-widgets-test/test/integration-test/navigation/DynamicNavigations.spec.js +++ b/packages/ringcentral-widgets-test/test/integration-test/navigation/DynamicNavigations.spec.js @@ -1,9 +1,5 @@ -import * as mock from '@ringcentral-integration/commons/integration-test/mock'; import NavigationBar from '@ringcentral-integration/widgets/components/NavigationBar'; import TabNavigationButton from '@ringcentral-integration/widgets/components/TabNavigationButton'; -import DropdownNavigationView from '@ringcentral-integration/widgets/components/DropdownNavigationView'; -import DropdownNavigationItem from '@ringcentral-integration/widgets/components/DropdownNavigationItem'; - import { getWrapper } from '../shared'; let originalPhone = null; @@ -24,21 +20,18 @@ afterEach(async () => { * TODO: Consider generalize getTabs functions in each app into a NavigationTabsUI module, * and apply UT to the module. */ -describe.skip('dynamic navigationb bar', () => { +describe.skip('dynamic navigation bar', () => { test('navigation bar should be normal when has permissions', async () => { const phone = wrapper.props().phone; - Object.defineProperties(phone.rolesAndPermissions, { - callingEnabled: { value: true }, + Object.defineProperties(phone.appFeatures, { + isCallingEnabled: { value: true }, hasReadMessagesPermission: { value: true }, hasComposeTextPermission: { value: true }, - permissions: { - value: { - ...phone.rolesAndPermissions.permissions, - ReadCallLog: true, - OrganizeConference: true, - Meetings: true, - }, - }, + }); + Object.defineProperties(phone.extensionFeatures.features, { + Meetings: { value: { available: true } }, + ReadExtensionCallLog: { value: { available: true } }, + Conferencing: { value: { available: true } }, }); wrapper.setProps({ phone }); wrapper.update(); @@ -53,8 +46,8 @@ describe.skip('dynamic navigationb bar', () => { test('navigation bar should be dynamically customizable by permissions', () => { const phone = wrapper.props().phone; - Object.defineProperties(phone.rolesAndPermissions, { - callingEnabled: { value: false }, + Object.defineProperties(phone.appFeatures, { + isCallingEnabled: { value: false }, hasReadMessagesPermission: { value: false }, hasComposeTextPermission: { value: false }, }); @@ -78,23 +71,11 @@ describe.skip('dynamic navigationb bar', () => { test('should hide breadcrumbs when the number of nav items are less than or equals to 5', () => { const phone = wrapper.props().phone; - Object.defineProperty(phone.rolesAndPermissions, 'callingEnabled', { - value: false, + Object.defineProperties(phone.appFeatures, { + isCallingEnabled: { value: false }, + hasReadMessagesPermission: { value: false }, + hasComposeTextPermission: { value: false }, }); - Object.defineProperty( - phone.rolesAndPermissions, - 'hasReadMessagesPermission', - { - value: false, - }, - ); - Object.defineProperty( - phone.rolesAndPermissions, - 'hasComposeTextPermission', - { - value: false, - }, - ); wrapper.setProps({ phone }); wrapper.update(); const navigationBar = wrapper.find(NavigationBar).first(); @@ -103,10 +84,12 @@ describe.skip('dynamic navigationb bar', () => { ).toHaveLength(0); }); - test('should hide dialpad when no calling permsision', () => { + test('should hide dialpad when no calling permission', () => { const phone = wrapper.props().phone; - Object.defineProperty(phone.rolesAndPermissions, 'callingEnabled', { - value: false, + Object.defineProperties(phone.appFeatures, { + isCallingEnabled: { value: false }, + hasReadMessagesPermission: { value: true }, + hasComposeTextPermission: { value: true }, }); wrapper.setProps({ phone }); wrapper.update(); @@ -117,15 +100,13 @@ describe.skip('dynamic navigationb bar', () => { ).toHaveLength(0); }); - test('should hide composeText when no composeText permsision', () => { + test('should hide composeText when no composeText permission', () => { const phone = wrapper.props().phone; - Object.defineProperty( - phone.rolesAndPermissions, - 'hasComposeTextPermission', - { - value: false, - }, - ); + Object.defineProperties(phone.appFeatures, { + isCallingEnabled: { value: true }, + hasReadMessagesPermission: { value: true }, + hasComposeTextPermission: { value: false }, + }); wrapper.setProps({ phone }); wrapper.update(); const navigationBar = wrapper.find(NavigationBar).first(); @@ -136,60 +117,30 @@ describe.skip('dynamic navigationb bar', () => { test('should hide messages when no hasReadMessagesPermission', () => { const phone = wrapper.props().phone; - Object.defineProperty( - phone.rolesAndPermissions, - 'hasReadMessagesPermission', - { - value: false, - }, - ); - wrapper.setProps({ phone }); - wrapper.update(); - const navigationBar = wrapper.find(NavigationBar).first(); - expect( - navigationBar.find(TabNavigationButton).find({ label: 'Messages' }), - ).toHaveLength(0); - }); - - test('should hide meeting when no meeting permissions', () => { - const phone = wrapper.props().phone; - Object.defineProperties(phone.rolesAndPermissions, { - callingEnabled: { value: false }, + Object.defineProperties(phone.appFeatures, { + isCallingEnabled: { value: true }, hasReadMessagesPermission: { value: false }, hasComposeTextPermission: { value: false }, - permissions: { - value: { - ...phone.rolesAndPermissions.permissions, - ReadCallLog: false, - OrganizeConference: true, - Meetings: false, - }, - }, }); wrapper.setProps({ phone }); wrapper.update(); const navigationBar = wrapper.find(NavigationBar).first(); expect( - navigationBar - .find(TabNavigationButton) - .find({ label: 'Schedule Meeting' }), + navigationBar.find(TabNavigationButton).find({ label: 'Messages' }), ).toHaveLength(0); }); - test('should hide conference when no conference permissions', () => { + test('should hide meeting when no meeting permissions', () => { const phone = wrapper.props().phone; - Object.defineProperties(phone.rolesAndPermissions, { - callingEnabled: { value: false }, + Object.defineProperties(phone.appFeatures, { + isCallingEnabled: { value: false }, hasReadMessagesPermission: { value: false }, hasComposeTextPermission: { value: false }, - permissions: { - value: { - ...phone.rolesAndPermissions.permissions, - ReadCallLog: false, - OrganizeConference: false, - Meetings: false, - }, - }, + }); + Object.defineProperties(phone.extensionFeatures.features, { + Meetings: { value: { available: false } }, + ReadExtensionCallLog: { value: { available: false } }, + Conferencing: { value: { available: true } }, }); wrapper.setProps({ phone }); wrapper.update(); @@ -201,15 +152,18 @@ describe.skip('dynamic navigationb bar', () => { ).toHaveLength(0); }); - test('should hide history when no readCallLog permsision', () => { + test('should hide history when no ReadExtensionCallLog feature', () => { const phone = wrapper.props().phone; - Object.defineProperty( - phone.rolesAndPermissions.permissions, - 'ReadCallLog', - { - value: false, - }, - ); + Object.defineProperties(phone.appFeatures, { + isCallingEnabled: { value: true }, + hasReadMessagesPermission: { value: true }, + hasComposeTextPermission: { value: true }, + }); + Object.defineProperties(phone.extensionFeatures.features, { + Meetings: { value: { available: true } }, + ReadExtensionCallLog: { value: { available: false } }, + Conferencing: { value: { available: true } }, + }); wrapper.setProps({ phone }); wrapper.update(); const navigationBar = wrapper.find(NavigationBar).first(); @@ -219,37 +173,33 @@ describe.skip('dynamic navigationb bar', () => { ).toHaveLength(0); }); - test('should hide contacts when no calling and read messages permsision', () => { + test('should hide contacts when no calling and read messages permission', () => { const phone = wrapper.props().phone; - Object.defineProperty( - phone.rolesAndPermissions.permissions, - 'ReadCallLog', - { - value: false, - }, - ); - Object.defineProperty( - phone.rolesAndPermissions.permissions, - 'hasReadMessagesPermission', - { - value: true, - }, - ); + Object.defineProperties(phone.appFeatures, { + isCallingEnabled: { value: true }, + hasReadMessagesPermission: { value: true }, + hasComposeTextPermission: { value: true }, + }); + Object.defineProperties(phone.extensionFeatures.features, { + Meetings: { value: { available: true } }, + ReadExtensionCallLog: { value: { available: false } }, + Conferencing: { value: { available: true } }, + }); wrapper.setProps({ phone }); wrapper.update(); let navigationBar = wrapper.find(NavigationBar).first(); expect( navigationBar.find(TabNavigationButton).find({ label: 'Contacts' }), ).toHaveLength(1); - Object.defineProperty( - phone.rolesAndPermissions, - 'hasReadMessagesPermission', - { - value: false, - }, - ); - Object.defineProperty(phone.rolesAndPermissions, 'callingEnabled', { - value: false, + Object.defineProperties(phone.appFeatures, { + isCallingEnabled: { value: false }, + hasReadMessagesPermission: { value: false }, + hasComposeTextPermission: { value: true }, + }); + Object.defineProperties(phone.extensionFeatures.features, { + Meetings: { value: { available: true } }, + ReadExtensionCallLog: { value: { available: true } }, + Conferencing: { value: { available: true } }, }); wrapper.setProps({ phone }); wrapper.update(); diff --git a/packages/ringcentral-widgets-test/test/integration-test/settings/DynamicSettings.spec.js b/packages/ringcentral-widgets-test/test/integration-test/settings/DynamicSettings.spec.js index 5ff7019460..347c3e396f 100644 --- a/packages/ringcentral-widgets-test/test/integration-test/settings/DynamicSettings.spec.js +++ b/packages/ringcentral-widgets-test/test/integration-test/settings/DynamicSettings.spec.js @@ -21,7 +21,7 @@ describe.skip('dynamic setting page', () => { // TODO: consider removing this page since the definition of "normal" is vague and can change test('setting page should be normal when has permissions', async () => { const phone = wrapper.props().phone; - Object.defineProperty(phone.rolesAndPermissions, 'callingEnabled', { + Object.defineProperty(phone.appFeatures, 'isCallingEnabled', { value: true, }); wrapper.setProps({ phone }); @@ -30,29 +30,14 @@ describe.skip('dynamic setting page', () => { await navigationBar.props().goTo('/settings'); wrapper.update(); const settingsPanel = wrapper.find(SettingsPanel).first(); - expect( - settingsPanel - .find(LinkLine) - .at(0) - .text(), - ).toEqual('Calling'); - expect( - settingsPanel - .find(LinkLine) - .at(1) - .text(), - ).toEqual('Region'); - expect( - settingsPanel - .find(LinkLine) - .at(2) - .text(), - ).toEqual('Audio'); + expect(settingsPanel.find(LinkLine).at(0).text()).toEqual('Calling'); + expect(settingsPanel.find(LinkLine).at(1).text()).toEqual('Region'); + expect(settingsPanel.find(LinkLine).at(2).text()).toEqual('Audio'); }); test('should hide Calling, Region, Audio when not has calling permissions', async () => { const phone = wrapper.props().phone; - Object.defineProperty(phone.rolesAndPermissions, 'callingEnabled', { + Object.defineProperty(phone.appFeatures, 'isCallingEnabled', { value: false, }); wrapper.setProps({ phone }); diff --git a/packages/ringcentral-widgets-test/test/integration-test/shared.js b/packages/ringcentral-widgets-test/test/integration-test/shared.js index ffbfd06804..729179daca 100644 --- a/packages/ringcentral-widgets-test/test/integration-test/shared.js +++ b/packages/ringcentral-widgets-test/test/integration-test/shared.js @@ -6,13 +6,12 @@ import { ensureLogin } from '@ringcentral-integration/commons/integration-test/u import SimulateWindowObject from '@ringcentral-integration/commons/integration-test/utils/SimulateWindowObject'; import ClientHistoryRequest from '@ringcentral-integration/commons/integration-test/utils/ClientHistoryRequest'; import { waitUntilEqual } from '@ringcentral-integration/commons/integration-test/utils/WaitUtil'; - import { createPhone } from '@ringcentral-integration/widgets-demo/dev-server/Phone'; import App from '@ringcentral-integration/widgets-demo/dev-server/containers/App'; -import brandConfig from '@ringcentral-integration/widgets-demo/dev-server/brandConfig'; import version from '@ringcentral-integration/widgets-demo/dev-server/version'; import prefix from '@ringcentral-integration/widgets-demo/dev-server/prefix'; -import { subscriptionStatus } from '@ringcentral-integration/commons/modules/Subscription/subscriptionStatus'; +import ConfigData from '@ringcentral-integration/commons/modules/DynamicConfig/ConfigData.json'; +import { brandConfig } from '@ringcentral-integration/widgets-demo/dev-server/brandConfig'; export const timeout = (ms) => new Promise((resolve) => setTimeout(() => resolve(true), ms)); @@ -46,7 +45,7 @@ const getPhone = async ({ subscriptionRegisterDelay: 10, enableDiscovery: false, }); - + phone.dynamicConfig._source._props.fetchFunction = async () => ConfigData; const store = createStore(phone.reducer); phone.setStore(store); // mock.mockClient(phone.client); diff --git a/packages/ringcentral-widgets-test/test/support/WebphoneSessionMock.ts b/packages/ringcentral-widgets-test/test/support/WebphoneSessionMock.ts new file mode 100644 index 0000000000..7a1c7520d7 --- /dev/null +++ b/packages/ringcentral-widgets-test/test/support/WebphoneSessionMock.ts @@ -0,0 +1,43 @@ +class WebphoneSessionMock { + telephoneSessionId: string; + private _events: any; + + constructor(telephoneSessionId: string) { + this.telephoneSessionId = telephoneSessionId; + // mock events + this._events = {}; + } + + on(event: string, cb: () => {}) { + if (!this._events[event]) { + this._events[event] = []; + } + this._events[event].push(cb); + } + + trigger(event: string, ...args: []) { + if (this._events[event]) { + this._events[event].forEach((cb: () => {}) => { + cb(...args); + }); + } + } + + get request() { + const pRcApiIdsRaw = `party-id=${this.telephoneSessionId};session-id=${this.telephoneSessionId}`; + const callIDRaw = this.telephoneSessionId; + const request = { + headers: { + 'P-Rc-Api-Ids': [{ raw: pRcApiIdsRaw }], + 'Call-ID': [{ raw: callIDRaw }], + }, + }; + return request; + } + + get id() { + return this.telephoneSessionId; + } +} + +export default WebphoneSessionMock; diff --git a/packages/ringcentral-widgets-test/test/support/activeSessionCallHelper.ts b/packages/ringcentral-widgets-test/test/support/activeSessionCallHelper.ts new file mode 100644 index 0000000000..60d833b0a8 --- /dev/null +++ b/packages/ringcentral-widgets-test/test/support/activeSessionCallHelper.ts @@ -0,0 +1,77 @@ +import callDirections from '@ringcentral-integration/commons/enums/callDirections'; +import { + createTelephonySession, + PartyStatusCode, + telephonySessionBuildersCache, +} from '@ringcentral-integration/commons/integration-test/mock/telephonySessionBuilder'; +import WebphoneSessionMock from './WebphoneSessionMock'; +import { mockPubnub, mockWebphone } from './callHelper'; + +type normalStatus = 'ring' | 'connected'; + +type CallDirectionsKeys = keyof typeof callDirections; + +type CallDirections = typeof callDirections[CallDirectionsKeys]; + +interface InitACallProps { + phoneNumber?: string; + isWebRTC?: boolean; + direction?: CallDirections; + telephonySessionId?: string; + sessionId?: string; + status?: normalStatus; +} + +interface InitACallFunc { + (initParams: InitACallProps): any; +} + +const initACall: InitACallFunc = async ({ + phoneNumber, + isWebRTC = true, + direction = callDirections.outbound, + telephonySessionId = new Date().getTime().toString(), + sessionId = new Date().getTime().toString(), + status = 'ring', +}) => { + const partyStatus = + status === 'ring' ? PartyStatusCode.proceeding : PartyStatusCode.answered; + const telephonySessionBuilder = createTelephonySession({ + phoneNumber, + telephonySessionId, + direction, + sessionId, + status: partyStatus, + }); + + const telephoneSessionId = telephonySessionBuilder.telephoneSessionId; + + await mockPubnub(telephonySessionBuilder.done()); + + if (isWebRTC) { + const webSession = new WebphoneSessionMock(telephoneSessionId); + const callEvent = + direction === callDirections.inbound ? 'invite' : 'inviteSent'; + await mockWebphone(callEvent, webSession); + } +}; + +function getLastTelephonySessionBuilder() { + return telephonySessionBuildersCache[ + telephonySessionBuildersCache.length - 1 + ]; +} + +const connectLatestCall = async () => { + const telephonySessionBuilder = getLastTelephonySessionBuilder(); + telephonySessionBuilder.setConnected(); + await mockPubnub(telephonySessionBuilder.done()); +}; + +const disConnectLatestCall = async () => { + const telephonySessionBuilder = getLastTelephonySessionBuilder(); + telephonySessionBuilder.setDisconnected(); + await mockPubnub(telephonySessionBuilder.done()); +}; + +export { initACall, connectLatestCall, disConnectLatestCall }; diff --git a/packages/ringcentral-widgets-test/test/support/callHelper.js b/packages/ringcentral-widgets-test/test/support/callHelper.js index da2d42e8ff..01fede45fe 100644 --- a/packages/ringcentral-widgets-test/test/support/callHelper.js +++ b/packages/ringcentral-widgets-test/test/support/callHelper.js @@ -3,7 +3,8 @@ import subscriptionBody from '@ringcentral-integration/commons/integration-test/ import { isConferenceSession } from '@ringcentral-integration/commons/modules/Webphone/webphoneHelper'; import telephonyStatuses from '@ringcentral-integration/commons/enums/telephonyStatus'; import * as mock from '@ringcentral-integration/commons/integration-test/mock'; -import { getLastPubnub } from '../__mocks__/pubnub'; +import MockedPubNub, { getLastPubnub } from '../__mocks__/pubnub'; +import MockedWebphone from '../__mocks__/ringcentral-web-phone'; import Session, { CONFERENCE_SESSION_ID } from './session'; import { timeout } from '../integration-test/shared'; @@ -219,4 +220,30 @@ export function mockActiveCalls( }, mockOtherDeivce); } -export { CONFERENCE_SESSION_ID }; +async function mockPubnub(data) { + const pubnub = MockedPubNub.getLastPubnub(); + const encrypted = pubnub._realPubnub.encrypt( + JSON.stringify({ + ...data, + timestamp: new Date().toISOString(), + }), + subscriptionBody.deliveryMode.encryptionKey, + { + encryptKey: false, + keyEncoding: 'base64', + keyLength: 128, + mode: 'ecb', + }, + ); + pubnub.mockMessage(encrypted); + await timeout(2000); +} + +async function mockWebphone(eventName, webSession) { + const webphone = MockedWebphone.getLastWebphone() || new MockedWebphone(); + webphone.userAgent.trigger(eventName, webSession); + + await timeout(1000); +} + +export { CONFERENCE_SESSION_ID, mockPubnub, mockWebphone }; diff --git a/packages/ringcentral-widgets-test/test/support/setup.js b/packages/ringcentral-widgets-test/test/support/setup.js index 6e9457cf50..1e27a68a1c 100644 --- a/packages/ringcentral-widgets-test/test/support/setup.js +++ b/packages/ringcentral-widgets-test/test/support/setup.js @@ -1,6 +1,6 @@ import path from 'path'; import { configure } from 'enzyme'; -import Adapter from 'enzyme-adapter-react-16'; +import Adapter from '@wojtekmaj/enzyme-adapter-react-17'; configure({ adapter: new Adapter() }); diff --git a/packages/ringcentral-widgets-test/test/unit-test/MeetingCalendarHelper.unit.spec.ts b/packages/ringcentral-widgets-test/test/unit-test/MeetingCalendarHelper.unit.spec.ts index 1dcbbb1fe9..1d4a421fa4 100644 --- a/packages/ringcentral-widgets-test/test/unit-test/MeetingCalendarHelper.unit.spec.ts +++ b/packages/ringcentral-widgets-test/test/unit-test/MeetingCalendarHelper.unit.spec.ts @@ -10,6 +10,11 @@ import { } from '@ringcentral-integration/widgets/lib/MeetingCalendarHelper'; import { RcvMainParams } from '@ringcentral-integration/widgets/lib/MeetingCalendarHelper/index.interface'; import { getDefaultVideoSettings } from '@ringcentral-integration/commons/modules/RcVideoV2'; +import { + getRcmUriRegExp, + getRcvUriRegExp, +} from '@ringcentral-integration/commons/modules/DynamicConfig'; +import ConfigData from '@ringcentral-integration/commons/modules/DynamicConfig/ConfigData.json'; describe.each` meetingId | expected @@ -142,12 +147,14 @@ describe('formatTextToHtml', () => { test('all tabs replace with space', () => { const defaultMeetingSettings = getDefaultVideoSettings({ topic: 'rcv meeting topic', - startTime: new Date(), accountId: '111', extensionId: '222', }); const mockMeetingInfo = { - meeting: defaultMeetingSettings, + meeting: { + ...defaultMeetingSettings, + startTime: new Date(), + }, extensionInfo: { name: 'SystemNew', }, @@ -170,6 +177,57 @@ describe('formatTextToHtml', () => { }); }); +describe.each` + brand | rcvTeleconference | expected + ${'rc'} | ${'https://v.ringcentral.com/teleconference/'} | ${'https://v.ringcentral.com/teleconference/'} + ${'bt'} | ${'https://video.cloudwork.bt.com/teleconference'} | ${'https://video.cloudwork.bt.com/teleconference'} + ${'telus'} | ${'https://video.businessconnect.telus.com/teleconference'} | ${'https://video.businessconnect.telus.com/teleconference'} + ${'att'} | ${'https://meetings.officeathand.att.com/teleconference'} | ${'https://meetings.officeathand.att.com/teleconference'} +`( + '$brand rcv International numbers should be rcvTeleconference:', + ({ + brand, + rcvTeleconference, + expected, + }: { + brand: string; + rcvTeleconference: string; + expected: string; + }) => { + test(`returns ${expected}`, () => { + const defaultMeetingSettings = getDefaultVideoSettings({ + topic: 'rcv meeting topic', + accountId: '111', + extensionId: '222', + }); + const mockMeetingInfo = { + meeting: { + ...defaultMeetingSettings, + startTime: new Date(), + }, + extensionInfo: { + name: 'SystemNew', + }, + dialInNumber: '123456', + }; + const invitation = getRcvEventTpl( + mockMeetingInfo, + { + id: '1210', + code: brand, + name: 'RingCentral', + brandConfig: { + teleconference: '123', + }, + rcvTeleconference, + }, + 'en-US', + ); + expect(invitation).toMatch(new RegExp(expected, 'g')); + }); + }, +); + describe('getMeetingId', () => { describe.each` meetingLink | meetingId @@ -187,7 +245,11 @@ describe('getMeetingId', () => { meetingId: string; }) => { test(meetingLink, () => { - expect(getMeetingId(meetingLink)).toEqual(meetingId); + const rcvUriRegExp = getRcvUriRegExp(ConfigData.meetingUriReg.rcv); + const rcmUriRegExp = getRcmUriRegExp(ConfigData.meetingUriReg.rcm); + expect(getMeetingId(meetingLink, rcvUriRegExp, rcmUriRegExp)).toEqual( + meetingId, + ); }); }, ); @@ -203,7 +265,11 @@ describe('stripMeetingLinks', () => { 'Links of $text should be stripped -> $result', ({ text, result }: { text: string; result: string }) => { test(text, () => { - expect(stripMeetingLinks(text)).toEqual(result); + const rcvUriRegExp = getRcvUriRegExp(ConfigData.meetingUriReg.rcv); + const rcmUriRegExp = getRcmUriRegExp(ConfigData.meetingUriReg.rcm); + expect(stripMeetingLinks(text, rcvUriRegExp, rcmUriRegExp)).toEqual( + result, + ); }); }, ); diff --git a/packages/ringcentral-widgets/components/ActionMenuList/index.js b/packages/ringcentral-widgets/components/ActionMenuList/index.js index c844a76d38..faa578b235 100644 --- a/packages/ringcentral-widgets/components/ActionMenuList/index.js +++ b/packages/ringcentral-widgets/components/ActionMenuList/index.js @@ -213,6 +213,7 @@ export const PreviewButton = ({ title, onClick, disabled, className }) => { className={classnames(styles.button, styles.svgBtn, className)} onClick={onClick} disabled={disabled} + dataSign={title} > diff --git a/packages/ringcentral-widgets/components/ActiveCallItemV2/ActiveCallItem.interface.ts b/packages/ringcentral-widgets/components/ActiveCallItemV2/ActiveCallItem.interface.ts index 9a8857832b..09430c853a 100644 --- a/packages/ringcentral-widgets/components/ActiveCallItemV2/ActiveCallItem.interface.ts +++ b/packages/ringcentral-widgets/components/ActiveCallItemV2/ActiveCallItem.interface.ts @@ -66,6 +66,7 @@ export interface ActiveCallControlButtonsProps { webphoneHold?: (webphoneSessionId: string, telephonySessionId: string) => any; isConnecting?: boolean; clickSwitchTrack?: () => any; + isWide?: boolean; } interface Call { @@ -159,6 +160,7 @@ export interface ActiveCallItemProps { useCallDetailV2?: boolean; showIgnoreBtn?: boolean; clickSwitchTrack?: () => any; + isWide?: boolean; } export interface ActiveCallItemState { diff --git a/packages/ringcentral-widgets/components/ActiveCallItemV2/ActiveCallItem.tsx b/packages/ringcentral-widgets/components/ActiveCallItemV2/ActiveCallItem.tsx index 8e56d7c469..b4a860460e 100644 --- a/packages/ringcentral-widgets/components/ActiveCallItemV2/ActiveCallItem.tsx +++ b/packages/ringcentral-widgets/components/ActiveCallItemV2/ActiveCallItem.tsx @@ -680,29 +680,31 @@ export class ActiveCallItem extends Component< } onClickSwitchBtn = () => { + const { + renderContactName, + call, + modalConfirm, + isWide, + currentLocale, + webphoneSwitchCall, + } = this.props; const contactName = - typeof this.props.renderContactName === 'function' - ? this.props.renderContactName(this.props.call) + typeof renderContactName === 'function' + ? renderContactName(call) : undefined; // !refactor // TODO: Consider refactoring modalConfirm out of UI components!!!!!!!!!!!!!! - this.modalId = this.props.modalConfirm({ - size: 'small', - title: i18n.getString('callSwitch', this.props.currentLocale), + this.modalId = modalConfirm({ + size: isWide ? 'small' : 'xsmall', + title: i18n.getString('callSwitch', currentLocale), className: styles.switchDialog, contentProps: { contactName: contactName || this.getPhoneNumber(), }, - confirmButtonText: i18n.getString( - 'comfirmOKButton', - this.props.currentLocale, - ), - cancelButtonText: i18n.getString( - 'comfirmCancelButton', - this.props.currentLocale, - ), + confirmButtonText: i18n.getString('comfirmOKButton', currentLocale), + cancelButtonText: i18n.getString('comfirmCancelButton', currentLocale), onConfirm: () => { - this.props.webphoneSwitchCall(this.props.call); + webphoneSwitchCall(call); this.modalId = null; }, onCancel: () => { diff --git a/packages/ringcentral-widgets/components/ActiveCallList/index.js b/packages/ringcentral-widgets/components/ActiveCallList/index.js index f3ed0ebbcf..10ce4b0b40 100644 --- a/packages/ringcentral-widgets/components/ActiveCallList/index.js +++ b/packages/ringcentral-widgets/components/ActiveCallList/index.js @@ -73,6 +73,7 @@ const ActiveCallList = ({ newCallIcon, clickSwitchTrack, showMultipleMatch, + isWide, }) => { if (!calls.length) { return null; @@ -155,6 +156,7 @@ const ActiveCallList = ({ useCallDetailV2={useCallDetailV2} newCallIcon={newCallIcon} clickSwitchTrack={clickSwitchTrack} + isWide={isWide} /> ); })} @@ -220,9 +222,11 @@ ActiveCallList.propTypes = { useCallDetailV2: PropTypes.bool, newCallIcon: PropTypes.bool, clickSwitchTrack: PropTypes.func, + isWide: PropTypes.bool, }; ActiveCallList.defaultProps = { + isWide: true, className: undefined, brand: 'RingCentral', showContactDisplayPlaceholder: true, diff --git a/packages/ringcentral-widgets/components/ActiveCallsPanel/index.js b/packages/ringcentral-widgets/components/ActiveCallsPanel/index.js index 828dc58e0f..8fc32604e0 100644 --- a/packages/ringcentral-widgets/components/ActiveCallsPanel/index.js +++ b/packages/ringcentral-widgets/components/ActiveCallsPanel/index.js @@ -185,6 +185,7 @@ export default class ActiveCallsPanel extends Component { useCallDetailV2, newCallIcon, clickSwitchTrack, + isWide, } = this.props; return ( @@ -247,6 +248,7 @@ export default class ActiveCallsPanel extends Component { useCallDetailV2={useCallDetailV2} newCallIcon={newCallIcon} clickSwitchTrack={clickSwitchTrack} + isWide={isWide} /> ); } @@ -401,9 +403,11 @@ ActiveCallsPanel.propTypes = { useCallDetailV2: PropTypes.bool, newCallIcon: PropTypes.bool, clickSwitchTrack: PropTypes.func, + isWide: PropTypes.bool, }; ActiveCallsPanel.defaultProps = { + isWide: true, className: undefined, brand: 'RingCentral', showContactDisplayPlaceholder: true, diff --git a/packages/ringcentral-widgets/components/AlertRenderer/AlertRenderer.tsx b/packages/ringcentral-widgets/components/AlertRenderer/AlertRenderer.tsx index f88d6b565d..eda0262ec9 100644 --- a/packages/ringcentral-widgets/components/AlertRenderer/AlertRenderer.tsx +++ b/packages/ringcentral-widgets/components/AlertRenderer/AlertRenderer.tsx @@ -14,7 +14,7 @@ import MessageSenderAlert from './MessageSenderAlert'; import MessageStoreAlert from './MessageStoreAlert'; import RateExceededAlert from './RateExceededAlert'; import RegionSettingsAlert from './RegionSettingsAlert'; -import RolesAndPermissionsAlert from './RolesAndPermissionsAlert'; +import PermissionsAlert from './PermissionsAlert'; import WebphoneAlert from './WebphoneAlert'; export function AlertRenderer( @@ -54,6 +54,8 @@ export function AlertRenderer( {...props} brandCode={brand.code} brandName={brand.name} + shortBrandName={brand.shortName} + fullBrandName={brand.fullName} onCallingSettingsLinkClick={onCallingSettingsLinkClick} /> ); @@ -101,9 +103,9 @@ export function AlertRenderer( if (MeetingAlert.handleMessage(message)) { return (props) => ; } - if (RolesAndPermissionsAlert.handleMessage(message)) { + if (PermissionsAlert.handleMessage(message)) { return (props) => ( - { switch (message) { case callingSettingsMessages.saveSuccess: case callingSettingsMessages.saveSuccessWithSoftphone: @@ -24,9 +26,21 @@ function CallingSettingsAlert({ case callingSettingsMessages.saveSuccessWithJupiter: { let appName = brandName; if (message === callingSettingsMessages.saveSuccessWithJupiter) { - appName = getJupiterAppName(brandCode, brandName, currentLocale); + appName = getJupiterAppName({ + brandCode, + brandName, + currentLocale, + shortBrandName, + fullBrandName, + }); } else if (message === callingSettingsMessages.saveSuccessWithSoftphone) { - appName = getSoftphoneAppName(brandCode, brandName, currentLocale); + appName = getSoftphoneAppName({ + brandCode, + brandName, + currentLocale, + shortBrandName, + fullBrandName, + }); } return ( { let msg; switch (message) { case permissionsMessages.invalidTier: @@ -25,8 +25,8 @@ export default function RolesAndPermissionsAlert({ break; } return
{msg}
; -} -RolesAndPermissionsAlert.propTypes = { +}; +PermissionsAlert.propTypes = { message: PropTypes.shape({ message: PropTypes.string.isRequired, }).isRequired, @@ -35,10 +35,12 @@ RolesAndPermissionsAlert.propTypes = { currentLocale: PropTypes.string.isRequired, }; -RolesAndPermissionsAlert.defaultProps = { +PermissionsAlert.defaultProps = { application: undefined, }; -RolesAndPermissionsAlert.handleMessage = ({ message }) => +PermissionsAlert.handleMessage = ({ message }) => message === permissionsMessages.invalidTier || message === permissionsMessages.insufficientPrivilege; + +export default PermissionsAlert; diff --git a/packages/ringcentral-widgets/components/BasicCallInfo/BasicCallInfo.tsx b/packages/ringcentral-widgets/components/BasicCallInfo/BasicCallInfo.tsx index a8939353b5..c2b58b7692 100644 --- a/packages/ringcentral-widgets/components/BasicCallInfo/BasicCallInfo.tsx +++ b/packages/ringcentral-widgets/components/BasicCallInfo/BasicCallInfo.tsx @@ -94,8 +94,7 @@ export const BasicCallInfo: FunctionComponent = ({ {extraButton} - this.clickToSms({ countryCode, areaCode }) - : undefined - } - phoneNumber={phoneNumber} - disableLinks={disableLinks} - disableCallButton={disableCallButton} - disableClickToDial={disableClickToDial} - isLogging={isLogging || this.state.isLogging} - isLogged={activityMatches.length > 0} - isCreating={this.state.isCreating} - addLogTitle={i18n.getString('addLog', currentLocale)} - editLogTitle={i18n.getString('editLog', currentLocale)} - textTitle={i18n.getString('text', currentLocale)} - callTitle={i18n.getString('call', currentLocale)} - createEntityTitle={i18n.getString('addEntity', currentLocale)} - viewEntityTitle={i18n.getString('viewDetails', currentLocale)} - externalViewEntity={externalViewEntity && this.externalViewEntity} - externalHasEntity={ - externalHasEntity && externalHasEntity(this.props.call) - } - disableClickToSms={disableClickToSms} - withAnimation={withAnimation} - showChooseEntityModal={showChooseEntityModal} - /> + {shouldHideNumber ? null : ( + this.clickToSms({ countryCode, areaCode }) + : undefined + } + phoneNumber={phoneNumber} + disableLinks={shouldHideNumber || disableLinks} + disableCallButton={disableCallButton} + disableClickToDial={disableClickToDial} + isLogging={isLogging || this.state.isLogging} + isLogged={activityMatches.length > 0} + isCreating={this.state.isCreating} + addLogTitle={i18n.getString('addLog', currentLocale)} + editLogTitle={i18n.getString('editLog', currentLocale)} + textTitle={i18n.getString('text', currentLocale)} + callTitle={i18n.getString('call', currentLocale)} + createEntityTitle={i18n.getString('addEntity', currentLocale)} + viewEntityTitle={i18n.getString('viewDetails', currentLocale)} + externalViewEntity={externalViewEntity && this.externalViewEntity} + externalHasEntity={ + externalHasEntity && externalHasEntity(this.props.call) + } + disableClickToSms={disableClickToSms} + withAnimation={withAnimation} + showChooseEntityModal={showChooseEntityModal} + /> + )} ); } @@ -595,6 +602,7 @@ CallItem.propTypes = { currentSiteCode: PropTypes.string, isMultipleSiteEnabled: PropTypes.bool, showChooseEntityModal: PropTypes.bool, + enableCDC: PropTypes.bool, }; CallItem.defaultProps = { @@ -630,4 +638,5 @@ CallItem.defaultProps = { onSizeChanged: undefined, withAnimation: true, showChooseEntityModal: true, + enableCDC: false, }; diff --git a/packages/ringcentral-widgets/components/CallList/index.js b/packages/ringcentral-widgets/components/CallList/index.js index 6db61afc07..c85624fb66 100644 --- a/packages/ringcentral-widgets/components/CallList/index.js +++ b/packages/ringcentral-widgets/components/CallList/index.js @@ -45,6 +45,7 @@ export default class CallList extends PureComponent { externalViewEntity, externalHasEntity, readTextPermission, + enableCDC, } = this.props; if (calls && calls.length) { @@ -92,6 +93,7 @@ export default class CallList extends PureComponent { externalViewEntity={externalViewEntity} externalHasEntity={externalHasEntity} readTextPermission={readTextPermission} + enableCDC={enableCDC} /> ))} @@ -145,6 +147,7 @@ CallList.propTypes = { externalViewEntity: PropTypes.func, externalHasEntity: PropTypes.func, readTextPermission: PropTypes.bool, + enableCDC: PropTypes.bool, }; CallList.defaultProps = { @@ -181,4 +184,5 @@ CallList.defaultProps = { externalViewEntity: undefined, externalHasEntity: undefined, readTextPermission: true, + enableCDC: false, }; diff --git a/packages/ringcentral-widgets/components/CallListV2/index.js b/packages/ringcentral-widgets/components/CallListV2/index.js index 906453690c..a89ef065a0 100644 --- a/packages/ringcentral-widgets/components/CallListV2/index.js +++ b/packages/ringcentral-widgets/components/CallListV2/index.js @@ -97,6 +97,7 @@ export default class CallListV2 extends React.PureComponent { currentSiteCode, isMultipleSiteEnabled, showChooseEntityModal, + enableCDC, } = this.props; let content; @@ -156,6 +157,7 @@ export default class CallListV2 extends React.PureComponent { // disable animation when rendered with react-virtualized withAnimation={false} showChooseEntityModal={showChooseEntityModal} + enableCDC={enableCDC} /> ); } @@ -240,6 +242,7 @@ CallListV2.propTypes = { rowHeight: PropTypes.number, extendedRowHeight: PropTypes.number, showChooseEntityModal: PropTypes.bool, + enableCDC: PropTypes.bool, }; CallListV2.defaultProps = { @@ -279,4 +282,5 @@ CallListV2.defaultProps = { rowHeight: 65, extendedRowHeight: 130, showChooseEntityModal: true, + enableCDC: false, }; diff --git a/packages/ringcentral-widgets/components/CallLogCallCtrlComponent/CallLogDialpad/CallLogDialpad.tsx b/packages/ringcentral-widgets/components/CallLogCallCtrlComponent/CallLogDialpad/CallLogDialpad.tsx index 10d76767dd..944650b138 100644 --- a/packages/ringcentral-widgets/components/CallLogCallCtrlComponent/CallLogDialpad/CallLogDialpad.tsx +++ b/packages/ringcentral-widgets/components/CallLogCallCtrlComponent/CallLogDialpad/CallLogDialpad.tsx @@ -18,21 +18,31 @@ const CallLogDialpad: React.FunctionComponent = ({ isWide, }) => { const [value, setValue] = React.useState(''); - let audio: any; + const audioRef = React.useRef(null); React.useEffect(() => { if (typeof document !== 'undefined' && document.createElement) { - audio = document.createElement('audio'); + audioRef.current = document.createElement('audio'); } - }); + return () => { + if (audioRef.current) { + audioRef.current.remove(); + audioRef.current = null; + } + }; + }, []); const playAudio = (value: DtmfValue) => { - if (audio && audio.canPlayType('audio/ogg') !== '' && audios[value]) { - if (!audio.paused) { - audio.pause(); + if ( + audioRef.current && + audioRef.current.canPlayType('audio/ogg') !== '' && + audios[value] + ) { + if (!audioRef.current.paused) { + audioRef.current.pause(); } - audio.src = audios[value]; - audio.currentTime = 0; - audio.play(); + audioRef.current.src = audios[value]; + audioRef.current.currentTime = 0; + audioRef.current.play(); } }; diff --git a/packages/ringcentral-widgets/components/CallLogCallCtrlComponent/CallLogDialpad/styles.scss b/packages/ringcentral-widgets/components/CallLogCallCtrlComponent/CallLogDialpad/styles.scss index 5d581c5163..65254ed2b4 100644 --- a/packages/ringcentral-widgets/components/CallLogCallCtrlComponent/CallLogDialpad/styles.scss +++ b/packages/ringcentral-widgets/components/CallLogCallCtrlComponent/CallLogDialpad/styles.scss @@ -37,6 +37,7 @@ $dialpad-height-classic: $input-height + $input-margin-bottom-classic + } } .root { + width: 100%; box-sizing: border-box; position: fixed; bottom: 60px; diff --git a/packages/ringcentral-widgets/components/CallLogFields/CallLogFields.interface.ts b/packages/ringcentral-widgets/components/CallLogFields/CallLogFields.interface.ts index b18650c541..48a264b3d3 100644 --- a/packages/ringcentral-widgets/components/CallLogFields/CallLogFields.interface.ts +++ b/packages/ringcentral-widgets/components/CallLogFields/CallLogFields.interface.ts @@ -29,7 +29,12 @@ export type CallLogFieldsProps = { export interface FieldOption { getLabel: (item: any, length?: number, currentLog?: CallLog) => string; - getType: (item: any) => string; + getSelectedOptionLabel?: ( + item: any, + length?: number, + currentLog?: CallLog, + ) => string; + getType?: (item: any) => string; onChange: (item: any) => any; metadata?: FieldMetadata; currentOptionFinder: (task: Task) => (item: any) => boolean; @@ -45,6 +50,7 @@ export interface FieldOption { disableReason?: ReactNode | string; getValue?: (item: any) => any; foundFromServerEntityGetter?: (currentLog: CallLog) => any[]; + multiple?: boolean; } export interface FieldMetadata { diff --git a/packages/ringcentral-widgets/components/CallLogFields/CallLogFields.tsx b/packages/ringcentral-widgets/components/CallLogFields/CallLogFields.tsx index 77a874f08e..86eb5b21f1 100644 --- a/packages/ringcentral-widgets/components/CallLogFields/CallLogFields.tsx +++ b/packages/ringcentral-widgets/components/CallLogFields/CallLogFields.tsx @@ -29,7 +29,7 @@ export default class CallLogFields extends Component { const { currentLog: { customLogFields, - currentLogCall: { isAutoSave }, + currentLogCall: { isAutoSave } = {}, call, task = {} as Task, }, diff --git a/packages/ringcentral-widgets/components/CallLogFields/FieldItem/FieldItem.interface.ts b/packages/ringcentral-widgets/components/CallLogFields/FieldItem/FieldItem.interface.ts index a903f41820..432c602a1b 100644 --- a/packages/ringcentral-widgets/components/CallLogFields/FieldItem/FieldItem.interface.ts +++ b/packages/ringcentral-widgets/components/CallLogFields/FieldItem/FieldItem.interface.ts @@ -4,6 +4,7 @@ export type PickListOption = { label: string; value: any; disabled?: boolean; + title?: string; }; export type FieldItemType = @@ -21,6 +22,7 @@ export type FieldItemType = export type FieldItemOption = { label: string; + title?: string; type: FieldItemType; /** value key for task, that will get currentLog.task[value] to set this field value */ value: string; @@ -35,6 +37,7 @@ export type FieldItemOption = { onlyShowInMultipleMatches?: boolean; showOtherSection?: boolean; onChange?: (value?: any) => any; + multiple?: boolean; } & Pick; export type FieldsMap = { [p in FieldItemType]: () => JSX.Element }; diff --git a/packages/ringcentral-widgets/components/CallLogFields/FieldItem/FieldItem.tsx b/packages/ringcentral-widgets/components/CallLogFields/FieldItem/FieldItem.tsx index 3f90fcc92c..dbb9ddba62 100644 --- a/packages/ringcentral-widgets/components/CallLogFields/FieldItem/FieldItem.tsx +++ b/packages/ringcentral-widgets/components/CallLogFields/FieldItem/FieldItem.tsx @@ -68,10 +68,7 @@ export class FieldItem extends Component { showFoundFromServer, disabled, } = this.props; - const { - task, - currentLogCall: { phoneNumber }, - } = currentLog; + const { task, currentLogCall: { phoneNumber } = {} } = currentLog; const referenceFieldOption = referenceFieldOptions[value]; if (!referenceFieldOption) { console.warn( @@ -81,6 +78,7 @@ export class FieldItem extends Component { } const { getLabel, + getSelectedOptionLabel, getType, getValue: _getValue, onChange, @@ -97,6 +95,7 @@ export class FieldItem extends Component { foundFromServerEntityGetter, onBackClick, backHeaderClassName, + multiple, } = referenceFieldOption; const matchedEntities = matchedEntitiesGetter(currentLog); if (onlyShowInMultipleMatches && matchedEntities.length <= 1) { @@ -132,7 +131,14 @@ export class FieldItem extends Component { : undefined; const currentValue = - getLabel(currentOption, matchedEntities.length, currentLog) || ''; + (getSelectedOptionLabel && + getSelectedOptionLabel( + currentOption, + matchedEntities.length, + currentLog, + )) || + getLabel(currentOption, matchedEntities.length, currentLog) || + ''; return ( { helperText: disableReason, value: currentValue, }} + multiple={multiple} /> ); }; @@ -193,7 +200,15 @@ export class FieldItem extends Component { private renderTextArea = () => { const { - fieldOption: { label, value, error, helperText, required, onChange }, + fieldOption: { + label, + value, + error, + helperText, + required, + onChange, + disabled, + }, onSave, } = this.props; return ( @@ -205,6 +220,7 @@ export class FieldItem extends Component { placeholder={label} data-sign={value} multiline + disabled={disabled} value={this.currentValue || ''} onChange={(text: any) => { this._updateValue(value, text, onSave); @@ -285,22 +301,27 @@ export class FieldItem extends Component { let value: string = item as any; let label = item !== null ? (item as any) : appDefaultValue; let disabled = false; + let title; if (item instanceof Object) { value = item.value; label = item.label; disabled = item.disabled; + title = item?.title; } + return { label, value, disabled, + title, }; }); return ( { return (
{this.fieldsRenderMap[type]()} diff --git a/packages/ringcentral-widgets/components/CallLogFields/FieldItem/SelectField/SelectField.tsx b/packages/ringcentral-widgets/components/CallLogFields/FieldItem/SelectField/SelectField.tsx index e71ae92401..794798fdec 100644 --- a/packages/ringcentral-widgets/components/CallLogFields/FieldItem/SelectField/SelectField.tsx +++ b/packages/ringcentral-widgets/components/CallLogFields/FieldItem/SelectField/SelectField.tsx @@ -24,7 +24,7 @@ export const SelectField: FunctionComponent = ({ value={!item.value ? undefined : `${item.value}`} data-sign={`option${i}`} disabled={item.disabled} - title={item.title} + title={item.label} > {item.label} diff --git a/packages/ringcentral-widgets/components/CallLogFields/FieldItem/styles.scss b/packages/ringcentral-widgets/components/CallLogFields/FieldItem/styles.scss index 1127b69bb2..ccacfcf3da 100644 --- a/packages/ringcentral-widgets/components/CallLogFields/FieldItem/styles.scss +++ b/packages/ringcentral-widgets/components/CallLogFields/FieldItem/styles.scss @@ -14,6 +14,7 @@ } .selectLabel { + white-space: nowrap; text-overflow: ellipsis; overflow: hidden; } diff --git a/packages/ringcentral-widgets/components/CallLogPanel/CallLog.interface.ts b/packages/ringcentral-widgets/components/CallLogPanel/CallLog.interface.ts index 14bf404ca9..f8fee8c335 100644 --- a/packages/ringcentral-widgets/components/CallLogPanel/CallLog.interface.ts +++ b/packages/ringcentral-widgets/components/CallLogPanel/CallLog.interface.ts @@ -19,6 +19,10 @@ export interface CallLog { logName?: string; customLogFields?: FieldItemOption[]; disableSaveLog?: boolean; + foundFromServerEntities?: { + name: SfEntity[]; + relatedTo: SfEntity[]; + }; } export interface Call { @@ -124,6 +128,8 @@ export interface Task { calldisposition?: string; calldurationinseconds?: number; recording_information__c?: string; + isEdited?: boolean; + isLogged?: boolean; } export interface NavigateToEntities { diff --git a/packages/ringcentral-widgets/components/CallLogPanel/CallLogPanel.interface.tsx b/packages/ringcentral-widgets/components/CallLogPanel/CallLogPanel.interface.tsx index dce1312773..02fd1e89c5 100644 --- a/packages/ringcentral-widgets/components/CallLogPanel/CallLogPanel.interface.tsx +++ b/packages/ringcentral-widgets/components/CallLogPanel/CallLogPanel.interface.tsx @@ -34,6 +34,8 @@ export interface CallLogPanelProps extends CallLogPanelConfig { onHangup: (...args: any[]) => any; renderKeypadPanel: (...args: any[]) => any; renderSaveLogButton: (...args: any[]) => JSX.Element; + getRenderLogButton?: () => JSX.Element; + buttonStatus: { buttonDisabled: boolean; buttonContent: string }; additionalInfo?: object; onUpdateCallLog?: (data: { task }, id: string) => any; diff --git a/packages/ringcentral-widgets/components/CallLogPanel/CallLogPanel.tsx b/packages/ringcentral-widgets/components/CallLogPanel/CallLogPanel.tsx index f2154667b5..877232942d 100644 --- a/packages/ringcentral-widgets/components/CallLogPanel/CallLogPanel.tsx +++ b/packages/ringcentral-widgets/components/CallLogPanel/CallLogPanel.tsx @@ -121,6 +121,7 @@ export default class CallLogPanel extends Component {
{renderCallLogCallControl && renderCallLogCallControl( @@ -330,6 +331,7 @@ export default class CallLogPanel extends Component { isInTransferPage, isWide, children, + getRenderLogButton, } = this.props; if (!currentIdentify || isInTransferPage) return null; @@ -347,7 +349,7 @@ export default class CallLogPanel extends Component { currentLocale={currentLocale} backIcon={backIcon} isWide={isWide} - rightIcon={this.genSaveLogButtonV2()} + rightIcon={getRenderLogButton?.() || this.genSaveLogButtonV2()} title={i18n.getString(headerTitle, currentLocale)} className={classnames(styles.header, backHeader)} onBackClick={() => this.goBack()} diff --git a/packages/ringcentral-widgets/components/CallingSettingsPanel/CallingSettingsPanel.tsx b/packages/ringcentral-widgets/components/CallingSettingsPanel/CallingSettingsPanel.tsx index 2baf67c303..d665471802 100644 --- a/packages/ringcentral-widgets/components/CallingSettingsPanel/CallingSettingsPanel.tsx +++ b/packages/ringcentral-widgets/components/CallingSettingsPanel/CallingSettingsPanel.tsx @@ -45,7 +45,9 @@ export function getJupiterAppName({ brandName, shortBrandName, fullBrandName, + jupiterAppName, }: GetOptionNameProps): string { + if (jupiterAppName) return jupiterAppName; switch (brandCode) { case 'att': return fullBrandName; @@ -79,6 +81,7 @@ export function getCallingOptionName({ shortBrandName, fullBrandName, currentLocale, + jupiterAppName, }: GetCallingOptionProps) { if (callingOption === callingOptions.softphone) { return getSoftphoneAppName({ @@ -94,6 +97,7 @@ export function getCallingOptionName({ brandName, shortBrandName, fullBrandName, + jupiterAppName, }); } if (callingOption === callingOptions.ringout) { @@ -111,6 +115,7 @@ const Tooltip: FunctionComponent = ({ tooltipContainerRef, shortBrandName, fullBrandName, + jupiterAppName, }) => { const keys = [`${callWith}Tooltip`]; if ( @@ -127,6 +132,7 @@ const Tooltip: FunctionComponent = ({ currentLocale, shortBrandName, fullBrandName, + jupiterAppName, }); const overlay = (
@@ -165,6 +171,7 @@ const CallWithSettings: FunctionComponent = ({ currentLocale, disabled, onCallWithChange, + jupiterAppName, }) => { const tooltipContainerRef = useRef(null); @@ -176,6 +183,7 @@ const CallWithSettings: FunctionComponent = ({ currentLocale, shortBrandName, fullBrandName, + jupiterAppName, }); return optionName; }; @@ -194,6 +202,7 @@ const CallWithSettings: FunctionComponent = ({ tooltipContainerRef, shortBrandName, fullBrandName, + jupiterAppName, }} /> @@ -326,6 +335,7 @@ const CallingSettings: FunctionComponent = ({ defaultOutgoingAudioFile, shortBrandName, fullBrandName, + jupiterAppName, }) => { const [callWithState, setCallWithState] = useState(callWith); const [ringoutPromptState, setRingoutPromptState] = useState(ringoutPrompt); @@ -363,6 +373,7 @@ const CallingSettings: FunctionComponent = ({ brandCode, brandName, callWith: callWithState, + jupiterAppName, callWithOptions, currentLocale, disabled, diff --git a/packages/ringcentral-widgets/components/CallingSettingsPanel/CallingSettingsPenal.interface.ts b/packages/ringcentral-widgets/components/CallingSettingsPanel/CallingSettingsPenal.interface.ts index cce0d48123..2b8bc3a879 100644 --- a/packages/ringcentral-widgets/components/CallingSettingsPanel/CallingSettingsPenal.interface.ts +++ b/packages/ringcentral-widgets/components/CallingSettingsPanel/CallingSettingsPenal.interface.ts @@ -27,6 +27,7 @@ export interface CallingSettingsProps extends RingtoneBaseProps { myLocation: string; ringoutPrompt: boolean; onSave: (options: SaveFunctionProps) => void; + jupiterAppName?: string; } export interface CallingSettingsPanelProps extends CallingSettingsProps { showSpinner?: boolean; @@ -41,6 +42,7 @@ export interface GetOptionNameProps { shortBrandName: string; fullBrandName: string; currentLocale?: string; + jupiterAppName?: string; } export interface GetCallingOptionProps extends GetOptionNameProps { diff --git a/packages/ringcentral-widgets/components/CallsListPanel/index.js b/packages/ringcentral-widgets/components/CallsListPanel/index.js index a6fbc886cd..1e80e0ffac 100644 --- a/packages/ringcentral-widgets/components/CallsListPanel/index.js +++ b/packages/ringcentral-widgets/components/CallsListPanel/index.js @@ -234,7 +234,7 @@ export default class CallsListPanel extends React.PureComponent { }); } - componentWillReceiveProps(nextProps) { + UNSAFE_componentWillReceiveProps(nextProps) { if ( this.hasCalls(this.props) && !this.hasCalls(nextProps) && @@ -408,6 +408,7 @@ export default class CallsListPanel extends React.PureComponent { children, adaptive, showChooseEntityModal, + enableCDC, } = this.props; const { contentWidth, contentHeight } = this.state; @@ -456,6 +457,7 @@ export default class CallsListPanel extends React.PureComponent { externalHasEntity={externalHasEntity} readTextPermission={isShowMessageIcon} showChooseEntityModal={showChooseEntityModal} + enableCDC={enableCDC} /> ) : ( ); @@ -686,6 +689,7 @@ CallsListPanel.propTypes = { onlyHistory: PropTypes.bool, adaptive: PropTypes.bool, showChooseEntityModal: PropTypes.bool, + enableCDC: PropTypes.bool, }; CallsListPanel.defaultProps = { @@ -748,4 +752,5 @@ CallsListPanel.defaultProps = { children: null, onlyHistory: false, showChooseEntityModal: true, + enableCDC: false, }; diff --git a/packages/ringcentral-widgets/components/ComposeTextPanel/index.js b/packages/ringcentral-widgets/components/ComposeTextPanel/index.js index 2f3a511988..b1c2014c89 100644 --- a/packages/ringcentral-widgets/components/ComposeTextPanel/index.js +++ b/packages/ringcentral-widgets/components/ComposeTextPanel/index.js @@ -103,7 +103,7 @@ class ComposeTextPanel extends Component { { let contentEl; phoneNumber = formatNumber({ @@ -224,14 +226,17 @@ const ContactDisplay = ({ disabled={disabled || isLogging} options={options} placeholder={selectPlaceholder} - renderFunction={(entity) => - ContactDisplayItem({ - entityName: entity.name, - entityType: entity.entityType, - brand, - currentLocale, - sourceIcons, - }) + dropdownClassName={dropdownClassName} + renderFunction={ + dropdownRenderFunction || + ((entity) => + ContactDisplayItem({ + entityName: entity.name, + entityType: entity.entityType, + brand, + currentLocale, + sourceIcons, + })) } renderValue={(value) => displayFormatter({ @@ -297,6 +302,8 @@ ContactDisplay.propTypes = { showGroupNumberName: PropTypes.bool, contactName: PropTypes.any, iconClassName: PropTypes.string, + dropdownRenderFunction: PropTypes.func, + dropdownClassName: PropTypes.string, }; ContactDisplay.defaultProps = { @@ -324,6 +331,8 @@ ContactDisplay.defaultProps = { showGroupNumberName: false, contactName: undefined, iconClassName: null, + dropdownRenderFunction: undefined, + dropdownClassName: null, }; export default ContactDisplay; diff --git a/packages/ringcentral-widgets/components/ConversationList/index.js b/packages/ringcentral-widgets/components/ConversationList/index.js index 8eaa598692..9f65335847 100644 --- a/packages/ringcentral-widgets/components/ConversationList/index.js +++ b/packages/ringcentral-widgets/components/ConversationList/index.js @@ -116,6 +116,7 @@ ConversationList.propTypes = { loadNextPage: PropTypes.func, loadingNextPage: PropTypes.bool, renderExtraButton: PropTypes.func, + enableCDC: PropTypes.bool, }; ConversationList.defaultProps = { currentSiteCode: '', @@ -135,4 +136,5 @@ ConversationList.defaultProps = { loadingNextPage: false, typeFilter: undefined, renderExtraButton: undefined, + enableCDC: false, }; diff --git a/packages/ringcentral-widgets/components/ConversationPanel/index.js b/packages/ringcentral-widgets/components/ConversationPanel/index.js index 4e894f1f40..71c7a36688 100644 --- a/packages/ringcentral-widgets/components/ConversationPanel/index.js +++ b/packages/ringcentral-widgets/components/ConversationPanel/index.js @@ -1,16 +1,15 @@ -import React, { Component } from 'react'; -import PropTypes from 'prop-types'; import { RcAlert } from '@ringcentral/juno'; +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; import dynamicsFont from '../../assets/DynamicsFont/DynamicsFont.scss'; - -import { SpinnerOverlay } from '../SpinnerOverlay'; +import { checkShouldHidePhoneNumber } from '../../lib/checkShouldHidePhoneNumber'; +import ContactDisplay from '../ContactDisplay'; import ConversationMessageList from '../ConversationMessageList'; import LogButton from '../LogButton'; -import ContactDisplay from '../ContactDisplay'; import MessageInput from '../MessageInput'; - -import styles from './styles.scss'; +import { SpinnerOverlay } from '../SpinnerOverlay'; import i18n from './i18n'; +import styles from './styles.scss'; class ConversationPanel extends Component { constructor(props) { @@ -248,6 +247,10 @@ class ConversationPanel extends Component { } = this.props.conversation; const groupNumbers = this.getGroupPhoneNumbers(); const phoneNumber = this.getPhoneNumber(); + // TODO: Confirm on group messages similar to MessageItem + const shouldHideNumber = + this.props.enableCDC && + checkShouldHidePhoneNumber(phoneNumber, correspondentMatches); const fallbackName = this.getFallbackContactName(); const extraButton = this.props.renderExtraButton ? this.props.renderExtraButton(this.props.conversation, { @@ -281,7 +284,7 @@ class ConversationPanel extends Component { fallBackName={fallbackName} areaCode={this.props.areaCode} countryCode={this.props.countryCode} - phoneNumber={phoneNumber} + phoneNumber={shouldHideNumber ? null : phoneNumber} groupNumbers={groupNumbers} showType={false} currentLocale={this.props.currentLocale} @@ -292,6 +295,8 @@ class ConversationPanel extends Component { phoneTypeRenderer={this.props.phoneTypeRenderer} phoneSourceNameRenderer={this.props.phoneSourceNameRenderer} showGroupNumberName={this.props.showGroupNumberName} + dropdownRenderFunction={this.props.renderContactList} + dropdownClassName={this.props.dropdownClassName} /> this.props.goBack()} @@ -320,7 +325,8 @@ class ConversationPanel extends Component { ; @@ -233,6 +236,9 @@ export default class ConversationsPanel extends Component { showChooseEntityModal={showChooseEntityModal} shouldLogSelectRecord={shouldLogSelectRecord} onSelectContact={onSelectContact} + renderContactList={renderContactList} + dropdownClassName={dropdownClassName} + enableCDC={enableCDC} /> ) : ( !loadingNextPage && @@ -336,6 +342,9 @@ ConversationsPanel.propTypes = { showChooseEntityModal: PropTypes.bool, shouldLogSelectRecord: PropTypes.bool, onSelectContact: PropTypes.func, + renderContactList: PropTypes.func, + dropdownClassName: PropTypes.string, + enableCDC: PropTypes.bool, }; ConversationsPanel.defaultProps = { @@ -384,4 +393,7 @@ ConversationsPanel.defaultProps = { showChooseEntityModal: true, shouldLogSelectRecord: false, onSelectContact: undefined, + renderContactList: undefined, + dropdownClassName: null, + enableCDC: false, }; diff --git a/packages/ringcentral-widgets/components/DialButton/DialButton.tsx b/packages/ringcentral-widgets/components/DialButton/DialButton.tsx index a61c55eeb6..d8a42eba8e 100644 --- a/packages/ringcentral-widgets/components/DialButton/DialButton.tsx +++ b/packages/ringcentral-widgets/components/DialButton/DialButton.tsx @@ -1,10 +1,10 @@ import classnames from 'classnames'; import React, { Component } from 'react'; - -import audios from './audios'; +import { audios } from './audios'; import styles from './styles.scss'; const ALTERNATIVE_TIMEOUT = 1000; +let player: HTMLAudioElement = null; interface DialButtonProps { btn: { @@ -46,32 +46,27 @@ export default class DialButton extends Component< audio: HTMLAudioElement; - constructor(props: DialButtonProps, ...args) { + constructor(props: DialButtonProps, ...args: any[]) { super(props, ...args); - if ( - typeof document !== 'undefined' && - document.createElement && - audios[props.btn.value] - ) { - this.audio = document.createElement('audio'); - this.audio.src = audios[props.btn.value]; + if (typeof document !== 'undefined' && document.createElement && !player) { + player = document.createElement('audio'); } } onMouseDown = (e) => { e.preventDefault(); - if (this.audio && this.audio.canPlayType('audio/ogg') !== '') { - this.audio.volume = this.props.volume; - this.audio.muted = this.props.muted; - this.audio.currentTime = 0; - // on Edge, audio.play() could only use at the first time - // so we reset the src of the audio when using audio.play() - if (this.isEdge) { - this.audio.src = audios[this.props.btn.value]; - } - this.audio.play(); + if ( + player && + player.canPlayType('audio/ogg') !== '' && + audios[this.props.btn?.value] + ) { + player.volume = this.props.volume; + player.muted = this.props.muted; + player.src = audios[this.props.btn.value]; + player.currentTime = 0; + player.play(); } if (typeof this.props.onPress === 'function') { this.props.onPress(this.props.btn.value); diff --git a/packages/ringcentral-widgets/components/DialButton/audios.ts b/packages/ringcentral-widgets/components/DialButton/audios.ts index 44843ddda4..22359725c8 100644 --- a/packages/ringcentral-widgets/components/DialButton/audios.ts +++ b/packages/ringcentral-widgets/components/DialButton/audios.ts @@ -1,5 +1,4 @@ -/* eslint-disable */ -export default { +export const audios: Record = { '1': 'data:audio/ogg;base64,T2dnUwACAAAAAAAAAAB0Nx8FAAAAALH2CDABHgF2b3JiaXMAAAAAAUSsAAAAAAAAMKkDAAAAAAC4AU9nZ1MAAAAAAAAAAAAAdDcfBQEAAADtBChfET3////////////////////VA3ZvcmJpcy0AAABYaXBoLk9yZyBsaWJWb3JiaXMgSSAyMDEwMTEwMSAoU2NoYXVmZW51Z2dldCkAAAAAAQV2b3JiaXMrQkNWAQAIAAAAMUwgxYDQkFUAABAAAGAkKQ6TZkkppZShKHmYlEhJKaWUxTCJmJSJxRhjjDHGGGOMMcYYY4wgNGQVAAAEAIAoCY6j5klqzjlnGCeOcqA5aU44pyAHilHgOQnC9SZjbqa0pmtuziklCA1ZBQAAAgBASCGFFFJIIYUUYoghhhhiiCGHHHLIIaeccgoqqKCCCjLIIINMMumkk0466aijjjrqKLTQQgsttNJKTDHVVmOuvQZdfHPOOeecc84555xzzglCQ1YBACAAAARCBhlkEEIIIYUUUogppphyCjLIgNCQVQAAIACAAAAAAEeRFEmxFMuxHM3RJE/yLFETNdEzRVNUTVVVVVV1XVd2Zdd2ddd2fVmYhVu4fVm4hVvYhV33hWEYhmEYhmEYhmH4fd/3fd/3fSA0ZBUAIAEAoCM5luMpoiIaouI5ogOEhqwCAGQAAAQAIAmSIimSo0mmZmquaZu2aKu2bcuyLMuyDISGrAIAAAEABAAAAAAAoGmapmmapmmapmmapmmapmmapmmaZlmWZVmWZVmWZVmWZVmWZVmWZVmWZVmWZVmWZVmWZVmWZVmWZVlAaMgqAEACAEDHcRzHcSRFUiTHciwHCA1ZBQDIAAAIAEBSLMVyNEdzNMdzPMdzPEd0RMmUTM30TA8IDVkFAAACAAgAAAAAAEAxHMVxHMnRJE9SLdNyNVdzPddzTdd1XVdVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVgdCQVQAABAAAIZ1mlmqACDOQYSA0ZBUAgAAAABihCEMMCA1ZBQAABAAAiKHkIJrQmvPNOQ6a5aCpFJvTwYlUmye5qZibc84555xszhnjnHPOKcqZxaCZ0JpzzkkMmqWgmdCac855EpsHranSmnPOGeecDsYZYZxzzmnSmgep2Vibc85Z0JrmqLkUm3POiZSbJ7W5VJtzzjnnnHPOOeecc86pXpzOwTnhnHPOidqba7kJXZxzzvlknO7NCeGcc84555xzzjnnnHPOCUJDVgEAQAAABGHYGMadgiB9jgZiFCGmIZMedI8Ok6AxyCmkHo2ORkqpg1BSGSeldILQkFUAACAAAIQQUkghhRRSSCGFFFJIIYYYYoghp5xyCiqopJKKKsoos8wyyyyzzDLLrMPOOuuwwxBDDDG00kosNdVWY4215p5zrjlIa6W11lorpZRSSimlIDRkFQAAAgBAIGSQQQYZhRRSSCGGmHLKKaegggoIDVkFAAACAAgAAADwJM8RHdERHdERHdERHdERHc/xHFESJVESJdEyLVMzPVVUVVd2bVmXddu3hV3Ydd/Xfd/XjV8XhmVZlmVZlmVZlmVZlmVZlmUJQkNWAQAgAAAAQgghhBRSSCGFlGKMMcecg05CCYHQkFUAACAAgAAAAABHcRTHkRzJkSRLsiRN0izN8jRP8zTRE0VRNE1TFV3RFXXTFmVTNl3TNWXTVWXVdmXZtmVbt31Ztn3f933f933f933f933f13UgNGQVACABAKAjOZIiKZIiOY7jSJIEhIasAgBkAAAEAKAojuI4jiNJkiRZkiZ5lmeJmqmZnumpogqEhqwCAAABAAQAAAAAAKBoiqeYiqeIiueIjiiJlmmJmqq5omzKruu6ruu6ruu6ruu6ruu6ruu6ruu6ruu6ruu6ruu6ruu6ruu6QGjIKgBAAgBAR3IkR3IkRVIkRXIkBwgNWQUAyAAACADAMRxDUiTHsixN8zRP8zTREz3RMz1VdEUXCA1ZBQAAAgAIAAAAAADAkAxLsRzN0SRRUi3VUjXVUi1VVD1VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVXVNE3TNIHQkJUAABkAAOjFCCGEEJKjlloQvlfKOSg1914xZhTE3nulmEGOcvCZYko5KLWnzjGliJFcWyuRIsRhDjpVTimoQefWSQgtB0JDVgQAUQAAAEKIMcQYYoxByCBEjDEIGYSIMQYhg9BBCCWFlDIIIZWQUsQYg9BBySCElEJJGZSQUkilAACAAAcAgAALodCQFQFAnAAAgpBziDEIFWMQOgipdBBSqhiDkDknJXMOSiglpRBKShVjEDLnJGTOSQklpBRKSamDkFIopaVQSmoppRhTSi12EFIKpaQUSmkptRRbSi3GijEImXNSMuekhFJaCqWkljknpYOQUgehlJJSa6Wk1jLnpHTQSekglFJSaamU1FooJbWSUmslldZaazGm1mIMpaQUSmmtpNRiaim21lqsFWMQMuekZM5JCaWkFEpJLXNOSgchlc5BKSWV1kpJqWXOSekglNJBKKWk0lpJpbVQSkslpdZCKa211mJMqbUaSkmtpNRaSam11FqtrbUYOwgphVJaCqW0llqKMaUWYyiltZJSayWl1lprtbbWYgyltFRSaa2k1FpqrcbWWqyppRhTazG21mqNMcYcY805pRRjainG1FqMLbYcY6w1dxBSCqWkFkpJLbUUY2otxlBKaiWV1kpJLbbWakytxRpKaa2k1FpJqbXWWo2ttRpTSjGm1mpMqcUYY8y1tRhzai3G1lqsqbUYY6w1xxhrLQAAYMABACDAhDJQaMhKACAKAAAxBiHGnDMIKcUYhMYgpRiDECnFmHMQIqUYcw5CxphzEErJGHMOQikdhBJKSamDEEopKRUAAFDgAAAQYIOmxOIAhYasBABCAgAYhJRizDnnIJSSUoSQUow55xyEUlKKEFKKMeecg1BKSpVSTDHmHIRSUmqpUkoxxpyDUEpKqWWMMeYchBBKSam1jDHGnIMQQikptdY55xx0EkpJpaXYOuecgxBKKSWl1lrnHIQQSkmlpdZi65yDEEIpJaXUWoshhFJKSSWllmKLMYRSSiklpZRaizGWVFJKqaXWYouxxlJKSiml1lqLMcaaUmqptdZijLHGWlNKqbXWWosxxlprAQAABw4AAAFG0ElGlUXYaMKFB6DQkBUBQBQAAGAMYgwxhpxzEDIIkXMMQgchcs5J6aRkUkJpIaVMSkglpBY556R0UjIpoaVQUiYlpFRaKQAA7MABAOzAQig0ZCUAkAcAACGkFGOMMYaUUooxxhxDSinFGGOMKaUYY4wx55RSjDHGmHOMMcYcc845xhhjzDnnHGPMMeecc44xxpxzzjnHHHPOOeecY84555xzzgkAACpwAAAIsFFkc4KRoEJDVgIAqQAAhDFKMeYchFIahRhzzjkIpTRIMeaccxBKqRhzzjkIpZRSMeaccxBKKSVzzjkIIZSSUuaccxBCKCWlzjkIIYRSSkqdcxBCKKGUlEIIpZRSUkqphRBKKaWUVFoqpZSSUkqptVZKKSWllFpqrQAA8AQHAKACG1ZHOCkaCyw0ZCUAkAEAwBiDkEEGIWMQQgghhBBCCAkAABhwAAAIMKEMFBqyEgBIBQAADFKKMQelpBQpxZhzEEpJKVKKMecglJJSxZhzEEpJqbWKMecglJJSa51zEEpJqbUYO+cglJJSazGGEEpJqbUYYwwhlJJSazHWWkpJqbUYa8y1lJJSazHWWmtKrbUYa60155RaazHWWnPOBQAgNDgAgB3YsDrCSdFYYKEhKwGAPAAASCnGGGOMMaUUY4wxxphSijHGGGOMMcYYY4wxphhjjDHGGGOMMcYYY4wxxhhjjDHGGGOMMeYYY4wxxhhjzDnGGGOMOeYcY4wxxpxzTgAAUIEDAECAjSKbE4wEFRqyEgAIBwAAjGHMOecglJBKo5RzEEIoJZVWGqWcgxJCKSm1ljknJaVSUmottsw5KSmVklJrLXYSUmotpdZirLGDkFJrqbUWY40dhFJaii3GGnPtIJSSWmsxxlprKKWl2GKssdaaQymptRZjrTXnXFJqLcZaa82155JSazHGWmutuafWYqyx1lxz7z21FmONteace84FAJg8OABAJdg4w0rSWeFocKEhKwGA3AAARinGnHMOQgghhBBCCJVSjDnnHIQQQgghhBAqpRhzzjkIIYQQQgghZIw55xx0EEIIIYQQQsgYc845CCGEEEIIIYTQOecchBBCCCGEUEIppXPOOQchhBBCCCGEUErnHIQQQgghhBJKKKWUzjkIIYQQQgilhFJKKSGEEEIIIYQSSimllFI6CCGEEEIIpZRSSimlhBBCCCGEEEoppZRSSgkhhBBCCCGUUkoppZQSQgghhBJKKaWUUkopJYQQQgihlFJKKaWUUkoIIYRSSimllFJKKaWUEEIoIZRSSimllFJKKSGEEkoopZRSSimllFJCCCWUUkoppZRSSimlhBBCKKWUUkoppZRSSgkhlFJKKaWUUkoppZRSAADQgQMAQIARlRZipxlXHoEjChkmoEJDVgIA4QAAACGUUkoppZRSaiSllFJKKaWUUiMlpZRSSimllFJKKaWUUkoppZRSSimllFJKKaWUUkoppZRSSimllFJKKaWUUkoppZRSSimllFJKKaWUUkoppZRSSimllFJKKaWUUkoppZRSSimllFJKKaWUUkoppZRSSimllFJKpZRSSimllFJKKaWUUkoppZRSSimlAKjLDAfA6AkbZ1hJOiscDS40ZCUAkBYAABjDmGOOQSehlJRaa5iCUELopKTSSmyxNUpBCCGEUlJKrbXWMuiolJJKSq3FFmOMmYNSUiolpdRijLHWDkJKLbUWW4ux5lprB6GklFqLLcZaa669g5BKa63lGGOwOefaQSgptdhijDXXWnsOqbQWY4y19lxrzTmIUlKKMdYac80199xLSq3FmmuuNQefcxCmpdhqjTXnnHsQOvjUWo255h500EHnHnRKrdZaa849ByF88Lm1WGvNNefegw86CN9qqzXnXGvvPfeeg24x1lxz0MEHIXzwQbgYa8859xyEDjr4HgwAyI1wAEBcMJKQOsuw0ogbT8AQgRQasgoAiAEAIIxBBiGElFJKKaWUYoopxhhjjDHGGGOMMcYYY4wxxgQAACY4AAAEWMGuzNKqjeKmTvKiDwKf0BGbkSGXUjGTE0GP1FCLlWCHVnCDF4CFhqwEAMgAABCIseZac44QlNZi7blUSjlqseeUIYKctJxLyQxBTlprLWTIKCcxthQyhBS02lrplFKMYquxdIwxSanFlkrnIAAAAIIAAAMRMhMIFECBgQwAOEBIkAIACgsMHcNFQEAuIaPAoHBMOCedNgAAQYjMEImIxSAxoRooKqYDgMUFhnwAyNDYSLu4gC4DXNDFXQdCCEIQglgcQAEJODjhhife8IQbnKBTVOogAAAAAAAQAOABACDZACKimZnj6PD4AAkRGSEpMTlBSVEJAAAAAAAgAPgAAEhWgIhoZuY4Ojw+QEJERkhKTE5QUlQCAAAAAAAAAACAgIAAAAAAAEAAAACAgE9nZ1MABNcZAAAAAAAAdDcfBQIAAAB90D1rDDpdT59ucP8Z/9ABAaTZln09D/JG7sabbYw8/3w7bAMkwcd7qbhiUI+pv/9pfRIZbvhutwvREnt/XRVOxPzgbye2O4+g9wDsBfs+4S5v9bPxrca9rX6ZJznncX+UNb59K+H4u5ectvX3bjdOX5w59ox/HbyCr8E1T/z3UAT/7Pi7Jf1ds66v/byiSjQmXCJ9yFsikxOro+c/77GT3/X/P3BOWgr0DfuRcO8b/8tDMVPtPpV82Q4AvJyz3/yQxKnzzfPGcM+Y5h8A7hbOFWmnb8AeyqVaWWg3XobuFMIjYfEc1bXHS0siGVXw2/3QxqmfWgEAmhVE3OV7Jaa29JUUWxOHZkeGLWcvv/zyF3mRF7zI5RPO/xUAgJiff/75VQAAAhzJGAAgaioLI//Z9+P9Pm5idsVuN30wlEIAO70fOaTn1iBS/Z92QWlxTYNgZu/P//dxPp1Px9P1cn88P78n/zG9eL4+19M6fCIYUkUB9SsW7GunNmyCn9abCQT6ZqvY6WD56pdRfllZHvc2AgwYEi4AXiUk3UXiVpx/NlcV7/OLovbIsPcAAAAAFAAIEGKMAgAAAH96PoD93xMAAEXUJXptF+XSVp7Eqstrl3bdSlEEEBSDE7E83tFLDJoAwH3VCdb3j/g0bV13ZNjZNstz+0TC92XyoxbxfTViEkjBAgweJeT1VcILMf/bXlX0fYmiZmTYewAAAAAAAAGOYxQAAAB4cxcSYP96VgAAKEaTbep+MOvLLAY3RsPsoNvNCVEAQBFxjXboxp5vuRpRIFVBcQSlMln0lAbTgh4vYl2mLq3QjARRuGDHwBr8rkIcRIACfhVE+e02imO+VPFQ43w9Miw5gmu7Q+Lbt0YF377x3jcAAGLrHmCMAONUJWMA4CbJYrIrUflM2lgD7LPRgpm9Luo9n3EBODixMlodb4P/ZdEVRl0xMcss+Xz2+F7HtQ31OP3/4vZE6Go7/k/2f7J/8/6N91+/f/0m++X9ZwoAlQMcZO8gBw5y0EH7smbNmjVr1vzJevXLivkQ8ydd9/KTNkx0lFHQ48+HI/bAM1ZWs+VnvXt1a3bW0/s+a/mMZ325NU+dPOtdn7Xm6qdXf7l3Xb36rC+++zlnnHHG0885Y/nUqTPOODl5/+/jk5Pj8fjheNybZrftx92+tl08zGOF1QgHDjpwYMtBBw5aBw7KbDlo30HhoE1YGd5zExv5/F5ixutCEUVpnG/qfpqiti12j/fcfd7wqMThSPPNvpvbxk44xuHOSDju3LxtLDzcublrJMaRkZEY48hIVI/Rhj7//PPPP//888/P559//vnnn3/++SIVhFMAeYWNT9pWluxDKmm7j+TOc98cqtIZ5qqog/y72c49TV3+64am1vZPyuHz4/FxPp72j4fxND4cxg0tPhzGNS0+zMfT+PB4OPyBW+XKZPeWMQoku2MUQOPUR5U53g4hsN1f0m05P72irudPPXN6aempZ545c8XpL3zpS2eefuZ3fveXnnnmS//v937p2V/6f//f7/2yL/3O//f//e4vfen//X//35c9+3f+3//3e5/9zJd+9+/9smee+cLv/rIzT5/+wrPPXFra/9TpecJ2CG30gfHuj+9Ohze9/Z237LnpB37wO95yyw/8PX/PD/17fugP/sF/9+/5we+85e3vfOetbrnllltu2TM6umfPaDZN02wqZTlLwWTJhb8zfzgc7t+/f//+/X//97///e9/p0+fPn369DPPPPPMM88888wzzzzzhS89+5lnnnnmmTNPnz79zOnT//vf//53//79+/fnD4fD4XCY8/M5FxYWAAlOZQEODg==', '2': @@ -25,3 +24,5 @@ export default { '#': 'data:audio/ogg;base64,T2dnUwACAAAAAAAAAADa7NUXAAAAAGqqJRIBHgF2b3JiaXMAAAAAAUSsAAAAAAAAMKkDAAAAAAC4AU9nZ1MAAAAAAAAAAAAA2uzVFwEAAACtgpoiET3////////////////////VA3ZvcmJpcy0AAABYaXBoLk9yZyBsaWJWb3JiaXMgSSAyMDEwMTEwMSAoU2NoYXVmZW51Z2dldCkAAAAAAQV2b3JiaXMrQkNWAQAIAAAAMUwgxYDQkFUAABAAAGAkKQ6TZkkppZShKHmYlEhJKaWUxTCJmJSJxRhjjDHGGGOMMcYYY4wgNGQVAAAEAIAoCY6j5klqzjlnGCeOcqA5aU44pyAHilHgOQnC9SZjbqa0pmtuziklCA1ZBQAAAgBASCGFFFJIIYUUYoghhhhiiCGHHHLIIaeccgoqqKCCCjLIIINMMumkk0466aijjjrqKLTQQgsttNJKTDHVVmOuvQZdfHPOOeecc84555xzzglCQ1YBACAAAARCBhlkEEIIIYUUUogppphyCjLIgNCQVQAAIACAAAAAAEeRFEmxFMuxHM3RJE/yLFETNdEzRVNUTVVVVVV1XVd2Zdd2ddd2fVmYhVu4fVm4hVvYhV33hWEYhmEYhmEYhmH4fd/3fd/3fSA0ZBUAIAEAoCM5luMpoiIaouI5ogOEhqwCAGQAAAQAIAmSIimSo0mmZmquaZu2aKu2bcuyLMuyDISGrAIAAAEABAAAAAAAoGmapmmapmmapmmapmmapmmapmmaZlmWZVmWZVmWZVmWZVmWZVmWZVmWZVmWZVmWZVmWZVmWZVmWZVlAaMgqAEACAEDHcRzHcSRFUiTHciwHCA1ZBQDIAAAIAEBSLMVyNEdzNMdzPMdzPEd0RMmUTM30TA8IDVkFAAACAAgAAAAAAEAxHMVxHMnRJE9SLdNyNVdzPddzTdd1XVdVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVgdCQVQAABAAAIZ1mlmqACDOQYSA0ZBUAgAAAABihCEMMCA1ZBQAABAAAiKHkIJrQmvPNOQ6a5aCpFJvTwYlUmye5qZibc84555xszhnjnHPOKcqZxaCZ0JpzzkkMmqWgmdCac855EpsHranSmnPOGeecDsYZYZxzzmnSmgep2Vibc85Z0JrmqLkUm3POiZSbJ7W5VJtzzjnnnHPOOeecc86pXpzOwTnhnHPOidqba7kJXZxzzvlknO7NCeGcc84555xzzjnnnHPOCUJDVgEAQAAABGHYGMadgiB9jgZiFCGmIZMedI8Ok6AxyCmkHo2ORkqpg1BSGSeldILQkFUAACAAAIQQUkghhRRSSCGFFFJIIYYYYoghp5xyCiqopJKKKsoos8wyyyyzzDLLrMPOOuuwwxBDDDG00kosNdVWY4215p5zrjlIa6W11lorpZRSSimlIDRkFQAAAgBAIGSQQQYZhRRSSCGGmHLKKaegggoIDVkFAAACAAgAAADwJM8RHdERHdERHdERHdERHc/xHFESJVESJdEyLVMzPVVUVVd2bVmXddu3hV3Ydd/Xfd/XjV8XhmVZlmVZlmVZlmVZlmVZlmUJQkNWAQAgAAAAQgghhBRSSCGFlGKMMcecg05CCYHQkFUAACAAgAAAAABHcRTHkRzJkSRLsiRN0izN8jRP8zTRE0VRNE1TFV3RFXXTFmVTNl3TNWXTVWXVdmXZtmVbt31Ztn3f933f933f933f933f13UgNGQVACABAKAjOZIiKZIiOY7jSJIEhIasAgBkAAAEAKAojuI4jiNJkiRZkiZ5lmeJmqmZnumpogqEhqwCAAABAAQAAAAAAKBoiqeYiqeIiueIjiiJlmmJmqq5omzKruu6ruu6ruu6ruu6ruu6ruu6ruu6ruu6ruu6ruu6ruu6ruu6QGjIKgBAAgBAR3IkR3IkRVIkRXIkBwgNWQUAyAAACADAMRxDUiTHsixN8zRP8zTREz3RMz1VdEUXCA1ZBQAAAgAIAAAAAADAkAxLsRzN0SRRUi3VUjXVUi1VVD1VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVXVNE3TNIHQkJUAABkAAOjFCCGEEJKjlloQvlfKOSg1914xZhTE3nulmEGOcvCZYko5KLWnzjGliJFcWyuRIsRhDjpVTimoQefWSQgtB0JDVgQAUQAAAEKIMcQYYoxByCBEjDEIGYSIMQYhg9BBCCWFlDIIIZWQUsQYg9BBySCElEJJGZSQUkilAACAAAcAgAALodCQFQFAnAAAgpBziDEIFWMQOgipdBBSqhiDkDknJXMOSiglpRBKShVjEDLnJGTOSQklpBRKSamDkFIopaVQSmoppRhTSi12EFIKpaQUSmkptRRbSi3GijEImXNSMuekhFJaCqWkljknpYOQUgehlJJSa6Wk1jLnpHTQSekglFJSaamU1FooJbWSUmslldZaazGm1mIMpaQUSmmtpNRiaim21lqsFWMQMuekZM5JCaWkFEpJLXNOSgchlc5BKSWV1kpJqWXOSekglNJBKKWk0lpJpbVQSkslpdZCKa211mJMqbUaSkmtpNRaSam11FqtrbUYOwgphVJaCqW0llqKMaUWYyiltZJSayWl1lprtbbWYgyltFRSaa2k1FpqrcbWWqyppRhTazG21mqNMcYcY805pRRjainG1FqMLbYcY6w1dxBSCqWkFkpJLbUUY2otxlBKaiWV1kpJLbbWakytxRpKaa2k1FpJqbXWWo2ttRpTSjGm1mpMqcUYY8y1tRhzai3G1lqsqbUYY6w1xxhrLQAAYMABACDAhDJQaMhKACAKAAAxBiHGnDMIKcUYhMYgpRiDECnFmHMQIqUYcw5CxphzEErJGHMOQikdhBJKSamDEEopKRUAAFDgAAAQYIOmxOIAhYasBABCAgAYhJRizDnnIJSSUoSQUow55xyEUlKKEFKKMeecg1BKSpVSTDHmHIRSUmqpUkoxxpyDUEpKqWWMMeYchBBKSam1jDHGnIMQQikptdY55xx0EkpJpaXYOuecgxBKKSWl1lrnHIQQSkmlpdZi65yDEEIpJaXUWoshhFJKSSWllmKLMYRSSiklpZRaizGWVFJKqaXWYouxxlJKSiml1lqLMcaaUmqptdZijLHGWlNKqbXWWosxxlprAQAABw4AAAFG0ElGlUXYaMKFB6DQkBUBQBQAAGAMYgwxhpxzEDIIkXMMQgchcs5J6aRkUkJpIaVMSkglpBY556R0UjIpoaVQUiYlpFRaKQAA7MABAOzAQig0ZCUAkAcAACGkFGOMMYaUUooxxhxDSinFGGOMKaUYY4wx55RSjDHGmHOMMcYcc845xhhjzDnnHGPMMeecc44xxpxzzjnHHHPOOeecY84555xzzgkAACpwAAAIsFFkc4KRoEJDVgIAqQAAhDFKMeYchFIahRhzzjkIpTRIMeaccxBKqRhzzjkIpZRSMeaccxBKKSVzzjkIIZSSUuaccxBCKCWlzjkIIYRSSkqdcxBCKKGUlEIIpZRSUkqphRBKKaWUVFoqpZSSUkqptVZKKSWllFpqrQAA8AQHAKACG1ZHOCkaCyw0ZCUAkAEAwBiDkEEGIWMQQgghhBBCCAkAABhwAAAIMKEMFBqyEgBIBQAADFKKMQelpBQpxZhzEEpJKVKKMecglJJSxZhzEEpJqbWKMecglJJSa51zEEpJqbUYO+cglJJSazGGEEpJqbUYYwwhlJJSazHWWkpJqbUYa8y1lJJSazHWWmtKrbUYa60155RaazHWWnPOBQAgNDgAgB3YsDrCSdFYYKEhKwGAPAAASCnGGGOMMaUUY4wxxphSijHGGGOMMcYYY4wxphhjjDHGGGOMMcYYY4wxxhhjjDHGGGOMMeYYY4wxxhhjzDnGGGOMOeYcY4wxxpxzTgAAUIEDAECAjSKbE4wEFRqyEgAIBwAAjGHMOecglJBKo5RzEEIoJZVWGqWcgxJCKSm1ljknJaVSUmottsw5KSmVklJrLXYSUmotpdZirLGDkFJrqbUWY40dhFJaii3GGnPtIJSSWmsxxlprKKWl2GKssdaaQymptRZjrTXnXFJqLcZaa82155JSazHGWmutuafWYqyx1lxz7z21FmONteace84FAJg8OABAJdg4w0rSWeFocKEhKwGA3AAARinGnHMOQgghhBBCCJVSjDnnHIQQQgghhBAqpRhzzjkIIYQQQgghZIw55xx0EEIIIYQQQsgYc845CCGEEEIIIYTQOecchBBCCCGEUEIppXPOOQchhBBCCCGEUErnHIQQQgghhBJKKKWUzjkIIYQQQgilhFJKKSGEEEIIIYQSSimllFI6CCGEEEIIpZRSSimlhBBCCCGEEEoppZRSSgkhhBBCCCGUUkoppZQSQgghhBJKKaWUUkopJYQQQgihlFJKKaWUUkoIIYRSSimllFJKKaWUEEIoIZRSSimllFJKKSGEEkoopZRSSimllFJCCCWUUkoppZRSSimlhBBCKKWUUkoppZRSSgkhlFJKKaWUUkoppZRSAADQgQMAQIARlRZipxlXHoEjChkmoEJDVgIA4QAAACGUUkoppZRSaiSllFJKKaWUUiMlpZRSSimllFJKKaWUUkoppZRSSimllFJKKaWUUkoppZRSSimllFJKKaWUUkoppZRSSimllFJKKaWUUkoppZRSSimllFJKKaWUUkoppZRSSimllFJKKaWUUkoppZRSSimllFJKpZRSSimllFJKKaWUUkoppZRSSimlAKjLDAfA6AkbZ1hJOiscDS40ZCUAkBYAABjDmGOOQSehlJRaa5iCUELopKTSSmyxNUpBCCGEUlJKrbXWMuiolJJKSq3FFmOMmYNSUiolpdRijLHWDkJKLbUWW4ux5lprB6GklFqLLcZaa669g5BKa63lGGOwOefaQSgptdhijDXXWnsOqbQWY4y19lxrzTmIUlKKMdYac80199xLSq3FmmuuNQefcxCmpdhqjTXnnHsQOvjUWo255h500EHnHnRKrdZaa849ByF88Lm1WGvNNefegw86CN9qqzXnXGvvPfeeg24x1lxz0MEHIXzwQbgYa8859xyEDjr4HgwAyI1wAEBcMJKQOsuw0ogbT8AQgRQasgoAiAEAIIxBBiGElFJKKaWUYoopxhhjjDHGGGOMMcYYY4wxxgQAACY4AAAEWMGuzNKqjeKmTvKiDwKf0BGbkSGXUjGTE0GP1FCLlWCHVnCDF4CFhqwEAMgAABCIseZac44QlNZi7blUSjlqseeUIYKctJxLyQxBTlprLWTIKCcxthQyhBS02lrplFKMYquxdIwxSanFlkrnIAAAAIIAAAMRMhMIFECBgQwAOEBIkAIACgsMHcNFQEAuIaPAoHBMOCedNgAAQYjMEImIxSAxoRooKqYDgMUFhnwAyNDYSLu4gC4DXNDFXQdCCEIQglgcQAEJODjhhife8IQbnKBTVOogAAAAAAAQAOABACDZACKimZnj6PD4AAkRGSEpMTlBSVEJAAAAAAAgAPgAAEhWgIhoZuY4Ojw+QEJERkhKTE5QUlQCAAAAAAAAAACAgIAAAAAAAEAAAACAgE9nZ1MABNcZAAAAAAAA2uzVFwIAAADu/EL/CzVbS6Bibab/RgEBVNnQl0aAfmMPvOWnD4ex+ocDcwNQHACPlnE9zfXy/3/HIjbccAVs5a1uMnn44hj5H3VzZTNEAYVL4zLqY39g2ViaL7/I5bvz4WcElKl3d8vi2bm0Ln/7QePJt+d0+8ZoXrQacMIGVzODf4i+ufY9KMUk32ebEU7d2CgqU+ogeH7x01rRjpvlzH77yz1w/qwAVAnpfeNKmBfpbzC10/X/xJ2LCYUzud/YuW1M8w8SOHgD0yF7bnS246h8zMcOP4oen8J6On2miYapYj5PeoL++Qq9+/0/OM/HcwIAWiUk9U2kIH3y+KwuB9FTYRnq7rOfeLAdx7f+xm/+m//mP/QWAMDyAQAAAAQIMQoAIFYXW4vRiATfu7uqpedE7DT9ZaMPCfD0ZhgAcP///5/f93Oehqfte9x+PtfNvMvFls04XK62l/dtILND2tz/v+ftfDrutqvlbBr0TV3k0eX9119bh2dBSYOyWGM2SQ/yackRnmtwvhxHSHHqOIoaAB4lVF5374N9kmJ1LgqTkCTA4OAgAMDyCAAAAIAxCgAAAECkIUPsiHSCSaAAHlktAlD7UAEAWik0SdRwGW+2OougAACAoIy5vS5DRAEAAAAAGIvL6+7PrLanzF1/3UYEgg4AHiVUXnfv1ychV+eDKExCkgB3192BBWB5HAAAABBgjAIAAACA0/y09vZJcciOLcHp2yMB+NX/RAKAFyapFdfneF8+ayuKAAAAgr3J6na7qwAAAAAAAGDo+Tkv3ElrHuZv/6dZW1QlLFXGiqWLAH4VRPriH6xO+rWyhxqjGHFyMJ9Z8VA9O2cGcnqmpQAA7wAAQAFQxpOMAoAy1sVy6jdi0meQ3xgA7DevHgAwhlRP2+tlPZ/H93G9nLe5A6qYrBkMuq7v6/u5ux86qyk4YmO0grsrxtgB3JK9csZK7H/0nykgWfBvfCvyef8+19ZGRn6d/X9+NcaYe4yRmyZGxJMdX5yQ4Hxc6nzmHb87xX4ECZagBQAeZIPgxwesO8tv5rM0P3ElCOfVd8L4zq6xyHDXnjDU1vj80sPBFmiv/fnz72jaNtG2bVvb8xdfzs/L+USqAl5SQiQFAM8i4gjeYUP7kO8Pu5r+y5FvJqyj6y6Mv0OlVzPAZ1M/CPjPv98VumuP40b3ofX+dPjT3rzxA++4VzYd3TMmK2WaTXHYFAq7CUFVAXU4VNX2dgirXlpaquf7n3rm9NL+Z770pTNPf+F3/+4vnfnUF373lz379FNf+NKzzzz91BeefebS0ulnzlyql06fvn84HO7fP9R2OBwKWe18Zodbh4ePbqq4J2iq8sc/nU6n0+l0Op3e3p1Op7d3Z6fT6d270+n07t270+n08VfwBI+//Akef/nhhx9++ESHx6/bffv666+//vrPS11YWPjz31nq54e6sHCoCwsLX3/99dftwLcADg4=', }; + +export default audios; diff --git a/packages/ringcentral-widgets/components/DialerPanel/index.js b/packages/ringcentral-widgets/components/DialerPanel/index.js index 6cf8e0ab1a..d47812e2e5 100644 --- a/packages/ringcentral-widgets/components/DialerPanel/index.js +++ b/packages/ringcentral-widgets/components/DialerPanel/index.js @@ -45,6 +45,7 @@ const DialerPanel = ({ withTabs, inConference, isLastInputFromDialpad, + showAnonymous, useV2, }) => { const inputEl = useRef(null); @@ -112,6 +113,7 @@ const DialerPanel = ({ {showFromField ? (
= ( showSaveAsDefault, disableSaveAsDefault, updateMeetingSettings, - validatePasswordSettings, isRCM, isRCV, datePickerSize, @@ -59,18 +58,34 @@ const GenericMeetingPanel: React.ComponentType = ( showRcvAdminLock, showPmiAlert, enablePersonalMeeting, - enableWaitingRoom, + showWaitingRoom, + showE2EE, + isE2EEDisabled, personalMeetingId, switchUsePersonalMeetingId, updateHasSettingsChanged, + e2eeInteractFunc, showScheduleOnBehalf, delegators, + joinBeforeHostLabel, + authUserTypeValue, + isJoinBeforeHostDisabled, + isAuthenticatedCanJoinDisabled, + isRequirePasswordDisabled, + isWaitingRoomDisabled, + isWaitingRoomNotCoworkerDisabled, + isWaitingRoomGuestDisabled, + isWaitingRoomAllDisabled, + isAuthUserTypeDisabled, + isSignedInUsersDisabled, + isSignedInCoWorkersDisabled, updateScheduleFor, labelPlacement, showSpinnerInConfigPanel, enableServiceWebSettings, recurringMeetingPosition, defaultTopic, + isPersonalMeetingDisabled, } = props; if (showSpinner) { @@ -143,14 +158,14 @@ const GenericMeetingPanel: React.ComponentType = ( {isRCV && ( = ( checkboxSize={checkboxSize} showRcvAdminLock={showRcvAdminLock} showPmiAlert={showPmiAlert} - enableWaitingRoom={enableWaitingRoom} + showWaitingRoom={showWaitingRoom} + showE2EE={showE2EE} + isE2EEDisabled={isE2EEDisabled} + isWaitingRoomNotCoworkerDisabled={isWaitingRoomNotCoworkerDisabled} + isWaitingRoomGuestDisabled={isWaitingRoomGuestDisabled} + isWaitingRoomAllDisabled={isWaitingRoomAllDisabled} + isAuthUserTypeDisabled={isAuthUserTypeDisabled} + isSignedInUsersDisabled={isSignedInUsersDisabled} + isSignedInCoWorkersDisabled={isSignedInCoWorkersDisabled} enablePersonalMeeting={enablePersonalMeeting} personalMeetingId={personalMeetingId} switchUsePersonalMeetingId={switchUsePersonalMeetingId} @@ -167,6 +190,12 @@ const GenericMeetingPanel: React.ComponentType = ( showScheduleOnBehalf={showScheduleOnBehalf} showSpinnerInConfigPanel={showSpinnerInConfigPanel} delegators={delegators} + joinBeforeHostLabel={joinBeforeHostLabel} + authUserTypeValue={authUserTypeValue} + isJoinBeforeHostDisabled={isJoinBeforeHostDisabled} + isAuthenticatedCanJoinDisabled={isAuthenticatedCanJoinDisabled} + isWaitingRoomDisabled={isWaitingRoomDisabled} + isRequirePasswordDisabled={isRequirePasswordDisabled} > {showTopic && ( any; schedule?: (meeting: any, opener: any) => any; showPmiAlert?: boolean; - enableWaitingRoom?: boolean; enablePersonalMeeting?: boolean; hasSettingsChanged?: boolean; personalMeetingId: string; @@ -56,11 +55,28 @@ export interface VideoPanelProps extends CommonProps { updateMeetingSettings: (meeting: RcVMeetingModel | any) => void; updateHasSettingsChanged: (isChanged: boolean) => void; validatePasswordSettings: (password: string, isSecret: boolean) => boolean; + e2eeInteractFunc: (e2eeValue: boolean) => void; datePickerSize?: RcDatePickerSize; timePickerSize?: RcTimePickerSize; checkboxSize?: RcCheckboxProps['size']; showRcvAdminLock?: boolean; delegators?: RcvDelegator[]; + joinBeforeHostLabel: string; + authUserTypeValue: AUTH_USER; + isJoinBeforeHostDisabled: boolean; + isAuthenticatedCanJoinDisabled: boolean; + isWaitingRoomDisabled: boolean; + isRequirePasswordDisabled: boolean; + isWaitingRoomNotCoworkerDisabled: boolean; + isWaitingRoomGuestDisabled: boolean; + isWaitingRoomAllDisabled: boolean; + isAuthUserTypeDisabled: boolean; + isSignedInUsersDisabled: boolean; + isSignedInCoWorkersDisabled: boolean; + showWaitingRoom?: boolean; + showE2EE?: boolean; + isE2EEDisabled?: boolean; + isPersonalMeetingDisabled?: boolean; } export interface MeetingPanelProps extends CommonProps { diff --git a/packages/ringcentral-widgets/components/IncomingCallView/IncomingCallView.tsx b/packages/ringcentral-widgets/components/IncomingCallView/IncomingCallView.tsx index cab70071af..bfc697b290 100644 --- a/packages/ringcentral-widgets/components/IncomingCallView/IncomingCallView.tsx +++ b/packages/ringcentral-widgets/components/IncomingCallView/IncomingCallView.tsx @@ -106,8 +106,6 @@ class IncomingCallView extends Component { if (session.minimized) { return null; } - const phoneNumber = - session.direction === callDirections.outbound ? session.to : session.from; let fallbackUserName; if ( session.direction === callDirections.inbound && @@ -124,7 +122,7 @@ class IncomingCallView extends Component { nameMatches={this.props.nameMatches} fallBackName={fallbackUserName} callQueueName={showCallQueueName ? session.callQueueName : null} - phoneNumber={phoneNumber} + phoneNumber={this.props.phoneNumber} answer={this.answer} reject={this.reject} replyWithMessage={this.replyWithMessage} diff --git a/packages/ringcentral-widgets/components/LinkLine/index.js b/packages/ringcentral-widgets/components/LinkLine/index.js index c3f156e962..7ed89f67af 100644 --- a/packages/ringcentral-widgets/components/LinkLine/index.js +++ b/packages/ringcentral-widgets/components/LinkLine/index.js @@ -13,6 +13,8 @@ const LinkLine = ({ hrefClassName, iconClassName, tooltip, + pendoSignName, + ...rest }) => { return ( { - const index = result.length; - const value = (60 / MINUTE_SCALE) * index; - const text = formatMessage(i18n.getString('minutes', currentLocale), { - howMany: `${value}0`.slice(0, 2), - }); - return result.concat({ - value, - text, - }); - }, - [], - new Array(MINUTE_SCALE), - ); -} - -export function getHoursList(HOUR_SCALE: number, currentLocale: string) { - if (HOUR_SCALE > 23) { - throw new Error('HOUR_SCALE must be less than 23.'); - } - return reduce( - (result) => { - const value = result.length; - const text = formatMessage(i18n.getString('hours', currentLocale), { - howMany: `0${value}0`.slice(-3, -1), - }); - return result.concat({ - value, - text, - }); - }, - [], - new Array(HOUR_SCALE), - ); -} function getHelperTextForPasswordField( meeting: RcMMeetingModel, @@ -193,6 +159,13 @@ const MeetingOptionLabel: React.FunctionComponent<{
); }; + +const PanelRoot = styled.div` + ${RcCheckbox} { + padding: ${spacing(2)}; + } +`; + export const MeetingConfigs: React.FunctionComponent = ({ updateMeetingSettings, disabled, @@ -305,7 +278,7 @@ export const MeetingConfigs: React.FunctionComponent = ({ const minutesList = getMinutesList(MINUTE_SCALE, currentLocale); return ( -
= ({
-
+ ); }; diff --git a/packages/ringcentral-widgets/components/MeetingConfigsV2/styles.scss b/packages/ringcentral-widgets/components/MeetingConfigsV2/styles.scss index 948a236c2b..a8e94c57ba 100644 --- a/packages/ringcentral-widgets/components/MeetingConfigsV2/styles.scss +++ b/packages/ringcentral-widgets/components/MeetingConfigsV2/styles.scss @@ -1,5 +1,6 @@ -@import '@ringcentral-integration/widgets/lib/commonStyles/fonts'; -@import '@ringcentral-integration/widgets/lib/commonStyles/variable'; +@import '~@ringcentral-integration/widgets/lib/commonStyles/fonts'; +@import '~@ringcentral-integration/widgets/lib/commonStyles/variable'; +@import '~@ringcentral/juno/scss/theming'; $panel-side-padding: 20px; $checkbox-ripple-width: 20px; @@ -112,14 +113,14 @@ div.videoConfig div.accordion div.accordionDetails { display: flex; align-items: flex-start; & > span[class*='RcCheckbox'] { - margin-top: -4px; - margin-bottom: -4px; + margin-top: -2px; + margin-bottom: -2px; } } div.accordion div.toggleGroup label.labelPlacementStart { @extend .labelPlacement; padding: 0 - ($panel-side-padding - $checkbox-ripple-width/2 - $checkbox-right-margin) 0 + ($panel-side-padding - $checkbox-ripple-width/2) 0 $panel-side-padding; } @@ -268,6 +269,6 @@ div.accordion div.toggleGroup label.labelPlacementEnd { } .lockButton { - color: #6c7489; // need to migrate using juno token "$color-icon-default" + color: rc-palette('neutral', 'f04'); padding-top: 2px; } diff --git a/packages/ringcentral-widgets/components/MessageInput/index.js b/packages/ringcentral-widgets/components/MessageInput/index.js index 3bf4b13866..0690d47dc5 100644 --- a/packages/ringcentral-widgets/components/MessageInput/index.js +++ b/packages/ringcentral-widgets/components/MessageInput/index.js @@ -17,6 +17,7 @@ export default class MessageInput extends Component { value: PropTypes.string.isRequired, currentLocale: PropTypes.string.isRequired, disabled: PropTypes.bool, + sendButtonDisabled: PropTypes.bool, minHeight: PropTypes.number, maxHeight: PropTypes.number, maxLength: PropTypes.number, @@ -32,12 +33,13 @@ export default class MessageInput extends Component { static defaultProps = { disabled: false, + sendButtonDisabled: false, onSend: undefined, onChange: undefined, onHeightChange: undefined, minHeight: 63, maxHeight: 300, - maxLength: 5000, + maxLength: 1000, inputExpandable: true, supportAttachment: false, attachments: [], @@ -55,7 +57,7 @@ export default class MessageInput extends Component { this._fileInputRef = React.createRef(); } - componentWillReceiveProps(nextProps) { + UNSAFE_componentWillReceiveProps(nextProps) { if ( nextProps.value !== this.state.value && // ignore value changes from props for 300ms after typing @@ -183,6 +185,7 @@ export default class MessageInput extends Component { const { currentLocale, disabled, + sendButtonDisabled, maxLength, supportAttachment, attachments, @@ -203,6 +206,7 @@ export default class MessageInput extends Component { size="small" symbol={attachmentSvg} onClick={this.onAttachmentIconClick} + disabled={disabled} />
@@ -226,6 +231,7 @@ export default class MessageInput extends Component { style={{ height: inputHeight, }} + disabled={disabled} />
@@ -235,7 +241,7 @@ export default class MessageInput extends Component { value={i18n.getString('send', currentLocale)} onClick={this.onSend} className={styles.sendButton} - disabled={disabled} + disabled={disabled || sendButtonDisabled} />
@@ -251,6 +257,7 @@ export default class MessageInput extends Component { { removeAttachment(attachment); }} diff --git a/packages/ringcentral-widgets/components/MessageItem/index.js b/packages/ringcentral-widgets/components/MessageItem/index.js index 1f51fb5fa5..f953320f65 100644 --- a/packages/ringcentral-widgets/components/MessageItem/index.js +++ b/packages/ringcentral-widgets/components/MessageItem/index.js @@ -1,32 +1,28 @@ -import React, { Component } from 'react'; -import PropTypes from 'prop-types'; -import classnames from 'classnames'; -import formatMessage from 'format-message'; -import messageTypes from '@ringcentral-integration/commons/enums/messageTypes'; import { extensionTypes } from '@ringcentral-integration/commons/enums/extensionTypes'; import messageDirection from '@ringcentral-integration/commons/enums/messageDirection'; -import parseNumber from '@ringcentral-integration/commons/lib/parseNumber'; +import messageTypes from '@ringcentral-integration/commons/enums/messageTypes'; import { - messageIsTextMessage, messageIsFax, + messageIsTextMessage, } from '@ringcentral-integration/commons/lib/messageHelper'; - -import formatDuration from '../../lib/formatDuration'; - -import ContactDisplay from '../ContactDisplay'; -import ActionMenuList from '../ActionMenuList'; -import VoicemailPlayer from '../VoicemailPlayer'; -import SlideMenu from '../SlideMenu'; - -import VoicemailIcon from '../../assets/images/VoicemailIcon.svg'; +import parseNumber from '@ringcentral-integration/commons/lib/parseNumber'; +import classnames from 'classnames'; +import formatMessage from 'format-message'; +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import ComposeTextIcon from '../../assets/images/ComposeText.svg'; import FaxInboundIcon from '../../assets/images/FaxInbound.svg'; import FaxOutboundIcon from '../../assets/images/FaxOutbound.svg'; - -import ComposeTextIcon from '../../assets/images/ComposeText.svg'; import GroupConversationIcon from '../../assets/images/GroupConversation.svg'; - -import styles from './styles.scss'; +import VoicemailIcon from '../../assets/images/VoicemailIcon.svg'; +import { checkShouldHidePhoneNumber } from '../../lib/checkShouldHidePhoneNumber'; +import formatDuration from '../../lib/formatDuration'; +import ActionMenuList from '../ActionMenuList'; +import ContactDisplay from '../ContactDisplay'; +import SlideMenu from '../SlideMenu'; +import VoicemailPlayer from '../VoicemailPlayer'; import i18n from './i18n'; +import styles from './styles.scss'; const ConversationIcon = ({ group, type, currentLocale, direction }) => { let title; @@ -474,6 +470,9 @@ export default class MessageItem extends Component { renderExtraButton, onFaxDownload, showChooseEntityModal, + renderContactList, + dropdownClassName, + enableCDC, } = this.props; let disableLinks = parentDisableLinks; const isVoicemail = type === messageTypes.voiceMail; @@ -486,6 +485,15 @@ export default class MessageItem extends Component { } const groupNumbers = this.getGroupPhoneNumbers(); const phoneNumber = this.getPhoneNumber(); + /** + * TODO: + * * Group message is supported for internal paging: + * * What is the requirement when a hidden contact is part of a group conversation? + * * Is it possible to ignore this edge case initially as group conversations are rare, especially when most people use glip now for internal conversations? + */ + const shouldHideNumber = + enableCDC && + checkShouldHidePhoneNumber(phoneNumber, correspondentMatches); const fallbackName = this.getFallbackContactName(); const detail = this.getDetail(); const disableClickToSms = this.getDisableClickToSms(); @@ -511,6 +519,7 @@ export default class MessageItem extends Component { }) : null; const msgItem = `${type}MessageItem`; + return (
{extraButton}
- -
- {player} -
- 0} - isCreating={this.state.isCreating} - addLogTitle={i18n.getString('addLog', currentLocale)} - editLogTitle={i18n.getString('editLog', currentLocale)} - callTitle={i18n.getString('call', currentLocale)} - textTitle={i18n.getString('text', currentLocale)} - createEntityTitle={i18n.getString('addEntity', currentLocale)} - viewEntityTitle={i18n.getString('viewDetails', currentLocale)} - stopPropagation={false} - onDelete={isVoicemail || isFax ? this.onDeleteMessage : undefined} - deleteTitle={i18n.getString('delete', currentLocale)} - marked={unreadCounts > 0} - onMark={ - isVoicemail || (isFax && direction === messageDirection.inbound) - ? this.onMarkMessage - : undefined - } - onUnmark={ - isVoicemail || (isFax && direction === messageDirection.inbound) - ? this.onUnmarkMessage - : undefined - } - onPreview={isFax ? this.onPreviewFax : undefined} - markTitle={i18n.getString('mark', currentLocale)} - unmarkTitle={i18n.getString('unmark', currentLocale)} - faxAttachment={faxAttachment} - previewTitle={i18n.getString('preview', currentLocale)} - downloadTitle={i18n.getString('download', currentLocale)} - onFaxDownload={onFaxDownload} - showChooseEntityModal={showChooseEntityModal} - /> -
+
+ {player} +
+ {shouldHideNumber ? null : ( + 0} + isCreating={this.state.isCreating} + addLogTitle={i18n.getString('addLog', currentLocale)} + editLogTitle={i18n.getString('editLog', currentLocale)} + callTitle={i18n.getString('call', currentLocale)} + textTitle={i18n.getString('text', currentLocale)} + createEntityTitle={i18n.getString('addEntity', currentLocale)} + viewEntityTitle={i18n.getString('viewDetails', currentLocale)} + stopPropagation={false} + onDelete={ + isVoicemail || isFax ? this.onDeleteMessage : undefined + } + deleteTitle={i18n.getString('delete', currentLocale)} + marked={unreadCounts > 0} + onMark={ + isVoicemail || + (isFax && direction === messageDirection.inbound) + ? this.onMarkMessage + : undefined + } + onUnmark={ + isVoicemail || + (isFax && direction === messageDirection.inbound) + ? this.onUnmarkMessage + : undefined + } + onPreview={isFax ? this.onPreviewFax : undefined} + markTitle={i18n.getString('mark', currentLocale)} + unmarkTitle={i18n.getString('unmark', currentLocale)} + faxAttachment={faxAttachment} + previewTitle={i18n.getString('preview', currentLocale)} + downloadTitle={i18n.getString('download', currentLocale)} + onFaxDownload={onFaxDownload} + showChooseEntityModal={showChooseEntityModal} + /> + )} + + )}
); } @@ -741,6 +761,9 @@ MessageItem.propTypes = { showChooseEntityModal: PropTypes.bool, shouldLogSelectRecord: PropTypes.bool, onSelectContact: PropTypes.func, + renderContactList: PropTypes.func, + dropdownClassName: PropTypes.string, + enableCDC: PropTypes.bool, }; MessageItem.defaultProps = { @@ -773,4 +796,7 @@ MessageItem.defaultProps = { showChooseEntityModal: true, shouldLogSelectRecord: false, onSelectContact: undefined, + renderContactList: undefined, + dropdownClassName: null, + enableCDC: false, }; diff --git a/packages/ringcentral-widgets/components/PresenceDropdown/style.scss b/packages/ringcentral-widgets/components/PresenceDropdown/style.scss index ae9a43533c..2f6af168d2 100644 --- a/packages/ringcentral-widgets/components/PresenceDropdown/style.scss +++ b/packages/ringcentral-widgets/components/PresenceDropdown/style.scss @@ -2,7 +2,7 @@ margin-top: 24px; line-height: 17px; text-align: left; - min-width: 165px; + min-width: 124px; border-radius: 4px; box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2); background-color: #ffffff; diff --git a/packages/ringcentral-widgets/components/Rcui/CustomArrowButton/CustomArrowButton.tsx b/packages/ringcentral-widgets/components/Rcui/CustomArrowButton/CustomArrowButton.tsx index d33527d717..fa703332bc 100644 --- a/packages/ringcentral-widgets/components/Rcui/CustomArrowButton/CustomArrowButton.tsx +++ b/packages/ringcentral-widgets/components/Rcui/CustomArrowButton/CustomArrowButton.tsx @@ -1,10 +1,8 @@ import { RcIconButton, RcIconButtonProps } from '@ringcentral/juno'; -import arrowRight1Svg from '@ringcentral/juno/icon/ArrowRight1'; +import ArrowRight1 from '@ringcentral/juno/icon/ArrowRight1'; import React, { FunctionComponent } from 'react'; -type CustomArrowButtonProps = { - disabled?: boolean; -} & RcIconButtonProps; +type CustomArrowButtonProps = {} & RcIconButtonProps; export const CustomArrowButton: FunctionComponent = ({ ...rest @@ -12,8 +10,7 @@ export const CustomArrowButton: FunctionComponent = ({ return ( @@ -21,6 +18,6 @@ export const CustomArrowButton: FunctionComponent = ({ }; CustomArrowButton.defaultProps = { onClick() {}, - symbol: arrowRight1Svg, + symbol: ArrowRight1, size: 'large', }; diff --git a/packages/ringcentral-widgets/components/Rcui/DialPad/DialPad.tsx b/packages/ringcentral-widgets/components/Rcui/DialPad/DialPad.tsx index 418cfaed17..cefe7d450a 100644 --- a/packages/ringcentral-widgets/components/Rcui/DialPad/DialPad.tsx +++ b/packages/ringcentral-widgets/components/Rcui/DialPad/DialPad.tsx @@ -9,6 +9,7 @@ type DialPadProps = { dataSign?: string; } & RcDialPadProps; +/** @deprecated use juno RcDialPad directly */ export const DialPad: FunctionComponent = ({ className, dataSign, diff --git a/packages/ringcentral-widgets/components/Rcui/RecipientsInput/RecipientsInput.tsx b/packages/ringcentral-widgets/components/Rcui/RecipientsInput/RecipientsInput.tsx index f664ac4c81..f645d77336 100644 --- a/packages/ringcentral-widgets/components/Rcui/RecipientsInput/RecipientsInput.tsx +++ b/packages/ringcentral-widgets/components/Rcui/RecipientsInput/RecipientsInput.tsx @@ -6,15 +6,11 @@ import { RcTextField, RcTextFieldProps, useEventCallback, + useForkRef, } from '@ringcentral/juno'; -import deletenumberSvg from '@ringcentral/juno/icon/Deletenumber'; +import { Deletenumber } from '@ringcentral/juno/icon'; import classNames from 'classnames'; -import React, { - forwardRef, - useEffect, - useRef, - useState, -} from 'react'; +import React, { forwardRef, useEffect, useRef, useState } from 'react'; import i18n from './i18n'; import styles from './styles.scss'; @@ -35,7 +31,8 @@ export type RecipientsInputProps = { } & Omit; const throttledTime = 1000; -// FunctionComponent + +/** @deprecated use juno RcDialTextField directly */ export const RecipientsInput = forwardRef< HTMLInputElement, RecipientsInputProps @@ -54,8 +51,9 @@ export const RecipientsInput = forwardRef< }, ref, ) => { - const defaultRef = useRef(); - const inputRef = ref || defaultRef; + const innerRef = useRef(); + + const inputRef = useForkRef(ref, innerRef); const [mouseDownTime, setMouseDownTime] = useState(null); const [timer, setTimer] = useState(null); @@ -83,7 +81,7 @@ export const RecipientsInput = forwardRef< }); useEffect(() => { - inputRef.current.focus(); + innerRef.current!.focus(); // eslint-disable-next-line react-hooks/exhaustive-deps }, [value]); @@ -116,7 +114,7 @@ export const RecipientsInput = forwardRef< endAdornment: haveDeleteButton && ( + return (WrappedComponent) => { class Expandable extends PureComponent { constructor(props) { super(props); @@ -13,14 +14,16 @@ export default function expandable({ styles = {}, className = null }) { togglePanel = (event) => { // In case it's fired twice event.stopPropagation(); + this.props.trackClickToggle?.(!this.state.expanded); this.setState((prevState) => ({ expanded: !prevState.expanded })); }; render() { const { expanded } = this.state; - const _styles = Object.assign({}, styles, { + const _styles = { + ...styles, height: expanded ? styles.height : styles.offset, - }); + }; return (
); } + } + + Expandable.propTypes = { + trackClickToggle: PropTypes.func, + }; + + Expandable.defaultProps = { + trackClickToggle: undefined, }; + return Expandable; + }; } diff --git a/packages/ringcentral-widgets/components/RecentActivityView/index.js b/packages/ringcentral-widgets/components/RecentActivityView/index.js index b787ec2a06..b7aa34ae6c 100644 --- a/packages/ringcentral-widgets/components/RecentActivityView/index.js +++ b/packages/ringcentral-widgets/components/RecentActivityView/index.js @@ -54,7 +54,10 @@ export default class RecentActivityView extends PureComponent { if (showSpinner) return ; const props = { currentPath: this.state.currentTab, - goTo: this.onTabChanged, + goTo: (tabName) => { + this.props.trackClickTab?.(tabName); + this.onTabChanged(tabName); + }, tabs: this.props.tabs, }; return ( @@ -75,4 +78,9 @@ RecentActivityView.propTypes = { currentContact: PropTypes.object.isRequired, tabs: PropTypes.array.isRequired, defaultTab: PropTypes.string.isRequired, + trackClickTab: PropTypes.func, +}; + +RecentActivityView.defaultProps = { + trackClickTab: undefined, }; diff --git a/packages/ringcentral-widgets/components/SaveLogButton/SaveLogButton.js b/packages/ringcentral-widgets/components/SaveLogButton/SaveLogButton.js index 5cf72024fa..e35f4506f4 100644 --- a/packages/ringcentral-widgets/components/SaveLogButton/SaveLogButton.js +++ b/packages/ringcentral-widgets/components/SaveLogButton/SaveLogButton.js @@ -1,5 +1,5 @@ import { RcButton, RcCircularProgress, RcIcon } from '@ringcentral/juno'; -import CheckSvg from '@ringcentral/juno/icon/Check'; +import { Check } from '@ringcentral/juno/icon'; import classnames from 'classnames'; import PropTypes from 'prop-types'; import React from 'react'; @@ -23,7 +23,7 @@ const SaveLogButton = ({ const getContent = (buttonContent) => ( {buttonContent === 'saved' && ( - + )} {buttonContent === 'saving' && } {buttonContent === 'save' && i18n.getString('save', currentLocale)} diff --git a/packages/ringcentral-widgets/components/SaveLogButton/styles.scss b/packages/ringcentral-widgets/components/SaveLogButton/styles.scss index 170b4e9db9..c44fb654e0 100644 --- a/packages/ringcentral-widgets/components/SaveLogButton/styles.scss +++ b/packages/ringcentral-widgets/components/SaveLogButton/styles.scss @@ -6,9 +6,8 @@ padding: 0 4px !important; min-width: 0 !important; margin-right: 14px !important; -} - -.classic { - padding: 0 !important; - margin-right: 6px !important; + &.classic { + padding: 0 !important; + margin-right: 6px !important; + } } diff --git a/packages/ringcentral-widgets/components/SearchPanel/SearchPanel.tsx b/packages/ringcentral-widgets/components/SearchPanel/SearchPanel.tsx index 5d70b949b3..9fe3d7eb93 100644 --- a/packages/ringcentral-widgets/components/SearchPanel/SearchPanel.tsx +++ b/packages/ringcentral-widgets/components/SearchPanel/SearchPanel.tsx @@ -1,5 +1,5 @@ import { RcIcon, RcTextField } from '@ringcentral/juno'; -import searchSvg from '@ringcentral/juno/icon/Search'; +import { Search } from '@ringcentral/juno/icon'; import classNames from 'classnames'; import React, { FunctionComponent, useContext, useState } from 'react'; @@ -54,7 +54,7 @@ export const SearchPanel: FunctionComponent = ({ value={filter} InputProps={{ startAdornment: ( - + ), }} data-sign="searchBar" diff --git a/packages/ringcentral-widgets/components/SelectList/ListView/ListView.tsx b/packages/ringcentral-widgets/components/SelectList/ListView/ListView.tsx index 8a60053031..eec079bbdc 100644 --- a/packages/ringcentral-widgets/components/SelectList/ListView/ListView.tsx +++ b/packages/ringcentral-widgets/components/SelectList/ListView/ListView.tsx @@ -16,6 +16,7 @@ export type ListViewProps = { | 'valueFunction' | 'onChange' | 'value' + | 'multiple' >; export const ListView: FunctionComponent = ({ diff --git a/packages/ringcentral-widgets/components/SelectList/ListView/ListViewItem/ListViewItem.tsx b/packages/ringcentral-widgets/components/SelectList/ListView/ListViewItem/ListViewItem.tsx index 545cfdb315..36e83a7150 100644 --- a/packages/ringcentral-widgets/components/SelectList/ListView/ListViewItem/ListViewItem.tsx +++ b/packages/ringcentral-widgets/components/SelectList/ListView/ListViewItem/ListViewItem.tsx @@ -1,9 +1,11 @@ -import { RcListItem, RcListItemText } from '@ringcentral/juno'; -import classnames from 'classnames'; +import { + RcListItem, + RcListItemText, + RcFormControlLabel, + RcCheckbox, +} from '@ringcentral/juno'; import React, { FunctionComponent, useEffect, useRef } from 'react'; -import styles from './styles.scss'; - type OptionData = { type?: string; [key: string]: any; @@ -21,6 +23,7 @@ export interface ListViewItemProps { renderFunction: (option: OptionData) => React.ReactNode; secondaryRenderFunction?: (option: OptionData) => any; onSelect: (elm?: HTMLDivElement) => any; + multiple?: boolean; } export const ListViewItem: FunctionComponent = ({ @@ -34,11 +37,14 @@ export const ListViewItem: FunctionComponent = ({ onChange, index, onSelect, + multiple, }) => { const selectElm = useRef(); const currentValue = valueFunction(value); const thisValue = valueFunction(option); - const isSelected = thisValue === currentValue; + const isSelected = multiple + ? !!currentValue?.includes(thisValue) + : thisValue === currentValue; const { type } = option; useEffect(() => { if (isSelected) { @@ -65,14 +71,18 @@ export const ListViewItem: FunctionComponent = ({
onChange(isSelected ? {} : option)} + onClick={ + multiple + ? () => onChange({ ...option, isSelected: !isSelected }) + : () => onChange(isSelected ? {} : option) + } data-sign={`match${index}`} - className={classnames(styles.listItem)} selected={isSelected} > {startAdornment && startAdornment(type)} + {multiple && } void; + multiple?: boolean; } & Pick< ListViewProps, | 'options' @@ -79,6 +80,7 @@ export const SelectList: FunctionComponent = (props) => { onSelectViewVisible, foundFromServerTitle, secondaryRenderFunction, + multiple, } = props; const [open, setOpen] = useState(false); @@ -107,6 +109,7 @@ export const SelectList: FunctionComponent = (props) => { valueFunction={valueFunction} onSelect={(elm) => scrollCheck(elm, type)} startAdornment={startAdornment} + multiple={multiple} /> ); diff --git a/packages/ringcentral-widgets/components/SelectListBasic/SelectListBasic.tsx b/packages/ringcentral-widgets/components/SelectListBasic/SelectListBasic.tsx index 80c87ba400..941ac1eb84 100644 --- a/packages/ringcentral-widgets/components/SelectListBasic/SelectListBasic.tsx +++ b/packages/ringcentral-widgets/components/SelectListBasic/SelectListBasic.tsx @@ -1,5 +1,5 @@ import { RcIcon, RcTextField } from '@ringcentral/juno'; -import searchSvg from '@ringcentral/juno/icon/Search'; +import { Search } from '@ringcentral/juno/icon'; import classNames from 'classnames'; import formatMessage from 'format-message'; import React, { FunctionComponent, useEffect, useRef, useState } from 'react'; @@ -181,7 +181,7 @@ const SelectListBasic: FunctionComponent = ({ InputProps={{ startAdornment: ( diff --git a/packages/ringcentral-widgets/components/SettingsPanel/SettingItems/LinkLineItem.tsx b/packages/ringcentral-widgets/components/SettingsPanel/SettingItems/LinkLineItem.tsx index bc9bd75ca5..0cc06aaa1f 100644 --- a/packages/ringcentral-widgets/components/SettingsPanel/SettingItems/LinkLineItem.tsx +++ b/packages/ringcentral-widgets/components/SettingsPanel/SettingItems/LinkLineItem.tsx @@ -9,6 +9,7 @@ export interface LinkLineItemProps extends onLinkLineItemClick { customTitle?: string; currentLocale: string; show?: boolean; + pendoSignName?: string; } export const LinkLineItem: FunctionComponent = ({ @@ -17,12 +18,19 @@ export const LinkLineItem: FunctionComponent = ({ customTitle, currentLocale, onClick, + pendoSignName, + ...rest }) => { if (!show) { return null; } return ( - + {customTitle || i18n.getString(name, currentLocale)} ); diff --git a/packages/ringcentral-widgets/components/SettingsPanel/SettingsPanel.tsx b/packages/ringcentral-widgets/components/SettingsPanel/SettingsPanel.tsx index b4a04c7bb9..91b35b5236 100644 --- a/packages/ringcentral-widgets/components/SettingsPanel/SettingsPanel.tsx +++ b/packages/ringcentral-widgets/components/SettingsPanel/SettingsPanel.tsx @@ -227,6 +227,7 @@ const SettingsPanel: FunctionComponent = ({ {additional} ; +const StyledContainer = styled.div<{ top?: string }>` + position: absolute; + top: ${(props) => props.top}; + left: 50%; + width: 40px; + height: 40px; + transform: translate(-50%, -50%); + + @media only screen and (max-width: 50px) { + width: 30px; + height: 30px; + } +`; + export const SpinnerOverlay: FunctionComponent = memo< SpinnerOverlayProps ->(({ className, custom: SpinnerComponent, classes }) => { +>(({ className, custom: SpinnerComponent, classes, top = '40%' }) => { return (
-
+ -
+
); }); @@ -37,4 +52,5 @@ SpinnerOverlay.defaultProps = { className: undefined, custom: JunoSpinnerWrapper, classes: {}, + top: '40%', }; diff --git a/packages/ringcentral-widgets/components/SpinnerOverlay/styles.scss b/packages/ringcentral-widgets/components/SpinnerOverlay/styles.scss index f2edf3cf93..4332fc38c0 100644 --- a/packages/ringcentral-widgets/components/SpinnerOverlay/styles.scss +++ b/packages/ringcentral-widgets/components/SpinnerOverlay/styles.scss @@ -9,28 +9,12 @@ z-index: 99; } -.container { - position: absolute; - top: 40%; - left: 50%; - width: 40px; - height: 40px; - transform: translate(-50%, -50%); -} - .mask { @include full-size; background: rc-palette('neutral', 'b01'); opacity: rc-opacity('48'); } -@media only screen and (max-width: 50px) { - .container { - width: 30px; - height: 30px; - } -} - // fix animation freeze a bit under high load div[class*='MuiCircularProgress-indeterminate'] { animation: circular-rotate 1.4s linear infinite; diff --git a/packages/ringcentral-widgets/components/TransferPanel/index.js b/packages/ringcentral-widgets/components/TransferPanel/index.js index 82d142de5b..548772985a 100644 --- a/packages/ringcentral-widgets/components/TransferPanel/index.js +++ b/packages/ringcentral-widgets/components/TransferPanel/index.js @@ -2,7 +2,7 @@ import React, { PureComponent } from 'react'; import PropTypes from 'prop-types'; import classnames from 'classnames'; -import WarmTransferIcon from '@ringcentral/juno/icon/Askfirst'; +import { Askfirst } from '@ringcentral/juno/icon'; import DialPad from '../DialPad'; import RecipientsInput from '../RecipientsInput'; @@ -60,7 +60,7 @@ export default class TransferPanel extends PureComponent { this.load(); } - componentWillReceiveProps(nextProps) { + UNSAFE_componentWillReceiveProps(nextProps) { if (this.props.session && !nextProps.session) { this.props.onCallEnd(); } @@ -95,8 +95,8 @@ export default class TransferPanel extends PureComponent { }; onWarmTransfer = () => { - this.props.onWarmTransfer(this._getTransferNumber(), this.props.sessionId) - } + this.props.onWarmTransfer(this._getTransferNumber(), this.props.sessionId); + }; onToNumberChange = (toNumber) => { this.setState({ @@ -163,7 +163,7 @@ export default class TransferPanel extends PureComponent { dataSign="warnTransferBtn" className={isOnTransfer ? styles.disabled : undefined} onClick={this.onWarmTransfer} - icon={WarmTransferIcon} + icon={Askfirst} disabled={isOnTransfer || controlBusy} title={i18n.getString('warmTransfer', currentLocale)} /> diff --git a/packages/ringcentral-widgets/components/VideoPanel/SettingGroup/SettingGroup.tsx b/packages/ringcentral-widgets/components/VideoPanel/SettingGroup/SettingGroup.tsx index 131f36abd6..122c87d462 100644 --- a/packages/ringcentral-widgets/components/VideoPanel/SettingGroup/SettingGroup.tsx +++ b/packages/ringcentral-widgets/components/VideoPanel/SettingGroup/SettingGroup.tsx @@ -1,10 +1,12 @@ import React from 'react'; -import { RcIconButton, RcFormGroup } from '@ringcentral/juno'; +import { + RcAccordion, + RcAccordionDetails, + RcAccordionSummary, + RcFormGroup, +} from '@ringcentral/juno'; -import { RcAccordion } from '@ringcentral/juno/components/Accordion'; -import { RcAccordionDetails } from '@ringcentral/juno/components/Accordion/AccordionDetails'; -import { RcAccordionSummary } from '@ringcentral/juno/components/Accordion/AccordionSummary'; -import arrowDownSvg from '@ringcentral/juno/icon/ArrowDown2'; +import { ArrowDown2 } from '@ringcentral/juno/icon'; import styles from './styles.scss'; interface SettingGroupProps { @@ -34,7 +36,7 @@ export const SettingGroup: React.FunctionComponent = ({ root: styles.accordionSummary, disabled: expandable ? null : styles.accordionSummaryDisabled, }} - expandIcon={expandable ? arrowDownSvg : undefined} + expandIcon={expandable ? ArrowDown2 : undefined} data-sign={`${dataSign}Summary`} > {summary} diff --git a/packages/ringcentral-widgets/components/VideoPanel/VideoConfig.tsx b/packages/ringcentral-widgets/components/VideoPanel/VideoConfig.tsx index 45f9cc46e8..7c0a58d43d 100644 --- a/packages/ringcentral-widgets/components/VideoPanel/VideoConfig.tsx +++ b/packages/ringcentral-widgets/components/VideoPanel/VideoConfig.tsx @@ -1,4 +1,6 @@ import { + styled, + spacing, RcAlert, RcCheckbox, RcDatePicker, @@ -9,9 +11,10 @@ import { RcTimePicker, RcTimePickerProps, RcCheckboxProps, + RcIcon, } from '@ringcentral/juno'; +import { Info } from '@ringcentral/juno/icon'; import classnames from 'classnames'; -import { find, reduce } from 'ramda'; import React, { useEffect, useMemo, useRef, useState } from 'react'; import { updateFullTime, @@ -23,52 +26,23 @@ import { RCV_WAITING_ROOM_MODE, RcvDelegator, RcvWaitingRoomModeProps, -} from '@ringcentral-integration/commons/modules/RcVideo'; + AUTH_USER, + AUTH_USER_TYPE, +} from '@ringcentral-integration/commons/modules/RcVideoV2'; +import { ExtendedTooltip } from '../MeetingConfigsV2/ExtendedTooltip'; import { formatMeetingId } from '../../lib/MeetingCalendarHelper'; -import { useDebounce } from '../../react-hooks'; +import { + getMinutesList, + getHoursList, + HOUR_SCALE, + MINUTE_SCALE, +} from '../../lib/MeetingHelper'; import { SpinnerOverlay } from '../SpinnerOverlay'; import i18n from './i18n'; import { SettingGroup } from './SettingGroup'; import styles from './styles.scss'; -import { VideoSecuritySettingsItem } from './VideoSecuritySettingItem'; - -export const MINUTE_SCALE: number = 4; -export const HOUR_SCALE: number = 13; - -export function getMinutesList(MINUTE_SCALE: number) { - return reduce( - (result) => { - const index = result.length; - const value = (60 / MINUTE_SCALE) * index; - const text = `${`${value}0`.slice(0, 2)} min`; - return result.concat({ - value, - text, - }); - }, - [], - new Array(MINUTE_SCALE), - ); -} - -export function getHoursList(HOUR_SCALE: number) { - if (HOUR_SCALE > 23) { - throw new Error('HOUR_SCALE must be less than 23.'); - } - return reduce( - (result) => { - const value = result.length; - const text = `${`0${value}0`.slice(-3, -1)} hr`; - return result.concat({ - value, - text, - }); - }, - [], - new Array(HOUR_SCALE), - ); -} +import { VideoSecuritySettingItem } from './VideoSecuritySettingItem'; function getHelperTextForPasswordField( meeting: RcVMeetingModel, @@ -87,6 +61,8 @@ function getHelperTextForPasswordField( // when correct input without focus, show nothing return ''; } + +// TODO: integrate with VideoPanelProps from 'GenericMeetingPanel/interface' interface VideoConfigProps { disabled?: boolean; showScheduleOnBehalf?: boolean; @@ -95,29 +71,49 @@ interface VideoConfigProps { meeting: RcVMeetingModel; updateMeetingSettings: (meeting: Partial) => void; - validatePasswordSettings: (password: string, isSecret: boolean) => boolean; recipientsSection?: React.ReactNode; - showTopic?: boolean; showWhen?: boolean; showDuration?: boolean; showRcvAdminLock?: boolean; showPmiAlert?: boolean; - enableWaitingRoom?: boolean; + showWaitingRoom?: boolean; + showE2EE?: boolean; + isE2EEDisabled?: boolean; enablePersonalMeeting?: boolean; + isPersonalMeetingDisabled: boolean; personalMeetingId: string; switchUsePersonalMeetingId: (usePersonalMeetingId: boolean) => any; updateHasSettingsChanged: (isChanged: boolean) => void; updateScheduleFor: (userExtensionId: string) => any; init: () => any; + e2eeInteractFunc: (e2eeValue: boolean) => void; datePickerSize?: RcDatePickerProps['size']; timePickerSize?: RcTimePickerProps['size']; checkboxSize?: RcCheckboxProps['size']; labelPlacement?: 'end' | 'start' | 'top' | 'bottom'; showSpinnerInConfigPanel: boolean; + joinBeforeHostLabel: string; + authUserTypeValue: AUTH_USER; + isJoinBeforeHostDisabled: boolean; + isAuthenticatedCanJoinDisabled: boolean; + isWaitingRoomDisabled: boolean; + isRequirePasswordDisabled: boolean; + isWaitingRoomNotCoworkerDisabled: boolean; + isWaitingRoomGuestDisabled: boolean; + isWaitingRoomAllDisabled: boolean; + isAuthUserTypeDisabled: boolean; + isSignedInUsersDisabled: boolean; + isSignedInCoWorkersDisabled: boolean; } +const PanelRoot = styled.div` + ${RcCheckbox} { + padding: ${spacing(2)}; + } +`; + export const VideoConfig: React.FunctionComponent = ( props, ) => { @@ -126,20 +122,22 @@ export const VideoConfig: React.FunctionComponent = ( currentLocale, meeting, updateMeetingSettings, - validatePasswordSettings, recipientsSection, init, children, - showTopic, showWhen, showDuration, showRcvAdminLock, showPmiAlert, - enableWaitingRoom, + showWaitingRoom, + showE2EE, + isE2EEDisabled, enablePersonalMeeting, + isPersonalMeetingDisabled, personalMeetingId, switchUsePersonalMeetingId, updateHasSettingsChanged, + e2eeInteractFunc, datePickerSize, timePickerSize, checkboxSize, @@ -148,9 +146,23 @@ export const VideoConfig: React.FunctionComponent = ( showScheduleOnBehalf, updateScheduleFor, showSpinnerInConfigPanel, + joinBeforeHostLabel, + authUserTypeValue, + isJoinBeforeHostDisabled, + isAuthenticatedCanJoinDisabled, + isAuthUserTypeDisabled, + isSignedInUsersDisabled, + isSignedInCoWorkersDisabled, + isWaitingRoomDisabled, + isRequirePasswordDisabled, + isWaitingRoomNotCoworkerDisabled, + isWaitingRoomGuestDisabled, + isWaitingRoomAllDisabled, } = props; - const hoursList = getHoursList(HOUR_SCALE); - const minutesList = getMinutesList(MINUTE_SCALE); + + const settingsGroupExpandable = false; + const hoursList = getHoursList(HOUR_SCALE, currentLocale); + const minutesList = getMinutesList(MINUTE_SCALE, currentLocale); useEffect(() => { if (init) { @@ -158,17 +170,6 @@ export const VideoConfig: React.FunctionComponent = ( } }, []); - const [meetingPassword, setMeetingPassword] = useState( - meeting.meetingPassword, - ); - - /* Password */ - const [isPasswordFocus, setPasswordFocus] = useState(false); - - useEffect(() => { - setMeetingPassword(meeting.meetingPassword); - }, [meeting.meetingPassword]); - const update = (options: any) => { updateHasSettingsChanged(true); return updateMeetingSettings({ @@ -177,31 +178,14 @@ export const VideoConfig: React.FunctionComponent = ( }); }; - const debouncedPassword = useDebounce(meetingPassword, 200); - useEffect(() => { - const isMeetingPasswordValid = validatePasswordSettings( - debouncedPassword, - meeting.isMeetingSecret, - ); - updateMeetingSettings({ - ...meeting, - meetingPassword: debouncedPassword, - isMeetingPasswordValid, - }); - }, [debouncedPassword]); + /* Password validate interaction */ + const [isPasswordFocus, setPasswordFocus] = useState(false); const startTime = useMemo(() => { return new Date(meeting.startTime); }, [meeting.startTime]); - const authUserTypeValue = meeting.isOnlyCoworkersJoin - ? 'signedInCoWorkers' - : 'signedInUsers'; - const [authUserType, setAuthUserType] = useState(authUserTypeValue); - useEffect(() => { - setAuthUserType(authUserTypeValue); - }, [authUserTypeValue]); - + /* Scrollbar */ const configRef = useRef(); const [hasScrollBar, setHasScrollBar] = useState(false); @@ -211,24 +195,8 @@ export const VideoConfig: React.FunctionComponent = ( ); }, []); - const settingsGroupExpandable = false; - - const [joinBeforeHostLabel, setJoinBeforeHostLabel] = useState< - 'onlyJoinAfterMe' | 'onlyJoinAfterHost' - >('onlyJoinAfterMe'); - useEffect(() => { - const user = find( - (item) => item.extensionId === meeting.extensionId, - delegators || [], - ); - if (user && !user.isLoginUser) { - return setJoinBeforeHostLabel('onlyJoinAfterHost'); - } - return setJoinBeforeHostLabel('onlyJoinAfterMe'); - }, [delegators, meeting.extensionId]); - return ( -
= ( clearBtn={false} formatString="MM/DD/YYYY" size={datePickerSize} + locale={currentLocale} + todayButtonText={i18n.getString('today', currentLocale)} onChange={(value) => { update({ startTime: updateFullYear(startTime, value), @@ -387,10 +357,11 @@ export const VideoConfig: React.FunctionComponent = ( > {enablePersonalMeeting && personalMeetingId && ( <> - @@ -404,7 +375,7 @@ export const VideoConfig: React.FunctionComponent = ( > { @@ -412,7 +383,7 @@ export const VideoConfig: React.FunctionComponent = ( updateHasSettingsChanged(true); }} /> - + {meeting.usePersonalMeetingId && showPmiAlert ? ( = ( ) : null} )} - = ( }); }} /> - - + = ( }); }} /> - + - + + {i18n.getString('useE2ee', currentLocale)} + + + + + + } + > + { + e2eeInteractFunc(value); + }} + /> + + ) : null} + = ( { const next = !meeting.isMeetingSecret; @@ -491,7 +494,7 @@ export const VideoConfig: React.FunctionComponent = ( }); }} /> - + {meeting.isMeetingSecret ? (
= ( data-sign="password" clearBtn spellCheck={false} - value={meetingPassword} + value={meeting.meetingPassword} inputProps={{ maxLength: 255, }} onChange={(e) => { - setMeetingPassword(e.target.value); - updateHasSettingsChanged(true); + update({ + meetingPassword: e.target.value, + }); }} onFocus={() => { setPasswordFocus(true); @@ -533,7 +537,7 @@ export const VideoConfig: React.FunctionComponent = ( />
) : null} - = ( { update({ @@ -557,10 +556,10 @@ export const VideoConfig: React.FunctionComponent = ( }); }} /> - - {enableWaitingRoom ? ( + + {showWaitingRoom ? ( <> - = ( { update({ @@ -587,7 +583,7 @@ export const VideoConfig: React.FunctionComponent = ( }); }} /> - + {meeting.waitingRoomMode ? (
= ( > @@ -622,7 +618,7 @@ export const VideoConfig: React.FunctionComponent = ( @@ -630,6 +626,7 @@ export const VideoConfig: React.FunctionComponent = ( @@ -640,7 +637,7 @@ export const VideoConfig: React.FunctionComponent = ( ) : null} ) : null} - = ( { update({ @@ -665,7 +659,7 @@ export const VideoConfig: React.FunctionComponent = ( }); }} /> - + {meeting.isOnlyAuthUserJoin ? (
= ( variant="box" data-test-automation-id="authUserType" data-sign="authUserType" - disabled={ - disabled || - (showRcvAdminLock && meeting.settingLock.isOnlyCoworkersJoin) - } + disabled={isAuthUserTypeDisabled} className={styles.boxSelect} fullWidth onChange={(e) => { - setAuthUserType(e.target.value as string); update({ - isOnlyCoworkersJoin: e.target.value === 'signedInCoWorkers', + isOnlyCoworkersJoin: + e.target.value === AUTH_USER_TYPE.SIGNED_IN_CO_WORKERS, }); }} - value={authUserType} + value={authUserTypeValue} > - + {i18n.getString('signedInUsers', currentLocale)} - + {i18n.getString('signedInCoWorkers', currentLocale)}
) : null} - = ( }); }} /> - +
-
+ ); }; VideoConfig.defaultProps = { recipientsSection: undefined, - showTopic: true, showWhen: true, showDuration: true, showRcvAdminLock: false, showPmiAlert: false, enablePersonalMeeting: false, - enableWaitingRoom: false, + showWaitingRoom: false, + showE2EE: false, + isE2EEDisabled: false, datePickerSize: 'medium', timePickerSize: 'medium', labelPlacement: 'start', diff --git a/packages/ringcentral-widgets/components/VideoPanel/VideoPanel.tsx b/packages/ringcentral-widgets/components/VideoPanel/VideoPanel.tsx index d3e3791b98..1fc5bb93bb 100644 --- a/packages/ringcentral-widgets/components/VideoPanel/VideoPanel.tsx +++ b/packages/ringcentral-widgets/components/VideoPanel/VideoPanel.tsx @@ -1,6 +1,15 @@ -import React, { useRef, useState } from 'react'; +import React, { useRef } from 'react'; +import { + RcDatePickerSize, + RcTimePickerSize, + RcCheckboxProps, +} from '@ringcentral/juno'; import { RcVMeetingModel } from '@ringcentral-integration/commons/interfaces/Rcv.model'; import sleep from '@ringcentral-integration/commons/lib/sleep'; +import { + RcvDelegator, + AUTH_USER, +} from '@ringcentral-integration/commons/modules/RcVideoV2'; import isSafari from '../../lib/isSafari'; import { Topic, TopicRef } from '../InnerTopic'; @@ -10,6 +19,9 @@ import { VideoConfig } from './VideoConfig'; /** @deprecated */ export const VideoPanel: React.FunctionComponent = ({ scheduleButton: ScheduleButton, + datePickerSize, + timePickerSize, + checkboxSize, meeting, hidden, currentLocale, @@ -20,7 +32,6 @@ export const VideoPanel: React.FunctionComponent = ({ openNewWindow, schedule, updateMeetingSettings, - validatePasswordSettings, init, recipientsSection, showWhen, @@ -28,12 +39,34 @@ export const VideoPanel: React.FunctionComponent = ({ brandName, showRcvAdminLock, showPmiAlert, - enableWaitingRoom, + showWaitingRoom, + showE2EE, + isE2EEDisabled, enablePersonalMeeting, enableJoinAfterMeCopy, personalMeetingId, + isPersonalMeetingDisabled, + configDisabled, + labelPlacement, switchUsePersonalMeetingId, updateHasSettingsChanged, + e2eeInteractFunc, + updateScheduleFor, + delegators, + joinBeforeHostLabel, + authUserTypeValue, + isJoinBeforeHostDisabled, + isAuthenticatedCanJoinDisabled, + isAuthUserTypeDisabled, + isSignedInUsersDisabled, + isSignedInCoWorkersDisabled, + isWaitingRoomNotCoworkerDisabled, + isWaitingRoomGuestDisabled, + isWaitingRoomAllDisabled, + isWaitingRoomDisabled, + isRequirePasswordDisabled, + showScheduleOnBehalf, + showSpinnerInConfigPanel, }) => { const topicRef = useRef(null); @@ -43,7 +76,6 @@ export const VideoPanel: React.FunctionComponent = ({ currentLocale={currentLocale} meeting={meeting} updateMeetingSettings={updateMeetingSettings} - validatePasswordSettings={validatePasswordSettings} recipientsSection={recipientsSection} init={init} showWhen={showWhen} @@ -51,12 +83,37 @@ export const VideoPanel: React.FunctionComponent = ({ brandName={brandName} showRcvAdminLock={showRcvAdminLock} showPmiAlert={showPmiAlert} - enableWaitingRoom={enableWaitingRoom} + showWaitingRoom={showWaitingRoom} + showE2EE={showE2EE} + isE2EEDisabled={isE2EEDisabled} enablePersonalMeeting={enablePersonalMeeting} enableJoinAfterMeCopy={enableJoinAfterMeCopy} personalMeetingId={personalMeetingId} switchUsePersonalMeetingId={switchUsePersonalMeetingId} updateHasSettingsChanged={updateHasSettingsChanged} + disabled={configDisabled} + isPersonalMeetingDisabled={isPersonalMeetingDisabled} + labelPlacement={labelPlacement} + e2eeInteractFunc={e2eeInteractFunc} + updateScheduleFor={updateScheduleFor} + datePickerSize={datePickerSize} + timePickerSize={timePickerSize} + checkboxSize={checkboxSize} + isWaitingRoomNotCoworkerDisabled={isWaitingRoomNotCoworkerDisabled} + isWaitingRoomGuestDisabled={isWaitingRoomGuestDisabled} + isWaitingRoomAllDisabled={isWaitingRoomAllDisabled} + isAuthUserTypeDisabled={isAuthUserTypeDisabled} + isSignedInUsersDisabled={isSignedInUsersDisabled} + isSignedInCoWorkersDisabled={isSignedInCoWorkersDisabled} + showScheduleOnBehalf={showScheduleOnBehalf} + showSpinnerInConfigPanel={showSpinnerInConfigPanel} + delegators={delegators} + joinBeforeHostLabel={joinBeforeHostLabel} + authUserTypeValue={authUserTypeValue} + isJoinBeforeHostDisabled={isJoinBeforeHostDisabled} + isAuthenticatedCanJoinDisabled={isAuthenticatedCanJoinDisabled} + isWaitingRoomDisabled={isWaitingRoomDisabled} + isRequirePasswordDisabled={isRequirePasswordDisabled} > = ({ interface VideoPanelProps { currentLocale: string; meeting: RcVMeetingModel; - schedule: (meeting: RcVMeetingModel, opener: Window) => any; - updateMeetingSettings: (meeting: Partial) => void; - validatePasswordSettings: (password: string, isSecret: boolean) => boolean; hidden: boolean; disabled: boolean; onOK: any; @@ -118,10 +172,38 @@ interface VideoPanelProps { showDuration?: boolean; showRcvAdminLock?: boolean; showPmiAlert?: boolean; - enableWaitingRoom?: boolean; + showWaitingRoom?: boolean; + showE2EE?: boolean; + isE2EEDisabled?: boolean; enablePersonalMeeting?: boolean; enableJoinAfterMeCopy?: boolean; personalMeetingId: string; + isPersonalMeetingDisabled?: boolean; + datePickerSize?: RcDatePickerSize; + timePickerSize?: RcTimePickerSize; + checkboxSize?: RcCheckboxProps['size']; + labelPlacement?: 'end' | 'start' | 'top' | 'bottom'; + configDisabled?: boolean; + delegators?: RcvDelegator[]; + joinBeforeHostLabel: string; + authUserTypeValue: AUTH_USER; + isJoinBeforeHostDisabled: boolean; + isAuthenticatedCanJoinDisabled: boolean; + isWaitingRoomDisabled: boolean; + isRequirePasswordDisabled: boolean; + isWaitingRoomNotCoworkerDisabled: boolean; + isWaitingRoomGuestDisabled: boolean; + isWaitingRoomAllDisabled: boolean; + isAuthUserTypeDisabled: boolean; + isSignedInUsersDisabled: boolean; + isSignedInCoWorkersDisabled: boolean; + showScheduleOnBehalf: boolean; + showSpinnerInConfigPanel: boolean; switchUsePersonalMeetingId: (usePersonalMeetingId: boolean) => any; updateHasSettingsChanged: (isChanged: boolean) => void; + e2eeInteractFunc: (e2eeValue: boolean) => void; + schedule: (meeting: RcVMeetingModel, opener: Window) => any; + updateMeetingSettings: (meeting: Partial) => void; + validatePasswordSettings: (password: string, isSecret: boolean) => boolean; + updateScheduleFor: (userExtensionId: string) => any; } diff --git a/packages/ringcentral-widgets/components/VideoPanel/VideoSecuritySettingItem.tsx b/packages/ringcentral-widgets/components/VideoPanel/VideoSecuritySettingItem.tsx index 38375d3827..af79225421 100644 --- a/packages/ringcentral-widgets/components/VideoPanel/VideoSecuritySettingItem.tsx +++ b/packages/ringcentral-widgets/components/VideoPanel/VideoSecuritySettingItem.tsx @@ -1,6 +1,6 @@ import React, { FC, ReactNode } from 'react'; import { RcFormControlLabel, RcTooltip, RcIcon } from '@ringcentral/juno'; -import lockSvg from '@ringcentral/juno/icon/LockBorder'; +import { LockBorder } from '@ringcentral/juno/icon'; import i18n from './i18n'; import styles from './styles.scss'; @@ -21,15 +21,16 @@ function generateLockIcon( data-sign="lockButtonTooltip" title={i18n.getString('lockTooltip', currentLocale)} > - + ) : null; } -interface VideoSecuritySettingsItemProps { +interface VideoSecuritySettingItemProps { dataSign: string; label: string | React.ReactNode; isLock?: boolean; + isDisabled?: boolean; currentLocale: string; children: ReactNode; hasScrollBar: boolean; @@ -37,10 +38,11 @@ interface VideoSecuritySettingsItemProps { classes?: {}; } -export const VideoSecuritySettingsItem: FC = ({ +export const VideoSecuritySettingItem: FC = ({ dataSign, label, isLock = false, + isDisabled = false, currentLocale, children, hasScrollBar = false, @@ -49,7 +51,7 @@ export const VideoSecuritySettingsItem: FC = ({ return ( span { + margin-left: 4px; + } +} diff --git a/packages/ringcentral-widgets/components/WebRTCNotificationSection/WebRTCNotificationSection.tsx b/packages/ringcentral-widgets/components/WebRTCNotificationSection/WebRTCNotificationSection.tsx index abf674a36d..605119606f 100644 --- a/packages/ringcentral-widgets/components/WebRTCNotificationSection/WebRTCNotificationSection.tsx +++ b/packages/ringcentral-widgets/components/WebRTCNotificationSection/WebRTCNotificationSection.tsx @@ -1,17 +1,21 @@ -import classnames from 'classnames'; -import React, { FunctionComponent, useState, useEffect } from 'react'; import callDirections from '@ringcentral-integration/commons/enums/callDirections'; -import IgnoreIcon from '@ringcentral/juno/icon/Ignore'; -import VoicemailIcon from '@ringcentral/juno/icon/Voicemail'; -import { RcPopover, RcMenuList, RcMenuItem } from '@ringcentral/juno'; +import { RcMenuItem, RcMenuList, RcPopover, styled } from '@ringcentral/juno'; +import { Ignore, Voicemail } from '@ringcentral/juno/icon'; +import classnames from 'classnames'; +import React, { FunctionComponent, useEffect, useState } from 'react'; + +import AnswerIcon from '../../assets/images/Answer.svg'; +import EndAnswerIcon from '../../assets/images/EndAnswer.svg'; import ForwardIcon from '../../assets/images/Forward_white.svg'; import HoldAnswerIcon from '../../assets/images/HoldAnswer.svg'; -import EndAnswerIcon from '../../assets/images/EndAnswer.svg'; -import AnswerIcon from '../../assets/images/Answer.svg'; -import { WebRTCNotificationProps } from './WebRTCNotificationSection.interface'; import CircleButton from '../CircleButton'; -import styles from './styles.scss'; import i18n from './i18n'; +import styles from './styles.scss'; +import { WebRTCNotificationProps } from './WebRTCNotificationSection.interface'; + +const ForwardActiveList = styled.div` + max-width: 170px; +`; export const WebRTCNotificationSection: FunctionComponent = ({ call, @@ -75,7 +79,7 @@ export const WebRTCNotificationSection: FunctionComponent ) => { e.stopPropagation(); handleClose(); + // TODO: check that type, should switch to getAttribute const selectedValue = e.currentTarget.attributes['data-value'].value; onForward(selectedValue, call?.telephonySessionId); }; @@ -256,15 +261,10 @@ export const WebRTCNotificationSection: FunctionComponent handleClose()} classes={{ paper: styles.forwardPopover }} > -
+ {forwardList.map(({ text, subText, onClick, key }) => ( - +
{text && {text}} {subText && ( @@ -274,7 +274,7 @@ export const WebRTCNotificationSection: FunctionComponent ))} -
+
); }; diff --git a/packages/ringcentral-widgets/containers/CallCtrlPage/CallCtrlContainer.js b/packages/ringcentral-widgets/containers/CallCtrlPage/CallCtrlContainer.js index ce1753bda8..593a951e7e 100644 --- a/packages/ringcentral-widgets/containers/CallCtrlPage/CallCtrlContainer.js +++ b/packages/ringcentral-widgets/containers/CallCtrlPage/CallCtrlContainer.js @@ -140,7 +140,7 @@ class CallCtrlContainer extends Component { return this.props.getInitialLayout(nextProps); } - componentWillReceiveProps(nextProps, nextState) { + UNSAFE_componentWillReceiveProps(nextProps, nextState) { this._updateMergingPairToSessionId(nextProps, nextState); let layout = this.state.layout; @@ -234,9 +234,6 @@ class CallCtrlContainer extends Component { return null; } - const phoneNumber = - session.direction === callDirections.outbound ? session.to : session.from; - let fallbackUserName; if ( session.direction === callDirections.inbound && @@ -256,7 +253,7 @@ class CallCtrlContainer extends Component { i, - loadConference: (i) => i, getInitialLayout: () => callCtrlLayouts.normalCtrl, - layout: callCtrlLayouts.normalCtrl, closeMergingPair: null, - isWebRTC: false, - disableLinks: false, - isConferenceCallOverload: false, afterHideMergeConfirm: () => null, afterConfirmMerge: () => null, afterOnMerge: () => null, disableFlip: false, showCallQueueName: false, onCompleteTransfer: () => null, + showPark: false, }; export default CallCtrlContainer; diff --git a/packages/ringcentral-widgets/containers/ConnectivityBadgeContainer/index.js b/packages/ringcentral-widgets/containers/ConnectivityBadgeContainer/index.ts similarity index 100% rename from packages/ringcentral-widgets/containers/ConnectivityBadgeContainer/index.js rename to packages/ringcentral-widgets/containers/ConnectivityBadgeContainer/index.ts diff --git a/packages/ringcentral-widgets/containers/DialerPage/index.js b/packages/ringcentral-widgets/containers/DialerPage/index.ts similarity index 100% rename from packages/ringcentral-widgets/containers/DialerPage/index.js rename to packages/ringcentral-widgets/containers/DialerPage/index.ts diff --git a/packages/ringcentral-widgets/containers/HeaderView/HeaderView.interface.ts b/packages/ringcentral-widgets/containers/HeaderView/HeaderView.interface.ts new file mode 100644 index 0000000000..4f3d09405d --- /dev/null +++ b/packages/ringcentral-widgets/containers/HeaderView/HeaderView.interface.ts @@ -0,0 +1,26 @@ +import { BasicCall } from '@ringcentral-integration/commons/interfaces/Call.interface'; + +export interface HeaderViewProps { + userStatus?: string; + dndStatus?: string; + standAlone?: boolean; + ringingCalls?: BasicCall[]; + currentCalls?: BasicCall[]; + onHoldCalls?: BasicCall[]; + currentPath: string; + activeSessionId?: string; + incomingCallPageMinimized?: boolean; + currentLocale: string; + presenceReady?: boolean; + onCurrentCallBtnClick: () => void; + onViewCallBtnClick: () => void; + setAvailable: () => void; + setBusy: () => void; + setDoNotDisturb: () => void; + setInvisible: () => void; +} + +export interface Props extends HeaderViewProps { + logo: any; + children?: any; +} diff --git a/packages/ringcentral-widgets/containers/HeaderView/index.tsx b/packages/ringcentral-widgets/containers/HeaderView/index.tsx new file mode 100644 index 0000000000..3041618a7d --- /dev/null +++ b/packages/ringcentral-widgets/containers/HeaderView/index.tsx @@ -0,0 +1,82 @@ +import React, { FC } from 'react'; +import PresenceDropdown from '../../components/PresenceDropdown'; +import CallMonitorBar from '../../components/CallMonitorBar'; +import { connectModule } from '../../lib/phoneContext'; +import { Props } from './HeaderView.interface'; + +import styles from './styles.scss'; + +const ALL_CALL_PATH = '/calls'; +const ACTIVE_CALL_PATH = '/calls/active'; + +export const HeaderView: FC = ({ + logo, + userStatus, + dndStatus, + currentLocale, + setAvailable, + setBusy, + setDoNotDisturb, + setInvisible, + standAlone, + children, + ringingCalls, + onHoldCalls, + currentCalls, + currentPath, + activeSessionId, + incomingCallPageMinimized, + presenceReady, + ...props +}) => { + if (!standAlone) { + return children; + } + let shouldDisplayCallMonitorBar = false; + if ( + currentCalls.length > 0 || + ringingCalls.length > 0 || + onHoldCalls.length > 0 + ) { + shouldDisplayCallMonitorBar = true; + } + const Logo = logo; + + return ( +
+
+ + {shouldDisplayCallMonitorBar ? ( + + ) : ( + + )} +
+
{children}
+
+ ); +}; + +export default connectModule(({ headerViewUI }) => headerViewUI)(HeaderView); diff --git a/packages/ringcentral-widgets/containers/HeaderView/styles.scss b/packages/ringcentral-widgets/containers/HeaderView/styles.scss new file mode 100644 index 0000000000..4059c357dc --- /dev/null +++ b/packages/ringcentral-widgets/containers/HeaderView/styles.scss @@ -0,0 +1,91 @@ +@import '~@ringcentral-integration/widgets/lib/commonStyles/full-size'; +@import '~@ringcentral-integration/widgets/lib/commonStyles/no-select'; +@import '~@ringcentral-integration/widgets/lib/commonStyles/fonts'; + +$header-height: 36px; + +body { + @include primary-font; +} + +.root { + @include full-size; + padding-bottom: 0px; +} + +.header { + @include no-select; + position: relative; + height: $header-height; + line-height: $header-height; + text-align: center; + background-color: #fff; + border-bottom: 1px solid #e8e9ed; + z-index: 2; + box-sizing: border-box; +} + +.centerStyle { + top: 50%; + position: absolute; +} + +.presence { + @extend .centerStyle; + left: 20px; + height: 14px; + width: 14px; + border-radius: 8px; + margin-top: -7px; + display: none; + cursor: pointer; +} + +.Offline { + display: block; + background: #cdcdcd; +} + +.Busy { + display: block; + background: #f95b5c; +} + +.Available { + display: block; + background-color: #32ae31; +} + +.presenceBar { + display: none; + position: absolute; + width: 8px; + height: 2px; + border-radius: 1.5px; + background-color: #ffffff; + transform-origin: 50% 50%; + transform: translate(3px, 6px); +} + +.DoNotAcceptAnyCalls { + display: block; + background: #f95b5c; + .presenceBar { + display: block; + } +} + +.logo { + @extend .centerStyle; + left: 50%; + width: $header-logo-width; + height: $header-logo-height; + margin-left: -($header-logo-width / 2); + margin-top: -($header-logo-height / 2); +} + +.container { + position: relative; + height: calc(100% - #{$header-height}); + z-index: 1; +} diff --git a/packages/ringcentral-widgets/containers/RegionSettingsPage/index.js b/packages/ringcentral-widgets/containers/RegionSettingsPage/index.ts similarity index 100% rename from packages/ringcentral-widgets/containers/RegionSettingsPage/index.js rename to packages/ringcentral-widgets/containers/RegionSettingsPage/index.ts diff --git a/packages/ringcentral-widgets/containers/SettingsPage/index.ts b/packages/ringcentral-widgets/containers/SettingsPage/index.ts new file mode 100644 index 0000000000..398b71d79a --- /dev/null +++ b/packages/ringcentral-widgets/containers/SettingsPage/index.ts @@ -0,0 +1,4 @@ +import { connectModule } from '../../lib/phoneContext'; +import SettingsPanel from '../../components/SettingsPanel'; + +export default connectModule((phone) => phone.settingsUI)(SettingsPanel); diff --git a/packages/ringcentral-widgets/containers/TransferPage/index.js b/packages/ringcentral-widgets/containers/TransferPage/index.ts similarity index 100% rename from packages/ringcentral-widgets/containers/TransferPage/index.js rename to packages/ringcentral-widgets/containers/TransferPage/index.ts diff --git a/packages/ringcentral-widgets/jest.config.js b/packages/ringcentral-widgets/jest.config.js index caf590f64e..583e50ab1c 100644 --- a/packages/ringcentral-widgets/jest.config.js +++ b/packages/ringcentral-widgets/jest.config.js @@ -1,4 +1,5 @@ module.exports = { + testEnvironment: 'jsdom', transform: { 'loadLocale\\.(j|t)s$': '/test/__mocks__/loadLocale.ts', '^.+\\.(j|t)sx?$': diff --git a/packages/ringcentral-widgets/lib/AdapterCore/styles.scss b/packages/ringcentral-widgets/lib/AdapterCore/styles.scss index 449b4c488c..e1b6b25764 100644 --- a/packages/ringcentral-widgets/lib/AdapterCore/styles.scss +++ b/packages/ringcentral-widgets/lib/AdapterCore/styles.scss @@ -1,6 +1,8 @@ @import '../commonStyles/no-select'; @import '../commonStyles/colors'; +$header-height: 36px; + .centerStyle { top: 50%; position: absolute; @@ -14,8 +16,9 @@ display: block; visibility: visible; bottom: 0; - background-color: #f3f3f3; - transition: visibility 0.2s 0s linear, opacity 0.2s 0s linear, transform 0.1s 0s ease-in-out; + background-color: #fff; + transition: visibility 0.2s 0s linear, opacity 0.2s 0s linear, + transform 0.1s 0s ease-in-out; z-index: 99999; box-shadow: 0px 0px 5px 1px rgba(0, 0, 0, 0.18); overflow: hidden; @@ -54,18 +57,21 @@ .header { @include no-select; position: relative; - height: 35px; - line-height: 35px; - min-width: 165px; + height: $header-height; + line-height: $header-height; + min-width: 134px; text-align: center; cursor: move; z-index: 11; overflow: hidden; font-family: Helvetica; font-weight: normal; + border-bottom: 1px solid #e8e9ed; + box-sizing: border-box; } .minimized.header { + border-bottom: none; cursor: ew-resize; } @@ -73,10 +79,10 @@ @include no-select; @extend .centerStyle; left: 50%; - height: 16px; - width: 100px; + height: 18px; + width: 84px; margin-top: -8px; - margin-left: -50px; + margin-left: -32px; display: none; } .logo.visible { @@ -117,13 +123,13 @@ } .selected { - color: #066FAC; + color: #066fac; } .line { position: relative; width: 160px; - min-width: 165px; + min-width: 134px; left: 5px; padding: 0; min-height: 30px; @@ -136,9 +142,9 @@ border-bottom-width: 0px; border-color: #eeeeee; border-radius: 4px; - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14px; - color: #2F2F2F; + color: #2f2f2f; .horizontal { display: inline-flex; } @@ -204,21 +210,19 @@ @extend .centerStyle; height: 20px; width: 20px; - margin-top: -12px; + margin-top: -10px; border-radius: 3px; cursor: pointer; border-style: solid; border-width: 1px; border-color: transparent; } -.button:hover { - border-color: #cccccc; -} + .toggle { - right: 40px; + right: 44px; } .minimized .toggle { - right: 3px; + right: -18px; } .minimizeIcon { @@ -252,7 +256,8 @@ margin: 2px; width: 14px; height: 14px; - :first-child, :last-child { + :first-child, + :last-child { position: absolute; height: 2px; width: 100%; @@ -283,7 +288,8 @@ 0% { box-shadow: inset 0 0 7px -10px $primary-color; } - 40%, 50% { + 40%, + 50% { box-shadow: inset 0 0 7px 0px $primary-color; } 100% { @@ -345,7 +351,9 @@ font-size: 12px; white-space: nowrap; } -.duration.visible, .ringingCalls.visible, .onHoldCalls.visible { +.duration.visible, +.ringingCalls.visible, +.onHoldCalls.visible { top: 50%; } .duration { @@ -357,7 +365,8 @@ .duration.center { margin-left: -16px; } -.ringingCalls, .onHoldCalls { +.ringingCalls, +.onHoldCalls { @include callInfo; width: 100px; margin-left: -100px; @@ -365,7 +374,8 @@ overflow: hidden; text-align: center; } -.ringingCalls.center, .onHoldCalls.center { +.ringingCalls.center, +.onHoldCalls.center { margin-left: -50px; } diff --git a/packages/ringcentral-widgets/lib/AdapterModuleCore/index.js b/packages/ringcentral-widgets/lib/AdapterModuleCore/index.js index 0494474adc..f53a6c24e8 100644 --- a/packages/ringcentral-widgets/lib/AdapterModuleCore/index.js +++ b/packages/ringcentral-widgets/lib/AdapterModuleCore/index.js @@ -25,6 +25,7 @@ const ACTIVE_CALL_PATH = '/calls/active'; 'Storage', 'Webphone', 'CallMonitor', + { dep: 'ActiveCallControl', optional: true }, { dep: 'UserGuide', optional: true }, { dep: 'QuickAccess', optional: true }, ], @@ -46,6 +47,7 @@ export default class AdapterModuleCore extends AdapterModuleCoreBase { messageTransport = new IframeMessageTransport({ targetWindow: window.parent, }), + activeCallControl, ...options }: { prefix?: string, @@ -62,6 +64,7 @@ export default class AdapterModuleCore extends AdapterModuleCoreBase { quickAccess?: any, messageTransport?: any, storage?: any, + activeCallControl?: any, }) { super({ prefix, @@ -80,6 +83,7 @@ export default class AdapterModuleCore extends AdapterModuleCoreBase { this._callMonitor = callMonitor; this._userGuide = userGuide; this._quickAccess = quickAccess; + this._activeCallControl = activeCallControl; } _pushOtherStateChanges() { @@ -100,7 +104,12 @@ export default class AdapterModuleCore extends AdapterModuleCoreBase { if (!this._callingSettings) return; const { callingMode } = this._callingSettings; if (callingMode === callingModes.webphone) { - this._pushWebRTCRingingState(forcePush); + // TODO: should change to use ActiveCallControl module when introduce ActiveCallControl module into other project + if (this._activeCallControl) { + this._pushActiveCallRingingState(forcePush); + } else { + this._pushWebphoneRingingState(forcePush); + } this._pushCallStartTime(forcePush); this._pushIncomingCallPage(forcePush); } else { @@ -108,7 +117,37 @@ export default class AdapterModuleCore extends AdapterModuleCoreBase { } } - _pushWebRTCRingingState(forcePush) { + _pushActiveCallRingingState(forcePush) { + if ( + this._activeCallControl.ringSessions.length > 0 && + this._activeCallControl.ringSessionId && + (this._activeCallControl.ringSessionId !== this._ringSessionId || + forcePush) + ) { + this._ringSessionId = this._activeCallControl.ringSessionId; + this._postMessage({ + type: this._messageTypes.pushRingState, + ringing: true, + }); + } + // Check if ringing is over + if (this._ringSessionId) { + if (this._activeCallControl.ringSessions.length === 0) { + this._postMessage({ + type: this._messageTypes.pushRingState, + ringing: false, + }); + this._ringSessionId = null; + } + } else { + this._postMessage({ + type: this._messageTypes.pushRingState, + ringing: false, + }); + } + } + + _pushWebphoneRingingState(forcePush) { const webphone = this._webphone; if (!webphone) { throw new Error( @@ -132,14 +171,14 @@ export default class AdapterModuleCore extends AdapterModuleCoreBase { session.callStatus === 'webphone-session-connecting' && session.direction === 'Inbound', ); - if (ringingSessions.length <= 0) { + if (ringingSessions.length === 0) { this._postMessage({ type: this._messageTypes.pushRingState, ringing: false, }); this._ringSessionId = null; } - } else if (!this._ringSessionId) { + } else { this._postMessage({ type: this._messageTypes.pushRingState, ringing: false, diff --git a/packages/ringcentral-widgets/lib/MeetingCalendarHelper/config.ts b/packages/ringcentral-widgets/lib/MeetingCalendarHelper/config.ts index e3060efb67..68ccf56181 100644 --- a/packages/ringcentral-widgets/lib/MeetingCalendarHelper/config.ts +++ b/packages/ringcentral-widgets/lib/MeetingCalendarHelper/config.ts @@ -1,17 +1,13 @@ -const MEETING_URI_REGEXP: { - EMAIL: RegExp; - RCM: RegExp; - RCV: RegExp; -} = { - EMAIL: /w?(\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*)$/, - RCM: /(https?):\/\/((((meetings|rcm\.rcdev)\.(ringcentral|btcloudphone\.bt|businessconnect\.telus))|(meetings-officeathand\.att)|(rcm.rcdev.ringcentral))\.com|((\w+\.)*(meetzoom|zoom)\.us))(\/\w+)?(\/(\d+))(\?pwd=\w+)?/i, - RCV: /(https?):\/\/(((verizon\.)?(v\.ringcentral)|(meetings\.officeathand\.att)|(video\.(unifyoffice|cloudoffice\.avaya|rainbowoffice))|((glpci1xmn|itlcixmn|xmnup)-rxe-1-v(-(vodafone|avaya|atos|rainbow|bt|telus))?\.lab\.nordigy)|((vi11|amrupams-shr)-(1|2)-v(-(att|bt|telus))?\.lab\.nordigy))\.(com|ru|biz))(\/{1,2}\w+)*(\/{1,2}(\d+))(\?pw=\w{32})?/i, -}; +/** Domain of RCV + * Rainbow:xmnup-rxe-1-v-rainbow.lab.nordigy.ru (test env); video.rainbowoffice.com (prod env) + * Avaya: xmnup-rxe-1-v-avaya.lab.nordigy.ru (test env); video.cloudoffice.avaya.com (prod env) + * RC: xmnup-rxe-1-v.lab.nordigy.ru (test env); v.ringcentral.com (prod env) + * RND-VI3-AMS + RND-VI11-AMS: "vi11-1-v.lab.nordigy.ru | vi11-2-v.lab.nordigy.ru" (test env has two domain) + * AT&T: vi11-1-v-att.lab.nordigy.ru (test env) ; meetings.officeathand.att.com (prod env) + * Atos: xmnup-rxe-1-v-atos.lab.nordigy.ru(test env); video-atos.ringcentral.com (prod env) + */ -const rcvAttTeleconference: string = - 'https://meetings.officeathand.att.com/teleconference'; - -const rcvTeleconference: string = 'https://v.ringcentral.com/teleconference/'; +const MEETING_URI_REGEXP_EMAIL = /w?(\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*)$/; // gsuite is using export at bottom -export { MEETING_URI_REGEXP, rcvAttTeleconference, rcvTeleconference }; +export { MEETING_URI_REGEXP_EMAIL }; diff --git a/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/de-DE.js b/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/de-DE.js index b0f0fe10e5..f580f3733e 100644 --- a/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/de-DE.js +++ b/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/de-DE.js @@ -1,7 +1,10 @@ export default { inviteMeetingContent: "{accountName} lädt Sie zu einer {brandName}-Besprechung ein.\n\nÜber PC, Mac, iOS oder Android teilnehmen: {joinUri}{passwordTpl}\n\nOder iPhone One-tap:\n {mobileDialingNumberTpl}\n\nOder Telefon:\n Wählen Sie: {phoneDialingNumberTpl}\n Besprechungs-ID: {meetingId}\n Internationale Nummern verfügbar: {teleconference} ", rcvInviteMeetingContent: "{accountName} hat Sie zu einer {brandName}-Besprechung eingeladen.\n\nBitte nehmen Sie über folgenden Link teil:\n {joinUri}{passwordTpl}", + rcvTelusInviteMeetingContent: "{accountName} hat Sie zu einer TELUS Business Connect-Besprechung eingeladen.\n\nBitte nehmen Sie über folgenden Link teil:\n {joinUri}{passwordTpl}", rcvRCBrandInviteMeetingContent: "{accountName} hat Sie zu einer {productName}-Besprechung eingeladen.\n\nBitte nehmen Sie über folgenden Link teil:\n {joinUri}{passwordTpl}", + rcvE2EEInviteMeetingContent: "{accountName} hat Sie zu einer End-to-End-verschlüsselten {rcvProductName}-Besprechung eingeladen.\n\nBitte nehmen Sie über folgenden Link teil: Beachten Sie, dass Sie sich zuerst bei der {brandName}-App anmelden müssen:\n{joinUri}\n\nFür diese Besprechung ist keine Einwahl möglich.\n\n{e2EESupportLinkText}\n{rcvE2EESupportUrl}", + e2EESupportLinkText: "Erfahren Sie mehr über die End-to-End-Verschlüsselung von {brandName}.", rcvInviteMeetingContentDial: "\n\nEinmal tippen und mit dem Smartphone teilnehmen (nur Audio):\n {smartphones}\n\nOder wählen Sie:\n Wählen Sie: {dialNumber}\n Zugriffscode/Besprechungs-ID: {pinNumber} ", rcvInviteMeetingContentCountryDial: "\n\nEinmal tippen und mit dem Smartphone teilnehmen (nur Audio):\n {smartphones}\n\nOder wählen Sie:\n {dialNumber}\n Zugriffscode/Besprechungs-ID: {pinNumber} ", rcvTeleconference: "\n\nInternationale Nummern verfügbar: {teleconference} ", @@ -16,7 +19,10 @@ export default { // @key: @#@"inviteMeetingContent"@#@ @source: @#@"{accountName} is inviting you to a {brandName} meeting.\n\nJoin from PC, Mac, iOS or Android: {joinUri}{passwordTpl}\n\nOr iPhone one-tap:\n {mobileDialingNumberTpl}\n\nOr Telephone:\n Dial: {phoneDialingNumberTpl}\n Meeting ID: {meetingId}\n International numbers available: {teleconference} "@#@ // @key: @#@"rcvInviteMeetingContent"@#@ @source: @#@"{accountName} has invited you to a {brandName} Meeting.\n\nPlease join using this link:\n {joinUri}{passwordTpl}"@#@ +// @key: @#@"rcvTelusInviteMeetingContent"@#@ @source: @#@"{accountName} has invited you to a TELUS Business Connect Meeting.\n\nPlease join using this link:\n {joinUri}{passwordTpl}"@#@ // @key: @#@"rcvRCBrandInviteMeetingContent"@#@ @source: @#@"{accountName} has invited you to a {productName} meeting.\n\nPlease join using this link:\n {joinUri}{passwordTpl}"@#@ +// @key: @#@"rcvE2EEInviteMeetingContent"@#@ @source: @#@"{accountName} has invited you to an end-to-end encrypted {rcvProductName} meeting.\n\nPlease join using this link. Note, you'll need to log in to the {brandName} app first:\n{joinUri}\n\nDial-in is not available for this meeting.\n\n{e2EESupportLinkText}\n{rcvE2EESupportUrl}"@#@ +// @key: @#@"e2EESupportLinkText"@#@ @source: @#@"Find out more about {brandName}'s end-to-end encryption."@#@ // @key: @#@"rcvInviteMeetingContentDial"@#@ @source: @#@"\n\nOne tap to join audio only from a smartphone:\n {smartphones}\n\nOr dial:\n Dial: {dialNumber}\n Access Code / Meeting ID: {pinNumber} "@#@ // @key: @#@"rcvInviteMeetingContentCountryDial"@#@ @source: @#@"\n\nOne tap to join audio only from a smartphone:\n {smartphones}\n\nOr dial:\n {dialNumber}\n Access Code / Meeting ID: {pinNumber} "@#@ // @key: @#@"rcvTeleconference"@#@ @source: @#@"\n\nInternational numbers available: {teleconference} "@#@ diff --git a/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/en-AU.js b/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/en-AU.js index 35ac80aae2..eabb1905ec 100644 --- a/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/en-AU.js +++ b/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/en-AU.js @@ -1,7 +1,10 @@ export default { inviteMeetingContent: "{accountName} is inviting you to a {brandName} meeting.\n\nJoin from PC, Mac, iOS or Android: {joinUri}{passwordTpl}\n\nOr iPhone one-tap:\n {mobileDialingNumberTpl}\n\nOr Telephone:\n Dial: {phoneDialingNumberTpl}\n Meeting ID: {meetingId}\n International numbers available: {teleconference} ", rcvInviteMeetingContent: "{accountName} has invited you to a {brandName} Meeting.\n\nPlease join using this link:\n {joinUri}{passwordTpl}", + rcvTelusInviteMeetingContent: "{accountName} has invited you to a TELUS Business Connect Meeting.\n\nPlease join using this link:\n {joinUri}{passwordTpl}", rcvRCBrandInviteMeetingContent: "{accountName} has invited you to a {productName} meeting.\n\nPlease join using this link:\n {joinUri}{passwordTpl}", + rcvE2EEInviteMeetingContent: "{accountName} has invited you to an end-to-end encrypted {rcvProductName} meeting.\n\nPlease join using this link. Note, you’ll need to log in to the {brandName} app first:\n{joinUri}\n\nDial-in is not available for this meeting.\n\n{e2EESupportLinkText}\n{rcvE2EESupportUrl}", + e2EESupportLinkText: "Find out more about {brandName}’s end-to-end encryption.", rcvInviteMeetingContentDial: "\n\nOne tap to join audio only from a smartphone:\n {smartphones}\n\nOr dial:\n Dial: {dialNumber}\n Access Code/Meeting ID: {pinNumber} ", rcvInviteMeetingContentCountryDial: "\n\nOne tap to join audio only from a smartphone:\n {smartphones}\n\nOr dial:\n {dialNumber}\n Access Code/Meeting ID: {pinNumber} ", rcvTeleconference: "\n\nInternational numbers available: {teleconference} ", @@ -16,7 +19,10 @@ export default { // @key: @#@"inviteMeetingContent"@#@ @source: @#@"{accountName} is inviting you to a {brandName} meeting.\n\nJoin from PC, Mac, iOS or Android: {joinUri}{passwordTpl}\n\nOr iPhone one-tap:\n {mobileDialingNumberTpl}\n\nOr Telephone:\n Dial: {phoneDialingNumberTpl}\n Meeting ID: {meetingId}\n International numbers available: {teleconference} "@#@ // @key: @#@"rcvInviteMeetingContent"@#@ @source: @#@"{accountName} has invited you to a {brandName} Meeting.\n\nPlease join using this link:\n {joinUri}{passwordTpl}"@#@ +// @key: @#@"rcvTelusInviteMeetingContent"@#@ @source: @#@"{accountName} has invited you to a TELUS Business Connect Meeting.\n\nPlease join using this link:\n {joinUri}{passwordTpl}"@#@ // @key: @#@"rcvRCBrandInviteMeetingContent"@#@ @source: @#@"{accountName} has invited you to a {productName} meeting.\n\nPlease join using this link:\n {joinUri}{passwordTpl}"@#@ +// @key: @#@"rcvE2EEInviteMeetingContent"@#@ @source: @#@"{accountName} has invited you to an end-to-end encrypted {rcvProductName} meeting.\n\nPlease join using this link. Note, you'll need to log in to the {brandName} app first:\n{joinUri}\n\nDial-in is not available for this meeting.\n\n{e2EESupportLinkText}\n{rcvE2EESupportUrl}"@#@ +// @key: @#@"e2EESupportLinkText"@#@ @source: @#@"Find out more about {brandName}'s end-to-end encryption."@#@ // @key: @#@"rcvInviteMeetingContentDial"@#@ @source: @#@"\n\nOne tap to join audio only from a smartphone:\n {smartphones}\n\nOr dial:\n Dial: {dialNumber}\n Access Code / Meeting ID: {pinNumber} "@#@ // @key: @#@"rcvInviteMeetingContentCountryDial"@#@ @source: @#@"\n\nOne tap to join audio only from a smartphone:\n {smartphones}\n\nOr dial:\n {dialNumber}\n Access Code / Meeting ID: {pinNumber} "@#@ // @key: @#@"rcvTeleconference"@#@ @source: @#@"\n\nInternational numbers available: {teleconference} "@#@ diff --git a/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/en-GB.js b/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/en-GB.js index 35ac80aae2..eabb1905ec 100644 --- a/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/en-GB.js +++ b/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/en-GB.js @@ -1,7 +1,10 @@ export default { inviteMeetingContent: "{accountName} is inviting you to a {brandName} meeting.\n\nJoin from PC, Mac, iOS or Android: {joinUri}{passwordTpl}\n\nOr iPhone one-tap:\n {mobileDialingNumberTpl}\n\nOr Telephone:\n Dial: {phoneDialingNumberTpl}\n Meeting ID: {meetingId}\n International numbers available: {teleconference} ", rcvInviteMeetingContent: "{accountName} has invited you to a {brandName} Meeting.\n\nPlease join using this link:\n {joinUri}{passwordTpl}", + rcvTelusInviteMeetingContent: "{accountName} has invited you to a TELUS Business Connect Meeting.\n\nPlease join using this link:\n {joinUri}{passwordTpl}", rcvRCBrandInviteMeetingContent: "{accountName} has invited you to a {productName} meeting.\n\nPlease join using this link:\n {joinUri}{passwordTpl}", + rcvE2EEInviteMeetingContent: "{accountName} has invited you to an end-to-end encrypted {rcvProductName} meeting.\n\nPlease join using this link. Note, you’ll need to log in to the {brandName} app first:\n{joinUri}\n\nDial-in is not available for this meeting.\n\n{e2EESupportLinkText}\n{rcvE2EESupportUrl}", + e2EESupportLinkText: "Find out more about {brandName}’s end-to-end encryption.", rcvInviteMeetingContentDial: "\n\nOne tap to join audio only from a smartphone:\n {smartphones}\n\nOr dial:\n Dial: {dialNumber}\n Access Code/Meeting ID: {pinNumber} ", rcvInviteMeetingContentCountryDial: "\n\nOne tap to join audio only from a smartphone:\n {smartphones}\n\nOr dial:\n {dialNumber}\n Access Code/Meeting ID: {pinNumber} ", rcvTeleconference: "\n\nInternational numbers available: {teleconference} ", @@ -16,7 +19,10 @@ export default { // @key: @#@"inviteMeetingContent"@#@ @source: @#@"{accountName} is inviting you to a {brandName} meeting.\n\nJoin from PC, Mac, iOS or Android: {joinUri}{passwordTpl}\n\nOr iPhone one-tap:\n {mobileDialingNumberTpl}\n\nOr Telephone:\n Dial: {phoneDialingNumberTpl}\n Meeting ID: {meetingId}\n International numbers available: {teleconference} "@#@ // @key: @#@"rcvInviteMeetingContent"@#@ @source: @#@"{accountName} has invited you to a {brandName} Meeting.\n\nPlease join using this link:\n {joinUri}{passwordTpl}"@#@ +// @key: @#@"rcvTelusInviteMeetingContent"@#@ @source: @#@"{accountName} has invited you to a TELUS Business Connect Meeting.\n\nPlease join using this link:\n {joinUri}{passwordTpl}"@#@ // @key: @#@"rcvRCBrandInviteMeetingContent"@#@ @source: @#@"{accountName} has invited you to a {productName} meeting.\n\nPlease join using this link:\n {joinUri}{passwordTpl}"@#@ +// @key: @#@"rcvE2EEInviteMeetingContent"@#@ @source: @#@"{accountName} has invited you to an end-to-end encrypted {rcvProductName} meeting.\n\nPlease join using this link. Note, you'll need to log in to the {brandName} app first:\n{joinUri}\n\nDial-in is not available for this meeting.\n\n{e2EESupportLinkText}\n{rcvE2EESupportUrl}"@#@ +// @key: @#@"e2EESupportLinkText"@#@ @source: @#@"Find out more about {brandName}'s end-to-end encryption."@#@ // @key: @#@"rcvInviteMeetingContentDial"@#@ @source: @#@"\n\nOne tap to join audio only from a smartphone:\n {smartphones}\n\nOr dial:\n Dial: {dialNumber}\n Access Code / Meeting ID: {pinNumber} "@#@ // @key: @#@"rcvInviteMeetingContentCountryDial"@#@ @source: @#@"\n\nOne tap to join audio only from a smartphone:\n {smartphones}\n\nOr dial:\n {dialNumber}\n Access Code / Meeting ID: {pinNumber} "@#@ // @key: @#@"rcvTeleconference"@#@ @source: @#@"\n\nInternational numbers available: {teleconference} "@#@ diff --git a/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/en-US.js b/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/en-US.js index 8f1c5cfa9f..c600d94e4c 100644 --- a/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/en-US.js +++ b/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/en-US.js @@ -3,8 +3,13 @@ export default { '{accountName} is inviting you to a {brandName} meeting.\n\nJoin from PC, Mac, iOS or Android: {joinUri}{passwordTpl}\n\nOr iPhone one-tap:\n {mobileDialingNumberTpl}\n\nOr Telephone:\n Dial: {phoneDialingNumberTpl}\n Meeting ID: {meetingId}\n International numbers available: {teleconference} ', rcvInviteMeetingContent: '{accountName} has invited you to a {brandName} Meeting.\n\nPlease join using this link:\n {joinUri}{passwordTpl}', + rcvTelusInviteMeetingContent: + '{accountName} has invited you to a TELUS Business Connect Meeting.\n\nPlease join using this link:\n {joinUri}{passwordTpl}', rcvRCBrandInviteMeetingContent: '{accountName} has invited you to a {productName} meeting.\n\nPlease join using this link:\n {joinUri}{passwordTpl}', + rcvE2EEInviteMeetingContent: + "{accountName} has invited you to an end-to-end encrypted {rcvProductName} meeting.\n\nPlease join using this link. Note, you'll need to log in to the {brandName} app first:\n{joinUri}\n\nDial-in is not available for this meeting.\n\n{e2EESupportLinkText}\n{rcvE2EESupportUrl}", + e2EESupportLinkText: "Find out more about {brandName}'s end-to-end encryption.", rcvInviteMeetingContentDial: '\n\nOne tap to join audio only from a smartphone:\n {smartphones}\n\nOr dial:\n Dial: {dialNumber}\n Access Code / Meeting ID: {pinNumber} ', rcvInviteMeetingContentCountryDial: diff --git a/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/es-419.js b/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/es-419.js index 36141e783a..a4d5651466 100644 --- a/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/es-419.js +++ b/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/es-419.js @@ -1,7 +1,10 @@ export default { inviteMeetingContent: "{accountName} le invita a una reunión de {brandName}.\n\nUnirse desde una PC, Mac, iOS o Android: {joinUri}{passwordTpl}\n\nO desde iPhone con un solo toque:\n {mobileDialingNumberTpl}\n\nO por teléfono:\n Marcar: {phoneDialingNumberTpl}\n ID de reunión: {meetingId}\n Números internacionales disponibles: {teleconference} ", rcvInviteMeetingContent: "{accountName} lo invitó a una reunión de {brandName}.\n\nÚnase mediante este enlace:\n {joinUri}{passwordTpl}", + rcvTelusInviteMeetingContent: "{accountName} lo ha invitado a una reunión TELUS Business Connect.\n\nÚnase mediante este enlace:\n {joinUri}{passwordTpl}", rcvRCBrandInviteMeetingContent: "{accountName} lo invitó a una reunión de {productName}.\n\nÚnase mediante este enlace:\n {joinUri}{passwordTpl}", + rcvE2EEInviteMeetingContent: "{accountName} lo ha invitado a una reunión cifrada de extremo a extremo{rcvProductName}.\n\nÚnase con este enlace. Aviso, deberá iniciar sesión en la aplicación {brandName} primero:\n{joinUri}\n\nEl marcado no está disponible para esta reunión.\n\n{e2EESupportLinkText}\n{rcvE2EESupportUrl}", + e2EESupportLinkText: "Conozca más sobre el cifrado de extremo a extremo de {brandName}.", rcvInviteMeetingContentDial: "\n\nPulse una vez para unir el audio solo desde un smartphone:\n {smartphones}\n\nO marque:\n Marcar: {dialNumber}\n Código de acceso/ID de la reunión: {pinNumber} ", rcvInviteMeetingContentCountryDial: "\n\nPulse una vez para unir el audio solo desde un smartphone:\n {smartphones}\n\nO marque:\n {dialNumber}\n Código de acceso/ID de la reunión: {pinNumber} ", rcvTeleconference: "\n\nNúmeros internacionales disponibles: {teleconference} ", @@ -16,7 +19,10 @@ export default { // @key: @#@"inviteMeetingContent"@#@ @source: @#@"{accountName} is inviting you to a {brandName} meeting.\n\nJoin from PC, Mac, iOS or Android: {joinUri}{passwordTpl}\n\nOr iPhone one-tap:\n {mobileDialingNumberTpl}\n\nOr Telephone:\n Dial: {phoneDialingNumberTpl}\n Meeting ID: {meetingId}\n International numbers available: {teleconference} "@#@ // @key: @#@"rcvInviteMeetingContent"@#@ @source: @#@"{accountName} has invited you to a {brandName} Meeting.\n\nPlease join using this link:\n {joinUri}{passwordTpl}"@#@ +// @key: @#@"rcvTelusInviteMeetingContent"@#@ @source: @#@"{accountName} has invited you to a TELUS Business Connect Meeting.\n\nPlease join using this link:\n {joinUri}{passwordTpl}"@#@ // @key: @#@"rcvRCBrandInviteMeetingContent"@#@ @source: @#@"{accountName} has invited you to a {productName} meeting.\n\nPlease join using this link:\n {joinUri}{passwordTpl}"@#@ +// @key: @#@"rcvE2EEInviteMeetingContent"@#@ @source: @#@"{accountName} has invited you to an end-to-end encrypted {rcvProductName} meeting.\n\nPlease join using this link. Note, you'll need to log in to the {brandName} app first:\n{joinUri}\n\nDial-in is not available for this meeting.\n\n{e2EESupportLinkText}\n{rcvE2EESupportUrl}"@#@ +// @key: @#@"e2EESupportLinkText"@#@ @source: @#@"Find out more about {brandName}'s end-to-end encryption."@#@ // @key: @#@"rcvInviteMeetingContentDial"@#@ @source: @#@"\n\nOne tap to join audio only from a smartphone:\n {smartphones}\n\nOr dial:\n Dial: {dialNumber}\n Access Code / Meeting ID: {pinNumber} "@#@ // @key: @#@"rcvInviteMeetingContentCountryDial"@#@ @source: @#@"\n\nOne tap to join audio only from a smartphone:\n {smartphones}\n\nOr dial:\n {dialNumber}\n Access Code / Meeting ID: {pinNumber} "@#@ // @key: @#@"rcvTeleconference"@#@ @source: @#@"\n\nInternational numbers available: {teleconference} "@#@ diff --git a/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/es-ES.js b/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/es-ES.js index f6cf403e19..0a04b34896 100644 --- a/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/es-ES.js +++ b/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/es-ES.js @@ -1,7 +1,10 @@ export default { inviteMeetingContent: "{accountName} le invita a una reunión de {brandName}.\n\nÚnase desde un equipo PC, Mac, iOS o Android: {joinUri}{passwordTpl}\n\nO con un toque desde el iPhone:\n {mobileDialingNumberTpl}\n\nO por teléfono:\n Marque: {phoneDialingNumberTpl}\n ID de reunión: {meetingId}\n Números internacionales disponibles: {teleconference} ", rcvInviteMeetingContent: "{accountName} le ha invitado a una reunión de {brandName}.\n\nÚnase mediante este enlace:\n {joinUri}{passwordTpl}", + rcvTelusInviteMeetingContent: "{accountName} le ha invitado a una reunión de TELUS Business Connect.\n\nÚnase mediante este enlace:\n {joinUri}{passwordTpl}", rcvRCBrandInviteMeetingContent: "{accountName} le ha invitado a una reunión de {productName}.\n\nÚnase mediante este enlace:\n {joinUri}{passwordTpl}", + rcvE2EEInviteMeetingContent: "{accountName} le ha invitado a una reunión cifrada de extremo a extremo de {rcvProductName}.\n\nÚnase mediante este enlace. Tenga en cuenta que primero necesitará iniciar sesión en la aplicación {brandName}:\n{joinUri} La marcación no está disponible para esta reunión.\n\n{e2EESupportLinkText}\n{rcvE2EESupportUrl}", + e2EESupportLinkText: "Obtenga más información sobre el cifrado de extremo a extremo de {brandName}.", rcvInviteMeetingContentDial: "\n\nUn toque para unirse al audio solo desde un smartphone:\n {smartphones}\n\nO marque:\n Marque: {dialNumber}\n Código de acceso/ID de reunión: {pinNumber} ", rcvInviteMeetingContentCountryDial: "\n\nUn toque para unirse al audio solo desde un smartphone:\n {smartphones}\n\nO marque:\n {dialNumber}\n Código de acceso/ID de reunión: {pinNumber} ", rcvTeleconference: "\n\nNúmeros internacionales disponibles: {teleconference} ", @@ -16,7 +19,10 @@ export default { // @key: @#@"inviteMeetingContent"@#@ @source: @#@"{accountName} is inviting you to a {brandName} meeting.\n\nJoin from PC, Mac, iOS or Android: {joinUri}{passwordTpl}\n\nOr iPhone one-tap:\n {mobileDialingNumberTpl}\n\nOr Telephone:\n Dial: {phoneDialingNumberTpl}\n Meeting ID: {meetingId}\n International numbers available: {teleconference} "@#@ // @key: @#@"rcvInviteMeetingContent"@#@ @source: @#@"{accountName} has invited you to a {brandName} Meeting.\n\nPlease join using this link:\n {joinUri}{passwordTpl}"@#@ +// @key: @#@"rcvTelusInviteMeetingContent"@#@ @source: @#@"{accountName} has invited you to a TELUS Business Connect Meeting.\n\nPlease join using this link:\n {joinUri}{passwordTpl}"@#@ // @key: @#@"rcvRCBrandInviteMeetingContent"@#@ @source: @#@"{accountName} has invited you to a {productName} meeting.\n\nPlease join using this link:\n {joinUri}{passwordTpl}"@#@ +// @key: @#@"rcvE2EEInviteMeetingContent"@#@ @source: @#@"{accountName} has invited you to an end-to-end encrypted {rcvProductName} meeting.\n\nPlease join using this link. Note, you'll need to log in to the {brandName} app first:\n{joinUri}\n\nDial-in is not available for this meeting.\n\n{e2EESupportLinkText}\n{rcvE2EESupportUrl}"@#@ +// @key: @#@"e2EESupportLinkText"@#@ @source: @#@"Find out more about {brandName}'s end-to-end encryption."@#@ // @key: @#@"rcvInviteMeetingContentDial"@#@ @source: @#@"\n\nOne tap to join audio only from a smartphone:\n {smartphones}\n\nOr dial:\n Dial: {dialNumber}\n Access Code / Meeting ID: {pinNumber} "@#@ // @key: @#@"rcvInviteMeetingContentCountryDial"@#@ @source: @#@"\n\nOne tap to join audio only from a smartphone:\n {smartphones}\n\nOr dial:\n {dialNumber}\n Access Code / Meeting ID: {pinNumber} "@#@ // @key: @#@"rcvTeleconference"@#@ @source: @#@"\n\nInternational numbers available: {teleconference} "@#@ diff --git a/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/fr-CA.js b/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/fr-CA.js index f17b04c779..7750dbae8f 100644 --- a/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/fr-CA.js +++ b/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/fr-CA.js @@ -1,7 +1,10 @@ export default { inviteMeetingContent: "{accountName} vous invite à une réunion {brandName}.\n\nS’y joindre sur PC, Mac, iOS ou Android : {joinUri}{passwordTpl}\n\nOu participer d’un seul toucher sur iPhone :\n {mobileDialingNumberTpl}\n\nOu d’un téléphone :\n Numéro à composer : {phoneDialingNumberTpl}\n Code de réunion : {meetingId}\n Numéros internationaux disponibles : {teleconference} ", rcvInviteMeetingContent: "{accountName} vous invite à une réunion {brandName}.\n\nVeuillez vous joindre à la réunion en suivant ce lien :\n {joinUri}{passwordTpl}", + rcvTelusInviteMeetingContent: "{accountName} vous invite à une réunion Connexion Affaires de TELUS.\n\nVeuillez vous joindre à la réunion en suivant ce lien :\n {joinUri}{passwordTpl}", rcvRCBrandInviteMeetingContent: "{accountName} vous invite à une réunion {productName}.\n\nVeuillez vous joindre à la réunion en suivant ce lien :\n {joinUri}{passwordTpl}", + rcvE2EEInviteMeetingContent: "{accountName} vous a invité à une réunion {rcvProductName} chiffrée de bout en bout.\n\nVeuillez vous joindre à la réunion à l’aide de ce lien. Remarque : Vous devrez d’abord vous connecter à l’application {brandName}.\n{joinUri}\n\nLa participation par appel téléphonique n’est pas disponible pour cette réunion.\n\n{e2EESupportLinkText}\n{rcvE2EESupportUrl}", + e2EESupportLinkText: "Obtenez plus de renseignements sur le chiffrement de bout en bout de {brandName}.", rcvInviteMeetingContentDial: "\n\nParticiper à la réunion en un clic sur votre téléphone intelligent (son seulement) :\n {smartphones}\n\nOu composer le :\n Numéro à composer : {dialNumber}\n Code d’accès/code de réunion : {pinNumber} ", rcvInviteMeetingContentCountryDial: "\n\nParticiper à la réunion en un clic sur votre téléphone intelligent (son seulement) :\n {smartphones}\n\nOu composer le :\n {dialNumber}\n Code d’accès/code de réunion : {pinNumber} ", rcvTeleconference: "\n\nNuméros internationaux disponibles : {teleconference} ", @@ -16,7 +19,10 @@ export default { // @key: @#@"inviteMeetingContent"@#@ @source: @#@"{accountName} is inviting you to a {brandName} meeting.\n\nJoin from PC, Mac, iOS or Android: {joinUri}{passwordTpl}\n\nOr iPhone one-tap:\n {mobileDialingNumberTpl}\n\nOr Telephone:\n Dial: {phoneDialingNumberTpl}\n Meeting ID: {meetingId}\n International numbers available: {teleconference} "@#@ // @key: @#@"rcvInviteMeetingContent"@#@ @source: @#@"{accountName} has invited you to a {brandName} Meeting.\n\nPlease join using this link:\n {joinUri}{passwordTpl}"@#@ +// @key: @#@"rcvTelusInviteMeetingContent"@#@ @source: @#@"{accountName} has invited you to a TELUS Business Connect Meeting.\n\nPlease join using this link:\n {joinUri}{passwordTpl}"@#@ // @key: @#@"rcvRCBrandInviteMeetingContent"@#@ @source: @#@"{accountName} has invited you to a {productName} meeting.\n\nPlease join using this link:\n {joinUri}{passwordTpl}"@#@ +// @key: @#@"rcvE2EEInviteMeetingContent"@#@ @source: @#@"{accountName} has invited you to an end-to-end encrypted {rcvProductName} meeting.\n\nPlease join using this link. Note, you'll need to log in to the {brandName} app first:\n{joinUri}\n\nDial-in is not available for this meeting.\n\n{e2EESupportLinkText}\n{rcvE2EESupportUrl}"@#@ +// @key: @#@"e2EESupportLinkText"@#@ @source: @#@"Find out more about {brandName}'s end-to-end encryption."@#@ // @key: @#@"rcvInviteMeetingContentDial"@#@ @source: @#@"\n\nOne tap to join audio only from a smartphone:\n {smartphones}\n\nOr dial:\n Dial: {dialNumber}\n Access Code / Meeting ID: {pinNumber} "@#@ // @key: @#@"rcvInviteMeetingContentCountryDial"@#@ @source: @#@"\n\nOne tap to join audio only from a smartphone:\n {smartphones}\n\nOr dial:\n {dialNumber}\n Access Code / Meeting ID: {pinNumber} "@#@ // @key: @#@"rcvTeleconference"@#@ @source: @#@"\n\nInternational numbers available: {teleconference} "@#@ diff --git a/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/fr-FR.js b/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/fr-FR.js index 1c0875b0ed..b9ee8d4cf4 100644 --- a/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/fr-FR.js +++ b/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/fr-FR.js @@ -1,7 +1,10 @@ export default { inviteMeetingContent: "{accountName} vous invite à une réunion {brandName}.\n\nRejoindre à partir d’un PC, d’un Mac, d’iOS ou d’Android : {joinUri}{passwordTpl}\n\nOu avec une pression sur iPhone :\n {mobileDialingNumberTpl}\n\nOu par téléphone :\n Composer : {phoneDialingNumberTpl}\n ID de réunion : {meetingId}\n Numéros internationaux disponibles : {teleconference} ", rcvInviteMeetingContent: "{accountName} vous a invité à une réunion {brandName}.\n\nVeuillez rejoindre la réunion à l’aide de ce lien :\n {joinUri}{passwordTpl}", + rcvTelusInviteMeetingContent: "{accountName} vous a invité à une réunion Connexion Affaires de TELUS.\n\nVeuillez rejoindre la réunion à l’aide de ce lien :\n {joinUri}{passwordTpl}", rcvRCBrandInviteMeetingContent: "{accountName} vous a invité à une réunion {productName}.\n\nVeuillez rejoindre la réunion à l’aide de ce lien :\n {joinUri}{passwordTpl}", + rcvE2EEInviteMeetingContent: "{accountName} Vous a invité à une réunion {rcvProductName} chiffrée de bout en bout.\n\nVeuillez rejoindre la réunion à l’aide de ce lien. Vous devrez tout d’abord vous connecter à l’application {brandName} :\n{joinUri}\n\nLa composition n’est pas disponible pour cette réunion.\n\n{e2EESupportLinkText}\n{rcvE2EESupportUrl}", + e2EESupportLinkText: "En savoir plus sur le chiffrement de bout en bout de {brandName}.", rcvInviteMeetingContentDial: "\n\nAppuyer une seule fois pour rejoindre l’audio uniquement à partir d’un smartphone :\n {smartphones}\n\nOu composer :\n Composer : {dialNumber}\n Code d’accès/ID de réunion : {pinNumber} ", rcvInviteMeetingContentCountryDial: "\n\nAppuyer une seule fois pour rejoindre l’audio uniquement à partir d’un smartphone :\n {smartphones}\n\nOu composer :\n {dialNumber}\n Code d’accès/ID de réunion : {pinNumber} ", rcvTeleconference: "\n\nNuméros internationaux disponibles : {teleconference} ", @@ -16,7 +19,10 @@ export default { // @key: @#@"inviteMeetingContent"@#@ @source: @#@"{accountName} is inviting you to a {brandName} meeting.\n\nJoin from PC, Mac, iOS or Android: {joinUri}{passwordTpl}\n\nOr iPhone one-tap:\n {mobileDialingNumberTpl}\n\nOr Telephone:\n Dial: {phoneDialingNumberTpl}\n Meeting ID: {meetingId}\n International numbers available: {teleconference} "@#@ // @key: @#@"rcvInviteMeetingContent"@#@ @source: @#@"{accountName} has invited you to a {brandName} Meeting.\n\nPlease join using this link:\n {joinUri}{passwordTpl}"@#@ +// @key: @#@"rcvTelusInviteMeetingContent"@#@ @source: @#@"{accountName} has invited you to a TELUS Business Connect Meeting.\n\nPlease join using this link:\n {joinUri}{passwordTpl}"@#@ // @key: @#@"rcvRCBrandInviteMeetingContent"@#@ @source: @#@"{accountName} has invited you to a {productName} meeting.\n\nPlease join using this link:\n {joinUri}{passwordTpl}"@#@ +// @key: @#@"rcvE2EEInviteMeetingContent"@#@ @source: @#@"{accountName} has invited you to an end-to-end encrypted {rcvProductName} meeting.\n\nPlease join using this link. Note, you'll need to log in to the {brandName} app first:\n{joinUri}\n\nDial-in is not available for this meeting.\n\n{e2EESupportLinkText}\n{rcvE2EESupportUrl}"@#@ +// @key: @#@"e2EESupportLinkText"@#@ @source: @#@"Find out more about {brandName}'s end-to-end encryption."@#@ // @key: @#@"rcvInviteMeetingContentDial"@#@ @source: @#@"\n\nOne tap to join audio only from a smartphone:\n {smartphones}\n\nOr dial:\n Dial: {dialNumber}\n Access Code / Meeting ID: {pinNumber} "@#@ // @key: @#@"rcvInviteMeetingContentCountryDial"@#@ @source: @#@"\n\nOne tap to join audio only from a smartphone:\n {smartphones}\n\nOr dial:\n {dialNumber}\n Access Code / Meeting ID: {pinNumber} "@#@ // @key: @#@"rcvTeleconference"@#@ @source: @#@"\n\nInternational numbers available: {teleconference} "@#@ diff --git a/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/it-IT.js b/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/it-IT.js index 1dd4043d2e..4bd22ae555 100644 --- a/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/it-IT.js +++ b/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/it-IT.js @@ -1,7 +1,10 @@ export default { inviteMeetingContent: "{accountName} ti sta invitando a una riunione {brandName}.\n\nPartecipa da PC, Mac, iOS o Android: {joinUri}{passwordTpl}\n\nOppure da iPhone con un tocco:\n {mobileDialingNumberTpl}\n\nO via telefono:\n Componi: {phoneDialingNumberTpl}\n ID riunione: {meetingId}\n Numeri internazionali disponibili: {teleconference} ", rcvInviteMeetingContent: "{accountName} ti ha invitato a una riunione {brandName}.\n\nAccedi con questo collegamento:\n {joinUri}{passwordTpl}", + rcvTelusInviteMeetingContent: "{accountName} ti ha invitato a una riunione TELUS Business Connect.\n\nAccedi con questo link:\n {joinUri}{passwordTpl}", rcvRCBrandInviteMeetingContent: "{accountName} ti ha invitato a una riunione {productName}.\n\nAccedi con questo collegamento:\n {joinUri}{passwordTpl}", + rcvE2EEInviteMeetingContent: "{accountName} ti ha invitato a una riunione {rcvProductName} con crittografia end-to-end.\n\nAccedi con questo link. Tieni presente che prima è necessario accedere all'app {brandName}:\n{joinUri}\n\nPer questa riunione non è possibile collegarsi alla chiamata.\n\n{e2EESupportLinkText}\n{rcvE2EESupportUrl}", + e2EESupportLinkText: "Scopri di più sulla crittografia end-to-end di {brandName}.", rcvInviteMeetingContentDial: "\n\nAccedi con un tocco da smartphone per partecipare solo in modalità audio:\n {smartphones}\n\nO componi:\n Componi: {dialNumber}\n Codice di accesso / ID riunione: {pinNumber} ", rcvInviteMeetingContentCountryDial: "\n\nAccedi con un tocco da smartphone per partecipare solo in modalità audio:\n {smartphones}\n\nO componi:\n {dialNumber}\n Codice di accesso / ID riunione: {pinNumber} ", rcvTeleconference: "\n\nNumeri internazionali disponibili: {teleconference} ", @@ -16,7 +19,10 @@ export default { // @key: @#@"inviteMeetingContent"@#@ @source: @#@"{accountName} is inviting you to a {brandName} meeting.\n\nJoin from PC, Mac, iOS or Android: {joinUri}{passwordTpl}\n\nOr iPhone one-tap:\n {mobileDialingNumberTpl}\n\nOr Telephone:\n Dial: {phoneDialingNumberTpl}\n Meeting ID: {meetingId}\n International numbers available: {teleconference} "@#@ // @key: @#@"rcvInviteMeetingContent"@#@ @source: @#@"{accountName} has invited you to a {brandName} Meeting.\n\nPlease join using this link:\n {joinUri}{passwordTpl}"@#@ +// @key: @#@"rcvTelusInviteMeetingContent"@#@ @source: @#@"{accountName} has invited you to a TELUS Business Connect Meeting.\n\nPlease join using this link:\n {joinUri}{passwordTpl}"@#@ // @key: @#@"rcvRCBrandInviteMeetingContent"@#@ @source: @#@"{accountName} has invited you to a {productName} meeting.\n\nPlease join using this link:\n {joinUri}{passwordTpl}"@#@ +// @key: @#@"rcvE2EEInviteMeetingContent"@#@ @source: @#@"{accountName} has invited you to an end-to-end encrypted {rcvProductName} meeting.\n\nPlease join using this link. Note, you'll need to log in to the {brandName} app first:\n{joinUri}\n\nDial-in is not available for this meeting.\n\n{e2EESupportLinkText}\n{rcvE2EESupportUrl}"@#@ +// @key: @#@"e2EESupportLinkText"@#@ @source: @#@"Find out more about {brandName}'s end-to-end encryption."@#@ // @key: @#@"rcvInviteMeetingContentDial"@#@ @source: @#@"\n\nOne tap to join audio only from a smartphone:\n {smartphones}\n\nOr dial:\n Dial: {dialNumber}\n Access Code / Meeting ID: {pinNumber} "@#@ // @key: @#@"rcvInviteMeetingContentCountryDial"@#@ @source: @#@"\n\nOne tap to join audio only from a smartphone:\n {smartphones}\n\nOr dial:\n {dialNumber}\n Access Code / Meeting ID: {pinNumber} "@#@ // @key: @#@"rcvTeleconference"@#@ @source: @#@"\n\nInternational numbers available: {teleconference} "@#@ diff --git a/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/ja-JP.js b/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/ja-JP.js index d4a847378b..beb9943cf9 100644 --- a/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/ja-JP.js +++ b/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/ja-JP.js @@ -1,7 +1,10 @@ export default { inviteMeetingContent: "{accountName}さんから{brandName}会議に招待されています。\n\nPC、Mac、iOS、Androidのいずれかから参加してください。{joinUri}{passwordTpl}\n\nまたは1回のタップでiPhoneから参加できます。\n {mobileDialingNumberTpl}\n\nあるいは電話で参加することもできます。\n ダイヤル:{phoneDialingNumberTpl}\n 会議ID:{meetingId}\n 国際電話番号もご利用になれます。{teleconference} ", rcvInviteMeetingContent: "{accountName}さんから{brandName}会議に招待されました。\n\nこちらのリンクを使用して参加してください。\n {joinUri}{passwordTpl}", + rcvTelusInviteMeetingContent: "{accountName}があなたをTELUS Business Connect Meetingに招待しています。\n\nこちらのリンクを使用して参加してください。\n {joinUri}{passwordTpl}", rcvRCBrandInviteMeetingContent: "{accountName}さんから{productName}会議に招待されました。\n\nこちらのリンクを使用して参加してください。\n {joinUri}{passwordTpl}", + rcvE2EEInviteMeetingContent: "{accountName}はあなたをエンドツーエンドで暗号化された{rcvProductName}会議に招待しました。\n\nこのリンクを使用して参加してください。最初に{brandName}アプリにログインする必要があることにご注意ください。\n{joinUri}\n\nダイヤルインはこの会議で使用できません。\n\n{e2EESupportLinkText}\n{rcvE2EESupportUrl}", + e2EESupportLinkText: "{brandName}のエンドツーエンド暗号化の詳細を参照してください。", rcvInviteMeetingContentDial: "\n\n1回のタップでスマートフォンから音声のみで参加できます。\n {smartphones}\n\nまたはダイヤルできます。\n ダイヤル:{dialNumber}\n アクセスコード/会議ID:{pinNumber} ", rcvInviteMeetingContentCountryDial: "\n\n1回のタップでスマートフォンから音声のみで参加できます。\n {smartphones}\n\nまたはダイヤルできます。\n {dialNumber}\n アクセスコード/会議ID:{pinNumber} ", rcvTeleconference: "\n\n利用可能な国際電話番号: {teleconference} ", @@ -16,7 +19,10 @@ export default { // @key: @#@"inviteMeetingContent"@#@ @source: @#@"{accountName} is inviting you to a {brandName} meeting.\n\nJoin from PC, Mac, iOS or Android: {joinUri}{passwordTpl}\n\nOr iPhone one-tap:\n {mobileDialingNumberTpl}\n\nOr Telephone:\n Dial: {phoneDialingNumberTpl}\n Meeting ID: {meetingId}\n International numbers available: {teleconference} "@#@ // @key: @#@"rcvInviteMeetingContent"@#@ @source: @#@"{accountName} has invited you to a {brandName} Meeting.\n\nPlease join using this link:\n {joinUri}{passwordTpl}"@#@ +// @key: @#@"rcvTelusInviteMeetingContent"@#@ @source: @#@"{accountName} has invited you to a TELUS Business Connect Meeting.\n\nPlease join using this link:\n {joinUri}{passwordTpl}"@#@ // @key: @#@"rcvRCBrandInviteMeetingContent"@#@ @source: @#@"{accountName} has invited you to a {productName} meeting.\n\nPlease join using this link:\n {joinUri}{passwordTpl}"@#@ +// @key: @#@"rcvE2EEInviteMeetingContent"@#@ @source: @#@"{accountName} has invited you to an end-to-end encrypted {rcvProductName} meeting.\n\nPlease join using this link. Note, you'll need to log in to the {brandName} app first:\n{joinUri}\n\nDial-in is not available for this meeting.\n\n{e2EESupportLinkText}\n{rcvE2EESupportUrl}"@#@ +// @key: @#@"e2EESupportLinkText"@#@ @source: @#@"Find out more about {brandName}'s end-to-end encryption."@#@ // @key: @#@"rcvInviteMeetingContentDial"@#@ @source: @#@"\n\nOne tap to join audio only from a smartphone:\n {smartphones}\n\nOr dial:\n Dial: {dialNumber}\n Access Code / Meeting ID: {pinNumber} "@#@ // @key: @#@"rcvInviteMeetingContentCountryDial"@#@ @source: @#@"\n\nOne tap to join audio only from a smartphone:\n {smartphones}\n\nOr dial:\n {dialNumber}\n Access Code / Meeting ID: {pinNumber} "@#@ // @key: @#@"rcvTeleconference"@#@ @source: @#@"\n\nInternational numbers available: {teleconference} "@#@ diff --git a/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/ko-KR.js b/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/ko-KR.js index 0258a62315..bed31f46fe 100644 --- a/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/ko-KR.js +++ b/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/ko-KR.js @@ -1,7 +1,10 @@ export default { inviteMeetingContent: "{accountName} 님이 {brandName} 모임에 초대했습니다.\n\nPC 또는 Mac, iOS, Android에서 참가: {joinUri}{passwordTpl}\n\n또는 iPhone 한 번 탭하여 참가:\n {mobileDialingNumberTpl}\n\n또는 전화기:\n 전화 걸기: {phoneDialingNumberTpl}\n 모임 ID {meetingId}\n 이용 가능한 국제 번호: {teleconference} ", rcvInviteMeetingContent: "{accountName} 님이 {brandName} 모임에 초대했습니다.\n\n다음 링크로 참가하세요.\n {joinUri}{passwordTpl}", + rcvTelusInviteMeetingContent: "{accountName} 님이 TELUS Business Connect 모임에 초대했습니다.\n\n다음 링크로 참가하세요.\n {joinUri}{passwordTpl}", rcvRCBrandInviteMeetingContent: "{accountName} 님이 {productName} 모임에 초대했습니다.\n\n다음 링크로 참가하세요.\n {joinUri}{passwordTpl}", + rcvE2EEInviteMeetingContent: "{accountName}님이 E2EE {rcvProductName} 모임에 초대했습니다.\n\n다음 링크로 참가하세요. 참고로 {brandName} 앱에 먼저 로그인해야 합니다.\n{joinUri}\n\n이 모임에는 전화 걸기 기능이 지원되지 않습니다.\n\n{e2EESupportLinkText}\n{rcvE2EESupportUrl}", + e2EESupportLinkText: "{brandName}의 E2EE에 대해 자세히 알아보십시오.", rcvInviteMeetingContentDial: "\n\n스마트폰에서 오디오로만 참가하려면 다음에서 한 번 탭하세요.\n {smartphones}\n\n또는 전화 걸기:\n 전화 걸기: {dialNumber}\n 액세스 코드 / 모임 ID: {pinNumber} ", rcvInviteMeetingContentCountryDial: "\n\n스마트폰에서 오디오로만 참가하려면 다음에서 한 번 탭하세요.\n {smartphones}\n\n또는 전화 걸기:\n {dialNumber}\n 액세스 코드 / 모임 ID: {pinNumber} ", rcvTeleconference: "\n\n사용 가능한 국제 번호: {teleconference} ", @@ -16,7 +19,10 @@ export default { // @key: @#@"inviteMeetingContent"@#@ @source: @#@"{accountName} is inviting you to a {brandName} meeting.\n\nJoin from PC, Mac, iOS or Android: {joinUri}{passwordTpl}\n\nOr iPhone one-tap:\n {mobileDialingNumberTpl}\n\nOr Telephone:\n Dial: {phoneDialingNumberTpl}\n Meeting ID: {meetingId}\n International numbers available: {teleconference} "@#@ // @key: @#@"rcvInviteMeetingContent"@#@ @source: @#@"{accountName} has invited you to a {brandName} Meeting.\n\nPlease join using this link:\n {joinUri}{passwordTpl}"@#@ +// @key: @#@"rcvTelusInviteMeetingContent"@#@ @source: @#@"{accountName} has invited you to a TELUS Business Connect Meeting.\n\nPlease join using this link:\n {joinUri}{passwordTpl}"@#@ // @key: @#@"rcvRCBrandInviteMeetingContent"@#@ @source: @#@"{accountName} has invited you to a {productName} meeting.\n\nPlease join using this link:\n {joinUri}{passwordTpl}"@#@ +// @key: @#@"rcvE2EEInviteMeetingContent"@#@ @source: @#@"{accountName} has invited you to an end-to-end encrypted {rcvProductName} meeting.\n\nPlease join using this link. Note, you'll need to log in to the {brandName} app first:\n{joinUri}\n\nDial-in is not available for this meeting.\n\n{e2EESupportLinkText}\n{rcvE2EESupportUrl}"@#@ +// @key: @#@"e2EESupportLinkText"@#@ @source: @#@"Find out more about {brandName}'s end-to-end encryption."@#@ // @key: @#@"rcvInviteMeetingContentDial"@#@ @source: @#@"\n\nOne tap to join audio only from a smartphone:\n {smartphones}\n\nOr dial:\n Dial: {dialNumber}\n Access Code / Meeting ID: {pinNumber} "@#@ // @key: @#@"rcvInviteMeetingContentCountryDial"@#@ @source: @#@"\n\nOne tap to join audio only from a smartphone:\n {smartphones}\n\nOr dial:\n {dialNumber}\n Access Code / Meeting ID: {pinNumber} "@#@ // @key: @#@"rcvTeleconference"@#@ @source: @#@"\n\nInternational numbers available: {teleconference} "@#@ diff --git a/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/nl-NL.js b/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/nl-NL.js index 6b89ceb57a..168c4df634 100644 --- a/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/nl-NL.js +++ b/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/nl-NL.js @@ -1,7 +1,10 @@ export default { inviteMeetingContent: "{accountName} nodigt u uit voor een {brandName}-meeting.\n\nNeem deel via uw pc, Mac, iOS of Android. {joinUri}{passwordTpl}\n\nOf iPhone one-tap:\n {mobileDialingNumberTpl}\n\nOf telefonisch:\n Kies: {phoneDialingNumberTpl}\n Meeting-ID: {meetingId}\n Beschikbare internationale nummers: {teleconference} ", rcvInviteMeetingContent: "{accountName} heeft u uitgenodigd voor een {brandName} Meeting.\n\nNeem deel via deze koppeling:\n {joinUri}{passwordTpl}", + rcvTelusInviteMeetingContent: "{accountName} heeft u uitgenodigd voor een TELUS Business Connect Meeting.\n\nNeem deel via deze koppeling:\n {joinUri}{passwordTpl}", rcvRCBrandInviteMeetingContent: "{accountName} heeft u uitgenodigd voor een {productName}-meeting.\n\nNeem deel via deze koppeling:\n {joinUri}{passwordTpl}", + rcvE2EEInviteMeetingContent: "{accountName} heeft u uitgenodigd voor een end-to-end-versleutelde {rcvProductName}-meeting.\n\nNeem deel via deze link. Let op: u moet u eerst aanmelden bij de {brandName}-app:\n{joinUri}\n\nInbellen is niet mogelijk voor deze meeting.\n\n{e2EESupportLinkText}\n{rcvE2EESupportUrl}", + e2EESupportLinkText: "Meer informatie over de end-to-end-versleuteling van {brandName}.", rcvInviteMeetingContentDial: "\n\nTik één keer om deel te nemen met alleen audio vanaf een smartphone:\n {smartphones}\n\nOf kies:\n Kies: {dialNumber}\n Toegangscode/meeting-ID: {pinNumber} ", rcvInviteMeetingContentCountryDial: "\n\nTik één keer om deel te nemen met alleen audio vanaf een smartphone:\n {smartphones}\n\nOf kies:\n {dialNumber}\n Toegangscode/meeting-ID: {pinNumber} ", rcvTeleconference: "\n\nInternationale nummers beschikbaar: {teleconference} ", @@ -16,7 +19,10 @@ export default { // @key: @#@"inviteMeetingContent"@#@ @source: @#@"{accountName} is inviting you to a {brandName} meeting.\n\nJoin from PC, Mac, iOS or Android: {joinUri}{passwordTpl}\n\nOr iPhone one-tap:\n {mobileDialingNumberTpl}\n\nOr Telephone:\n Dial: {phoneDialingNumberTpl}\n Meeting ID: {meetingId}\n International numbers available: {teleconference} "@#@ // @key: @#@"rcvInviteMeetingContent"@#@ @source: @#@"{accountName} has invited you to a {brandName} Meeting.\n\nPlease join using this link:\n {joinUri}{passwordTpl}"@#@ +// @key: @#@"rcvTelusInviteMeetingContent"@#@ @source: @#@"{accountName} has invited you to a TELUS Business Connect Meeting.\n\nPlease join using this link:\n {joinUri}{passwordTpl}"@#@ // @key: @#@"rcvRCBrandInviteMeetingContent"@#@ @source: @#@"{accountName} has invited you to a {productName} meeting.\n\nPlease join using this link:\n {joinUri}{passwordTpl}"@#@ +// @key: @#@"rcvE2EEInviteMeetingContent"@#@ @source: @#@"{accountName} has invited you to an end-to-end encrypted {rcvProductName} meeting.\n\nPlease join using this link. Note, you'll need to log in to the {brandName} app first:\n{joinUri}\n\nDial-in is not available for this meeting.\n\n{e2EESupportLinkText}\n{rcvE2EESupportUrl}"@#@ +// @key: @#@"e2EESupportLinkText"@#@ @source: @#@"Find out more about {brandName}'s end-to-end encryption."@#@ // @key: @#@"rcvInviteMeetingContentDial"@#@ @source: @#@"\n\nOne tap to join audio only from a smartphone:\n {smartphones}\n\nOr dial:\n Dial: {dialNumber}\n Access Code / Meeting ID: {pinNumber} "@#@ // @key: @#@"rcvInviteMeetingContentCountryDial"@#@ @source: @#@"\n\nOne tap to join audio only from a smartphone:\n {smartphones}\n\nOr dial:\n {dialNumber}\n Access Code / Meeting ID: {pinNumber} "@#@ // @key: @#@"rcvTeleconference"@#@ @source: @#@"\n\nInternational numbers available: {teleconference} "@#@ diff --git a/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/pt-BR.js b/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/pt-BR.js index 536f6e4a53..37497165b3 100644 --- a/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/pt-BR.js +++ b/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/pt-BR.js @@ -1,7 +1,10 @@ export default { inviteMeetingContent: "{accountName} está convidando você para uma reunião do {brandName}.\n\nEntrar do PC, Mac, iOS ou Android: {joinUri}{passwordTpl}\n\nOu um toque de iPhone:\n {mobileDialingNumberTpl}\n\nOu telefone:\n Discar: {phoneDialingNumberTpl}\n ID da reunião: {meetingId}\n Números internacionais disponíveis: {teleconference} ", rcvInviteMeetingContent: "{accountName} convidou você para uma reunião do {brandName}.\n\nEntre usando este link:\n {joinUri}{passwordTpl}", + rcvTelusInviteMeetingContent: "{accountName} convidou você para uma reunião do TELUS Business Connect Meeting.\n\nEntre usando este link:\n {joinUri}{passwordTpl}", rcvRCBrandInviteMeetingContent: "{accountName} convidou você para uma reunião do {productName}.\n\nEntre usando este link:\n {joinUri}{passwordTpl}", + rcvE2EEInviteMeetingContent: "{accountName} convidou você para uma reunião do {rcvProductName} criptografada de ponta a ponta.\n\nEntre usando este link. Antes, você precisará fazer login no aplicativo {brandName}:\n{joinUri}\n\nA discagem não está disponível para esta reunião.\n\n{e2EESupportLinkText}\n{rcvE2EESupportUrl}", + e2EESupportLinkText: "Saiba mais sobre a criptografia de ponta a ponta do {brandName}.", rcvInviteMeetingContentDial: "\n\nUm toque para entrar apenas com áudio por um smartphone:\n {smartphones}\n\nOu disque para:\n Discar: {dialNumber}\n Código de acesso/ID da reunião: {pinNumber} ", rcvInviteMeetingContentCountryDial: "\n\nUm toque para entrar apenas com áudio por um smartphone:\n {smartphones}\n\nOu disque para:\n {dialNumber}\n Código de acesso/ID da reunião: {pinNumber} ", rcvTeleconference: "\n\nNúmeros internacionais disponíveis: {teleconference} ", @@ -16,7 +19,10 @@ export default { // @key: @#@"inviteMeetingContent"@#@ @source: @#@"{accountName} is inviting you to a {brandName} meeting.\n\nJoin from PC, Mac, iOS or Android: {joinUri}{passwordTpl}\n\nOr iPhone one-tap:\n {mobileDialingNumberTpl}\n\nOr Telephone:\n Dial: {phoneDialingNumberTpl}\n Meeting ID: {meetingId}\n International numbers available: {teleconference} "@#@ // @key: @#@"rcvInviteMeetingContent"@#@ @source: @#@"{accountName} has invited you to a {brandName} Meeting.\n\nPlease join using this link:\n {joinUri}{passwordTpl}"@#@ +// @key: @#@"rcvTelusInviteMeetingContent"@#@ @source: @#@"{accountName} has invited you to a TELUS Business Connect Meeting.\n\nPlease join using this link:\n {joinUri}{passwordTpl}"@#@ // @key: @#@"rcvRCBrandInviteMeetingContent"@#@ @source: @#@"{accountName} has invited you to a {productName} meeting.\n\nPlease join using this link:\n {joinUri}{passwordTpl}"@#@ +// @key: @#@"rcvE2EEInviteMeetingContent"@#@ @source: @#@"{accountName} has invited you to an end-to-end encrypted {rcvProductName} meeting.\n\nPlease join using this link. Note, you'll need to log in to the {brandName} app first:\n{joinUri}\n\nDial-in is not available for this meeting.\n\n{e2EESupportLinkText}\n{rcvE2EESupportUrl}"@#@ +// @key: @#@"e2EESupportLinkText"@#@ @source: @#@"Find out more about {brandName}'s end-to-end encryption."@#@ // @key: @#@"rcvInviteMeetingContentDial"@#@ @source: @#@"\n\nOne tap to join audio only from a smartphone:\n {smartphones}\n\nOr dial:\n Dial: {dialNumber}\n Access Code / Meeting ID: {pinNumber} "@#@ // @key: @#@"rcvInviteMeetingContentCountryDial"@#@ @source: @#@"\n\nOne tap to join audio only from a smartphone:\n {smartphones}\n\nOr dial:\n {dialNumber}\n Access Code / Meeting ID: {pinNumber} "@#@ // @key: @#@"rcvTeleconference"@#@ @source: @#@"\n\nInternational numbers available: {teleconference} "@#@ diff --git a/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/pt-PT.js b/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/pt-PT.js index a52ac8da1f..7065bab125 100644 --- a/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/pt-PT.js +++ b/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/pt-PT.js @@ -1,7 +1,10 @@ export default { inviteMeetingContent: "{accountName} enviou-lhe um convite para uma reunião do {brandName}.\n\nEntre através de PC, Mac, iOS ou Android: {joinUri}{passwordTpl}\n\nOu iPhone one-tap:\n {mobileDialingNumberTpl}\n\nOu telefone:\n Marque: {phoneDialingNumberTpl}\n ID da reunião: {meetingId}\n Números internacionais disponíveis: {teleconference} ", rcvInviteMeetingContent: "{accountName} enviou-lhe um convite para uma reunião do {brandName}.\n\nEntre através desta hiperligação:\n {joinUri}{passwordTpl}", + rcvTelusInviteMeetingContent: "{accountName} enviou-lhe um convite para uma reunião do TELUS Business Connect.\n\nEntre através desta hiperligação:\n {joinUri}{passwordTpl}", rcvRCBrandInviteMeetingContent: "{accountName} enviou-lhe um convite para uma reunião do {productName}.\n\nEntre através desta hiperligação:\n {joinUri}{passwordTpl}", + rcvE2EEInviteMeetingContent: "Recebeu um convite de {accountName} para uma reunião do {rcvProductName} encriptada ponto a ponto.\n\nEntre através desta ligação. Tenha em atenção que terá de iniciar sessão na aplicação {brandName} primeiro:\n{joinUri}\n\nA marcação não está disponível para esta reunião.\n\n{e2EESupportLinkText}\n{rcvE2EESupportUrl}", + e2EESupportLinkText: "Saiba mais acerca da encriptação ponto a ponto da {brandName}.", rcvInviteMeetingContentDial: "\n\nUm toque para entrar apenas com áudio a partir de um smartphone:\n {smartphones}\n\nOu marque:\n Marque: {dialNumber}\n Código de acesso/ID da reunião: {pinNumber} ", rcvInviteMeetingContentCountryDial: "\n\nUm toque para entrar apenas com áudio a partir de um smartphone:\n {smartphones}\n\nOu marque:\n {dialNumber}\n Código de acesso/ID da reunião: {pinNumber} ", rcvTeleconference: "\n\nNúmeros internacionais disponíveis: {teleconference} ", @@ -16,7 +19,10 @@ export default { // @key: @#@"inviteMeetingContent"@#@ @source: @#@"{accountName} is inviting you to a {brandName} meeting.\n\nJoin from PC, Mac, iOS or Android: {joinUri}{passwordTpl}\n\nOr iPhone one-tap:\n {mobileDialingNumberTpl}\n\nOr Telephone:\n Dial: {phoneDialingNumberTpl}\n Meeting ID: {meetingId}\n International numbers available: {teleconference} "@#@ // @key: @#@"rcvInviteMeetingContent"@#@ @source: @#@"{accountName} has invited you to a {brandName} Meeting.\n\nPlease join using this link:\n {joinUri}{passwordTpl}"@#@ +// @key: @#@"rcvTelusInviteMeetingContent"@#@ @source: @#@"{accountName} has invited you to a TELUS Business Connect Meeting.\n\nPlease join using this link:\n {joinUri}{passwordTpl}"@#@ // @key: @#@"rcvRCBrandInviteMeetingContent"@#@ @source: @#@"{accountName} has invited you to a {productName} meeting.\n\nPlease join using this link:\n {joinUri}{passwordTpl}"@#@ +// @key: @#@"rcvE2EEInviteMeetingContent"@#@ @source: @#@"{accountName} has invited you to an end-to-end encrypted {rcvProductName} meeting.\n\nPlease join using this link. Note, you'll need to log in to the {brandName} app first:\n{joinUri}\n\nDial-in is not available for this meeting.\n\n{e2EESupportLinkText}\n{rcvE2EESupportUrl}"@#@ +// @key: @#@"e2EESupportLinkText"@#@ @source: @#@"Find out more about {brandName}'s end-to-end encryption."@#@ // @key: @#@"rcvInviteMeetingContentDial"@#@ @source: @#@"\n\nOne tap to join audio only from a smartphone:\n {smartphones}\n\nOr dial:\n Dial: {dialNumber}\n Access Code / Meeting ID: {pinNumber} "@#@ // @key: @#@"rcvInviteMeetingContentCountryDial"@#@ @source: @#@"\n\nOne tap to join audio only from a smartphone:\n {smartphones}\n\nOr dial:\n {dialNumber}\n Access Code / Meeting ID: {pinNumber} "@#@ // @key: @#@"rcvTeleconference"@#@ @source: @#@"\n\nInternational numbers available: {teleconference} "@#@ diff --git a/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/zh-CN.js b/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/zh-CN.js index 61ca214742..baa2cf5d27 100644 --- a/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/zh-CN.js +++ b/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/zh-CN.js @@ -1,7 +1,10 @@ export default { inviteMeetingContent: "{accountName} 正在邀请您参加 {brandName} 会议。\n\n通过电脑、Mac、iOS 或 Android 设备加入:{joinUri}{passwordTpl}\n\n或通过 iPhone 一键加入:\n {mobileDialingNumberTpl}\n\n或通过电话加入:\n 拨打:{phoneDialingNumberTpl}\n 会议 ID:{meetingId}\n 可用的国际号码:{teleconference} ", rcvInviteMeetingContent: "{accountName} 已邀请您参加 {brandName} 会议。\n\n请使用以下链接加入:\n {joinUri}{passwordTpl}", + rcvTelusInviteMeetingContent: "{accountName} 已邀请您参加 TELUS Business Connect 会议。\n\n请使用以下链接加入:\n {joinUri}{passwordTpl}", rcvRCBrandInviteMeetingContent: "{accountName} 已邀请您参加 {productName} 会议。\n\n请使用以下链接加入:\n {joinUri}{passwordTpl}", + rcvE2EEInviteMeetingContent: "{accountName}已邀请您参加{rcvProductName} 端到端加密会议。\n\n请使用此链接加入。请注意,您需要先登录{brandName}应用:\n{joinUri}\n\n此会议不支持使用拨入。\n\n{e2EESupportLinkText}\n{rcvE2EESupportUrl}", + e2EESupportLinkText: "详细了解 {brandName}的端到端加密。", rcvInviteMeetingContentDial: "\n\n在智能手机上一键加入纯音频会议:\n {smartphones}\n\n或拨打:\n 拨打:{dialNumber}\n 访问码/会议 ID:{pinNumber} ", rcvInviteMeetingContentCountryDial: "\n\n在智能手机上一键加入纯音频会议:\n {smartphones}\n\n或拨打:\n {dialNumber}\n 访问码/会议 ID:{pinNumber} ", rcvTeleconference: "\n\n可用的国际号码: {teleconference} ", @@ -16,7 +19,10 @@ export default { // @key: @#@"inviteMeetingContent"@#@ @source: @#@"{accountName} is inviting you to a {brandName} meeting.\n\nJoin from PC, Mac, iOS or Android: {joinUri}{passwordTpl}\n\nOr iPhone one-tap:\n {mobileDialingNumberTpl}\n\nOr Telephone:\n Dial: {phoneDialingNumberTpl}\n Meeting ID: {meetingId}\n International numbers available: {teleconference} "@#@ // @key: @#@"rcvInviteMeetingContent"@#@ @source: @#@"{accountName} has invited you to a {brandName} Meeting.\n\nPlease join using this link:\n {joinUri}{passwordTpl}"@#@ +// @key: @#@"rcvTelusInviteMeetingContent"@#@ @source: @#@"{accountName} has invited you to a TELUS Business Connect Meeting.\n\nPlease join using this link:\n {joinUri}{passwordTpl}"@#@ // @key: @#@"rcvRCBrandInviteMeetingContent"@#@ @source: @#@"{accountName} has invited you to a {productName} meeting.\n\nPlease join using this link:\n {joinUri}{passwordTpl}"@#@ +// @key: @#@"rcvE2EEInviteMeetingContent"@#@ @source: @#@"{accountName} has invited you to an end-to-end encrypted {rcvProductName} meeting.\n\nPlease join using this link. Note, you'll need to log in to the {brandName} app first:\n{joinUri}\n\nDial-in is not available for this meeting.\n\n{e2EESupportLinkText}\n{rcvE2EESupportUrl}"@#@ +// @key: @#@"e2EESupportLinkText"@#@ @source: @#@"Find out more about {brandName}'s end-to-end encryption."@#@ // @key: @#@"rcvInviteMeetingContentDial"@#@ @source: @#@"\n\nOne tap to join audio only from a smartphone:\n {smartphones}\n\nOr dial:\n Dial: {dialNumber}\n Access Code / Meeting ID: {pinNumber} "@#@ // @key: @#@"rcvInviteMeetingContentCountryDial"@#@ @source: @#@"\n\nOne tap to join audio only from a smartphone:\n {smartphones}\n\nOr dial:\n {dialNumber}\n Access Code / Meeting ID: {pinNumber} "@#@ // @key: @#@"rcvTeleconference"@#@ @source: @#@"\n\nInternational numbers available: {teleconference} "@#@ diff --git a/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/zh-HK.js b/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/zh-HK.js index 462b27cee6..c1561eb12c 100644 --- a/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/zh-HK.js +++ b/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/zh-HK.js @@ -1,7 +1,10 @@ export default { inviteMeetingContent: "{accountName} 正邀請您加入 {brandName} 會議。\n\n請從 PC、Mac、iOS 或 Android 加入:{joinUri}{passwordTpl}\n\n或在 iPhone 點一下加入:\n {mobileDialingNumberTpl}\n\n或透過電話加入:\n 請撥打:{phoneDialingNumberTpl}\n 會議 ID:{meetingId}\n 可用的國際號碼:{teleconference} ", rcvInviteMeetingContent: "{accountName} 已邀請您加入 {brandName} 會議。\n\n請使用此連結加入:\n {joinUri}{passwordTpl}", + rcvTelusInviteMeetingContent: "{accountName} 已邀請您加入 TELUS Business Connect 會議。\n\n請使用此連結加入:\n {joinUri}{passwordTpl}", rcvRCBrandInviteMeetingContent: "{accountName} 已邀請您加入 {productName} 會議。\n\n請使用此連結加入:\n {joinUri}{passwordTpl}", + rcvE2EEInviteMeetingContent: "{accountName} 邀請您加入端對端加密的 {rcvProductName} 會議。\n\n請使用此連結加入:注意,您需要先登入 {brandName} 應用程式:\n{joinUri}\n\n此會議無法使用撥入功能。\n\n{e2EESupportLinkText}\n{rcvE2EESupportUrl}", + e2EESupportLinkText: "瞭解更多關於 {brandName} 端對端加密。", rcvInviteMeetingContentDial: "\n\n點一下即可從智慧型手機加入僅限音訊的會議:\n {smartphones}\n\n或撥打:\n 請撥打:{dialNumber}\n 存取碼 / 會議 ID:{pinNumber} ", rcvInviteMeetingContentCountryDial: "\n\n點一下即可從智慧型手機加入僅限音訊的會議:\n {smartphones}\n\n或撥打:\n {dialNumber}\n 存取碼 / 會議 ID:{pinNumber} ", rcvTeleconference: "\n\n可用的國際號碼: {teleconference} ", @@ -16,7 +19,10 @@ export default { // @key: @#@"inviteMeetingContent"@#@ @source: @#@"{accountName} is inviting you to a {brandName} meeting.\n\nJoin from PC, Mac, iOS or Android: {joinUri}{passwordTpl}\n\nOr iPhone one-tap:\n {mobileDialingNumberTpl}\n\nOr Telephone:\n Dial: {phoneDialingNumberTpl}\n Meeting ID: {meetingId}\n International numbers available: {teleconference} "@#@ // @key: @#@"rcvInviteMeetingContent"@#@ @source: @#@"{accountName} has invited you to a {brandName} Meeting.\n\nPlease join using this link:\n {joinUri}{passwordTpl}"@#@ +// @key: @#@"rcvTelusInviteMeetingContent"@#@ @source: @#@"{accountName} has invited you to a TELUS Business Connect Meeting.\n\nPlease join using this link:\n {joinUri}{passwordTpl}"@#@ // @key: @#@"rcvRCBrandInviteMeetingContent"@#@ @source: @#@"{accountName} has invited you to a {productName} meeting.\n\nPlease join using this link:\n {joinUri}{passwordTpl}"@#@ +// @key: @#@"rcvE2EEInviteMeetingContent"@#@ @source: @#@"{accountName} has invited you to an end-to-end encrypted {rcvProductName} meeting.\n\nPlease join using this link. Note, you'll need to log in to the {brandName} app first:\n{joinUri}\n\nDial-in is not available for this meeting.\n\n{e2EESupportLinkText}\n{rcvE2EESupportUrl}"@#@ +// @key: @#@"e2EESupportLinkText"@#@ @source: @#@"Find out more about {brandName}'s end-to-end encryption."@#@ // @key: @#@"rcvInviteMeetingContentDial"@#@ @source: @#@"\n\nOne tap to join audio only from a smartphone:\n {smartphones}\n\nOr dial:\n Dial: {dialNumber}\n Access Code / Meeting ID: {pinNumber} "@#@ // @key: @#@"rcvInviteMeetingContentCountryDial"@#@ @source: @#@"\n\nOne tap to join audio only from a smartphone:\n {smartphones}\n\nOr dial:\n {dialNumber}\n Access Code / Meeting ID: {pinNumber} "@#@ // @key: @#@"rcvTeleconference"@#@ @source: @#@"\n\nInternational numbers available: {teleconference} "@#@ diff --git a/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/zh-TW.js b/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/zh-TW.js index 462b27cee6..c1561eb12c 100644 --- a/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/zh-TW.js +++ b/packages/ringcentral-widgets/lib/MeetingCalendarHelper/i18n/zh-TW.js @@ -1,7 +1,10 @@ export default { inviteMeetingContent: "{accountName} 正邀請您加入 {brandName} 會議。\n\n請從 PC、Mac、iOS 或 Android 加入:{joinUri}{passwordTpl}\n\n或在 iPhone 點一下加入:\n {mobileDialingNumberTpl}\n\n或透過電話加入:\n 請撥打:{phoneDialingNumberTpl}\n 會議 ID:{meetingId}\n 可用的國際號碼:{teleconference} ", rcvInviteMeetingContent: "{accountName} 已邀請您加入 {brandName} 會議。\n\n請使用此連結加入:\n {joinUri}{passwordTpl}", + rcvTelusInviteMeetingContent: "{accountName} 已邀請您加入 TELUS Business Connect 會議。\n\n請使用此連結加入:\n {joinUri}{passwordTpl}", rcvRCBrandInviteMeetingContent: "{accountName} 已邀請您加入 {productName} 會議。\n\n請使用此連結加入:\n {joinUri}{passwordTpl}", + rcvE2EEInviteMeetingContent: "{accountName} 邀請您加入端對端加密的 {rcvProductName} 會議。\n\n請使用此連結加入:注意,您需要先登入 {brandName} 應用程式:\n{joinUri}\n\n此會議無法使用撥入功能。\n\n{e2EESupportLinkText}\n{rcvE2EESupportUrl}", + e2EESupportLinkText: "瞭解更多關於 {brandName} 端對端加密。", rcvInviteMeetingContentDial: "\n\n點一下即可從智慧型手機加入僅限音訊的會議:\n {smartphones}\n\n或撥打:\n 請撥打:{dialNumber}\n 存取碼 / 會議 ID:{pinNumber} ", rcvInviteMeetingContentCountryDial: "\n\n點一下即可從智慧型手機加入僅限音訊的會議:\n {smartphones}\n\n或撥打:\n {dialNumber}\n 存取碼 / 會議 ID:{pinNumber} ", rcvTeleconference: "\n\n可用的國際號碼: {teleconference} ", @@ -16,7 +19,10 @@ export default { // @key: @#@"inviteMeetingContent"@#@ @source: @#@"{accountName} is inviting you to a {brandName} meeting.\n\nJoin from PC, Mac, iOS or Android: {joinUri}{passwordTpl}\n\nOr iPhone one-tap:\n {mobileDialingNumberTpl}\n\nOr Telephone:\n Dial: {phoneDialingNumberTpl}\n Meeting ID: {meetingId}\n International numbers available: {teleconference} "@#@ // @key: @#@"rcvInviteMeetingContent"@#@ @source: @#@"{accountName} has invited you to a {brandName} Meeting.\n\nPlease join using this link:\n {joinUri}{passwordTpl}"@#@ +// @key: @#@"rcvTelusInviteMeetingContent"@#@ @source: @#@"{accountName} has invited you to a TELUS Business Connect Meeting.\n\nPlease join using this link:\n {joinUri}{passwordTpl}"@#@ // @key: @#@"rcvRCBrandInviteMeetingContent"@#@ @source: @#@"{accountName} has invited you to a {productName} meeting.\n\nPlease join using this link:\n {joinUri}{passwordTpl}"@#@ +// @key: @#@"rcvE2EEInviteMeetingContent"@#@ @source: @#@"{accountName} has invited you to an end-to-end encrypted {rcvProductName} meeting.\n\nPlease join using this link. Note, you'll need to log in to the {brandName} app first:\n{joinUri}\n\nDial-in is not available for this meeting.\n\n{e2EESupportLinkText}\n{rcvE2EESupportUrl}"@#@ +// @key: @#@"e2EESupportLinkText"@#@ @source: @#@"Find out more about {brandName}'s end-to-end encryption."@#@ // @key: @#@"rcvInviteMeetingContentDial"@#@ @source: @#@"\n\nOne tap to join audio only from a smartphone:\n {smartphones}\n\nOr dial:\n Dial: {dialNumber}\n Access Code / Meeting ID: {pinNumber} "@#@ // @key: @#@"rcvInviteMeetingContentCountryDial"@#@ @source: @#@"\n\nOne tap to join audio only from a smartphone:\n {smartphones}\n\nOr dial:\n {dialNumber}\n Access Code / Meeting ID: {pinNumber} "@#@ // @key: @#@"rcvTeleconference"@#@ @source: @#@"\n\nInternational numbers available: {teleconference} "@#@ diff --git a/packages/ringcentral-widgets/lib/MeetingCalendarHelper/index.interface.ts b/packages/ringcentral-widgets/lib/MeetingCalendarHelper/index.interface.ts index f20c61fab4..4c82276b4a 100644 --- a/packages/ringcentral-widgets/lib/MeetingCalendarHelper/index.interface.ts +++ b/packages/ringcentral-widgets/lib/MeetingCalendarHelper/index.interface.ts @@ -11,7 +11,7 @@ interface RcmMeeting { topic: string; meetingType: MeetingTypeV; schedule?: { - startTime: Date; + startTime: Date | string; durationInMinutes: number; timeZone: { id: string; @@ -23,12 +23,13 @@ interface RcmMeeting { interface RcvMeeting { id: string; name: string; - startTime: Date; + startTime: Date | string; duration: number; joinUri: string; shortId: string; links: { joinUri: string }; isMeetingSecret: boolean; + e2ee: boolean; meetingPassword: string; meetingPasswordPSTN: string; } @@ -47,22 +48,25 @@ export interface CommonBrand { code: string; name: string; rcvProductName?: string; + rcvE2EESupportUrl?: string; brandConfig: { teleconference: string; }; + rcvTeleconference: string; } export interface RcmMainParams { meeting: RcmMeeting; serviceInfo: RcmServiceInfo; extensionInfo: CommonExtensionInfo; - invitationInfo: RcmInvitationInfo; + invitationInfo?: RcmInvitationInfo; } export interface RcvMainParams { meeting: RcvMeeting; extensionInfo: CommonExtensionInfo; dialInNumber: string | RcVDialInNumberObj[]; + hasRoomConnectorBeta: boolean; /** * provide this as the alternative invitation result, e.g. from rcv api */ @@ -77,8 +81,14 @@ export interface TplResult { }; } +export interface ParcelledLink { + uri: string; + text: string; +} + export interface FormatToHtmlOptions { - links?: string[]; + links?: Array; + uselessSentences?: Array; searchLinks?: boolean; newLine?: string; indentation?: string; diff --git a/packages/ringcentral-widgets/lib/MeetingCalendarHelper/index.ts b/packages/ringcentral-widgets/lib/MeetingCalendarHelper/index.ts index c30ce4e5eb..101eece3b4 100644 --- a/packages/ringcentral-widgets/lib/MeetingCalendarHelper/index.ts +++ b/packages/ringcentral-widgets/lib/MeetingCalendarHelper/index.ts @@ -1,16 +1,12 @@ import formatMessage from 'format-message'; import { RcVDialInNumberObj } from '@ringcentral-integration/commons/interfaces/Rcv.model'; -import { - MEETING_URI_REGEXP, - rcvAttTeleconference, - rcvTeleconference, -} from './config'; import { formatMeetingId } from './formatMeetingId'; import i18n from './i18n'; import { CommonBrand, FormatToHtmlOptions, + ParcelledLink, RcmMainParams, RcvMainParams, TplResult, @@ -111,6 +107,7 @@ function formatTextToHtml( ): string { const { links = [], + uselessSentences = [], searchLinks = false, newLine = htmlNewLine, indentation = htmlIndentation, @@ -123,16 +120,30 @@ function formatTextToHtml( .map((line) => { return line .replace(/\t/g, tabIndentation) // replace all Tab with 4 indentations - .replace(/^\s*/, ($0) => indentation.repeat($0.length)); // replace leading whtespaces with indentations + .replace(/^\s*/, ($0) => indentation.repeat($0.length)); // replace leading white spaces with indentations }) .join(newLine); - links.forEach((uri) => { - if (uri) { - htmlContent = htmlContent.replace( - uri, - `
${uri}`, - ); + uselessSentences.forEach((sentence) => { + if (sentence) { + htmlContent = htmlContent.replace(sentence, ''); + } + }); + + links.forEach((link) => { + if (link) { + const isPlantLink = typeof link === 'string'; + const uri = isPlantLink ? (link as string) : (link as ParcelledLink).uri; + const text = isPlantLink + ? (link as string) + : (link as ParcelledLink).text; + + if (uri && text) { + htmlContent = htmlContent.replace( + uri, + `${text}`, + ); + } } }); @@ -220,10 +231,11 @@ function getBaseRcvTpl( brand: CommonBrand, currentLocale: string, enableRcvConnector = false, + enableE2EE = false, ): TplResult { const joinUri = meeting.joinUri; const isATT = brand.code === 'att'; - const teleconference = isATT ? rcvAttTeleconference : rcvTeleconference; + const teleconference = brand.rcvTeleconference; if (invitationInfo?.body) { return { @@ -236,16 +248,50 @@ function getBaseRcvTpl( } const accountName = extensionInfo.name; - const { meetingPassword, meetingPasswordPSTN, isMeetingSecret } = meeting; + const { + meetingPassword, + meetingPasswordPSTN, + isMeetingSecret, + e2ee, + } = meeting; let productName; const meetingContent: Array = []; const showMeetingPasswordPSTN = !!(isMeetingSecret && meetingPasswordPSTN); - if (brand.name === 'RingCentral') { + if (enableE2EE && e2ee) { + meetingContent.push( + i18n.getString('rcvE2EEInviteMeetingContent', currentLocale), + ); + return { + formattedMsg: formatMessage(meetingContent.join(''), { + accountName, + brandName: i18n.getString(brand.name), + rcvProductName: i18n.getString(brand.rcvProductName), + joinUri, + e2EESupportLinkText: formatMessage( + i18n.getString('e2EESupportLinkText', currentLocale), + { + brandName: i18n.getString(brand.name), + }, + ), + rcvE2EESupportUrl: brand.rcvE2EESupportUrl, + }), + links: { + joinUri, + teleconference, + }, + }; + } + + if (brand.code === 'rc') { productName = 'RingCentral Video'; meetingContent.push( i18n.getString('rcvRCBrandInviteMeetingContent', currentLocale), ); + } else if (brand.code === 'telus') { + meetingContent.push( + i18n.getString('rcvTelusInviteMeetingContent', currentLocale), + ); } else { productName = brand.name; meetingContent.push( @@ -320,12 +366,14 @@ function getRcvEventTpl( brand: CommonBrand, currentLocale: string, enableRcvConnector = false, + enableE2EE = false, ): string { const tplResult = getBaseRcvTpl( mainInfo, brand, currentLocale, enableRcvConnector, + enableE2EE, ); return tplResult.formattedMsg; } @@ -335,21 +383,47 @@ function getRcvHtmlEventTpl( brand: CommonBrand, currentLocale: string, enableRcvConnector = false, + enableE2EE = false, ): string { const tplResult = getBaseRcvTpl( mainInfo, brand, currentLocale, enableRcvConnector, + enableE2EE, ); + + const links: [string, string, ParcelledLink] = [ + tplResult.links.joinUri, + tplResult.links.teleconference, + { + uri: brand.rcvE2EESupportUrl, + text: formatMessage( + i18n.getString('e2EESupportLinkText', currentLocale), + { + brandName: i18n.getString(brand.name), + }, + ), + }, + ]; + return formatTextToHtml(tplResult.formattedMsg, { - links: [tplResult.links.joinUri, tplResult.links.teleconference], + uselessSentences: [ + `${formatMessage(i18n.getString('e2EESupportLinkText', currentLocale), { + brandName: i18n.getString(brand.name), + })}
`, + ], + links, }); } -function getMeetingId(meetingUri: string): string { +function getMeetingId( + meetingUri: string, + rcvUriRegExp: RegExp, + rcmUriRegExp: RegExp, +): string { if (meetingUri) { - const regs = [MEETING_URI_REGEXP.RCM, MEETING_URI_REGEXP.RCV]; + const regs = [rcmUriRegExp, rcvUriRegExp]; for (let i = 0; i < regs.length; i += 1) { const matches = regs[i].exec(meetingUri); if (matches && matches.length > 0) { @@ -368,9 +442,13 @@ function getMeetingId(meetingUri: string): string { return null; } -function stripMeetingLinks(text: string): string { +function stripMeetingLinks( + text: string, + rcvUriRegExp: RegExp, + rcmUriRegExp: RegExp, +): string { let result = text; - [MEETING_URI_REGEXP.RCM, MEETING_URI_REGEXP.RCV].forEach((reg) => { + [rcmUriRegExp, rcvUriRegExp].forEach((reg) => { while (reg.test(result)) { result = result.replace(reg, ''); } @@ -379,11 +457,13 @@ function stripMeetingLinks(text: string): string { } function meetingLinkContains( + rcvUriRegExp: RegExp, + rcmUriRegExp: RegExp, text?: string, ): { hasRCM: boolean; hasRCV: boolean } { return { - hasRCM: MEETING_URI_REGEXP.RCM.test(text ?? ''), - hasRCV: MEETING_URI_REGEXP.RCV.test(text ?? ''), + hasRCM: rcmUriRegExp.test(text ?? ''), + hasRCV: rcvUriRegExp.test(text ?? ''), }; } diff --git a/packages/ringcentral-widgets/lib/MeetingHelper/index.ts b/packages/ringcentral-widgets/lib/MeetingHelper/index.ts new file mode 100644 index 0000000000..570635404b --- /dev/null +++ b/packages/ringcentral-widgets/lib/MeetingHelper/index.ts @@ -0,0 +1,44 @@ +import formatMessage from 'format-message'; +import { reduce } from 'ramda'; +import i18n from '../../components/MeetingConfigsV2/i18n'; + +export const MINUTE_SCALE: number = 4; +export const HOUR_SCALE: number = 13; + +export function getMinutesList(MINUTE_SCALE: number, currentLocale: string) { + return reduce( + (result) => { + const index = result.length; + const value = (60 / MINUTE_SCALE) * index; + const text = formatMessage(i18n.getString('minutes', currentLocale), { + howMany: `${value}0`.slice(0, 2), + }); + return result.concat({ + value, + text, + }); + }, + [], + new Array(MINUTE_SCALE), + ); +} + +export function getHoursList(HOUR_SCALE: number, currentLocale: string) { + if (HOUR_SCALE > 23) { + throw new Error('HOUR_SCALE must be less than 23.'); + } + return reduce( + (result) => { + const value = result.length; + const text = formatMessage(i18n.getString('hours', currentLocale), { + howMany: `0${value}0`.slice(-3, -1), + }); + return result.concat({ + value, + text, + }); + }, + [], + new Array(HOUR_SCALE), + ); +} diff --git a/packages/ringcentral-widgets/lib/channel.ts b/packages/ringcentral-widgets/lib/channel.ts new file mode 100644 index 0000000000..56283f8eb6 --- /dev/null +++ b/packages/ringcentral-widgets/lib/channel.ts @@ -0,0 +1,68 @@ +type Handler = (request: any, sender: any) => void; + +type Packet = { + [s: string]: any; +}; +class Channel { + _mux: { + [k: string]: Handler; + }; + _type: string; + constructor(type: string) { + // action -> handler + this._mux = {}; + this._type = type; + this._make(); + } + + select(actionType: string, handler: Handler) { + this._mux[actionType] = handler; + return this; + } + + send(packet: Packet) { + return new Promise((resolve) => { + chrome.runtime.sendMessage({ type: this._type, ...packet }, resolve); + }); + } + + broadcast(packet: Packet) { + const promises: Promise[] = []; + chrome.tabs.query({}, (tabs) => { + if (!tabs.length) return; + tabs.forEach((tab) => { + promises.push( + new Promise((resolve) => { + chrome.tabs.sendMessage( + tab.id, + { type: this._type, ...packet }, + resolve, + ); + }), + ); + }); + }); + return Promise.all(promises); + } + + _make() { + chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { + const { type, action } = request; + if (type === this._type) { + const handler = this._mux[action]; + if (typeof handler === 'function') { + Promise.resolve(handler(request, sender)) + .then((retval) => { + sendResponse(retval); + }) + .catch((err) => console.error(err)); + // Async + return true; + } + } + return false; + }); + } +} + +export { Channel }; diff --git a/packages/ringcentral-widgets/lib/checkShouldHidePhoneNumber.ts b/packages/ringcentral-widgets/lib/checkShouldHidePhoneNumber.ts new file mode 100644 index 0000000000..a97848fba8 --- /dev/null +++ b/packages/ringcentral-widgets/lib/checkShouldHidePhoneNumber.ts @@ -0,0 +1,30 @@ +import { filter, find } from 'ramda'; +import { Entity } from '@ringcentral-integration/commons/interfaces/Entity.interface'; + +export function checkShouldHidePhoneNumber( + phoneNumber: string, + contactMatches: Entity[], +) { + if ( + !phoneNumber || + phoneNumber === '' || + !contactMatches || + !Array.isArray(contactMatches) || + contactMatches.length === 0 + ) { + return false; + } + const filteredMatches = filter((item) => !item.hidden, contactMatches); + if ( + filteredMatches.length && + find((m) => { + return !!find( + (p) => p.phoneNumber === phoneNumber && !p.hidden, + m.phoneNumbers ?? [], + ); + }, filteredMatches) + ) { + return false; + } + return true; +} diff --git a/packages/ringcentral-widgets/lib/getWebpackConfig/index.js b/packages/ringcentral-widgets/lib/getWebpackConfig/index.js index 647d698cd3..2acbfb4d18 100644 --- a/packages/ringcentral-widgets/lib/getWebpackConfig/index.js +++ b/packages/ringcentral-widgets/lib/getWebpackConfig/index.js @@ -5,6 +5,9 @@ import autoprefixer from 'autoprefixer'; import path from 'path'; import webpack from 'webpack'; +/** + * @deprecated + */ function getBaseConfig({ cacheDirectory = false, hashPrefix = '', diff --git a/packages/ringcentral-widgets/lib/phoneContext/brands/attRich/theme.json b/packages/ringcentral-widgets/lib/phoneContext/brands/attRich/theme.json deleted file mode 100644 index 89d01f45a2..0000000000 --- a/packages/ringcentral-widgets/lib/phoneContext/brands/attRich/theme.json +++ /dev/null @@ -1,550 +0,0 @@ -{ - "breakpoints": { - "values": { - "xs": 0, - "sm": 641, - "md": 960, - "lg": 1280, - "xl": 1920 - } - }, - "palette": { - "primary": { - "50": "#e1f4fb", - "100": "#b2e3f4", - "200": "#82d1ed", - "300": "#66bffa", - "400": "#34b1e2", - "500": "#6990fd", - "600": "#4475fd", - "700": "#4475fd", - "800": "#2f51b1", - "900": "#005488", - "light": "#6990fd", - "main": "#4475fd", - "dark": "#2f51b1" - }, - "secondary": { - "50": "#fff3e0", - "100": "#ffdfb1", - "200": "#ffca7f", - "300": "#ffb44c", - "400": "#ffa424", - "500": "#ff9f33", - "600": "#ff8800", - "700": "#f97802", - "800": "#b25f00", - "900": "#ea4b04", - "light": "#ff9f33", - "main": "#ff8800", - "dark": "#b25f00" - }, - "semantic": { - "negative": "#f44336", - "positive": "#26a304", - "critical": "#f6ad16", - "neutral": "#616161" - }, - "accent": { - "ash": "#bfbfbf", - "lake": "#69a3eb", - "tiffany": "#22c2d6", - "cateye": "#52d2b1", - "grass": "#bdd655", - "olive": "#4cd964", - "gold": "#edb63c", - "lemon": "#ffd800", - "tomato": "#ff3737", - "indigo": "#4a1e8c", - "purple": "#4A44FD", - "persimmon": "#ff793d", - "black": "#212121", - "red": "#f44336", - "blue": "#4475fd", - "orange": "#FF8800", - "yellow": "#EDB63C", - "green": "#26A304" - }, - "grey": { - "100": "#f5f6fb", - "200": "#EEEEEE", - "400": "#8F98A8", - "500": "#8192AF", - "600": "#737983", - "900": "#212121" - }, - "background": { - "disabled": "rgba(255,55,55,.05)", - "default": "#fff" - }, - "action": { - "hoverOpacity": 0.12, - "active": "#EBF6FA", - "grayLight": "#666666", - "grayDark": "#494949", - "primary": "#0A6EBE" - }, - "tooltip": { - "dark": "#616161" - }, - "avatar": { - "tomato": "#C93637", - "blueberry": "#5A5ABF", - "oasis": "#04549F", - "gold": "#7A7000", - "sage": "#047C68", - "ash": "#666666", - "persimmon": "#A14B00", - "pear": "#3C7E44", - "brass": "#8E6B2B", - "lake": "#1A70C1", - "red": "#f54c3d", - "orange": "#FF8800", - "yellow": "#F6AD16", - "green": "#299e0b", - "tiffany": "#3096a8", - "primary": "#6990FD", - "purple": "#8c79e7", - "neutral": "#8D93A5", - "global": "#5399D1" - }, - "common": { - "white": "#fff" - }, - "bg": { - "paper": "#FFFFFF", - "light": "#F9F9FA", - "dark": "#F0F1F4", - "primaryLightest": "#F5F6FB", - "primary": "#4475FD", - "secondary": "#FF8800", - "negative": "#f54c3d", - "positive": "#299e0b", - "neutral": "#6C7489", - "critical": "#F6AD16", - "redLight": "#F9EBE9", - "orangeLight": "#FAECDF", - "yellowLight": "#f7edd7", - "greenLight": "#e8f1e8", - "tiffanyLight": "#E8F0F2", - "blueLight": "#EAEEF5", - "purpleLight": "#EDEDF5", - "redLightest": "#fbf5f4", - "orangeLightest": "#fbf5ef", - "yellowLightest": "#f9f6ec", - "greenLightest": "#f3f8f3", - "tiffanyLightest": "#f3f7f8", - "blueLightest": "#F5F6FB", - "purpleLightest": "#f6f6fa", - "buttonDisabled": "#F0F1F4", - "transparentDark": "rgba(66, 73, 92, 0.72)", - "transparentDarkDisabled": "rgba(66, 73, 92, 0.32)", - "primaryLight": "#EAEEF5" - }, - "element": { - "default": "#8D93A5", - "primary": "#4475FD", - "negative": "#f54c3d", - "disabled": "#CED1D9" - }, - "border": { - "default": "#CED1D9", - "primary": "#4475FD", - "negative": "#f54c3d", - "disabled": "#E8E9ED", - "inverse": "#FFFFFF", - "light": "#E8E9ED", - "secondary": "#FF8800", - "redLight": "#F9EBE9", - "dark": "#282B33" - }, - "text": { - "dark": "#282B33", - "default": "#464B59", - "subdued": "#6C7489", - "info": "#4475FD", - "negative": "#c64335", - "positive": "#31841d", - "critical": "#FF8800", - "inverse": "#FFFFFF", - "bgPrimary": "#FFFFFF", - "bgSecondary": "#FFFFFF", - "bgNegative": "#FFFFFF", - "bgPositive": "#FFFFFF", - "bgNeutral": "#FFFFFF", - "hint": "#81899D", - "disabled": "#B5B9C5", - "button": "#4475FD", - "secondaryInfo": "#FF8800" - }, - "icon": { - "subdued": "#81899D", - "default": "#6C7489", - "dark": "#282B33", - "primary": "#4475FD", - "negative": "#f54c3d", - "positive": "#299e0b", - "critical": "#F6AD16", - "secondary": "#FF8800", - "inverse": "#FFFFFF", - "inverseDisabled": "#FFFFFF", - "disabled": "#B5B9C5", - "bookmark": "#4475FD" - }, - "label": { - "red": { - "icon": "#f54c3d", - "text": "#c64335" - }, - "orange": { - "icon": "#FF8800", - "text": "#FF8800" - }, - "yellow": { - "icon": "#F6AD16", - "text": "#8e6b2b" - }, - "green": { - "icon": "#299e0b", - "text": "#31841d" - }, - "tiffany": { - "icon": "#3096a8", - "text": "#367987" - }, - "blue": { - "icon": "#4475FD", - "text": "#4475FD" - }, - "purple": { - "icon": "#8c79e7", - "text": "#7265b3" - }, - "black": { - "icon": "#282B33", - "text": "#282B33" - }, - "red01": "#E6413C", - "red02": "#BE3933", - "orange01": "#CD6E0D", - "orange02": "#A15600", - "yellow01": "#B17D1A", - "yellow02": "#896219", - "green01": "#3C9949", - "green02": "#32773B", - "teal01": "#3093A4", - "teal02": "#2B727F", - "blue01": "#066FAC", - "blue02": "#066FAC", - "purple01": "#8A77E3", - "purple02": "#6C5DAF", - "black02": "#121212" - }, - "globalHeader": { - "bgLight": "#66bffa", - "bgDark": "#4475FD", - "bgTransparent": "rgba(255, 255, 255, 0.16)", - "bgTransparentDisabled": "rgba(255, 255, 255, 0.08)", - "text": "#FFFFFF", - "textHint": "rgba(255, 255, 255, 0.48)", - "icon": "#FFFFFF", - "iconDisabled": "rgba(255, 255, 255, 0.32)", - "border": "#FFFFFF", - "critical": "#F6AD16", - "positive": "rgb(116, 200, 158)" - }, - "header": { - "bgLeft": "#0A6EBE", - "bgRight": "#5399D1", - "bgOverlay": "rgba(0, 0, 0, 0.16)", - "bgOverlayDisabled": "rgba(0, 0, 0, 0.08)", - "fabBg": "#FFFFFF", - "fabIcon": "#121212", - "border": "transparent", - "divider": "rgba(0, 0, 0, 0.12)", - "focusBorder": "#FFFFFF", - "text": "#FFFFFF", - "textHint": "rgba(255, 255, 255, 0.88)", - "icon": "#FFFFFF", - "iconDisabled": "rgba(255, 255, 255, 0.32)" - }, - "dialHeader": { - "bg": "#0A6EBE", - "text": "#FFFFFF", - "textHint": "rgba(255, 255, 255, 0.88)", - "icon": "#FFFFFF", - "avatarBg": "#FFFFFF", - "avatarIcon": "#0A6EBE", - "focusBorder": "#FFFFFF" - }, - "nav": { - "iconDefault": "#121212", - "iconSelected": "#0A6EBE", - "b01": "#FFFFFF", - "b02": "#F9F9F9", - "line": "#E5E5E5", - "menuBg": "#0A6EBE", - "menuText": "#FFFFFF", - "f01": "#757575", - "f02": "#666666", - "f03": "#494949", - "f04": "#121212", - "bookmark": "#0A6EBE", - "mention": "#A15600", - "ctlDefault": "#939393", - "ctlSelected": "#0A6EBE" - }, - "tab": { - "default": "#121212", - "selected": "#0A6EBE" - }, - "subAction": "#0A6EBE", - "umi": { - "bg": "#666666", - "text": "#FFFFFF", - "mentioned": "#A15600" - }, - "content": { - "brand": "#0A6EBE" - }, - "interactive": { - "f01": "#0A6EBE", - "b01": "#E6F2F8", - "b02": "#0A6EBE" - }, - "success": { - "b01": "#F0FCEF", - "b02": "#CEF4CE", - "b03": "#3C9949", - "b04": "#368541", - "b05": "#3C9949", - "f01": "#CEF4CE", - "f02": "#32773B", - "f11": "#46BE59" - }, - "warning": { - "b01": "#FFF7EB", - "b02": "#FFE7C1", - "b03": "#F6AD16", - "f01": "#F6AD16", - "f02": "#896219", - "f11": "#F6AD16" - }, - "danger": { - "b01": "#FFF7F5", - "b02": "#FFE5E0", - "b03": "#E6413C", - "b04": "#D63E39", - "f01": "#FFE5E0", - "f02": "#BE3933", - "f11": "#F88878" - }, - "highlight": { - "b01": "#FF8800", - "b02": "#FFDFB1", - "b03": "#FF8800", - "f01": "#121212", - "f02": "#FF8800" - }, - "informative": { - "b01": "#F6F9FC", - "f01": "#E3EBF4", - "f02": "#066FAC" - }, - "neutral": { - "f01": "#FFFFFF", - "f02": "#939393", - "f03": "#757575", - "f04": "#666666", - "f05": "#494949", - "f06": "#121212", - "f07": "#121212", - "f11": "#FFFFFF", - "elevation": "#FFFFFF", - "transparent": "transparent", - "b01": "#FFFFFF", - "b02": "#F9F9F9", - "b03": "#F3F3F3", - "b04": "#666666", - "b05": "#494949", - "b06": "#000000", - "l01": "#FFFFFF", - "l02": "#E5E5E5", - "l03": "#C7C7C7", - "l04": "#666666" - }, - "disabled": { - "f01": "#FFFFFF", - "f02": "#B9B9B9", - "b01": "#B9B9B9" - }, - "presence": { - "busy": "#E6413C", - "available": "#3C9949", - "invisible": "#939393" - }, - "highContrast": "transparent" - }, - "radius": { - "circle": "50%", - "zero": "0px", - "sm": "2px", - "md": "3px", - "lg": "4px", - "xl": "8px", - "xxl": "16px", - "round": "100vw" - }, - "shape": { - "borderRadius": 4 - }, - "shadows": [ - "none", - "0 1px 3px 0 rgba(0, 0, 0, 0.2), 0 1px 1px 0 rgba(0, 0, 0, 0.14), 0 2px 1px -1px rgba(0, 0, 0, 0.12)", - "0px 1px 5px 0px rgba(0, 0, 0, 0.2),0px 2px 2px 0px rgba(0, 0, 0, 0.14),0px 3px 1px -2px rgba(0, 0, 0, 0.12)", - "0px 1px 8px 0px rgba(0, 0, 0, 0.2),0px 3px 4px 0px rgba(0, 0, 0, 0.14),0px 3px 3px -2px rgba(0, 0, 0, 0.12)", - "0px 2px 4px -1px rgba(0, 0, 0, 0.2),0px 4px 5px 0px rgba(0, 0, 0, 0.14),0px 1px 10px 0px rgba(0, 0, 0, 0.12)", - "0px 3px 5px -1px rgba(0, 0, 0, 0.2),0px 5px 8px 0px rgba(0, 0, 0, 0.14),0px 1px 14px 0px rgba(0, 0, 0, 0.12)", - "0px 3px 5px -1px rgba(0, 0, 0, 0.2),0px 6px 10px 0px rgba(0, 0, 0, 0.14),0px 1px 18px 0px rgba(0, 0, 0, 0.12)", - "0px 4px 5px -2px rgba(0, 0, 0, 0.2),0px 7px 10px 1px rgba(0, 0, 0, 0.14),0px 2px 16px 1px rgba(0, 0, 0, 0.12)", - "0px 5px 5px -3px rgba(0, 0, 0, 0.2),0px 8px 10px 1px rgba(0, 0, 0, 0.14),0px 3px 14px 2px rgba(0, 0, 0, 0.12)", - "0px 5px 6px -3px rgba(0, 0, 0, 0.2),0px 9px 12px 1px rgba(0, 0, 0, 0.14),0px 3px 16px 2px rgba(0, 0, 0, 0.12)", - "0px 6px 6px -3px rgba(0, 0, 0, 0.2),0px 10px 14px 1px rgba(0, 0, 0, 0.14),0px 4px 18px 3px rgba(0, 0, 0, 0.12)", - "0px 6px 7px -4px rgba(0, 0, 0, 0.2),0px 11px 15px 1px rgba(0, 0, 0, 0.14),0px 4px 20px 3px rgba(0, 0, 0, 0.12)", - "0px 7px 8px -4px rgba(0, 0, 0, 0.2),0px 12px 17px 2px rgba(0, 0, 0, 0.14),0px 5px 22px 4px rgba(0, 0, 0, 0.12)", - "0px 7px 8px -4px rgba(0, 0, 0, 0.2),0px 13px 19px 2px rgba(0, 0, 0, 0.14),0px 5px 24px 4px rgba(0, 0, 0, 0.12)", - "0px 7px 9px -4px rgba(0, 0, 0, 0.2),0px 14px 21px 2px rgba(0, 0, 0, 0.14),0px 5px 26px 4px rgba(0, 0, 0, 0.12)", - "0px 8px 9px -5px rgba(0, 0, 0, 0.2),0px 15px 22px 2px rgba(0, 0, 0, 0.14),0px 6px 28px 5px rgba(0, 0, 0, 0.12)", - "0px 8px 10px -5px rgba(0, 0, 0, 0.2),0px 16px 24px 2px rgba(0, 0, 0, 0.14),0px 6px 30px 5px rgba(0, 0, 0, 0.12)", - "0px 8px 11px -5px rgba(0, 0, 0, 0.2),0px 17px 26px 2px rgba(0, 0, 0, 0.14),0px 6px 32px 5px rgba(0, 0, 0, 0.12)", - "0px 9px 11px -5px rgba(0, 0, 0, 0.2),0px 18px 28px 2px rgba(0, 0, 0, 0.14),0px 7px 34px 6px rgba(0, 0, 0, 0.12)", - "0px 9px 12px -6px rgba(0, 0, 0, 0.2),0px 19px 29px 2px rgba(0, 0, 0, 0.14),0px 7px 36px 6px rgba(0, 0, 0, 0.12)", - "0px 10px 13px -6px rgba(0, 0, 0, 0.2),0px 20px 31px 3px rgba(0, 0, 0, 0.14),0px 8px 38px 7px rgba(0, 0, 0, 0.12)", - "0px 10px 13px -6px rgba(0, 0, 0, 0.2),0px 21px 33px 3px rgba(0, 0, 0, 0.14),0px 8px 40px 7px rgba(0, 0, 0, 0.12)", - "0px 10px 14px -6px rgba(0, 0, 0, 0.2),0px 22px 35px 3px rgba(0, 0, 0, 0.14),0px 8px 42px 7px rgba(0, 0, 0, 0.12)", - "0px 11px 14px -7px rgba(0, 0, 0, 0.2),0px 23px 36px 3px rgba(0, 0, 0, 0.14),0px 9px 44px 8px rgba(0, 0, 0, 0.12)", - "0px 11px 15px -7px rgba(0, 0, 0, 0.2),0px 24px 38px 3px rgba(0, 0, 0, 0.14),0px 9px 46px 8px rgba(0, 0, 0, 0.12)" - ], - "zIndex": { - "default": 1, - "banner": 9500, - "snackbar": 10000, - "dialog": 6000, - "mask": 5000, - "popup": 3000, - "spinner": 9050, - "model": 9000, - "dropdown": 7000, - "ripple": 1, - "elementOnRipple": 2, - "loading": 1000, - "dragging": 2000, - "moreMenu": 999, - "toast": 3000, - "memberListHeader": 100, - "floatButton": 10, - "makeZIndexStackingContext": 1, - "codeEditor": 0 - }, - "typography": { - "fontFamily": "Lato, Helvetica, Arial, sans-serif", - "codeFontFamily": "Courier", - "fontSize": 14, - "fontWeightLight": 300, - "fontWeightRegular": 400, - "fontWeightMedium": 500, - "display4": { - "fontSize": "6rem", - "fontWeight": 700, - "lineHeight": "112px" - }, - "display3": { - "fontSize": "3.5rem", - "fontWeight": 700, - "lineHeight": "72px" - }, - "display2": { - "fontSize": "2.8125rem", - "fontWeight": 400, - "lineHeight": "56px" - }, - "display1": { - "fontSize": "2.125rem", - "fontWeight": 400, - "lineHeight": "40px" - }, - "headline2": { - "fontSize": "1.5rem", - "fontWeight": 700, - "lineHeight": "32px" - }, - "headline": { - "fontSize": "1.5rem", - "fontWeight": 400, - "lineHeight": "32px" - }, - "title2": { - "fontSize": "1.25rem", - "fontWeight": 700, - "lineHeight": "28px" - }, - "title1": { - "fontSize": "1.25rem", - "fontWeight": 400, - "lineHeight": "28px" - }, - "subheading2": { - "fontSize": "1rem", - "fontWeight": 700, - "lineHeight": "24px" - }, - "subheading1": { - "fontSize": "1rem", - "fontWeight": 400, - "lineHeight": "24px" - }, - "body2": { - "fontSize": "0.9375rem", - "fontWeight": 700, - "lineHeight": "22px" - }, - "body1": { - "fontSize": "0.9375rem", - "fontWeight": 400, - "lineHeight": "22px" - }, - "caption2": { - "fontSize": "0.75rem", - "fontWeight": 700, - "lineHeight": "16px" - }, - "caption1": { - "fontSize": "0.75rem", - "fontWeight": 400, - "lineHeight": "16px" - }, - "button": { - "fontSize": "0.9375rem", - "fontWeight": 700, - "lineHeight": "20px", - "textTransform": "none" - } - }, - "transitions": { - "easing": { - "easeIn": "cubic-bezier(0.4, 0, 1, 1)", - "easeOut": "cubic-bezier(0.0, 0, 0.2, 1)", - "easeInOut": "cubic-bezier(0.4, 0, 0.2, 1)", - "sharp": "cubic-bezier(0.4, 0, 0.6, 1)" - }, - "duration": { - "shortest": 150, - "shorter": 200, - "short": 250, - "standard": 300, - "complex": 375, - "enteringScreen": 225, - "leavingScreen": 195 - } - } -} diff --git a/packages/ringcentral-widgets/lib/phoneContext/brands/btRich/theme.json b/packages/ringcentral-widgets/lib/phoneContext/brands/btRich/theme.json deleted file mode 100644 index 86a71e2de0..0000000000 --- a/packages/ringcentral-widgets/lib/phoneContext/brands/btRich/theme.json +++ /dev/null @@ -1,552 +0,0 @@ -{ - "breakpoints": { - "values": { - "xs": 0, - "sm": 641, - "md": 960, - "lg": 1280, - "xl": 1920 - } - }, - "palette": { - "primary": { - "50": "#e1f4fb", - "100": "#b2e3f4", - "200": "#82d1ed", - "300": "#66bffa", - "400": "#34b1e2", - "500": "#6990fd", - "600": "#4475fd", - "700": "#4475fd", - "800": "#2f51b1", - "900": "#005488", - "light": "#6990fd", - "main": "#4475fd", - "dark": "#2f51b1" - }, - "secondary": { - "50": "#fff3e0", - "100": "#ffdfb1", - "200": "#ffca7f", - "300": "#ffb44c", - "400": "#ffa424", - "500": "#ff9f33", - "600": "#ff8800", - "700": "#f97802", - "800": "#b25f00", - "900": "#ea4b04", - "light": "#ff9f33", - "main": "#ff8800", - "dark": "#b25f00" - }, - "semantic": { - "negative": "#f44336", - "positive": "#26a304", - "critical": "#f6ad16", - "neutral": "#616161" - }, - "accent": { - "ash": "#bfbfbf", - "lake": "#69a3eb", - "tiffany": "#22c2d6", - "cateye": "#52d2b1", - "grass": "#bdd655", - "olive": "#4cd964", - "gold": "#edb63c", - "lemon": "#ffd800", - "tomato": "#ff3737", - "indigo": "#4a1e8c", - "purple": "#4A44FD", - "persimmon": "#ff793d", - "black": "#212121", - "red": "#f44336", - "blue": "#4475fd", - "orange": "#FF8800", - "yellow": "#EDB63C", - "green": "#26A304" - }, - "grey": { - "100": "#f5f6fb", - "200": "#EEEEEE", - "400": "#8F98A8", - "500": "#8192AF", - "600": "#737983", - "900": "#212121" - }, - "background": { - "disabled": "rgba(255,55,55,.05)", - "default": "#fff" - }, - "action": { - "hoverOpacity": 0.12, - "active": "#EBF6FA", - "grayLight": "#666666", - "grayDark": "#494949", - "primary": "#5514B4" - }, - "tooltip": { - "dark": "#616161" - }, - "avatar": { - "tomato": "#C93637", - "blueberry": "#5A5ABF", - "oasis": "#04549F", - "gold": "#7A7000", - "sage": "#047C68", - "ash": "#666666", - "persimmon": "#A14B00", - "pear": "#3C7E44", - "brass": "#8E6B2B", - "lake": "#1A70C1", - "red": "#f54c3d", - "orange": "#FF8800", - "yellow": "#F6AD16", - "green": "#299e0b", - "tiffany": "#3096a8", - "primary": "#6990FD", - "purple": "#8c79e7", - "neutral": "#8D93A5", - "global": "#885ACA" - }, - "common": { - "white": "#fff" - }, - "bg": { - "paper": "#FFFFFF", - "light": "#F9F9FA", - "dark": "#F0F1F4", - "primaryLightest": "#F5F6FB", - "primary": "#4475FD", - "secondary": "#FF8800", - "negative": "#f54c3d", - "positive": "#299e0b", - "neutral": "#6C7489", - "critical": "#F6AD16", - "redLight": "#F9EBE9", - "orangeLight": "#FAECDF", - "yellowLight": "#f7edd7", - "greenLight": "#e8f1e8", - "tiffanyLight": "#E8F0F2", - "blueLight": "#EAEEF5", - "purpleLight": "#EDEDF5", - "redLightest": "#fbf5f4", - "orangeLightest": "#fbf5ef", - "yellowLightest": "#f9f6ec", - "greenLightest": "#f3f8f3", - "tiffanyLightest": "#f3f7f8", - "blueLightest": "#F5F6FB", - "purpleLightest": "#f6f6fa", - "buttonDisabled": "#F0F1F4", - "transparentDark": "rgba(66, 73, 92, 0.72)", - "transparentDarkDisabled": "rgba(66, 73, 92, 0.32)", - "primaryLight": "#EAEEF5" - }, - "element": { - "default": "#8D93A5", - "primary": "#4475FD", - "negative": "#f54c3d", - "disabled": "#CED1D9" - }, - "border": { - "default": "#CED1D9", - "primary": "#4475FD", - "negative": "#f54c3d", - "disabled": "#E8E9ED", - "inverse": "#FFFFFF", - "light": "#E8E9ED", - "secondary": "#FF8800", - "redLight": "#F9EBE9", - "dark": "#282B33" - }, - "text": { - "dark": "#282B33", - "default": "#464B59", - "subdued": "#6C7489", - "info": "#4475FD", - "negative": "#c64335", - "positive": "#31841d", - "critical": "#FF8800", - "inverse": "#FFFFFF", - "bgPrimary": "#FFFFFF", - "bgSecondary": "#FFFFFF", - "bgNegative": "#FFFFFF", - "bgPositive": "#FFFFFF", - "bgNeutral": "#FFFFFF", - "hint": "#81899D", - "disabled": "#B5B9C5", - "button": "#4475FD", - "secondaryInfo": "#FF8800" - }, - "icon": { - "subdued": "#81899D", - "default": "#6C7489", - "dark": "#282B33", - "primary": "#4475FD", - "negative": "#f54c3d", - "positive": "#299e0b", - "critical": "#F6AD16", - "secondary": "#FF8800", - "inverse": "#FFFFFF", - "inverseDisabled": "#FFFFFF", - "disabled": "#B5B9C5", - "bookmark": "#4475FD" - }, - "label": { - "red": { - "icon": "#f54c3d", - "text": "#c64335" - }, - "orange": { - "icon": "#FF8800", - "text": "#FF8800" - }, - "yellow": { - "icon": "#F6AD16", - "text": "#8e6b2b" - }, - "green": { - "icon": "#299e0b", - "text": "#31841d" - }, - "tiffany": { - "icon": "#3096a8", - "text": "#367987" - }, - "blue": { - "icon": "#4475FD", - "text": "#4475FD" - }, - "purple": { - "icon": "#8c79e7", - "text": "#7265b3" - }, - "black": { - "icon": "#282B33", - "text": "#282B33" - }, - "red01": "#E6413C", - "red02": "#BE3933", - "orange01": "#CD6E0D", - "orange02": "#A15600", - "yellow01": "#B17D1A", - "yellow02": "#896219", - "green01": "#3C9949", - "green02": "#32773B", - "teal01": "#3093A4", - "teal02": "#2B727F", - "blue01": "#066FAC", - "blue02": "#066FAC", - "purple01": "#8A77E3", - "purple02": "#6C5DAF", - "black02": "#121212" - }, - "globalHeader": { - "bgLight": "#66bffa", - "bgDark": "#4475FD", - "bgTransparent": "rgba(255, 255, 255, 0.16)", - "bgTransparentDisabled": "rgba(255, 255, 255, 0.08)", - "text": "#FFFFFF", - "textHint": "rgba(255, 255, 255, 0.48)", - "icon": "#FFFFFF", - "iconDisabled": "rgba(255, 255, 255, 0.32)", - "border": "#FFFFFF", - "critical": "#F6AD16", - "positive": "rgb(116, 200, 158)" - }, - "header": { - "bgLeft": "#5514B4", - "bgRight": "#885ACA", - "bgOverlay": "rgba(255, 255, 255, 0.16)", - "bgOverlayDisabled": "rgba(255, 255, 255, 0.08)", - "fabBg": "#FFFFFF", - "fabIcon": "#121212", - "border": "transparent", - "divider": "rgba(0, 0, 0, 0.12)", - "focusBorder": "#FFFFFF", - "text": "#FFFFFF", - "textHint": "rgba(255, 255, 255, 0.48)", - "icon": "#FFFFFF", - "iconDisabled": "rgba(255, 255, 255, 0.32)" - }, - "dialHeader": { - "bg": "#5514B4", - "text": "#FFFFFF", - "textHint": "rgba(255, 255, 255, 0.72)", - "icon": "#FFFFFF", - "avatarBg": "#FFFFFF", - "avatarIcon": "#5514B4", - "focusBorder": "#FFFFFF" - }, - "nav": { - "iconDefault": "#121212", - "iconSelected": "#5514B4", - "b01": "#FFFFFF", - "b02": "#F9F9F9", - "line": "#E5E5E5", - "menuBg": "#5514B4", - "menuText": "#FFFFFF", - "f01": "#757575", - "f02": "#666666", - "f03": "#494949", - "f04": "#121212", - "bookmark": "#5514B4", - "mention": "#FF8800", - "ctlDefault": "#939393", - "ctlSelected": "#5514B4" - }, - "tab": { - "default": "#121212", - "selected": "#5514B4" - }, - "subAction": "#5514B4", - "umi": { - "bg": "#666666", - "text": "#FFFFFF", - "mentioned": "#FF8800" - }, - "content": { - "brand": "#5514B4" - }, - "interactive": { - "f01": "#5514B4", - "b01": "#F9F8FE", - "b02": "#5514B4" - }, - "success": { - "b01": "#F0FCEF", - "b02": "#CEF4CE", - "b03": "#3C9949", - "b04": "#368541", - "b05": "#3C9949", - "f01": "#CEF4CE", - "f02": "#32773B", - "f11": "#46BE59" - }, - "warning": { - "b01": "#FFF7EB", - "b02": "#FFE7C1", - "b03": "#F6AD16", - "f01": "#F6AD16", - "f02": "#896219", - "f11": "#F6AD16" - }, - "danger": { - "b01": "#FFF7F5", - "b02": "#FFE5E0", - "b03": "#E6413C", - "b04": "#D63E39", - "f01": "#FFE5E0", - "f02": "#BE3933", - "f11": "#F88878" - }, - "highlight": { - "b01": "#FF8800", - "b02": "#FFDFB1", - "b03": "#FF8800", - "f01": "#121212", - "f02": "#FF8800" - }, - "informative": { - "b01": "#F6F9FC", - "f01": "#E3EBF4", - "f02": "#066FAC" - }, - "neutral": { - "f01": "#FFFFFF", - "f02": "#939393", - "f03": "#757575", - "f04": "#666666", - "f05": "#494949", - "f06": "#121212", - "f07": "#121212", - "elevation": "#FFFFFF", - "transparent": "transparent", - "b01": "#FFFFFF", - "b02": "#F9F9F9", - "b03": "#F3F3F3", - "b04": "#666666", - "b05": "#494949", - "b06": "#000000", - "l01": "#FFFFFF", - "l02": "#E5E5E5", - "l03": "#C7C7C7", - "l04": "#666666" - }, - "disabled": { - "f01": "#FFFFFF", - "f02": "#B9B9B9", - "b01": "#B9B9B9" - }, - "presence": { - "busy": "#E6413C", - "available": "#3C9949", - "invisible": "#939393" - }, - "highContrast": "transparent" - }, - "radius": { - "circle": "50%", - "zero": "0px", - "sm": "2px", - "md": "3px", - "lg": "4px", - "xl": "8px", - "xxl": "16px", - "round": "100vw" - }, - "shape": { - "borderRadius": 4 - }, - "shadows": [ - "none", - "0 1px 3px 0 rgba(0, 0, 0, 0.2), 0 1px 1px 0 rgba(0, 0, 0, 0.14), 0 2px 1px -1px rgba(0, 0, 0, 0.12)", - "0px 1px 5px 0px rgba(0, 0, 0, 0.2),0px 2px 2px 0px rgba(0, 0, 0, 0.14),0px 3px 1px -2px rgba(0, 0, 0, 0.12)", - "0px 1px 8px 0px rgba(0, 0, 0, 0.2),0px 3px 4px 0px rgba(0, 0, 0, 0.14),0px 3px 3px -2px rgba(0, 0, 0, 0.12)", - "0px 2px 4px -1px rgba(0, 0, 0, 0.2),0px 4px 5px 0px rgba(0, 0, 0, 0.14),0px 1px 10px 0px rgba(0, 0, 0, 0.12)", - "0px 3px 5px -1px rgba(0, 0, 0, 0.2),0px 5px 8px 0px rgba(0, 0, 0, 0.14),0px 1px 14px 0px rgba(0, 0, 0, 0.12)", - "0px 3px 5px -1px rgba(0, 0, 0, 0.2),0px 6px 10px 0px rgba(0, 0, 0, 0.14),0px 1px 18px 0px rgba(0, 0, 0, 0.12)", - "0px 4px 5px -2px rgba(0, 0, 0, 0.2),0px 7px 10px 1px rgba(0, 0, 0, 0.14),0px 2px 16px 1px rgba(0, 0, 0, 0.12)", - "0px 5px 5px -3px rgba(0, 0, 0, 0.2),0px 8px 10px 1px rgba(0, 0, 0, 0.14),0px 3px 14px 2px rgba(0, 0, 0, 0.12)", - "0px 5px 6px -3px rgba(0, 0, 0, 0.2),0px 9px 12px 1px rgba(0, 0, 0, 0.14),0px 3px 16px 2px rgba(0, 0, 0, 0.12)", - "0px 6px 6px -3px rgba(0, 0, 0, 0.2),0px 10px 14px 1px rgba(0, 0, 0, 0.14),0px 4px 18px 3px rgba(0, 0, 0, 0.12)", - "0px 6px 7px -4px rgba(0, 0, 0, 0.2),0px 11px 15px 1px rgba(0, 0, 0, 0.14),0px 4px 20px 3px rgba(0, 0, 0, 0.12)", - "0px 7px 8px -4px rgba(0, 0, 0, 0.2),0px 12px 17px 2px rgba(0, 0, 0, 0.14),0px 5px 22px 4px rgba(0, 0, 0, 0.12)", - "0px 7px 8px -4px rgba(0, 0, 0, 0.2),0px 13px 19px 2px rgba(0, 0, 0, 0.14),0px 5px 24px 4px rgba(0, 0, 0, 0.12)", - "0px 7px 9px -4px rgba(0, 0, 0, 0.2),0px 14px 21px 2px rgba(0, 0, 0, 0.14),0px 5px 26px 4px rgba(0, 0, 0, 0.12)", - "0px 8px 9px -5px rgba(0, 0, 0, 0.2),0px 15px 22px 2px rgba(0, 0, 0, 0.14),0px 6px 28px 5px rgba(0, 0, 0, 0.12)", - "0px 8px 10px -5px rgba(0, 0, 0, 0.2),0px 16px 24px 2px rgba(0, 0, 0, 0.14),0px 6px 30px 5px rgba(0, 0, 0, 0.12)", - "0px 8px 11px -5px rgba(0, 0, 0, 0.2),0px 17px 26px 2px rgba(0, 0, 0, 0.14),0px 6px 32px 5px rgba(0, 0, 0, 0.12)", - "0px 9px 11px -5px rgba(0, 0, 0, 0.2),0px 18px 28px 2px rgba(0, 0, 0, 0.14),0px 7px 34px 6px rgba(0, 0, 0, 0.12)", - "0px 9px 12px -6px rgba(0, 0, 0, 0.2),0px 19px 29px 2px rgba(0, 0, 0, 0.14),0px 7px 36px 6px rgba(0, 0, 0, 0.12)", - "0px 10px 13px -6px rgba(0, 0, 0, 0.2),0px 20px 31px 3px rgba(0, 0, 0, 0.14),0px 8px 38px 7px rgba(0, 0, 0, 0.12)", - "0px 10px 13px -6px rgba(0, 0, 0, 0.2),0px 21px 33px 3px rgba(0, 0, 0, 0.14),0px 8px 40px 7px rgba(0, 0, 0, 0.12)", - "0px 10px 14px -6px rgba(0, 0, 0, 0.2),0px 22px 35px 3px rgba(0, 0, 0, 0.14),0px 8px 42px 7px rgba(0, 0, 0, 0.12)", - "0px 11px 14px -7px rgba(0, 0, 0, 0.2),0px 23px 36px 3px rgba(0, 0, 0, 0.14),0px 9px 44px 8px rgba(0, 0, 0, 0.12)", - "0px 11px 15px -7px rgba(0, 0, 0, 0.2),0px 24px 38px 3px rgba(0, 0, 0, 0.14),0px 9px 46px 8px rgba(0, 0, 0, 0.12)" - ], - "zIndex": { - "default": 1, - "banner": 9500, - "snackbar": 10000, - "dialog": 6000, - "mask": 5000, - "popup": 3000, - "spinner": 9050, - "model": 9000, - "dropdown": 7000, - "ripple": 1, - "elementOnRipple": 2, - "loading": 1000, - "dragging": 2000, - "moreMenu": 999, - "toast": 3000, - "memberListHeader": 100, - "floatButton": 10, - "makeZIndexStackingContext": 1, - "codeEditor": 0 - }, - "size": { - "width": 4, - "height": 4 - },"typography": { - "fontFamily": "Lato, Helvetica, Arial, sans-serif", - "codeFontFamily": "Courier", - "fontSize": 14, - "fontWeightLight": 300, - "fontWeightRegular": 400, - "fontWeightMedium": 500, - "display4": { - "fontSize": "6rem", - "fontWeight": 700, - "lineHeight": "112px" - }, - "display3": { - "fontSize": "3.5rem", - "fontWeight": 700, - "lineHeight": "72px" - }, - "display2": { - "fontSize": "2.8125rem", - "fontWeight": 400, - "lineHeight": "56px" - }, - "display1": { - "fontSize": "2.125rem", - "fontWeight": 400, - "lineHeight": "40px" - }, - "headline2": { - "fontSize": "1.5rem", - "fontWeight": 700, - "lineHeight": "32px" - }, - "headline": { - "fontSize": "1.5rem", - "fontWeight": 400, - "lineHeight": "32px" - }, - "title2": { - "fontSize": "1.25rem", - "fontWeight": 700, - "lineHeight": "28px" - }, - "title1": { - "fontSize": "1.25rem", - "fontWeight": 400, - "lineHeight": "28px" - }, - "subheading2": { - "fontSize": "1rem", - "fontWeight": 700, - "lineHeight": "24px" - }, - "subheading1": { - "fontSize": "1rem", - "fontWeight": 400, - "lineHeight": "24px" - }, - "body2": { - "fontSize": "0.9375rem", - "fontWeight": 700, - "lineHeight": "22px" - }, - "body1": { - "fontSize": "0.9375rem", - "fontWeight": 400, - "lineHeight": "22px" - }, - "caption2": { - "fontSize": "0.75rem", - "fontWeight": 700, - "lineHeight": "16px" - }, - "caption1": { - "fontSize": "0.75rem", - "fontWeight": 400, - "lineHeight": "16px" - }, - "button": { - "fontSize": "0.9375rem", - "fontWeight": 700, - "lineHeight": "20px", - "textTransform": "none" - } - }, - "transitions": { - "easing": { - "easeIn": "cubic-bezier(0.4, 0, 1, 1)", - "easeOut": "cubic-bezier(0.0, 0, 0.2, 1)", - "easeInOut": "cubic-bezier(0.4, 0, 0.2, 1)", - "sharp": "cubic-bezier(0.4, 0, 0.6, 1)" - }, - "duration": { - "shortest": 150, - "shorter": 200, - "short": 250, - "standard": 300, - "complex": 375, - "enteringScreen": 225, - "leavingScreen": 195 - } - } -} diff --git a/packages/ringcentral-widgets/lib/phoneContext/brands/rcBlue/theme.json b/packages/ringcentral-widgets/lib/phoneContext/brands/rcBlue/theme.json deleted file mode 100644 index e07acf770a..0000000000 --- a/packages/ringcentral-widgets/lib/phoneContext/brands/rcBlue/theme.json +++ /dev/null @@ -1,550 +0,0 @@ -{ - "breakpoints": { - "values": { - "xs": 0, - "sm": 641, - "md": 960, - "lg": 1280, - "xl": 1920 - } - }, - "palette": { - "primary": { - "50": "#e1f4fb", - "100": "#b2e3f4", - "200": "#82d1ed", - "300": "#66bffa", - "400": "#34b1e2", - "500": "#6990fd", - "600": "#4475fd", - "700": "#4475fd", - "800": "#2f51b1", - "900": "#005488", - "light": "#6990fd", - "main": "#4475fd", - "dark": "#2f51b1" - }, - "secondary": { - "50": "#fff3e0", - "100": "#ffdfb1", - "200": "#ffca7f", - "300": "#ffb44c", - "400": "#ffa424", - "500": "#ff9f33", - "600": "#ff8800", - "700": "#f97802", - "800": "#b25f00", - "900": "#ea4b04", - "light": "#ff9f33", - "main": "#ff8800", - "dark": "#b25f00" - }, - "semantic": { - "negative": "#f44336", - "positive": "#26a304", - "critical": "#f6ad16", - "neutral": "#616161" - }, - "accent": { - "ash": "#bfbfbf", - "lake": "#69a3eb", - "tiffany": "#22c2d6", - "cateye": "#52d2b1", - "grass": "#bdd655", - "olive": "#4cd964", - "gold": "#edb63c", - "lemon": "#ffd800", - "tomato": "#ff3737", - "indigo": "#4a1e8c", - "purple": "#4A44FD", - "persimmon": "#ff793d", - "black": "#212121", - "red": "#f44336", - "blue": "#4475fd", - "orange": "#FF8800", - "yellow": "#EDB63C", - "green": "#26A304" - }, - "grey": { - "100": "#f5f6fb", - "200": "#EEEEEE", - "400": "#8F98A8", - "500": "#8192AF", - "600": "#737983", - "900": "#212121" - }, - "background": { - "disabled": "rgba(255,55,55,.05)", - "default": "#fff" - }, - "action": { - "hoverOpacity": 0.12, - "active": "#EBF6FA", - "grayLight": "#666666", - "grayDark": "#494949", - "primary": "#066FAC" - }, - "tooltip": { - "dark": "#616161" - }, - "avatar": { - "tomato": "#C93637", - "blueberry": "#5A5ABF", - "oasis": "#04549F", - "gold": "#7A7000", - "sage": "#047C68", - "ash": "#666666", - "persimmon": "#A14B00", - "pear": "#3C7E44", - "brass": "#8E6B2B", - "lake": "#1A70C1", - "red": "#f54c3d", - "orange": "#FF8800", - "yellow": "#F6AD16", - "green": "#299e0b", - "tiffany": "#3096a8", - "primary": "#6990FD", - "purple": "#8c79e7", - "neutral": "#8D93A5", - "global": "#509AC4" - }, - "common": { - "white": "#fff" - }, - "bg": { - "paper": "#FFFFFF", - "light": "#F9F9FA", - "dark": "#F0F1F4", - "primaryLightest": "#F5F6FB", - "primary": "#4475FD", - "secondary": "#FF8800", - "negative": "#f54c3d", - "positive": "#299e0b", - "neutral": "#6C7489", - "critical": "#F6AD16", - "redLight": "#F9EBE9", - "orangeLight": "#FAECDF", - "yellowLight": "#f7edd7", - "greenLight": "#e8f1e8", - "tiffanyLight": "#E8F0F2", - "blueLight": "#EAEEF5", - "purpleLight": "#EDEDF5", - "redLightest": "#fbf5f4", - "orangeLightest": "#fbf5ef", - "yellowLightest": "#f9f6ec", - "greenLightest": "#f3f8f3", - "tiffanyLightest": "#f3f7f8", - "blueLightest": "#F5F6FB", - "purpleLightest": "#f6f6fa", - "buttonDisabled": "#F0F1F4", - "transparentDark": "rgba(66, 73, 92, 0.72)", - "transparentDarkDisabled": "rgba(66, 73, 92, 0.32)", - "primaryLight": "#EAEEF5" - }, - "element": { - "default": "#8D93A5", - "primary": "#4475FD", - "negative": "#f54c3d", - "disabled": "#CED1D9" - }, - "border": { - "default": "#CED1D9", - "primary": "#4475FD", - "negative": "#f54c3d", - "disabled": "#E8E9ED", - "inverse": "#FFFFFF", - "light": "#E8E9ED", - "secondary": "#FF8800", - "redLight": "#F9EBE9", - "dark": "#282B33" - }, - "text": { - "dark": "#282B33", - "default": "#464B59", - "subdued": "#6C7489", - "info": "#4475FD", - "negative": "#c64335", - "positive": "#31841d", - "critical": "#FF8800", - "inverse": "#FFFFFF", - "bgPrimary": "#FFFFFF", - "bgSecondary": "#FFFFFF", - "bgNegative": "#FFFFFF", - "bgPositive": "#FFFFFF", - "bgNeutral": "#FFFFFF", - "hint": "#81899D", - "disabled": "#B5B9C5", - "button": "#4475FD", - "secondaryInfo": "#FF8800" - }, - "icon": { - "subdued": "#81899D", - "default": "#6C7489", - "dark": "#282B33", - "primary": "#4475FD", - "negative": "#f54c3d", - "positive": "#299e0b", - "critical": "#F6AD16", - "secondary": "#FF8800", - "inverse": "#FFFFFF", - "inverseDisabled": "#FFFFFF", - "disabled": "#B5B9C5", - "bookmark": "#4475FD" - }, - "label": { - "red": { - "icon": "#f54c3d", - "text": "#c64335" - }, - "orange": { - "icon": "#FF8800", - "text": "#FF8800" - }, - "yellow": { - "icon": "#F6AD16", - "text": "#8e6b2b" - }, - "green": { - "icon": "#299e0b", - "text": "#31841d" - }, - "tiffany": { - "icon": "#3096a8", - "text": "#367987" - }, - "blue": { - "icon": "#4475FD", - "text": "#4475FD" - }, - "purple": { - "icon": "#8c79e7", - "text": "#7265b3" - }, - "black": { - "icon": "#282B33", - "text": "#282B33" - }, - "red01": "#E6413C", - "red02": "#BE3933", - "orange01": "#CD6E0D", - "orange02": "#A15600", - "yellow01": "#B17D1A", - "yellow02": "#896219", - "green01": "#3C9949", - "green02": "#32773B", - "teal01": "#3093A4", - "teal02": "#2B727F", - "blue01": "#066FAC", - "blue02": "#066FAC", - "purple01": "#8A77E3", - "purple02": "#6C5DAF", - "black02": "#121212" - }, - "globalHeader": { - "bgLight": "#66bffa", - "bgDark": "#4475FD", - "bgTransparent": "rgba(255, 255, 255, 0.16)", - "bgTransparentDisabled": "rgba(255, 255, 255, 0.08)", - "text": "#FFFFFF", - "textHint": "rgba(255, 255, 255, 0.48)", - "icon": "#FFFFFF", - "iconDisabled": "rgba(255, 255, 255, 0.32)", - "border": "#FFFFFF", - "critical": "#F6AD16", - "positive": "rgb(116, 200, 158)" - }, - "header": { - "bgLeft": "#066FAC", - "bgRight": "#509AC4", - "bgOverlay": "rgba(255, 255, 255, 0.16)", - "bgOverlayDisabled": "rgba(255, 255, 255, 0.08)", - "fabBg": "#FFFFFF", - "fabIcon": "#121212", - "border": "transparent", - "divider": "rgba(0, 0, 0, 0.12)", - "focusBorder": "#FFFFFF", - "text": "#FFFFFF", - "textHint": "rgba(255, 255, 255, 0.48)", - "icon": "#FFFFFF", - "iconDisabled": "rgba(255, 255, 255, 0.32)" - }, - "dialHeader": { - "bg": "#066FAC", - "text": "#FFFFFF", - "textHint": "rgba(255, 255, 255, 0.88)", - "icon": "#FFFFFF", - "avatarBg": "#FFFFFF", - "avatarIcon": "#066FAC", - "focusBorder": "#FFFFFF" - }, - "nav": { - "iconDefault": "#121212", - "iconSelected": "#066FAC", - "b01": "#FFFFFF", - "b02": "#F9F9F9", - "line": "#E5E5E5", - "menuBg": "#066FAC", - "menuText": "#FFFFFF", - "f01": "#757575", - "f02": "#666666", - "f03": "#494949", - "f04": "#121212", - "bookmark": "#066FAC", - "mention": "#FF8800", - "ctlDefault": "#939393", - "ctlSelected": "#066FAC" - }, - "tab": { - "default": "#121212", - "selected": "#066FAC" - }, - "subAction": "#066FAC", - "umi": { - "bg": "#666666", - "text": "#FFFFFF", - "mentioned": "#FF8800" - }, - "content": { - "brand": "#066FAC" - }, - "interactive": { - "f01": "#066FAC", - "b01": "#E6F2F8", - "b02": "#066FAC" - }, - "success": { - "b01": "#F0FCEF", - "b02": "#CEF4CE", - "b03": "#3C9949", - "b04": "#368541", - "b05": "#3C9949", - "f01": "#CEF4CE", - "f02": "#32773B", - "f11": "#46BE59" - }, - "warning": { - "b01": "#FFF7EB", - "b02": "#FFE7C1", - "b03": "#F6AD16", - "f01": "#F6AD16", - "f02": "#896219", - "f11": "#F6AD16" - }, - "danger": { - "b01": "#FFF7F5", - "b02": "#FFE5E0", - "b03": "#E6413C", - "b04": "#D63E39", - "f01": "#FFE5E0", - "f02": "#BE3933", - "f11": "#F88878" - }, - "highlight": { - "b01": "#FF8800", - "b02": "#FFDFB1", - "b03": "#FF8800", - "f01": "#121212", - "f02": "#FF8800" - }, - "informative": { - "b01": "#F6F9FC", - "f01": "#E3EBF4", - "f02": "#066FAC" - }, - "neutral": { - "f01": "#FFFFFF", - "f02": "#939393", - "f03": "#757575", - "f04": "#666666", - "f05": "#494949", - "f06": "#121212", - "f07": "#121212", - "f11": "#FFFFFF", - "elevation": "#FFFFFF", - "transparent": "transparent", - "b01": "#FFFFFF", - "b02": "#F9F9F9", - "b03": "#F3F3F3", - "b04": "#666666", - "b05": "#494949", - "b06": "#000000", - "l01": "#FFFFFF", - "l02": "#E5E5E5", - "l03": "#C7C7C7", - "l04": "#666666" - }, - "disabled": { - "f01": "#FFFFFF", - "f02": "#B9B9B9", - "b01": "#B9B9B9" - }, - "presence": { - "busy": "#E6413C", - "available": "#3C9949", - "invisible": "#939393" - }, - "highContrast": "transparent" - }, - "radius": { - "circle": "50%", - "zero": "0px", - "sm": "2px", - "md": "3px", - "lg": "4px", - "xl": "8px", - "xxl": "16px", - "round": "100vw" - }, - "shape": { - "borderRadius": 4 - }, - "shadows": [ - "none", - "0 1px 3px 0 rgba(0, 0, 0, 0.2), 0 1px 1px 0 rgba(0, 0, 0, 0.14), 0 2px 1px -1px rgba(0, 0, 0, 0.12)", - "0px 1px 5px 0px rgba(0, 0, 0, 0.2),0px 2px 2px 0px rgba(0, 0, 0, 0.14),0px 3px 1px -2px rgba(0, 0, 0, 0.12)", - "0px 1px 8px 0px rgba(0, 0, 0, 0.2),0px 3px 4px 0px rgba(0, 0, 0, 0.14),0px 3px 3px -2px rgba(0, 0, 0, 0.12)", - "0px 2px 4px -1px rgba(0, 0, 0, 0.2),0px 4px 5px 0px rgba(0, 0, 0, 0.14),0px 1px 10px 0px rgba(0, 0, 0, 0.12)", - "0px 3px 5px -1px rgba(0, 0, 0, 0.2),0px 5px 8px 0px rgba(0, 0, 0, 0.14),0px 1px 14px 0px rgba(0, 0, 0, 0.12)", - "0px 3px 5px -1px rgba(0, 0, 0, 0.2),0px 6px 10px 0px rgba(0, 0, 0, 0.14),0px 1px 18px 0px rgba(0, 0, 0, 0.12)", - "0px 4px 5px -2px rgba(0, 0, 0, 0.2),0px 7px 10px 1px rgba(0, 0, 0, 0.14),0px 2px 16px 1px rgba(0, 0, 0, 0.12)", - "0px 5px 5px -3px rgba(0, 0, 0, 0.2),0px 8px 10px 1px rgba(0, 0, 0, 0.14),0px 3px 14px 2px rgba(0, 0, 0, 0.12)", - "0px 5px 6px -3px rgba(0, 0, 0, 0.2),0px 9px 12px 1px rgba(0, 0, 0, 0.14),0px 3px 16px 2px rgba(0, 0, 0, 0.12)", - "0px 6px 6px -3px rgba(0, 0, 0, 0.2),0px 10px 14px 1px rgba(0, 0, 0, 0.14),0px 4px 18px 3px rgba(0, 0, 0, 0.12)", - "0px 6px 7px -4px rgba(0, 0, 0, 0.2),0px 11px 15px 1px rgba(0, 0, 0, 0.14),0px 4px 20px 3px rgba(0, 0, 0, 0.12)", - "0px 7px 8px -4px rgba(0, 0, 0, 0.2),0px 12px 17px 2px rgba(0, 0, 0, 0.14),0px 5px 22px 4px rgba(0, 0, 0, 0.12)", - "0px 7px 8px -4px rgba(0, 0, 0, 0.2),0px 13px 19px 2px rgba(0, 0, 0, 0.14),0px 5px 24px 4px rgba(0, 0, 0, 0.12)", - "0px 7px 9px -4px rgba(0, 0, 0, 0.2),0px 14px 21px 2px rgba(0, 0, 0, 0.14),0px 5px 26px 4px rgba(0, 0, 0, 0.12)", - "0px 8px 9px -5px rgba(0, 0, 0, 0.2),0px 15px 22px 2px rgba(0, 0, 0, 0.14),0px 6px 28px 5px rgba(0, 0, 0, 0.12)", - "0px 8px 10px -5px rgba(0, 0, 0, 0.2),0px 16px 24px 2px rgba(0, 0, 0, 0.14),0px 6px 30px 5px rgba(0, 0, 0, 0.12)", - "0px 8px 11px -5px rgba(0, 0, 0, 0.2),0px 17px 26px 2px rgba(0, 0, 0, 0.14),0px 6px 32px 5px rgba(0, 0, 0, 0.12)", - "0px 9px 11px -5px rgba(0, 0, 0, 0.2),0px 18px 28px 2px rgba(0, 0, 0, 0.14),0px 7px 34px 6px rgba(0, 0, 0, 0.12)", - "0px 9px 12px -6px rgba(0, 0, 0, 0.2),0px 19px 29px 2px rgba(0, 0, 0, 0.14),0px 7px 36px 6px rgba(0, 0, 0, 0.12)", - "0px 10px 13px -6px rgba(0, 0, 0, 0.2),0px 20px 31px 3px rgba(0, 0, 0, 0.14),0px 8px 38px 7px rgba(0, 0, 0, 0.12)", - "0px 10px 13px -6px rgba(0, 0, 0, 0.2),0px 21px 33px 3px rgba(0, 0, 0, 0.14),0px 8px 40px 7px rgba(0, 0, 0, 0.12)", - "0px 10px 14px -6px rgba(0, 0, 0, 0.2),0px 22px 35px 3px rgba(0, 0, 0, 0.14),0px 8px 42px 7px rgba(0, 0, 0, 0.12)", - "0px 11px 14px -7px rgba(0, 0, 0, 0.2),0px 23px 36px 3px rgba(0, 0, 0, 0.14),0px 9px 44px 8px rgba(0, 0, 0, 0.12)", - "0px 11px 15px -7px rgba(0, 0, 0, 0.2),0px 24px 38px 3px rgba(0, 0, 0, 0.14),0px 9px 46px 8px rgba(0, 0, 0, 0.12)" - ], - "zIndex": { - "default": 1, - "banner": 9500, - "snackbar": 10000, - "dialog": 6000, - "mask": 5000, - "popup": 3000, - "spinner": 9050, - "model": 9000, - "dropdown": 7000, - "ripple": 1, - "elementOnRipple": 2, - "loading": 1000, - "dragging": 2000, - "moreMenu": 999, - "toast": 3000, - "memberListHeader": 100, - "floatButton": 10, - "makeZIndexStackingContext": 1, - "codeEditor": 0 - }, - "typography": { - "fontFamily": "Lato, Helvetica, Arial, sans-serif", - "codeFontFamily": "Courier", - "fontSize": 14, - "fontWeightLight": 300, - "fontWeightRegular": 400, - "fontWeightMedium": 500, - "display4": { - "fontSize": "6rem", - "fontWeight": 700, - "lineHeight": "112px" - }, - "display3": { - "fontSize": "3.5rem", - "fontWeight": 700, - "lineHeight": "72px" - }, - "display2": { - "fontSize": "2.8125rem", - "fontWeight": 400, - "lineHeight": "56px" - }, - "display1": { - "fontSize": "2.125rem", - "fontWeight": 400, - "lineHeight": "40px" - }, - "headline2": { - "fontSize": "1.5rem", - "fontWeight": 700, - "lineHeight": "32px" - }, - "headline": { - "fontSize": "1.5rem", - "fontWeight": 400, - "lineHeight": "32px" - }, - "title2": { - "fontSize": "1.25rem", - "fontWeight": 700, - "lineHeight": "28px" - }, - "title1": { - "fontSize": "1.25rem", - "fontWeight": 400, - "lineHeight": "28px" - }, - "subheading2": { - "fontSize": "1rem", - "fontWeight": 700, - "lineHeight": "24px" - }, - "subheading1": { - "fontSize": "1rem", - "fontWeight": 400, - "lineHeight": "24px" - }, - "body2": { - "fontSize": "0.9375rem", - "fontWeight": 700, - "lineHeight": "22px" - }, - "body1": { - "fontSize": "0.9375rem", - "fontWeight": 400, - "lineHeight": "22px" - }, - "caption2": { - "fontSize": "0.75rem", - "fontWeight": 700, - "lineHeight": "16px" - }, - "caption1": { - "fontSize": "0.75rem", - "fontWeight": 400, - "lineHeight": "16px" - }, - "button": { - "fontSize": "0.9375rem", - "fontWeight": 700, - "lineHeight": "20px", - "textTransform": "none" - } - }, - "transitions": { - "easing": { - "easeIn": "cubic-bezier(0.4, 0, 1, 1)", - "easeOut": "cubic-bezier(0.0, 0, 0.2, 1)", - "easeInOut": "cubic-bezier(0.4, 0, 0.2, 1)", - "sharp": "cubic-bezier(0.4, 0, 0.6, 1)" - }, - "duration": { - "shortest": 150, - "shorter": 200, - "short": 250, - "standard": 300, - "complex": 375, - "enteringScreen": 225, - "leavingScreen": 195 - } - } -} diff --git a/packages/ringcentral-widgets/lib/phoneContext/brands/rcJupiterBlue/theme.json b/packages/ringcentral-widgets/lib/phoneContext/brands/rcJupiterBlue/theme.json deleted file mode 100644 index 8ba5931c1d..0000000000 --- a/packages/ringcentral-widgets/lib/phoneContext/brands/rcJupiterBlue/theme.json +++ /dev/null @@ -1,550 +0,0 @@ -{ - "breakpoints": { - "values": { - "xs": 0, - "sm": 641, - "md": 960, - "lg": 1280, - "xl": 1920 - } - }, - "palette": { - "primary": { - "50": "#e1f4fb", - "100": "#b2e3f4", - "200": "#82d1ed", - "300": "#66bffa", - "400": "#34b1e2", - "500": "#6990fd", - "600": "#4475fd", - "700": "#4475fd", - "800": "#2f51b1", - "900": "#005488", - "light": "#6990fd", - "main": "#4475fd", - "dark": "#2f51b1" - }, - "secondary": { - "50": "#fff3e0", - "100": "#ffdfb1", - "200": "#ffca7f", - "300": "#ffb44c", - "400": "#ffa424", - "500": "#ff9f33", - "600": "#ff8800", - "700": "#f97802", - "800": "#b25f00", - "900": "#ea4b04", - "light": "#ff9f33", - "main": "#ff8800", - "dark": "#b25f00" - }, - "semantic": { - "negative": "#f44336", - "positive": "#26a304", - "critical": "#f6ad16", - "neutral": "#616161" - }, - "accent": { - "ash": "#bfbfbf", - "lake": "#69a3eb", - "tiffany": "#22c2d6", - "cateye": "#52d2b1", - "grass": "#bdd655", - "olive": "#4cd964", - "gold": "#edb63c", - "lemon": "#ffd800", - "tomato": "#ff3737", - "indigo": "#4a1e8c", - "purple": "#4A44FD", - "persimmon": "#ff793d", - "black": "#212121", - "red": "#f44336", - "blue": "#4475fd", - "orange": "#FF8800", - "yellow": "#EDB63C", - "green": "#26A304" - }, - "grey": { - "100": "#f5f6fb", - "200": "#EEEEEE", - "400": "#8F98A8", - "500": "#8192AF", - "600": "#737983", - "900": "#212121" - }, - "background": { - "disabled": "rgba(255,55,55,.05)", - "default": "#fff" - }, - "action": { - "hoverOpacity": 0.12, - "active": "#EBF6FA", - "grayLight": "#656C80", - "grayDark": "#464B59", - "primary": "#2559E4" - }, - "tooltip": { - "dark": "#616161" - }, - "avatar": { - "tomato": "#C93637", - "blueberry": "#5A5ABF", - "oasis": "#04549F", - "gold": "#7A7000", - "sage": "#047C68", - "ash": "#666666", - "persimmon": "#A14B00", - "pear": "#3C7E44", - "brass": "#8E6B2B", - "lake": "#1A70C1", - "red": "#f54c3d", - "orange": "#FF8800", - "yellow": "#F6AD16", - "green": "#299e0b", - "tiffany": "#3096a8", - "primary": "#6990FD", - "purple": "#8c79e7", - "neutral": "#8D93A5", - "global": "#638EFF" - }, - "common": { - "white": "#fff" - }, - "bg": { - "paper": "#FFFFFF", - "light": "#F9F9FA", - "dark": "#F0F1F4", - "primaryLightest": "#F5F6FB", - "primary": "#4475FD", - "secondary": "#FF8800", - "negative": "#f54c3d", - "positive": "#299e0b", - "neutral": "#6C7489", - "critical": "#F6AD16", - "redLight": "#F9EBE9", - "orangeLight": "#FAECDF", - "yellowLight": "#f7edd7", - "greenLight": "#e8f1e8", - "tiffanyLight": "#E8F0F2", - "blueLight": "#EAEEF5", - "purpleLight": "#EDEDF5", - "redLightest": "#fbf5f4", - "orangeLightest": "#fbf5ef", - "yellowLightest": "#f9f6ec", - "greenLightest": "#f3f8f3", - "tiffanyLightest": "#f3f7f8", - "blueLightest": "#F5F6FB", - "purpleLightest": "#f6f6fa", - "buttonDisabled": "#F0F1F4", - "transparentDark": "rgba(66, 73, 92, 0.72)", - "transparentDarkDisabled": "rgba(66, 73, 92, 0.32)", - "primaryLight": "#EAEEF5" - }, - "element": { - "default": "#8D93A5", - "primary": "#4475FD", - "negative": "#f54c3d", - "disabled": "#CED1D9" - }, - "border": { - "default": "#CED1D9", - "primary": "#4475FD", - "negative": "#f54c3d", - "disabled": "#E8E9ED", - "inverse": "#FFFFFF", - "light": "#E8E9ED", - "secondary": "#FF8800", - "redLight": "#F9EBE9", - "dark": "#282B33" - }, - "text": { - "dark": "#282B33", - "default": "#464B59", - "subdued": "#6C7489", - "info": "#4475FD", - "negative": "#c64335", - "positive": "#31841d", - "critical": "#FF8800", - "inverse": "#FFFFFF", - "bgPrimary": "#FFFFFF", - "bgSecondary": "#FFFFFF", - "bgNegative": "#FFFFFF", - "bgPositive": "#FFFFFF", - "bgNeutral": "#FFFFFF", - "hint": "#81899D", - "disabled": "#B5B9C5", - "button": "#4475FD", - "secondaryInfo": "#FF8800" - }, - "icon": { - "subdued": "#81899D", - "default": "#6C7489", - "dark": "#282B33", - "primary": "#4475FD", - "negative": "#f54c3d", - "positive": "#299e0b", - "critical": "#F6AD16", - "secondary": "#FF8800", - "inverse": "#FFFFFF", - "inverseDisabled": "#FFFFFF", - "disabled": "#B5B9C5", - "bookmark": "#4475FD" - }, - "label": { - "red": { - "icon": "#f54c3d", - "text": "#c64335" - }, - "orange": { - "icon": "#FF8800", - "text": "#FF8800" - }, - "yellow": { - "icon": "#F6AD16", - "text": "#8e6b2b" - }, - "green": { - "icon": "#299e0b", - "text": "#31841d" - }, - "tiffany": { - "icon": "#3096a8", - "text": "#367987" - }, - "blue": { - "icon": "#4475FD", - "text": "#4475FD" - }, - "purple": { - "icon": "#8c79e7", - "text": "#7265b3" - }, - "black": { - "icon": "#282B33", - "text": "#282B33" - }, - "red01": "#E6413C", - "red02": "#BE3933", - "orange01": "#CD6E0D", - "orange02": "#A15600", - "yellow01": "#B17D1A", - "yellow02": "#896219", - "green01": "#3C9949", - "green02": "#32773B", - "teal01": "#3093A4", - "teal02": "#2B727F", - "blue01": "#2559E4", - "blue02": "#2559E4", - "purple01": "#8A77E3", - "purple02": "#6C5DAF", - "black02": "#16181D" - }, - "globalHeader": { - "bgLight": "#66bffa", - "bgDark": "#4475FD", - "bgTransparent": "rgba(255, 255, 255, 0.16)", - "bgTransparentDisabled": "rgba(255, 255, 255, 0.08)", - "text": "#FFFFFF", - "textHint": "rgba(255, 255, 255, 0.48)", - "icon": "#FFFFFF", - "iconDisabled": "rgba(255, 255, 255, 0.32)", - "border": "#FFFFFF", - "critical": "#F6AD16", - "positive": "rgb(116, 200, 158)" - }, - "header": { - "bgLeft": "#2559E4", - "bgRight": "#638EFF", - "bgOverlay": "rgba(255, 255, 255, 0.16)", - "bgOverlayDisabled": "rgba(255, 255, 255, 0.08)", - "fabBg": "#FFFFFF", - "fabIcon": "#16181D", - "border": "transparent", - "divider": "rgba(0, 0, 0, 0.12)", - "focusBorder": "#FFFFFF", - "text": "#FFFFFF", - "textHint": "rgba(255, 255, 255, 0.48)", - "icon": "#FFFFFF", - "iconDisabled": "rgba(255, 255, 255, 0.32)" - }, - "dialHeader": { - "bg": "#2559E4", - "text": "#FFFFFF", - "textHint": "rgba(255, 255, 255, 0.88)", - "icon": "#FFFFFF", - "avatarBg": "#FFFFFF", - "avatarIcon": "#2559E4", - "focusBorder": "#FFFFFF" - }, - "nav": { - "iconDefault": "#16181D", - "iconSelected": "#2559E4", - "b01": "#FFFFFF", - "b02": "#F5F6FB", - "line": "#E8E9ED", - "menuBg": "#2559E4", - "menuText": "#FFFFFF", - "f01": "#6D768D", - "f02": "#656C80", - "f03": "#464B59", - "f04": "#16181D", - "bookmark": "#2559E4", - "mention": "#FF8800", - "ctlDefault": "#8D93A5", - "ctlSelected": "#2559E4" - }, - "tab": { - "default": "#16181D", - "selected": "#2559E4" - }, - "subAction": "#2559E4", - "umi": { - "bg": "#656C80", - "text": "#FFFFFF", - "mentioned": "#FF8800" - }, - "content": { - "brand": "#2559E4" - }, - "interactive": { - "f01": "#2559E4", - "b01": "#F5F6FB", - "b02": "#2559E4" - }, - "success": { - "b01": "#F0FCEF", - "b02": "#CEF4CE", - "b03": "#3C9949", - "b04": "#368541", - "b05": "#3C9949", - "f01": "#CEF4CE", - "f02": "#32773B", - "f11": "#46BE59" - }, - "warning": { - "b01": "#FFF7EB", - "b02": "#FFE7C1", - "b03": "#F6AD16", - "f01": "#F6AD16", - "f02": "#896219", - "f11": "#F6AD16" - }, - "danger": { - "b01": "#FFF7F5", - "b02": "#FFE5E0", - "b03": "#E6413C", - "b04": "#D63E39", - "f01": "#FFE5E0", - "f02": "#BE3933", - "f11": "#F88878" - }, - "highlight": { - "b01": "#FF8800", - "b02": "#FFDFB1", - "b03": "#FF8800", - "f01": "#16181D", - "f02": "#FF8800" - }, - "informative": { - "b01": "#F5F6FB", - "f01": "#E3EAFC", - "f02": "#2559E4" - }, - "neutral": { - "f01": "#FFFFFF", - "f02": "#8D93A5", - "f03": "#6D768D", - "f04": "#656C80", - "f05": "#464B59", - "f06": "#16181D", - "f07": "#16181D", - "f11": "#FFFFFF", - "elevation": "#FFFFFF", - "transparent": "transparent", - "b01": "#FFFFFF", - "b02": "#F9F9FA", - "b03": "#F0F1F4", - "b04": "#656C80", - "b05": "#464B59", - "b06": "#000000", - "l01": "#FFFFFF", - "l02": "#E8E9ED", - "l03": "#CED1D9", - "l04": "#656C80" - }, - "disabled": { - "f01": "#FFFFFF", - "f02": "#B5B9C5", - "b01": "#B5B9C5" - }, - "presence": { - "busy": "#E6413C", - "available": "#3C9949", - "invisible": "#8D93A5" - }, - "highContrast": "transparent" - }, - "radius": { - "circle": "50%", - "zero": "0px", - "sm": "2px", - "md": "3px", - "lg": "4px", - "xl": "8px", - "xxl": "16px", - "round": "100vw" - }, - "shape": { - "borderRadius": 4 - }, - "shadows": [ - "none", - "0 1px 3px 0 rgba(0, 0, 0, 0.2), 0 1px 1px 0 rgba(0, 0, 0, 0.14), 0 2px 1px -1px rgba(0, 0, 0, 0.12)", - "0px 1px 5px 0px rgba(0, 0, 0, 0.2),0px 2px 2px 0px rgba(0, 0, 0, 0.14),0px 3px 1px -2px rgba(0, 0, 0, 0.12)", - "0px 1px 8px 0px rgba(0, 0, 0, 0.2),0px 3px 4px 0px rgba(0, 0, 0, 0.14),0px 3px 3px -2px rgba(0, 0, 0, 0.12)", - "0px 2px 4px -1px rgba(0, 0, 0, 0.2),0px 4px 5px 0px rgba(0, 0, 0, 0.14),0px 1px 10px 0px rgba(0, 0, 0, 0.12)", - "0px 3px 5px -1px rgba(0, 0, 0, 0.2),0px 5px 8px 0px rgba(0, 0, 0, 0.14),0px 1px 14px 0px rgba(0, 0, 0, 0.12)", - "0px 3px 5px -1px rgba(0, 0, 0, 0.2),0px 6px 10px 0px rgba(0, 0, 0, 0.14),0px 1px 18px 0px rgba(0, 0, 0, 0.12)", - "0px 4px 5px -2px rgba(0, 0, 0, 0.2),0px 7px 10px 1px rgba(0, 0, 0, 0.14),0px 2px 16px 1px rgba(0, 0, 0, 0.12)", - "0px 5px 5px -3px rgba(0, 0, 0, 0.2),0px 8px 10px 1px rgba(0, 0, 0, 0.14),0px 3px 14px 2px rgba(0, 0, 0, 0.12)", - "0px 5px 6px -3px rgba(0, 0, 0, 0.2),0px 9px 12px 1px rgba(0, 0, 0, 0.14),0px 3px 16px 2px rgba(0, 0, 0, 0.12)", - "0px 6px 6px -3px rgba(0, 0, 0, 0.2),0px 10px 14px 1px rgba(0, 0, 0, 0.14),0px 4px 18px 3px rgba(0, 0, 0, 0.12)", - "0px 6px 7px -4px rgba(0, 0, 0, 0.2),0px 11px 15px 1px rgba(0, 0, 0, 0.14),0px 4px 20px 3px rgba(0, 0, 0, 0.12)", - "0px 7px 8px -4px rgba(0, 0, 0, 0.2),0px 12px 17px 2px rgba(0, 0, 0, 0.14),0px 5px 22px 4px rgba(0, 0, 0, 0.12)", - "0px 7px 8px -4px rgba(0, 0, 0, 0.2),0px 13px 19px 2px rgba(0, 0, 0, 0.14),0px 5px 24px 4px rgba(0, 0, 0, 0.12)", - "0px 7px 9px -4px rgba(0, 0, 0, 0.2),0px 14px 21px 2px rgba(0, 0, 0, 0.14),0px 5px 26px 4px rgba(0, 0, 0, 0.12)", - "0px 8px 9px -5px rgba(0, 0, 0, 0.2),0px 15px 22px 2px rgba(0, 0, 0, 0.14),0px 6px 28px 5px rgba(0, 0, 0, 0.12)", - "0px 8px 10px -5px rgba(0, 0, 0, 0.2),0px 16px 24px 2px rgba(0, 0, 0, 0.14),0px 6px 30px 5px rgba(0, 0, 0, 0.12)", - "0px 8px 11px -5px rgba(0, 0, 0, 0.2),0px 17px 26px 2px rgba(0, 0, 0, 0.14),0px 6px 32px 5px rgba(0, 0, 0, 0.12)", - "0px 9px 11px -5px rgba(0, 0, 0, 0.2),0px 18px 28px 2px rgba(0, 0, 0, 0.14),0px 7px 34px 6px rgba(0, 0, 0, 0.12)", - "0px 9px 12px -6px rgba(0, 0, 0, 0.2),0px 19px 29px 2px rgba(0, 0, 0, 0.14),0px 7px 36px 6px rgba(0, 0, 0, 0.12)", - "0px 10px 13px -6px rgba(0, 0, 0, 0.2),0px 20px 31px 3px rgba(0, 0, 0, 0.14),0px 8px 38px 7px rgba(0, 0, 0, 0.12)", - "0px 10px 13px -6px rgba(0, 0, 0, 0.2),0px 21px 33px 3px rgba(0, 0, 0, 0.14),0px 8px 40px 7px rgba(0, 0, 0, 0.12)", - "0px 10px 14px -6px rgba(0, 0, 0, 0.2),0px 22px 35px 3px rgba(0, 0, 0, 0.14),0px 8px 42px 7px rgba(0, 0, 0, 0.12)", - "0px 11px 14px -7px rgba(0, 0, 0, 0.2),0px 23px 36px 3px rgba(0, 0, 0, 0.14),0px 9px 44px 8px rgba(0, 0, 0, 0.12)", - "0px 11px 15px -7px rgba(0, 0, 0, 0.2),0px 24px 38px 3px rgba(0, 0, 0, 0.14),0px 9px 46px 8px rgba(0, 0, 0, 0.12)" - ], - "zIndex": { - "default": 1, - "banner": 9500, - "snackbar": 10000, - "dialog": 6000, - "mask": 5000, - "popup": 3000, - "spinner": 9050, - "model": 9000, - "dropdown": 7000, - "ripple": 1, - "elementOnRipple": 2, - "loading": 1000, - "dragging": 2000, - "moreMenu": 999, - "toast": 3000, - "memberListHeader": 100, - "floatButton": 10, - "makeZIndexStackingContext": 1, - "codeEditor": 0 - }, - "typography": { - "fontFamily": "Lato, Helvetica, Arial, sans-serif", - "codeFontFamily": "Courier", - "fontSize": 14, - "fontWeightLight": 300, - "fontWeightRegular": 400, - "fontWeightMedium": 500, - "display4": { - "fontSize": "6rem", - "fontWeight": 700, - "lineHeight": "112px" - }, - "display3": { - "fontSize": "3.5rem", - "fontWeight": 700, - "lineHeight": "72px" - }, - "display2": { - "fontSize": "2.8125rem", - "fontWeight": 400, - "lineHeight": "56px" - }, - "display1": { - "fontSize": "2.125rem", - "fontWeight": 400, - "lineHeight": "40px" - }, - "headline2": { - "fontSize": "1.5rem", - "fontWeight": 700, - "lineHeight": "32px" - }, - "headline": { - "fontSize": "1.5rem", - "fontWeight": 400, - "lineHeight": "32px" - }, - "title2": { - "fontSize": "1.25rem", - "fontWeight": 700, - "lineHeight": "28px" - }, - "title1": { - "fontSize": "1.25rem", - "fontWeight": 400, - "lineHeight": "28px" - }, - "subheading2": { - "fontSize": "1rem", - "fontWeight": 700, - "lineHeight": "24px" - }, - "subheading1": { - "fontSize": "1rem", - "fontWeight": 400, - "lineHeight": "24px" - }, - "body2": { - "fontSize": "0.9375rem", - "fontWeight": 700, - "lineHeight": "22px" - }, - "body1": { - "fontSize": "0.9375rem", - "fontWeight": 400, - "lineHeight": "22px" - }, - "caption2": { - "fontSize": "0.75rem", - "fontWeight": 700, - "lineHeight": "16px" - }, - "caption1": { - "fontSize": "0.75rem", - "fontWeight": 400, - "lineHeight": "16px" - }, - "button": { - "fontSize": "0.9375rem", - "fontWeight": 700, - "lineHeight": "20px", - "textTransform": "none" - } - }, - "transitions": { - "easing": { - "easeIn": "cubic-bezier(0.4, 0, 1, 1)", - "easeOut": "cubic-bezier(0.0, 0, 0.2, 1)", - "easeInOut": "cubic-bezier(0.4, 0, 0.2, 1)", - "sharp": "cubic-bezier(0.4, 0, 0.6, 1)" - }, - "duration": { - "shortest": 150, - "shorter": 200, - "short": 250, - "standard": 300, - "complex": 375, - "enteringScreen": 225, - "leavingScreen": 195 - } - } -} diff --git a/packages/ringcentral-widgets/lib/phoneContext/brands/telusRich/theme.json b/packages/ringcentral-widgets/lib/phoneContext/brands/telusRich/theme.json deleted file mode 100644 index 2c02c976d0..0000000000 --- a/packages/ringcentral-widgets/lib/phoneContext/brands/telusRich/theme.json +++ /dev/null @@ -1,550 +0,0 @@ -{ - "breakpoints": { - "values": { - "xs": 0, - "sm": 641, - "md": 960, - "lg": 1280, - "xl": 1920 - } - }, - "palette": { - "primary": { - "50": "#e1f4fb", - "100": "#b2e3f4", - "200": "#82d1ed", - "300": "#66bffa", - "400": "#34b1e2", - "500": "#6990fd", - "600": "#4475fd", - "700": "#4475fd", - "800": "#2f51b1", - "900": "#005488", - "light": "#6990fd", - "main": "#4475fd", - "dark": "#2f51b1" - }, - "secondary": { - "50": "#fff3e0", - "100": "#ffdfb1", - "200": "#ffca7f", - "300": "#ffb44c", - "400": "#ffa424", - "500": "#ff9f33", - "600": "#ff8800", - "700": "#f97802", - "800": "#b25f00", - "900": "#ea4b04", - "light": "#ff9f33", - "main": "#ff8800", - "dark": "#b25f00" - }, - "semantic": { - "negative": "#f44336", - "positive": "#26a304", - "critical": "#f6ad16", - "neutral": "#616161" - }, - "accent": { - "ash": "#bfbfbf", - "lake": "#69a3eb", - "tiffany": "#22c2d6", - "cateye": "#52d2b1", - "grass": "#bdd655", - "olive": "#4cd964", - "gold": "#edb63c", - "lemon": "#ffd800", - "tomato": "#ff3737", - "indigo": "#4a1e8c", - "purple": "#4A44FD", - "persimmon": "#ff793d", - "black": "#212121", - "red": "#f44336", - "blue": "#4475fd", - "orange": "#FF8800", - "yellow": "#EDB63C", - "green": "#26A304" - }, - "grey": { - "100": "#f5f6fb", - "200": "#EEEEEE", - "400": "#8F98A8", - "500": "#8192AF", - "600": "#737983", - "900": "#212121" - }, - "background": { - "disabled": "rgba(255,55,55,.05)", - "default": "#fff" - }, - "action": { - "hoverOpacity": 0.12, - "active": "#EBF6FA", - "grayLight": "#666666", - "grayDark": "#494949", - "primary": "#2B8000" - }, - "tooltip": { - "dark": "#616161" - }, - "avatar": { - "tomato": "#C93637", - "blueberry": "#5A5ABF", - "oasis": "#04549F", - "gold": "#7A7000", - "sage": "#047C68", - "ash": "#666666", - "persimmon": "#A14B00", - "pear": "#3C7E44", - "brass": "#8E6B2B", - "lake": "#1A70C1", - "red": "#f54c3d", - "orange": "#FF8800", - "yellow": "#F6AD16", - "green": "#299e0b", - "tiffany": "#3096a8", - "primary": "#6990FD", - "purple": "#8c79e7", - "neutral": "#8D93A5", - "global": "#6AA64C" - }, - "common": { - "white": "#fff" - }, - "bg": { - "paper": "#FFFFFF", - "light": "#F9F9FA", - "dark": "#F0F1F4", - "primaryLightest": "#F5F6FB", - "primary": "#4475FD", - "secondary": "#FF8800", - "negative": "#f54c3d", - "positive": "#299e0b", - "neutral": "#6C7489", - "critical": "#F6AD16", - "redLight": "#F9EBE9", - "orangeLight": "#FAECDF", - "yellowLight": "#f7edd7", - "greenLight": "#e8f1e8", - "tiffanyLight": "#E8F0F2", - "blueLight": "#EAEEF5", - "purpleLight": "#EDEDF5", - "redLightest": "#fbf5f4", - "orangeLightest": "#fbf5ef", - "yellowLightest": "#f9f6ec", - "greenLightest": "#f3f8f3", - "tiffanyLightest": "#f3f7f8", - "blueLightest": "#F5F6FB", - "purpleLightest": "#f6f6fa", - "buttonDisabled": "#F0F1F4", - "transparentDark": "rgba(66, 73, 92, 0.72)", - "transparentDarkDisabled": "rgba(66, 73, 92, 0.32)", - "primaryLight": "#EAEEF5" - }, - "element": { - "default": "#8D93A5", - "primary": "#4475FD", - "negative": "#f54c3d", - "disabled": "#CED1D9" - }, - "border": { - "default": "#CED1D9", - "primary": "#4475FD", - "negative": "#f54c3d", - "disabled": "#E8E9ED", - "inverse": "#FFFFFF", - "light": "#E8E9ED", - "secondary": "#FF8800", - "redLight": "#F9EBE9", - "dark": "#282B33" - }, - "text": { - "dark": "#282B33", - "default": "#464B59", - "subdued": "#6C7489", - "info": "#4475FD", - "negative": "#c64335", - "positive": "#31841d", - "critical": "#FF8800", - "inverse": "#FFFFFF", - "bgPrimary": "#FFFFFF", - "bgSecondary": "#FFFFFF", - "bgNegative": "#FFFFFF", - "bgPositive": "#FFFFFF", - "bgNeutral": "#FFFFFF", - "hint": "#81899D", - "disabled": "#B5B9C5", - "button": "#4475FD", - "secondaryInfo": "#FF8800" - }, - "icon": { - "subdued": "#81899D", - "default": "#6C7489", - "dark": "#282B33", - "primary": "#4475FD", - "negative": "#f54c3d", - "positive": "#299e0b", - "critical": "#F6AD16", - "secondary": "#FF8800", - "inverse": "#FFFFFF", - "inverseDisabled": "#FFFFFF", - "disabled": "#B5B9C5", - "bookmark": "#4475FD" - }, - "label": { - "red": { - "icon": "#f54c3d", - "text": "#c64335" - }, - "orange": { - "icon": "#FF8800", - "text": "#FF8800" - }, - "yellow": { - "icon": "#F6AD16", - "text": "#8e6b2b" - }, - "green": { - "icon": "#299e0b", - "text": "#31841d" - }, - "tiffany": { - "icon": "#3096a8", - "text": "#367987" - }, - "blue": { - "icon": "#4475FD", - "text": "#4475FD" - }, - "purple": { - "icon": "#8c79e7", - "text": "#7265b3" - }, - "black": { - "icon": "#282B33", - "text": "#282B33" - }, - "red01": "#E6413C", - "red02": "#BE3933", - "orange01": "#CD6E0D", - "orange02": "#A15600", - "yellow01": "#B17D1A", - "yellow02": "#896219", - "green01": "#3C9949", - "green02": "#32773B", - "teal01": "#3093A4", - "teal02": "#2B727F", - "blue01": "#066FAC", - "blue02": "#066FAC", - "purple01": "#8A77E3", - "purple02": "#6C5DAF", - "black02": "#121212" - }, - "globalHeader": { - "bgLight": "#66bffa", - "bgDark": "#4475FD", - "bgTransparent": "rgba(255, 255, 255, 0.16)", - "bgTransparentDisabled": "rgba(255, 255, 255, 0.08)", - "text": "#FFFFFF", - "textHint": "rgba(255, 255, 255, 0.48)", - "icon": "#FFFFFF", - "iconDisabled": "rgba(255, 255, 255, 0.32)", - "border": "#FFFFFF", - "critical": "#F6AD16", - "positive": "rgb(116, 200, 158)" - }, - "header": { - "bgLeft": "#2B8000", - "bgRight": "#6AA64C", - "bgOverlay": "rgba(255, 255, 255, 0.16)", - "bgOverlayDisabled": "rgba(255, 255, 255, 0.08)", - "fabBg": "#FFFFFF", - "fabIcon": "#121212", - "border": "transparent", - "divider": "rgba(0, 0, 0, 0.12)", - "focusBorder": "#FFFFFF", - "text": "#FFFFFF", - "textHint": "rgba(255, 255, 255, 0.48)", - "icon": "#FFFFFF", - "iconDisabled": "rgba(255, 255, 255, 0.32)" - }, - "dialHeader": { - "bg": "#2B8000", - "text": "#FFFFFF", - "textHint": "rgba(255, 255, 255, 0.72)", - "icon": "#FFFFFF", - "avatarBg": "#FFFFFF", - "avatarIcon": "#2B8000", - "focusBorder": "#FFFFFF" - }, - "nav": { - "iconDefault": "#121212", - "iconSelected": "#2B8000", - "b01": "#FFFFFF", - "b02": "#F9F9F9", - "line": "#E5E5E5", - "menuBg": "#2B8000", - "menuText": "#FFFFFF", - "f01": "#757575", - "f02": "#666666", - "f03": "#494949", - "f04": "#121212", - "bookmark": "#2B8000", - "mention": "#FF8800", - "ctlDefault": "#939393", - "ctlSelected": "#2B8000" - }, - "tab": { - "default": "#121212", - "selected": "#2B8000" - }, - "subAction": "#2B8000", - "umi": { - "bg": "#666666", - "text": "#FFFFFF", - "mentioned": "#FF8800" - }, - "content": { - "brand": "#2B8000" - }, - "interactive": { - "f01": "#2B8000", - "b01": "#F0FCEF", - "b02": "#2B8000" - }, - "success": { - "b01": "#F0FCEF", - "b02": "#CEF4CE", - "b03": "#3C9949", - "b04": "#368541", - "b05": "#3C9949", - "f01": "#CEF4CE", - "f02": "#32773B", - "f11": "#46BE59" - }, - "warning": { - "b01": "#FFF7EB", - "b02": "#FFE7C1", - "b03": "#F6AD16", - "f01": "#F6AD16", - "f02": "#896219", - "f11": "#F6AD16" - }, - "danger": { - "b01": "#FFF7F5", - "b02": "#FFE5E0", - "b03": "#E6413C", - "b04": "#D63E39", - "f01": "#FFE5E0", - "f02": "#BE3933", - "f11": "#F88878" - }, - "highlight": { - "b01": "#FF8800", - "b02": "#FFDFB1", - "b03": "#FF8800", - "f01": "#121212", - "f02": "#FF8800" - }, - "informative": { - "b01": "#F6F9FC", - "f01": "#E3EBF4", - "f02": "#066FAC" - }, - "neutral": { - "f01": "#FFFFFF", - "f02": "#939393", - "f03": "#757575", - "f04": "#666666", - "f05": "#494949", - "f06": "#121212", - "f07": "#121212", - "f11": "#FFFFFF", - "elevation": "#FFFFFF", - "transparent": "transparent", - "b01": "#FFFFFF", - "b02": "#F9F9F9", - "b03": "#F3F3F3", - "b04": "#666666", - "b05": "#494949", - "b06": "#000000", - "l01": "#FFFFFF", - "l02": "#E5E5E5", - "l03": "#C7C7C7", - "l04": "#666666" - }, - "disabled": { - "f01": "#FFFFFF", - "f02": "#B9B9B9", - "b01": "#B9B9B9" - }, - "presence": { - "busy": "#E6413C", - "available": "#3C9949", - "invisible": "#939393" - }, - "highContrast": "transparent" - }, - "radius": { - "circle": "50%", - "zero": "0px", - "sm": "2px", - "md": "3px", - "lg": "4px", - "xl": "8px", - "xxl": "16px", - "round": "100vw" - }, - "shape": { - "borderRadius": 4 - }, - "shadows": [ - "none", - "0 1px 3px 0 rgba(0, 0, 0, 0.2), 0 1px 1px 0 rgba(0, 0, 0, 0.14), 0 2px 1px -1px rgba(0, 0, 0, 0.12)", - "0px 1px 5px 0px rgba(0, 0, 0, 0.2),0px 2px 2px 0px rgba(0, 0, 0, 0.14),0px 3px 1px -2px rgba(0, 0, 0, 0.12)", - "0px 1px 8px 0px rgba(0, 0, 0, 0.2),0px 3px 4px 0px rgba(0, 0, 0, 0.14),0px 3px 3px -2px rgba(0, 0, 0, 0.12)", - "0px 2px 4px -1px rgba(0, 0, 0, 0.2),0px 4px 5px 0px rgba(0, 0, 0, 0.14),0px 1px 10px 0px rgba(0, 0, 0, 0.12)", - "0px 3px 5px -1px rgba(0, 0, 0, 0.2),0px 5px 8px 0px rgba(0, 0, 0, 0.14),0px 1px 14px 0px rgba(0, 0, 0, 0.12)", - "0px 3px 5px -1px rgba(0, 0, 0, 0.2),0px 6px 10px 0px rgba(0, 0, 0, 0.14),0px 1px 18px 0px rgba(0, 0, 0, 0.12)", - "0px 4px 5px -2px rgba(0, 0, 0, 0.2),0px 7px 10px 1px rgba(0, 0, 0, 0.14),0px 2px 16px 1px rgba(0, 0, 0, 0.12)", - "0px 5px 5px -3px rgba(0, 0, 0, 0.2),0px 8px 10px 1px rgba(0, 0, 0, 0.14),0px 3px 14px 2px rgba(0, 0, 0, 0.12)", - "0px 5px 6px -3px rgba(0, 0, 0, 0.2),0px 9px 12px 1px rgba(0, 0, 0, 0.14),0px 3px 16px 2px rgba(0, 0, 0, 0.12)", - "0px 6px 6px -3px rgba(0, 0, 0, 0.2),0px 10px 14px 1px rgba(0, 0, 0, 0.14),0px 4px 18px 3px rgba(0, 0, 0, 0.12)", - "0px 6px 7px -4px rgba(0, 0, 0, 0.2),0px 11px 15px 1px rgba(0, 0, 0, 0.14),0px 4px 20px 3px rgba(0, 0, 0, 0.12)", - "0px 7px 8px -4px rgba(0, 0, 0, 0.2),0px 12px 17px 2px rgba(0, 0, 0, 0.14),0px 5px 22px 4px rgba(0, 0, 0, 0.12)", - "0px 7px 8px -4px rgba(0, 0, 0, 0.2),0px 13px 19px 2px rgba(0, 0, 0, 0.14),0px 5px 24px 4px rgba(0, 0, 0, 0.12)", - "0px 7px 9px -4px rgba(0, 0, 0, 0.2),0px 14px 21px 2px rgba(0, 0, 0, 0.14),0px 5px 26px 4px rgba(0, 0, 0, 0.12)", - "0px 8px 9px -5px rgba(0, 0, 0, 0.2),0px 15px 22px 2px rgba(0, 0, 0, 0.14),0px 6px 28px 5px rgba(0, 0, 0, 0.12)", - "0px 8px 10px -5px rgba(0, 0, 0, 0.2),0px 16px 24px 2px rgba(0, 0, 0, 0.14),0px 6px 30px 5px rgba(0, 0, 0, 0.12)", - "0px 8px 11px -5px rgba(0, 0, 0, 0.2),0px 17px 26px 2px rgba(0, 0, 0, 0.14),0px 6px 32px 5px rgba(0, 0, 0, 0.12)", - "0px 9px 11px -5px rgba(0, 0, 0, 0.2),0px 18px 28px 2px rgba(0, 0, 0, 0.14),0px 7px 34px 6px rgba(0, 0, 0, 0.12)", - "0px 9px 12px -6px rgba(0, 0, 0, 0.2),0px 19px 29px 2px rgba(0, 0, 0, 0.14),0px 7px 36px 6px rgba(0, 0, 0, 0.12)", - "0px 10px 13px -6px rgba(0, 0, 0, 0.2),0px 20px 31px 3px rgba(0, 0, 0, 0.14),0px 8px 38px 7px rgba(0, 0, 0, 0.12)", - "0px 10px 13px -6px rgba(0, 0, 0, 0.2),0px 21px 33px 3px rgba(0, 0, 0, 0.14),0px 8px 40px 7px rgba(0, 0, 0, 0.12)", - "0px 10px 14px -6px rgba(0, 0, 0, 0.2),0px 22px 35px 3px rgba(0, 0, 0, 0.14),0px 8px 42px 7px rgba(0, 0, 0, 0.12)", - "0px 11px 14px -7px rgba(0, 0, 0, 0.2),0px 23px 36px 3px rgba(0, 0, 0, 0.14),0px 9px 44px 8px rgba(0, 0, 0, 0.12)", - "0px 11px 15px -7px rgba(0, 0, 0, 0.2),0px 24px 38px 3px rgba(0, 0, 0, 0.14),0px 9px 46px 8px rgba(0, 0, 0, 0.12)" - ], - "zIndex": { - "default": 1, - "banner": 9500, - "snackbar": 10000, - "dialog": 6000, - "mask": 5000, - "popup": 3000, - "spinner": 9050, - "model": 9000, - "dropdown": 7000, - "ripple": 1, - "elementOnRipple": 2, - "loading": 1000, - "dragging": 2000, - "moreMenu": 999, - "toast": 3000, - "memberListHeader": 100, - "floatButton": 10, - "makeZIndexStackingContext": 1, - "codeEditor": 0 - }, - "typography": { - "fontFamily": "Lato, Helvetica, Arial, sans-serif", - "codeFontFamily": "Courier", - "fontSize": 14, - "fontWeightLight": 300, - "fontWeightRegular": 400, - "fontWeightMedium": 500, - "display4": { - "fontSize": "6rem", - "fontWeight": 700, - "lineHeight": "112px" - }, - "display3": { - "fontSize": "3.5rem", - "fontWeight": 700, - "lineHeight": "72px" - }, - "display2": { - "fontSize": "2.8125rem", - "fontWeight": 400, - "lineHeight": "56px" - }, - "display1": { - "fontSize": "2.125rem", - "fontWeight": 400, - "lineHeight": "40px" - }, - "headline2": { - "fontSize": "1.5rem", - "fontWeight": 700, - "lineHeight": "32px" - }, - "headline": { - "fontSize": "1.5rem", - "fontWeight": 400, - "lineHeight": "32px" - }, - "title2": { - "fontSize": "1.25rem", - "fontWeight": 700, - "lineHeight": "28px" - }, - "title1": { - "fontSize": "1.25rem", - "fontWeight": 400, - "lineHeight": "28px" - }, - "subheading2": { - "fontSize": "1rem", - "fontWeight": 700, - "lineHeight": "24px" - }, - "subheading1": { - "fontSize": "1rem", - "fontWeight": 400, - "lineHeight": "24px" - }, - "body2": { - "fontSize": "0.9375rem", - "fontWeight": 700, - "lineHeight": "22px" - }, - "body1": { - "fontSize": "0.9375rem", - "fontWeight": 400, - "lineHeight": "22px" - }, - "caption2": { - "fontSize": "0.75rem", - "fontWeight": 700, - "lineHeight": "16px" - }, - "caption1": { - "fontSize": "0.75rem", - "fontWeight": 400, - "lineHeight": "16px" - }, - "button": { - "fontSize": "0.9375rem", - "fontWeight": 700, - "lineHeight": "20px", - "textTransform": "none" - } - }, - "transitions": { - "easing": { - "easeIn": "cubic-bezier(0.4, 0, 1, 1)", - "easeOut": "cubic-bezier(0.0, 0, 0.2, 1)", - "easeInOut": "cubic-bezier(0.4, 0, 0.2, 1)", - "sharp": "cubic-bezier(0.4, 0, 0.6, 1)" - }, - "duration": { - "shortest": 150, - "shorter": 200, - "short": 250, - "standard": 300, - "complex": 375, - "enteringScreen": 225, - "leavingScreen": 195 - } - } -} diff --git a/packages/ringcentral-widgets/lib/phoneContext/index.ts b/packages/ringcentral-widgets/lib/phoneContext/index.ts index a148118750..17b389c287 100644 --- a/packages/ringcentral-widgets/lib/phoneContext/index.ts +++ b/packages/ringcentral-widgets/lib/phoneContext/index.ts @@ -5,4 +5,3 @@ export { connectModule }; export * from './connectModule'; export default phoneContext; export * from './phoneContext'; -export * from './theme'; diff --git a/packages/ringcentral-widgets/lib/phoneContext/phoneContext.tsx b/packages/ringcentral-widgets/lib/phoneContext/phoneContext.tsx index d79bc5e230..0897417e9e 100644 --- a/packages/ringcentral-widgets/lib/phoneContext/phoneContext.tsx +++ b/packages/ringcentral-widgets/lib/phoneContext/phoneContext.tsx @@ -1,8 +1,6 @@ import { RcThemeProvider, RcThemeProviderProps } from '@ringcentral/juno'; import React from 'react'; -import { brandThemeMapping } from './theme'; - export interface PhoneProviderProps { phone: T; theme?: RcThemeProviderProps['theme']; @@ -12,9 +10,13 @@ export const PhoneContext = React.createContext(null); export default PhoneContext; +/** + * Init `UI module system provider` and `Juno theme provider` + * make sure you only have one `PhoneProvider` in your app + */ export const PhoneProvider: React.FunctionComponent = ({ phone, - theme = brandThemeMapping.rcBlue, + theme, children, }) => { return ( @@ -24,6 +26,11 @@ export const PhoneProvider: React.FunctionComponent = ({ ); }; +/** + * @deprecated please use UI module System + * bind phone provider + * @param Comp target component that you want to bind phone state + */ export function withPhone(Comp: any) { // eslint-disable-next-line func-names return function (props: any) { diff --git a/packages/ringcentral-widgets/lib/phoneContext/theme.ts b/packages/ringcentral-widgets/lib/phoneContext/theme.ts deleted file mode 100644 index 678f64cf8a..0000000000 --- a/packages/ringcentral-widgets/lib/phoneContext/theme.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { RcThemeInput } from '@ringcentral/juno'; - -import attRich from './brands/attRich/theme.json'; -import btRich from './brands/btRich/theme.json'; -import rcBlue from './brands/rcBlue/theme.json'; -import rcJupiterBlue from './brands/rcJupiterBlue/theme.json'; -import telusRich from './brands/telusRich/theme.json'; - -// TODO: temporary import all, wait dynamic load way implement -export const brandThemeMapping = { - jupiterBlue: rcJupiterBlue as RcThemeInput, - rcBlue: rcBlue as RcThemeInput, - att: attRich as RcThemeInput, - telus: telusRich as RcThemeInput, - bt: btRich as RcThemeInput, -} as const; - -export type BrandTheme = keyof typeof brandThemeMapping | 'rc'; - -const innerGetBrandTheme = ( - brand: BrandTheme = 'rc', - defaultTheme: RcThemeInput, -): RcThemeInput => { - if (brand === 'rc') { - return defaultTheme; - } - - return brandThemeMapping[brand] || defaultTheme; -}; - -export const getBrandTheme = (brand: BrandTheme = 'rc'): RcThemeInput => { - return innerGetBrandTheme(brand, brandThemeMapping.rcBlue); -}; - -export const getBrandThemeWithJupiterBlue = ( - brand: BrandTheme = 'rc', -): RcThemeInput => { - return innerGetBrandTheme(brand, brandThemeMapping.jupiterBlue); -}; diff --git a/packages/ringcentral-widgets/lib/phoneTypeNames/de-DE.js b/packages/ringcentral-widgets/lib/phoneTypeNames/de-DE.js index 02dbdeea28..afd330b30d 100644 --- a/packages/ringcentral-widgets/lib/phoneTypeNames/de-DE.js +++ b/packages/ringcentral-widgets/lib/phoneTypeNames/de-DE.js @@ -8,6 +8,7 @@ export default { [phoneTypes.unknown]: "Unbekannter Telefontyp", [phoneTypes.company]: "Firmennummer", [phoneTypes.direct]: "Direktwahlnummer", + [phoneTypes.contact]: "Kontakttelefon", [phoneTypes.fax]: "Fax", [phoneTypes.other]: "Andere" }; @@ -20,5 +21,6 @@ export default { // @key: @#@"[phoneTypes.unknown]"@#@ @source: @#@"Unknown Phone Type"@#@ // @key: @#@"[phoneTypes.company]"@#@ @source: @#@"Company Number"@#@ // @key: @#@"[phoneTypes.direct]"@#@ @source: @#@"Direct Number"@#@ +// @key: @#@"[phoneTypes.contact]"@#@ @source: @#@"Contact Phone"@#@ // @key: @#@"[phoneTypes.fax]"@#@ @source: @#@"Fax"@#@ // @key: @#@"[phoneTypes.other]"@#@ @source: @#@"Other"@#@ diff --git a/packages/ringcentral-widgets/lib/phoneTypeNames/en-AU.js b/packages/ringcentral-widgets/lib/phoneTypeNames/en-AU.js index 5fcd13b898..a3805848ec 100644 --- a/packages/ringcentral-widgets/lib/phoneTypeNames/en-AU.js +++ b/packages/ringcentral-widgets/lib/phoneTypeNames/en-AU.js @@ -8,6 +8,7 @@ export default { [phoneTypes.unknown]: "Unknown phone type", [phoneTypes.company]: "Company number", [phoneTypes.direct]: "Direct number", + [phoneTypes.contact]: "Contact Phone", [phoneTypes.fax]: "Fax", [phoneTypes.other]: "Other" }; @@ -20,5 +21,6 @@ export default { // @key: @#@"[phoneTypes.unknown]"@#@ @source: @#@"Unknown Phone Type"@#@ // @key: @#@"[phoneTypes.company]"@#@ @source: @#@"Company Number"@#@ // @key: @#@"[phoneTypes.direct]"@#@ @source: @#@"Direct Number"@#@ +// @key: @#@"[phoneTypes.contact]"@#@ @source: @#@"Contact Phone"@#@ // @key: @#@"[phoneTypes.fax]"@#@ @source: @#@"Fax"@#@ // @key: @#@"[phoneTypes.other]"@#@ @source: @#@"Other"@#@ diff --git a/packages/ringcentral-widgets/lib/phoneTypeNames/en-GB.js b/packages/ringcentral-widgets/lib/phoneTypeNames/en-GB.js index 5fcd13b898..a3805848ec 100644 --- a/packages/ringcentral-widgets/lib/phoneTypeNames/en-GB.js +++ b/packages/ringcentral-widgets/lib/phoneTypeNames/en-GB.js @@ -8,6 +8,7 @@ export default { [phoneTypes.unknown]: "Unknown phone type", [phoneTypes.company]: "Company number", [phoneTypes.direct]: "Direct number", + [phoneTypes.contact]: "Contact Phone", [phoneTypes.fax]: "Fax", [phoneTypes.other]: "Other" }; @@ -20,5 +21,6 @@ export default { // @key: @#@"[phoneTypes.unknown]"@#@ @source: @#@"Unknown Phone Type"@#@ // @key: @#@"[phoneTypes.company]"@#@ @source: @#@"Company Number"@#@ // @key: @#@"[phoneTypes.direct]"@#@ @source: @#@"Direct Number"@#@ +// @key: @#@"[phoneTypes.contact]"@#@ @source: @#@"Contact Phone"@#@ // @key: @#@"[phoneTypes.fax]"@#@ @source: @#@"Fax"@#@ // @key: @#@"[phoneTypes.other]"@#@ @source: @#@"Other"@#@ diff --git a/packages/ringcentral-widgets/lib/phoneTypeNames/en-US.js b/packages/ringcentral-widgets/lib/phoneTypeNames/en-US.js index 64a6c51df4..f21cd8abd4 100644 --- a/packages/ringcentral-widgets/lib/phoneTypeNames/en-US.js +++ b/packages/ringcentral-widgets/lib/phoneTypeNames/en-US.js @@ -9,6 +9,7 @@ export default { [phoneTypes.unknown]: 'Unknown Phone Type', [phoneTypes.company]: 'Company Number', [phoneTypes.direct]: 'Direct Number', + [phoneTypes.contact]: 'Contact Phone', [phoneTypes.fax]: 'Fax', [phoneTypes.other]: 'Other', }; diff --git a/packages/ringcentral-widgets/lib/phoneTypeNames/es-419.js b/packages/ringcentral-widgets/lib/phoneTypeNames/es-419.js index f6e43d1028..984635aee9 100644 --- a/packages/ringcentral-widgets/lib/phoneTypeNames/es-419.js +++ b/packages/ringcentral-widgets/lib/phoneTypeNames/es-419.js @@ -8,6 +8,7 @@ export default { [phoneTypes.unknown]: "Tipo de teléfono desconocido", [phoneTypes.company]: "Número de la compañía", [phoneTypes.direct]: "Número directo", + [phoneTypes.contact]: "Teléfono de contacto", [phoneTypes.fax]: "Fax", [phoneTypes.other]: "Otro" }; @@ -20,5 +21,6 @@ export default { // @key: @#@"[phoneTypes.unknown]"@#@ @source: @#@"Unknown Phone Type"@#@ // @key: @#@"[phoneTypes.company]"@#@ @source: @#@"Company Number"@#@ // @key: @#@"[phoneTypes.direct]"@#@ @source: @#@"Direct Number"@#@ +// @key: @#@"[phoneTypes.contact]"@#@ @source: @#@"Contact Phone"@#@ // @key: @#@"[phoneTypes.fax]"@#@ @source: @#@"Fax"@#@ // @key: @#@"[phoneTypes.other]"@#@ @source: @#@"Other"@#@ diff --git a/packages/ringcentral-widgets/lib/phoneTypeNames/es-ES.js b/packages/ringcentral-widgets/lib/phoneTypeNames/es-ES.js index 64da3c6770..c0eae880a6 100644 --- a/packages/ringcentral-widgets/lib/phoneTypeNames/es-ES.js +++ b/packages/ringcentral-widgets/lib/phoneTypeNames/es-ES.js @@ -8,6 +8,7 @@ export default { [phoneTypes.unknown]: "Tipo de teléfono desconocido", [phoneTypes.company]: "Número de la compañía", [phoneTypes.direct]: "Número directo", + [phoneTypes.contact]: "Teléfono de contacto", [phoneTypes.fax]: "Fax", [phoneTypes.other]: "Otro" }; @@ -20,5 +21,6 @@ export default { // @key: @#@"[phoneTypes.unknown]"@#@ @source: @#@"Unknown Phone Type"@#@ // @key: @#@"[phoneTypes.company]"@#@ @source: @#@"Company Number"@#@ // @key: @#@"[phoneTypes.direct]"@#@ @source: @#@"Direct Number"@#@ +// @key: @#@"[phoneTypes.contact]"@#@ @source: @#@"Contact Phone"@#@ // @key: @#@"[phoneTypes.fax]"@#@ @source: @#@"Fax"@#@ // @key: @#@"[phoneTypes.other]"@#@ @source: @#@"Other"@#@ diff --git a/packages/ringcentral-widgets/lib/phoneTypeNames/fr-CA.js b/packages/ringcentral-widgets/lib/phoneTypeNames/fr-CA.js index 8ec4201d2e..a3d0f2e8a7 100644 --- a/packages/ringcentral-widgets/lib/phoneTypeNames/fr-CA.js +++ b/packages/ringcentral-widgets/lib/phoneTypeNames/fr-CA.js @@ -8,6 +8,7 @@ export default { [phoneTypes.unknown]: "Type de téléphone inconnu", [phoneTypes.company]: "Numéro de l'entreprise", [phoneTypes.direct]: "Numéro direct", + [phoneTypes.contact]: "Numéro de téléphone", [phoneTypes.fax]: "Télécopieur", [phoneTypes.other]: "Autre" }; @@ -20,5 +21,6 @@ export default { // @key: @#@"[phoneTypes.unknown]"@#@ @source: @#@"Unknown Phone Type"@#@ // @key: @#@"[phoneTypes.company]"@#@ @source: @#@"Company Number"@#@ // @key: @#@"[phoneTypes.direct]"@#@ @source: @#@"Direct Number"@#@ +// @key: @#@"[phoneTypes.contact]"@#@ @source: @#@"Contact Phone"@#@ // @key: @#@"[phoneTypes.fax]"@#@ @source: @#@"Fax"@#@ // @key: @#@"[phoneTypes.other]"@#@ @source: @#@"Other"@#@ diff --git a/packages/ringcentral-widgets/lib/phoneTypeNames/fr-FR.js b/packages/ringcentral-widgets/lib/phoneTypeNames/fr-FR.js index a6b44f29c6..c54a310bd1 100644 --- a/packages/ringcentral-widgets/lib/phoneTypeNames/fr-FR.js +++ b/packages/ringcentral-widgets/lib/phoneTypeNames/fr-FR.js @@ -8,6 +8,7 @@ export default { [phoneTypes.unknown]: "Type de téléphone inconnu", [phoneTypes.company]: "Numéro de l'entreprise", [phoneTypes.direct]: "Numéro direct", + [phoneTypes.contact]: "Contact téléphonique", [phoneTypes.fax]: "Fax", [phoneTypes.other]: "Autre" }; @@ -20,5 +21,6 @@ export default { // @key: @#@"[phoneTypes.unknown]"@#@ @source: @#@"Unknown Phone Type"@#@ // @key: @#@"[phoneTypes.company]"@#@ @source: @#@"Company Number"@#@ // @key: @#@"[phoneTypes.direct]"@#@ @source: @#@"Direct Number"@#@ +// @key: @#@"[phoneTypes.contact]"@#@ @source: @#@"Contact Phone"@#@ // @key: @#@"[phoneTypes.fax]"@#@ @source: @#@"Fax"@#@ // @key: @#@"[phoneTypes.other]"@#@ @source: @#@"Other"@#@ diff --git a/packages/ringcentral-widgets/lib/phoneTypeNames/it-IT.js b/packages/ringcentral-widgets/lib/phoneTypeNames/it-IT.js index 02ec57b5c7..ee33002122 100644 --- a/packages/ringcentral-widgets/lib/phoneTypeNames/it-IT.js +++ b/packages/ringcentral-widgets/lib/phoneTypeNames/it-IT.js @@ -8,6 +8,7 @@ export default { [phoneTypes.unknown]: "Tipo di telefono sconosciuto", [phoneTypes.company]: "Numero aziendale", [phoneTypes.direct]: "Numero diretto", + [phoneTypes.contact]: "Telefono di contatto", [phoneTypes.fax]: "Fax", [phoneTypes.other]: "Altro" }; @@ -20,5 +21,6 @@ export default { // @key: @#@"[phoneTypes.unknown]"@#@ @source: @#@"Unknown Phone Type"@#@ // @key: @#@"[phoneTypes.company]"@#@ @source: @#@"Company Number"@#@ // @key: @#@"[phoneTypes.direct]"@#@ @source: @#@"Direct Number"@#@ +// @key: @#@"[phoneTypes.contact]"@#@ @source: @#@"Contact Phone"@#@ // @key: @#@"[phoneTypes.fax]"@#@ @source: @#@"Fax"@#@ // @key: @#@"[phoneTypes.other]"@#@ @source: @#@"Other"@#@ diff --git a/packages/ringcentral-widgets/lib/phoneTypeNames/ja-JP.js b/packages/ringcentral-widgets/lib/phoneTypeNames/ja-JP.js index 2405946ed9..e3e4917e07 100644 --- a/packages/ringcentral-widgets/lib/phoneTypeNames/ja-JP.js +++ b/packages/ringcentral-widgets/lib/phoneTypeNames/ja-JP.js @@ -8,6 +8,7 @@ export default { [phoneTypes.unknown]: "電話タイプが不明", [phoneTypes.company]: "会社の代表番号", [phoneTypes.direct]: "ダイレクトナンバー", + [phoneTypes.contact]: "電話で連絡", [phoneTypes.fax]: "FAX", [phoneTypes.other]: "その他" }; @@ -20,5 +21,6 @@ export default { // @key: @#@"[phoneTypes.unknown]"@#@ @source: @#@"Unknown Phone Type"@#@ // @key: @#@"[phoneTypes.company]"@#@ @source: @#@"Company Number"@#@ // @key: @#@"[phoneTypes.direct]"@#@ @source: @#@"Direct Number"@#@ +// @key: @#@"[phoneTypes.contact]"@#@ @source: @#@"Contact Phone"@#@ // @key: @#@"[phoneTypes.fax]"@#@ @source: @#@"Fax"@#@ // @key: @#@"[phoneTypes.other]"@#@ @source: @#@"Other"@#@ diff --git a/packages/ringcentral-widgets/lib/phoneTypeNames/ko-KR.js b/packages/ringcentral-widgets/lib/phoneTypeNames/ko-KR.js index 0fa5bcc1a6..545882eb1a 100644 --- a/packages/ringcentral-widgets/lib/phoneTypeNames/ko-KR.js +++ b/packages/ringcentral-widgets/lib/phoneTypeNames/ko-KR.js @@ -8,6 +8,7 @@ export default { [phoneTypes.unknown]: "알 수 없는 전화 유형", [phoneTypes.company]: "회사 번호", [phoneTypes.direct]: "직통 번호", + [phoneTypes.contact]: "연락처 전화번호", [phoneTypes.fax]: "팩스", [phoneTypes.other]: "기타" }; @@ -20,5 +21,6 @@ export default { // @key: @#@"[phoneTypes.unknown]"@#@ @source: @#@"Unknown Phone Type"@#@ // @key: @#@"[phoneTypes.company]"@#@ @source: @#@"Company Number"@#@ // @key: @#@"[phoneTypes.direct]"@#@ @source: @#@"Direct Number"@#@ +// @key: @#@"[phoneTypes.contact]"@#@ @source: @#@"Contact Phone"@#@ // @key: @#@"[phoneTypes.fax]"@#@ @source: @#@"Fax"@#@ // @key: @#@"[phoneTypes.other]"@#@ @source: @#@"Other"@#@ diff --git a/packages/ringcentral-widgets/lib/phoneTypeNames/nl-NL.js b/packages/ringcentral-widgets/lib/phoneTypeNames/nl-NL.js index 8111dc0899..08ba4475ce 100644 --- a/packages/ringcentral-widgets/lib/phoneTypeNames/nl-NL.js +++ b/packages/ringcentral-widgets/lib/phoneTypeNames/nl-NL.js @@ -8,6 +8,7 @@ export default { [phoneTypes.unknown]: "Onbekend telefoontype", [phoneTypes.company]: "Bedrijfsnummer", [phoneTypes.direct]: "Direct nummer", + [phoneTypes.contact]: "Telefoon contactpersoon", [phoneTypes.fax]: "Fax", [phoneTypes.other]: "Anders" }; @@ -20,5 +21,6 @@ export default { // @key: @#@"[phoneTypes.unknown]"@#@ @source: @#@"Unknown Phone Type"@#@ // @key: @#@"[phoneTypes.company]"@#@ @source: @#@"Company Number"@#@ // @key: @#@"[phoneTypes.direct]"@#@ @source: @#@"Direct Number"@#@ +// @key: @#@"[phoneTypes.contact]"@#@ @source: @#@"Contact Phone"@#@ // @key: @#@"[phoneTypes.fax]"@#@ @source: @#@"Fax"@#@ // @key: @#@"[phoneTypes.other]"@#@ @source: @#@"Other"@#@ diff --git a/packages/ringcentral-widgets/lib/phoneTypeNames/pt-BR.js b/packages/ringcentral-widgets/lib/phoneTypeNames/pt-BR.js index 9d8590c1e8..45e90acf08 100644 --- a/packages/ringcentral-widgets/lib/phoneTypeNames/pt-BR.js +++ b/packages/ringcentral-widgets/lib/phoneTypeNames/pt-BR.js @@ -8,6 +8,7 @@ export default { [phoneTypes.unknown]: "Tipo de telefone desconhecido", [phoneTypes.company]: "Número da empresa", [phoneTypes.direct]: "Número direto", + [phoneTypes.contact]: "Telefone de contato", [phoneTypes.fax]: "Fax", [phoneTypes.other]: "Outro" }; @@ -20,5 +21,6 @@ export default { // @key: @#@"[phoneTypes.unknown]"@#@ @source: @#@"Unknown Phone Type"@#@ // @key: @#@"[phoneTypes.company]"@#@ @source: @#@"Company Number"@#@ // @key: @#@"[phoneTypes.direct]"@#@ @source: @#@"Direct Number"@#@ +// @key: @#@"[phoneTypes.contact]"@#@ @source: @#@"Contact Phone"@#@ // @key: @#@"[phoneTypes.fax]"@#@ @source: @#@"Fax"@#@ // @key: @#@"[phoneTypes.other]"@#@ @source: @#@"Other"@#@ diff --git a/packages/ringcentral-widgets/lib/phoneTypeNames/pt-PT.js b/packages/ringcentral-widgets/lib/phoneTypeNames/pt-PT.js index 33d32a9420..85555e0662 100644 --- a/packages/ringcentral-widgets/lib/phoneTypeNames/pt-PT.js +++ b/packages/ringcentral-widgets/lib/phoneTypeNames/pt-PT.js @@ -8,6 +8,7 @@ export default { [phoneTypes.unknown]: "Tipo de telefone desconhecido", [phoneTypes.company]: "Número da empresa", [phoneTypes.direct]: "Número direto", + [phoneTypes.contact]: "Telefone de contacto", [phoneTypes.fax]: "Fax", [phoneTypes.other]: "Outro" }; @@ -20,5 +21,6 @@ export default { // @key: @#@"[phoneTypes.unknown]"@#@ @source: @#@"Unknown Phone Type"@#@ // @key: @#@"[phoneTypes.company]"@#@ @source: @#@"Company Number"@#@ // @key: @#@"[phoneTypes.direct]"@#@ @source: @#@"Direct Number"@#@ +// @key: @#@"[phoneTypes.contact]"@#@ @source: @#@"Contact Phone"@#@ // @key: @#@"[phoneTypes.fax]"@#@ @source: @#@"Fax"@#@ // @key: @#@"[phoneTypes.other]"@#@ @source: @#@"Other"@#@ diff --git a/packages/ringcentral-widgets/lib/phoneTypeNames/zh-CN.js b/packages/ringcentral-widgets/lib/phoneTypeNames/zh-CN.js index 9328b0b25e..378ca65990 100644 --- a/packages/ringcentral-widgets/lib/phoneTypeNames/zh-CN.js +++ b/packages/ringcentral-widgets/lib/phoneTypeNames/zh-CN.js @@ -8,6 +8,7 @@ export default { [phoneTypes.unknown]: "未知电话类型", [phoneTypes.company]: "公司号码", [phoneTypes.direct]: "直拨号码", + [phoneTypes.contact]: "联系电话", [phoneTypes.fax]: "传真", [phoneTypes.other]: "其他" }; @@ -20,5 +21,6 @@ export default { // @key: @#@"[phoneTypes.unknown]"@#@ @source: @#@"Unknown Phone Type"@#@ // @key: @#@"[phoneTypes.company]"@#@ @source: @#@"Company Number"@#@ // @key: @#@"[phoneTypes.direct]"@#@ @source: @#@"Direct Number"@#@ +// @key: @#@"[phoneTypes.contact]"@#@ @source: @#@"Contact Phone"@#@ // @key: @#@"[phoneTypes.fax]"@#@ @source: @#@"Fax"@#@ // @key: @#@"[phoneTypes.other]"@#@ @source: @#@"Other"@#@ diff --git a/packages/ringcentral-widgets/lib/phoneTypeNames/zh-HK.js b/packages/ringcentral-widgets/lib/phoneTypeNames/zh-HK.js index 0c10d32f36..33cf7711fe 100644 --- a/packages/ringcentral-widgets/lib/phoneTypeNames/zh-HK.js +++ b/packages/ringcentral-widgets/lib/phoneTypeNames/zh-HK.js @@ -8,6 +8,7 @@ export default { [phoneTypes.unknown]: "未知的電話類型", [phoneTypes.company]: "公司號碼", [phoneTypes.direct]: "直撥號碼", + [phoneTypes.contact]: "連絡人電話", [phoneTypes.fax]: "傳真", [phoneTypes.other]: "其他" }; @@ -20,5 +21,6 @@ export default { // @key: @#@"[phoneTypes.unknown]"@#@ @source: @#@"Unknown Phone Type"@#@ // @key: @#@"[phoneTypes.company]"@#@ @source: @#@"Company Number"@#@ // @key: @#@"[phoneTypes.direct]"@#@ @source: @#@"Direct Number"@#@ +// @key: @#@"[phoneTypes.contact]"@#@ @source: @#@"Contact Phone"@#@ // @key: @#@"[phoneTypes.fax]"@#@ @source: @#@"Fax"@#@ // @key: @#@"[phoneTypes.other]"@#@ @source: @#@"Other"@#@ diff --git a/packages/ringcentral-widgets/lib/phoneTypeNames/zh-TW.js b/packages/ringcentral-widgets/lib/phoneTypeNames/zh-TW.js index 0c10d32f36..33cf7711fe 100644 --- a/packages/ringcentral-widgets/lib/phoneTypeNames/zh-TW.js +++ b/packages/ringcentral-widgets/lib/phoneTypeNames/zh-TW.js @@ -8,6 +8,7 @@ export default { [phoneTypes.unknown]: "未知的電話類型", [phoneTypes.company]: "公司號碼", [phoneTypes.direct]: "直撥號碼", + [phoneTypes.contact]: "連絡人電話", [phoneTypes.fax]: "傳真", [phoneTypes.other]: "其他" }; @@ -20,5 +21,6 @@ export default { // @key: @#@"[phoneTypes.unknown]"@#@ @source: @#@"Unknown Phone Type"@#@ // @key: @#@"[phoneTypes.company]"@#@ @source: @#@"Company Number"@#@ // @key: @#@"[phoneTypes.direct]"@#@ @source: @#@"Direct Number"@#@ +// @key: @#@"[phoneTypes.contact]"@#@ @source: @#@"Contact Phone"@#@ // @key: @#@"[phoneTypes.fax]"@#@ @source: @#@"Fax"@#@ // @key: @#@"[phoneTypes.other]"@#@ @source: @#@"Other"@#@ diff --git a/packages/ringcentral-widgets/modules/ActiveCallsUI/ActiveCallsUI.interface.ts b/packages/ringcentral-widgets/modules/ActiveCallsUI/ActiveCallsUI.interface.ts index 5686212e8c..2d2720f799 100644 --- a/packages/ringcentral-widgets/modules/ActiveCallsUI/ActiveCallsUI.interface.ts +++ b/packages/ringcentral-widgets/modules/ActiveCallsUI/ActiveCallsUI.interface.ts @@ -1,13 +1,13 @@ import { ComponentType } from 'react'; -import { Brand } from '@ringcentral-integration/commons/modules/BrandV2'; -import { Locale } from '@ringcentral-integration/commons/modules/LocaleV2'; +import { Brand } from '@ringcentral-integration/commons/modules/Brand'; +import { Locale } from '@ringcentral-integration/commons/modules/Locale'; import { CallMonitor } from '@ringcentral-integration/commons/modules/CallMonitorV2'; import { RateLimiter } from '@ringcentral-integration/commons/modules/RateLimiterV2'; import { ContactSearch } from '@ringcentral-integration/commons/modules/ContactSearchV2'; import { RegionSettings } from '@ringcentral-integration/commons/modules/RegionSettingsV2'; import { ContactMatcher } from '@ringcentral-integration/commons/modules/ContactMatcherV2'; import { CallingSettings } from '@ringcentral-integration/commons/modules/CallingSettingsV2'; -import { ExtensionFeatures } from '@ringcentral-integration/commons/modules/ExtensionFeatures'; +import { AppFeatures } from '@ringcentral-integration/commons/modules/AppFeatures'; import { ConnectivityMonitor } from '@ringcentral-integration/commons/modules/ConnectivityMonitorV2'; import { SwitchCallActiveCallParams, @@ -51,7 +51,7 @@ export interface Deps { contactMatcher: ContactMatcher; callingSettings: CallingSettings; routerInteraction: RouterInteraction; - extensionFeatures: ExtensionFeatures; + appFeatures: AppFeatures; connectivityMonitor: ConnectivityMonitor; modalUI?: ModalUI; webphone?: Webphone; @@ -195,4 +195,5 @@ export interface ActiveCallsPanelProps { newCallIcon?: boolean; useCallControl: boolean; clickSwitchTrack: () => void; + isWide: boolean; } diff --git a/packages/ringcentral-widgets/modules/ActiveCallsUI/ActiveCallsUI.tsx b/packages/ringcentral-widgets/modules/ActiveCallsUI/ActiveCallsUI.tsx index d3330253e0..b1c3fb4a8a 100644 --- a/packages/ringcentral-widgets/modules/ActiveCallsUI/ActiveCallsUI.tsx +++ b/packages/ringcentral-widgets/modules/ActiveCallsUI/ActiveCallsUI.tsx @@ -1,23 +1,23 @@ -import React from 'react'; -import { - RcUIModuleV2, - UIFunctions, - UIProps, -} from '@ringcentral-integration/core'; -import { Module } from '@ringcentral-integration/commons/lib/di'; -import formatNumber from '@ringcentral-integration/commons/lib/formatNumber'; import callDirections from '@ringcentral-integration/commons/enums/callDirections'; import { isRingingInboundCall } from '@ringcentral-integration/commons/lib/callLogHelpers'; +import { Module } from '@ringcentral-integration/commons/lib/di'; +import formatNumber from '@ringcentral-integration/commons/lib/formatNumber'; +import { ActiveSession } from '@ringcentral-integration/commons/modules/ActiveCallControlV2'; +import { isHolding } from '@ringcentral-integration/commons/modules/ActiveCallControlV2/helpers'; import callingModes from '@ringcentral-integration/commons/modules/CallingSettings/callingModes'; import { isOnHold } from '@ringcentral-integration/commons/modules/Webphone/webphoneHelper'; -import { isHolding } from '@ringcentral-integration/commons/modules/ActiveCallControlV2/helpers'; -import { ActiveSession } from '@ringcentral-integration/commons/modules/ActiveCallControlV2'; import { SwitchCallActiveCallParams } from '@ringcentral-integration/commons/modules/WebphoneV2'; +import { + RcUIModuleV2, + UIFunctions, + UIProps, +} from '@ringcentral-integration/core'; +import React from 'react'; import { ModalContent } from '../../components/ActiveCallItemV2'; import { - Deps, ActiveCallsContainerProps, ActiveCallsPanelProps, + Deps, } from './ActiveCallsUI.interface'; const ModalContentRendererID = 'ActiveCallsUI.ModalContentRenderer'; @@ -33,7 +33,7 @@ const ModalContentRendererID = 'ActiveCallsUI.ModalContentRenderer'; 'ContactMatcher', 'CallingSettings', 'RouterInteraction', - 'ExtensionFeatures', + 'AppFeatures', 'ConnectivityMonitor', { dep: 'ModalUI', optional: true }, { dep: 'Webphone', optional: true }, @@ -77,10 +77,8 @@ export class ActiveCallsUI extends RcUIModuleV2 { otherDeviceCalls: this._deps.callMonitor.otherDeviceCalls, areaCode: this._deps.regionSettings.areaCode, countryCode: this._deps.regionSettings.countryCode, - outboundSmsPermission: !!this._deps.extensionFeatures.features?.SMSSending - ?.available, - internalSmsPermission: !!this._deps.extensionFeatures.features - ?.PagesSending?.available, + outboundSmsPermission: this._deps.appFeatures.hasOutboundSMSPermission, + internalSmsPermission: this._deps.appFeatures.hasInternalSMSPermission, showSpinner: !!this._deps.conferenceCall?.isMerging, brand: this._deps.brand.fullName, showContactDisplayPlaceholder, @@ -100,6 +98,7 @@ export class ActiveCallsUI extends RcUIModuleV2 { this._deps.rateLimiter.throttling || controlBusy, useCallControl, + isWide: this.isWide, }; } @@ -344,4 +343,8 @@ export class ActiveCallsUI extends RcUIModuleV2 { }, }; } + + get isWide() { + return true; + } } diff --git a/packages/ringcentral-widgets/modules/AlertUI/AlertUI.interface.ts b/packages/ringcentral-widgets/modules/AlertUI/AlertUI.interface.ts index 6eddba7af3..cc9f8aa9c0 100644 --- a/packages/ringcentral-widgets/modules/AlertUI/AlertUI.interface.ts +++ b/packages/ringcentral-widgets/modules/AlertUI/AlertUI.interface.ts @@ -1,6 +1,6 @@ import { Alert } from '@ringcentral-integration/commons/modules/AlertV2'; -import { Brand } from '@ringcentral-integration/commons/modules/BrandV2'; -import { Locale } from '@ringcentral-integration/commons/modules/LocaleV2'; +import { Brand } from '@ringcentral-integration/commons/modules/Brand'; +import { Locale } from '@ringcentral-integration/commons/modules/Locale'; import { RateLimiter } from '@ringcentral-integration/commons/modules/RateLimiterV2'; import { RouterInteraction } from '../RouterInteraction'; diff --git a/packages/ringcentral-widgets/modules/AudioSettingsUI/AudioSettingsUI.interface.ts b/packages/ringcentral-widgets/modules/AudioSettingsUI/AudioSettingsUI.interface.ts index ed3a1865a0..396a27c4a7 100644 --- a/packages/ringcentral-widgets/modules/AudioSettingsUI/AudioSettingsUI.interface.ts +++ b/packages/ringcentral-widgets/modules/AudioSettingsUI/AudioSettingsUI.interface.ts @@ -2,7 +2,7 @@ import { AudioSettings } from '@ringcentral-integration/commons/modules/AudioSet import { CallMonitor } from '@ringcentral-integration/commons/modules/CallMonitorV2'; import { Webphone } from '@ringcentral-integration/commons/modules/WebphoneV2'; import { CallingSettings } from '@ringcentral-integration/commons/modules/CallingSettingsV2'; -import { Locale } from '@ringcentral-integration/commons/modules/LocaleV2'; +import { Locale } from '@ringcentral-integration/commons/modules/Locale'; import { RouterInteraction } from '../RouterInteraction'; export interface AudioSettingsUIOptions { diff --git a/packages/ringcentral-widgets/modules/CallBadgeUI/CallBadgeUI.interface.ts b/packages/ringcentral-widgets/modules/CallBadgeUI/CallBadgeUI.interface.ts index 97d8c69ed4..0a8576b560 100644 --- a/packages/ringcentral-widgets/modules/CallBadgeUI/CallBadgeUI.interface.ts +++ b/packages/ringcentral-widgets/modules/CallBadgeUI/CallBadgeUI.interface.ts @@ -1,4 +1,4 @@ -import { Locale } from '@ringcentral-integration/commons/modules/LocaleV2'; +import { Locale } from '@ringcentral-integration/commons/modules/Locale'; import { Webphone } from '@ringcentral-integration/commons/modules/WebphoneV2'; import { NormalizedSession } from '@ringcentral-integration/commons/interfaces/Webphone.interface'; diff --git a/packages/ringcentral-widgets/modules/CallControlUI/CallControlUI.interface.ts b/packages/ringcentral-widgets/modules/CallControlUI/CallControlUI.interface.ts index 115f434baf..857458e018 100644 --- a/packages/ringcentral-widgets/modules/CallControlUI/CallControlUI.interface.ts +++ b/packages/ringcentral-widgets/modules/CallControlUI/CallControlUI.interface.ts @@ -1,5 +1,7 @@ -import { ReactNode } from 'react'; -import { Brand } from '@ringcentral-integration/commons/modules/BrandV2'; +import callDirections from '@ringcentral-integration/commons/enums/callDirections'; +import calleeTypes from '@ringcentral-integration/commons/enums/calleeTypes'; +import { NormalizedSession } from '@ringcentral-integration/commons/interfaces/Webphone.interface'; +import { Brand } from '@ringcentral-integration/commons/modules/Brand'; import { CallingSettings } from '@ringcentral-integration/commons/modules/CallingSettingsV2'; import { CallMonitor } from '@ringcentral-integration/commons/modules/CallMonitorV2'; import { ConferenceCall } from '@ringcentral-integration/commons/modules/ConferenceCallV2'; @@ -7,12 +9,11 @@ import { ContactMatcher } from '@ringcentral-integration/commons/modules/Contact import { ContactSearch } from '@ringcentral-integration/commons/modules/ContactSearchV2'; import { ExtensionInfo } from '@ringcentral-integration/commons/modules/ExtensionInfoV2'; import { ForwardingNumber } from '@ringcentral-integration/commons/modules/ForwardingNumberV2'; -import { Locale } from '@ringcentral-integration/commons/modules/LocaleV2'; +import { Locale } from '@ringcentral-integration/commons/modules/Locale'; import { RegionSettings } from '@ringcentral-integration/commons/modules/RegionSettingsV2'; import { Webphone } from '@ringcentral-integration/commons/modules/WebphoneV2'; -import callDirections from '../../../ringcentral-integration/enums/callDirections'; -import calleeTypes from '../../../ringcentral-integration/enums/calleeTypes'; -import { NormalizedSession } from '../../../ringcentral-integration/interfaces/Webphone.interface'; +import { ReactNode } from 'react'; +import { AppFeatures } from '@ringcentral-integration/commons/modules/AppFeatures/AppFeatures'; import { ConnectivityManager } from '../ConnectivityManager'; import { RouterInteraction } from '../RouterInteraction'; @@ -32,6 +33,7 @@ export interface CallControlComponentProps { } export interface Deps { + appFeatures: AppFeatures; webphone: Webphone; locale: Locale; contactMatcher: ContactMatcher; diff --git a/packages/ringcentral-widgets/modules/CallControlUI/CallControlUI.ts b/packages/ringcentral-widgets/modules/CallControlUI/CallControlUI.ts index 8d86fb11a3..00c7f213f0 100644 --- a/packages/ringcentral-widgets/modules/CallControlUI/CallControlUI.ts +++ b/packages/ringcentral-widgets/modules/CallControlUI/CallControlUI.ts @@ -7,12 +7,13 @@ import { LastCallInfo, } from '@ringcentral-integration/commons/modules/ConferenceCallV2'; import { Webphone } from '@ringcentral-integration/commons/modules/WebphoneV2'; -import callDirections from '../../../ringcentral-integration/enums/callDirections'; -import { NormalizedSession } from '../../../ringcentral-integration/interfaces/Webphone.interface'; -import { formatNumber } from '../../../ringcentral-integration/lib/formatNumber'; -import callingModes from '../../../ringcentral-integration/modules/CallingSettings/callingModes'; -import { sessionStatus } from '../../../ringcentral-integration/modules/Webphone/sessionStatus'; +import callDirections from '@ringcentral-integration/commons/enums/callDirections'; +import { NormalizedSession } from '@ringcentral-integration/commons/interfaces/Webphone.interface'; +import { formatNumber } from '@ringcentral-integration/commons/lib/formatNumber'; +import callingModes from '@ringcentral-integration/commons/modules/CallingSettings/callingModes'; +import { sessionStatus } from '@ringcentral-integration/commons/modules/Webphone/sessionStatus'; import callCtrlLayouts from '../../enums/callCtrlLayouts'; +import { checkShouldHidePhoneNumber } from '../../lib/checkShouldHidePhoneNumber'; import { CallControlComponentProps, Deps, @@ -32,6 +33,7 @@ import { 'ForwardingNumber', 'CallMonitor', 'ExtensionInfo', + 'AppFeatures', { dep: 'ConferenceCall', optional: true }, { dep: 'RouterInteraction', optional: true }, ], @@ -123,9 +125,22 @@ export class CallControlUI extends RcUIModuleV2 { connectivityManager.isOfflineMode || connectivityManager.isVoipOnlyMode ); + let phoneNumber = + currentSession.direction === callDirections.outbound + ? currentSession.to + : currentSession.from; + + if ( + this._deps.appFeatures.isCDCEnabled && + checkShouldHidePhoneNumber(phoneNumber, nameMatches) + ) { + phoneNumber = null; + } + return { brand: brand.fullName, nameMatches, + phoneNumber, currentLocale: locale.currentLocale, session: currentSession, areaCode: regionSettings.areaCode, diff --git a/packages/ringcentral-widgets/modules/CallHistoryUI/CallHistoryUI.interface.ts b/packages/ringcentral-widgets/modules/CallHistoryUI/CallHistoryUI.interface.ts index 1b3a54320e..320c01eb0a 100644 --- a/packages/ringcentral-widgets/modules/CallHistoryUI/CallHistoryUI.interface.ts +++ b/packages/ringcentral-widgets/modules/CallHistoryUI/CallHistoryUI.interface.ts @@ -1,4 +1,4 @@ -import { Brand } from '@ringcentral-integration/commons/modules/BrandV2'; +import { Brand } from '@ringcentral-integration/commons/modules/Brand'; import { CallHistory } from '@ringcentral-integration/commons/modules/CallHistoryV2'; import { CallLogger } from '@ringcentral-integration/commons/modules/CallLoggerV2'; import { Call } from '@ringcentral-integration/commons/modules/CallV2'; @@ -7,9 +7,9 @@ import { ConnectivityMonitor } from '@ringcentral-integration/commons/modules/Co import { ContactMatcher } from '@ringcentral-integration/commons/modules/ContactMatcherV2'; import { ContactSearch } from '@ringcentral-integration/commons/modules/ContactSearchV2'; import { DateTimeFormat } from '@ringcentral-integration/commons/modules/DateTimeFormatV2'; -import { ExtensionFeatures } from '@ringcentral-integration/commons/modules/ExtensionFeatures'; +import { AppFeatures } from '@ringcentral-integration/commons/modules/AppFeatures'; import { ExtensionInfo } from '@ringcentral-integration/commons/modules/ExtensionInfoV2'; -import { Locale } from '@ringcentral-integration/commons/modules/LocaleV2'; +import { Locale } from '@ringcentral-integration/commons/modules/Locale'; import { RateLimiter } from '@ringcentral-integration/commons/modules/RateLimiterV2'; import { RegionSettings } from '@ringcentral-integration/commons/modules/RegionSettingsV2'; import { @@ -30,7 +30,7 @@ export interface Deps { connectivityMonitor: ConnectivityMonitor; connectivityManager: ConnectivityManager; rateLimiter: RateLimiter; - extensionFeatures: ExtensionFeatures; + appFeatures: AppFeatures; contactMatcher: ContactMatcher; routerInteraction: RouterInteraction; contactSearch: ContactSearch; diff --git a/packages/ringcentral-widgets/modules/CallHistoryUI/CallHistoryUI.ts b/packages/ringcentral-widgets/modules/CallHistoryUI/CallHistoryUI.ts index 8230316052..2e36af218f 100644 --- a/packages/ringcentral-widgets/modules/CallHistoryUI/CallHistoryUI.ts +++ b/packages/ringcentral-widgets/modules/CallHistoryUI/CallHistoryUI.ts @@ -21,7 +21,7 @@ import i18n from './i18n'; 'ConnectivityMonitor', 'RateLimiter', 'DateTimeFormat', - 'ExtensionFeatures', + 'AppFeatures', { dep: 'CallLogger', optional: true }, { dep: 'Call', optional: true }, { dep: 'ComposeText', optional: true }, @@ -58,7 +58,7 @@ export class CallHistoryUI extends RcUIModuleV2 { callLogger, dateTimeFormat, composeText, - extensionFeatures, + appFeatures, } = this._deps; return { enableContactFallback, @@ -80,8 +80,8 @@ export class CallHistoryUI extends RcUIModuleV2 { connectivityManager.isWebphoneInitializing || rateLimiter.throttling, disableClickToDial: !(call && call.isIdle), - outboundSmsPermission: extensionFeatures.hasOutboundSMSPermission, - internalSmsPermission: extensionFeatures.hasInternalSMSPermission, + outboundSmsPermission: appFeatures.hasOutboundSMSPermission, + internalSmsPermission: appFeatures.hasInternalSMSPermission, loggingMap: callLogger && callLogger.loggingMap, showSpinner: !( callHistory.ready && @@ -89,7 +89,7 @@ export class CallHistoryUI extends RcUIModuleV2 { regionSettings.ready && dateTimeFormat.ready && connectivityMonitor.ready && - extensionFeatures.ready && + appFeatures.ready && (!call || call.ready) && (!composeText || composeText.ready) && (!callLogger || callLogger.ready) @@ -120,7 +120,7 @@ export class CallHistoryUI extends RcUIModuleV2 { routerInteraction, contactSearch, callHistory, - extensionFeatures, + appFeatures, } = this._deps; return { dateTimeFormatter, @@ -149,7 +149,7 @@ export class CallHistoryUI extends RcUIModuleV2 { } : undefined, onClickToDial: - dialerUI && extensionFeatures.isCallingEnabled + dialerUI && appFeatures.isCallingEnabled ? (recipient: any) => { if (call.isIdle) { routerInteraction.push(dialerRoute); diff --git a/packages/ringcentral-widgets/modules/CallLogSection/actionTypes.js b/packages/ringcentral-widgets/modules/CallLogSection/actionTypes.js index 0038c32df1..77bc23c477 100644 --- a/packages/ringcentral-widgets/modules/CallLogSection/actionTypes.js +++ b/packages/ringcentral-widgets/modules/CallLogSection/actionTypes.js @@ -9,6 +9,7 @@ export const actionTypes = ObjectMap.prefixKeys( 'saveSuccess', 'saveError', 'cleanUp', + 'syncing', 'showLogSection', 'closeLogSection', 'showLogNotification', diff --git a/packages/ringcentral-widgets/modules/CallLogSection/getStorageReducer.js b/packages/ringcentral-widgets/modules/CallLogSection/getStorageReducer.js index 68ea46cd7f..8dc00c289e 100644 --- a/packages/ringcentral-widgets/modules/CallLogSection/getStorageReducer.js +++ b/packages/ringcentral-widgets/modules/CallLogSection/getStorageReducer.js @@ -2,39 +2,44 @@ import { combineReducers } from 'redux'; function getCallsMappingReducer(types) { return (state = {}, { type, identify }) => { + const originalState = state[identify]; switch (type) { case types.update: - if (state[identify] && state[identify].isEdited) { - return state; - } return { ...state, [identify]: { - ...state[identify], + ...originalState, + latestUpdateTime: Date.now(), isEdited: true, }, }; case types.saving: + case types.syncing: return { ...state, [identify]: { - ...state[identify], + ...originalState, + latestSaveTime: Date.now(), }, }; case types.saveSuccess: return { ...state, [identify]: { - ...state[identify], - isEdited: false, + ...originalState, isSucceed: true, + isEdited: !!( + originalState?.latestUpdateTime && + originalState?.latestSaveTime && + originalState?.latestSaveTime < originalState?.latestUpdateTime + ), }, }; case types.saveError: return { ...state, [identify]: { - ...state[identify], + ...originalState, isEdited: true, isSucceed: false, }, diff --git a/packages/ringcentral-widgets/modules/CallLogSectionV2/CallLogSection.interface.ts b/packages/ringcentral-widgets/modules/CallLogSectionV2/CallLogSection.interface.ts new file mode 100644 index 0000000000..b66c9d9e6b --- /dev/null +++ b/packages/ringcentral-widgets/modules/CallLogSectionV2/CallLogSection.interface.ts @@ -0,0 +1,40 @@ +import { Storage } from '@ringcentral-integration/commons/modules/StorageV2'; +import { CallLogTasks } from '@ringcentral-integration/commons/modules/CallLogTasks'; +import { CallHistory } from '@ringcentral-integration/commons/modules/CallHistoryV2'; +import { CallMonitor } from '@ringcentral-integration/commons/modules/CallMonitorV2'; + +export interface CallLogSectionCallStatus { + isEdited: boolean; + isSucceed: boolean; + isSaving: boolean; +} + +export type CallsMappingType = Record< + string, + { + isSucceed: boolean; + isEdited: boolean; + latestSaveTime: number; + latestUpdateTime: number; + } +>; + +interface CallLogSectionOptions { + notSyncOpenState: boolean; +} + +export interface Deps { + storage: Storage; + callLogTasks: CallLogTasks; + callHistory: CallHistory; + callMonitor: CallMonitor; + callLogSectionOptions: CallLogSectionOptions; +} + +export type AddLogHandlerFunctions = { + logFunction: (identify: string, ...args: any) => {}; + readyCheckFunction: (identify?: string, ...args: any) => boolean; + onSuccess: (identify: string, ...args: any) => void; + onUpdate: (identify: string, ...args: any) => void; + onError: (identify: string, ...args: any) => void; +}; diff --git a/packages/ringcentral-widgets/modules/CallLogSectionV2/CallLogSection.ts b/packages/ringcentral-widgets/modules/CallLogSectionV2/CallLogSection.ts new file mode 100644 index 0000000000..c90c611dfa --- /dev/null +++ b/packages/ringcentral-widgets/modules/CallLogSectionV2/CallLogSection.ts @@ -0,0 +1,466 @@ +import { + assoc, + converge, + flip, + identity, + keys, + mergeWith, + pick, + useWith, +} from 'ramda'; +import { Module } from '@ringcentral-integration/commons/lib/di'; +import { + action, + computed, + RcModuleV2, + state, + storage, +} from '@ringcentral-integration/core'; +import { proxify } from '@ringcentral-integration/commons/lib/proxy/proxify'; +import { Call } from '@ringcentral-integration/commons/interfaces/Call.interface'; +import { Mapping } from '../../typings'; +import { + AddLogHandlerFunctions, + CallLogSectionCallStatus, + CallsMappingType, + Deps, +} from './CallLogSection.interface'; + +@Module({ + deps: [ + 'Storage', + 'CallLogTasks', + 'CallHistory', + 'CallMonitor', + { + dep: 'CallLogSectionOptions', + optional: true, + }, + ], +}) +export class CallLogSection extends RcModuleV2 { + _notSyncOpenState: boolean; + _storageKey: string; + private _readyCheckFunction: AddLogHandlerFunctions['readyCheckFunction']; + private _logFunction: AddLogHandlerFunctions['logFunction']; + private _onSuccess: AddLogHandlerFunctions['onSuccess']; + private _onUpdate: AddLogHandlerFunctions['onUpdate']; + private _onError: AddLogHandlerFunctions['onError']; + + constructor(deps: Deps) { + super({ + deps, + storageKey: 'callLogSection', + enableCache: true, + }); + this._notSyncOpenState = !!this._deps.callLogSectionOptions + ?.notSyncOpenState; + } + + // TODO: merge these states in callLogTasks.loggingmapping + @state + callsSavingStatus: Record = {}; + + @storage + @state + callsMappingState: CallsMappingType = {}; + + @storage + @state + identifyList: Array = []; + + @state + stateCurrentIdentify: string = null; + + @storage + @state + storageCurrentIdentify: string = null; + + @state + stateCurrentNotificationIdentify: string = null; + + @storage + @state + storageCurrentNotificationIdentify: string = null; + + @state + stateNotificationIsExpand: boolean = false; + + @storage + @state + storageNotificationIsExpand: boolean = false; + + _shouldInit() { + return super._shouldInit() && this._readyCheckFunction(); + } + + _shouldReset() { + return super._shouldReset() || (this.ready && !this._readyCheckFunction()); + } + + @action + update( + identify: string, + newValue: Partial, + callsSavingStatus: boolean, + ) { + this.callsSavingStatus[identify] = callsSavingStatus; + const originalState = this.callsMappingState[identify]; + this.callsMappingState = { + ...this.callsMappingState, + [identify]: { + ...originalState, + ...newValue, + }, + }; + this.identifyList = Array.from(new Set([...this.identifyList, identify])); + } + + @proxify + async saveSuccess(identify: string) { + const originalState = this.callsMappingState[identify]; + this.update( + identify, + { + isSucceed: true, + isEdited: !!( + originalState?.latestUpdateTime && + originalState?.latestSaveTime && + originalState?.latestSaveTime < originalState?.latestUpdateTime + ), + }, + false, + ); + } + + @proxify + async saving(identify: string) { + this.update( + identify, + { + latestSaveTime: Date.now(), + }, + true, + ); + } + + @proxify + async saveError(identify: string) { + this.update( + identify, + { + isEdited: true, + isSucceed: false, + }, + false, + ); + } + + // TODO: add args type + @proxify + async _handleSuccess(identify: string, ...args: any) { + this.saveSuccess(identify); + if (typeof this._onSuccess === 'function') + this._onSuccess(identify, ...args); + } + + // TODO: add args type + @proxify + async _handleError(identify: string, ...args: any) { + this.saveError(identify); + if (typeof this._onError === 'function') { + await this._onError(identify, ...args); + } + } + + @proxify + async showLogSection(identify: string) { + if (!this.show || identify !== this.currentIdentify) { + this.setLogSectionIdentify(identify); + } + } + + @action + setLogSectionIdentify(identify: string) { + if (this._notSyncOpenState) { + this.stateCurrentIdentify = identify; + } else { + this.storageCurrentIdentify = identify; + } + } + + @action + setLogNotificationIdentify(identify: string) { + if (this._notSyncOpenState) { + this.stateCurrentNotificationIdentify = identify; + } else { + this.storageCurrentNotificationIdentify = identify; + } + } + + @proxify + async showLogNotification(identify: string) { + if ( + !this.showNotification || + identify !== this.currentNotificationIdentify + ) { + this.setLogNotificationIdentify(identify); + } + } + + addLogHandler({ + logFunction, + readyCheckFunction, + onUpdate, + onSuccess, + onError, + }: AddLogHandlerFunctions) { + if (typeof logFunction !== 'function') { + throw new Error('CallLogSection: "logFunction" must be a function.'); + } + if (typeof readyCheckFunction !== 'function') { + throw new Error( + 'CallLogSection: "readyCheckFunction" must be a function.', + ); + } + this._logFunction = logFunction; + this._readyCheckFunction = readyCheckFunction; + this._onUpdate = onUpdate; + this._onSuccess = onSuccess; + this._onError = onError; + } + + // TODO: add args type + @proxify + async updateCallLog(identify: string, ...args: any) { + this.update( + identify, + { + latestUpdateTime: Date.now(), + isEdited: true, + }, + this.callsSavingStatus[identify], + ); + await this._onUpdate(identify, ...args); + } + + // TODO: add args type when implement call log ui + @proxify + async saveCallLog(identify: string, ...args: any) { + if ( + identify && + (!this.callsMapping[identify] || !this.callsMapping[identify].isSaving) + ) { + this.saving(identify); + try { + const result = await this._logFunction(identify, ...args); + if (!result) { + throw new Error('Result is empty'); + } + await this._handleSuccess(identify, ...args); + return result; + } catch (e) { + await this._handleError(identify, ...args); + console.warn(e); + } + } + } + + @proxify + async handleLogSection(identify: string) { + if (!this.show) { + // Preferentially show call log section. + await this.showLogSection(identify); + } else if ( + !this.notificationIsExpand && + this.currentIdentify !== identify + ) { + // Check it to show log notification when the call log notification isn't expanded. + await this.showLogNotification(identify); + } + } + + @proxify + async closeLogSection() { + if (this.show) { + this.setLogSectionIdentify(null); + } + } + + @proxify + async discardAndHandleNotification() { + const currentNotificationIdentify = this.currentNotificationIdentify; + await this.closeLogNotification(); + await this.closeLogSection(); + await this.showLogSection(currentNotificationIdentify); + } + + @proxify + async saveAndHandleNotification() { + const currentNotificationIdentify = this.currentNotificationIdentify; + const currentIdentify = this.currentIdentify; + await this.saveCallLog(currentIdentify); + await this.closeLogNotification(); + await this.closeLogSection(); + await this.showLogSection(currentNotificationIdentify); + } + + @proxify + async closeLogNotification() { + if (this.showNotification) { + this.setLogNotificationIdentify(null); + this.setNotificationIsExpand(false); + } + } + + @action + setNotificationIsExpand(isExpand: boolean) { + if (this._notSyncOpenState) { + this.stateNotificationIsExpand = isExpand; + } else { + this.storageNotificationIsExpand = isExpand; + } + } + + // shrink the popover menu appear when click log button at call notificaiton + @proxify + async shrinkNotification() { + if (this.notificationIsExpand) { + this.setNotificationIsExpand(false); + } + } + + @proxify + async expandNotification() { + if (!this.notificationIsExpand) { + this.setNotificationIsExpand(true); + } + } + + @proxify + async expandLogNotification() { + if (!this.show) { + await this.showLogSection(this.currentNotificationIdentify); + await this.closeLogNotification(); + } + await this.expandNotification(); + } + + @proxify + async viewTask(call: Call) { + await this._deps.callLogTasks.fetchAndUpdateTask(call); + this.showLogSection(call.sessionId); + } + + @proxify + async onNewCall(call: Call) { + await this._deps.callLogTasks.fetchAndUpdateTask(call); + this.handleLogSection(call.sessionId); + } + + @computed((that: CallLogSection) => [ + that.identifyList, + that.callsMappingState, + ]) + get calls() { + const calls = this.identifyList.map( + (identify: string) => this.callsMappingState[identify], + ); + return calls; + } + + /** + * Merge isSaving property from reducer to callsMapping + */ + @computed((that: CallLogSection) => [ + that.callsMappingState, + that.callsSavingStatus, + ]) + get callsMapping(): Mapping { + return converge(mergeWith(flip(assoc('isSaving'))), [ + identity, + // eslint-disable-next-line react-hooks/rules-of-hooks + useWith(pick, [keys, identity]), + ]) as any; + } + + @computed((that: CallLogSection) => [ + that.currentIdentify, + that._deps.callLogTasks.logInfoMapping, + ]) + get currentLogCall() { + return this._deps.callLogTasks.logInfoMapping[this.currentIdentify] || {}; + } + + @computed((that: CallLogSection) => [ + that.currentIdentify, + that.callsMappingState, + ]) + get currentCallLogStatus() { + return this.callsMappingState[this.currentIdentify] || ({} as any); + } + + @computed((that: CallLogSection) => [ + that.currentNotificationIdentify, + that._deps.callLogTasks.logInfoMapping, + ]) + get currentLogNotificationCall() { + return ( + this._deps.callLogTasks.logInfoMapping[ + this.currentNotificationIdentify + ] || {} + ); + } + + @computed((that: CallLogSection) => [ + that.currentIdentify, + that._deps.callHistory.calls, + that._deps.callMonitor.calls, + ]) + get currentCall() { + return ( + [...this._deps.callHistory.calls, ...this._deps.callMonitor.calls].find( + (call) => call.sessionId === this.currentIdentify, + ) || {} + ); + } + + @computed((that: CallLogSection) => [ + that.currentNotificationIdentify, + that._deps.callHistory.calls, + that._deps.callMonitor.calls, + ]) + get currentNotificationCall() { + return ( + [...this._deps.callHistory.calls, ...this._deps.callMonitor.calls].find( + (call) => call.sessionId === this.currentNotificationIdentify, + ) || {} + ); + } + + get currentIdentify() { + return this._notSyncOpenState + ? this.stateCurrentIdentify + : this.storageCurrentIdentify; + } + + get show() { + return !!this.currentIdentify; + } + + get currentNotificationIdentify() { + return this._notSyncOpenState + ? this.stateCurrentNotificationIdentify + : this.storageCurrentNotificationIdentify; + } + + get showNotification() { + return !!this.currentNotificationIdentify; + } + + get notificationIsExpand() { + return this._notSyncOpenState + ? this.stateNotificationIsExpand + : this.storageNotificationIsExpand; + } +} diff --git a/packages/ringcentral-widgets/modules/CallLogSectionV2/i18n/de-DE.js b/packages/ringcentral-widgets/modules/CallLogSectionV2/i18n/de-DE.js new file mode 100644 index 0000000000..648daeb5c6 --- /dev/null +++ b/packages/ringcentral-widgets/modules/CallLogSectionV2/i18n/de-DE.js @@ -0,0 +1,9 @@ +export default { + unknown: "Unbekannt", + multipleMatches: "Mehrfache Übereinstimmungen", + anonymous: "Anonym" +}; + +// @key: @#@"unknown"@#@ @source: @#@"Unknown"@#@ +// @key: @#@"multipleMatches"@#@ @source: @#@"Multiple matches"@#@ +// @key: @#@"anonymous"@#@ @source: @#@"Anonymous"@#@ diff --git a/packages/ringcentral-widgets/modules/CallLogSectionV2/i18n/en-AU.js b/packages/ringcentral-widgets/modules/CallLogSectionV2/i18n/en-AU.js new file mode 100644 index 0000000000..c6533e3add --- /dev/null +++ b/packages/ringcentral-widgets/modules/CallLogSectionV2/i18n/en-AU.js @@ -0,0 +1,9 @@ +export default { + unknown: "Unknown", + multipleMatches: "Multiple matches", + anonymous: "Anonymous" +}; + +// @key: @#@"unknown"@#@ @source: @#@"Unknown"@#@ +// @key: @#@"multipleMatches"@#@ @source: @#@"Multiple matches"@#@ +// @key: @#@"anonymous"@#@ @source: @#@"Anonymous"@#@ diff --git a/packages/ringcentral-widgets/modules/CallLogSectionV2/i18n/en-GB.js b/packages/ringcentral-widgets/modules/CallLogSectionV2/i18n/en-GB.js new file mode 100644 index 0000000000..c6533e3add --- /dev/null +++ b/packages/ringcentral-widgets/modules/CallLogSectionV2/i18n/en-GB.js @@ -0,0 +1,9 @@ +export default { + unknown: "Unknown", + multipleMatches: "Multiple matches", + anonymous: "Anonymous" +}; + +// @key: @#@"unknown"@#@ @source: @#@"Unknown"@#@ +// @key: @#@"multipleMatches"@#@ @source: @#@"Multiple matches"@#@ +// @key: @#@"anonymous"@#@ @source: @#@"Anonymous"@#@ diff --git a/packages/ringcentral-widgets/modules/CallLogSectionV2/i18n/en-US.ts b/packages/ringcentral-widgets/modules/CallLogSectionV2/i18n/en-US.ts new file mode 100644 index 0000000000..0e507a4da1 --- /dev/null +++ b/packages/ringcentral-widgets/modules/CallLogSectionV2/i18n/en-US.ts @@ -0,0 +1,5 @@ +export default { + unknown: 'Unknown', + multipleMatches: 'Multiple matches', + anonymous: 'Anonymous', +}; diff --git a/packages/ringcentral-widgets/modules/CallLogSectionV2/i18n/es-419.js b/packages/ringcentral-widgets/modules/CallLogSectionV2/i18n/es-419.js new file mode 100644 index 0000000000..7e45dc091a --- /dev/null +++ b/packages/ringcentral-widgets/modules/CallLogSectionV2/i18n/es-419.js @@ -0,0 +1,9 @@ +export default { + unknown: "Desconocido", + multipleMatches: "Varias coincidencias", + anonymous: "Anónimo" +}; + +// @key: @#@"unknown"@#@ @source: @#@"Unknown"@#@ +// @key: @#@"multipleMatches"@#@ @source: @#@"Multiple matches"@#@ +// @key: @#@"anonymous"@#@ @source: @#@"Anonymous"@#@ diff --git a/packages/ringcentral-widgets/modules/CallLogSectionV2/i18n/es-ES.js b/packages/ringcentral-widgets/modules/CallLogSectionV2/i18n/es-ES.js new file mode 100644 index 0000000000..7e45dc091a --- /dev/null +++ b/packages/ringcentral-widgets/modules/CallLogSectionV2/i18n/es-ES.js @@ -0,0 +1,9 @@ +export default { + unknown: "Desconocido", + multipleMatches: "Varias coincidencias", + anonymous: "Anónimo" +}; + +// @key: @#@"unknown"@#@ @source: @#@"Unknown"@#@ +// @key: @#@"multipleMatches"@#@ @source: @#@"Multiple matches"@#@ +// @key: @#@"anonymous"@#@ @source: @#@"Anonymous"@#@ diff --git a/packages/ringcentral-widgets/modules/CallLogSectionV2/i18n/fr-CA.js b/packages/ringcentral-widgets/modules/CallLogSectionV2/i18n/fr-CA.js new file mode 100644 index 0000000000..1dbda4d953 --- /dev/null +++ b/packages/ringcentral-widgets/modules/CallLogSectionV2/i18n/fr-CA.js @@ -0,0 +1,9 @@ +export default { + unknown: "Inconnu", + multipleMatches: "Plusieurs correspondances", + anonymous: "Anonyme" +}; + +// @key: @#@"unknown"@#@ @source: @#@"Unknown"@#@ +// @key: @#@"multipleMatches"@#@ @source: @#@"Multiple matches"@#@ +// @key: @#@"anonymous"@#@ @source: @#@"Anonymous"@#@ diff --git a/packages/ringcentral-widgets/modules/CallLogSectionV2/i18n/fr-FR.js b/packages/ringcentral-widgets/modules/CallLogSectionV2/i18n/fr-FR.js new file mode 100644 index 0000000000..1dbda4d953 --- /dev/null +++ b/packages/ringcentral-widgets/modules/CallLogSectionV2/i18n/fr-FR.js @@ -0,0 +1,9 @@ +export default { + unknown: "Inconnu", + multipleMatches: "Plusieurs correspondances", + anonymous: "Anonyme" +}; + +// @key: @#@"unknown"@#@ @source: @#@"Unknown"@#@ +// @key: @#@"multipleMatches"@#@ @source: @#@"Multiple matches"@#@ +// @key: @#@"anonymous"@#@ @source: @#@"Anonymous"@#@ diff --git a/packages/ringcentral-widgets/modules/CallLogSectionV2/i18n/index.ts b/packages/ringcentral-widgets/modules/CallLogSectionV2/i18n/index.ts new file mode 100644 index 0000000000..b67573a87a --- /dev/null +++ b/packages/ringcentral-widgets/modules/CallLogSectionV2/i18n/index.ts @@ -0,0 +1,4 @@ +import I18n from '@ringcentral-integration/i18n'; +import loadLocale from './loadLocale'; + +export default new I18n(loadLocale); diff --git a/packages/ringcentral-widgets/modules/CallLogSectionV2/i18n/it-IT.js b/packages/ringcentral-widgets/modules/CallLogSectionV2/i18n/it-IT.js new file mode 100644 index 0000000000..a233a27bf1 --- /dev/null +++ b/packages/ringcentral-widgets/modules/CallLogSectionV2/i18n/it-IT.js @@ -0,0 +1,9 @@ +export default { + unknown: "Sconosciuto", + multipleMatches: "Corrispondenze multiple", + anonymous: "Anonimo" +}; + +// @key: @#@"unknown"@#@ @source: @#@"Unknown"@#@ +// @key: @#@"multipleMatches"@#@ @source: @#@"Multiple matches"@#@ +// @key: @#@"anonymous"@#@ @source: @#@"Anonymous"@#@ diff --git a/packages/ringcentral-widgets/modules/CallLogSectionV2/i18n/ja-JP.js b/packages/ringcentral-widgets/modules/CallLogSectionV2/i18n/ja-JP.js new file mode 100644 index 0000000000..fe623c8059 --- /dev/null +++ b/packages/ringcentral-widgets/modules/CallLogSectionV2/i18n/ja-JP.js @@ -0,0 +1,9 @@ +export default { + unknown: "不明", + multipleMatches: "複数の一致", + anonymous: "匿名" +}; + +// @key: @#@"unknown"@#@ @source: @#@"Unknown"@#@ +// @key: @#@"multipleMatches"@#@ @source: @#@"Multiple matches"@#@ +// @key: @#@"anonymous"@#@ @source: @#@"Anonymous"@#@ diff --git a/packages/ringcentral-widgets/modules/CallLogSectionV2/i18n/ko-KR.js b/packages/ringcentral-widgets/modules/CallLogSectionV2/i18n/ko-KR.js new file mode 100644 index 0000000000..88e08126a8 --- /dev/null +++ b/packages/ringcentral-widgets/modules/CallLogSectionV2/i18n/ko-KR.js @@ -0,0 +1,9 @@ +export default { + unknown: "알 수 없음", + multipleMatches: "여러 일치 항목", + anonymous: "익명" +}; + +// @key: @#@"unknown"@#@ @source: @#@"Unknown"@#@ +// @key: @#@"multipleMatches"@#@ @source: @#@"Multiple matches"@#@ +// @key: @#@"anonymous"@#@ @source: @#@"Anonymous"@#@ diff --git a/packages/ringcentral-widgets/modules/CallLogSectionV2/i18n/loadLocale.ts b/packages/ringcentral-widgets/modules/CallLogSectionV2/i18n/loadLocale.ts new file mode 100644 index 0000000000..12b11cfa2e --- /dev/null +++ b/packages/ringcentral-widgets/modules/CallLogSectionV2/i18n/loadLocale.ts @@ -0,0 +1 @@ +/* loadLocale */ diff --git a/packages/ringcentral-widgets/modules/CallLogSectionV2/i18n/nl-NL.js b/packages/ringcentral-widgets/modules/CallLogSectionV2/i18n/nl-NL.js new file mode 100644 index 0000000000..7c7f7fb24b --- /dev/null +++ b/packages/ringcentral-widgets/modules/CallLogSectionV2/i18n/nl-NL.js @@ -0,0 +1,9 @@ +export default { + unknown: "Onbekend", + multipleMatches: "Meerdere overeenkomsten", + anonymous: "Anoniem" +}; + +// @key: @#@"unknown"@#@ @source: @#@"Unknown"@#@ +// @key: @#@"multipleMatches"@#@ @source: @#@"Multiple matches"@#@ +// @key: @#@"anonymous"@#@ @source: @#@"Anonymous"@#@ diff --git a/packages/ringcentral-widgets/modules/CallLogSectionV2/i18n/pt-BR.js b/packages/ringcentral-widgets/modules/CallLogSectionV2/i18n/pt-BR.js new file mode 100644 index 0000000000..207dba396b --- /dev/null +++ b/packages/ringcentral-widgets/modules/CallLogSectionV2/i18n/pt-BR.js @@ -0,0 +1,9 @@ +export default { + unknown: "Desconhecido", + multipleMatches: "Várias correspondências", + anonymous: "Anônimo" +}; + +// @key: @#@"unknown"@#@ @source: @#@"Unknown"@#@ +// @key: @#@"multipleMatches"@#@ @source: @#@"Multiple matches"@#@ +// @key: @#@"anonymous"@#@ @source: @#@"Anonymous"@#@ diff --git a/packages/ringcentral-widgets/modules/CallLogSectionV2/i18n/pt-PT.js b/packages/ringcentral-widgets/modules/CallLogSectionV2/i18n/pt-PT.js new file mode 100644 index 0000000000..83a5dc1915 --- /dev/null +++ b/packages/ringcentral-widgets/modules/CallLogSectionV2/i18n/pt-PT.js @@ -0,0 +1,9 @@ +export default { + unknown: "Desconhecido", + multipleMatches: "Várias correspondências", + anonymous: "Anónimo" +}; + +// @key: @#@"unknown"@#@ @source: @#@"Unknown"@#@ +// @key: @#@"multipleMatches"@#@ @source: @#@"Multiple matches"@#@ +// @key: @#@"anonymous"@#@ @source: @#@"Anonymous"@#@ diff --git a/packages/ringcentral-widgets/modules/CallLogSectionV2/i18n/zh-CN.js b/packages/ringcentral-widgets/modules/CallLogSectionV2/i18n/zh-CN.js new file mode 100644 index 0000000000..ca411a137a --- /dev/null +++ b/packages/ringcentral-widgets/modules/CallLogSectionV2/i18n/zh-CN.js @@ -0,0 +1,9 @@ +export default { + unknown: "未知", + multipleMatches: "多个匹配项", + anonymous: "匿名" +}; + +// @key: @#@"unknown"@#@ @source: @#@"Unknown"@#@ +// @key: @#@"multipleMatches"@#@ @source: @#@"Multiple matches"@#@ +// @key: @#@"anonymous"@#@ @source: @#@"Anonymous"@#@ diff --git a/packages/ringcentral-widgets/modules/CallLogSectionV2/i18n/zh-HK.js b/packages/ringcentral-widgets/modules/CallLogSectionV2/i18n/zh-HK.js new file mode 100644 index 0000000000..1c7e8d5800 --- /dev/null +++ b/packages/ringcentral-widgets/modules/CallLogSectionV2/i18n/zh-HK.js @@ -0,0 +1,9 @@ +export default { + unknown: "未知", + multipleMatches: "多個相符項目", + anonymous: "匿名" +}; + +// @key: @#@"unknown"@#@ @source: @#@"Unknown"@#@ +// @key: @#@"multipleMatches"@#@ @source: @#@"Multiple matches"@#@ +// @key: @#@"anonymous"@#@ @source: @#@"Anonymous"@#@ diff --git a/packages/ringcentral-widgets/modules/CallLogSectionV2/i18n/zh-TW.js b/packages/ringcentral-widgets/modules/CallLogSectionV2/i18n/zh-TW.js new file mode 100644 index 0000000000..1c7e8d5800 --- /dev/null +++ b/packages/ringcentral-widgets/modules/CallLogSectionV2/i18n/zh-TW.js @@ -0,0 +1,9 @@ +export default { + unknown: "未知", + multipleMatches: "多個相符項目", + anonymous: "匿名" +}; + +// @key: @#@"unknown"@#@ @source: @#@"Unknown"@#@ +// @key: @#@"multipleMatches"@#@ @source: @#@"Multiple matches"@#@ +// @key: @#@"anonymous"@#@ @source: @#@"Anonymous"@#@ diff --git a/packages/ringcentral-widgets/modules/CallLogSectionV2/index.ts b/packages/ringcentral-widgets/modules/CallLogSectionV2/index.ts new file mode 100644 index 0000000000..060128dc3a --- /dev/null +++ b/packages/ringcentral-widgets/modules/CallLogSectionV2/index.ts @@ -0,0 +1,2 @@ +export * from './CallLogSection'; +export * from './CallLogSection.interface'; diff --git a/packages/ringcentral-widgets/modules/CallLogUI/CallLogUI.interface.ts b/packages/ringcentral-widgets/modules/CallLogUI/CallLogUI.interface.ts index f451e67755..3685ec0cba 100644 --- a/packages/ringcentral-widgets/modules/CallLogUI/CallLogUI.interface.ts +++ b/packages/ringcentral-widgets/modules/CallLogUI/CallLogUI.interface.ts @@ -1,14 +1,15 @@ import { ActiveCallControl } from '@ringcentral-integration/commons/modules/ActiveCallControlV2'; +import { AppFeatures } from '@ringcentral-integration/commons/modules/AppFeatures'; import { CallingSettings } from '@ringcentral-integration/commons/modules/CallingSettingsV2'; import CallLogger from '@ringcentral-integration/commons/modules/CallLogger'; import ConnectivityMonitor from '@ringcentral-integration/commons/modules/ConnectivityMonitor'; import DateTimeFormat from '@ringcentral-integration/commons/modules/DateTimeFormat'; import { ForwardingNumber } from '@ringcentral-integration/commons/modules/ForwardingNumberV2'; -import Locale from '@ringcentral-integration/commons/modules/Locale'; +import { Locale } from '@ringcentral-integration/commons/modules/Locale'; import RateLimiter from '@ringcentral-integration/commons/modules/RateLimiter'; import RegionSettings from '@ringcentral-integration/commons/modules/RegionSettings'; -import { ExtensionFeatures } from '../../../ringcentral-integration/modules/ExtensionFeatures'; import { CallLogPanelProps } from '../../components/CallLogPanel'; +import { CallLogSection as CallLogSectionV2 } from '../CallLogSectionV2'; import CallLogSection from '../CallLogSection'; import { RouterInteraction } from '../RouterInteraction'; @@ -24,10 +25,10 @@ export interface Deps { rateLimiter: RateLimiter; regionSettings: RegionSettings; dateTimeFormat: DateTimeFormat; - callLogSection: CallLogSection; + callLogSection: CallLogSection | CallLogSectionV2; routerInteraction: RouterInteraction; activeCallControl: ActiveCallControl; - extensionFeatures: ExtensionFeatures; + appFeatures: AppFeatures; connectivityMonitor: ConnectivityMonitor; callingSettings: CallingSettings; forwardingNumber: ForwardingNumber; diff --git a/packages/ringcentral-widgets/modules/CallLogUI/CallLogUI.tsx b/packages/ringcentral-widgets/modules/CallLogUI/CallLogUI.tsx index f29339e6e1..774e94016e 100644 --- a/packages/ringcentral-widgets/modules/CallLogUI/CallLogUI.tsx +++ b/packages/ringcentral-widgets/modules/CallLogUI/CallLogUI.tsx @@ -37,14 +37,14 @@ const CallLogCallControlRenderer = ( 'CallLogSection', 'RouterInteraction', 'ActiveCallControl', - 'ExtensionFeatures', + 'AppFeatures', 'ConnectivityMonitor', 'CallingSettings', 'ForwardingNumber', { dep: 'CallLogUIOptions', optional: true }, ], }) -export abstract class CallLogUIBase +export abstract class CallLogUIBase extends RcUIModuleV2 implements CallLogUIInterface { constructor({ deps, ...options }: RcModuleOptions) { @@ -64,7 +64,7 @@ export abstract class CallLogUIBase callLogSection, routerInteraction, activeCallControl, - extensionFeatures, + appFeatures, connectivityMonitor, callingSettings, forwardingNumber, @@ -80,7 +80,7 @@ export abstract class CallLogUIBase locale.ready && regionSettings.ready && dateTimeFormat.ready && - extensionFeatures.ready && + appFeatures.ready && (!callLogger || callLogger.ready) ), isInTransferPage, diff --git a/packages/ringcentral-widgets/modules/CallingSettingsUI/CallingSettingsUI.interface.ts b/packages/ringcentral-widgets/modules/CallingSettingsUI/CallingSettingsUI.interface.ts index 15dd782508..65a1eac2b9 100644 --- a/packages/ringcentral-widgets/modules/CallingSettingsUI/CallingSettingsUI.interface.ts +++ b/packages/ringcentral-widgets/modules/CallingSettingsUI/CallingSettingsUI.interface.ts @@ -1,6 +1,6 @@ import { CallingSettings } from '@ringcentral-integration/commons/modules/CallingSettingsV2'; -import { Brand } from '@ringcentral-integration/commons/modules/BrandV2'; -import { Locale } from '@ringcentral-integration/commons/modules/LocaleV2'; +import { Brand } from '@ringcentral-integration/commons/modules/Brand'; +import { Locale } from '@ringcentral-integration/commons/modules/Locale'; import { Webphone } from '@ringcentral-integration/commons/modules/WebphoneV2'; import { RouterInteraction } from '../RouterInteraction'; diff --git a/packages/ringcentral-widgets/modules/CallingSettingsUI/CallingSettingsUI.tsx b/packages/ringcentral-widgets/modules/CallingSettingsUI/CallingSettingsUI.tsx index 32dc0044f7..56bc353102 100644 --- a/packages/ringcentral-widgets/modules/CallingSettingsUI/CallingSettingsUI.tsx +++ b/packages/ringcentral-widgets/modules/CallingSettingsUI/CallingSettingsUI.tsx @@ -72,6 +72,7 @@ class CallingSettingsUI extends RcUIModuleV2 { defaultIncomingAudio: this._deps.webphone?.defaultIncomingAudio, defaultOutgoingAudioFile: this._deps.webphone?.outgoingAudioFile, defaultOutgoingAudio: this._deps.webphone?.outgoingAudio, + jupiterAppName: this._deps.callingSettings.jupiterAppName, }; } diff --git a/packages/ringcentral-widgets/modules/CallsListUI/CallsListUI.interface.ts b/packages/ringcentral-widgets/modules/CallsListUI/CallsListUI.interface.ts index f8cf033317..2461dbe73d 100644 --- a/packages/ringcentral-widgets/modules/CallsListUI/CallsListUI.interface.ts +++ b/packages/ringcentral-widgets/modules/CallsListUI/CallsListUI.interface.ts @@ -1,5 +1,6 @@ import { Call as ICall } from '@ringcentral-integration/commons/interfaces/Call.interface'; -import { Brand } from '@ringcentral-integration/commons/modules/BrandV2'; +import { AppFeatures } from '@ringcentral-integration/commons/modules/AppFeatures'; +import { Brand } from '@ringcentral-integration/commons/modules/Brand'; import { CallHistory, HistoryCall, @@ -19,11 +20,10 @@ import { FormatDateTimeOptions, } from '@ringcentral-integration/commons/modules/DateTimeFormatV2'; import { ExtensionInfo } from '@ringcentral-integration/commons/modules/ExtensionInfoV2'; -import { Locale } from '@ringcentral-integration/commons/modules/LocaleV2'; +import { Locale } from '@ringcentral-integration/commons/modules/Locale'; import { RateLimiter } from '@ringcentral-integration/commons/modules/RateLimiterV2'; import { RegionSettings } from '@ringcentral-integration/commons/modules/RegionSettingsV2'; import { Webphone } from '@ringcentral-integration/commons/modules/WebphoneV2'; -import { ExtensionFeatures } from '../../../ringcentral-integration/modules/ExtensionFeatures'; import { ContactDetailsUI, RouteParams } from '../ContactDetailsUI'; import { RouterInteraction } from '../RouterInteraction'; @@ -33,7 +33,7 @@ export interface Deps { callMonitor: CallMonitor; locale: Locale; regionSettings: RegionSettings; - extensionFeatures: ExtensionFeatures; + appFeatures: AppFeatures; callHistory: CallHistory; connectivityMonitor: ConnectivityMonitor; rateLimiter: RateLimiter; @@ -82,6 +82,7 @@ export interface CallsListUIProps { loggingMap: Record; showSpinner: boolean; readTextPermission: boolean; + enableCDC: boolean; } export interface OnCreateContactOptions { diff --git a/packages/ringcentral-widgets/modules/CallsListUI/CallsListUI.ts b/packages/ringcentral-widgets/modules/CallsListUI/CallsListUI.ts index 0c8fd29ee8..744c16fedb 100644 --- a/packages/ringcentral-widgets/modules/CallsListUI/CallsListUI.ts +++ b/packages/ringcentral-widgets/modules/CallsListUI/CallsListUI.ts @@ -1,8 +1,8 @@ -import { RcUIModuleV2 } from '@ringcentral-integration/core'; import { Module } from '@ringcentral-integration/commons/lib/di'; import formatNumber from '@ringcentral-integration/commons/lib/formatNumber'; import { FormatDateTimeOptions } from '@ringcentral-integration/commons/modules/DateTimeFormatV2'; -import { ToNumber } from '../../../ringcentral-integration/modules/ComposeTextV2'; +import { RcUIModuleV2 } from '@ringcentral-integration/core'; +import { ToNumber } from '@ringcentral-integration/commons/modules/ComposeTextV2'; import { RouteParams } from '../ContactDetailsUI'; import { CallsListUIFunctions, @@ -23,7 +23,6 @@ export const FILTER_THRESHOLD: number = 500; 'CallMonitor', 'Locale', 'RegionSettings', - 'ExtensionFeatures', 'CallHistory', 'ConnectivityMonitor', 'RateLimiter', @@ -34,6 +33,7 @@ export const FILTER_THRESHOLD: number = 500; 'ContactSearch', 'RouterInteraction', 'ContactDetailsUI', + 'AppFeatures', { dep: 'DialerUI', optional: true }, { dep: 'DialerUI', optional: true }, { dep: 'CallLogger', optional: true }, @@ -57,7 +57,7 @@ export class CallsListUI extends RcUIModuleV2 { callMonitor, locale, regionSettings, - extensionFeatures, + appFeatures, callHistory, connectivityMonitor, rateLimiter, @@ -76,8 +76,8 @@ export class CallsListUI extends RcUIModuleV2 { otherDeviceCalls: callMonitor.otherDeviceCalls, areaCode: regionSettings.areaCode, countryCode: regionSettings.countryCode, - outboundSmsPermission: extensionFeatures.hasOutboundSMSPermission, - internalSmsPermission: extensionFeatures.hasInternalSMSPermission, + outboundSmsPermission: appFeatures.hasOutboundSMSPermission, + internalSmsPermission: appFeatures.hasInternalSMSPermission, brand: brand.fullName, showContactDisplayPlaceholder, autoLog: !!(callLogger && callLogger.autoLog), @@ -92,12 +92,13 @@ export class CallsListUI extends RcUIModuleV2 { regionSettings.ready && dateTimeFormat.ready && connectivityMonitor.ready && - extensionFeatures.ready && + appFeatures.ready && (!call || call.ready) && (!composeText || composeText.ready) && (!callLogger || callLogger.ready) ), - readTextPermission: extensionFeatures.hasReadTextPermission, + readTextPermission: appFeatures.hasReadTextPermission, + enableCDC: appFeatures.isCDCEnabled, }; } diff --git a/packages/ringcentral-widgets/modules/ComposeTextUI/ComposeTextUI.interface.ts b/packages/ringcentral-widgets/modules/ComposeTextUI/ComposeTextUI.interface.ts index 285a8673b5..4cfb1c8787 100644 --- a/packages/ringcentral-widgets/modules/ComposeTextUI/ComposeTextUI.interface.ts +++ b/packages/ringcentral-widgets/modules/ComposeTextUI/ComposeTextUI.interface.ts @@ -1,4 +1,5 @@ -import { Brand } from '@ringcentral-integration/commons/modules/BrandV2'; +import { AppFeatures } from '@ringcentral-integration/commons/modules/AppFeatures'; +import { Brand } from '@ringcentral-integration/commons/modules/Brand'; import { ComposeText, ToNumber, @@ -7,18 +8,17 @@ import { ConnectivityMonitor } from '@ringcentral-integration/commons/modules/Co import { ContactSearch, Entities, -} from '../../../ringcentral-integration/modules/ContactSearchV2'; -import { Conversations } from '../../../ringcentral-integration/modules/ConversationsV2'; -import { ExtensionFeatures } from '../../../ringcentral-integration/modules/ExtensionFeatures'; -import { Locale } from '../../../ringcentral-integration/modules/LocaleV2'; +} from '@ringcentral-integration/commons/modules/ContactSearchV2'; +import { Conversations } from '@ringcentral-integration/commons/modules/ConversationsV2'; +import { Locale } from '@ringcentral-integration/commons/modules/Locale'; import { Attachment, MessageSender, SenderNumber, -} from '../../../ringcentral-integration/modules/MessageSenderV2'; -import { MessageStore } from '../../../ringcentral-integration/modules/MessageStoreV2'; -import { RateLimiter } from '../../../ringcentral-integration/modules/RateLimiterV2'; -import { RegionSettings } from '../../../ringcentral-integration/modules/RegionSettingsV2'; +} from '@ringcentral-integration/commons/modules/MessageSenderV2'; +import { MessageStore } from '@ringcentral-integration/commons/modules/MessageStoreV2'; +import { RateLimiter } from '@ringcentral-integration/commons/modules/RateLimiterV2'; +import { RegionSettings } from '@ringcentral-integration/commons/modules/RegionSettingsV2'; import { RouterInteraction } from '../RouterInteraction'; export interface Deps { @@ -32,7 +32,7 @@ export interface Deps { messageStore: MessageStore; rateLimiter: RateLimiter; regionSettings: RegionSettings; - extensionFeatures: ExtensionFeatures; + appFeatures: AppFeatures; routerInteraction: RouterInteraction; } // TODO: Move to and align with ComposeTextPanel when refactoring ComposeTextPanel to TypeScript diff --git a/packages/ringcentral-widgets/modules/ComposeTextUI/ComposeTextUI.ts b/packages/ringcentral-widgets/modules/ComposeTextUI/ComposeTextUI.ts index cfa1f5f7cb..2541f257cc 100644 --- a/packages/ringcentral-widgets/modules/ComposeTextUI/ComposeTextUI.ts +++ b/packages/ringcentral-widgets/modules/ComposeTextUI/ComposeTextUI.ts @@ -1,10 +1,10 @@ +import Module from '@ringcentral-integration/commons/lib/di/decorators/module'; +import formatNumber from '@ringcentral-integration/commons/lib/formatNumber'; import { RcUIModuleV2, UIFunctions, UIProps, } from '@ringcentral-integration/core'; -import Module from '@ringcentral-integration/commons/lib/di/decorators/module'; -import formatNumber from '@ringcentral-integration/commons/lib/formatNumber'; import { ComposeTextPanelProps, ComposeTextUIComponentProps, @@ -28,7 +28,7 @@ import { 'MessageStore', 'RateLimiter', 'RegionSettings', - 'ExtensionFeatures', + 'AppFeatures', 'RouterInteraction', ], }) @@ -49,7 +49,7 @@ export class ComposeTextUI extends RcUIModuleV2 { messageSender, connectivityMonitor, rateLimiter, - extensionFeatures, + appFeatures, contactSearch, } = this._deps; const isContentEmpty = @@ -70,13 +70,13 @@ export class ComposeTextUI extends RcUIModuleV2 { typingToNumber: composeText.typingToNumber, toNumbers: composeText.toNumbers, messageText: composeText.messageText, - outboundSMS: extensionFeatures.hasOutboundSMSPermission, + outboundSMS: appFeatures.hasOutboundSMSPermission, searchContactList: contactSearch.sortedResult, showSpinner: !( composeText.ready && locale.ready && messageSender.ready && - extensionFeatures.ready && + appFeatures.ready && contactSearch.ready ), inputExpandable, diff --git a/packages/ringcentral-widgets/modules/ConferenceParticipantUI/ConferenceParticipantUI.interface.ts b/packages/ringcentral-widgets/modules/ConferenceParticipantUI/ConferenceParticipantUI.interface.ts index 1935fa5172..671a3ec3d9 100644 --- a/packages/ringcentral-widgets/modules/ConferenceParticipantUI/ConferenceParticipantUI.interface.ts +++ b/packages/ringcentral-widgets/modules/ConferenceParticipantUI/ConferenceParticipantUI.interface.ts @@ -1,4 +1,4 @@ -import { Locale } from '@ringcentral-integration/commons/modules/LocaleV2'; +import { Locale } from '@ringcentral-integration/commons/modules/Locale'; import { ConferenceCall, Party, diff --git a/packages/ringcentral-widgets/modules/ConferenceUI/index.js b/packages/ringcentral-widgets/modules/ConferenceUI/index.js index 7914b4cc46..90f1411f43 100644 --- a/packages/ringcentral-widgets/modules/ConferenceUI/index.js +++ b/packages/ringcentral-widgets/modules/ConferenceUI/index.js @@ -1,7 +1,7 @@ import { Module } from '@ringcentral-integration/commons/lib/di'; -import { reduce, map } from 'ramda'; -import RcUIModule from '../../lib/RcUIModule'; +import { map, reduce } from 'ramda'; import countryNames from '../../lib/countryNames'; +import RcUIModule from '../../lib/RcUIModule'; @Module({ name: 'ConferenceUI', @@ -10,7 +10,7 @@ import countryNames from '../../lib/countryNames'; 'RegionSettings', 'Locale', 'ComposeText', - 'ExtensionFeatures', + 'AppFeatures', 'Brand', 'Alert', 'RouterInteraction', @@ -23,7 +23,7 @@ export default class ConferenceUI extends RcUIModule { regionSettings, locale, composeText, - extensionFeatures, + appFeatures, brand, alert, routerInteraction, @@ -37,7 +37,7 @@ export default class ConferenceUI extends RcUIModule { this._regionSettings = regionSettings; this._locale = locale; this._composeText = composeText; - this._extensionFeatures = extensionFeatures; + this._appFeatures = appFeatures; this._brand = brand; this._alert = alert; this._routerInteraction = routerInteraction; @@ -87,10 +87,7 @@ export default class ConferenceUI extends RcUIModule { participantCode, allowJoinBeforeHost, additionalNumbers: this._conference.additionalNumbers, - disableTxtBtn: !( - this._extensionFeatures.hasOutboundSMSPermission || - this._extensionFeatures.hasInternalSMSPermission - ), + disableTxtBtn: !this._appFeatures.hasComposeTextPermission, countryCode: this._regionSettings.countryCode, areaCode: this._regionSettings.areaCode, currentLocale: this._locale.currentLocale, diff --git a/packages/ringcentral-widgets/modules/ContactDetailsUI/ContactDetailsUI.interface.ts b/packages/ringcentral-widgets/modules/ContactDetailsUI/ContactDetailsUI.interface.ts index 28fd44d83a..348368936c 100644 --- a/packages/ringcentral-widgets/modules/ContactDetailsUI/ContactDetailsUI.interface.ts +++ b/packages/ringcentral-widgets/modules/ContactDetailsUI/ContactDetailsUI.interface.ts @@ -1,12 +1,12 @@ +import { AppFeatures } from '@ringcentral-integration/commons/modules/AppFeatures'; import { Call } from '@ringcentral-integration/commons/modules/CallV2'; import { ComposeText } from '@ringcentral-integration/commons/modules/ComposeTextV2'; import { ContactSearch } from '@ringcentral-integration/commons/modules/ContactSearchV2'; import { Contacts } from '@ringcentral-integration/commons/modules/ContactsV2'; import { ExtensionInfo } from '@ringcentral-integration/commons/modules/ExtensionInfoV2'; -import { Locale } from '@ringcentral-integration/commons/modules/LocaleV2'; +import { Locale } from '@ringcentral-integration/commons/modules/Locale'; import { RateLimiter } from '@ringcentral-integration/commons/modules/RateLimiterV2'; import { RegionSettings } from '@ringcentral-integration/commons/modules/RegionSettingsV2'; -import { ExtensionFeatures } from '../../../ringcentral-integration/modules/ExtensionFeatures'; import { ConnectivityManager } from '../ConnectivityManager'; import DialerUI from '../DialerUI'; import { RouterInteraction } from '../RouterInteraction'; @@ -22,7 +22,7 @@ export interface Deps { contactSearch: ContactSearch; contacts: Contacts; extensionInfo: ExtensionInfo; - extensionFeatures: ExtensionFeatures; + appFeatures: AppFeatures; rateLimiter: RateLimiter; connectivityManager: ConnectivityManager; regionSettings: RegionSettings; diff --git a/packages/ringcentral-widgets/modules/ContactDetailsUI/ContactDetailsUI.ts b/packages/ringcentral-widgets/modules/ContactDetailsUI/ContactDetailsUI.ts index f8558561d6..b327754de3 100644 --- a/packages/ringcentral-widgets/modules/ContactDetailsUI/ContactDetailsUI.ts +++ b/packages/ringcentral-widgets/modules/ContactDetailsUI/ContactDetailsUI.ts @@ -38,7 +38,7 @@ const DEFAULT_COMPOSE_TEXT_ROUTE = '/composeText'; 'ContactSearch', 'Contacts', 'ExtensionInfo', - 'ExtensionFeatures', + 'AppFeatures', 'RateLimiter', 'RegionSettings', 'ConnectivityManager', @@ -163,7 +163,7 @@ export class ContactDetailsUI extends RcUIModuleV2 { this.currentContactReadyState === contactReadyStates.loaded && this._deps.locale.ready && this._deps.contactSearch.ready && - this._deps.extensionFeatures.ready + this._deps.appFeatures.ready ), }; } @@ -210,9 +210,9 @@ export class ContactDetailsUI extends RcUIModuleV2 { return phoneNumber; }, canTextButtonShow: (phoneType: string) => { - const outboundSmsPermission = this._deps.extensionFeatures + const outboundSmsPermission = this._deps.appFeatures .hasOutboundSMSPermission; - const internalSmsPermission = this._deps.extensionFeatures + const internalSmsPermission = this._deps.appFeatures .hasInternalSMSPermission; // guess this statement is to avoid exception const isClickToTextEnabled = !!this._deps.composeText; @@ -226,7 +226,7 @@ export class ContactDetailsUI extends RcUIModuleV2 { }, canCallButtonShow: (phoneType: string) => { const isClickToDialEnabled = !!( - this._deps.dialerUI && this._deps.extensionFeatures.isCallingEnabled + this._deps.dialerUI && this._deps.appFeatures.isCallingEnabled ); return isClickToDialEnabled && phoneType !== phoneTypes.fax; }, diff --git a/packages/ringcentral-widgets/modules/ContactListUI/ContactListUI.interface.ts b/packages/ringcentral-widgets/modules/ContactListUI/ContactListUI.interface.ts index 86b56b8d79..c8b5fb8d8c 100644 --- a/packages/ringcentral-widgets/modules/ContactListUI/ContactListUI.interface.ts +++ b/packages/ringcentral-widgets/modules/ContactListUI/ContactListUI.interface.ts @@ -1,5 +1,5 @@ import { Auth } from '@ringcentral-integration/commons/modules/AuthV2'; -import { Locale } from '@ringcentral-integration/commons/modules/LocaleV2'; +import { Locale } from '@ringcentral-integration/commons/modules/Locale'; import { ExtensionInfo } from '@ringcentral-integration/commons/modules/ExtensionInfoV2'; import { IContact, diff --git a/packages/ringcentral-widgets/modules/ConversationUI/ConversationUI.interface.ts b/packages/ringcentral-widgets/modules/ConversationUI/ConversationUI.interface.ts index 8eb3402542..d21229028a 100644 --- a/packages/ringcentral-widgets/modules/ConversationUI/ConversationUI.interface.ts +++ b/packages/ringcentral-widgets/modules/ConversationUI/ConversationUI.interface.ts @@ -1,24 +1,25 @@ -import GetMessageInfoResponse from 'ringcentral-client/build/definitions/GetMessageInfoResponse'; -import { Brand } from '@ringcentral-integration/commons/modules/BrandV2'; -import { Locale } from '@ringcentral-integration/commons/modules/LocaleV2'; +import { Entity } from '@ringcentral-integration/commons/interfaces/Entity.interface'; +import { Message } from '@ringcentral-integration/commons/interfaces/MessageStore.model'; +import { Correspondent } from '@ringcentral-integration/commons/lib/messageHelper'; +import { Brand } from '@ringcentral-integration/commons/modules/Brand'; +import { ConnectivityMonitor } from '@ringcentral-integration/commons/modules/ConnectivityMonitorV2'; +import { ContactMatcher } from '@ringcentral-integration/commons/modules/ContactMatcherV2'; import { ConversationLogger } from '@ringcentral-integration/commons/modules/ConversationLoggerV2'; -import { - DateTimeFormat, - FormatDateTimeOptions, -} from '@ringcentral-integration/commons/modules/DateTimeFormatV2'; -import { RegionSettings } from '@ringcentral-integration/commons/modules/RegionSettingsV2'; import { Conversations, CurrentConversation, } from '@ringcentral-integration/commons/modules/ConversationsV2'; -import { RateLimiter } from '@ringcentral-integration/commons/modules/RateLimiterV2'; -import { ConnectivityMonitor } from '@ringcentral-integration/commons/modules/ConnectivityMonitorV2'; -import { MessageStore } from '@ringcentral-integration/commons/modules/MessageStoreV2'; -import { ContactMatcher } from '@ringcentral-integration/commons/modules/ContactMatcherV2'; -import { Correspondent } from '@ringcentral-integration/commons/lib/messageHelper'; -import { Message } from '@ringcentral-integration/commons/interfaces/MessageStore.model'; +import { + DateTimeFormat, + FormatDateTimeOptions, +} from '@ringcentral-integration/commons/modules/DateTimeFormatV2'; +import { Locale } from '@ringcentral-integration/commons/modules/Locale'; import { Attachment } from '@ringcentral-integration/commons/modules/MessageSenderV2'; -import { Entity } from '@ringcentral-integration/commons/interfaces/Entity.interface'; +import { MessageStore } from '@ringcentral-integration/commons/modules/MessageStoreV2'; +import { RateLimiter } from '@ringcentral-integration/commons/modules/RateLimiterV2'; +import { RegionSettings } from '@ringcentral-integration/commons/modules/RegionSettingsV2'; +import GetMessageInfoResponse from 'ringcentral-client/build/definitions/GetMessageInfoResponse'; +import { AppFeatures } from '@ringcentral-integration/commons/modules/AppFeatures/AppFeatures'; import { RouterInteraction } from '../RouterInteraction'; export interface ConversationUIOptions { @@ -26,6 +27,7 @@ export interface ConversationUIOptions { } export interface Deps { + appFeatures: AppFeatures; brand: Brand; locale: Locale; conversationLogger: ConversationLogger; @@ -101,6 +103,7 @@ export interface ConversationPanelProps { inputExpandable: boolean; shouldLogSelectRecord?: boolean; contactPlaceholder?: string; + dropdownClassName?: string; replyToReceivers: ( text: string, attachments?: Attachment[], @@ -125,4 +128,6 @@ export interface ConversationPanelProps { ): React.ReactElement; onSelectContact?(options: OnSelectContactOptions): Promise | void; restrictSendMessage?(...args: any): boolean; + renderContactList?: (entity: { name: string; labelType: string }) => any; + enableCDC: boolean; } diff --git a/packages/ringcentral-widgets/modules/ConversationUI/ConversationUI.ts b/packages/ringcentral-widgets/modules/ConversationUI/ConversationUI.ts index 6909dc62b7..666175d490 100644 --- a/packages/ringcentral-widgets/modules/ConversationUI/ConversationUI.ts +++ b/packages/ringcentral-widgets/modules/ConversationUI/ConversationUI.ts @@ -17,6 +17,7 @@ import { @Module({ name: 'ConversationUI', deps: [ + 'AppFeatures', 'Brand', 'Locale', 'DateTimeFormat', @@ -32,7 +33,7 @@ import { ], }) export class ConversationUI extends RcUIModuleV2 { - constructor(deps: Deps) { + constructor(deps: Deps & T) { super({ deps, }); @@ -56,6 +57,7 @@ export class ConversationUI extends RcUIModuleV2 { conversations, rateLimiter, connectivityMonitor, + appFeatures, } = this._deps; const disableLinks = rateLimiter.throttling || !connectivityMonitor.connectivity; @@ -97,6 +99,7 @@ export class ConversationUI extends RcUIModuleV2 { perPage, loadingNextPage: conversations.loadingOldMessages, inputExpandable, + enableCDC: appFeatures.isCDCEnabled, }; } diff --git a/packages/ringcentral-widgets/modules/ConversationsUI/ConversationsUI.interface.ts b/packages/ringcentral-widgets/modules/ConversationsUI/ConversationsUI.interface.ts index cea3bed085..de8adfa3e0 100644 --- a/packages/ringcentral-widgets/modules/ConversationsUI/ConversationsUI.interface.ts +++ b/packages/ringcentral-widgets/modules/ConversationsUI/ConversationsUI.interface.ts @@ -1,7 +1,7 @@ -import { ObjectMapValue } from '@ringcentral-integration/core/lib/ObjectMap'; import messageTypes from '@ringcentral-integration/commons/enums/messageTypes'; import { Entity } from '@ringcentral-integration/commons/interfaces/Entity.interface'; -import { Brand } from '@ringcentral-integration/commons/modules/BrandV2'; +import { AppFeatures } from '@ringcentral-integration/commons/modules/AppFeatures'; +import { Brand } from '@ringcentral-integration/commons/modules/Brand'; import { Call } from '@ringcentral-integration/commons/modules/CallV2'; import { ComposeText } from '@ringcentral-integration/commons/modules/ComposeTextV2'; import { ConnectivityMonitor } from '@ringcentral-integration/commons/modules/ConnectivityMonitorV2'; @@ -17,12 +17,12 @@ import { DateTimeFormat, FormatDateTimeOptions, } from '@ringcentral-integration/commons/modules/DateTimeFormatV2'; -import { ExtensionFeatures } from '@ringcentral-integration/commons/modules/ExtensionFeatures'; import { ExtensionInfo } from '@ringcentral-integration/commons/modules/ExtensionInfoV2'; -import { Locale } from '@ringcentral-integration/commons/modules/LocaleV2'; +import { Locale } from '@ringcentral-integration/commons/modules/Locale'; import { MessageStore } from '@ringcentral-integration/commons/modules/MessageStoreV2'; import { RateLimiter } from '@ringcentral-integration/commons/modules/RateLimiterV2'; import { RegionSettings } from '@ringcentral-integration/commons/modules/RegionSettingsV2'; +import { ObjectMapValue } from '@ringcentral-integration/core/lib/ObjectMap'; import { ContactDetailsUI } from '../ContactDetailsUI'; import { RouterInteraction } from '../RouterInteraction'; @@ -31,13 +31,13 @@ export interface ConversationsUIOptions { } export interface Deps { + appFeatures: AppFeatures; brand: Brand; locale: Locale; conversations: Conversations; contactMatcher: ContactMatcher; dateTimeFormat: DateTimeFormat; regionSettings: RegionSettings; - extensionFeatures: ExtensionFeatures; call: Call; conversationLogger: ConversationLogger; connectivityMonitor: ConnectivityMonitor; @@ -181,4 +181,7 @@ export interface ConversationsPanelProps { conversation: CurrentConversation; }) => Promise | void; contactPlaceholder?: string; + dropdownClassName?: string; + renderContactList?: (entity: { name: string; labelType: string }) => any; + enableCDC: boolean; } diff --git a/packages/ringcentral-widgets/modules/ConversationsUI/ConversationsUI.ts b/packages/ringcentral-widgets/modules/ConversationsUI/ConversationsUI.ts index 28b24e277a..bec7e6fc3a 100644 --- a/packages/ringcentral-widgets/modules/ConversationsUI/ConversationsUI.ts +++ b/packages/ringcentral-widgets/modules/ConversationsUI/ConversationsUI.ts @@ -1,13 +1,13 @@ +import { Module } from '@ringcentral-integration/commons/lib/di'; import { RcUIModuleV2, UIFunctions, UIProps, } from '@ringcentral-integration/core'; -import { Module } from '@ringcentral-integration/commons/lib/di'; import { - Deps, ConversationsContainerProps, ConversationsPanelProps, + Deps, } from './ConversationsUI.interface'; @Module({ @@ -18,7 +18,7 @@ import { 'Conversations', 'DateTimeFormat', 'RegionSettings', - 'ExtensionFeatures', + 'AppFeatures', 'Call', 'ConnectivityMonitor', 'RateLimiter', @@ -54,7 +54,7 @@ export class ConversationsUI extends RcUIModuleV2 { contactMatcher, dateTimeFormat, regionSettings, - extensionFeatures, + appFeatures, call, conversationLogger, connectivityMonitor, @@ -84,9 +84,9 @@ export class ConversationsUI extends RcUIModuleV2 { connectivityManager.isWebphoneInitializing || rateLimiter.throttling, disableClickToDial: !(call && call.isIdle), - outboundSmsPermission: extensionFeatures.hasOutboundSMSPermission, - internalSmsPermission: extensionFeatures.hasInternalSMSPermission, - composeTextPermission: extensionFeatures.hasComposeTextPermission, + outboundSmsPermission: appFeatures.hasOutboundSMSPermission, + internalSmsPermission: appFeatures.hasInternalSMSPermission, + composeTextPermission: appFeatures.hasComposeTextPermission, loggingMap: conversationLogger && conversationLogger.loggingMap, showSpinner: !( locale.ready && @@ -94,7 +94,7 @@ export class ConversationsUI extends RcUIModuleV2 { (!contactMatcher || contactMatcher.ready) && dateTimeFormat.ready && regionSettings.ready && - extensionFeatures.ready && + appFeatures.ready && connectivityMonitor.ready && rateLimiter.ready && (!call || call.ready) && @@ -106,10 +106,11 @@ export class ConversationsUI extends RcUIModuleV2 { textUnreadCounts: messageStore.textUnreadCounts, voiceUnreadCounts: messageStore.voiceUnreadCounts, faxUnreadCounts: messageStore.faxUnreadCounts, - readTextPermission: extensionFeatures.hasReadTextPermission, - readVoicemailPermission: extensionFeatures.hasVoicemailPermission, - readFaxPermission: extensionFeatures.hasReadFaxPermission, + readTextPermission: appFeatures.hasReadTextPermission, + readVoicemailPermission: appFeatures.hasVoicemailPermission, + readFaxPermission: appFeatures.hasReadFaxPermission, loadingNextPage: conversations.loadingOldConversations, + enableCDC: appFeatures.isCDCEnabled, }; } @@ -137,7 +138,7 @@ export class ConversationsUI extends RcUIModuleV2 { contactDetailsUI, composeText, contactSearch, - extensionFeatures, + appFeatures, } = this._deps; return { @@ -166,7 +167,7 @@ export class ConversationsUI extends RcUIModuleV2 { } : undefined, onClickToDial: - dialerUI && extensionFeatures.isCallingEnabled + dialerUI && appFeatures.isCallingEnabled ? (recipient) => { if (call.isIdle) { routerInteraction.push(dialerRoute); @@ -176,7 +177,7 @@ export class ConversationsUI extends RcUIModuleV2 { } } : undefined, - onClickToSms: extensionFeatures.hasComposeTextPermission + onClickToSms: appFeatures.hasComposeTextPermission ? (contact, isDummyContact = false) => { if (routerInteraction) { routerInteraction.push(composeTextRoute); diff --git a/packages/ringcentral-widgets/modules/DialerAndCallsTabUI/DialerAndCallsTabUI.interface.ts b/packages/ringcentral-widgets/modules/DialerAndCallsTabUI/DialerAndCallsTabUI.interface.ts index 16e72e57c0..d2b10bad29 100644 --- a/packages/ringcentral-widgets/modules/DialerAndCallsTabUI/DialerAndCallsTabUI.interface.ts +++ b/packages/ringcentral-widgets/modules/DialerAndCallsTabUI/DialerAndCallsTabUI.interface.ts @@ -1,4 +1,4 @@ -import { Locale } from '@ringcentral-integration/commons/modules/LocaleV2'; +import { Locale } from '@ringcentral-integration/commons/modules/Locale'; import { CallingSettings } from '@ringcentral-integration/commons/modules/CallingSettingsV2'; import { Webphone } from '@ringcentral-integration/commons/modules/WebphoneV2'; import { CallMonitor } from '@ringcentral-integration/commons/modules/CallMonitorV2'; diff --git a/packages/ringcentral-widgets/modules/DialerUI/index.js b/packages/ringcentral-widgets/modules/DialerUI/index.js index 23e2cb9878..9822183d35 100644 --- a/packages/ringcentral-widgets/modules/DialerUI/index.js +++ b/packages/ringcentral-widgets/modules/DialerUI/index.js @@ -258,6 +258,13 @@ export default class DialerUI extends RcUIModule { ); } + get isShowAnonymous() { + return ( + this._extensionFeatures.ready && + this._extensionFeatures.features?.BlockingCallerId?.available + ); + } + getUIProps() { return { currentLocale: this._locale.currentLocale, @@ -280,6 +287,7 @@ export default class DialerUI extends RcUIModule { isLastInputFromDialpad: this.isLastInputFromDialpad, disableFromField: this.disableFromField, useV2: this._useV2, + showAnonymous: this.isShowAnonymous, }; } diff --git a/packages/ringcentral-widgets/modules/ForwardUI/ForwardUI.interface.ts b/packages/ringcentral-widgets/modules/ForwardUI/ForwardUI.interface.ts index 36c48f227d..5533478e1c 100644 --- a/packages/ringcentral-widgets/modules/ForwardUI/ForwardUI.interface.ts +++ b/packages/ringcentral-widgets/modules/ForwardUI/ForwardUI.interface.ts @@ -1,4 +1,4 @@ -import Locale from '@ringcentral-integration/commons/modules/Locale'; +import { Locale } from '@ringcentral-integration/commons/modules/Locale'; import { ActiveCallControl } from '@ringcentral-integration/commons/modules/ActiveCallControlV2'; import RouterInteraction from '../RouterInteraction'; diff --git a/packages/ringcentral-widgets/modules/GenericMeetingUI/index.ts b/packages/ringcentral-widgets/modules/GenericMeetingUI/index.ts index d0d8478168..2de0a6e117 100644 --- a/packages/ringcentral-widgets/modules/GenericMeetingUI/index.ts +++ b/packages/ringcentral-widgets/modules/GenericMeetingUI/index.ts @@ -1,16 +1,37 @@ +import { any, find } from 'ramda'; import { Module } from '@ringcentral-integration/commons/lib/di'; -import { RcVMeetingModel } from '@ringcentral-integration/commons/interfaces/Rcv.model'; +import { + RcVMeetingModel, + RcVSettingLocks, +} from '@ringcentral-integration/commons/interfaces/Rcv.model'; +import { + RcvDelegator, + AUTH_USER_TYPE, + RCV_WAITING_ROOM_MODE, + RCV_E2EE_DEFAULT_SECURITY_OPTIONS, + DisableE2eeWhenRelatedOptionMatch, + DISABLE_E2EE_WHEN_RELATED_OPTION_MATCH, + JBH_LABEL, +} from '@ringcentral-integration/commons/modules/RcVideoV2'; import { RcMMeetingModel } from '@ringcentral-integration/commons/modules/MeetingV2'; import { GenericMeeting } from '@ringcentral-integration/commons/modules/GenericMeetingV2'; +import { AppFeatures } from '@ringcentral-integration/commons/modules/AppFeatures'; import RcUIModule from '../../lib/RcUIModule'; @Module({ name: 'GenericMeetingUI', - deps: ['GenericMeeting', 'Locale', 'RateLimiter', 'ConnectivityMonitor'], + deps: [ + 'GenericMeeting', + 'AppFeatures', + 'Locale', + 'RateLimiter', + 'ConnectivityMonitor', + ], }) export default class GenericMeetingUI extends RcUIModule { _genericMeeting: GenericMeeting; + _appFeatures: AppFeatures; _locale: any; _rateLimiter: any; _connectivityMonitor: any; @@ -20,12 +41,14 @@ export default class GenericMeetingUI extends RcUIModule { locale, rateLimiter, connectivityMonitor, + appFeatures, ...options }) { super({ ...options, }); this._genericMeeting = genericMeeting; + this._appFeatures = appFeatures; this._locale = locale; this._rateLimiter = rateLimiter; this._connectivityMonitor = connectivityMonitor; @@ -45,50 +68,91 @@ export default class GenericMeetingUI extends RcUIModule { timePickerSize, recurringMeetingPosition, showRcvAdminLock = false, + configDisabled = false, }) { - const invalidPassowrd = - this._genericMeeting.ready && - this._genericMeeting.meeting && - (this._genericMeeting.isRCV || this._genericMeeting.isRCM) && - !this._genericMeeting.validatePasswordSettings( - this._genericMeeting.isRCV - ? this._genericMeeting.meeting.meetingPassword - : this._genericMeeting.meeting.password, - this._genericMeeting.isRCV - ? this._genericMeeting.meeting.isMeetingSecret - : this._genericMeeting.meeting._requireMeetingPassword, - ); + const isRCM = this._genericMeeting.isRCM; + const isRCV = this._genericMeeting.isRCV; const meeting = (this._genericMeeting.ready && this._genericMeeting.meeting) || {}; + const delegators = (this._genericMeeting.ready && this._genericMeeting.delegators) || []; + let isDelegator = false; + if (isRCV) { + const user = find( + (item) => item.extensionId === (meeting as RcVMeetingModel).extensionId, + delegators as RcvDelegator[], + ); + isDelegator = user && !user.isLoginUser; + } + const enableWaitingRoom = + this._genericMeeting.ready && this._genericMeeting.enableWaitingRoom; + const isAllOptionDisabled = !!( + disabled || + !meeting.isMeetingPasswordValid || + (this._genericMeeting.ready && this._genericMeeting.isScheduling) || + (this._connectivityMonitor && !this._connectivityMonitor.connectivity) || + (this._rateLimiter && this._rateLimiter.throttling) + ); + + const showE2EE = + this._genericMeeting.ready && this._genericMeeting.enableE2EE; + + /** for rcv part * */ + const { + settingLock, + e2ee, + isOnlyCoworkersJoin, + } = meeting as RcVMeetingModel; + + // when e2ee is on, waiting room&auth can join&require password&jbh will be disabled and turn on. + const isE2eeRelatedOptionsDisabled = showE2EE && e2ee; + + const isE2EEDisabled = + showE2EE && + ((this._appFeatures.ready && !this._appFeatures.hasVideoE2EE) || + (settingLock as RcVSettingLocks).e2ee || + any( + (key: DisableE2eeWhenRelatedOptionMatch) => + settingLock[key] && + (meeting as RcVMeetingModel)[key] === + DISABLE_E2EE_WHEN_RELATED_OPTION_MATCH[key], + )( + Object.keys( + DISABLE_E2EE_WHEN_RELATED_OPTION_MATCH, + ) as DisableE2eeWhenRelatedOptionMatch[], + ) || + configDisabled); + + const authUserTypeValue = isOnlyCoworkersJoin + ? AUTH_USER_TYPE.SIGNED_IN_CO_WORKERS + : AUTH_USER_TYPE.SIGNED_IN_USERS; + /** for rcv part * */ return { + isRCV, + isRCM, meeting, useRcmV2, + showWhen, + showTopic, delegators, + showDuration, + openNewWindow, + scheduleButton, labelPlacement, datePickerSize, timePickerSize, - recurringMeetingPosition, showRcvAdminLock, + recurringMeetingPosition, + showE2EE, + isE2EEDisabled, currentLocale: this._locale.currentLocale, - disabled: !!( - disabled || - invalidPassowrd || - (this._genericMeeting.ready && this._genericMeeting.isScheduling) || - (this._connectivityMonitor && - !this._connectivityMonitor.connectivity) || - (this._rateLimiter && this._rateLimiter.throttling) - ), - configDisabled: false, - showTopic, - showWhen, - showDuration, + disabled: isAllOptionDisabled, + configDisabled, showScheduleOnBehalf: !!(delegators && delegators.length > 0), showRecurringMeeting: !meeting.usePersonalMeetingId && showRecurringMeeting, - openNewWindow, showSaveAsDefault: this._genericMeeting.ready && this._genericMeeting.showSaveAsDefault, // Need to add this back when we back to this ticket @@ -97,41 +161,80 @@ export default class GenericMeetingUI extends RcUIModule { // this._genericMeeting.ready && // !this._genericMeeting.isPreferencesChanged, disableSaveAsDefault: false, - isRCM: this._genericMeeting.isRCM, - isRCV: this._genericMeeting.isRCV, - scheduleButton, enableServiceWebSettings: this._genericMeeting.ready && this._genericMeeting.enableServiceWebSettings, enablePersonalMeeting: this._genericMeeting.ready && this._genericMeeting.enablePersonalMeeting, - enableWaitingRoom: - this._genericMeeting.ready && this._genericMeeting.enableWaitingRoom, + showWaitingRoom: enableWaitingRoom, + // RCV AuthCanJoin + authUserTypeValue, personalMeetingId: this._genericMeeting.ready && this._genericMeeting.personalMeetingId, showSpinner: !!( !this._locale.ready || !this._genericMeeting.ready || - (!this._genericMeeting.isRCM && !this._genericMeeting.isRCV) || + (!isRCM && !isRCV) || !this._genericMeeting.meeting || (this._connectivityMonitor && !this._connectivityMonitor.ready) || (this._rateLimiter && !this._rateLimiter.ready) ), showSpinnerInConfigPanel: this._genericMeeting.isUpdating, hasSettingsChanged: this._genericMeeting.hasSettingsChanged, + defaultSetting: this._genericMeeting.defaultSetting, defaultTopic: this._genericMeeting.ready ? this._genericMeeting.defaultTopic : '', + isPersonalMeetingDisabled: + (showE2EE && (meeting as RcVMeetingModel).e2ee) || configDisabled, + /* RCV JBH */ + joinBeforeHostLabel: isDelegator + ? JBH_LABEL.JOIN_AFTER_HOST + : JBH_LABEL.JOIN_AFTER_ME, + /* RCV option */ + isRequirePasswordDisabled: + isE2eeRelatedOptionsDisabled || + configDisabled || + (showRcvAdminLock && + (meeting as RcVMeetingModel).settingLock?.isMeetingSecret), + isJoinBeforeHostDisabled: + isE2eeRelatedOptionsDisabled || + configDisabled || + (showRcvAdminLock && meeting.settingLock?.allowJoinBeforeHost) || + (enableWaitingRoom && + (meeting as RcVMeetingModel).waitingRoomMode === + RCV_WAITING_ROOM_MODE.all), + isWaitingRoomDisabled: + isE2eeRelatedOptionsDisabled || + configDisabled || + (showRcvAdminLock && + (meeting as RcVMeetingModel).settingLock?.waitingRoomMode), + isWaitingRoomNotCoworkerDisabled: (meeting as RcVMeetingModel) + .isOnlyCoworkersJoin, + isWaitingRoomGuestDisabled: + (meeting as RcVMeetingModel).isOnlyAuthUserJoin || + (showE2EE && (meeting as RcVMeetingModel).e2ee), + isWaitingRoomAllDisabled: false, + isAuthenticatedCanJoinDisabled: + isE2eeRelatedOptionsDisabled || + configDisabled || + (showRcvAdminLock && + (meeting as RcVMeetingModel).settingLock?.isOnlyAuthUserJoin), + isAuthUserTypeDisabled: + disabled || + configDisabled || + (showRcvAdminLock && + (meeting as RcVMeetingModel).settingLock?.isOnlyCoworkersJoin), + isSignedInUsersDisabled: false, + isSignedInCoWorkersDisabled: false, }; } - getUIFunctions(props?: any) { - const { schedule } = props; + getUIFunctions({ schedule }) { return { switchUsePersonalMeetingId: (usePersonalMeetingId: boolean) => this._genericMeeting.switchUsePersonalMeetingId(usePersonalMeetingId), - updateHasSettingsChanged: (isChanged: boolean) => { this._genericMeeting.updateHasSettingsChanged(isChanged); }, @@ -149,17 +252,37 @@ export default class GenericMeetingUI extends RcUIModule { isSecret, ); }, - schedule: async ( + schedule: ( meetingInfo: RcMMeetingModel | RcVMeetingModel, opener: Window, ) => { if (schedule) { - await schedule(meetingInfo, opener); - return; + return schedule(meetingInfo, opener); } - await this._genericMeeting.schedule(meetingInfo, {}, opener); + return this._genericMeeting.schedule(meetingInfo, {}, opener); }, init: () => this._genericMeeting.init(), + // TODO: Moving to RcVideo updateMeetingSettings would be better + e2eeInteractFunc: (e2eeValue: boolean) => { + if (!e2eeValue) { + this._genericMeeting.updateMeetingSettings({ + e2ee: e2eeValue, + } as RcVMeetingModel); + // when user turn on e2ee option in pmi meeting, should switch to non-pmi meeting + } else if (this._genericMeeting.meeting.usePersonalMeetingId) { + this._genericMeeting.switchUsePersonalMeetingId(false); + this._genericMeeting.updateMeetingSettings({ + e2ee: true, + ...RCV_E2EE_DEFAULT_SECURITY_OPTIONS, + } as RcVMeetingModel); + } else { + this._genericMeeting.updateMeetingSettings({ + e2ee: e2eeValue, + ...RCV_E2EE_DEFAULT_SECURITY_OPTIONS, + } as RcVMeetingModel); + } + this._genericMeeting.updateHasSettingsChanged(true); + }, }; } } diff --git a/packages/ringcentral-widgets/modules/HeaderViewUI/HeaderViewUI.interface.ts b/packages/ringcentral-widgets/modules/HeaderViewUI/HeaderViewUI.interface.ts new file mode 100644 index 0000000000..c50147e3c4 --- /dev/null +++ b/packages/ringcentral-widgets/modules/HeaderViewUI/HeaderViewUI.interface.ts @@ -0,0 +1,19 @@ +import { Auth } from '@ringcentral-integration/commons/modules/AuthV2'; +import { Locale } from '@ringcentral-integration/commons/modules/Locale'; +import { CallMonitor } from '@ringcentral-integration/commons/modules/CallMonitorV2'; +import { Webphone } from '@ringcentral-integration/commons/modules/WebphoneV2'; +import { Presence } from '@ringcentral-integration/commons/modules/PresenceV2'; +import { UserGuide } from '@ringcentral-integration/commons/modules/UserGuideV2'; +import { QuickAccess } from '@ringcentral-integration/commons/modules/QuickAccessV2'; +import { RouterInteraction } from '../RouterInteraction'; + +export interface Deps { + auth: Auth; + callMonitor: CallMonitor; + routerInteraction: RouterInteraction; + locale: Locale; + webphone: Webphone; + presence: Presence; + userGuide: UserGuide; + quickAccess: QuickAccess; +} diff --git a/packages/ringcentral-widgets/modules/HeaderViewUI/HeaderViewUI.ts b/packages/ringcentral-widgets/modules/HeaderViewUI/HeaderViewUI.ts new file mode 100644 index 0000000000..2b8be5d143 --- /dev/null +++ b/packages/ringcentral-widgets/modules/HeaderViewUI/HeaderViewUI.ts @@ -0,0 +1,106 @@ +import { + RcUIModuleV2, + UIFunctions, + UIProps, +} from '@ringcentral-integration/core'; +import { Module } from '@ringcentral-integration/commons/lib/di'; +import { Deps } from './HeaderViewUI.interface'; +import { HeaderViewProps } from '../../containers/HeaderView/HeaderView.interface'; + +@Module({ + name: 'HeaderViewUI', + deps: [ + 'Auth', + 'CallMonitor', + 'RouterInteraction', + 'Locale', + 'Webphone', + 'Presence', + 'UserGuide', + 'QuickAccess', + ], +}) +export class HeaderViewUI extends RcUIModuleV2 { + constructor(deps: Deps) { + super({ deps }); + } + + getUIProps(): UIProps { + const { + auth, + callMonitor, + routerInteraction, + locale, + webphone, + presence, + } = this._deps; + + return { + userStatus: (auth.loggedIn && presence.userStatus) || undefined, + dndStatus: (auth.loggedIn && presence.dndStatus) || undefined, + ringingCalls: callMonitor.activeRingCalls || [], + onHoldCalls: callMonitor.activeOnHoldCalls || [], + currentCalls: callMonitor.activeCurrentCalls || [], + currentPath: routerInteraction.currentPath, + currentLocale: locale.currentLocale, + activeSessionId: webphone.activeSessionId || '', + incomingCallPageMinimized: + !webphone.ringSession || webphone.ringSession.minimized, + presenceReady: presence.ready, + }; + } + + getUIFunctions(): UIFunctions { + const { + routerInteraction, + userGuide, + quickAccess, + webphone, + presence, + } = this._deps; + + return { + onCurrentCallBtnClick() { + if (routerInteraction.currentPath !== '/calls/active') { + routerInteraction.push('/calls/active'); + } + if (userGuide) { + userGuide.dismiss(); + } + if (quickAccess) { + quickAccess.exit(); + } + // TODO: need to replace webphone with webphoneV2 + if ( + webphone && + webphone.ringSession && + !webphone.ringSession.minimized + ) { + webphone.toggleMinimized(webphone.ringSession.id); + } + }, + onViewCallBtnClick() { + if (routerInteraction.currentPath !== '/calls') { + routerInteraction.push('/calls'); + } + if (userGuide) { + userGuide.dismiss(); + } + if (quickAccess) { + quickAccess.exit(); + } + if ( + webphone && + webphone.ringSession && + !webphone.ringSession.minimized + ) { + webphone.toggleMinimized(webphone.ringSession.id); + } + }, + setAvailable: () => presence && presence.setAvailable(), + setBusy: () => presence && presence.setBusy(), + setDoNotDisturb: () => presence && presence.setDoNotDisturb(), + setInvisible: () => presence && presence.setInvisible(), + }; + } +} diff --git a/packages/ringcentral-widgets/modules/HeaderViewUI/index.ts b/packages/ringcentral-widgets/modules/HeaderViewUI/index.ts new file mode 100644 index 0000000000..bb0058ba3b --- /dev/null +++ b/packages/ringcentral-widgets/modules/HeaderViewUI/index.ts @@ -0,0 +1,2 @@ +export * from './HeaderViewUI'; +export * from './HeaderViewUI.interface'; diff --git a/packages/ringcentral-widgets/modules/IncomingCallUI/IncomingCallUI.interface.ts b/packages/ringcentral-widgets/modules/IncomingCallUI/IncomingCallUI.interface.ts index 8897320a78..31ce94b402 100644 --- a/packages/ringcentral-widgets/modules/IncomingCallUI/IncomingCallUI.interface.ts +++ b/packages/ringcentral-widgets/modules/IncomingCallUI/IncomingCallUI.interface.ts @@ -1,10 +1,10 @@ import { ComponentType, ReactElement } from 'react'; import { Webphone } from '@ringcentral-integration/commons/modules/WebphoneV2'; -import { Locale } from '@ringcentral-integration/commons/modules/LocaleV2'; +import { Locale } from '@ringcentral-integration/commons/modules/Locale'; import { ContactSearch } from '@ringcentral-integration/commons/modules/ContactSearchV2'; import { RegionSettings } from '@ringcentral-integration/commons/modules/RegionSettingsV2'; import { ForwardingNumber } from '@ringcentral-integration/commons/modules/ForwardingNumberV2'; -import { Brand } from '@ringcentral-integration/commons/modules/BrandV2'; +import { Brand } from '@ringcentral-integration/commons/modules/Brand'; import { ExtensionInfo } from '@ringcentral-integration/commons/modules/ExtensionInfoV2'; import { ConferenceCall } from '@ringcentral-integration/commons/modules/ConferenceCallV2'; import { ContactMatcher } from '@ringcentral-integration/commons/modules/ContactMatcherV2'; @@ -12,12 +12,14 @@ import { IContact } from '@ringcentral-integration/commons/interfaces/Contact.mo import { Entity } from '@ringcentral-integration/commons/interfaces/Entity.interface'; import { NormalizedSession } from '@ringcentral-integration/commons/interfaces/Webphone.interface'; import { ForwardingNumberInfo } from '@rc-ex/core/definitions'; +import { AppFeatures } from '@ringcentral-integration/commons/modules/AppFeatures'; export interface IncomingCallUIOptions { // } export interface Deps { + appFeatures: AppFeatures; webphone: Webphone; locale: Locale; contactSearch: ContactSearch; @@ -54,6 +56,7 @@ export interface IncomingCallUIPanelProps { name: string; phoneNumber: string; }[]; + phoneNumber?: string; sourceIcons?: Record; phoneTypeRenderer?: (type: string) => ReactElement; phoneSourceNameRenderer: (type: string) => string; diff --git a/packages/ringcentral-widgets/modules/IncomingCallUI/IncomingCallUI.ts b/packages/ringcentral-widgets/modules/IncomingCallUI/IncomingCallUI.ts index 139d99e69d..f94a3807a1 100644 --- a/packages/ringcentral-widgets/modules/IncomingCallUI/IncomingCallUI.ts +++ b/packages/ringcentral-widgets/modules/IncomingCallUI/IncomingCallUI.ts @@ -1,12 +1,13 @@ +import callDirections from '@ringcentral-integration/commons/enums/callDirections'; +import { NormalizedSession } from '@ringcentral-integration/commons/interfaces/Webphone.interface'; +import { Module } from '@ringcentral-integration/commons/lib/di'; +import formatNumber from '@ringcentral-integration/commons/lib/formatNumber'; import { RcUIModuleV2, - UIProps, UIFunctions, + UIProps, } from '@ringcentral-integration/core'; -import { Module } from '@ringcentral-integration/commons/lib/di'; -import formatNumber from '@ringcentral-integration/commons/lib/formatNumber'; -import callDirections from '@ringcentral-integration/commons/enums/callDirections'; -import { NormalizedSession } from '@ringcentral-integration/commons/interfaces/Webphone.interface'; +import { checkShouldHidePhoneNumber } from '../../lib/checkShouldHidePhoneNumber'; import { Deps, IncomingCallContainerProps, @@ -23,6 +24,7 @@ import { 'ForwardingNumber', 'Brand', 'ExtensionInfo', + 'AppFeatures', { dep: 'ConferenceCall', optional: true }, { dep: 'ContactMatcher', optional: true }, { dep: 'IncomingCallUIOptions', optional: true }, @@ -60,6 +62,17 @@ class IncomingCallUI extends RcUIModuleV2 { currentSession.direction === callDirections.outbound ? toMatches : fromMatches; + let phoneNumber = + currentSession.direction === callDirections.outbound + ? currentSession.to + : currentSession.from; + + if ( + this._deps.appFeatures.isCDCEnabled && + checkShouldHidePhoneNumber(phoneNumber, nameMatches) + ) { + phoneNumber = null; + } return { sourceIcons, brand: brand.fullName, @@ -73,6 +86,7 @@ class IncomingCallUI extends RcUIModuleV2 { showContactDisplayPlaceholder, searchContactList: contactSearch.sortedResult, showCallQueueName, + phoneNumber, }; } diff --git a/packages/ringcentral-widgets/modules/LoginUIV2/LoginUI.interface.ts b/packages/ringcentral-widgets/modules/LoginUIV2/LoginUI.interface.ts index 11fda0b2e0..05819fd807 100644 --- a/packages/ringcentral-widgets/modules/LoginUIV2/LoginUI.interface.ts +++ b/packages/ringcentral-widgets/modules/LoginUIV2/LoginUI.interface.ts @@ -1,6 +1,6 @@ import { Auth } from '@ringcentral-integration/commons/modules/AuthV2'; import ConnectivityMonitor from '@ringcentral-integration/commons/modules/ConnectivityMonitor'; -import Locale from '@ringcentral-integration/commons/modules/Locale'; +import { Locale } from '@ringcentral-integration/commons/modules/Locale'; import RateLimiter from '@ringcentral-integration/commons/modules/RateLimiter'; import OAuth from '../OAuth'; diff --git a/packages/ringcentral-widgets/modules/ModalUIV2/ModalUI.interface.ts b/packages/ringcentral-widgets/modules/ModalUIV2/ModalUI.interface.ts index 3a86383da6..9e4bf10c8d 100644 --- a/packages/ringcentral-widgets/modules/ModalUIV2/ModalUI.interface.ts +++ b/packages/ringcentral-widgets/modules/ModalUIV2/ModalUI.interface.ts @@ -1,5 +1,5 @@ import { RcBaseProps } from '@ringcentral/juno'; -import { Locale } from '@ringcentral-integration/commons/modules/LocaleV2'; +import { Locale } from '@ringcentral-integration/commons/modules/Locale'; import { ModalProps } from '../../components/ModalV2/interface'; @@ -46,6 +46,8 @@ export type ModalOptions = RcBaseProps< variant?: 'alert' | 'confirm' | 'info'; /** auto show loading when `confirm button` click, if that `onConfirm` is promise */ useLoadingOverlay?: boolean; + /** auto disableBackdropClick handling when loading, only works when disableBackdropClick is set to false */ + autoDisableBackdropClick?: boolean; }; export type ConfirmModalOptions = RcBaseProps; @@ -62,7 +64,7 @@ export type InfoModalOptions = RcBaseProps< export type DehydratedModalState = RcBaseProps< ModalOptions, - 'onCancel' | 'onConfirm' + 'onCancel' | 'onConfirm' | 'onExited' > & { /** current open state */ open: boolean; @@ -70,8 +72,10 @@ export type DehydratedModalState = RcBaseProps< id: string; /** onConfirm function id */ onConfirm?: string; - /** cancel function id */ + /** onCancel function id */ onCancel?: string; + /** onExited function id */ + onExited?: string; /** this modal handler ids */ handlerIDs: string[]; }; diff --git a/packages/ringcentral-widgets/modules/ModalUIV2/ModalUI.tsx b/packages/ringcentral-widgets/modules/ModalUIV2/ModalUI.tsx index c024dc361c..37613933bd 100644 --- a/packages/ringcentral-widgets/modules/ModalUIV2/ModalUI.tsx +++ b/packages/ringcentral-widgets/modules/ModalUIV2/ModalUI.tsx @@ -102,9 +102,20 @@ export class ModalUI extends RcUIModuleV2 { this._setLoading(id, true); const handler = this._handlerRegister.get(id).get(onConfirm); - if (handler && (await handler()) === false) { - this._setLoading(id, false); - return; + if (handler) { + // even though we add extra error handling here, handlers are expected to handle all its errors + // this is only a best-effort attempt to not let a modal block usage if the handler threw error + try { + if ((await handler()) === false) { + this._setLoading(id, false); + return; + } + } catch (err) { + // if handler has unhandled error, at least remove the loading state so the modal could + // still be closed by the user if cancel button is provided. + this._setLoading(id, false); + throw err; + } } this._promises.get(id).resolve(true); @@ -113,8 +124,9 @@ export class ModalUI extends RcUIModuleV2 { } @proxify - private async _onExited(id: string) { + private async _onExited(id: string, onExited?: string) { this._promises.get(id)?.resolve(false); + this._handlerRegister.get(id).get(onExited)?.(); this._promises.delete(id); this._removeModal(id); this._handlerRegister.delete(id); @@ -272,7 +284,12 @@ export class ModalUI extends RcUIModuleV2 { public open(props: ModalOptions, usePromise: true): Promise; @background open( - { disableBackdropClick = true, fullScreen = false, ...props }: ModalOptions, + { + autoDisableBackdropClick = true, + disableBackdropClick = true, + fullScreen = false, + ...props + }: ModalOptions, usePromise?: boolean, ) { const id = v4(); @@ -280,6 +297,7 @@ export class ModalUI extends RcUIModuleV2 { const dehydratedState = this._getDehydratedState({ ...props, id, + autoDisableBackdropClick, disableBackdropClick, fullScreen, open: true, @@ -386,6 +404,7 @@ export class ModalUI extends RcUIModuleV2 { id, onConfirm, onCancel, + onExited, title, content, footer, @@ -396,6 +415,10 @@ export class ModalUI extends RcUIModuleV2 { footerProps = {}, variant, handlerIDs, + autoDisableBackdropClick, + disableBackdropClick, + loading, + loadingOverlay, // * just pick this field out of rest // eslint-disable-next-line @typescript-eslint/no-unused-vars useLoadingOverlay, @@ -404,8 +427,13 @@ export class ModalUI extends RcUIModuleV2 { const uiProps: ModalProps = { ...rest, key: id, + loading, + loadingOverlay, + disableBackdropClick: + (autoDisableBackdropClick && (loading || loadingOverlay)) || + disableBackdropClick, onConfirm: () => this._onConfirm(id, onConfirm), - onExited: () => this._onExited(id), + onExited: () => this._onExited(id, onExited), }; if (onCancel || cancelButtonText) { diff --git a/packages/ringcentral-widgets/modules/OAuth/index.js b/packages/ringcentral-widgets/modules/OAuth/index.js index 8837ed35df..a422994ed5 100644 --- a/packages/ringcentral-widgets/modules/OAuth/index.js +++ b/packages/ringcentral-widgets/modules/OAuth/index.js @@ -22,7 +22,6 @@ export default class OAuth extends OAuthBase { redirectUri = './redirect.html', restrictSameOriginRedirectUri = true, routerInteraction, - useDiscovery, client, ...options }) { @@ -41,7 +40,6 @@ export default class OAuth extends OAuthBase { this._isInElectron = isElectron(); this._restrictSameOriginRedirectUri = restrictSameOriginRedirectUri; this._uuid = uuid.v4(); - this._useDiscovery = useDiscovery; } initialize() { @@ -130,7 +128,7 @@ export default class OAuth extends OAuthBase { @proxify async openOAuthPage() { if (this.oAuthReady) { - if (this._useDiscovery) { + if (this._client.service.platform().discovery()) { await this._client.service.platform().loginUrlWithDiscovery(); } this._loginWindow = popWindow(this.oAuthUri, 'rc-oauth', 600, 600); @@ -142,7 +140,7 @@ export default class OAuth extends OAuthBase { @proxify async openOAuthPageInOtherRouter() { - if (this._useDiscovery) { + if (this._client.service.platform().discovery()) { await this._client.service.platform().loginUrlWithDiscovery(); } this._loginWindow = popWindow(this.oAuthUri, 'rc-oauth', 600, 600); diff --git a/packages/ringcentral-widgets/modules/RecentActivityUI/RecentActivityUI.interface.ts b/packages/ringcentral-widgets/modules/RecentActivityUI/RecentActivityUI.interface.ts index 4c70e5fa7e..23a57f4bb2 100644 --- a/packages/ringcentral-widgets/modules/RecentActivityUI/RecentActivityUI.interface.ts +++ b/packages/ringcentral-widgets/modules/RecentActivityUI/RecentActivityUI.interface.ts @@ -1,6 +1,6 @@ import { RecentMessages } from '@ringcentral-integration/commons/modules/RecentMessagesV2'; import { RecentCalls } from '@ringcentral-integration/commons/modules/RecentCallsV2'; -import { Locale } from '@ringcentral-integration/commons/modules/LocaleV2'; +import { Locale } from '@ringcentral-integration/commons/modules/Locale'; import { NormalizedSession } from '@ringcentral-integration/commons/interfaces/Webphone.interface'; import { Entity } from '@ringcentral-integration/commons/interfaces/Entity.interface'; import { @@ -9,7 +9,7 @@ import { } from '@ringcentral-integration/commons/modules/DateTimeFormatV2'; import { ContactMatcher } from '@ringcentral-integration/commons/modules/ContactMatcherV2'; import { HistoryCall } from '@ringcentral-integration/commons/modules/CallHistoryV2'; -import { Tab } from './getTabs'; +import { Tab, trackTabsMap } from './getTabs'; export interface RecentActivityUIOptions { // @@ -35,6 +35,7 @@ export interface RecentActivityContainerProps { showRecentMessage?: boolean; showFax?: boolean; showVoiceMails?: boolean; + entry: string; } // TODO: move to `RecentActivityPanel` @@ -47,4 +48,6 @@ export interface RecentActivityPanelProps { tabs: Tab[]; defaultTab: string; className?: string; + trackClickToggle?: (expanded: boolean) => void; + trackClickTab?: (tabName: keyof typeof trackTabsMap) => void; } diff --git a/packages/ringcentral-widgets/modules/RecentActivityUI/RecentActivityUI.ts b/packages/ringcentral-widgets/modules/RecentActivityUI/RecentActivityUI.ts index 01330e1d92..5355da8f72 100644 --- a/packages/ringcentral-widgets/modules/RecentActivityUI/RecentActivityUI.ts +++ b/packages/ringcentral-widgets/modules/RecentActivityUI/RecentActivityUI.ts @@ -2,11 +2,14 @@ import { RcUIModuleV2, UIFunctions, UIProps, + track, } from '@ringcentral-integration/core'; import callDirections from '@ringcentral-integration/commons/enums/callDirections'; import { Module } from '@ringcentral-integration/commons/lib/di'; +import { trackEvents } from '@ringcentral-integration/commons/modules/Analytics'; +import { proxify } from '@ringcentral-integration/commons/lib/proxy/proxify'; import i18n from './i18n'; -import { getTabs, GetTabsOptions } from './getTabs'; +import { getTabs, GetTabsOptions, trackTabsMap } from './getTabs'; import { Deps, RecentActivityContainerProps, @@ -35,6 +38,27 @@ export class RecentActivityUI extends RcUIModuleV2 { return getTabs(options); } + @track((_: RecentActivityUI, entry: string) => [ + trackEvents.clickRecentActivity, + { Entry: entry }, + ]) + @proxify + async trackClickToggle(entry: string) { + // + } + + @track( + ( + _: RecentActivityUI, + tabName: keyof typeof trackTabsMap, + entry: string, + ) => [trackTabsMap[tabName], { Entry: entry }], + ) + @proxify + async trackClickTab(tabName: string, entry: string) { + // + } + getUIProps({ currentLocale = this._deps.locale.currentLocale, navigateTo, @@ -99,7 +123,16 @@ export class RecentActivityUI extends RcUIModuleV2 { }; } - getUIFunctions(): UIFunctions { - return {}; + getUIFunctions({ + entry, + }: RecentActivityContainerProps): UIFunctions { + return { + trackClickToggle: (expanded) => { + if (expanded) { + this.trackClickToggle(entry); + } + }, + trackClickTab: (tabName) => this.trackClickTab(tabName, entry), + }; } } diff --git a/packages/ringcentral-widgets/modules/RecentActivityUI/getTabs.tsx b/packages/ringcentral-widgets/modules/RecentActivityUI/getTabs.tsx index c3ad64a199..3878eb7e86 100644 --- a/packages/ringcentral-widgets/modules/RecentActivityUI/getTabs.tsx +++ b/packages/ringcentral-widgets/modules/RecentActivityUI/getTabs.tsx @@ -8,6 +8,7 @@ import { RecentMessages, } from '@ringcentral-integration/commons/modules/RecentMessagesV2'; import { RecentCalls } from '@ringcentral-integration/commons/modules/RecentCallsV2'; +import { trackEvents } from '@ringcentral-integration/commons/modules/Analytics'; import dynamicsFont from '../../assets/DynamicsFont/DynamicsFont.scss'; import RecentActivityMessages from '../../components/RecentActivityMessages'; import RecentActivityCalls from '../../components/RecentActivityCalls'; @@ -25,6 +26,13 @@ export interface Tab { cleanUp: () => void; } +export const trackTabsMap = { + recentCalls: trackEvents.clickRecentActivityCall, + faxes: trackEvents.clickRecentActivityFaxes, + recentMessages: trackEvents.clickRecentActivitySms, + voicemails: trackEvents.clickRecentActivityVoicemails, +}; + export interface GetTabsOptions { ready: boolean; currentLocale: string; diff --git a/packages/ringcentral-widgets/modules/SettingsUI/SettingUI.interface.ts b/packages/ringcentral-widgets/modules/SettingsUI/SettingUI.interface.ts new file mode 100644 index 0000000000..39d79ed223 --- /dev/null +++ b/packages/ringcentral-widgets/modules/SettingsUI/SettingUI.interface.ts @@ -0,0 +1,93 @@ +import { Auth } from '@ringcentral-integration/commons/modules/AuthV2'; +import { Brand } from '@ringcentral-integration/commons/modules/Brand'; +import { Locale } from '@ringcentral-integration/commons/modules/Locale'; +import { Presence } from '@ringcentral-integration/commons/modules/PresenceV2'; +import { AccountInfo } from '@ringcentral-integration/commons/modules/AccountInfoV2'; +import { ExtensionInfo } from '@ringcentral-integration/commons/modules/ExtensionInfoV2'; +import { RegionSettings } from '@ringcentral-integration/commons/modules/RegionSettingsV2'; +import { ExtensionFeatures } from '@ringcentral-integration/commons/modules/ExtensionFeatures'; +import { AppFeatures } from '@ringcentral-integration/commons/modules/AppFeatures'; +import { CallingSettings } from '@ringcentral-integration/commons/modules/CallingSettingsV2'; +import { LocaleSettings } from '@ringcentral-integration/commons/modules/LocaleSettingsV2'; +import { QuickAccess } from '@ringcentral-integration/commons/modules/QuickAccessV2'; +import { UserGuide } from '@ringcentral-integration/commons/modules/UserGuideV2'; +import { BasePhone } from '@ringcentral-integration/commons/interfaces/BasePhone.interface'; +import { PresenceInfoModel } from '@ringcentral-integration/commons/interfaces/Presence.model'; +import { RouterInteraction } from '../RouterInteraction'; + +interface SettingsUIOptions { + // +} + +export interface Deps { + auth: Auth; + brand: Brand; + locale: Locale; + version?: string; + presence?: Presence; + accountInfo: AccountInfo; + extensionInfo: ExtensionInfo; + regionSettings: RegionSettings; + extensionFeatures: ExtensionFeatures; + appFeatures: AppFeatures; + routerInteraction: RouterInteraction; + callingSettings?: CallingSettings; + localeSettings?: LocaleSettings; + quickAccess?: QuickAccess; + userGuide?: UserGuide; + settingsUIOptions?: SettingsUIOptions; +} + +export interface SettingsContainerProps { + phone: BasePhone; + showRegion: boolean; + showCalling: boolean; + showAudio: boolean; + showFeedback: boolean; + showUserGuide: boolean; + showPresenceSettings: boolean; + showQuickAccess: boolean; + params?: { + showPresenceSettings?: boolean; + }; + regionSettingsUrl?: string; + callingSettingsUrl?: string; + audioSettingsUrl?: string; + feedbackSettingsUrl?: string; +} + +export interface SettingsPanelProps { + version: string; + loginNumber: string; + showFeedback: boolean; + showQuickAccess: boolean; + showSpinner: boolean; + showCalling: boolean; + showAudio: boolean; + showRegion: boolean; + currentLocale: string; + brandId: string; + ringoutEnabled: boolean; + outboundSMS: boolean; + isCallQueueMember: boolean; + dndStatus: PresenceInfoModel['dndStatus']; + userStatus: PresenceInfoModel['userStatus']; + openPresenceSettings: boolean; + showPresenceSettings: boolean; + supportedLocales: string[]; + savedLocale: string; + showUserGuide: boolean; + onLogoutButtonClick(): Promise; + onRegionSettingsLinkClick(): void; + onCallingSettingsLinkClick(): void; + onAudioSettingsLinkClick(): void; + onFeedbackSettingsLinkClick(): void; + onUserGuideClick(): void; + onQuickAccessLinkClick(): void; + setAvailable: Presence['setAvailable']; + setBusy: Presence['setBusy']; + setDoNotDisturb: Presence['setDoNotDisturb']; + setInvisible: Presence['setInvisible']; + toggleAcceptCallQueueCalls: Presence['toggleAcceptCallQueueCalls']; + saveLocale?: LocaleSettings['saveLocale']; +} diff --git a/packages/ringcentral-widgets/modules/SettingsUI/index.js b/packages/ringcentral-widgets/modules/SettingsUI/SettingsUI.ts similarity index 74% rename from packages/ringcentral-widgets/modules/SettingsUI/index.js rename to packages/ringcentral-widgets/modules/SettingsUI/SettingsUI.ts index 5856eeceb0..73a3353876 100644 --- a/packages/ringcentral-widgets/modules/SettingsUI/index.js +++ b/packages/ringcentral-widgets/modules/SettingsUI/SettingsUI.ts @@ -1,7 +1,16 @@ +import { + RcUIModuleV2, + UIFunctions, + UIProps, +} from '@ringcentral-integration/core'; import { Module } from '@ringcentral-integration/commons/lib/di'; import formatNumber from '@ringcentral-integration/commons/lib/formatNumber'; import loginStatus from '@ringcentral-integration/commons/modules/Auth/loginStatus'; -import RcUIModule from '../../lib/RcUIModule'; +import { + Deps, + SettingsContainerProps, + SettingsPanelProps, +} from './SettingUI.interface'; const DEFAULT_REGION_SETTINGS_URL = '/settings/region'; const DEFAULT_CALLING_SETTINGS_URL = '/settings/calling'; @@ -14,6 +23,12 @@ const DEFAULT_FEEDBACK_SETTINGS_URL = '/settings/feedback'; 'Auth', 'Brand', 'Locale', + 'AccountInfo', + 'ExtensionInfo', + 'RegionSettings', + 'ExtensionFeatures', + 'AppFeatures', + 'RouterInteraction', { dep: 'Version', optional: true, @@ -22,11 +37,6 @@ const DEFAULT_FEEDBACK_SETTINGS_URL = '/settings/feedback'; dep: 'Presence', optional: true, }, - 'AccountInfo', - 'ExtensionInfo', - 'RegionSettings', - 'ExtensionFeatures', - 'RouterInteraction', { dep: 'CallingSettings', optional: true, @@ -49,31 +59,36 @@ const DEFAULT_FEEDBACK_SETTINGS_URL = '/settings/feedback'; }, ], }) -export default class SettingsUI extends RcUIModule { +export class SettingsUI extends RcUIModuleV2 { + constructor(deps: T) { + super({ deps }); + } + getUIProps({ - phone: { + showRegion = true, + showCalling = true, + showAudio = true, + showFeedback = true, + showUserGuide = true, + showPresenceSettings = true, + showQuickAccess = false, + params, + }: SettingsContainerProps): UIProps { + const { accountInfo, auth, brand, extensionInfo, + extensionFeatures, locale, localeSettings, regionSettings, callingSettings, version, - extensionFeatures, + appFeatures, presence, userGuide, - }, - showRegion = true, - showCalling = true, - showAudio = true, - showFeedback = true, - showUserGuide = true, - showPresenceSettings = true, - showQuickAccess = false, - params, - }) { + } = this._deps; let loginNumber = brand.name; const loggedIn = auth.loginStatus === loginStatus.loggedIn; if ( @@ -109,28 +124,28 @@ export default class SettingsUI extends RcUIModule { locale.ready && regionSettings.ready && (!callingSettings || callingSettings.ready) && - extensionFeatures.ready && + appFeatures.ready && (!presence || presence.ready) && (!localeSettings || localeSettings.ready) ), showCalling: - showCalling && callingSettings && extensionFeatures.isCallingEnabled, - showAudio: showAudio && extensionFeatures.isCallingEnabled, + showCalling && callingSettings && appFeatures.isCallingEnabled, + showAudio: showAudio && appFeatures.isCallingEnabled, showRegion: loggedIn && - brand.code === 'rc' && - regionSettings.showReginSetting && - extensionFeatures.isCallingEnabled && + brand.brandConfig.allowRegionSetting && + regionSettings.showRegionSetting && + appFeatures.isCallingEnabled && showRegion, currentLocale: locale.currentLocale, brandId: brand.id, - ringoutEnabled: extensionFeatures.isRingOutEnabled, + ringoutEnabled: appFeatures.isRingOutEnabled, outboundSMS: - !!extensionFeatures.hasOutboundSMSPermission || - !!extensionFeatures.hasInternalSMSPermission, + !!appFeatures.hasOutboundSMSPermission || + !!appFeatures.hasInternalSMSPermission, isCallQueueMember: extensionInfo.isCallQueueMember, - dndStatus: presence && presence.dndStatus, - userStatus: presence && presence.userStatus, + dndStatus: presence?.dndStatus, + userStatus: presence?.userStatus, openPresenceSettings: !!( presence && params && @@ -139,8 +154,8 @@ export default class SettingsUI extends RcUIModule { showPresenceSettings: showPresenceSettings && !!extensionFeatures.features?.EditPresenceStatus?.available, - supportedLocales: localeSettings && localeSettings.supportedLocales, - savedLocale: localeSettings && localeSettings.savedLocale, + supportedLocales: localeSettings?.supportedLocales, + savedLocale: localeSettings?.savedLocale, showUserGuide: showUserGuide && !!userGuide?.hasPermission, }; } @@ -150,15 +165,15 @@ export default class SettingsUI extends RcUIModule { callingSettingsUrl = DEFAULT_CALLING_SETTINGS_URL, audioSettingsUrl = DEFAULT_AUDIO_SETTINGS_URL, feedbackSettingsUrl = DEFAULT_FEEDBACK_SETTINGS_URL, - phone: { + }: SettingsContainerProps): UIFunctions { + const { auth, presence, routerInteraction, localeSettings, userGuide, quickAccess, - }, - }) { + } = this._deps; return { async onLogoutButtonClick() { await auth.logout(); @@ -181,14 +196,12 @@ export default class SettingsUI extends RcUIModule { onQuickAccessLinkClick() { quickAccess.enter(); }, - - setAvailable: (...args) => presence && presence.setAvailable(...args), - setBusy: (...args) => presence && presence.setBusy(...args), - setDoNotDisturb: (...args) => - presence && presence.setDoNotDisturb(...args), - setInvisible: (...args) => presence && presence.setInvisible(...args), + setAvailable: (...args) => presence?.setAvailable(...args), + setBusy: (...args) => presence?.setBusy(...args), + setDoNotDisturb: (...args) => presence?.setDoNotDisturb(...args), + setInvisible: (...args) => presence?.setInvisible(...args), toggleAcceptCallQueueCalls: (...args) => - presence && presence.toggleAcceptCallQueueCalls(...args), + presence?.toggleAcceptCallQueueCalls(...args), saveLocale: localeSettings && ((locale) => localeSettings.saveLocale(locale)), }; diff --git a/packages/ringcentral-widgets/modules/SettingsUI/index.ts b/packages/ringcentral-widgets/modules/SettingsUI/index.ts new file mode 100644 index 0000000000..f4537fb576 --- /dev/null +++ b/packages/ringcentral-widgets/modules/SettingsUI/index.ts @@ -0,0 +1,2 @@ +export * from './SettingUI.interface'; +export * from './SettingsUI'; diff --git a/packages/ringcentral-widgets/modules/SimpleCallControlUI/SimpleCallControlUI.interface.ts b/packages/ringcentral-widgets/modules/SimpleCallControlUI/SimpleCallControlUI.interface.ts index c546067541..a88076755f 100644 --- a/packages/ringcentral-widgets/modules/SimpleCallControlUI/SimpleCallControlUI.interface.ts +++ b/packages/ringcentral-widgets/modules/SimpleCallControlUI/SimpleCallControlUI.interface.ts @@ -1,7 +1,7 @@ import { ActiveCallControl } from '@ringcentral-integration/commons/modules/ActiveCallControlV2'; import { RegionSettings } from '@ringcentral-integration/commons/modules/RegionSettingsV2'; -import { Locale } from '@ringcentral-integration/commons/modules/LocaleV2'; -import { Brand } from '@ringcentral-integration/commons/modules/BrandV2'; +import { Locale } from '@ringcentral-integration/commons/modules/Locale'; +import { Brand } from '@ringcentral-integration/commons/modules/Brand'; import { RouterInteraction } from '../RouterInteraction'; export interface Deps { diff --git a/packages/ringcentral-widgets/modules/VideoUI/index.ts b/packages/ringcentral-widgets/modules/VideoUI/index.ts index 8b2bd5e6d4..16b7af658b 100644 --- a/packages/ringcentral-widgets/modules/VideoUI/index.ts +++ b/packages/ringcentral-widgets/modules/VideoUI/index.ts @@ -1,16 +1,36 @@ +import { any, find } from 'ramda'; import { Module } from '@ringcentral-integration/commons/lib/di'; -import { Brand } from '@ringcentral-integration/commons/modules/BrandV2'; +import { Brand } from '@ringcentral-integration/commons/modules/Brand'; import { RcVideo } from '@ringcentral-integration/commons/modules/RcVideo'; -import { RcVMeetingModel } from '@ringcentral-integration/commons/interfaces/Rcv.model'; - +import { + RcVMeetingModel, + RcVSettingLocks, +} from '@ringcentral-integration/commons/interfaces/Rcv.model'; +import { + DisableE2eeWhenRelatedOptionMatch, + DISABLE_E2EE_WHEN_RELATED_OPTION_MATCH, + RCV_E2EE_DEFAULT_SECURITY_OPTIONS, + RCV_WAITING_ROOM_MODE, + AUTH_USER_TYPE, + RcvDelegator, + JBH_LABEL, +} from '@ringcentral-integration/commons/modules/RcVideoV2'; import RcUIModule from '../../lib/RcUIModule'; @Module({ name: 'VideoUI', - deps: ['RcVideo', 'Locale', 'RateLimiter', 'ConnectivityMonitor', 'Brand'], + deps: [ + 'RcVideo', + 'AppFeatures', + 'Locale', + 'RateLimiter', + 'ConnectivityMonitor', + 'Brand', + ], }) export default class VideoUI extends RcUIModule { private _locale: any; + private _appFeatures: any; private _rcVideo: RcVideo; private _rateLimiter: any; private _connectivityMonitor: any; @@ -21,11 +41,13 @@ export default class VideoUI extends RcUIModule { rateLimiter, connectivityMonitor, brand, + appFeatures, ...options }) { super({ ...options, }); + this._appFeatures = appFeatures; this._rcVideo = rcVideo; this._locale = locale; this._rateLimiter = rateLimiter; @@ -33,27 +55,124 @@ export default class VideoUI extends RcUIModule { this._brand = brand; } - getUIProps({ disabled }) { + getUIProps({ + disabled, + labelPlacement, + datePickerSize, + timePickerSize, + showRcvAdminLock = false, + configDisabled = false, + }) { + const showE2EE = this._rcVideo.ready && this._rcVideo.enableE2EE; + + const meeting: RcVMeetingModel = + this._rcVideo.ready && this._rcVideo.meeting; + + const delegators = (this._rcVideo.ready && this._rcVideo.delegators) || []; + let isDelegator = false; + const user = find( + (item) => item.extensionId === meeting.extensionId, + delegators as RcvDelegator[], + ); + isDelegator = user && !user.isLoginUser; + + const enableWaitingRoom = + this._rcVideo.ready && this._rcVideo.enableWaitingRoom; + + const isAllOptionDisabled = !!( + disabled || + !meeting.isMeetingPasswordValid || + (this._rcVideo.ready && this._rcVideo.isScheduling) || + (this._connectivityMonitor && !this._connectivityMonitor.connectivity) || + (this._rateLimiter && this._rateLimiter.throttling) + ); + + const { settingLock, e2ee, isOnlyCoworkersJoin } = meeting; + + // when e2ee is on, waiting room&auth can join&require password&jbh will be disabled and turn on. + const isE2eeRelatedOptionsDisabled = showE2EE && e2ee; + + const isE2EEDisabled = + showE2EE && + ((this._appFeatures.ready && !this._appFeatures.hasVideoE2EE) || + (settingLock as RcVSettingLocks).e2ee || + any( + (key: DisableE2eeWhenRelatedOptionMatch) => + settingLock[key] && + meeting[key] === DISABLE_E2EE_WHEN_RELATED_OPTION_MATCH[key], + )( + Object.keys( + DISABLE_E2EE_WHEN_RELATED_OPTION_MATCH, + ) as DisableE2eeWhenRelatedOptionMatch[], + ) || + configDisabled); + + const authUserTypeValue = isOnlyCoworkersJoin + ? AUTH_USER_TYPE.SIGNED_IN_CO_WORKERS + : AUTH_USER_TYPE.SIGNED_IN_USERS; + return { + datePickerSize, + timePickerSize, + labelPlacement, + isE2EEDisabled, + delegators, + authUserTypeValue, currentLocale: this._locale.currentLocale, meeting: this._rcVideo.meeting, enablePersonalMeeting: this._rcVideo.enablePersonalMeeting, + showWaitingRoom: this._rcVideo.enableWaitingRoom, + showE2EE: this._rcVideo.enableE2EE, personalMeetingId: this._rcVideo.ready && this._rcVideo.personalMeeting?.shortId, showSaveAsDefault: this._rcVideo.showSaveAsDefault, + showScheduleOnBehalf: !!(delegators && delegators.length > 0), disableSaveAsDefault: !this._rcVideo.isPreferencesChanged, + showSpinnerInConfigPanel: + this._rcVideo.isInitializing || this._rcVideo.isScheduling, brandName: this._brand.name, - disabled: - this._rcVideo.isScheduling || - disabled || - !this._connectivityMonitor.connectivity || - (this._rateLimiter && this._rateLimiter.throttling), + configDisabled, + disabled: isAllOptionDisabledp, hasSettingsChanged: this._rcVideo.hasSettingsChanged, + joinBeforeHostLabel: isDelegator + ? JBH_LABEL.JOIN_AFTER_HOST + : JBH_LABEL.JOIN_AFTER_ME, + isPersonalMeetingDisabled: (showE2EE && meeting.e2ee) || configDisabled, + isRequirePasswordDisabled: + isE2eeRelatedOptionsDisabled || + configDisabled || + (showRcvAdminLock && meeting.settingLock?.isMeetingSecret), + isJoinBeforeHostDisabled: + isE2eeRelatedOptionsDisabled || + configDisabled || + (showRcvAdminLock && meeting.settingLock?.allowJoinBeforeHost) || + (enableWaitingRoom && + meeting.waitingRoomMode === RCV_WAITING_ROOM_MODE.all), + isWaitingRoomDisabled: + isE2eeRelatedOptionsDisabled || + configDisabled || + (showRcvAdminLock && meeting.settingLock?.waitingRoomMode), + isWaitingRoomNotCoworkerDisabled: meeting.isOnlyCoworkersJoin, + isWaitingRoomGuestDisabled: + meeting.isOnlyAuthUserJoin || (showE2EE && meeting.e2ee), + isWaitingRoomAllDisabled: false, + isAuthenticatedCanJoinDisabled: + isE2eeRelatedOptionsDisabled || + configDisabled || + (showRcvAdminLock && meeting.settingLock?.isOnlyAuthUserJoin), + isAuthUserTypeDisabled: + disabled || + configDisabled || + (showRcvAdminLock && meeting.settingLock?.isOnlyCoworkersJoin), + isSignedInUsersDisabled: false, + isSignedInCoWorkersDisabled: false, }; } getUIFunctions({ schedule }) { return { + updateScheduleFor: (userExtensionId: string) => + this._rcVideo.updateScheduleFor(userExtensionId), updateMeetingSettings: (value: RcVMeetingModel) => this._rcVideo.updateMeetingSettings(value), validatePasswordSettings: ( @@ -82,6 +201,28 @@ export default class VideoUI extends RcUIModule { init: () => { this._rcVideo.init(); }, + e2eeInteractFunc: (e2eeValue: boolean) => { + if (!e2eeValue) { + this._rcVideo.updateMeetingSettings({ + e2ee: e2eeValue, + }); + return; + } + // when user turn on e2ee option in pmi meeting, should switch to non-pmi meeting + if (this._rcVideo.meeting.usePersonalMeetingId) { + this._rcVideo.switchUsePersonalMeetingId(false); + this._rcVideo.updateMeetingSettings({ + e2ee: true, + ...RCV_E2EE_DEFAULT_SECURITY_OPTIONS, + }); + } else { + this._rcVideo.updateMeetingSettings({ + e2ee: e2eeValue, + ...RCV_E2EE_DEFAULT_SECURITY_OPTIONS, + }); + } + this._rcVideo.updateHasSettingsChanged(true); + }, }; } } diff --git a/packages/ringcentral-widgets/package.json b/packages/ringcentral-widgets/package.json index c68e49940b..fa5edc3004 100644 --- a/packages/ringcentral-widgets/package.json +++ b/packages/ringcentral-widgets/package.json @@ -44,16 +44,16 @@ "uuid": "^8.3.0" }, "devDependencies": { - "@rc-ex/core": "^0.8.1", + "@rc-ex/core": "^0.9.3", "@ringcentral-integration/babel-settings": "*", "@ringcentral-integration/commons": "*", "@ringcentral-integration/core": "*", "@ringcentral-integration/locale-loader": "*", "@ringcentral-integration/locale-settings": "*", "@ringcentral-integration/phone-number": "*", - "@ringcentral/juno": "^1.8.5-beta.5034-128a9f16", - "@ringcentral/sdk": "^4.5.0", - "@ringcentral/subscriptions": "^4.5.0", + "@ringcentral/juno": "^1.11.2", + "@ringcentral/sdk": "^4.6.0", + "@ringcentral/subscriptions": "^4.6.0", "@testing-library/jest-dom": "^5.11.2", "@testing-library/react": "^11.2.6", "@types/autoprefixer": "^9.7.2", @@ -71,13 +71,13 @@ "gulp-sourcemaps": "^2.6.5", "identity-obj-proxy": "^3.0.0", "pubnub": "^4.20.1", - "react": "^16.14.0", - "react-dom": "^16.14.0", + "react": "^17.0.2", + "react-dom": "^17.0.2", "react-redux": "^5.1.1", "react-router": "^3.0.0", "react-router-redux": "^4.0.7", "react-svg-loader": "^3.0.3", - "react-test-renderer": "^16.8.3", + "react-test-renderer": "^17.0.2", "redux": "^4.0.5", "redux-logger": "^3.0.6", "redux-thunk": "^2.2.0", @@ -85,23 +85,23 @@ "styled-components": "^5.2.0", "thread-loader": "^3.0.1", "webpack": "^4.29.0", - "webpack-bundle-analyzer": "^4.4.0", - "yargs": "^14.0.0" + "webpack-bundle-analyzer": "^4.4.2", + "yargs": "^17.1.1" }, "peerDependencies": { - "@rc-ex/core": "^0.8.1", + "@rc-ex/core": "^0.9.3", "@ringcentral-integration/commons": "^0.13.0", "@ringcentral-integration/core": "^0.13.0", "@ringcentral-integration/i18n": "^2.0.1", "@ringcentral-integration/phone-number": "^1.0.4", - "@ringcentral/juno": "^1.8.5-beta.5034-128a9f16", - "@ringcentral/sdk": "^4.5.0", - "@ringcentral/subscriptions": "^4.5.0", + "@ringcentral/juno": "^1.11.2", + "@ringcentral/sdk": "^4.6.0", + "@ringcentral/subscriptions": "^4.6.0", "format-message": "^6.2.3", "isomorphic-fetch": "^2.2.1", "moment": "^2.24.0", - "react": "^16.14.0", - "react-dom": "^16.14.0", + "react": "^17.0.2", + "react-dom": "^17.0.2", "react-redux": "^5.1.1", "react-router": "^3.0.0", "react-router-redux": "^4.0.7", diff --git a/packages/ringcentral-widgets/test/modules/ContactDetailsUI/canCallButtonShow.test.js b/packages/ringcentral-widgets/test/modules/ContactDetailsUI/canCallButtonShow.test.js index 1d2dd33e7b..f3ef83e0ab 100644 --- a/packages/ringcentral-widgets/test/modules/ContactDetailsUI/canCallButtonShow.test.js +++ b/packages/ringcentral-widgets/test/modules/ContactDetailsUI/canCallButtonShow.test.js @@ -1,47 +1,48 @@ import { phoneTypes } from '@ringcentral-integration/commons/enums/phoneTypes'; import { ObjectMap } from '@ringcentral-integration/core/lib/ObjectMap'; import { ContactDetailsUI } from '../../../modules/ContactDetailsUI/ContactDetailsUI'; -import { phone } from './testUtils'; +import { phone, defaultPropsParams } from './testSetup'; -test("if dialerUI's dependency is not exist, should return false", () => { +test.skip("if dialerUI's dependency is not exist, should return false", () => { /** - * callingEnabled permission = true && phoneType !== fax, should return true + * isCallingEnabled permission = true && phoneType !== fax, should return true * However if the composeText's dependency is not exist, then it should return false */ const phoneType = phoneTypes.extension; let { canCallButtonShow } = new ContactDetailsUI({ ...phone, dialerUI: {}, - rolesAndPermissions: { callingEnabled: true }, - }).getUIFunctions(); + appFeatures: { isCallingEnabled: true }, + }).getUIFunctions(defaultPropsParams); expect(canCallButtonShow(phoneType)).toBeTruthy(); ({ canCallButtonShow } = new ContactDetailsUI({ ...phone, dialerUI: null, - rolesAndPermissions: { callingEnabled: true }, + appFeatures: { isCallingEnabled: true }, }).getUIFunctions()); expect(canCallButtonShow(phoneType)).toBeFalsy(); }); -test('when disable callingEnabled permission, result should return false', () => { +test.skip('when disable isCallingEnabled permission, result should return false', () => { const phoneType = phoneTypes.extension; const { canCallButtonShow } = new ContactDetailsUI({ ...phone, dialerUI: {}, - rolesAndPermissions: { callingEnabled: false }, - }).getUIFunctions(); + appFeatures: { isCallingEnabled: false }, + }).getUIFunctions(defaultPropsParams); expect(canCallButtonShow(phoneType)).toBeFalsy(); }); -describe('when enable callingEnabled permission', () => { +// TODO: refactor to use IT +describe.skip('when enable isCallingEnabled permission', () => { const { canCallButtonShow } = new ContactDetailsUI({ ...phone, dialerUI: {}, - rolesAndPermissions: { callingEnabled: true }, - }).getUIFunctions(); + appFeatures: { isCallingEnabled: true }, + }).getUIFunctions(defaultPropsParams); test('if phoneType = fax, return false', () => { const phoneType = phoneTypes.fax; expect(canCallButtonShow(phoneType)).toBeFalsy(); diff --git a/packages/ringcentral-widgets/test/modules/ContactDetailsUI/canTextButtonShow.test.js b/packages/ringcentral-widgets/test/modules/ContactDetailsUI/canTextButtonShow.test.js index 61fb73b9ed..c85d10c488 100644 --- a/packages/ringcentral-widgets/test/modules/ContactDetailsUI/canTextButtonShow.test.js +++ b/packages/ringcentral-widgets/test/modules/ContactDetailsUI/canTextButtonShow.test.js @@ -1,7 +1,7 @@ import { phoneTypes } from '@ringcentral-integration/commons/enums/phoneTypes'; import { ObjectMap } from '@ringcentral-integration/core/lib/ObjectMap'; import { ContactDetailsUI } from '../../../modules/ContactDetailsUI/ContactDetailsUI'; -import { phone } from './testUtils'; +import { phone, defaultPropsParams } from './testSetup'; test("if composeText's dependency is not exist, then should return false", () => { /** @@ -12,16 +12,16 @@ test("if composeText's dependency is not exist, then should return false", () => let { canTextButtonShow } = new ContactDetailsUI({ ...phone, composeText: {}, - rolesAndPermissions: { permissions: { OutboundSMS: true } }, - }).getUIFunctions(); + appFeatures: { hasOutboundSMSPermission: true }, + }).getUIFunctions(defaultPropsParams); expect(canTextButtonShow(phoneType)).toBeTruthy(); canTextButtonShow = new ContactDetailsUI({ ...phone, composeText: null, - rolesAndPermissions: { permissions: { OutboundSMS: true } }, - }).getUIFunctions().canTextButtonShow; + appFeatures: { hasOutboundSMSPermission: true }, + }).getUIFunctions(defaultPropsParams).canTextButtonShow; expect(canTextButtonShow(phoneType)).toBeFalsy(); }); @@ -32,7 +32,7 @@ test('if the phoneType is fax, then should return false', () => { const { canTextButtonShow } = new ContactDetailsUI({ ...phone, composeText: {}, // not null - }).getUIFunctions(); + }).getUIFunctions(defaultPropsParams); expect(canTextButtonShow(phoneType)).toBeFalsy(); }); @@ -50,8 +50,8 @@ describe('Given phoneType is extension, the result is in proportion to the Inter const { canTextButtonShow } = new ContactDetailsUI({ ...phone, composeText: {}, // not null - rolesAndPermissions: { permissions: { InternalSMS } }, - }).getUIFunctions(); + appFeatures: { hasInternalSMSPermission: InternalSMS }, + }).getUIFunctions(defaultPropsParams); expect(canTextButtonShow(phoneType)).toBe(expected); }, @@ -74,8 +74,8 @@ describe('Given the phoneType is neither fax nor extension, then result is in pr const { canTextButtonShow } = new ContactDetailsUI({ ...phone, composeText: {}, // not null - rolesAndPermissions: { permissions: { OutboundSMS } }, - }).getUIFunctions(); + appFeatures: { hasOutboundSMSPermission: OutboundSMS }, + }).getUIFunctions(defaultPropsParams); expect(canTextButtonShow(phoneType)).toBe(expected); }, phoneTypeEnum); diff --git a/packages/ringcentral-widgets/test/modules/ContactDetailsUI/contact.test.js b/packages/ringcentral-widgets/test/modules/ContactDetailsUI/contact.test.js index b722eeba7b..545cb58484 100644 --- a/packages/ringcentral-widgets/test/modules/ContactDetailsUI/contact.test.js +++ b/packages/ringcentral-widgets/test/modules/ContactDetailsUI/contact.test.js @@ -1,9 +1,10 @@ import { ContactDetailsUI } from '../../../modules/ContactDetailsUI/ContactDetailsUI'; -import { phone } from './testUtils'; +import { phone } from './testSetup'; -describe('use contactId and contactType to get the specific contact', () => { +// TODO: prefer IT +describe.skip('use contactId and contactType to get the specific contact', () => { const mockContactsModule = { - find: jest.fn(), + findContact: jest.fn(), }; test.each` @@ -15,16 +16,22 @@ describe('use contactId and contactType to get the specific contact', () => { `( 'Given contactId: $contactId, contactType: $contactType, then $result', ({ contactId, contactType, shouldMatch }) => { - const { find: mockFind } = mockContactsModule; + const { findContact: mockFind } = mockContactsModule; const expectedContact = { id: contactId, type: contactType }; shouldMatch ? mockFind.mockReturnValueOnce(expectedContact) : mockFind.mockReturnValueOnce(null); - const { contact } = new ContactDetailsUI({ + const contactDetailsUI = new ContactDetailsUI({ ...phone, contacts: mockContactsModule, - }).getUIProps({ params: { contactId, contactType } }); + }); + contactDetailsUI + .getUIFunctions({ params: { contactId, contactType } }) + .onVisitPage(); + const { contact } = contactDetailsUI.getUIProps({ + params: { contactId, contactType }, + }); expect(mockFind).toBeCalledWith({ id: contactId, type: contactType }); shouldMatch ? expect(contact).toMatchObject(expectedContact) diff --git a/packages/ringcentral-widgets/test/modules/ContactDetailsUI/disableLinks.test.js b/packages/ringcentral-widgets/test/modules/ContactDetailsUI/disableLinks.test.js index 72d11f05d1..2475d874fb 100644 --- a/packages/ringcentral-widgets/test/modules/ContactDetailsUI/disableLinks.test.js +++ b/packages/ringcentral-widgets/test/modules/ContactDetailsUI/disableLinks.test.js @@ -1,5 +1,5 @@ import { ContactDetailsUI } from '../../../modules/ContactDetailsUI/ContactDetailsUI'; -import { phone, defaultPropsParams } from './testUtils'; +import { phone, defaultPropsParams } from './testSetup'; describe('If all dependencies = false, return false; Otherwise return true ', () => { test.each` diff --git a/packages/ringcentral-widgets/test/modules/ContactDetailsUI/formatNumber.test.js b/packages/ringcentral-widgets/test/modules/ContactDetailsUI/formatNumber.test.js index 5e2b05944a..0d4cf75605 100644 --- a/packages/ringcentral-widgets/test/modules/ContactDetailsUI/formatNumber.test.js +++ b/packages/ringcentral-widgets/test/modules/ContactDetailsUI/formatNumber.test.js @@ -4,7 +4,7 @@ import { parseIncompletePhoneNumber as mockParseIncompletePhoneNumber, } from '@ringcentral-integration/phone-number'; import { ContactDetailsUI } from '../../../modules/ContactDetailsUI/ContactDetailsUI'; -import { phone } from './testUtils'; +import { phone, defaultPropsParams } from './testSetup'; jest.mock('@ringcentral-integration/phone-number', () => ({ isE164: jest.fn(), @@ -24,7 +24,6 @@ const formattedNumber = '+12058711434'; const defaultProps = { ...phone, regionSettings: { countryCode: '' }, - extensionInfo: null, }; afterEach(() => { @@ -39,7 +38,7 @@ test("if phoneNumber's format is E164, it should return formattedNumber", () => mockParseIncompletePhoneNumber.mockReturnValueOnce(cleanNumber); const result = new ContactDetailsUI(defaultProps) - .getUIFunctions() + .getUIFunctions(defaultPropsParams) .formatNumber(phoneNumber); expect(result).toBe(formattedNumber); @@ -50,7 +49,9 @@ test("if phoneNumber isn't an E164 nor an extension, it should keep the number i mockIsE164.mockReturnValueOnce(false); const instance = new ContactDetailsUI(defaultProps); expect(mockFormatNumber).not.toBeCalled(); - const result = instance.getUIFunctions().formatNumber(phoneNumber); + const result = instance + .getUIFunctions(defaultPropsParams) + .formatNumber(phoneNumber); expect(result).toBe(phoneNumber); }); @@ -58,7 +59,9 @@ test('if phoneNumber is an extension, it should keep the number intact', () => { const phoneNumber = '24705'; mockIsE164.mockReturnValueOnce(false); const instance = new ContactDetailsUI(defaultProps); - const result = instance.getUIFunctions().formatNumber(phoneNumber); + const result = instance + .getUIFunctions(defaultPropsParams) + .formatNumber(phoneNumber); expect(mockFormatNumber).not.toBeCalled(); expect(mockParseIncompletePhoneNumber).toBeCalledWith(phoneNumber); expect(result).toBe(phoneNumber); @@ -75,7 +78,9 @@ describe('multiple site feature(just for extension)', () => { site: null, }, }); - const result = instance.getUIFunctions().formatNumber(phoneNumber); + const result = instance + .getUIFunctions(defaultPropsParams) + .formatNumber(phoneNumber); expect(mockFormatNumber).not.toBeCalled(); expect(mockParseIncompletePhoneNumber).toBeCalledWith(phoneNumber); expect(result).toBe(phoneNumber); @@ -90,7 +95,9 @@ describe('multiple site feature(just for extension)', () => { isMultipleSiteEnabled: false, }, }); - const result = instance.getUIFunctions().formatNumber(phoneNumber); + const result = instance + .getUIFunctions(defaultPropsParams) + .formatNumber(phoneNumber); expect(mockFormatNumber).not.toBeCalled(); expect(mockParseIncompletePhoneNumber).toBeCalledWith(phoneNumber); expect(result).toBe(phoneNumber); @@ -116,7 +123,9 @@ describe('multiple site feature(just for extension)', () => { }, }, }); - const result = instance.getUIFunctions().formatNumber(extension); + const result = instance + .getUIFunctions(defaultPropsParams) + .formatNumber(extension); expect(result).toBe(expected); }, ); diff --git a/packages/ringcentral-widgets/test/modules/ContactDetailsUI/isCallButtonDisabled.test.js b/packages/ringcentral-widgets/test/modules/ContactDetailsUI/isCallButtonDisabled.test.js index f80a1a54b1..7d9eb0bdef 100644 --- a/packages/ringcentral-widgets/test/modules/ContactDetailsUI/isCallButtonDisabled.test.js +++ b/packages/ringcentral-widgets/test/modules/ContactDetailsUI/isCallButtonDisabled.test.js @@ -1,5 +1,5 @@ import { ContactDetailsUI } from '../../../modules/ContactDetailsUI/ContactDetailsUI'; -import { phone, defaultPropsParams } from './testUtils'; +import { phone, defaultPropsParams } from './testSetup'; describe('If all dependencies = false, return false; Otherwise return true', () => { test.each` diff --git a/packages/ringcentral-widgets/test/modules/ContactDetailsUI/isMultipleSiteEnabled.test.js b/packages/ringcentral-widgets/test/modules/ContactDetailsUI/isMultipleSiteEnabled.test.js index 7528a85fbe..077e2c0e52 100644 --- a/packages/ringcentral-widgets/test/modules/ContactDetailsUI/isMultipleSiteEnabled.test.js +++ b/packages/ringcentral-widgets/test/modules/ContactDetailsUI/isMultipleSiteEnabled.test.js @@ -1,5 +1,5 @@ import { ContactDetailsUI } from '../../../modules/ContactDetailsUI/ContactDetailsUI'; -import { phone, defaultPropsParams } from './testUtils'; +import { phone, defaultPropsParams } from './testSetup'; describe('result is proportional to isMultipleSiteEnabled', () => { test.each` diff --git a/packages/ringcentral-widgets/test/modules/ContactDetailsUI/showSpinner.test.js b/packages/ringcentral-widgets/test/modules/ContactDetailsUI/showSpinner.test.js index 590256771c..d84c1ec637 100644 --- a/packages/ringcentral-widgets/test/modules/ContactDetailsUI/showSpinner.test.js +++ b/packages/ringcentral-widgets/test/modules/ContactDetailsUI/showSpinner.test.js @@ -1,5 +1,5 @@ import { ContactDetailsUI } from '../../../modules/ContactDetailsUI/ContactDetailsUI'; -import { phone } from './testUtils'; +import { phone } from './testSetup'; const defaultPropsParams = { params: { @@ -8,26 +8,22 @@ const defaultPropsParams = { }, }; -describe('If all the dependencies are true, return true; Otherwise return false;', () => { +// TODO: refactor to use IT +describe.skip('If all the dependencies are true, return true; Otherwise return false;', () => { test.each` - localeReady | contactSearchReady | rolesAndPermissionsReady | expected - ${true} | ${true} | ${true} | ${false} - ${false} | ${true} | ${true} | ${true} - ${true} | ${false} | ${true} | ${true} - ${true} | ${true} | ${false} | ${true} + localeReady | contactSearchReady | appFeaturesReady | expected + ${true} | ${true} | ${true} | ${false} + ${false} | ${true} | ${true} | ${true} + ${true} | ${false} | ${true} | ${true} + ${true} | ${true} | ${false} | ${true} `( - 'Given localeReady = $localeReady, contactSearchReady = $contactSearchReady, rolesAndPermissionsReady = $rolesAndPermissionsReady, return $expected', - ({ - localeReady, - contactSearchReady, - rolesAndPermissionsReady, - expected, - }) => { + 'Given localeReady = $localeReady, contactSearchReady = $contactSearchReady, appFeaturesReady = $appFeaturesReady, return $expected', + ({ localeReady, contactSearchReady, appFeaturesReady, expected }) => { const { showSpinner } = new ContactDetailsUI({ ...phone, locale: { ready: localeReady }, contactSearch: { ready: contactSearchReady }, - rolesAndPermissions: { ready: rolesAndPermissionsReady }, + appFeatures: { ready: appFeaturesReady }, }).getUIProps(defaultPropsParams); expect(showSpinner).toBe(expected); diff --git a/packages/ringcentral-widgets/test/modules/ContactDetailsUI/testSetup.js b/packages/ringcentral-widgets/test/modules/ContactDetailsUI/testSetup.js index 95b2400e2b..77f21a6766 100644 --- a/packages/ringcentral-widgets/test/modules/ContactDetailsUI/testSetup.js +++ b/packages/ringcentral-widgets/test/modules/ContactDetailsUI/testSetup.js @@ -2,7 +2,7 @@ export const phone = { routerInteraction: null, contactSearch: null, contacts: null, - rolesAndPermissions: null, + appFeatures: {}, rateLimiter: null, regionSettings: null, connectivityManager: null, @@ -10,9 +10,9 @@ export const phone = { dialerUI: null, composeText: null, brand: null, - locale: null, + locale: {}, callingSettings: null, - extensionInfo: null, + extensionInfo: {}, }; export const defaultPropsParams = { diff --git a/packages/test-utils/README.md b/packages/test-utils/README.md index d9ff6fbc1a..a1de28b20f 100644 --- a/packages/test-utils/README.md +++ b/packages/test-utils/README.md @@ -24,6 +24,17 @@ Run the following command to start `jest.retryTimes(3)` by default on CI: cross-env NODE_ENV=ci yarn jest ``` +## Run test with CLI + +```sh +cd example-project-dir +yarn run-test +``` + +You can use it with any jest cli parameter. For example, `yarn run-test --coverage`. + +> If the run-test command does not exist, just run `npm link @ringcentral-integration/test-utils` in repo root directory. + ## APIs - `mount(Component, props)` diff --git a/packages/test-utils/bin/run-test.js b/packages/test-utils/bin/run-test.js new file mode 100755 index 0000000000..3a3c515492 --- /dev/null +++ b/packages/test-utils/bin/run-test.js @@ -0,0 +1,21 @@ +#!/usr/bin/env node +const fs = require('fs-extra'); +const path = require('path'); +const execa = require('execa'); + +const currentDir = process.cwd(); +const rootDir = path.resolve(__dirname, '../../../'); +const { testPaths = ['.'] } = fs.readJsonSync('package.json'); +const projectPaths = testPaths + .map((testPath) => path.relative(rootDir, path.resolve(currentDir, testPath))) + .join(' '); + +process.chdir(rootDir); + +const argv = ['--projects', projectPaths] + .concat(process.argv.slice(2)) + .join(' '); + +execa.commandSync(`yarn jest ${argv}`, { + stdio: 'inherit', +}); diff --git a/packages/test-utils/lib/render.tsx b/packages/test-utils/lib/render.tsx index e3a6a079b8..4abd29d589 100644 --- a/packages/test-utils/lib/render.tsx +++ b/packages/test-utils/lib/render.tsx @@ -27,6 +27,18 @@ export const mount: ( ); }; +export const remount = ( + rerender: ReRender, + Component: ComponentType, + props: T, +) => { + return rerender( + + + , + ); +}; + function _pageRender( page: any, sourceProps: any, diff --git a/packages/test-utils/lib/test-utils/index.ts b/packages/test-utils/lib/test-utils/index.ts new file mode 100644 index 0000000000..f235ac2cc1 --- /dev/null +++ b/packages/test-utils/lib/test-utils/index.ts @@ -0,0 +1,2 @@ +export * from './test-utils'; +export * from './waitForRenderReady'; diff --git a/packages/test-utils/lib/test-utils.tsx b/packages/test-utils/lib/test-utils/test-utils.tsx similarity index 100% rename from packages/test-utils/lib/test-utils.tsx rename to packages/test-utils/lib/test-utils/test-utils.tsx diff --git a/packages/test-utils/lib/test-utils/waitForRenderReady.ts b/packages/test-utils/lib/test-utils/waitForRenderReady.ts new file mode 100644 index 0000000000..e65fbf3662 --- /dev/null +++ b/packages/test-utils/lib/test-utils/waitForRenderReady.ts @@ -0,0 +1,22 @@ +import { act } from '@testing-library/react'; + +/** + * use for ait react renderer task ready, + * when you need event bind with re-render + * + * + * always use like below + * + * @example + * + * ```ts + * jest.useFakeTimers(); + * + * // some action you want to trigger + * + * await waitForRenderReady(); + * jest.runOnlyPendingTimers(); + * jest.useRealTimers(); + * ``` + */ +export const waitForRenderReady = () => act(() => Promise.resolve()); diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json index 23ce08a29a..064c8018c5 100644 --- a/packages/test-utils/package.json +++ b/packages/test-utils/package.json @@ -8,7 +8,8 @@ "test": "echo \"Error: no test specified\" && exit 1" }, "bin": { - "test-cli": "bin/index.js" + "test-cli": "bin/index.js", + "run-test": "bin/run-test.js" }, "repository": { "type": "git", @@ -22,19 +23,21 @@ "license": "MIT", "dependencies": { "@ringcentral-integration/babel-settings": "*", - "@ringcentral/juno": "^1.8.5-beta.5034-128a9f16", + "@ringcentral/juno": "^1.11.2", "@testing-library/react": "^11.2.6", "babel-jest": "^27.0.1", "babel-preset-crius": "^1.0.0-alpha.2", "cross-env": "^5.1.3", "enzyme": "^3.7.0", - "enzyme-adapter-react-16": "^1.6.0", + "execa": "^5.0.0", + "@wojtekmaj/enzyme-adapter-react-17": "^0.6.3", "enzyme-to-json": "^3.3.4", + "fs-extra": "^9.0.1", "identity-obj-proxy": "3.0.0", "jest": "^27.0.1", "jest-circus": "^27.0.1", "jest-junit": "^6.3.0", - "react": "^16.14.0", + "react": "^17.0.2", "@ringcentral-integration/crius": "*" } } diff --git a/packages/test-utils/scripts/jest.setup.js b/packages/test-utils/scripts/jest.setup.js index 354815a3c0..fe253d1255 100644 --- a/packages/test-utils/scripts/jest.setup.js +++ b/packages/test-utils/scripts/jest.setup.js @@ -1,5 +1,5 @@ import { configure } from 'enzyme'; -import Adapter from 'enzyme-adapter-react-16'; +import Adapter from '@wojtekmaj/enzyme-adapter-react-17'; // Using for React UI component Unit Test. const adapter = new Adapter(); diff --git a/packages/tsconfig.json b/packages/tsconfig.json index d20e4e71ff..2e091f5f19 100644 --- a/packages/tsconfig.json +++ b/packages/tsconfig.json @@ -60,12 +60,6 @@ // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ "resolveJsonModule": true, - /* Custom Options */ - "plugins": [], - "baseUrl": "./", - "paths": { - "ringcentral-widgets/*": ["./ringcentral-widgets/*"] - } }, "exclude": ["node_modules"] } diff --git a/yarn.lock b/yarn.lock index 3af2fc84ee..a3778dc18c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -971,7 +971,7 @@ core-js-pure "^3.0.0" regenerator-runtime "^0.13.4" -"@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.5", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.2.0", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.0", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": +"@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.5", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.5", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.0", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": version "7.14.0" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.14.0.tgz#46794bc20b612c5f75e62dd071e24dfd95f1cbe6" integrity sha512-JELkvo/DlpNdJ7dlyw/eY7E0suy5i5GQH+Vlxaq1nsNJ+H7f4Vtv3jMeCEgRhZZQFXTjldYfQgv2qmM6M1v5wA== @@ -1537,42 +1537,57 @@ resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.15.tgz#6a9d143f7f4f49db2d782f9e1c8839a29b43ae23" integrity sha512-15spi3V28QdevleWBNXE4pIls3nFZmBbUGrW9IVPwiQczuSb9n76TCB4bsk8TSel+I1OkHEdPhu5QKMfY6rQHA== -"@rc-ex/core@^0.8.1": - version "0.8.1" - resolved "https://registry.yarnpkg.com/@rc-ex/core/-/core-0.8.1.tgz#df53fa3df3ff48f43875dc8f55aea0f7edf45d2a" - integrity sha512-T/niq/4g65NY9VP9Xjo0Hwbe82j65YJEe1zTWgOLEIt8NWlsmXwy+3vRYeMNFJVkgYzIe7hm9t7KxOSHxkELKA== +"@rc-ex/core@^0.9.3": + version "0.9.3" + resolved "https://registry.yarnpkg.com/@rc-ex/core/-/core-0.9.3.tgz#6253367f89c7d84751f9724df6b64a04634b0697" + integrity sha512-QCyFiUvPOM9L9fdyxBStPCxK6o3BWPOj/9BIyGtvXOPqlvKkFVR6aG8SMevjAs1xMfRk5n3rbRgf4HwSa6S+Xw== dependencies: - "@types/qs" "^6.9.6" + "@types/qs" "^6.9.7" axios "^0.21.1" form-data "^4.0.0" qs "^6.10.1" -"@rc-ex/debug@^0.7.9": - version "0.7.9" - resolved "https://registry.yarnpkg.com/@rc-ex/debug/-/debug-0.7.9.tgz#f6eb569b81ac257e590fd3222a8304e91ed1511e" - integrity sha512-IElV6g7c9M3NtkB3VqfzC1aNVM8DSZMOscrHGpHe3fU1P+OxuRmWD5ERe4taTYph0fYV7BeeonOCX+ReY7p5Bw== +"@rc-ex/debug@^0.7.20": + version "0.7.20" + resolved "https://registry.yarnpkg.com/@rc-ex/debug/-/debug-0.7.20.tgz#d5cc1b38a9c0cfd08f08bb9119154d585bd7d5a0" + integrity sha512-jmCNzQnfZ3Svz9kXTMJ0Qz84+xD28mRvQWz2MbWyoyfroUoHCJVjD19xdF8Dvx/1vnBfPVR1gaKAPsZ7crWBGw== + +"@rc-ex/rate-limit@^0.7.20": + version "0.7.20" + resolved "https://registry.yarnpkg.com/@rc-ex/rate-limit/-/rate-limit-0.7.20.tgz#d860bd49133df22b7cfaf23db886878f7cf75060" + integrity sha512-YgG5qGJGUFTb1UE5istYdPL6BRtVMYv5AVP1IkP+8annwNJtBU0OKYsRiLBTYv7cEctFxMxZ66bmYWlGib00iw== + dependencies: + "@rc-ex/retry" "^0.7.20" -"@rc-ex/rcsdk@^0.7.9": - version "0.7.9" - resolved "https://registry.yarnpkg.com/@rc-ex/rcsdk/-/rcsdk-0.7.9.tgz#6f85668aae8390585645b57e7e0ab14b0a37fe83" - integrity sha512-+Ex+EuSMeqP+u4m9/iLR7YsBYRLDkzJrSRZsL1z8/Sbm2p5DPDyZRH05aj7Bwh5QSUQUzGBTQc5voaR7WjhqyQ== +"@rc-ex/rcsdk@^0.7.20": + version "0.7.20" + resolved "https://registry.yarnpkg.com/@rc-ex/rcsdk/-/rcsdk-0.7.20.tgz#d3f32491c8de2f9be12f356f3f762ffc2ced754a" + integrity sha512-iA8xS/6yhu7r84jz30tpTdj7Nc5hVaMonSCbiwc6/4MdekVITtMje5lxprGJLzs2zw4PTztuiiFAkxtmlesOtA== -"@rc-ex/ws@^0.9.10": - version "0.9.10" - resolved "https://registry.yarnpkg.com/@rc-ex/ws/-/ws-0.9.10.tgz#3b035c70a758bc43abae98c62c99b43c91db1e7d" - integrity sha512-dNhtW+7j/rnE41sg4IDGAntJj+2DgsbwkskrrlX9juH55sEoI8/uadC5xiimjHTQde40bADpPYCzNguWT1bxRg== +"@rc-ex/retry@^0.7.20": + version "0.7.20" + resolved "https://registry.yarnpkg.com/@rc-ex/retry/-/retry-0.7.20.tgz#c8de6404fa7015c44baa97012e3c88cbd8a945b0" + integrity sha512-I+95Re8rq2M+f2DetE2Uj1zCptD8DM0ShUCysA8MR1p3nJCJ7gOB5CT70TlZeJhTCX65dygN5lLcKWqCBNlXMA== dependencies: - "@types/ws" "^7.4.2" + wait-for-async "^0.5.0" + +"@rc-ex/ws@^0.10.2": + version "0.10.2" + resolved "https://registry.yarnpkg.com/@rc-ex/ws/-/ws-0.10.2.tgz#3cf0a1fd741241771f9495030f9c2f2b005d11a4" + integrity sha512-Q9ZlYUh/tHnX0UAJh4XpG6b40M6OJSnz4lRoxj3Y+aePdZ9XBc6BsBrQmr8CFgq4nos9FAB9zbXuCn4OFgXNtw== + dependencies: + "@rc-ex/rate-limit" "^0.7.20" + "@types/ws" "^7.4.7" http-status-codes "^2.1.4" - hyperid "^2.1.0" + hyperid "^2.3.1" isomorphic-ws "^4.0.1" wait-for-async "^0.5.0" - ws "^7.4.5" + ws "^8.2.0" -"@ringcentral/juno@^1.8.5-beta.5034-128a9f16": - version "1.8.5-beta.5034-128a9f16" - resolved "https://registry.yarnpkg.com/@ringcentral/juno/-/juno-1.8.5-beta.5034-128a9f16.tgz#d2344888201ca94af25a93c555207fe31a2a6ad8" - integrity sha512-62AL7t+bQ4W6etL+HpkuBoYc+SuMAGYqyC6U4TYnu5u1PI1acl4dC1ykD4P/kumvl8+xdwUOCeWiNgiAIYQvEg== +"@ringcentral/juno@^1.11.2": + version "1.11.2" + resolved "https://registry.yarnpkg.com/@ringcentral/juno/-/juno-1.11.2.tgz#0714f0eb1a35763d31dab8a475a5b813f508b274" + integrity sha512-PLv5/eF4E2dP8KvqKxFNiDlr1dDrual1tQquzQVLmXonFNMzrFaqvr8jdYxB4rZmbI8tdSTESHrPPBO8aAEOWQ== dependencies: "@date-io/moment" "^1.3.11" "@emotion/core" "^10.0.27" @@ -1580,39 +1595,30 @@ "@material-ui/lab" "^4.0.0-alpha.57" "@material-ui/pickers" "^3.2.10" "@material-ui/styles" "^4.11.3" - "@types/animejs" "^3.1.0" "@types/lodash" "^4.14.169" "@types/react-beautiful-dnd" "^13.0.0" - "@types/smoothscroll-polyfill" "^0.3.1" "@types/styled-components" "4.0.3" - animejs "^3.1.0" clsx "^1.0.4" - deepmerge "^4.0.0" - downshift "^6.1.0" focus-visible "^5.1.0" lodash "^4.17.21" react-beautiful-dnd "^13.0.0" - react-resize-detector "^4.2.1" - react-sortable-hoc "^1.11.0" - react-useportal "^1.0.13" - react-virtuoso "^1.8.6" + react-virtuoso "^1.9.3" resize-observer-polyfill "^1.5.1" - smoothscroll-polyfill "^0.4.4" typeface-lato "^0.0.75" -"@ringcentral/sdk@^4.5.0": - version "4.5.0" - resolved "https://registry.yarnpkg.com/@ringcentral/sdk/-/sdk-4.5.0.tgz#619a65012ac97b7c11b283bac3240a9ad261ded7" - integrity sha512-BrRJ37u4RsWtgCiKL4c7n6iWqFmqbGWJkIJnWjDd3rpuDoPGRzy5MAvzpM+Y8dwiL9o8+9pmkOPnTPUzo83Rpw== +"@ringcentral/sdk@^4.5.0", "@ringcentral/sdk@^4.6.0": + version "4.6.0" + resolved "https://registry.yarnpkg.com/@ringcentral/sdk/-/sdk-4.6.0.tgz#ee3f6a9725494cdd8bac8f3059b6fb12295bf7d1" + integrity sha512-Cwwqfd5MFIJeATnTponkDrWbshzeWujWwdigQhXVG6oaKCt20GNdWx5lT4jRpEzfNlIVgxd16Nqv0yOepWwRtg== dependencies: dom-storage "2.1.0" is-plain-object "2.0.4" node-fetch "2.6.1" -"@ringcentral/subscriptions@^4.5.0": - version "4.5.0" - resolved "https://registry.yarnpkg.com/@ringcentral/subscriptions/-/subscriptions-4.5.0.tgz#09c68108187dc4e132929451329257bae35ead83" - integrity sha512-3tyRgx3nK9ZDVzly8ZtCky17VllQEtcAsw4/WiUNMW89YLKoMLSSkLlFttEMIUmV4Qe+wtK6qe7zpKEApdB0fw== +"@ringcentral/subscriptions@^4.5.0", "@ringcentral/subscriptions@^4.6.0": + version "4.6.0" + resolved "https://registry.yarnpkg.com/@ringcentral/subscriptions/-/subscriptions-4.6.0.tgz#70c1263d13d201b332629ec45bf544a2075dd5e9" + integrity sha512-Pv/YR9lfPRZaLiAu9c3yWpzUXOksyHkQqBTY8p/vQQ2xYNWgwP8+NZrFw953Rpp108zjqgQNzigS8sYvt2N35w== dependencies: pubnub "^4.29.11" @@ -1683,9 +1689,9 @@ "@sinonjs/commons" "^1.7.0" "@testing-library/dom@^7.28.1": - version "7.29.6" - resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-7.29.6.tgz#eb37844fb431186db7960a7ff6749ea65a19617c" - integrity sha512-vzTsAXa439ptdvav/4lsKRcGpAQX7b6wBIqia7+iNzqGJ5zjswApxA6jDAsexrc6ue9krWcbh8o+LYkBXW+GCQ== + version "7.29.4" + resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-7.29.4.tgz#1647c2b478789621ead7a50614ad81ab5ae5b86c" + integrity sha512-CtrJRiSYEfbtNGtEsd78mk1n1v2TUbeABlNIcOCJdDfkN5/JTOwQEbbQpoSRxGqzcWPgStMvJ4mNolSuBRv1NA== dependencies: "@babel/code-frame" "^7.10.4" "@babel/runtime" "^7.12.5" @@ -1725,11 +1731,6 @@ resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw== -"@types/animejs@^3.1.0": - version "3.1.2" - resolved "https://registry.yarnpkg.com/@types/animejs/-/animejs-3.1.2.tgz#93289a902b0b9bfac3020d29413139dcca6acdbc" - integrity sha512-GyyuoztWbZMErx9brJQChvvfeMd5vplWU/H6BYVl7JUcLoMaDOVxlqF3d4ypB7TzXnbgnMSykGmjAVVRsvhHhQ== - "@types/aria-query@^4.2.0": version "4.2.0" resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-4.2.0.tgz#14264692a9d6e2fa4db3df5e56e94b5e25647ac0" @@ -1888,10 +1889,10 @@ resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.4.tgz#15925414e0ad2cd765bfef58842f7e26a7accb24" integrity sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug== -"@types/qs@^6.9.6": - version "6.9.6" - resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.6.tgz#df9c3c8b31a247ec315e6996566be3171df4b3b1" - integrity sha512-0/HnwIfW4ki2D8L8c9GVcG5I72s9jP5GSLVF0VIXDW00kmIpA6O33G7a8n59Tmh7Nz0WUC3rSb7PTY/sdW2JzA== +"@types/qs@^6.9.7": + version "6.9.7" + resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb" + integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw== "@types/react-beautiful-dnd@^13.0.0": version "13.0.0" @@ -1915,11 +1916,6 @@ "@types/prop-types" "*" csstype "^2.2.0" -"@types/smoothscroll-polyfill@^0.3.1": - version "0.3.1" - resolved "https://registry.yarnpkg.com/@types/smoothscroll-polyfill/-/smoothscroll-polyfill-0.3.1.tgz#77fb3a6e116bdab4a5959122e3b8e201224dcd49" - integrity sha512-+KkHw4y+EyeCtVXET7woHUhIbfWFCflc0E0mZnSV+ZdjPQeHt/9KPEuT7gSW/kFQ8O3EG30PLO++YhChDt8+Ag== - "@types/stack-utils@^2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.0.tgz#7036640b4e21cc2f259ae826ce843d277dad8cff" @@ -1947,10 +1943,10 @@ dependencies: "@types/jest" "*" -"@types/ws@^7.4.2": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@types/ws/-/ws-7.4.4.tgz#93e1e00824c1de2608c30e6de4303ab3b4c0c9bc" - integrity sha512-d/7W23JAXPodQNbOZNXvl2K+bqAQrCMwlh/nuQsPSQk6Fq0opHoPrUw43aHsvSbIiQPr8Of2hkFbnz1XBFVyZQ== +"@types/ws@^7.4.7": + version "7.4.7" + resolved "https://registry.yarnpkg.com/@types/ws/-/ws-7.4.7.tgz#f7c390a36f7a0679aa69de2d501319f4f8d9b702" + integrity sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww== dependencies: "@types/node" "*" @@ -2221,6 +2217,31 @@ "@webassemblyjs/wast-parser" "1.9.0" "@xtuc/long" "4.2.2" +"@wojtekmaj/enzyme-adapter-react-17@^0.6.3": + version "0.6.3" + resolved "https://registry.yarnpkg.com/@wojtekmaj/enzyme-adapter-react-17/-/enzyme-adapter-react-17-0.6.3.tgz#bf7cd6007d99996bd7d98c843644b213a3ecc74e" + integrity sha512-Kp1ZJxtHkKEnUksaWrcMABNTOgL4wOt8VI6k2xOek2aH9PtZcWRXJNUEgnKrdJrqg5UqIjRslbVF9uUqwQJtFg== + dependencies: + "@wojtekmaj/enzyme-adapter-utils" "^0.1.1" + enzyme-shallow-equal "^1.0.0" + has "^1.0.0" + object.assign "^4.1.0" + object.values "^1.1.0" + prop-types "^15.7.0" + react-is "^17.0.2" + react-test-renderer "^17.0.0" + +"@wojtekmaj/enzyme-adapter-utils@^0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@wojtekmaj/enzyme-adapter-utils/-/enzyme-adapter-utils-0.1.1.tgz#17773cf264570fbcfc0d33bb74e4002c17f2f1ec" + integrity sha512-bNPWtN/d8huKOkC6j1E3EkSamnRrHHT7YuR6f9JppAQqtoAm3v4/vERe4J14jQKmHLCyEBHXrlgb7H6l817hVg== + dependencies: + function.prototype.name "^1.1.0" + has "^1.0.0" + object.assign "^4.1.0" + object.fromentries "^2.0.0" + prop-types "^15.7.0" + "@xtuc/ieee754@^1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" @@ -2357,22 +2378,6 @@ aggregate-error@^3.0.0: clean-stack "^2.0.0" indent-string "^4.0.0" -airbnb-prop-types@^2.15.0: - version "2.15.0" - resolved "https://registry.yarnpkg.com/airbnb-prop-types/-/airbnb-prop-types-2.15.0.tgz#5287820043af1eb469f5b0af0d6f70da6c52aaef" - integrity sha512-jUh2/hfKsRjNFC4XONQrxo/n/3GG4Tn6Hl0WlFQN5PY9OMC9loSCoAYKnZsWaP8wEfd5xcrPloK0Zg6iS1xwVA== - dependencies: - array.prototype.find "^2.1.0" - function.prototype.name "^1.1.1" - has "^1.0.3" - is-regex "^1.0.4" - object-is "^1.0.1" - object.assign "^4.1.0" - object.entries "^1.1.0" - prop-types "^15.7.2" - prop-types-exact "^1.2.0" - react-is "^16.9.0" - ajv-errors@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.1.tgz#f35986aceb91afadec4102fbd85014950cefa64d" @@ -2403,11 +2408,6 @@ animate.css@^3.5.2: resolved "https://registry.yarnpkg.com/animate.css/-/animate.css-3.7.2.tgz#e73e0d50e92cb1cfef1597d9b38a9481020e08ea" integrity sha512-0bE8zYo7C0KvgOYrSVfrzkbYk6IOTVPNqkiHg2cbyF4Pq/PXzilz4BRWA3hwEUBoMp5VBgrC29lQIZyhRWdBTw== -animejs@^3.1.0: - version "3.2.1" - resolved "https://registry.yarnpkg.com/animejs/-/animejs-3.2.1.tgz#de9fe2e792f44a777a7fdf6ae160e26604b0cdda" - integrity sha512-sWno3ugFryK5nhiDm/2BKeFCpZv7vzerWUcUPyAZLDhMek3+S/p418ldZJbJXo5ZUOpfm2kP2XRO4NJcULMy9A== - ansi-colors@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-1.1.0.tgz#6374b4dd5d4718ff3ce27a671a3b1cad077132a9" @@ -2701,14 +2701,6 @@ array-unique@^0.3.2: resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= -array.prototype.find@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/array.prototype.find/-/array.prototype.find-2.1.1.tgz#3baca26108ca7affb08db06bf0be6cb3115a969c" - integrity sha512-mi+MYNJYLTx2eNYy+Yh6raoQacCsNeeMUaspFPh9Y141lFSsWxxB8V9mM2ye+eqiRs917J6/pJ4M9ZPzenWckA== - dependencies: - define-properties "^1.1.3" - es-abstract "^1.17.4" - array.prototype.flat@^1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.2.3.tgz#0de82b426b0318dbfdb940089e38b043d37f6c7b" @@ -2731,7 +2723,7 @@ asap@~1.0.0: resolved "https://registry.yarnpkg.com/asap/-/asap-1.0.0.tgz#b2a45da5fdfa20b0496fc3768cc27c12fa916a7d" integrity sha1-sqRdpf36ILBJb8N2jMJ8EvqRan0= -asap@~2.0.3, asap@~2.0.6: +asap@~2.0.3: version "2.0.6" resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY= @@ -3710,13 +3702,13 @@ cachedir@2.2.0: resolved "https://registry.yarnpkg.com/cachedir/-/cachedir-2.2.0.tgz#19afa4305e05d79e417566882e0c8f960f62ff0e" integrity sha512-VvxA0xhNqIIfg0V9AmJkDg91DaJwryutH5rVEZAhcNi4iJFj9f+QxmAjgK1LT9I8OgToX27fypX6/MeCXVbBjQ== -call-bind@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.0.tgz#24127054bb3f9bdcb4b1fb82418186072f77b8ce" - integrity sha512-AEXsYIyyDY3MCzbwdhzG3Jx1R0J2wetQyUynn6dYHAO+bg8l1k7jwZtRv4ryryFs7EP+NDlikJlVe59jr0cM2w== +call-bind@^1.0.0, call-bind@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" + integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== dependencies: function-bind "^1.1.1" - get-intrinsic "^1.0.0" + get-intrinsic "^1.0.2" caller-callsite@^2.0.0: version "2.0.0" @@ -4242,11 +4234,6 @@ compression@^1.7.4: safe-buffer "5.1.2" vary "~1.1.2" -compute-scroll-into-view@^1.0.17: - version "1.0.17" - resolved "https://registry.yarnpkg.com/compute-scroll-into-view/-/compute-scroll-into-view-1.0.17.tgz#6a88f18acd9d42e9cf4baa6bec7e0522607ab7ab" - integrity sha512-j4dx+Fb0URmzbwwMUrhqWM2BEWHdFGx+qZ9qqASHRPqvTYdqvWnHg0H1hIbcyLnvgnoNAVMlwkepyqM3DaIFUg== - concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -4415,7 +4402,7 @@ core-js@^2.4.0, core-js@^2.4.1, core-js@^2.5.0, core-js@^2.6.11: resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.11.tgz#38831469f9922bded8ee21c9dc46985e0399308c" integrity sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg== -core-js@^3.2.1, core-js@^3.5.0: +core-js@^3.2.1: version "3.14.0" resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.14.0.tgz#62322b98c71cc2018b027971a69419e2425c2a6c" integrity sha512-3s+ed8er9ahK+zJpp9ZtuVcDoFzHNiZsPbNAAE4KXgrRHbjSqqNN6xGSXq6bq7TZIbKj4NLrLb6bJ5i+vSVjHA== @@ -4953,7 +4940,7 @@ deep-is@^0.1.3, deep-is@~0.1.3: resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= -deepmerge@^4.0.0, deepmerge@^4.2.2: +deepmerge@^4.2.2: version "4.2.2" resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== @@ -5316,16 +5303,6 @@ dotenv@^6.2.0: resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-6.2.0.tgz#941c0410535d942c8becf28d3f357dbd9d476064" integrity sha512-HygQCKUBSFl8wKQZBSemMywRWcEDNidvNbjGVyZu3nbZ8qq9ubiPoGLMdRDpfSrpkkm9BXYFkpKxxFX38o/76w== -downshift@^6.1.0: - version "6.1.3" - resolved "https://registry.yarnpkg.com/downshift/-/downshift-6.1.3.tgz#e794b7805d24810968f21e81ad6bdd9f3fdc40da" - integrity sha512-RA1MuaNcTbt0j+sVLhSs8R2oZbBXYAtdQP/V+uHhT3DoDteZzJPjlC+LQVm9T07Wpvo84QXaZtUCePLDTDwGXg== - dependencies: - "@babel/runtime" "^7.13.10" - compute-scroll-into-view "^1.0.17" - prop-types "^15.7.2" - react-is "^17.0.2" - draft-js@^0.10.0, draft-js@~0.10.0: version "0.10.5" resolved "https://registry.yarnpkg.com/draft-js/-/draft-js-0.10.5.tgz#bfa9beb018fe0533dbb08d6675c371a6b08fa742" @@ -5492,40 +5469,13 @@ entities@^2.0.0: resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.2.tgz#ac74db0bba8d33808bbf36809c3a5c3683531436" integrity sha512-dmD3AvJQBUjKpcNkoqr+x+IF0SdRtPz9Vk0uTy4yWqga9ibB6s4v++QFWNohjiUGoMlF552ZvNyXDxz5iW0qmw== -enzyme-adapter-react-16@^1.15.1, enzyme-adapter-react-16@^1.6.0: - version "1.15.2" - resolved "https://registry.yarnpkg.com/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.15.2.tgz#b16db2f0ea424d58a808f9df86ab6212895a4501" - integrity sha512-SkvDrb8xU3lSxID8Qic9rB8pvevDbLybxPK6D/vW7PrT0s2Cl/zJYuXvsd1EBTz0q4o3iqG3FJhpYz3nUNpM2Q== - dependencies: - enzyme-adapter-utils "^1.13.0" - enzyme-shallow-equal "^1.0.1" - has "^1.0.3" - object.assign "^4.1.0" - object.values "^1.1.1" - prop-types "^15.7.2" - react-is "^16.12.0" - react-test-renderer "^16.0.0-0" - semver "^5.7.0" - -enzyme-adapter-utils@^1.13.0: - version "1.13.0" - resolved "https://registry.yarnpkg.com/enzyme-adapter-utils/-/enzyme-adapter-utils-1.13.0.tgz#01c885dde2114b4690bf741f8dc94cee3060eb78" - integrity sha512-YuEtfQp76Lj5TG1NvtP2eGJnFKogk/zT70fyYHXK2j3v6CtuHqc8YmgH/vaiBfL8K1SgVVbQXtTcgQZFwzTVyQ== - dependencies: - airbnb-prop-types "^2.15.0" - function.prototype.name "^1.1.2" - object.assign "^4.1.0" - object.fromentries "^2.0.2" - prop-types "^15.7.2" - semver "^5.7.1" - -enzyme-shallow-equal@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/enzyme-shallow-equal/-/enzyme-shallow-equal-1.0.1.tgz#7afe03db3801c9b76de8440694096412a8d9d49e" - integrity sha512-hGA3i1so8OrYOZSM9whlkNmVHOicJpsjgTzC+wn2JMJXhq1oO4kA4bJ5MsfzSIcC71aLDKzJ6gZpIxrqt3QTAQ== +enzyme-shallow-equal@^1.0.0, enzyme-shallow-equal@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/enzyme-shallow-equal/-/enzyme-shallow-equal-1.0.4.tgz#b9256cb25a5f430f9bfe073a84808c1d74fced2e" + integrity sha512-MttIwB8kKxypwHvRynuC3ahyNc+cFbR8mjVIltnmzQ0uKGqmsfO4bfBuLxb0beLNPhjblUEYvEbsg+VSygvF1Q== dependencies: has "^1.0.3" - object-is "^1.0.2" + object-is "^1.1.2" enzyme-to-json@^3.3.4: version "3.5.0" @@ -5577,22 +5527,28 @@ error-ex@^1.2.0, error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" -es-abstract@^1.17.0, es-abstract@^1.17.0-next.1, es-abstract@^1.17.2, es-abstract@^1.17.4, es-abstract@^1.17.5: - version "1.17.5" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.5.tgz#d8c9d1d66c8981fb9200e2251d799eee92774ae9" - integrity sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg== +es-abstract@^1.17.0, es-abstract@^1.17.0-next.1, es-abstract@^1.17.2, es-abstract@^1.17.5, es-abstract@^1.18.0-next.2: + version "1.18.5" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.5.tgz#9b10de7d4c206a3581fd5b2124233e04db49ae19" + integrity sha512-DDggyJLoS91CkJjgauM5c0yZMjiD1uK3KcaCeAmffGwZ+ODWzOkPN4QwRbsK5DOFf06fywmyLci3ZD8jLGhVYA== dependencies: + call-bind "^1.0.2" es-to-primitive "^1.2.1" function-bind "^1.1.1" + get-intrinsic "^1.1.1" has "^1.0.3" - has-symbols "^1.0.1" - is-callable "^1.1.5" - is-regex "^1.0.5" - object-inspect "^1.7.0" + has-symbols "^1.0.2" + internal-slot "^1.0.3" + is-callable "^1.2.3" + is-negative-zero "^2.0.1" + is-regex "^1.1.3" + is-string "^1.0.6" + object-inspect "^1.11.0" object-keys "^1.1.1" - object.assign "^4.1.0" - string.prototype.trimleft "^2.1.1" - string.prototype.trimright "^2.1.1" + object.assign "^4.1.2" + string.prototype.trimend "^1.0.4" + string.prototype.trimstart "^1.0.4" + unbox-primitive "^1.0.1" es-to-primitive@^1.2.1: version "1.2.1" @@ -6700,24 +6656,25 @@ function-bind@^1.1.1: resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== -function.prototype.name@^1.1.1, function.prototype.name@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.2.tgz#5cdf79d7c05db401591dfde83e3b70c5123e9a45" - integrity sha512-C8A+LlHBJjB2AdcRPorc5JvJ5VUoWlXdEHLOJdCI7kjHEtGTpHQUiqMvCIKUwIsGwZX2jZJy761AXsn356bJQg== +function.prototype.name@^1.1.0, function.prototype.name@^1.1.2: + version "1.1.4" + resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.4.tgz#e4ea839b9d3672ae99d0efd9f38d9191c5eaac83" + integrity sha512-iqy1pIotY/RmhdFZygSSlW0wko2yxkSCKqsuv4pr8QESohpYyG/Z7B/XXvPRKTJS//960rgguE5mSRUsDdaJrQ== dependencies: + call-bind "^1.0.2" define-properties "^1.1.3" - es-abstract "^1.17.0-next.1" - functions-have-names "^1.2.0" + es-abstract "^1.18.0-next.2" + functions-have-names "^1.2.2" functional-red-black-tree@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= -functions-have-names@^1.2.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.1.tgz#a981ac397fa0c9964551402cdc5533d7a4d52f91" - integrity sha512-j48B/ZI7VKs3sgeI2cZp7WXWmZXu7Iq5pl5/vptV5N2mq+DGFuS/ulaDjtaoLpYzuD6u8UgrUKHfgo7fDTSiBA== +functions-have-names@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.2.tgz#98d93991c39da9361f8e50b337c4f6e41f120e21" + integrity sha512-bLgc3asbWdwPbx2mNk2S49kmJCuQeu0nfmaOgbs8WIyzzkw3r4htszdIi9Q9EMezDPTYuJx2wvjZ/EwgAthpnA== gauge@~2.7.3: version "2.7.4" @@ -6772,7 +6729,7 @@ get-func-name@^2.0.0: resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" integrity sha1-6td0q+5y4gQJQzoGY2YCPdaIekE= -get-intrinsic@^1.0.0, get-intrinsic@^1.0.2: +get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6" integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q== @@ -7187,6 +7144,11 @@ has-ansi@^2.0.0: dependencies: ansi-regex "^2.0.0" +has-bigints@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.1.tgz#64fe6acb020673e3b78db035a5af69aa9d07b113" + integrity sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA== + has-flag@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" @@ -7207,10 +7169,17 @@ has-flag@^4.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== -has-symbols@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" - integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== +has-symbols@^1.0.1, has-symbols@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423" + integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw== + +has-tostringtag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" + integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== + dependencies: + has-symbols "^1.0.2" has-unicode@^2.0.0: version "2.0.1" @@ -7521,12 +7490,12 @@ humanize-ms@^1.2.1: dependencies: ms "^2.0.0" -hyperid@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/hyperid/-/hyperid-2.1.0.tgz#2f5ed7537e87e8fddd344710a610be501b3d2da6" - integrity sha512-cSakhxbUsaIuqjfvvcUuvl/Fl342J65xgLLYrYxSSr9qmJ/EJK+S8crS6mIlQd/a7i+Pe4D0MgSrtZPLze+aCw== +hyperid@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/hyperid/-/hyperid-2.3.1.tgz#70cc2c917b6367c9f7307718be243bc28b258353" + integrity sha512-mIbI7Ymn6MCdODaW1/6wdf5lvvXzmPsARN4zTLakMmcziBOuP4PxCBJvHF6kbAIHX6H4vAELx/pDmt0j6Th5RQ== dependencies: - uuid "^3.4.0" + uuid "^8.3.2" uuid-parse "^1.1.0" hyphenate-style-name@^1.0.3: @@ -7811,14 +7780,14 @@ internal-ip@^4.3.0: default-gateway "^4.2.0" ipaddr.js "^1.9.0" -internal-slot@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.2.tgz#9c2e9fb3cd8e5e4256c6f45fe310067fcfa378a3" - integrity sha512-2cQNfwhAfJIkU4KZPkDI+Gj5yNNnbqi40W9Gge6dfnk4TocEVm00B3bdiL+JINrbGJil2TeHvM4rETGzk/f/0g== +internal-slot@^1.0.2, internal-slot@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c" + integrity sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA== dependencies: - es-abstract "^1.17.0-next.1" + get-intrinsic "^1.1.0" has "^1.0.3" - side-channel "^1.0.2" + side-channel "^1.0.4" interpret@1.2.0: version "1.2.0" @@ -7912,6 +7881,13 @@ is-arrayish@^0.2.1: resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= +is-bigint@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" + integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg== + dependencies: + has-bigints "^1.0.1" + is-binary-path@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" @@ -7926,20 +7902,23 @@ is-binary-path@~2.1.0: dependencies: binary-extensions "^2.0.0" -is-boolean-object@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.0.1.tgz#10edc0900dd127697a92f6f9807c7617d68ac48e" - integrity sha512-TqZuVwa/sppcrhUCAYkGBk7w0yxfQQnxq28fjkO53tnK9FQXmdwz2JS5+GjsWQ6RByES1K40nI+yDic5c9/aAQ== +is-boolean-object@^1.0.1, is-boolean-object@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" + integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" is-buffer@^1.1.0, is-buffer@^1.1.4, is-buffer@^1.1.5: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== -is-callable@^1.1.4, is-callable@^1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.5.tgz#f7e46b596890456db74e7f6e976cb3273d06faab" - integrity sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q== +is-callable@^1.1.4, is-callable@^1.1.5, is-callable@^1.2.3: + version "1.2.4" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.4.tgz#47301d58dd0259407865547853df6d61fe471945" + integrity sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w== is-ci@^3.0.0: version "3.0.0" @@ -8075,6 +8054,11 @@ is-negated-glob@^1.0.0: resolved "https://registry.yarnpkg.com/is-negated-glob/-/is-negated-glob-1.0.0.tgz#6910bca5da8c95e784b5751b976cf5a10fee36d2" integrity sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI= +is-negative-zero@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.1.tgz#3de746c18dda2319241a53675908d8f766f11c24" + integrity sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w== + is-number-object@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.4.tgz#36ac95e741cf18b283fc1ddf5e83da798e3ec197" @@ -8138,12 +8122,13 @@ is-promise@^2.1: resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.2.2.tgz#39ab959ccbf9a774cf079f7b40c7a26f763135f1" integrity sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ== -is-regex@^1.0.4, is-regex@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.5.tgz#39d589a358bf18967f726967120b8fc1aed74eae" - integrity sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ== +is-regex@^1.0.4, is-regex@^1.0.5, is-regex@^1.1.3: + version "1.1.4" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" + integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== dependencies: - has "^1.0.3" + call-bind "^1.0.2" + has-tostringtag "^1.0.0" is-relative@^1.0.0: version "1.0.0" @@ -8162,22 +8147,24 @@ is-stream@^2.0.0: resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3" integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw== -is-string@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.5.tgz#40493ed198ef3ff477b8c7f92f644ec82a5cd3a6" - integrity sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ== +is-string@^1.0.5, is-string@^1.0.6: + version "1.0.7" + resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" + integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== + dependencies: + has-tostringtag "^1.0.0" is-subset@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/is-subset/-/is-subset-0.1.1.tgz#8a59117d932de1de00f245fcdd39ce43f1e939a6" integrity sha1-ilkRfZMt4d4A8kX83TnOQ/HpOaY= -is-symbol@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.3.tgz#38e1014b9e6329be0de9d24a414fd7441ec61937" - integrity sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ== +is-symbol@^1.0.2, is-symbol@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" + integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== dependencies: - has-symbols "^1.0.1" + has-symbols "^1.0.2" is-typedarray@^1.0.0, is-typedarray@~1.0.0: version "1.0.0" @@ -8828,6 +8815,13 @@ jest-watcher@^27.0.2: jest-util "^27.0.2" string-length "^4.0.1" +jest-websocket-mock@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/jest-websocket-mock/-/jest-websocket-mock-2.2.1.tgz#db4fc63733c9fc549c1fd0f79e6db8b3f947af1d" + integrity sha512-fhsGLXrPfs06PhHoxqOSA9yZ6Rb4qYrf4Wcm7/nfRzjlrf1gIeuhYUkzMRjjE0TMQ37SwkmeLanwrZY4ZaNp8g== + dependencies: + jest-diff "^27.0.2" + jest-worker@^27.0.2: version "27.0.2" resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.0.2.tgz#4ebeb56cef48b3e7514552f80d0d80c0129f0b05" @@ -9388,11 +9382,6 @@ locate-path@^5.0.0: dependencies: p-locate "^4.1.0" -lodash-es@^4.17.15: - version "4.17.15" - resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.15.tgz#21bd96839354412f23d7a10340e5eac6ee455d78" - integrity sha512-rlrc3yU3+JNOpZ9zj5pQtxnx2THmvRykwL4Xlxoa8I9lHBlVbbyPhgyPMioxVZ4NqyxaVVtaJnzsyOidQIhyyQ== - lodash.clonedeep@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" @@ -9910,6 +9899,13 @@ mocha@^4.1.0: mkdirp "0.5.1" supports-color "4.4.0" +mock-socket@^9.0.3: + version "9.0.3" + resolved "https://registry.yarnpkg.com/mock-socket/-/mock-socket-9.0.3.tgz#4bc6d2aea33191e4fed5ec71f039e2bbeb95e414" + integrity sha512-SxIiD2yE/By79p3cNAAXyLQWTvEFNEzcAO7PH+DzRqKSFaplAPFjiQLmw8ofmpCsZf+Rhfn2/xCJagpdGmYdTw== + dependencies: + url-parse "^1.4.4" + module-deps@^4.0.8: version "4.1.1" resolved "https://registry.yarnpkg.com/module-deps/-/module-deps-4.1.1.tgz#23215833f1da13fd606ccb8087b44852dcb821fd" @@ -10314,18 +10310,18 @@ object-copy@^0.1.0: define-property "^0.2.5" kind-of "^3.0.3" -object-inspect@^1.7.0, object-inspect@^1.9.0: - version "1.10.3" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.10.3.tgz#c2aa7d2d09f50c99375704f7a0adf24c5782d369" - integrity sha512-e5mCJlSH7poANfC8z8S9s9S2IN5/4Zb3aZ33f5s8YqoazCFzNLloLU8r5VCG+G7WoqLvAAZoVMcy3tp/3X0Plw== +object-inspect@^1.11.0, object-inspect@^1.7.0, object-inspect@^1.9.0: + version "1.11.0" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.11.0.tgz#9dceb146cedd4148a0d9e51ab88d34cf509922b1" + integrity sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg== -object-is@^1.0.1, object-is@^1.0.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.2.tgz#c5d2e87ff9e119f78b7a088441519e2eec1573b6" - integrity sha512-5lHCz+0uufF6wZ7CRFWJN3hp8Jqblpgve06U5CMQ3f//6iDjPr2PEo9MWCjEssDsa+UZEL4PkFpr+BMop6aKzQ== +object-is@^1.0.1, object-is@^1.0.2, object-is@^1.1.2: + version "1.1.5" + resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac" + integrity sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw== dependencies: + call-bind "^1.0.2" define-properties "^1.1.3" - es-abstract "^1.17.5" object-keys@^1.0.12, object-keys@^1.1.1: version "1.1.1" @@ -10339,7 +10335,7 @@ object-visit@^1.0.0: dependencies: isobject "^3.0.0" -object.assign@^4.0.4, object.assign@^4.1.0, object.assign@^4.1.1: +object.assign@^4.0.4, object.assign@^4.1.0, object.assign@^4.1.1, object.assign@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940" integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ== @@ -10359,7 +10355,7 @@ object.defaults@^1.0.0, object.defaults@^1.1.0: for-own "^1.0.0" isobject "^3.0.0" -object.entries@^1.1.0, object.entries@^1.1.1, object.entries@^1.1.2: +object.entries@^1.1.1, object.entries@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.2.tgz#bc73f00acb6b6bb16c203434b10f9a7e797d3add" integrity sha512-BQdB9qKmb/HyNdMNWVr7O3+z5MUIx3aiegEIJqjMBbBf0YT9RRxTJSim4mzFqtyr7PDAHigq0N9dO0m0tRakQA== @@ -10368,14 +10364,14 @@ object.entries@^1.1.0, object.entries@^1.1.1, object.entries@^1.1.2: es-abstract "^1.17.5" has "^1.0.3" -object.fromentries@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.2.tgz#4a09c9b9bb3843dd0f89acdb517a794d4f355ac9" - integrity sha512-r3ZiBH7MQppDJVLx6fhD618GKNG40CZYH9wgwdhKxBDDbQgjeWGGd4AtkZad84d291YxvWe7bJGuE65Anh0dxQ== +object.fromentries@^2.0.0, object.fromentries@^2.0.2: + version "2.0.4" + resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.4.tgz#26e1ba5c4571c5c6f0890cef4473066456a120b8" + integrity sha512-EsFBshs5RUUpQEY1D4q/m59kMfz4YJvxuNCJcv/jWwOJr34EaVnG11ZrZa0UHB3wnzV1wx8m58T4hQL8IuNXlQ== dependencies: + call-bind "^1.0.2" define-properties "^1.1.3" - es-abstract "^1.17.0-next.1" - function-bind "^1.1.1" + es-abstract "^1.18.0-next.2" has "^1.0.3" object.getownpropertydescriptors@^2.0.3, object.getownpropertydescriptors@^2.1.0: @@ -11212,13 +11208,6 @@ promise@^7.1.1: dependencies: asap "~2.0.3" -promise@^8.0.3: - version "8.1.0" - resolved "https://registry.yarnpkg.com/promise/-/promise-8.1.0.tgz#697c25c3dfe7435dd79fcd58c38a135888eaf05e" - integrity sha512-W04AqnILOL/sPRXziNicCjSNRruLAuIHEOVBazepu0545DDNGYHz7ar9ZgZ1fMU8/MA4mVxp5rkBWRi6OXIy3Q== - dependencies: - asap "~2.0.6" - prompts@^2.0.1: version "2.3.2" resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.3.2.tgz#480572d89ecf39566d2bd3fe2c9fccb7c4c0b068" @@ -11227,15 +11216,6 @@ prompts@^2.0.1: kleur "^3.0.3" sisteransi "^1.0.4" -prop-types-exact@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/prop-types-exact/-/prop-types-exact-1.2.0.tgz#825d6be46094663848237e3925a98c6e944e9869" - integrity sha512-K+Tk3Kd9V0odiXFP9fwDHUYRyvK3Nun3GVyPapSIs5OBkITAm15W0CPFD/YKTkMUAbc0b9CUwRQp2ybiBIq+eA== - dependencies: - has "^1.0.3" - object.assign "^4.1.0" - reflect.ownkeys "^0.2.0" - prop-types-extra@^1.0.1: version "1.1.1" resolved "https://registry.yarnpkg.com/prop-types-extra/-/prop-types-extra-1.1.1.tgz#58c3b74cbfbb95d304625975aa2f0848329a010b" @@ -11244,7 +11224,7 @@ prop-types-extra@^1.0.1: react-is "^16.3.2" warning "^4.0.0" -prop-types@15.x, prop-types@^15.5.10, prop-types@^15.5.7, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2: +prop-types@15.x, prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.0, prop-types@^15.7.2: version "15.7.2" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== @@ -11581,18 +11561,6 @@ rc-util@^4.0.4, rc-util@^4.15.3, rc-util@^4.4.0: react-lifecycles-compat "^3.0.4" shallowequal "^1.1.0" -react-app-polyfill@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/react-app-polyfill/-/react-app-polyfill-1.0.6.tgz#890f8d7f2842ce6073f030b117de9130a5f385f0" - integrity sha512-OfBnObtnGgLGfweORmdZbyEz+3dgVePQBb3zipiaDsMHV1NpWm0rDFYIVXFV/AK+x4VIIfWHhrdMIeoTLyRr2g== - dependencies: - core-js "^3.5.0" - object-assign "^4.1.1" - promise "^8.0.3" - raf "^3.4.1" - regenerator-runtime "^0.13.3" - whatwg-fetch "^3.0.0" - react-base16-styling@^0.5.1: version "0.5.3" resolved "https://registry.yarnpkg.com/react-base16-styling/-/react-base16-styling-0.5.3.tgz#3858f24e9c4dd8cbd3f702f3f74d581ca2917269" @@ -11637,27 +11605,26 @@ react-docgen@^2.20.1: node-dir "^0.1.10" recast "^0.12.6" -react-dom@^16.14.0: - version "16.14.0" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.14.0.tgz#7ad838ec29a777fb3c75c3a190f661cf92ab8b89" - integrity sha512-1gCeQXDLoIqMgqD3IO2Ah9bnf0w9kzhwN5q4FGnHZ67hBm9yePzB5JJAIQCc8x3pFnNlwFq4RidZggNAAkzWWw== +react-dom@^17.0.2: + version "17.0.2" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.2.tgz#ecffb6845e3ad8dbfcdc498f0d0a939736502c23" + integrity sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" - prop-types "^15.6.2" - scheduler "^0.19.1" + scheduler "^0.20.2" react-emojione@^5.0.0: version "5.0.1" resolved "https://registry.yarnpkg.com/react-emojione/-/react-emojione-5.0.1.tgz#faa4ccdad4bf24e2f5a1a96d9b44c2e902d2bc79" integrity sha512-sjI6k8uQ14rWENYoAb+2BFQGLBt/cpLDJJNhnZvdFJytAJijhv+JmbmyyrfQPdyID0Cs4N8XFqnek0xq6POwGA== -react-is@^16.12.0, react-is@^16.13.0, react-is@^16.13.1, react-is@^16.3.2, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.4, react-is@^16.8.6, react-is@^16.9.0: +react-is@^16.12.0, react-is@^16.13.0, react-is@^16.13.1, react-is@^16.3.2, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.4: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== -"react-is@^16.8.0 || ^17.0.0", react-is@^17.0.1, react-is@^17.0.2: +"react-is@^16.12.0 || ^17.0.0", "react-is@^16.8.0 || ^17.0.0", react-is@^17.0.1, react-is@^17.0.2: version "17.0.2" resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== @@ -11719,17 +11686,6 @@ react-redux@^7.1.1: prop-types "^15.7.2" react-is "^16.13.1" -react-resize-detector@^4.2.1: - version "4.2.3" - resolved "https://registry.yarnpkg.com/react-resize-detector/-/react-resize-detector-4.2.3.tgz#7df258668a30bdfd88e655bbdb27db7fd7b23127" - integrity sha512-4AeS6lxdz2KOgDZaOVt1duoDHrbYwSrUX32KeM9j6t9ISyRphoJbTRCMS1aPFxZHFqcCGLT1gMl3lEcSWZNW0A== - dependencies: - lodash "^4.17.15" - lodash-es "^4.17.15" - prop-types "^15.7.2" - raf-schd "^4.0.2" - resize-observer-polyfill "^1.5.1" - react-router-dom@^4.1.1: version "4.3.1" resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-4.3.1.tgz#4c2619fc24c4fa87c9fd18f4fb4a43fe63fbd5c6" @@ -11774,14 +11730,13 @@ react-router@^4.3.1: prop-types "^15.6.1" warning "^4.0.1" -react-sortable-hoc@^1.11.0: - version "1.11.0" - resolved "https://registry.yarnpkg.com/react-sortable-hoc/-/react-sortable-hoc-1.11.0.tgz#fe4022362bbafc4b836f5104b9676608a40a278f" - integrity sha512-v1CDCvdfoR3zLGNp6qsBa4J1BWMEVH25+UKxF/RvQRh+mrB+emqtVHMgZ+WreUiKJoEaiwYoScaueIKhMVBHUg== +react-shallow-renderer@^16.13.1: + version "16.14.1" + resolved "https://registry.yarnpkg.com/react-shallow-renderer/-/react-shallow-renderer-16.14.1.tgz#bf0d02df8a519a558fd9b8215442efa5c840e124" + integrity sha512-rkIMcQi01/+kxiTE9D3fdS959U1g7gs+/rborw++42m1O9FAQiNI/UNRZExVUoAOprn4umcXf+pFRou8i4zuBg== dependencies: - "@babel/runtime" "^7.2.0" - invariant "^2.2.4" - prop-types "^15.5.7" + object-assign "^4.1.1" + react-is "^16.12.0 || ^17.0.0" react-svg-core@^3.0.3: version "3.0.3" @@ -11804,15 +11759,15 @@ react-svg-loader@^3.0.3: loader-utils "^1.2.3" react-svg-core "^3.0.3" -react-test-renderer@^16.0.0-0, react-test-renderer@^16.8.3: - version "16.13.1" - resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.13.1.tgz#de25ea358d9012606de51e012d9742e7f0deabc1" - integrity sha512-Sn2VRyOK2YJJldOqoh8Tn/lWQ+ZiKhyZTPtaO0Q6yNj+QDbmRkVFap6pZPy3YQk8DScRDfyqm/KxKYP9gCMRiQ== +react-test-renderer@^17.0.0, react-test-renderer@^17.0.2: + version "17.0.2" + resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-17.0.2.tgz#4cd4ae5ef1ad5670fc0ef776e8cc7e1231d9866c" + integrity sha512-yaQ9cB89c17PUb0x6UfWRs7kQCorVdHlutU1boVPEsB8IDZH6n9tHxMacc3y0JoXOJUsZb/t/Mb8FUWMKaM7iQ== dependencies: object-assign "^4.1.1" - prop-types "^15.6.2" - react-is "^16.8.6" - scheduler "^0.19.1" + react-is "^17.0.2" + react-shallow-renderer "^16.13.1" + scheduler "^0.20.2" react-transition-group@^2.2.1, react-transition-group@^2.4.0: version "2.9.0" @@ -11834,13 +11789,6 @@ react-transition-group@^4.0.0, react-transition-group@^4.4.0: loose-envify "^1.4.0" prop-types "^15.6.2" -react-useportal@^1.0.13: - version "1.0.13" - resolved "https://registry.yarnpkg.com/react-useportal/-/react-useportal-1.0.13.tgz#abfc29f8128756cd7382bff7c81a4f446b792199" - integrity sha512-83KpNTXUIHnRVTLeMberIblCtssvRSKCPnG/xT9NW60gDYfU13pQBNQKCVUF8MBK+7LnCQ/ZrOuXl8Mp+iXdXA== - dependencies: - use-ssr "^1.0.19" - react-virtualized@^9.19.1: version "9.21.2" resolved "https://registry.yarnpkg.com/react-virtualized/-/react-virtualized-9.21.2.tgz#02e6df65c1e020c8dbf574ec4ce971652afca84e" @@ -11853,14 +11801,13 @@ react-virtualized@^9.19.1: prop-types "^15.6.0" react-lifecycles-compat "^3.0.4" -react-virtuoso@^1.8.6: - version "1.9.1" - resolved "https://registry.yarnpkg.com/react-virtuoso/-/react-virtuoso-1.9.1.tgz#e59b9b05e35152e0797dcd66b9aca457a2023407" - integrity sha512-X0RPoFTVtayTEcBjkT1dY4MKBcuBojGb8jYz7IK0o40J/plnLDk5cllQfopEWczLDSMRXKamUAAurXz4UXjXfw== +react-virtuoso@^1.9.3: + version "1.11.1" + resolved "https://registry.yarnpkg.com/react-virtuoso/-/react-virtuoso-1.11.1.tgz#350dc88866b3f42cb396bf8f40b90efc6daaadde" + integrity sha512-NH8eLLmoowdq0x7/AEfXxOY9OY4PDpLuPPmCc8F2IoBQLvIcMait3A2TnR0fT9UT+gl8n7GHoORzeGqF5Ka0MA== dependencies: "@virtuoso.dev/react-urx" "^0.2.5" "@virtuoso.dev/urx" "^0.2.5" - react-app-polyfill "^1.0.6" resize-observer-polyfill "^1.5.1" react-widgets-moment@^4.0.4: @@ -11884,14 +11831,13 @@ react-widgets@^4.1.1: uncontrollable "^5.0.0" warning "^3.0.0" -react@^16.14.0: - version "16.14.0" - resolved "https://registry.yarnpkg.com/react/-/react-16.14.0.tgz#94d776ddd0aaa37da3eda8fc5b6b18a4c9a3114d" - integrity sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g== +react@^17.0.2: + version "17.0.2" + resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037" + integrity sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" - prop-types "^15.6.2" read-only-stream@^2.0.0: version "2.0.0" @@ -12048,11 +11994,6 @@ redux@^4.0.4, redux@^4.0.5: loose-envify "^1.4.0" symbol-observable "^1.2.0" -reflect.ownkeys@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/reflect.ownkeys/-/reflect.ownkeys-0.2.0.tgz#749aceec7f3fdf8b63f927a04809e90c5c0b3460" - integrity sha1-dJrO7H8/34tj+SegSAnpDFwLNGA= - regenerate-unicode-properties@^8.2.0: version "8.2.0" resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz#e5de7111d655e7ba60c057dbe9ff37c87e65cdec" @@ -12070,7 +12011,7 @@ regenerator-runtime@^0.11.0: resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== -regenerator-runtime@^0.13.3, regenerator-runtime@^0.13.4: +regenerator-runtime@^0.13.4: version "0.13.7" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz#cac2dacc8a1ea675feaabaeb8ae833898ae46f55" integrity sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew== @@ -12531,10 +12472,10 @@ saxes@^5.0.1: dependencies: xmlchars "^2.2.0" -scheduler@^0.19.1: - version "0.19.1" - resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.19.1.tgz#4f3e2ed2c1a7d65681f4c854fa8c5a1ccb40f196" - integrity sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA== +scheduler@^0.20.2: + version "0.20.2" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.20.2.tgz#4baee39436e34aa93b4874bddcbf0fe8b8b50e91" + integrity sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" @@ -12593,7 +12534,7 @@ semver-greatest-satisfied-range@^1.1.0: dependencies: sver-compat "^1.5.0" -"semver@2 || 3 || 4 || 5", semver@^5.4.1, semver@^5.5.0, semver@^5.6.0, semver@^5.7.0, semver@^5.7.1: +"semver@2 || 3 || 4 || 5", semver@^5.4.1, semver@^5.5.0, semver@^5.6.0, semver@^5.7.0: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== @@ -12853,11 +12794,6 @@ smart-buffer@^4.1.0: resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.1.0.tgz#91605c25d91652f4661ea69ccf45f1b331ca21ba" integrity sha512-iVICrxOzCynf/SNaBQCw34eM9jROU/s5rzIhpOvzhzuYHfJR/DhZfDkXiZSgKXfgv26HT3Yni3AV/DGw0cGnnw== -smoothscroll-polyfill@^0.4.4: - version "0.4.4" - resolved "https://registry.yarnpkg.com/smoothscroll-polyfill/-/smoothscroll-polyfill-0.4.4.tgz#3a259131dc6930e6ca80003e1cb03b603b69abf8" - integrity sha512-TK5ZA9U5RqCwMpfoMq/l1mrH0JAR7y7KRvOBx0n2869aLxch+gT9GhN3yUfjiw+d/DiF1mKo14+hd62JyMmoBg== - snapdragon-node@^2.0.1: version "2.1.1" resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" @@ -13275,39 +13211,21 @@ string.prototype.trim@^1.2.1: es-abstract "^1.17.0-next.1" function-bind "^1.1.1" -string.prototype.trimend@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz#85812a6b847ac002270f5808146064c995fb6913" - integrity sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g== - dependencies: - define-properties "^1.1.3" - es-abstract "^1.17.5" - -string.prototype.trimleft@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.2.tgz#4408aa2e5d6ddd0c9a80739b087fbc067c03b3cc" - integrity sha512-gCA0tza1JBvqr3bfAIFJGqfdRTyPae82+KTnm3coDXkZN9wnuW3HjGgN386D7hfv5CHQYCI022/rJPVlqXyHSw== - dependencies: - define-properties "^1.1.3" - es-abstract "^1.17.5" - string.prototype.trimstart "^1.0.0" - -string.prototype.trimright@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.2.tgz#c76f1cef30f21bbad8afeb8db1511496cfb0f2a3" - integrity sha512-ZNRQ7sY3KroTaYjRS6EbNiiHrOkjihL9aQE/8gfQ4DtAC/aEBRHFJa44OmoWxGGqXuJlfKkZW4WcXErGr+9ZFg== +string.prototype.trimend@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz#e75ae90c2942c63504686c18b287b4a0b1a45f80" + integrity sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A== dependencies: + call-bind "^1.0.2" define-properties "^1.1.3" - es-abstract "^1.17.5" - string.prototype.trimend "^1.0.0" -string.prototype.trimstart@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz#14af6d9f34b053f7cfc89b72f8f2ee14b9039a54" - integrity sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw== +string.prototype.trimstart@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz#b36399af4ab2999b4c9c648bd7a3fb2bb26feeed" + integrity sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw== dependencies: + call-bind "^1.0.2" define-properties "^1.1.3" - es-abstract "^1.17.5" string_decoder@^1.0.0, string_decoder@^1.1.1: version "1.3.0" @@ -14018,10 +13936,10 @@ typescript-plugin-css-modules@^1.0.5: reserved-words "^0.1.2" sass "^1.22.4" -typescript@^4.2.3: - version "4.2.4" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.2.4.tgz#8610b59747de028fda898a8aef0e103f156d0961" - integrity sha512-V+evlYHZnQkaz8TRBuxTA92yZBPotr5H+WhQ7bD3hZUndx5tGOa1fuCgeSjxAzM1RiN5IzvadIXTVefuuwZCRg== +typescript@^4.3.5: + version "4.4.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.4.2.tgz#6d618640d430e3569a1dfb44f7d7e600ced3ee86" + integrity sha512-gzP+t5W4hdy4c+68bfcv0t400HVJMMd2+H9B7gae1nQlBzCqvrXX+6GL/b3GAgyTH966pzrZ70/fRjwAtZksSQ== ua-parser-js@^0.7.18: version "0.7.21" @@ -14040,6 +13958,16 @@ umd@^3.0.0: resolved "https://registry.yarnpkg.com/umd/-/umd-3.0.3.tgz#aa9fe653c42b9097678489c01000acb69f0b26cf" integrity sha512-4IcGSufhFshvLNcMCV80UnQVlZ5pMOC8mvNPForqwA4+lzYQuetTESLDQkeLmihq8bRcnpbQa48Wb8Lh16/xow== +unbox-primitive@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.1.tgz#085e215625ec3162574dc8859abee78a59b14471" + integrity sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw== + dependencies: + function-bind "^1.1.1" + has-bigints "^1.0.1" + has-symbols "^1.0.2" + which-boxed-primitive "^1.0.2" + unc-path-regex@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/unc-path-regex/-/unc-path-regex-0.1.2.tgz#e73dd3d7b0d7c5ed86fbac6b0ae7d8c6a69d50fa" @@ -14258,10 +14186,10 @@ url-loader@^1.1.2: mime "^2.0.3" schema-utils "^1.0.0" -url-parse@^1.2.0, url-parse@^1.4.3: - version "1.4.7" - resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.4.7.tgz#a8a83535e8c00a316e403a5db4ac1b9b853ae278" - integrity sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg== +url-parse@^1.2.0, url-parse@^1.4.3, url-parse@^1.4.4: + version "1.5.3" + resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.3.tgz#71c1303d38fb6639ade183c2992c8cc0686df862" + integrity sha512-IIORyIQD9rvj0A4CLWsHkBBJuNqWpFQe224b6j9t/ABmquIS0qDU2pY6kl6AuOrL5OkCXHMCFNe1jBcuAggjvQ== dependencies: querystringify "^2.1.1" requires-port "^1.0.0" @@ -14279,11 +14207,6 @@ use-memo-one@^1.1.1: resolved "https://registry.yarnpkg.com/use-memo-one/-/use-memo-one-1.1.1.tgz#39e6f08fe27e422a7d7b234b5f9056af313bd22c" integrity sha512-oFfsyun+bP7RX8X2AskHNTxu+R3QdE/RC5IefMbqptmACAA/gfol1KDD5KRzPsGMa62sWxGZw+Ui43u6x4ddoQ== -use-ssr@^1.0.19: - version "1.0.23" - resolved "https://registry.yarnpkg.com/use-ssr/-/use-ssr-1.0.23.tgz#3bde1e10cd01b3b61ab6386d7cddb72e74828bf8" - integrity sha512-5bvlssgROgPgIrnILJe2mJch4e2Id0/bVm1SQzqvPvEAXmlsinCCVHWK3a2iHcPat7PkdJHBo0gmSmODIz6tNA== - use@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" @@ -14340,10 +14263,10 @@ uuid@^3.3.2, uuid@^3.4.0: resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== -uuid@^8.3.0: - version "8.3.1" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.1.tgz#2ba2e6ca000da60fce5a196954ab241131e05a31" - integrity sha512-FOmRr+FmWEIG8uhZv6C2bTgEVXsHk08kE7mPlrBbEe+c3r9pjceVPgupIfNIhc4yx55H69OXANrUaSuu9eInKg== +uuid@^8.3.0, uuid@^8.3.2: + version "8.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" + integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== v8-compile-cache@2.0.3: version "2.0.3" @@ -14583,7 +14506,7 @@ webidl-conversions@^6.1.0: resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-6.1.0.tgz#9111b4d7ea80acd40f5270d666621afa78b69514" integrity sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w== -webpack-bundle-analyzer@^4.4.0: +webpack-bundle-analyzer@^4.4.2: version "4.4.2" resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.4.2.tgz#39898cf6200178240910d629705f0f3493f7d666" integrity sha512-PIagMYhlEzFfhMYOzs5gFT55DkUdkyrJi/SxJp8EF3YMWhS+T9vvs2EoTetpk5qb6VsCq02eXTlRDOydRhDFAQ== @@ -14738,7 +14661,7 @@ whatwg-encoding@^1.0.5: dependencies: iconv-lite "0.4.24" -whatwg-fetch@>=0.10.0, whatwg-fetch@^3.0.0: +whatwg-fetch@>=0.10.0: version "3.6.2" resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz#dced24f37f2624ed0281725d51d0e2e3fe677f8c" integrity sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA== @@ -14757,6 +14680,17 @@ whatwg-url@^8.0.0, whatwg-url@^8.5.0: tr46 "^2.1.0" webidl-conversions "^6.1.0" +which-boxed-primitive@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" + integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== + dependencies: + is-bigint "^1.0.1" + is-boolean-object "^1.1.0" + is-number-object "^1.0.4" + is-string "^1.0.5" + is-symbol "^1.0.3" + which-module@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" @@ -14872,6 +14806,11 @@ ws@^7.3.1, ws@^7.4.5: resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.5.tgz#a484dd851e9beb6fdb420027e3885e8ce48986c1" integrity sha512-xzyu3hFvomRfXKH8vOFMU3OguG6oOvhXMo3xsGy3xWExqaM2dxBbVxuD99O7m3ZUFMvvscsZDqxfgMaRr/Nr1g== +ws@^8.2.0: + version "8.2.1" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.2.1.tgz#bdd92b3c56fdb47d2379b5ae534281922cc5bd12" + integrity sha512-XkgWpJU3sHU7gX8f13NqTn6KQ85bd1WU7noBHTT8fSohx7OS1TPY8k+cyRPCzFkia7C4mM229yeHr1qK9sM4JQ== + x-is-string@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/x-is-string/-/x-is-string-0.1.0.tgz#474b50865af3a49a9c4657f05acd145458f77d82" @@ -14980,14 +14919,6 @@ yargs-parser@^13.1.0, yargs-parser@^13.1.2: camelcase "^5.0.0" decamelize "^1.2.0" -yargs-parser@^15.0.1: - version "15.0.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-15.0.1.tgz#54786af40b820dcb2fb8025b11b4d659d76323b3" - integrity sha512-0OAMV2mAZQrs3FkNpDQcBk1x5HXb8X4twADss4S0Iuk+2dGnLOE/fRHrsYm542GduMveyA77OF4wrNJuanRCWw== - dependencies: - camelcase "^5.0.0" - decamelize "^1.2.0" - yargs-parser@^20.2.2: version "20.2.7" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.7.tgz#61df85c113edfb5a7a4e36eb8aa60ef423cbc90a" @@ -15026,24 +14957,7 @@ yargs@^13.3.2: y18n "^4.0.0" yargs-parser "^13.1.2" -yargs@^14.0.0: - version "14.2.3" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-14.2.3.tgz#1a1c3edced1afb2a2fea33604bc6d1d8d688a414" - integrity sha512-ZbotRWhF+lkjijC/VhmOT9wSgyBQ7+zr13+YLkhfsSiTriYsMzkTUFP18pFhWwBeMa5gUc1MzbhrO6/VB7c9Xg== - dependencies: - cliui "^5.0.0" - decamelize "^1.2.0" - find-up "^3.0.0" - get-caller-file "^2.0.1" - require-directory "^2.1.1" - require-main-filename "^2.0.0" - set-blocking "^2.0.0" - string-width "^3.0.0" - which-module "^2.0.0" - y18n "^4.0.0" - yargs-parser "^15.0.1" - -yargs@^16.0.0, yargs@^16.0.3: +yargs@^16.0.3: version "16.2.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== @@ -15056,6 +14970,19 @@ yargs@^16.0.0, yargs@^16.0.3: y18n "^5.0.5" yargs-parser "^20.2.2" +yargs@^17.1.1: + version "17.1.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.1.1.tgz#c2a8091564bdb196f7c0a67c1d12e5b85b8067ba" + integrity sha512-c2k48R0PwKIqKhPMWjeiF6y2xY/gPMUlro0sgxqXpbOIohWiLNXWslsootttv7E1e73QPAMQSg5FeySbVcpsPQ== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.0" + y18n "^5.0.5" + yargs-parser "^20.2.2" + yargs@^7.1.0: version "7.1.1" resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.1.tgz#67f0ef52e228d4ee0d6311acede8850f53464df6"