Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
"*.html.tmpl": "html",
".babelrc": "jsonc"
},
"editor.rulers": [100],
"editor.rulers": [
100
],
"editor.tabSize": 2,
"search.exclude": {
"**/node_modules": true,
Expand All @@ -25,8 +27,8 @@
"[javascript]": {
"editor.formatOnSave": true
},
// Allow formatting for other languages
// Allow formatting for other languages
"editor.formatOnSave": true,
// Enable ESLint (with Prettier plugin) to format code on save
"eslint.autoFixOnSave": false
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ export default new Enum([
...Object.keys(baseActionTypes),
'setAutoLog',
'setLogOnRinging',
'addTransferredCall'
], 'callLogger');
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { combineReducers } from 'redux';

const DEFAULT_OPACITY = 20;

export function getLogOnRingingReducer(types) {
return (state = true, { type, logOnRinging }) => {
if (type === types.setLogOnRinging) return !!logOnRinging;
Expand All @@ -14,10 +16,23 @@ export function getAutoLogReducer(types, initialState = true) {
};
}

export function getTransferredCallsReducer(types, opacity = DEFAULT_OPACITY) {
return (state = [], { type, sessionId }) => {
if (type === types.addTransferredCall) {
return [
...(state.slice(state.length >= opacity ? 1 : 0, opacity)),
{ [sessionId]: true }
];
}
return state;
};
}

/* istanbul ignore next */
export default function getDataReducer(types, initialState = {}) {
return combineReducers({
autoLog: getAutoLogReducer(types, initialState.autoLog),
logOnRinging: getLogOnRingingReducer(types),
transferredCallsMap: getTransferredCallsReducer(types)
});
}
Original file line number Diff line number Diff line change
@@ -1,92 +1,137 @@
// import { expect } from 'chai';
// import {
// getAutoLogReducer,
// getLogOnRingingReducer,
// } from './getDataReducer';
// import actionTypes from './actionTypes';
import { expect } from 'chai';
import {
getAutoLogReducer,
getLogOnRingingReducer,
getTransferredCallsReducer
} from './getDataReducer';
import actionTypes from './actionTypes';

// describe('getAutoLogReducer', () => {
// it('should be a function', () => {
// expect(getAutoLogReducer).to.be.a('function');
// });
// it('should return a function', () => {
// expect(getAutoLogReducer(actionTypes)).to.be.a('function');
// });
// describe('autoLogReducer', () => {
// const reducer = getAutoLogReducer(actionTypes);
// it('should have initial state of true', () => {
// expect(reducer(undefined, {})).to.equal(true);
// });
// it('should return true when type === setAutoLog and action.autoLog is true', () => {
// expect(reducer(true, {
// type: actionTypes.setAutoLog,
// autoLog: true,
// })).to.equal(true);
// expect(reducer(false, {
// type: actionTypes.setAutoLog,
// autoLog: true,
// })).to.equal(true);
// });
// it('should return true when type === setAutoLog and action.autoLog is false', () => {
// expect(reducer(true, {
// type: actionTypes.setAutoLog,
// autoLog: false,
// })).to.equal(false);
// expect(reducer(false, {
// type: actionTypes.setAutoLog,
// autoLog: false,
// })).to.equal(false);
// });
// it('should return originalState for other actionTypes', () => {
// const originalState = {};
// expect(reducer(originalState, {
// type: 'foo',
// })).to.equal(originalState);
// });
// });
// });
describe('getAutoLogReducer', () => {
it('should be a function', () => {
expect(getAutoLogReducer).to.be.a('function');
});
it('should return a function', () => {
expect(getAutoLogReducer(actionTypes)).to.be.a('function');
});
describe('autoLogReducer', () => {
const reducer = getAutoLogReducer(actionTypes);
it('should have initial state of true', () => {
expect(reducer(undefined, {})).to.equal(true);
});
it('should return true when type === setAutoLog and action.autoLog is true', () => {
expect(reducer(true, {
type: actionTypes.setAutoLog,
autoLog: true,
})).to.equal(true);
expect(reducer(false, {
type: actionTypes.setAutoLog,
autoLog: true,
})).to.equal(true);
});
it('should return true when type === setAutoLog and action.autoLog is false', () => {
expect(reducer(true, {
type: actionTypes.setAutoLog,
autoLog: false,
})).to.equal(false);
expect(reducer(false, {
type: actionTypes.setAutoLog,
autoLog: false,
})).to.equal(false);
});
it('should return originalState for other actionTypes', () => {
const originalState = {};
expect(reducer(originalState, {
type: 'foo',
})).to.equal(originalState);
});
});
});

// describe('getLogOnRingingReducer', () => {
// it('should be a function', () => {
// expect(getLogOnRingingReducer).to.be.a('function');
// });
// it('should return a function', () => {
// expect(getLogOnRingingReducer(actionTypes)).to.be.a('function');
// });
// describe('logOnRingingReducer', () => {
// const reducer = getLogOnRingingReducer(actionTypes);
// it('should have initial state of true', () => {
// expect(reducer(undefined, {})).to.equal(true);
// });
// it('should return true when type === setLogOnRinging and action.logOnRinging is true',
// () => {
// expect(reducer(true, {
// type: actionTypes.setLogOnRinging,
// logOnRinging: true,
// })).to.equal(true);
// expect(reducer(false, {
// type: actionTypes.setLogOnRinging,
// logOnRinging: true,
// })).to.equal(true);
// },
// );
// it('should return true when type === setLogOnRinging and action.logOnRinging is false',
// () => {
// expect(reducer(true, {
// type: actionTypes.setLogOnRinging,
// logOnRinging: false,
// })).to.equal(false);
// expect(reducer(false, {
// type: actionTypes.setLogOnRinging,
// logOnRinging: false,
// })).to.equal(false);
// },
// );
// it('should return originalState for other actionTypes', () => {
// const originalState = {};
// expect(reducer(originalState, {
// type: 'foo',
// })).to.equal(originalState);
// });
// });
// });
describe('getLogOnRingingReducer', () => {
it('should be a function', () => {
expect(getLogOnRingingReducer).to.be.a('function');
});
it('should return a function', () => {
expect(getLogOnRingingReducer(actionTypes)).to.be.a('function');
});
describe('logOnRingingReducer', () => {
const reducer = getLogOnRingingReducer(actionTypes);
it('should have initial state of true', () => {
expect(reducer(undefined, {})).to.equal(true);
});
it('should return true when type === setLogOnRinging and action.logOnRinging is true',
() => {
expect(reducer(true, {
type: actionTypes.setLogOnRinging,
logOnRinging: true,
})).to.equal(true);
expect(reducer(false, {
type: actionTypes.setLogOnRinging,
logOnRinging: true,
})).to.equal(true);
},
);
it('should return true when type === setLogOnRinging and action.logOnRinging is false',
() => {
expect(reducer(true, {
type: actionTypes.setLogOnRinging,
logOnRinging: false,
})).to.equal(false);
expect(reducer(false, {
type: actionTypes.setLogOnRinging,
logOnRinging: false,
})).to.equal(false);
},
);
it('should return originalState for other actionTypes', () => {
const originalState = {};
expect(reducer(originalState, {
type: 'foo',
})).to.equal(originalState);
});
});
});

describe('getTransferredCallsReducer', () => {
it('should be a function', () => {
expect(getTransferredCallsReducer).to.be.a('function');
});
it('should return a function', () => {
expect(getTransferredCallsReducer(actionTypes)).to.be.a('function');
});
describe('getTransferredCallsReducer', () => {
const opacity = 5;
const reducer = getTransferredCallsReducer(actionTypes, opacity);
it('should have initial state of []', () => {
expect(reducer(undefined, {})).to.deep.equal([]);
});
it('should return original state when actionType is not recognized', () => {
const originalState = [{ 123: true }];
expect(reducer(originalState, { type: 'foo' }))
.to.deep.equal(originalState);
});
it('should add new matcher when actionType is addTransferredCall', () => {
const originalState = [{
123: true
}];
expect(reducer(originalState, {
type: actionTypes.addTransferredCall,
sessionId: '456',
})).to.deep.equal([{ 123: true }, { 456: true }]);
});
it('should remove oldest matcher when actionType is addTransferredCall andsize of temporary matcher exceed the opacity', () => {
const originalState = [];
const opacity = 5;
originalState.push({ 1: true }, { 2: true }, { 3: true }, { 4: true }, { 5: true });
expect(originalState.length).to.equal(opacity);
expect(reducer(originalState, {
type: actionTypes.addTransferredCall,
sessionId: '456',
}).length).to.equal(opacity);
expect(reducer(originalState, {
type: actionTypes.addTransferredCall,
sessionId: '456',
})[opacity - 1]).to.deep.equal({ 456: true });
});
});
});
42 changes: 37 additions & 5 deletions packages/ringcentral-integration/modules/CallLogger/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ import callLoggerTriggerTypes from '../../enums/callLoggerTriggerTypes';
import actionTypes from './actionTypes';
import getDataReducer from './getDataReducer';
import proxify from '../../lib/proxy/proxify';
import { getTokenReducer } from '../Auth/getAuthReducer';
import getter from '../../lib/getter';
import { createSelector } from 'reselect';

/**
* @function
Expand Down Expand Up @@ -74,7 +77,6 @@ export default class CallLogger extends LoggerBase {
key: this._storageKey,
reducer: getDataReducer(this.actionTypes, initialState),
});

this._lastProcessedCalls = null;
this._lastProcessedEndedCalls = null;
this._customMatcherHooks = [];
Expand Down Expand Up @@ -152,7 +154,9 @@ export default class CallLogger extends LoggerBase {
toEntity,
});
}
async _autoLogCall({ call, fromEntity, toEntity, triggerType }) {
async _autoLogCall({
call, fromEntity, toEntity, triggerType
}) {
await this.log({
call: {
...call,
Expand Down Expand Up @@ -262,12 +266,28 @@ export default class CallLogger extends LoggerBase {
const oldCall = oldCalls[oldCallIndex];
oldCalls.splice(oldCallIndex, 1);
if (call.telephonyStatus !== oldCall.telephonyStatus) {
this._onCallUpdated(call, callLoggerTriggerTypes.presenceUpdate);
this._onCallUpdated({
...call,
isTransferredCall: !!this.transferredCallsMap[call.sessionId]
}, callLoggerTriggerTypes.presenceUpdate);
}
if ((call.from && call.from.phoneNumber) !== (oldCall.from && oldCall.from.phoneNumber)) {
this.store.dispatch({
type: this.actionTypes.addTransferredCall,
sessionId: call.sessionId
});
this._onCallUpdated({
...call,
isTransferredCall: true
}, callLoggerTriggerTypes.presenceUpdate);
}
}
});
oldCalls.forEach((call) => {
this._onCallUpdated(call, callLoggerTriggerTypes.presenceUpdate);
this._onCallUpdated({
...call,
isTransferredCall: !!this.transferredCallsMap[call.sessionId]
}, callLoggerTriggerTypes.presenceUpdate);
});
}
if (
Expand All @@ -289,7 +309,10 @@ export default class CallLogger extends LoggerBase {
const callInfo = this._callHistory.calls
.find(item => item.sessionId === call.sessionId);
if (callInfo) {
this._onCallUpdated(callInfo, callLoggerTriggerTypes.callLogSync);
this._onCallUpdated({
...callInfo,
isTransferredCall: !!this.transferredCallsMap[callInfo.sessionId]
}, callLoggerTriggerTypes.callLogSync);
}
}
});
Expand Down Expand Up @@ -325,7 +348,16 @@ export default class CallLogger extends LoggerBase {
}
}

@getter
transferredCallsMap = createSelector(
() => this.transferredCallsArr,
transferredCallsArr => transferredCallsArr.reduce((mapping, matcher) => Object.assign({}, mapping, matcher), {})
)
get logOnRinging() {
return this._storage.getItem(this._storageKey).logOnRinging;
}

get transferredCallsArr() {
return this._storage.getItem(this._storageKey).transferredCallsMap;
}
}
6 changes: 4 additions & 2 deletions packages/ringcentral-integration/modules/CallMonitor/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -413,8 +413,10 @@ export default class CallMonitor extends RcModule {
} else {
const oldCall = oldCalls[oldCallIndex];
oldCalls.splice(oldCallIndex, 1);
if (
call.telephonyStatus !== oldCall.telephonyStatus &&
if ((
call.telephonyStatus !== oldCall.telephonyStatus ||
(oldCall.from && oldCall.from.phoneNumber) !== (call.from && call.from.phoneNumber)
) &&
typeof this._onCallUpdated === 'function'
) {
this._onCallUpdated(call);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export default class DetailedPresence extends Presence {
_subscriptionHandler = (message) => {
if (presenceRegExp.test(message.event) && message.body) {
if (message.body.sequence) {
if (message.body.sequence <= this._lastSequence) {
if (message.body.sequence < this._lastSequence) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think when we remove '=', we need to consider if it has any impact for call secenario.
I think QAs need to do call scenario tests as many as possible.

return;
}
this._lastSequence = message.body.sequence;
Expand Down
Loading