Skip to content

Commit

Permalink
Merge branch 'next' into descriptiontag
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisadubois authored Dec 16, 2024
2 parents 3a3abe6 + 885e4bb commit b5ae591
Show file tree
Hide file tree
Showing 15 changed files with 403 additions and 28 deletions.
10 changes: 10 additions & 0 deletions packages/@webex/plugin-meetings/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -904,6 +904,10 @@ export const DISPLAY_HINTS = {
RECORDING_CONTROL_PAUSE: 'RECORDING_CONTROL_PAUSE',
RECORDING_CONTROL_STOP: 'RECORDING_CONTROL_STOP',
RECORDING_CONTROL_RESUME: 'RECORDING_CONTROL_RESUME',
PREMISE_RECORDING_CONTROL_START: 'PREMISE_RECORDING_CONTROL_START',
PREMISE_RECORDING_CONTROL_PAUSE: 'PREMISE_RECORDING_CONTROL_PAUSE',
PREMISE_RECORDING_CONTROL_STOP: 'PREMISE_RECORDING_CONTROL_STOP',
PREMISE_RECORDING_CONTROL_RESUME: 'PREMISE_RECORDING_CONTROL_RESUME',
LOCK_CONTROL_UNLOCK: 'LOCK_CONTROL_UNLOCK',
LOCK_CONTROL_LOCK: 'LOCK_CONTROL_LOCK',
LOCK_STATUS_LOCKED: 'LOCK_STATUS_LOCKED',
Expand Down Expand Up @@ -988,6 +992,12 @@ export const DISPLAY_HINTS = {
STAGE_VIEW_INACTIVE: 'STAGE_VIEW_INACTIVE',
ENABLE_STAGE_VIEW: 'ENABLE_STAGE_VIEW',
DISABLE_STAGE_VIEW: 'DISABLE_STAGE_VIEW',

// Practice Session
PRACTICE_SESSION_ON: 'PRACTICE_SESSION_ON',
PRACTICE_SESSION_OFF: 'PRACTICE_SESSION_OFF',
SHOW_PRACTICE_SESSION_START: 'SHOW_PRACTICE_SESSION_START',
SHOW_PRACTICE_SESSION_STOP: 'SHOW_PRACTICE_SESSION_STOP',
};

export const INTERSTITIAL_DISPLAY_HINTS = [DISPLAY_HINTS.VOIP_IS_ENABLED];
Expand Down
21 changes: 21 additions & 0 deletions packages/@webex/plugin-meetings/src/meeting/in-meeting-actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ interface IInMeetingActions {
canStartRecording?: boolean;
canPauseRecording?: boolean;
canResumeRecording?: boolean;
isPremiseRecordingEnabled?: boolean;
canStopRecording?: boolean;
canRaiseHand?: boolean;
canLowerAllHands?: boolean;
Expand Down Expand Up @@ -93,6 +94,10 @@ interface IInMeetingActions {
canShowStageView?: boolean;
canEnableStageView?: boolean;
canDisableStageView?: boolean;
isPracticeSessionOn?: boolean;
isPracticeSessionOff?: boolean;
canStartPracticeSession?: boolean;
canStopPracticeSession?: boolean;
}

/**
Expand All @@ -117,6 +122,8 @@ export default class InMeetingActions implements IInMeetingActions {

canResumeRecording = null;

isPremiseRecordingEnabled = null;

canStopRecording = null;

canSetMuteOnEntry = null;
Expand Down Expand Up @@ -266,6 +273,15 @@ export default class InMeetingActions implements IInMeetingActions {
canEnableStageView = null;

canDisableStageView = null;

isPracticeSessionOn = null;

isPracticeSessionOff = null;

canStartPracticeSession = null;

canStopPracticeSession = null;

/**
* Returns all meeting action options
* @returns {Object}
Expand All @@ -288,6 +304,7 @@ export default class InMeetingActions implements IInMeetingActions {
canPauseRecording: this.canPauseRecording,
canResumeRecording: this.canResumeRecording,
canStopRecording: this.canStopRecording,
isPremiseRecordingEnabled: this.isPremiseRecordingEnabled,
canRaiseHand: this.canRaiseHand,
canLowerAllHands: this.canLowerAllHands,
canLowerSomeoneElsesHand: this.canLowerSomeoneElsesHand,
Expand Down Expand Up @@ -354,6 +371,10 @@ export default class InMeetingActions implements IInMeetingActions {
canShowStageView: this.canShowStageView,
canEnableStageView: this.canEnableStageView,
canDisableStageView: this.canDisableStageView,
isPracticeSessionOn: this.isPracticeSessionOn,
isPracticeSessionOff: this.isPracticeSessionOff,
canStartPracticeSession: this.canStartPracticeSession,
canStopPracticeSession: this.canStopPracticeSession,
});

/**
Expand Down
22 changes: 22 additions & 0 deletions packages/@webex/plugin-meetings/src/meeting/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2660,6 +2660,7 @@ export default class Meeting extends StatelessWebexPlugin {
});

this.locusInfo.on(LOCUSINFO.EVENTS.CONTROLS_PRACTICE_SESSION_STATUS_UPDATED, ({state}) => {
this.webinar.updatePracticeSessionStatus(state);
Trigger.trigger(
this,
{file: 'meeting/index', function: 'setupLocusControlsListener'},
Expand Down Expand Up @@ -3516,6 +3517,7 @@ export default class Meeting extends StatelessWebexPlugin {
emailAddress: string;
email: string;
phoneNumber: string;
roles: Array<string>;
},
alertIfActive = true
) {
Expand Down Expand Up @@ -3772,6 +3774,10 @@ export default class Meeting extends StatelessWebexPlugin {
this.userDisplayHints,
this.selfUserPolicies
),
isPremiseRecordingEnabled: RecordingUtil.isPremiseRecordingEnabled(
this.userDisplayHints,
this.selfUserPolicies
),
canRaiseHand: MeetingUtil.canUserRaiseHand(this.userDisplayHints),
canLowerAllHands: MeetingUtil.canUserLowerAllHands(this.userDisplayHints),
canLowerSomeoneElsesHand: MeetingUtil.canUserLowerSomeoneElsesHand(this.userDisplayHints),
Expand Down Expand Up @@ -3915,6 +3921,22 @@ export default class Meeting extends StatelessWebexPlugin {
requiredHints: [DISPLAY_HINTS.DISABLE_STAGE_VIEW],
displayHints: this.userDisplayHints,
}),
isPracticeSessionOn: ControlsOptionsUtil.hasHints({
requiredHints: [DISPLAY_HINTS.PRACTICE_SESSION_ON],
displayHints: this.userDisplayHints,
}),
isPracticeSessionOff: ControlsOptionsUtil.hasHints({
requiredHints: [DISPLAY_HINTS.PRACTICE_SESSION_OFF],
displayHints: this.userDisplayHints,
}),
canStartPracticeSession: ControlsOptionsUtil.hasHints({
requiredHints: [DISPLAY_HINTS.SHOW_PRACTICE_SESSION_START],
displayHints: this.userDisplayHints,
}),
canStopPracticeSession: ControlsOptionsUtil.hasHints({
requiredHints: [DISPLAY_HINTS.SHOW_PRACTICE_SESSION_STOP],
displayHints: this.userDisplayHints,
}),
canShareFile:
(ControlsOptionsUtil.hasHints({
requiredHints: [DISPLAY_HINTS.SHARE_FILE],
Expand Down
1 change: 1 addition & 0 deletions packages/@webex/plugin-meetings/src/members/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ const MembersUtil = {
{
address:
options.invitee.emailAddress || options.invitee.email || options.invitee.phoneNumber,
...(options.invitee.roles ? {roles: options.invitee.roles} : {}),
},
],
alertIfActive: options.alertIfActive,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
enum RecordingAction {
export enum RecordingAction {
Start = 'Start',
Stop = 'Stop',
Pause = 'Pause',
Resume = 'Resume',
}

export default RecordingAction;
export enum RecordingType {
Premise = 'premise',
Cloud = 'cloud',
}
21 changes: 17 additions & 4 deletions packages/@webex/plugin-meetings/src/recording-controller/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import PermissionError from '../common/errors/permission';
import LoggerProxy from '../common/logs/logger-proxy';
import {CONTROLS, HTTP_VERBS, SELF_POLICY} from '../constants';
import MeetingRequest from '../meeting/request';
import RecordingAction from './enums';
import {RecordingAction, RecordingType} from './enums';
import Util from './util';
import LoggerProxy from '../common/logs/logger-proxy';

/**
* @description Recording manages the recording functionality of the meeting object, there should only be one instantation of recording per meeting
Expand Down Expand Up @@ -228,11 +228,12 @@ export default class RecordingController {

/**
* @param {RecordingAction} action
* @param {RecordingType} recordingType
* @private
* @memberof RecordingController
* @returns {Promise}
*/
private recordingService(action: RecordingAction): Promise<any> {
private recordingService(action: RecordingAction, recordingType: RecordingType): Promise<any> {
// @ts-ignore
return this.request.request({
body: {
Expand All @@ -242,6 +243,7 @@ export default class RecordingController {
recording: {
action: action.toLowerCase(),
},
recordingType,
},
uri: `${this.serviceUrl}/loci/${this.locusId}/recording`,
method: HTTP_VERBS.PUT,
Expand Down Expand Up @@ -276,14 +278,25 @@ export default class RecordingController {
* @returns {Promise}
*/
private recordingFacade(action: RecordingAction): Promise<any> {
const isPremiseRecordingEnabled = Util.isPremiseRecordingEnabled(
this.displayHints,
this.selfUserPolicies
);
LoggerProxy.logger.log(
`RecordingController:index#recordingFacade --> recording action [${action}]`
);

let recordingType: RecordingType;
if (isPremiseRecordingEnabled) {
recordingType = RecordingType.Premise;
} else {
recordingType = RecordingType.Cloud;
}

// assumes action is proper cased (i.e., Example)
if (Util?.[`canUser${action}`](this.displayHints, this.selfUserPolicies)) {
if (this.serviceUrl) {
return this.recordingService(action);
return this.recordingService(action, recordingType);
}

return this.recordingControls(action);
Expand Down
25 changes: 20 additions & 5 deletions packages/@webex/plugin-meetings/src/recording-controller/util.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,47 @@
import {DISPLAY_HINTS, SELF_POLICY} from '../constants';
import RecordingAction from './enums';
import {RecordingAction} from './enums';
import MeetingUtil from '../meeting/util';

const canUserStart = (
displayHints: Array<string>,
userPolicies: Record<SELF_POLICY, boolean>
): boolean =>
displayHints.includes(DISPLAY_HINTS.RECORDING_CONTROL_START) &&
(displayHints.includes(DISPLAY_HINTS.RECORDING_CONTROL_START) ||
displayHints.includes(DISPLAY_HINTS.PREMISE_RECORDING_CONTROL_START)) &&
MeetingUtil.selfSupportsFeature(SELF_POLICY.SUPPORT_NETWORK_BASED_RECORD, userPolicies);

const canUserPause = (
displayHints: Array<string>,
userPolicies: Record<SELF_POLICY, boolean>
): boolean =>
displayHints.includes(DISPLAY_HINTS.RECORDING_CONTROL_PAUSE) &&
(displayHints.includes(DISPLAY_HINTS.RECORDING_CONTROL_PAUSE) ||
displayHints.includes(DISPLAY_HINTS.PREMISE_RECORDING_CONTROL_PAUSE)) &&
MeetingUtil.selfSupportsFeature(SELF_POLICY.SUPPORT_NETWORK_BASED_RECORD, userPolicies);

const canUserResume = (
displayHints: Array<string>,
userPolicies: Record<SELF_POLICY, boolean>
): boolean =>
displayHints.includes(DISPLAY_HINTS.RECORDING_CONTROL_RESUME) &&
(displayHints.includes(DISPLAY_HINTS.RECORDING_CONTROL_RESUME) ||
displayHints.includes(DISPLAY_HINTS.PREMISE_RECORDING_CONTROL_RESUME)) &&
MeetingUtil.selfSupportsFeature(SELF_POLICY.SUPPORT_NETWORK_BASED_RECORD, userPolicies);

const canUserStop = (
displayHints: Array<string>,
userPolicies: Record<SELF_POLICY, boolean>
): boolean =>
displayHints.includes(DISPLAY_HINTS.RECORDING_CONTROL_STOP) &&
(displayHints.includes(DISPLAY_HINTS.RECORDING_CONTROL_STOP) ||
displayHints.includes(DISPLAY_HINTS.PREMISE_RECORDING_CONTROL_STOP)) &&
MeetingUtil.selfSupportsFeature(SELF_POLICY.SUPPORT_NETWORK_BASED_RECORD, userPolicies);

const isPremiseRecordingEnabled = (
displayHints: Array<string>,
userPolicies: Record<SELF_POLICY, boolean>
): boolean =>
(displayHints.includes(DISPLAY_HINTS.PREMISE_RECORDING_CONTROL_START) ||
displayHints.includes(DISPLAY_HINTS.PREMISE_RECORDING_CONTROL_PAUSE) ||
displayHints.includes(DISPLAY_HINTS.PREMISE_RECORDING_CONTROL_STOP) ||
displayHints.includes(DISPLAY_HINTS.PREMISE_RECORDING_CONTROL_RESUME)) &&
MeetingUtil.selfSupportsFeature(SELF_POLICY.SUPPORT_NETWORK_BASED_RECORD, userPolicies);

const extractLocusId = (url: string) => {
Expand Down Expand Up @@ -70,6 +84,7 @@ export default {
canUserPause,
canUserResume,
canUserStop,
isPremiseRecordingEnabled,
deriveRecordingStates,
extractLocusId,
};
48 changes: 40 additions & 8 deletions packages/@webex/plugin-meetings/src/webinar/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@
*/
import {WebexPlugin} from '@webex/webex-core';
import {get} from 'lodash';
import {MEETINGS, SELF_ROLES} from '../constants';
import {HTTP_VERBS, MEETINGS, SELF_ROLES} from '../constants';

import WebinarCollection from './collection';
import LoggerProxy from '../common/logs/logger-proxy';

/**
* @class Webinar
Expand All @@ -22,6 +23,7 @@ const Webinar = WebexPlugin.extend({
canManageWebcast: 'boolean', // appears the ability to manage webcast
selfIsPanelist: 'boolean', // self is panelist
selfIsAttendee: 'boolean', // self is attendee
practiceSessionEnabled: 'boolean', // practice session enabled
},

/**
Expand Down Expand Up @@ -59,18 +61,48 @@ const Webinar = WebexPlugin.extend({
* @returns {{isPromoted: boolean, isDemoted: boolean}} Role transition states
*/
updateRoleChanged(payload) {
const oldRoles = get(payload, 'oldRoles', []);
const newRoles = get(payload, 'newRoles', []);

const isPromoted =
get(payload, 'oldRoles', []).includes(SELF_ROLES.ATTENDEE) &&
get(payload, 'newRoles', []).includes(SELF_ROLES.PANELIST);
oldRoles.includes(SELF_ROLES.ATTENDEE) && newRoles.includes(SELF_ROLES.PANELIST);
const isDemoted =
get(payload, 'oldRoles', []).includes(SELF_ROLES.PANELIST) &&
get(payload, 'newRoles', []).includes(SELF_ROLES.ATTENDEE);
this.set('selfIsPanelist', get(payload, 'newRoles', []).includes(SELF_ROLES.PANELIST));
this.set('selfIsAttendee', get(payload, 'newRoles', []).includes(SELF_ROLES.ATTENDEE));
this.updateCanManageWebcast(get(payload, 'newRoles', []).includes(SELF_ROLES.MODERATOR));
oldRoles.includes(SELF_ROLES.PANELIST) && newRoles.includes(SELF_ROLES.ATTENDEE);
this.set('selfIsPanelist', newRoles.includes(SELF_ROLES.PANELIST));
this.set('selfIsAttendee', newRoles.includes(SELF_ROLES.ATTENDEE));
this.updateCanManageWebcast(newRoles.includes(SELF_ROLES.MODERATOR));

return {isPromoted, isDemoted};
},

/**
* start or stop practice session for webinar
* @param {boolean} enabled
* @returns {Promise}
*/
setPracticeSessionState(enabled) {
return this.request({
method: HTTP_VERBS.PATCH,
uri: `${this.locusUrl}/controls`,
body: {
practiceSession: {
enabled,
},
},
}).catch((error) => {
LoggerProxy.logger.error('Meeting:webinar#setPracticeSessionState failed', error);
throw error;
});
},

/**
* update practice session status
* @param {object} payload
* @returns {void}
*/
updatePracticeSessionStatus(payload) {
this.set('practiceSessionEnabled', payload.enabled);
},
});

export default Webinar;
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ describe('plugin-meetings', () => {
canStartManualCaption: null,
canStopManualCaption: null,
isManualCaptionActive: null,
isPremiseRecordingEnabled: null,
isSaveTranscriptsEnabled: null,
isWebexAssistantActive: null,
canViewCaptionPanel: null,
Expand Down Expand Up @@ -88,6 +89,11 @@ describe('plugin-meetings', () => {
canShowStageView: null,
canEnableStageView: null,
canDisableStageView: null,
isPracticeSessionOn : null,
isPracticeSessionOff : null,
canStartPracticeSession: null,
canStopPracticeSession: null,

...expected,
};

Expand Down Expand Up @@ -126,6 +132,7 @@ describe('plugin-meetings', () => {
'canStartManualCaption',
'canStopManualCaption',
'isManualCaptionActive',
'isPremiseRecordingEnabled',
'isSaveTranscriptsEnabled',
'isWebexAssistantActive',
'canViewCaptionPanel',
Expand Down Expand Up @@ -181,7 +188,12 @@ describe('plugin-meetings', () => {
'canShowStageView',
'canEnableStageView',
'canDisableStageView',
].forEach((key) => {
'isPracticeSessionOn',
'isPracticeSessionOff',
'canStartPracticeSession',
'canStopPracticeSession',

].forEach((key) => {
it(`get and set for ${key} work as expected`, () => {
const inMeetingActions = new InMeetingActions();

Expand Down
Loading

0 comments on commit b5ae591

Please sign in to comment.