diff --git a/Project/package-lock.json b/Project/package-lock.json index 70c965e1..45483121 100644 --- a/Project/package-lock.json +++ b/Project/package-lock.json @@ -13,6 +13,7 @@ "@azure/communication-common": "^2.3.0", "@azure/communication-identity": "^1.3.0", "@azure/communication-network-traversal": "^1.1.0-beta.1", + "@azure/communication-rooms": "1.1.1", "@azure/logger": "^1.0.3", "@azure/msal-browser": "^2.33.0", "@azure/msal-node": "^1.17.1", @@ -86,9 +87,9 @@ } }, "node_modules/@azure/communication-common": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@azure/communication-common/-/communication-common-2.3.0.tgz", - "integrity": "sha512-KqpdV1AsojDcmISMnvv9MTE8lNRcgz+OQukp2mFl/cm4aKjzROrGcSlayU6p9A51knRGwgoS6hXkaUdqU5cXow==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@azure/communication-common/-/communication-common-2.3.1.tgz", + "integrity": "sha512-6ZQt20iMZbyckQn4m1TDwiDv3Fzyt1h4lnQ1szBBns2x3VQY9XHbnskPtvUdwK/HT+c/1PoUwof3toy1AIznbQ==", "dependencies": { "@azure/abort-controller": "^1.0.0", "@azure/core-auth": "^1.3.0", @@ -96,11 +97,11 @@ "@azure/core-tracing": "^1.0.0", "@azure/core-util": "^1.0.0", "events": "^3.0.0", - "jwt-decode": "^3.1.2", + "jwt-decode": "^4.0.0", "tslib": "^2.2.0" }, "engines": { - "node": ">=14.0.0" + "node": ">=18.0.0" } }, "node_modules/@azure/communication-identity": { @@ -176,34 +177,75 @@ "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-2.2.0.tgz", "integrity": "sha512-86GgN2vzfUu7m9Wcj63iUkuDzFNYFVmjeDm2GzWpUk+opB0pEpMsw6ePCMrhYkumz2C1ihqtZzOMAg7FiXcNoQ==" }, + "node_modules/@azure/communication-rooms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@azure/communication-rooms/-/communication-rooms-1.1.1.tgz", + "integrity": "sha512-zz/vEW4CLep8McLzzJd17jmQh4cyKv4kwSEzgZcxaAHO/re17cruD9NyATQ3fpu0FQ7n+4ikYq5ePZB6nIGBlw==", + "dependencies": { + "@azure/communication-common": "^2.3.1", + "@azure/core-auth": "^1.9.0", + "@azure/core-client": "^1.9.2", + "@azure/core-paging": "^1.6.2", + "@azure/core-rest-pipeline": "^1.18.0", + "@azure/core-tracing": "^1.2.0", + "@azure/core-util": "^1.11.0", + "@azure/logger": "^1.1.4", + "tslib": "^2.8.1" + }, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/@azure/core-auth": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@azure/core-auth/-/core-auth-1.5.0.tgz", - "integrity": "sha512-udzoBuYG1VBoHVohDTrvKjyzel34zt77Bhp7dQntVGGD0ehVq48owENbBG8fIgkHRNUBQH5k1r0hpoMu5L8+kw==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@azure/core-auth/-/core-auth-1.9.0.tgz", + "integrity": "sha512-FPwHpZywuyasDSLMqJ6fhbOK3TqUdviZNF8OqRGA4W5Ewib2lEEZ+pBsYcBa88B2NGO/SEnYPGhyBqNlE8ilSw==", "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-util": "^1.1.0", - "tslib": "^2.2.0" + "@azure/abort-controller": "^2.0.0", + "@azure/core-util": "^1.11.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=18.0.0" + } + }, + "node_modules/@azure/core-auth/node_modules/@azure/abort-controller": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz", + "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" } }, "node_modules/@azure/core-client": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/@azure/core-client/-/core-client-1.7.3.tgz", - "integrity": "sha512-kleJ1iUTxcO32Y06dH9Pfi9K4U+Tlb111WXEnbt7R/ne+NLRwppZiTGJuTD5VVoxTMK5NTbEtm5t2vcdNCFe2g==", + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@azure/core-client/-/core-client-1.9.2.tgz", + "integrity": "sha512-kRdry/rav3fUKHl/aDLd/pDLcB+4pOFwPPTVEExuMyaI5r+JBbMWqRbCY1pn5BniDaU3lRxO9eaQ1AmSMehl/w==", "dependencies": { - "@azure/abort-controller": "^1.0.0", + "@azure/abort-controller": "^2.0.0", "@azure/core-auth": "^1.4.0", "@azure/core-rest-pipeline": "^1.9.1", "@azure/core-tracing": "^1.0.0", - "@azure/core-util": "^1.0.0", + "@azure/core-util": "^1.6.1", "@azure/logger": "^1.0.0", - "tslib": "^2.2.0" + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=18.0.0" + } + }, + "node_modules/@azure/core-client/node_modules/@azure/abort-controller": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz", + "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" } }, "node_modules/@azure/core-http": { @@ -258,67 +300,88 @@ } }, "node_modules/@azure/core-paging": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@azure/core-paging/-/core-paging-1.5.0.tgz", - "integrity": "sha512-zqWdVIt+2Z+3wqxEOGzR5hXFZ8MGKK52x4vFLw8n58pR6ZfKRx3EXYTxTaYxYHc/PexPUTyimcTWFJbji9Z6Iw==", + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/@azure/core-paging/-/core-paging-1.6.2.tgz", + "integrity": "sha512-YKWi9YuCU04B55h25cnOYZHxXYtEvQEbKST5vqRga7hWY9ydd3FZHdeQF8pyh+acWZvppw13M/LMGx0LABUVMA==", "dependencies": { - "tslib": "^2.2.0" + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=18.0.0" } }, "node_modules/@azure/core-rest-pipeline": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.12.1.tgz", - "integrity": "sha512-SsyWQ+T5MFQRX+M8H/66AlaI6HyCbQStGfFngx2fuiW+vKI2DkhtOvbYodPyf9fOe/ARLWWc3ohX54lQ5Kmaog==", + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.19.0.tgz", + "integrity": "sha512-bM3308LRyg5g7r3Twprtqww0R/r7+GyVxj4BafcmVPo4WQoGt5JXuaqxHEFjw2o3rvFZcUPiqJMg6WuvEEeVUA==", "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.4.0", + "@azure/abort-controller": "^2.0.0", + "@azure/core-auth": "^1.8.0", "@azure/core-tracing": "^1.0.1", - "@azure/core-util": "^1.3.0", + "@azure/core-util": "^1.11.0", "@azure/logger": "^1.0.0", - "form-data": "^4.0.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "tslib": "^2.2.0" + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=18.0.0" + } + }, + "node_modules/@azure/core-rest-pipeline/node_modules/@azure/abort-controller": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz", + "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" } }, "node_modules/@azure/core-tracing": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@azure/core-tracing/-/core-tracing-1.0.1.tgz", - "integrity": "sha512-I5CGMoLtX+pI17ZdiFJZgxMJApsK6jjfm85hpgp3oazCdq5Wxgh4wMr7ge/TTWW1B5WBuvIOI1fMU/FrOAMKrw==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@azure/core-tracing/-/core-tracing-1.2.0.tgz", + "integrity": "sha512-UKTiEJPkWcESPYJz3X5uKRYyOcJD+4nYph+KpfdPRnQJVrZfk0KJgdnaAWKfhsBBtAf/D58Az4AvCJEmWgIBAg==", "dependencies": { - "tslib": "^2.2.0" + "tslib": "^2.6.2" }, "engines": { - "node": ">=12.0.0" + "node": ">=18.0.0" } }, "node_modules/@azure/core-util": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@azure/core-util/-/core-util-1.5.0.tgz", - "integrity": "sha512-GZBpVFDtQ/15hW1OgBcRdT4Bl7AEpcEZqLfbAvOtm1CQUncKWiYapFHVD588hmlV27NbOOtSm3cnLF3lvoHi4g==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@azure/core-util/-/core-util-1.11.0.tgz", + "integrity": "sha512-DxOSLua+NdpWoSqULhjDyAZTXFdP/LKkqtYuxxz1SCN289zk3OG8UOpnCQAz/tygyACBtWp/BoO72ptK7msY8g==", "dependencies": { - "@azure/abort-controller": "^1.0.0", - "tslib": "^2.2.0" + "@azure/abort-controller": "^2.0.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=18.0.0" + } + }, + "node_modules/@azure/core-util/node_modules/@azure/abort-controller": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz", + "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" } }, "node_modules/@azure/logger": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@azure/logger/-/logger-1.0.4.tgz", - "integrity": "sha512-ustrPY8MryhloQj7OWGe+HrYx+aoiOxzbXTtgblbV3xwCqpzUK36phH3XNHQKj3EPonyFUuDTfR3qFhTEAuZEg==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@azure/logger/-/logger-1.1.4.tgz", + "integrity": "sha512-4IXXzcCdLdlXuCG+8UKEwLA1T1NHqUfanhXYHiQTn+6sfWCZXduqbtXDGceg3Ce5QxTGo7EqmbV6Bi+aqKuClQ==", "dependencies": { - "tslib": "^2.2.0" + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=18.0.0" } }, "node_modules/@azure/msal-browser": { @@ -2590,14 +2653,6 @@ "tslib": "^2.8.0" } }, - "node_modules/@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", - "engines": { - "node": ">= 10" - } - }, "node_modules/@types/body-parser": { "version": "1.19.3", "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.3.tgz", @@ -3069,14 +3124,11 @@ } }, "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dependencies": { - "debug": "4" - }, + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", + "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==", "engines": { - "node": ">= 6.0.0" + "node": ">= 14" } }, "node_modules/ajv": { @@ -4879,16 +4931,15 @@ } }, "node_modules/http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", "dependencies": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" + "agent-base": "^7.1.0", + "debug": "^4.3.4" }, "engines": { - "node": ">= 6" + "node": ">= 14" } }, "node_modules/http-proxy-middleware": { @@ -4916,15 +4967,15 @@ } }, "node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", "dependencies": { - "agent-base": "6", + "agent-base": "^7.1.2", "debug": "4" }, "engines": { - "node": ">= 6" + "node": ">= 14" } }, "node_modules/human-signals": { @@ -5301,9 +5352,12 @@ } }, "node_modules/jwt-decode": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz", - "integrity": "sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A==" + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz", + "integrity": "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==", + "engines": { + "node": ">=18" + } }, "node_modules/kind-of": { "version": "6.0.3", diff --git a/Project/package.json b/Project/package.json index 00d362cf..f1e85cc7 100644 --- a/Project/package.json +++ b/Project/package.json @@ -8,6 +8,7 @@ "@azure/communication-common": "^2.3.0", "@azure/communication-identity": "^1.3.0", "@azure/communication-network-traversal": "^1.1.0-beta.1", + "@azure/communication-rooms": "1.1.1", "@azure/logger": "^1.0.3", "@azure/msal-browser": "^2.33.0", "@azure/msal-node": "^1.17.1", diff --git a/Project/src/MakeCall/MakeCall.js b/Project/src/MakeCall/MakeCall.js index 80d6b247..b9b78f01 100644 --- a/Project/src/MakeCall/MakeCall.js +++ b/Project/src/MakeCall/MakeCall.js @@ -13,6 +13,7 @@ import MediaConstraint from './MediaConstraint'; import { setLogLevel, AzureLogger } from '@azure/logger'; import { inflate } from 'pako'; import { URL_PARAM } from "../Constants"; +import { utils } from "../Utils/Utils"; export default class MakeCall extends React.Component { constructor(props) { super(props); @@ -33,7 +34,9 @@ export default class MakeCall extends React.Component { this.meetingLink = null; this.meetingId = null; this.passcode = null; - this.roomsId = null; + this.presenterUserId = null; + this.attendeeUserId = null; + this.consumerUserId = null; this.threadId = null; this.messageId = null; this.organizerId = null; @@ -58,6 +61,8 @@ export default class MakeCall extends React.Component { showCustomContextSampleCode: false, showPreCallDiagnostcisResults: false, showCustomContext: false, + roomId: undefined, + showCreateRoomPanel: false, xHeadersCount: 1, xHeadersMaxCount: 5, isPreCallDiagnosticsCallInProgress: false, @@ -360,13 +365,23 @@ export default class MakeCall extends React.Component { joinRooms = async (withVideo) => { try { const callOptions = await this.getCallOptions({video: withVideo, micMuted: false}); - this.callAgent.join({ roomId: this.roomsId.value }, callOptions); + this.callAgent.join({ roomId: this.state.roomId }, callOptions); } catch (e) { console.error('Failed to join a call', e); this.setState({ callError: 'Failed to join a call: ' + e }); } }; + createRoom = async () => { + try { + const roomId = await utils.createRoom(this.presenterUserId.value, this.attendeeUserId.value, this.consumerUserId.value); + console.log('Room id created: ', roomId); + this.setState({ roomId }); + } catch (e) { + console.error('Failed to create a room: ', e); + } + }; + joinTeamsMeeting = async (withVideo, micMuted = false) => { try { const callOptions = await this.getCallOptions({video: withVideo, micMuted: micMuted}); @@ -980,7 +995,7 @@ this.callAgent.on('incomingCall', async (args) => { className="mt-0" disabled={this.state.call || !this.state.loggedIn} label={`Enter an Identity to make a call to. You can specify multiple Identities to call by using \",\" separated values.`} - placeholder="8:acs:_" + placeholder="8:acs:_" componentRef={(val) => this.destinationUserIds = val} /> { this.roomsId = val} /> + onChange={(e) => this.setState({ roomId: e.target.value })}/> { disabled={this.state.call || !this.state.loggedIn} onClick={() => this.joinRooms(true)}> + this.setState({ showCreateRoomPanel: !this.state.showCreateRoomPanel })}> + + { + this.state.showCreateRoomPanel && +
+

