From be224536b2beaa0930ce146b2f090cf92cacb817 Mon Sep 17 00:00:00 2001 From: Allison Chiang Date: Thu, 3 Apr 2025 11:58:50 -0700 Subject: [PATCH 1/6] update calling SDK version and rooms version --- Project/package-lock.json | 8 ++++---- Project/package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Project/package-lock.json b/Project/package-lock.json index 4548312..6115538 100644 --- a/Project/package-lock.json +++ b/Project/package-lock.json @@ -8,7 +8,7 @@ "name": "ACSCallingSample", "version": "1.0.0", "dependencies": { - "@azure/communication-calling": "1.33.2-beta.1", + "@azure/communication-calling": "1.34.1-beta.2", "@azure/communication-calling-effects": "1.1.1-beta.1", "@azure/communication-common": "^2.3.0", "@azure/communication-identity": "^1.3.0", @@ -69,9 +69,9 @@ } }, "node_modules/@azure/communication-calling": { - "version": "1.33.2-beta.1", - "resolved": "https://registry.npmjs.org/@azure/communication-calling/-/communication-calling-1.33.2-beta.1.tgz", - "integrity": "sha512-kwMh8RF65dJkk+SDog+DtMD/UZWxDvObd+OSatBQmsFOX6rwAc5NVik0iyqnLk8bm+5Xdieb6AotQaKDgOd4zg==", + "version": "1.34.1-beta.2", + "resolved": "https://registry.npmjs.org/@azure/communication-calling/-/communication-calling-1.34.1-beta.2.tgz", + "integrity": "sha512-rh2JHu4UekXq/Gc/+hF3i2VCLpZYa6fAl7++ByIG0gp6jUoFkFQfi3wT8ziZbAcp1AbSh7BNy9TQKTQr5V1tzg==", "dependencies": { "@azure/communication-common": "^2.3.0", "@azure/logger": "^1.0.3" diff --git a/Project/package.json b/Project/package.json index f1e85cc..5c0cc14 100644 --- a/Project/package.json +++ b/Project/package.json @@ -3,7 +3,7 @@ "version": "1.0.0", "private": true, "dependencies": { - "@azure/communication-calling": "1.33.2-beta.1", + "@azure/communication-calling": "1.34.1-beta.2", "@azure/communication-calling-effects": "1.1.1-beta.1", "@azure/communication-common": "^2.3.0", "@azure/communication-identity": "^1.3.0", From aa9754c49d2749a1fdc1b9abf1507876d679b3c5 Mon Sep 17 00:00:00 2001 From: Allison Chiang Date: Thu, 3 Apr 2025 11:59:12 -0700 Subject: [PATCH 2/6] change Create Room panel naming --- Project/src/MakeCall/MakeCall.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Project/src/MakeCall/MakeCall.js b/Project/src/MakeCall/MakeCall.js index 822e8bb..dd13e1d 100644 --- a/Project/src/MakeCall/MakeCall.js +++ b/Project/src/MakeCall/MakeCall.js @@ -62,7 +62,7 @@ export default class MakeCall extends React.Component { showPreCallDiagnostcisResults: false, showCustomContext: false, roomId: undefined, - showCreateRoomPanel: false, + showManageRoomsPanel: false, xHeadersCount: 1, xHeadersMaxCount: 5, isPreCallDiagnosticsCallInProgress: false, @@ -1193,15 +1193,16 @@ this.callAgent.on('incomingCall', async (args) => { this.setState({ showCreateRoomPanel: !this.state.showCreateRoomPanel })}> + onClick={() => this.setState({ showManageRoomsPanel: !this.state.showManageRoomsPanel })}> { - this.state.showCreateRoomPanel && + this.state.showManageRoomsPanel &&
-

Create a Room

+

Manage Rooms

+

Create a Room

Date: Thu, 3 Apr 2025 13:49:23 -0700 Subject: [PATCH 3/6] allow multiple participants to be added to the room including collaborator --- Project/package-lock.json | 8 +++--- Project/package.json | 2 +- Project/src/MakeCall/MakeCall.js | 28 +++++++++++++------- Project/src/Utils/Utils.js | 23 +++++++++++++--- Project/webpack.config.js | 45 +++++++++++++++++++++++--------- 5 files changed, 75 insertions(+), 31 deletions(-) diff --git a/Project/package-lock.json b/Project/package-lock.json index 6115538..bb83cd2 100644 --- a/Project/package-lock.json +++ b/Project/package-lock.json @@ -13,7 +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/communication-rooms": "1.2.0", "@azure/logger": "^1.0.3", "@azure/msal-browser": "^2.33.0", "@azure/msal-node": "^1.17.1", @@ -178,9 +178,9 @@ "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==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@azure/communication-rooms/-/communication-rooms-1.2.0.tgz", + "integrity": "sha512-jT61/d0MCv7UL4AcEf8lhn5qK709NsuEv7iLIIx6jGbs55U/PVe5DQvPm8FG9hb6sUH1oEP9L1BF8LXmfT8pgg==", "dependencies": { "@azure/communication-common": "^2.3.1", "@azure/core-auth": "^1.9.0", diff --git a/Project/package.json b/Project/package.json index 5c0cc14..643548d 100644 --- a/Project/package.json +++ b/Project/package.json @@ -8,7 +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/communication-rooms": "1.2.0", "@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 dd13e1d..f757a79 100644 --- a/Project/src/MakeCall/MakeCall.js +++ b/Project/src/MakeCall/MakeCall.js @@ -34,9 +34,10 @@ export default class MakeCall extends React.Component { this.meetingLink = null; this.meetingId = null; this.passcode = null; - this.presenterUserId = null; - this.attendeeUserId = null; - this.consumerUserId = null; + this.presenterUserIds = null; + this.collaboratorUserIds = null; + this.attendeeUserIds = null; + this.consumerUserIds = null; this.threadId = null; this.messageId = null; this.organizerId = null; @@ -374,7 +375,7 @@ export default class MakeCall extends React.Component { createRoom = async () => { try { - const roomId = await utils.createRoom(this.presenterUserId.value, this.attendeeUserId.value, this.consumerUserId.value); + const roomId = await utils.createRoom(this.presenterUserIds.value,this.collaboratorUserIds.value, this.attendeeUserIds.value, this.consumerUserIds.value); console.log('Room id created: ', roomId); this.setState({ roomId }); } catch (e) { @@ -1207,23 +1208,30 @@ this.callAgent.on('incomingCall', async (args) => {
this.presenterUserId = val} /> + componentRef={(val) => this.presenterUserIds = val} />
this.attendeeUserId = val} /> + componentRef={(val) => this.collaboratorUserIds = val} />
this.consumerUserId = val} /> + componentRef={(val) => this.attendeeUserIds = val} /> +
+
+ this.consumerUserIds = val} />
{ + createRoom: async (presenterUserIds, collaboratorUserIds, attendeeUserIds, consumerUserIds) => { try { + const data = {}; + if (presenterUserIds) { + data.presenterUserIds = presenterUserIds.split(',').map(id => id.trim()); + } + if (collaboratorUserIds) { + data.collaboratorUserIds = collaboratorUserIds.split(',').map(id => id.trim()); + } + if (attendeeUserIds) { + data.attendeeUserIds = attendeeUserIds.split(',').map(id => id.trim()); + } + if (consumerUserIds) { + data.consumerUserIds = consumerUserIds.split(',').map(id => id.trim()); + } + const response = await axios({ url: 'createRoom', method: 'POST', @@ -106,12 +120,13 @@ export const utils = { 'Accept': 'application/json, text/plain, */*', 'Content-type': 'application/json' }, - data: JSON.stringify({ presenterUserId, attendeeUserId, consumerUserId }) - }) - + data: JSON.stringify(data) + }); + console.log('Room created successfully:', response.data); return response.data.roomId; } catch (error) { + console.error('Error creating room:', error); throw error.response.data.message; } }, diff --git a/Project/webpack.config.js b/Project/webpack.config.js index 473e26b..15f0d2a 100644 --- a/Project/webpack.config.js +++ b/Project/webpack.config.js @@ -238,18 +238,39 @@ module.exports = { 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; + console.log('req.body:', req.body); + if (req.body.presenterUserIds && Array.isArray(req.body.presenterUserIds)) { + req.body.presenterUserIds.forEach(presenterUserId => { + participants.push({ + id: { communicationUserId: presenterUserId }, + role: "Presenter" + }); + }); + } + if (req.body.collaboratorUserIds && Array.isArray(req.body.collaboratorUserIds)) { + req.body.collaboratorUserIds.forEach(collaboratorUserId => { + participants.push({ + id: { communicationUserId: collaboratorUserId }, + role: "Collaborator" + }); + }); + } + if (req.body.attendeeUserIds && Array.isArray(req.body.attendeeUserIds)) { + req.body.attendeeUserIds.forEach(attendeeUserId => { + participants.push({ + id: { communicationUserId: attendeeUserId }, + role: "Attendee" + }); + }); + } + if (req.body.consumerUserIds && Array.isArray(req.body.consumerUserIds)) { + req.body.consumerUserIds.forEach(consumerUserId => { + participants.push({ + id: { communicationUserId: consumerUserId }, + role: "Consumer" + }); + }); + } if (participants.length === 0) { res.status(400).json({ From e24306f6be0013ab51ed0fad0a7e82ee0d390042 Mon Sep 17 00:00:00 2001 From: Allison Chiang Date: Thu, 3 Apr 2025 15:29:50 -0700 Subject: [PATCH 4/6] add pstn dialout toggle --- Project/src/MakeCall/MakeCall.js | 14 ++++++++++++-- Project/src/Utils/Utils.js | 2 +- Project/webpack.config.js | 2 +- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/Project/src/MakeCall/MakeCall.js b/Project/src/MakeCall/MakeCall.js index f757a79..017287b 100644 --- a/Project/src/MakeCall/MakeCall.js +++ b/Project/src/MakeCall/MakeCall.js @@ -3,7 +3,7 @@ import { CallClient, LocalVideoStream, Features, CallAgentKind, VideoStreamRende import { AzureCommunicationTokenCredential, createIdentifierFromRawId} from '@azure/communication-common'; import { PrimaryButton } from '@fluentui/react/lib/Button'; import { TextField } from '@fluentui/react/lib/TextField'; -import { MessageBar, MessageBarType } from '@fluentui/react'; +import { MessageBar, MessageBarType, Toggle } from '@fluentui/react'; import { Icon } from '@fluentui/react/lib/Icon'; import IncomingCallCard from './IncomingCallCard'; import CallCard from '../MakeCall/CallCard'; @@ -34,6 +34,7 @@ export default class MakeCall extends React.Component { this.meetingLink = null; this.meetingId = null; this.passcode = null; + this.roomPstnDialOutEnabled = true; this.presenterUserIds = null; this.collaboratorUserIds = null; this.attendeeUserIds = null; @@ -375,7 +376,7 @@ export default class MakeCall extends React.Component { createRoom = async () => { try { - const roomId = await utils.createRoom(this.presenterUserIds.value,this.collaboratorUserIds.value, this.attendeeUserIds.value, this.consumerUserIds.value); + const roomId = await utils.createRoom(this.roomPstnDialOutEnabled, this.presenterUserIds.value, this.collaboratorUserIds.value, this.attendeeUserIds.value, this.consumerUserIds.value); console.log('Room id created: ', roomId); this.setState({ roomId }); } catch (e) { @@ -1205,6 +1206,15 @@ this.callAgent.on('incomingCall', async (args) => {

Manage Rooms

Create a Room

+
+ {this.roomPstnDialOutEnabled = !this.roomPstnDialOutEnabled}} /> +
{ + createRoom: async (pstnDialOutEnabled, presenterUserIds, collaboratorUserIds, attendeeUserIds, consumerUserIds) => { try { const data = {}; if (presenterUserIds) { diff --git a/Project/webpack.config.js b/Project/webpack.config.js index 15f0d2a..5fd967f 100644 --- a/Project/webpack.config.js +++ b/Project/webpack.config.js @@ -282,7 +282,7 @@ module.exports = { console.log('participants:', participants); const validFrom = new Date(Date.now()); const validUntil = new Date(validFrom.getTime() + 60 * 60 * 1000); - const pstnDialOutEnabled = true; + const pstnDialOutEnabled = req.body.pstnDialOutEnabled; const roomsClient = new RoomsClient(config.connectionString); const createRoom = await roomsClient.createRoom({ validFrom, From bd1e16aa90ac1beb3a1738326831951be6455b94 Mon Sep 17 00:00:00 2001 From: Allison Chiang Date: Thu, 3 Apr 2025 15:58:34 -0700 Subject: [PATCH 5/6] add patch participants --- Project/src/MakeCall/MakeCall.js | 51 +++++++++++++++++++++++++++++--- Project/src/Utils/Utils.js | 26 ++++++++++++++++ Project/webpack.config.js | 20 +++++++++++++ 3 files changed, 93 insertions(+), 4 deletions(-) diff --git a/Project/src/MakeCall/MakeCall.js b/Project/src/MakeCall/MakeCall.js index 017287b..96dab18 100644 --- a/Project/src/MakeCall/MakeCall.js +++ b/Project/src/MakeCall/MakeCall.js @@ -39,6 +39,9 @@ export default class MakeCall extends React.Component { this.collaboratorUserIds = null; this.attendeeUserIds = null; this.consumerUserIds = null; + this.patchRoomId = null; + this.patchParticipantId = null; + this.patchParticipantRole = null; this.threadId = null; this.messageId = null; this.organizerId = null; @@ -384,6 +387,15 @@ export default class MakeCall extends React.Component { } }; + updateParticipant = async () => { + try { + await utils.updateParticipant(this.patchRoomId.value, this.patchParticipantId.value, this.patchParticipantRole.value); + console.log('Participant updated successfully'); + } catch (e) { + console.error('Failed to update participant ', e); + } + }; + joinTeamsMeeting = async (withVideo, micMuted = false) => { try { const callOptions = await this.getCallOptions({video: withVideo, micMuted: micMuted}); @@ -1177,7 +1189,7 @@ this.callAgent.on('incomingCall', async (args) => { disabled={this.state.call || !this.state.loggedIn} label="Rooms id" value={ this.state.roomId } - placeholder="" + placeholder="" onChange={(e) => this.setState({ roomId: e.target.value })}/>
@@ -1211,6 +1223,7 @@ this.callAgent.on('incomingCall', async (args) => { disabled={this.state.call || !this.state.loggedIn} checked={this.roomPstnDialOutEnabled} label="PSTN Dial Out Enabled" + inlineLabel="True" onText="True" offText="False" onChange={() => {this.roomPstnDialOutEnabled = !this.roomPstnDialOutEnabled}} /> @@ -1243,13 +1256,43 @@ this.callAgent.on('incomingCall', async (args) => { placeholder="8:acs:_" componentRef={(val) => this.consumerUserIds = val} />
-
- this.createRoom()}> - + + +

Update a Participant

+
+
+ this.patchRoomId = val} /> +
+
+ this.patchParticipantId = val} /> +
+
+ this.patchParticipantRole = val} /> +
+ this.updateParticipant()}> + +
} diff --git a/Project/src/Utils/Utils.js b/Project/src/Utils/Utils.js index 3a2bfa2..28378ea 100644 --- a/Project/src/Utils/Utils.js +++ b/Project/src/Utils/Utils.js @@ -100,6 +100,7 @@ export const utils = { createRoom: async (pstnDialOutEnabled, presenterUserIds, collaboratorUserIds, attendeeUserIds, consumerUserIds) => { try { const data = {}; + data.pstnDialOutEnabled = pstnDialOutEnabled; if (presenterUserIds) { data.presenterUserIds = presenterUserIds.split(',').map(id => id.trim()); } @@ -130,6 +131,31 @@ export const utils = { throw error.response.data.message; } }, + updateParticipant: async (patchRoomId, patchParticipantId, patchParticipantRole) => { + try { + if (!patchRoomId.trim() || !patchParticipantId.trim() || !patchParticipantRole.trim()) { + throw new Error('All parameters (patchRoomId, patchParticipantId, patchParticipantRole) must be non-empty strings without trailing whitespace.'); + } + + const response = await axios({ + url: 'updateParticipant', + method: 'PATCH', + headers: { + 'Accept': 'application/json, text/plain, */*', + 'Content-type': 'application/json' + }, + data: JSON.stringify({ + patchRoomId: patchRoomId.trim(), + patchParticipantId: patchParticipantId.trim(), + patchParticipantRole: patchParticipantRole.trim() + }) + }); + console.log('Participant updated successfully:', response.data); + } catch (error) { + console.error('Error updating participant:', error); + throw error.response?.data?.message || error.message; + } + }, getIdentifierText: (identifier) => { if (isCommunicationUserIdentifier(identifier)) { return identifier.communicationUserId; diff --git a/Project/webpack.config.js b/Project/webpack.config.js index 5fd967f..a67e938 100644 --- a/Project/webpack.config.js +++ b/Project/webpack.config.js @@ -304,6 +304,26 @@ module.exports = { throw e; } }); + devServer.app.patch('/updateParticipant', async (req, res) => { + try { + const roomId = req.body.patchRoomId; + const participantId = req.body.patchParticipantId; + const participantRole = req.body.patchParticipantRole; + const roomsClient = new RoomsClient(config.connectionString); + const participant = [ + { + id: { communicationUserId: participantId}, + role: participantRole, + }, + ]; + await roomsClient.addOrUpdateParticipants(roomId, participant); + res.setHeader('Content-Type', 'application/json'); + res.status(200).json({message: 'Participant updated successfully'}); + } catch (e) { + console.error(e); + throw e; + } + }); return middlewares; } From fc62406ee171882a740f55494246ff97dfbf347c Mon Sep 17 00:00:00 2001 From: Allison Chiang Date: Thu, 3 Apr 2025 16:15:55 -0700 Subject: [PATCH 6/6] fix toggle bug --- Project/src/MakeCall/MakeCall.js | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/Project/src/MakeCall/MakeCall.js b/Project/src/MakeCall/MakeCall.js index 96dab18..b7503ea 100644 --- a/Project/src/MakeCall/MakeCall.js +++ b/Project/src/MakeCall/MakeCall.js @@ -34,7 +34,6 @@ export default class MakeCall extends React.Component { this.meetingLink = null; this.meetingId = null; this.passcode = null; - this.roomPstnDialOutEnabled = true; this.presenterUserIds = null; this.collaboratorUserIds = null; this.attendeeUserIds = null; @@ -67,6 +66,7 @@ export default class MakeCall extends React.Component { showPreCallDiagnostcisResults: false, showCustomContext: false, roomId: undefined, + roomPstnDialOutEnabled: true, showManageRoomsPanel: false, xHeadersCount: 1, xHeadersMaxCount: 5, @@ -379,7 +379,7 @@ export default class MakeCall extends React.Component { createRoom = async () => { try { - const roomId = await utils.createRoom(this.roomPstnDialOutEnabled, this.presenterUserIds.value, this.collaboratorUserIds.value, this.attendeeUserIds.value, this.consumerUserIds.value); + const roomId = await utils.createRoom(this.state.roomPstnDialOutEnabled, this.presenterUserIds.value, this.collaboratorUserIds.value, this.attendeeUserIds.value, this.consumerUserIds.value); console.log('Room id created: ', roomId); this.setState({ roomId }); } catch (e) { @@ -1208,7 +1208,6 @@ this.callAgent.on('incomingCall', async (args) => { this.setState({ showManageRoomsPanel: !this.state.showManageRoomsPanel })}> @@ -1220,38 +1219,35 @@ this.callAgent.on('incomingCall', async (args) => {
{this.roomPstnDialOutEnabled = !this.roomPstnDialOutEnabled}} /> + onClick={() => { + console.log(this.state.roomPstnDialOutEnabled); + this.setState({roomPstnDialOutEnabled: !this.state.roomPstnDialOutEnabled}) + }} />
this.presenterUserIds = val} />
this.collaboratorUserIds = val} />
this.attendeeUserIds = val} />
this.consumerUserIds = val} /> @@ -1259,7 +1255,6 @@ this.callAgent.on('incomingCall', async (args) => { this.createRoom()}>
@@ -1267,21 +1262,18 @@ this.callAgent.on('incomingCall', async (args) => {
this.patchRoomId = val} />
this.patchParticipantId = val} />
this.patchParticipantRole = val} /> @@ -1289,7 +1281,6 @@ this.callAgent.on('incomingCall', async (args) => { this.updateParticipant()}>