@webex/plugin-meetings 2.19.3 → 2.20.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/constants.js +7 -3
- package/dist/constants.js.map +1 -1
- package/dist/locus-info/index.js +9 -0
- package/dist/locus-info/index.js.map +1 -1
- package/dist/locus-info/selfUtils.js +29 -7
- package/dist/locus-info/selfUtils.js.map +1 -1
- package/dist/meeting/index.js +8 -0
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting-info/meeting-info-v2.js +8 -3
- package/dist/meeting-info/meeting-info-v2.js.map +1 -1
- package/package.json +5 -5
- package/src/constants.ts +4 -0
- package/src/locus-info/index.js +11 -0
- package/src/locus-info/selfUtils.js +13 -0
- package/src/meeting/index.js +14 -0
- package/src/meeting-info/meeting-info-v2.js +8 -4
- package/test/unit/spec/locus-info/index.js +46 -0
- package/test/unit/spec/locus-info/selfUtils.js +40 -0
- package/test/unit/spec/meeting/index.js +20 -10
- package/test/unit/spec/meeting-info/meetinginfov2.js +34 -6
|
@@ -349,8 +349,6 @@ var MeetingInfoV2 = /*#__PURE__*/function () {
|
|
|
349
349
|
body = _context2.sent;
|
|
350
350
|
options = {
|
|
351
351
|
method: _constants.HTTP_VERBS.POST,
|
|
352
|
-
service: 'webex-appapi-service',
|
|
353
|
-
resource: 'meetingInfo',
|
|
354
352
|
body: body
|
|
355
353
|
};
|
|
356
354
|
_context2.next = 14;
|
|
@@ -358,7 +356,14 @@ var MeetingInfoV2 = /*#__PURE__*/function () {
|
|
|
358
356
|
|
|
359
357
|
case 14:
|
|
360
358
|
directURI = _context2.sent;
|
|
361
|
-
|
|
359
|
+
|
|
360
|
+
if (directURI) {
|
|
361
|
+
options.uri = directURI;
|
|
362
|
+
} else {
|
|
363
|
+
options.service = _constants.WBXAPPAPI_SERVICE;
|
|
364
|
+
options.resource = 'meetingInfo';
|
|
365
|
+
}
|
|
366
|
+
|
|
362
367
|
return _context2.abrupt("return", this.webex.request(options).then(function (response) {
|
|
363
368
|
_metrics.default.sendBehavioralMetric(_constants2.default.FETCH_MEETING_INFO_V1_SUCCESS);
|
|
364
369
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["PASSWORD_ERROR_DEFAULT_MESSAGE","CAPTCHA_ERROR_DEFAULT_MESSAGE","ADHOC_MEETING_DEFAULT_ERROR","CAPTCHA_ERROR_REQUIRES_PASSWORD_CODES","MeetingInfoV2PasswordError","wbxAppApiErrorCode","meetingInfo","message","name","sdkMessage","stack","Error","wbxAppApiCode","MeetingInfoV2AdhocMeetingError","MeetingInfoV2CaptchaError","captchaInfo","isPasswordRequired","includes","MeetingInfoV2","webex","destination","type","MeetingInfoUtil","getDestinationType","conversationUrl","meetings","preferredWebexSite","getInvitees","particpants","invitees","forEach","participant","push","email","emailAddress","ciUserUuid","entryUUID","internal","conversation","get","url","includeParticipants","disableTransform","then","body","title","displayName","spaceUrl","keyUrl","encryptionKeyUrl","kroUrl","kmsResourceObjectUrl","participants","items","uri","Metrics","sendBehavioralMetric","BEHAVIORAL_METRICS","ADHOC_MEETING_SUCCESS","request","method","HTTP_VERBS","POST","catch","err","ADHOC_MEETING_FAILURE","reason","code","password","destinationType","_CONVERSATION_URL_","config","experimental","enableAdhocMeetings","createAdhocSpaceMeeting","getRequestBody","options","service","resource","getDirectMeetingInfoURI","directURI","response","FETCH_MEETING_INFO_V1_SUCCESS","statusCode","VERIFY_PASSWORD_ERROR","data","VERIFY_CAPTCHA_ERROR","captchaId","captchaID","verificationImageURL","verificationAudioURL","refreshURL","FETCH_MEETING_INFO_V1_FAILURE"],"sources":["meeting-info-v2.js"],"sourcesContent":["\nimport {HTTP_VERBS, _CONVERSATION_URL_} from '../constants';\nimport Metrics from '../metrics';\nimport BEHAVIORAL_METRICS from '../metrics/constants';\n\nimport MeetingInfoUtil from './utilv2';\n\nconst PASSWORD_ERROR_DEFAULT_MESSAGE = 'Password required. Call fetchMeetingInfo() with password argument';\nconst CAPTCHA_ERROR_DEFAULT_MESSAGE = 'Captcha required. Call fetchMeetingInfo() with captchaInfo argument';\nconst ADHOC_MEETING_DEFAULT_ERROR = 'Failed starting the adhoc meeting, Please contact support team ';\nconst CAPTCHA_ERROR_REQUIRES_PASSWORD_CODES = [423005, 423006];\n\n/**\n * Error to indicate that wbxappapi requires a password\n */\nexport class MeetingInfoV2PasswordError extends Error {\n /**\n *\n * @constructor\n * @param {Number} [wbxAppApiErrorCode]\n * @param {Object} [meetingInfo]\n * @param {String} [message]\n */\n constructor(wbxAppApiErrorCode, meetingInfo, message = PASSWORD_ERROR_DEFAULT_MESSAGE) {\n super(`${message}, code=${wbxAppApiErrorCode}`);\n this.name = 'MeetingInfoV2PasswordError';\n this.sdkMessage = message;\n this.stack = (new Error()).stack;\n this.wbxAppApiCode = wbxAppApiErrorCode;\n this.meetingInfo = meetingInfo;\n }\n}\n\n/**\n * Error generating a adhoc space meeting\n */\nexport class MeetingInfoV2AdhocMeetingError extends Error {\n /**\n *\n * @constructor\n * @param {Number} [wbxAppApiErrorCode]\n * @param {String} [message]\n */\n constructor(wbxAppApiErrorCode, message = ADHOC_MEETING_DEFAULT_ERROR) {\n super(`${message}, code=${wbxAppApiErrorCode}`);\n this.name = 'MeetingInfoV2AdhocMeetingError';\n this.sdkMessage = message;\n this.stack = (new Error()).stack;\n this.wbxAppApiCode = wbxAppApiErrorCode;\n }\n}\n\n\n/**\n * Error to indicate that preferred webex site not present to start adhoc meeting\n */\nexport class MeetingInfoV2CaptchaError extends Error {\n /**\n *\n * @constructor\n * @param {Number} [wbxAppApiErrorCode]\n * @param {Object} [captchaInfo]\n * @param {String} [message]\n */\n constructor(wbxAppApiErrorCode, captchaInfo, message = CAPTCHA_ERROR_DEFAULT_MESSAGE) {\n super(`${message}, code=${wbxAppApiErrorCode}`);\n this.name = 'MeetingInfoV2PasswordError';\n this.sdkMessage = message;\n this.stack = (new Error()).stack;\n this.wbxAppApiCode = wbxAppApiErrorCode;\n this.isPasswordRequired = CAPTCHA_ERROR_REQUIRES_PASSWORD_CODES.includes(wbxAppApiErrorCode);\n this.captchaInfo = captchaInfo;\n }\n}\n\n/**\n * @class MeetingInfo\n */\nexport default class MeetingInfoV2 {\n /**\n *\n * @param {WebexSDK} webex\n */\n constructor(webex) {\n this.webex = webex;\n }\n\n /**\n * converts hydra id into conversation url and persons Id\n * @param {String} destination one of many different types of destinations to look up info for\n * @param {String} [type] to match up with the destination value\n * @returns {Promise} destination and type\n * @public\n * @memberof MeetingInfo\n */\n fetchInfoOptions(destination, type = null) {\n return MeetingInfoUtil.getDestinationType({\n destination,\n type,\n webex: this.webex\n });\n }\n\n /**\n * Creates adhoc space meetings for a space by fetching the conversation infomation\n * @param {String} conversationUrl conversationUrl to start adhoc meeting on\n * @returns {Promise} returns a meeting info object\n * @public\n * @memberof MeetingInfo\n */\n async createAdhocSpaceMeeting(conversationUrl) {\n if (!this.webex.meetings.preferredWebexSite) {\n throw Error('No preferred webex site found');\n }\n const getInvitees = (particpants = []) => {\n const invitees = [];\n\n if (particpants) {\n particpants.forEach((participant) => {\n invitees.push({\n email: participant.emailAddress,\n ciUserUuid: participant.entryUUID\n });\n });\n }\n\n return invitees;\n };\n\n return this.webex.internal.conversation.get(\n {url: conversationUrl},\n {includeParticipants: true, disableTransform: true}\n )\n .then((conversation) => {\n const body = {\n title: conversation.displayName,\n spaceUrl: conversation.url,\n keyUrl: conversation.encryptionKeyUrl,\n kroUrl: conversation.kmsResourceObjectUrl,\n invitees: getInvitees(conversation.participants?.items)\n };\n\n const uri = this.webex.meetings.preferredWebexSite ?\n `https://${this.webex.meetings.preferredWebexSite}/wbxappapi/v2/meetings/spaceInstant` : '';\n\n Metrics.sendBehavioralMetric(\n BEHAVIORAL_METRICS.ADHOC_MEETING_SUCCESS\n );\n\n return this.webex.request({\n method: HTTP_VERBS.POST,\n uri,\n body\n });\n })\n .catch((err) => {\n Metrics.sendBehavioralMetric(\n BEHAVIORAL_METRICS.ADHOC_MEETING_FAILURE,\n {\n reason: err.message,\n stack: err.stack\n }\n );\n throw new MeetingInfoV2AdhocMeetingError(err.body?.code, err.body?.message);\n });\n }\n\n /**\n * Fetches meeting info from the server\n * @param {String} destination one of many different types of destinations to look up info for\n * @param {String} [type] to match up with the destination value\n * @param {String} password\n * @param {Object} captchaInfo\n * @param {String} captchaInfo.code\n * @param {String} captchaInfo.id\n * @returns {Promise} returns a meeting info object\n * @public\n * @memberof MeetingInfo\n */\n async fetchMeetingInfo(destination, type = null, password = null, captchaInfo = null) {\n const destinationType = await MeetingInfoUtil.getDestinationType({\n destination,\n type,\n webex: this.webex\n });\n\n if (destinationType.type === _CONVERSATION_URL_ && this.webex.config.meetings.experimental.enableAdhocMeetings) {\n return this.createAdhocSpaceMeeting(destinationType.destination);\n }\n\n const body = await MeetingInfoUtil.getRequestBody({...destinationType, password, captchaInfo});\n\n const options = {\n method: HTTP_VERBS.POST,\n service: 'webex-appapi-service',\n resource: 'meetingInfo',\n body\n };\n\n const directURI = await MeetingInfoUtil.getDirectMeetingInfoURI(destinationType);\n\n if (directURI) options.directURI = directURI;\n\n return this.webex.request(options)\n .then((response) => {\n Metrics.sendBehavioralMetric(\n BEHAVIORAL_METRICS.FETCH_MEETING_INFO_V1_SUCCESS\n );\n\n return response;\n })\n .catch((err) => {\n if (err?.statusCode === 403) {\n Metrics.sendBehavioralMetric(\n BEHAVIORAL_METRICS.VERIFY_PASSWORD_ERROR,\n {\n reason: err.message,\n stack: err.stack\n }\n );\n\n throw new MeetingInfoV2PasswordError(err.body?.code, err.body?.data?.meetingInfo);\n }\n if (err?.statusCode === 423) {\n Metrics.sendBehavioralMetric(\n BEHAVIORAL_METRICS.VERIFY_CAPTCHA_ERROR,\n {\n reason: err.message,\n stack: err.stack\n }\n );\n\n throw new MeetingInfoV2CaptchaError(err.body?.code, {\n captchaId: err.body.captchaID,\n verificationImageURL: err.body.verificationImageURL,\n verificationAudioURL: err.body.verificationAudioURL,\n refreshURL: err.body.refreshURL\n });\n }\n\n Metrics.sendBehavioralMetric(\n BEHAVIORAL_METRICS.FETCH_MEETING_INFO_V1_FAILURE,\n {\n reason: err.message,\n stack: err.stack\n }\n );\n throw err;\n });\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"names":["PASSWORD_ERROR_DEFAULT_MESSAGE","CAPTCHA_ERROR_DEFAULT_MESSAGE","ADHOC_MEETING_DEFAULT_ERROR","CAPTCHA_ERROR_REQUIRES_PASSWORD_CODES","MeetingInfoV2PasswordError","wbxAppApiErrorCode","meetingInfo","message","name","sdkMessage","stack","Error","wbxAppApiCode","MeetingInfoV2AdhocMeetingError","MeetingInfoV2CaptchaError","captchaInfo","isPasswordRequired","includes","MeetingInfoV2","webex","destination","type","MeetingInfoUtil","getDestinationType","conversationUrl","meetings","preferredWebexSite","getInvitees","particpants","invitees","forEach","participant","push","email","emailAddress","ciUserUuid","entryUUID","internal","conversation","get","url","includeParticipants","disableTransform","then","body","title","displayName","spaceUrl","keyUrl","encryptionKeyUrl","kroUrl","kmsResourceObjectUrl","participants","items","uri","Metrics","sendBehavioralMetric","BEHAVIORAL_METRICS","ADHOC_MEETING_SUCCESS","request","method","HTTP_VERBS","POST","catch","err","ADHOC_MEETING_FAILURE","reason","code","password","destinationType","_CONVERSATION_URL_","config","experimental","enableAdhocMeetings","createAdhocSpaceMeeting","getRequestBody","options","getDirectMeetingInfoURI","directURI","service","WBXAPPAPI_SERVICE","resource","response","FETCH_MEETING_INFO_V1_SUCCESS","statusCode","VERIFY_PASSWORD_ERROR","data","VERIFY_CAPTCHA_ERROR","captchaId","captchaID","verificationImageURL","verificationAudioURL","refreshURL","FETCH_MEETING_INFO_V1_FAILURE"],"sources":["meeting-info-v2.js"],"sourcesContent":["\nimport {HTTP_VERBS, _CONVERSATION_URL_, WBXAPPAPI_SERVICE} from '../constants';\nimport Metrics from '../metrics';\nimport BEHAVIORAL_METRICS from '../metrics/constants';\n\nimport MeetingInfoUtil from './utilv2';\n\nconst PASSWORD_ERROR_DEFAULT_MESSAGE = 'Password required. Call fetchMeetingInfo() with password argument';\nconst CAPTCHA_ERROR_DEFAULT_MESSAGE = 'Captcha required. Call fetchMeetingInfo() with captchaInfo argument';\nconst ADHOC_MEETING_DEFAULT_ERROR = 'Failed starting the adhoc meeting, Please contact support team ';\nconst CAPTCHA_ERROR_REQUIRES_PASSWORD_CODES = [423005, 423006];\n\n/**\n * Error to indicate that wbxappapi requires a password\n */\nexport class MeetingInfoV2PasswordError extends Error {\n /**\n *\n * @constructor\n * @param {Number} [wbxAppApiErrorCode]\n * @param {Object} [meetingInfo]\n * @param {String} [message]\n */\n constructor(wbxAppApiErrorCode, meetingInfo, message = PASSWORD_ERROR_DEFAULT_MESSAGE) {\n super(`${message}, code=${wbxAppApiErrorCode}`);\n this.name = 'MeetingInfoV2PasswordError';\n this.sdkMessage = message;\n this.stack = (new Error()).stack;\n this.wbxAppApiCode = wbxAppApiErrorCode;\n this.meetingInfo = meetingInfo;\n }\n}\n\n/**\n * Error generating a adhoc space meeting\n */\nexport class MeetingInfoV2AdhocMeetingError extends Error {\n /**\n *\n * @constructor\n * @param {Number} [wbxAppApiErrorCode]\n * @param {String} [message]\n */\n constructor(wbxAppApiErrorCode, message = ADHOC_MEETING_DEFAULT_ERROR) {\n super(`${message}, code=${wbxAppApiErrorCode}`);\n this.name = 'MeetingInfoV2AdhocMeetingError';\n this.sdkMessage = message;\n this.stack = (new Error()).stack;\n this.wbxAppApiCode = wbxAppApiErrorCode;\n }\n}\n\n\n/**\n * Error to indicate that preferred webex site not present to start adhoc meeting\n */\nexport class MeetingInfoV2CaptchaError extends Error {\n /**\n *\n * @constructor\n * @param {Number} [wbxAppApiErrorCode]\n * @param {Object} [captchaInfo]\n * @param {String} [message]\n */\n constructor(wbxAppApiErrorCode, captchaInfo, message = CAPTCHA_ERROR_DEFAULT_MESSAGE) {\n super(`${message}, code=${wbxAppApiErrorCode}`);\n this.name = 'MeetingInfoV2PasswordError';\n this.sdkMessage = message;\n this.stack = (new Error()).stack;\n this.wbxAppApiCode = wbxAppApiErrorCode;\n this.isPasswordRequired = CAPTCHA_ERROR_REQUIRES_PASSWORD_CODES.includes(wbxAppApiErrorCode);\n this.captchaInfo = captchaInfo;\n }\n}\n\n/**\n * @class MeetingInfo\n */\nexport default class MeetingInfoV2 {\n /**\n *\n * @param {WebexSDK} webex\n */\n constructor(webex) {\n this.webex = webex;\n }\n\n /**\n * converts hydra id into conversation url and persons Id\n * @param {String} destination one of many different types of destinations to look up info for\n * @param {String} [type] to match up with the destination value\n * @returns {Promise} destination and type\n * @public\n * @memberof MeetingInfo\n */\n fetchInfoOptions(destination, type = null) {\n return MeetingInfoUtil.getDestinationType({\n destination,\n type,\n webex: this.webex\n });\n }\n\n /**\n * Creates adhoc space meetings for a space by fetching the conversation infomation\n * @param {String} conversationUrl conversationUrl to start adhoc meeting on\n * @returns {Promise} returns a meeting info object\n * @public\n * @memberof MeetingInfo\n */\n async createAdhocSpaceMeeting(conversationUrl) {\n if (!this.webex.meetings.preferredWebexSite) {\n throw Error('No preferred webex site found');\n }\n const getInvitees = (particpants = []) => {\n const invitees = [];\n\n if (particpants) {\n particpants.forEach((participant) => {\n invitees.push({\n email: participant.emailAddress,\n ciUserUuid: participant.entryUUID\n });\n });\n }\n\n return invitees;\n };\n\n return this.webex.internal.conversation.get(\n {url: conversationUrl},\n {includeParticipants: true, disableTransform: true}\n )\n .then((conversation) => {\n const body = {\n title: conversation.displayName,\n spaceUrl: conversation.url,\n keyUrl: conversation.encryptionKeyUrl,\n kroUrl: conversation.kmsResourceObjectUrl,\n invitees: getInvitees(conversation.participants?.items)\n };\n\n const uri = this.webex.meetings.preferredWebexSite ?\n `https://${this.webex.meetings.preferredWebexSite}/wbxappapi/v2/meetings/spaceInstant` : '';\n\n Metrics.sendBehavioralMetric(\n BEHAVIORAL_METRICS.ADHOC_MEETING_SUCCESS\n );\n\n return this.webex.request({\n method: HTTP_VERBS.POST,\n uri,\n body\n });\n })\n .catch((err) => {\n Metrics.sendBehavioralMetric(\n BEHAVIORAL_METRICS.ADHOC_MEETING_FAILURE,\n {\n reason: err.message,\n stack: err.stack\n }\n );\n throw new MeetingInfoV2AdhocMeetingError(err.body?.code, err.body?.message);\n });\n }\n\n /**\n * Fetches meeting info from the server\n * @param {String} destination one of many different types of destinations to look up info for\n * @param {String} [type] to match up with the destination value\n * @param {String} password\n * @param {Object} captchaInfo\n * @param {String} captchaInfo.code\n * @param {String} captchaInfo.id\n * @returns {Promise} returns a meeting info object\n * @public\n * @memberof MeetingInfo\n */\n async fetchMeetingInfo(destination, type = null, password = null, captchaInfo = null) {\n const destinationType = await MeetingInfoUtil.getDestinationType({\n destination,\n type,\n webex: this.webex\n });\n\n if (destinationType.type === _CONVERSATION_URL_ && this.webex.config.meetings.experimental.enableAdhocMeetings) {\n return this.createAdhocSpaceMeeting(destinationType.destination);\n }\n\n const body = await MeetingInfoUtil.getRequestBody({...destinationType, password, captchaInfo});\n\n const options = {\n method: HTTP_VERBS.POST,\n body\n };\n\n const directURI = await MeetingInfoUtil.getDirectMeetingInfoURI(destinationType);\n\n if (directURI) {\n options.uri = directURI;\n }\n else {\n options.service = WBXAPPAPI_SERVICE;\n options.resource = 'meetingInfo';\n }\n\n return this.webex.request(options)\n .then((response) => {\n Metrics.sendBehavioralMetric(\n BEHAVIORAL_METRICS.FETCH_MEETING_INFO_V1_SUCCESS\n );\n\n return response;\n })\n .catch((err) => {\n if (err?.statusCode === 403) {\n Metrics.sendBehavioralMetric(\n BEHAVIORAL_METRICS.VERIFY_PASSWORD_ERROR,\n {\n reason: err.message,\n stack: err.stack\n }\n );\n\n throw new MeetingInfoV2PasswordError(err.body?.code, err.body?.data?.meetingInfo);\n }\n if (err?.statusCode === 423) {\n Metrics.sendBehavioralMetric(\n BEHAVIORAL_METRICS.VERIFY_CAPTCHA_ERROR,\n {\n reason: err.message,\n stack: err.stack\n }\n );\n\n throw new MeetingInfoV2CaptchaError(err.body?.code, {\n captchaId: err.body.captchaID,\n verificationImageURL: err.body.verificationImageURL,\n verificationAudioURL: err.body.verificationAudioURL,\n refreshURL: err.body.refreshURL\n });\n }\n\n Metrics.sendBehavioralMetric(\n BEHAVIORAL_METRICS.FETCH_MEETING_INFO_V1_FAILURE,\n {\n reason: err.message,\n stack: err.stack\n }\n );\n throw err;\n });\n }\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webex/plugin-meetings",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.20.1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"contributors": [
|
|
@@ -24,15 +24,15 @@
|
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"@babel/runtime-corejs2": "^7.14.8",
|
|
27
|
-
"@webex/webex-core": "2.
|
|
28
|
-
"@webex/internal-plugin-mercury": "2.
|
|
29
|
-
"@webex/internal-plugin-conversation": "2.
|
|
27
|
+
"@webex/webex-core": "2.20.1",
|
|
28
|
+
"@webex/internal-plugin-mercury": "2.20.1",
|
|
29
|
+
"@webex/internal-plugin-conversation": "2.20.1",
|
|
30
30
|
"webrtc-adapter": "^7.7.0",
|
|
31
31
|
"lodash": "^4.17.21",
|
|
32
32
|
"uuid": "^3.3.2",
|
|
33
33
|
"global": "^4.4.0",
|
|
34
34
|
"ip-anonymize": "^0.1.0",
|
|
35
|
-
"@webex/common": "2.
|
|
35
|
+
"@webex/common": "2.20.1",
|
|
36
36
|
"bowser": "^2.11.0",
|
|
37
37
|
"sdp-transform": "^2.12.0",
|
|
38
38
|
"btoa": "^1.2.1",
|
package/src/constants.ts
CHANGED
|
@@ -165,6 +165,8 @@ export const WEBEX_DOT_COM = 'webex.com';
|
|
|
165
165
|
|
|
166
166
|
export const CONVERSATION_SERVICE = 'identityLookup';
|
|
167
167
|
|
|
168
|
+
export const WBXAPPAPI_SERVICE = 'webex-appapi-service';
|
|
169
|
+
|
|
168
170
|
// ******************* ARRAYS ********************
|
|
169
171
|
// Please alphabetize
|
|
170
172
|
export const DEFAULT_EXCLUDED_STATS = ['timestamp', 'ssrc', 'priority'];
|
|
@@ -284,6 +286,7 @@ export const EVENT_TRIGGERS = {
|
|
|
284
286
|
MEETING_SELF_UNMUTED_BY_OTHERS: 'meeting:self:unmutedByOthers',
|
|
285
287
|
MEETING_SELF_REQUESTED_TO_UNMUTE: 'meeting:self:requestedToUnmute',
|
|
286
288
|
MEETING_SELF_PHONE_AUDIO_UPDATE: 'meeting:self:phoneAudioUpdate',
|
|
289
|
+
MEETING_CONTROLS_LAYOUT_UPDATE: 'meeting:layout:update',
|
|
287
290
|
MEMBERS_UPDATE: 'members:update',
|
|
288
291
|
MEMBERS_CONTENT_UPDATE: 'members:content:update',
|
|
289
292
|
MEMBERS_HOST_UPDATE: 'members:host:update',
|
|
@@ -486,6 +489,7 @@ export const LOCUS = {
|
|
|
486
489
|
|
|
487
490
|
export const LOCUSINFO = {
|
|
488
491
|
EVENTS: {
|
|
492
|
+
CONTROLS_MEETING_LAYOUT_UPDATED: 'CONTROLS_MEETING_LAYOUT_UPDATED',
|
|
489
493
|
CONTROLS_RECORDING_UPDATED: 'CONTROLS_RECORDING_UPDATED',
|
|
490
494
|
CONTROLS_MEETING_TRANSCRIBE_UPDATED: 'CONTROLS_MEETING_TRANSCRIBE_UPDATED',
|
|
491
495
|
CONTROLS_MEETING_CONTAINER_UPDATED: 'CONTROLS_MEETING_CONTAINER_UPDATED',
|
package/src/locus-info/index.js
CHANGED
|
@@ -927,6 +927,17 @@ export default class LocusInfo extends EventsScope {
|
|
|
927
927
|
this.compareAndUpdateFlags.compareHostAndSelf = false;
|
|
928
928
|
}
|
|
929
929
|
|
|
930
|
+
if (parsedSelves.updates.layoutChanged) {
|
|
931
|
+
this.emitScoped(
|
|
932
|
+
{
|
|
933
|
+
file: 'locus-info',
|
|
934
|
+
function: 'updateSelf'
|
|
935
|
+
},
|
|
936
|
+
LOCUSINFO.EVENTS.CONTROLS_MEETING_LAYOUT_UPDATED,
|
|
937
|
+
{layout: parsedSelves.current.layout}
|
|
938
|
+
);
|
|
939
|
+
}
|
|
940
|
+
|
|
930
941
|
if (parsedSelves.updates.isMediaInactiveOrReleased) {
|
|
931
942
|
this.emitScoped(
|
|
932
943
|
{
|
|
@@ -58,12 +58,15 @@ SelfUtils.parse = (self, deviceId) => {
|
|
|
58
58
|
removed: self.removed,
|
|
59
59
|
roles: SelfUtils.getRoles(self),
|
|
60
60
|
isUserUnadmitted: self.state === _IDLE_ && joinedWith?.intent?.type === _WAIT_,
|
|
61
|
+
layout: SelfUtils.getLayout(self)
|
|
61
62
|
};
|
|
62
63
|
}
|
|
63
64
|
|
|
64
65
|
return null;
|
|
65
66
|
};
|
|
66
67
|
|
|
68
|
+
SelfUtils.getLayout = (self) => (Array.isArray(self?.controls?.layouts) ? self.controls.layouts[0].type : undefined);
|
|
69
|
+
|
|
67
70
|
SelfUtils.getRoles = (self) => (self?.controls?.role?.roles || []).reduce((roles, role) => {
|
|
68
71
|
if (role.hasRole) {
|
|
69
72
|
roles.push(role.type);
|
|
@@ -85,6 +88,7 @@ SelfUtils.getSelves = (oldSelf, newSelf, deviceId) => {
|
|
|
85
88
|
updates.moderatorChanged = SelfUtils.moderatorChanged(previous, current);
|
|
86
89
|
updates.isMediaInactiveOrReleased = SelfUtils.wasMediaInactiveOrReleased(previous, current);
|
|
87
90
|
updates.isUserObserving = SelfUtils.isDeviceObserving(previous, current);
|
|
91
|
+
updates.layoutChanged = SelfUtils.layoutChanged(previous, current);
|
|
88
92
|
|
|
89
93
|
updates.isMediaInactive = SelfUtils.isMediaInactive(previous, current);
|
|
90
94
|
updates.audioStateChange = previous?.currentMediaStatus.audio !== current.currentMediaStatus.audio;
|
|
@@ -105,6 +109,15 @@ SelfUtils.getSelves = (oldSelf, newSelf, deviceId) => {
|
|
|
105
109
|
*/
|
|
106
110
|
SelfUtils.isJoined = (self) => self?.state === _JOINED_;
|
|
107
111
|
|
|
112
|
+
/**
|
|
113
|
+
* Validate if the Meeting Layout Controls Layout has changed.
|
|
114
|
+
*
|
|
115
|
+
* @param {Self} previous - Previous self state
|
|
116
|
+
* @param {Self} current - Current self state [per event]
|
|
117
|
+
* @returns {boolean} - If the MEeting Layout Controls Layout has changed.
|
|
118
|
+
*/
|
|
119
|
+
SelfUtils.layoutChanged = (previous, current) => current?.layout && previous?.layout !== current?.layout;
|
|
120
|
+
|
|
108
121
|
|
|
109
122
|
SelfUtils.isMediaInactive = (previous, current) => {
|
|
110
123
|
if (
|
package/src/meeting/index.js
CHANGED
|
@@ -5216,6 +5216,20 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5216
5216
|
}
|
|
5217
5217
|
this.lastVideoLayoutInfo = cloneDeep(layoutInfo);
|
|
5218
5218
|
|
|
5219
|
+
this.locusInfo.once(LOCUSINFO.EVENTS.CONTROLS_MEETING_LAYOUT_UPDATED, (envelope) => {
|
|
5220
|
+
Trigger.trigger(
|
|
5221
|
+
this,
|
|
5222
|
+
{
|
|
5223
|
+
file: 'meeting/index',
|
|
5224
|
+
function: 'changeVideoLayout',
|
|
5225
|
+
},
|
|
5226
|
+
EVENT_TRIGGERS.MEETING_CONTROLS_LAYOUT_UPDATE,
|
|
5227
|
+
{
|
|
5228
|
+
layout: envelope.layout
|
|
5229
|
+
}
|
|
5230
|
+
);
|
|
5231
|
+
});
|
|
5232
|
+
|
|
5219
5233
|
return this.meetingRequest
|
|
5220
5234
|
.changeVideoLayoutDebounced({
|
|
5221
5235
|
locusUrl: this.locusInfo.self.url,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
import {HTTP_VERBS, _CONVERSATION_URL_} from '../constants';
|
|
2
|
+
import {HTTP_VERBS, _CONVERSATION_URL_, WBXAPPAPI_SERVICE} from '../constants';
|
|
3
3
|
import Metrics from '../metrics';
|
|
4
4
|
import BEHAVIORAL_METRICS from '../metrics/constants';
|
|
5
5
|
|
|
@@ -192,14 +192,18 @@ export default class MeetingInfoV2 {
|
|
|
192
192
|
|
|
193
193
|
const options = {
|
|
194
194
|
method: HTTP_VERBS.POST,
|
|
195
|
-
service: 'webex-appapi-service',
|
|
196
|
-
resource: 'meetingInfo',
|
|
197
195
|
body
|
|
198
196
|
};
|
|
199
197
|
|
|
200
198
|
const directURI = await MeetingInfoUtil.getDirectMeetingInfoURI(destinationType);
|
|
201
199
|
|
|
202
|
-
if (directURI)
|
|
200
|
+
if (directURI) {
|
|
201
|
+
options.uri = directURI;
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
options.service = WBXAPPAPI_SERVICE;
|
|
205
|
+
options.resource = 'meetingInfo';
|
|
206
|
+
}
|
|
203
207
|
|
|
204
208
|
return this.webex.request(options)
|
|
205
209
|
.then((response) => {
|
|
@@ -428,6 +428,52 @@ describe('plugin-meetings', () => {
|
|
|
428
428
|
});
|
|
429
429
|
|
|
430
430
|
describe('#updateSelf', () => {
|
|
431
|
+
it('should trigger CONTROLS_MEETING_LAYOUT_UPDATED when the meeting layout controls change', () => {
|
|
432
|
+
const layoutType = 'EXAMPLE TYPE';
|
|
433
|
+
|
|
434
|
+
locusInfo.self = undefined;
|
|
435
|
+
const selfWithLayoutChanged = cloneDeep(self);
|
|
436
|
+
|
|
437
|
+
selfWithLayoutChanged.controls.layouts = [{
|
|
438
|
+
type: layoutType,
|
|
439
|
+
}];
|
|
440
|
+
|
|
441
|
+
locusInfo.emitScoped = sinon.stub();
|
|
442
|
+
locusInfo.updateSelf(selfWithLayoutChanged, []);
|
|
443
|
+
|
|
444
|
+
assert.calledWith(locusInfo.emitScoped, {
|
|
445
|
+
file: 'locus-info',
|
|
446
|
+
function: 'updateSelf'
|
|
447
|
+
},
|
|
448
|
+
LOCUSINFO.EVENTS.CONTROLS_MEETING_LAYOUT_UPDATED,
|
|
449
|
+
{layout: layoutType});
|
|
450
|
+
});
|
|
451
|
+
|
|
452
|
+
it('should not trigger CONTROLS_MEETING_LAYOUT_UPDATED when the meeting layout controls did not change', () => {
|
|
453
|
+
const layoutType = 'EXAMPLE TYPE';
|
|
454
|
+
|
|
455
|
+
locusInfo.self = undefined;
|
|
456
|
+
const selfWithLayoutChanged = cloneDeep(self);
|
|
457
|
+
|
|
458
|
+
selfWithLayoutChanged.controls.layouts = [{
|
|
459
|
+
type: layoutType,
|
|
460
|
+
}];
|
|
461
|
+
|
|
462
|
+
// Set the layout prior to stubbing to validate it does not change.
|
|
463
|
+
locusInfo.updateSelf(selfWithLayoutChanged, []);
|
|
464
|
+
|
|
465
|
+
locusInfo.emitScoped = sinon.stub();
|
|
466
|
+
|
|
467
|
+
locusInfo.updateSelf(selfWithLayoutChanged, []);
|
|
468
|
+
|
|
469
|
+
assert.neverCalledWith(locusInfo.emitScoped, {
|
|
470
|
+
file: 'locus-info',
|
|
471
|
+
function: 'updateSelf'
|
|
472
|
+
},
|
|
473
|
+
LOCUSINFO.EVENTS.CONTROLS_MEETING_LAYOUT_UPDATED,
|
|
474
|
+
{layout: layoutType});
|
|
475
|
+
});
|
|
476
|
+
|
|
431
477
|
it('should trigger MEDIA_INACTIVITY on server media inactivity', () => {
|
|
432
478
|
locusInfo.self = self;
|
|
433
479
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {assert} from '@webex/test-helper-chai';
|
|
2
2
|
import Sinon from 'sinon';
|
|
3
|
+
import {cloneDeep} from 'lodash';
|
|
3
4
|
|
|
4
5
|
import SelfUtils from '@webex/plugin-meetings/src/locus-info/selfUtils';
|
|
5
6
|
|
|
@@ -7,6 +8,23 @@ import {self} from './selfConstant';
|
|
|
7
8
|
|
|
8
9
|
describe('plugin-meetings', () => {
|
|
9
10
|
describe('selfUtils', () => {
|
|
11
|
+
describe('layoutChanged', () => {
|
|
12
|
+
it('should return true if the layout has changed', () => {
|
|
13
|
+
const parsedSelf = SelfUtils.parse(self);
|
|
14
|
+
const clonedSelf = cloneDeep(parsedSelf);
|
|
15
|
+
|
|
16
|
+
clonedSelf.layout = 'DIFFERENT';
|
|
17
|
+
|
|
18
|
+
assert.deepEqual(SelfUtils.layoutChanged(parsedSelf, clonedSelf), true);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it('should return false if the layout has not changed', () => {
|
|
22
|
+
const parsedSelf = SelfUtils.parse(self);
|
|
23
|
+
|
|
24
|
+
assert.deepEqual(SelfUtils.layoutChanged(parsedSelf, parsedSelf), false);
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
|
|
10
28
|
describe('parse', () => {
|
|
11
29
|
it('parse calls getRoles and returns the resulting roles', () => {
|
|
12
30
|
const getRolesSpy = Sinon.spy(SelfUtils, 'getRoles');
|
|
@@ -17,6 +35,28 @@ describe('plugin-meetings', () => {
|
|
|
17
35
|
|
|
18
36
|
assert.deepEqual(parsedSelf.roles, ['PRESENTER']);
|
|
19
37
|
});
|
|
38
|
+
|
|
39
|
+
it('calls getLayout and returns the resulting layout', () => {
|
|
40
|
+
const spy = Sinon.spy(SelfUtils, 'getLayout');
|
|
41
|
+
const parsedSelf = SelfUtils.parse(self);
|
|
42
|
+
|
|
43
|
+
assert.calledWith(spy, self);
|
|
44
|
+
assert.deepEqual(parsedSelf.layout, self.controls.layouts[0].type);
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
describe('getLayout', () => {
|
|
49
|
+
it('should get supplied layout', () => {
|
|
50
|
+
assert.deepEqual(SelfUtils.getLayout(self), self.controls.layouts[0].type);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it('should return undefined if the new self does not have a provided layout', () => {
|
|
54
|
+
const mutatedSelf = cloneDeep(self);
|
|
55
|
+
|
|
56
|
+
delete mutatedSelf.controls.layouts;
|
|
57
|
+
|
|
58
|
+
assert.deepEqual(SelfUtils.getLayout(mutatedSelf), undefined);
|
|
59
|
+
});
|
|
20
60
|
});
|
|
21
61
|
|
|
22
62
|
describe('getRoles', () => {
|
|
@@ -10,6 +10,17 @@ import {assert} from '@webex/test-helper-chai';
|
|
|
10
10
|
import {Credentials} from '@webex/webex-core';
|
|
11
11
|
import Support from '@webex/internal-plugin-support';
|
|
12
12
|
import MockWebex from '@webex/test-helper-mock-webex';
|
|
13
|
+
import {
|
|
14
|
+
FLOOR_ACTION,
|
|
15
|
+
SHARE_STATUS,
|
|
16
|
+
MEETING_INFO_FAILURE_REASON,
|
|
17
|
+
PASSWORD_STATUS,
|
|
18
|
+
EVENTS,
|
|
19
|
+
EVENT_TRIGGERS,
|
|
20
|
+
_SIP_URI_,
|
|
21
|
+
_MEETING_ID_,
|
|
22
|
+
LOCUSINFO,
|
|
23
|
+
} from '@webex/plugin-meetings/src/constants';
|
|
13
24
|
|
|
14
25
|
import * as StatsAnalyzerModule from '@webex/plugin-meetings/src/statsAnalyzer';
|
|
15
26
|
import EventsScope from '@webex/plugin-meetings/src/common/events/events-scope';
|
|
@@ -31,16 +42,6 @@ import TriggerProxy from '@webex/plugin-meetings/src/common/events/trigger-proxy
|
|
|
31
42
|
import BrowserDetection from '@webex/plugin-meetings/src/common/browser-detection';
|
|
32
43
|
import Metrics from '@webex/plugin-meetings/src/metrics';
|
|
33
44
|
import {eventType} from '@webex/plugin-meetings/src/metrics/config';
|
|
34
|
-
import {
|
|
35
|
-
FLOOR_ACTION,
|
|
36
|
-
SHARE_STATUS,
|
|
37
|
-
MEETING_INFO_FAILURE_REASON,
|
|
38
|
-
PASSWORD_STATUS,
|
|
39
|
-
EVENTS,
|
|
40
|
-
EVENT_TRIGGERS,
|
|
41
|
-
_SIP_URI_,
|
|
42
|
-
_MEETING_ID_,
|
|
43
|
-
} from '@webex/plugin-meetings/src/constants';
|
|
44
45
|
import BEHAVIORAL_METRICS from '@webex/plugin-meetings/src/metrics/constants';
|
|
45
46
|
|
|
46
47
|
import locus from '../fixture/locus';
|
|
@@ -1912,6 +1913,15 @@ describe('plugin-meetings', () => {
|
|
|
1912
1913
|
};
|
|
1913
1914
|
});
|
|
1914
1915
|
|
|
1916
|
+
it('should listen once for CONTROLS_MEETING_LAYOUT_UPDATED', async () => {
|
|
1917
|
+
// const spy = sinon.spy(TriggerProxy, 'trigger');
|
|
1918
|
+
const spy = sinon.spy(meeting.locusInfo, 'once');
|
|
1919
|
+
|
|
1920
|
+
await meeting.changeVideoLayout('Equal');
|
|
1921
|
+
|
|
1922
|
+
assert.calledWith(spy, LOCUSINFO.EVENTS.CONTROLS_MEETING_LAYOUT_UPDATED);
|
|
1923
|
+
});
|
|
1924
|
+
|
|
1915
1925
|
it('should have receiveVideo true and remote video track should exist', () => {
|
|
1916
1926
|
assert.equal(meeting.mediaProperties.mediaDirection.receiveVideo, true);
|
|
1917
1927
|
assert.exists(meeting.mediaProperties.remoteVideoTrack);
|
|
@@ -7,13 +7,15 @@ import sinon from 'sinon';
|
|
|
7
7
|
import MockWebex from '@webex/test-helper-mock-webex';
|
|
8
8
|
import Device from '@webex/internal-plugin-device';
|
|
9
9
|
import Mercury from '@webex/internal-plugin-mercury';
|
|
10
|
-
|
|
11
|
-
import Meetings from '@webex/plugin-meetings/src/meetings';
|
|
12
10
|
import {
|
|
13
11
|
_MEETING_ID_,
|
|
14
12
|
_PERSONAL_ROOM_,
|
|
15
|
-
_CONVERSATION_URL_
|
|
13
|
+
_CONVERSATION_URL_,
|
|
14
|
+
_SIP_URI_,
|
|
15
|
+
WBXAPPAPI_SERVICE
|
|
16
16
|
} from '@webex/plugin-meetings/src/constants';
|
|
17
|
+
|
|
18
|
+
import Meetings from '@webex/plugin-meetings/src/meetings';
|
|
17
19
|
import MeetingInfo, {MeetingInfoV2PasswordError, MeetingInfoV2CaptchaError, MeetingInfoV2AdhocMeetingError} from '@webex/plugin-meetings/src/meeting-info/meeting-info-v2';
|
|
18
20
|
import MeetingInfoUtil from '@webex/plugin-meetings/src/meeting-info/utilv2';
|
|
19
21
|
import Metrics from '@webex/plugin-meetings/src/metrics';
|
|
@@ -101,7 +103,7 @@ describe('plugin-meetings', () => {
|
|
|
101
103
|
});
|
|
102
104
|
|
|
103
105
|
assert.calledWith(webex.request, {
|
|
104
|
-
method: 'POST', service:
|
|
106
|
+
method: 'POST', service: WBXAPPAPI_SERVICE, resource: 'meetingInfo', body: {meetingKey: '1234323'}
|
|
105
107
|
});
|
|
106
108
|
assert.deepEqual(result, requestResponse);
|
|
107
109
|
|
|
@@ -122,12 +124,38 @@ describe('plugin-meetings', () => {
|
|
|
122
124
|
});
|
|
123
125
|
|
|
124
126
|
assert.calledWith(webex.request, {
|
|
125
|
-
method: 'POST', service:
|
|
127
|
+
method: 'POST', service: WBXAPPAPI_SERVICE, resource: 'meetingInfo', body: {meetingKey: '1234323'}
|
|
128
|
+
});
|
|
129
|
+
assert.deepEqual(result, requestResponse);
|
|
130
|
+
|
|
131
|
+
MeetingInfoUtil.getDestinationType.restore();
|
|
132
|
+
MeetingInfoUtil.getRequestBody.restore();
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it('should use the direct uri for the request if it exists', async () => {
|
|
136
|
+
const body = {meetingKey: '1234323'};
|
|
137
|
+
const requestResponse = {statusCode: 200, body};
|
|
138
|
+
|
|
139
|
+
sinon.stub(MeetingInfoUtil, 'getDestinationType').returns(Promise.resolve({type: _SIP_URI_, destination: 'example@something.webex.com'}));
|
|
140
|
+
sinon.stub(MeetingInfoUtil, 'getRequestBody').returns(Promise.resolve(body));
|
|
141
|
+
sinon.stub(MeetingInfoUtil, 'getDirectMeetingInfoURI').returns('https://example.com');
|
|
142
|
+
webex.request.resolves(requestResponse);
|
|
143
|
+
|
|
144
|
+
const result = await meetingInfo.fetchMeetingInfo(
|
|
145
|
+
'example@something.webex.com',
|
|
146
|
+
_SIP_URI_,
|
|
147
|
+
);
|
|
148
|
+
|
|
149
|
+
assert.calledWith(MeetingInfoUtil.getDestinationType, {destination: 'example@something.webex.com', type: _SIP_URI_, webex});
|
|
150
|
+
assert.calledWith(MeetingInfoUtil.getDirectMeetingInfoURI, {destination: 'example@something.webex.com', type: _SIP_URI_});
|
|
151
|
+
assert.calledWith(webex.request, {
|
|
152
|
+
method: 'POST', uri: 'https://example.com', body: {meetingKey: '1234323'}
|
|
126
153
|
});
|
|
127
154
|
assert.deepEqual(result, requestResponse);
|
|
128
155
|
|
|
129
156
|
MeetingInfoUtil.getDestinationType.restore();
|
|
130
157
|
MeetingInfoUtil.getRequestBody.restore();
|
|
158
|
+
MeetingInfoUtil.getDirectMeetingInfoURI.restore();
|
|
131
159
|
});
|
|
132
160
|
|
|
133
161
|
it('should fetch meeting info with provided password and captcha code', async () => {
|
|
@@ -139,7 +167,7 @@ describe('plugin-meetings', () => {
|
|
|
139
167
|
|
|
140
168
|
assert.calledWith(webex.request, {
|
|
141
169
|
method: 'POST',
|
|
142
|
-
service:
|
|
170
|
+
service: WBXAPPAPI_SERVICE,
|
|
143
171
|
resource: 'meetingInfo',
|
|
144
172
|
body: {
|
|
145
173
|
supportHostKey: true,
|