Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/byods next 1 #3844

Open
wants to merge 32 commits into
base: feat/byods
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
6302094
fix(plugin-meetings): clientSignallingProtocol stat (#3803)
SomeBody16 Sep 4, 2024
d354100
fix(audio-mute): fix sometimes out-of-sync remote audio mute (#3797)
chburket Sep 4, 2024
73e75b7
fix: update internal media core version (#3806)
edvujic Sep 5, 2024
90cc9c2
fix(plugin-meetings): add to peer connection bare turn tcp server (#3…
k-wasniowski Sep 5, 2024
d5da303
fix: update internal media core (#3814)
k-wasniowski Sep 6, 2024
7e6755b
feat:(munge-sdp): updated-sdk-with-latest-media-core (#3815)
adhmenon Sep 9, 2024
77ac358
fix(plugin-authorization): use orgId if emailhash unavailable (#3788)
Coread Sep 9, 2024
6a34e63
feat(webex-core): hostmap interceptor (#3789)
Coread Sep 10, 2024
de15248
feat(contacts): move contacts to scim from dss (#3819)
sreenara Sep 11, 2024
eaa8f48
fix(meetings): sending ice candidate errors with add media success me…
marcin-bazyl Sep 12, 2024
3f6f375
refactor: remove network quality monitor (#3817)
edvujic Sep 12, 2024
8573ece
fix(contacts): handle optional scim fields (#3827)
sreenara Sep 13, 2024
523ae6d
fix(contacts): fix loop and use only resolved contacts from scim (#3829)
sreenara Sep 13, 2024
1de73b3
fix(contacts): use webexapis.com url to avoid cors (#3834)
sreenara Sep 14, 2024
8fa3283
fix(meetings): empty webrtc dumps when user closes the browser early …
marcin-bazyl Sep 16, 2024
cd652ad
docs(samples): add support for locus calls and resolve join button is…
RAM1232 Sep 16, 2024
9bb81a2
fix(meetings): webrtc dumps are sometimes empty when users join a mee…
marcin-bazyl Sep 16, 2024
4c321d2
Upstreamsvcs (#3832)
chrisadubois Sep 16, 2024
d927e6f
fix(plugin-meetings): add retry mechanism to fetching clusters (#3813)
k-wasniowski Sep 17, 2024
11f97f5
feat(meetings): do ip version detection in parallel with reachability…
marcin-bazyl Sep 17, 2024
c04a29f
feat(calling): update failover logic for cc (#3805)
rarajes2 Sep 18, 2024
e42b390
feat(callhistory): add-support-for-multiline-in-callhistory (#3816)
akulakum Sep 18, 2024
ce687dc
Merge branch 'next' into feat/byods-next-1
bhabalan Sep 18, 2024
15d6e91
Operational buisness metrics (#3818)
covidal-cisco Sep 19, 2024
1eaba02
feat(contacts): add the resolved field to contacts (#3848)
sreenara Sep 23, 2024
0af7097
feat(presence-plugin): pass label to aphelia API whilst setting statu…
CormacGCisco Sep 24, 2024
b93ddef
fix(meetings): added reachability trigger to metrics (#3850)
marcin-bazyl Sep 24, 2024
8f8e880
fix(media-effects): include fix for sluggy video in background tab (#…
sreenara Sep 26, 2024
0bf3d24
fix(meetings): webex.internal.device doesn't know when user is in a m…
marcin-bazyl Sep 26, 2024
19c6bf5
fix: update internal-media-core with conditional device permissions f…
antsukanova Sep 27, 2024
40a9120
Merge branch 'webex:next' into feat/byods-next-1
bhabalan Sep 27, 2024
f319209
Merge branch 'feat/byods' into feat/byods-next-1
bhabalan Oct 1, 2024
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
22 changes: 21 additions & 1 deletion docs/samples/browser-plugin-meetings/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,7 @@ const passwordCaptchaStatusElm = document.querySelector('#password-captcha-statu
const refreshCaptchaElm = document.querySelector('#meetings-join-captcha-refresh');
const verifyPasswordElm = document.querySelector('#btn-verify-password');
const displayMeetingStatusElm = document.querySelector('#display-meeting-status');
const notes=document.querySelector('#notes');
const spaceIDError = `Using the space ID as a destination is no longer supported. Please refer to the <a href="https://github.com/webex/webex-js-sdk/wiki/Migration-to-Unified-Space-Meetings" target="_blank">migration guide</a> to migrate to use the meeting ID or SIP address.`;
const BNR = 'BNR';
const VBG = 'VBG';
Expand Down Expand Up @@ -381,6 +382,17 @@ createMeetingSelectElm.addEventListener('change', (event) => {
}
});

createMeetingSelectElm.addEventListener('change', (event) => {
if (event.target.value === 'Others') {
notes.classList.remove('hidden');
}
else {
notes.classList.add('hidden');

}
});


function createMeeting(e) {
e.preventDefault();

Expand Down Expand Up @@ -427,19 +439,26 @@ function refreshCaptcha() {
meetingsListElm.onclick = (e) => {
selectedMeetingId = e.target.value;
const meeting = webex.meetings.getAllMeetings()[selectedMeetingId];
const selectedMeetingType = createMeetingSelectElm.options[createMeetingSelectElm.selectedIndex].innerText;

if (meeting && meeting.passwordStatus === 'REQUIRED') {
meetingsJoinPinElm.disabled = false;
verifyPasswordElm.disabled = false;
document.getElementById('btn-join').disabled = true;
document.getElementById('btn-join-media').disabled = true;
}
else if (meeting && meeting.passwordStatus === 'UNKNOWN') {
else if (meeting && (meeting.passwordStatus === 'UNKNOWN' && selectedMeetingType === 'SIP URI')) {
meetingsJoinPinElm.disabled = true;
verifyPasswordElm.disabled = true;
document.getElementById('btn-join').disabled = true;
document.getElementById('btn-join-media').disabled = true;
}
else if(meeting && (meeting.passwordStatus === 'UNKNOWN' && selectedMeetingType != 'SIP URI')) {
meetingsJoinPinElm.disabled = true;
verifyPasswordElm.disabled = true;
document.getElementById('btn-join').disabled = false;
document.getElementById('btn-join-media').disabled = false;
}
else {
meetingsJoinPinElm.disabled = true;
verifyPasswordElm.disabled = true;
Expand Down Expand Up @@ -1387,6 +1406,7 @@ async function handleVbg() {
"bgImageUrl": blurVBGImageUrl,
"bgVideoUrl": blurVBGVideoUrl,
env: integrationEnv.checked ? 'int' : 'prod',
preventBackgroundThrottling: true,
});
handleEffectsButton(toggleVbgBtn, VBG, effect);
await localMedia.cameraStream.addEffect(effect);
Expand Down
4 changes: 2 additions & 2 deletions docs/samples/browser-plugin-meetings/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -338,14 +338,14 @@ <h2 class="collapsible">
<input id="create-meeting-destination" name="createMeetingDestination" placeholder="Destination"
value="" type="text" required>
<select name="createMeetingDest" id="createMeetingDest">
<option value="">Email</option>
<option value="">Person ID</option>
<option value="">SIP URI</option>
<option value="CONVERSATION_URL">Conversation URL</option>
<option value="Others">Others</option>
</select>
<button id="create-meeting-action" type="submit" class="btn-code">Create Meeting</button>
</div>
</div>
<p class="note hidden" id="notes">NOTE: The destination shall be "Person ID" or "Email".</p>
</form>
</div>

Expand Down
4 changes: 4 additions & 0 deletions docs/samples/calling/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -1301,6 +1301,10 @@ async function createCustomContact() {
type: 'work',
value: formData.get('phone')
}],
emails: [{
type: 'work',
value: formData.get('email')
}],
contactType: 'CUSTOM',
};
const res = await contacts.createContact(contact);
Expand Down
6 changes: 6 additions & 0 deletions packages/@webex/internal-plugin-device/src/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@ export default {
* @type {boolean}
*/
ephemeralDeviceTTL: 30 * 60,

/**
* energyForcast
* @type {boolean}
*/
energyForecast: false,
},

/**
Expand Down
27 changes: 27 additions & 0 deletions packages/@webex/internal-plugin-device/src/device.js
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,14 @@ const Device = WebexPlugin.extend({
*/
isReachabilityChecked: ['boolean', false, false],

/**
* This property stores whether or not the next refresh or register request should request energy forecast data
* in order to prevent over fetching energy forecasts
*
* @type {boolean}
*/
energyForecastConfig: 'boolean',

/**
* This property stores whether or not the current device is in a meeting
* to prevent an unneeded timeout of a meeting due to inactivity.
Expand Down Expand Up @@ -344,6 +352,15 @@ const Device = WebexPlugin.extend({
this.webex.trigger('meeting ended');
},

/**
* Set the value of energy forecast config for the current registered device.
* @param {boolean} [energyForecastConfig=false] - fetch an energy forecast on the next refresh/register
* @returns {void}
*/
setEnergyForecastConfig(energyForecastConfig = false) {
this.energyForecastConfig = energyForecastConfig;
},

// Registration method members

/* eslint-disable require-jsdoc */
Expand Down Expand Up @@ -395,6 +412,11 @@ const Device = WebexPlugin.extend({
uri: this.url,
body,
headers,
qs: {
includeUpstreamServices: `all${
this.config.energyForecast && this.energyForecastConfig ? ',energyforecast' : ''
}`,
},
})
.then((response) => this.processRegistrationSuccess(response))
.catch((reason) => {
Expand Down Expand Up @@ -464,6 +486,11 @@ const Device = WebexPlugin.extend({
resource: 'devices',
body,
headers,
qs: {
includeUpstreamServices: `all${
this.config.energyForecast && this.energyForecastConfig ? ',energyforecast' : ''
}`,
},
})
.catch((error) => {
this.webex.internal.newMetrics.submitInternalEvent({
Expand Down
68 changes: 66 additions & 2 deletions packages/@webex/internal-plugin-device/test/unit/spec/device.js
Original file line number Diff line number Diff line change
Expand Up @@ -176,11 +176,14 @@ describe('plugin-device', () => {
describe('#refresh()', () => {
let requestSpy;

const setup = () => {
const setup = (config = {}) => {
sinon.stub(device, 'canRegister').callsFake(() => Promise.resolve());
sinon.stub(device, 'processRegistrationSuccess').callsFake(() => {});
requestSpy = sinon.spy(device, 'request');
device.config.defaults = {};
Object.keys((config)).forEach((key) => {
device.config[key] = config[key];
});
device.set('registered', true);
};

Expand All @@ -207,15 +210,40 @@ describe('plugin-device', () => {

assert.deepEqual(requestSpy.args[0][0].headers, {});
});

it('uses the energy forecast config to append upstream services to the outgoing call', async () => {
setup({energyForecast: true});
device.setEnergyForecastConfig(true);

await device.register();

assert.calledWith(requestSpy, sinon.match({
qs: { includeUpstreamServices: 'all,energyforecast' }
}))
});

it('uses the energy forecast config to not append upstream services to the outgoing call', async () => {
setup({energyForecast: true});
device.setEnergyForecastConfig(false);

await device.register();

assert.calledWith(requestSpy, sinon.match({
qs: { includeUpstreamServices: 'all' }
}))
});
});

describe('#register()', () => {
const setup = () => {
const setup = (config = {}) => {
webex.internal.metrics.submitClientMetrics = sinon.stub();

sinon.stub(device, 'processRegistrationSuccess').callsFake(() => {});

device.config.defaults = {};
Object.keys(config).forEach((key) => {
device.config[key] = config[key];
});
device.set('registered', false);
};

Expand Down Expand Up @@ -284,6 +312,42 @@ describe('plugin-device', () => {

});

it('uses the energy forecast config to append upstream services to the outgoing call', async () => {
setup({energyForecast: true});
sinon.stub(device, 'canRegister').callsFake(() => Promise.resolve());
const spy = sinon.spy(device, 'request');
device.setEnergyForecastConfig(true);

await device.register();

assert.calledWith(spy, {
method: 'POST',
service: 'wdm',
resource: 'devices',
body: {},
headers: {},
qs: { includeUpstreamServices: 'all,energyforecast' }
} )
});

it('uses the energy forecast config to not append upstream services to the outgoing call', async () => {
setup({energyForecast: true});
sinon.stub(device, 'canRegister').callsFake(() => Promise.resolve());
const spy = sinon.spy(device, 'request');
device.setEnergyForecastConfig(false);

await device.register();

assert.calledWith(spy, {
method: 'POST',
service: 'wdm',
resource: 'devices',
body: {},
headers: {},
qs: { includeUpstreamServices: 'all' }
} )
});

});

describe('#processRegistrationSuccess()', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import {MetricEventProduct, MetricEventAgent, MetricEventVerb, EventPayload} from './metrics.types';
import GenericMetrics from './generic-metrics';

/**
* @description Util class to handle Behavioral Metrics
* @export
* @class BehavioralMetrics
*/
export default class BehavioralMetrics extends GenericMetrics {
/**
* Submit a behavioral metric to our metrics endpoint.
* @param {MetricEventProduct} product the product from which the metric is being submitted, e.g. 'webex' web client, 'wxcc_desktop'
* @param {MetricEventAgent} agent the source of the action for this metric
* @param {string} target the 'thing' that this metric includes information about
* @param {MetricEventVerb} verb the action that this metric includes information about
* @param {EventPayload} payload information specific to this event. This should be flat, i.e. it should not include nested objects.
* @returns {Promise<any>}
*/
public submitBehavioralEvent({
product,
agent,
target,
verb,
payload,
}: {
product: MetricEventProduct;
agent: MetricEventAgent;
target: string;
verb: MetricEventVerb;
payload?: EventPayload;
}) {
const name = `${product}.${agent}.${target}.${verb}`;
const event = this.createTaggedEventObject({
type: ['behavioral'],
name,
payload,
});
this.submitEvent({kind: 'behavioral-events -> ', name, event});
}
}
Loading
Loading