Create a Room

+
+
+ this.presenterUserId = val} /> +
+
+ this.attendeeUserId = val} /> +
+
+ this.consumerUserId = val} /> +
+
+ this.createRoom()}> + +
+ }
diff --git a/Project/src/Utils/Utils.js b/Project/src/Utils/Utils.js index c03e8268..c01873d9 100644 --- a/Project/src/Utils/Utils.js +++ b/Project/src/Utils/Utils.js @@ -97,6 +97,24 @@ export const utils = { } throw new Error('Failed to get Teams User Acccess token'); }, + createRoom: async (presenterUserId, attendeeUserId, consumerUserId) => { + try { + const response = await axios({ + url: 'createRoom', + method: 'POST', + headers: { + 'Accept': 'application/json, text/plain, */*', + 'Content-type': 'application/json' + }, + data: JSON.stringify({ presenterUserId, attendeeUserId, consumerUserId }) + }) + + return response.data.roomId; + + } catch (error) { + throw error.response.data.message; + } + }, getIdentifierText: (identifier) => { if (isCommunicationUserIdentifier(identifier)) { return identifier.communicationUserId; diff --git a/Project/webpack.config.js b/Project/webpack.config.js index 15ca5c18..473e26b5 100644 --- a/Project/webpack.config.js +++ b/Project/webpack.config.js @@ -1,4 +1,5 @@ const CommunicationIdentityClient = require("@azure/communication-identity").CommunicationIdentityClient; +const { RoomsClient } = require('@azure/communication-rooms'); const HtmlWebPackPlugin = require("html-webpack-plugin"); const config = require("./serverConfig.json"); const clientConfig = require("./clientConfig.json"); @@ -234,6 +235,54 @@ module.exports = { res.sendStatus(400); } }); + devServer.app.post('/createRoom', async (req, res) => { + try { + let participants = []; + req.body.presenterUserId ? participants.push({ + id: { communicationUserId: req.body.presenterUserId }, + role: "Presenter" + }) : null; + req.body.attendeeUserId ? participants.push({ + id: { communicationUserId: req.body.attendeeUserId }, + role: "Attendee" + }) : null; + req.body.consumerUserId ? participants.push({ + id: { communicationUserId: req.body.consumerUserId }, + role: "Consumer" + }) : null; + + if (participants.length === 0) { + res.status(400).json({ + message: "At least one participant must be provided to create a room." + }); + return; + } + + console.log('participants:', participants); + const validFrom = new Date(Date.now()); + const validUntil = new Date(validFrom.getTime() + 60 * 60 * 1000); + const pstnDialOutEnabled = true; + const roomsClient = new RoomsClient(config.connectionString); + const createRoom = await roomsClient.createRoom({ + validFrom, + validUntil, + pstnDialOutEnabled, + participants + }); + const roomId = createRoom.id; + console.log('\nRoom successfully created'); + console.log('Room ID:', roomId); + console.log('Participants:', participants); + + res.setHeader('Content-Type', 'application/json'); + res.status(200).json({ + roomId + }); + } catch (e) { + console.error(e); + throw e; + } + }); return middlewares; }