frontend: enhance participant role management with original role tracking
This commit is contained in:
parent
a636ad485f
commit
f1fc2e0ba4
@ -3,22 +3,37 @@ import { ParticipantModel, ParticipantProperties } from 'openvidu-components-ang
|
|||||||
|
|
||||||
// Represents a participant in the application.
|
// Represents a participant in the application.
|
||||||
export class CustomParticipantModel extends ParticipantModel {
|
export class CustomParticipantModel extends ParticipantModel {
|
||||||
// Indicates the role of the participant.
|
// Indicates the original role of the participant.
|
||||||
|
private _meetOriginalRole: ParticipantRole;
|
||||||
|
// Indicates the current role of the participant.
|
||||||
private _meetRole: ParticipantRole;
|
private _meetRole: ParticipantRole;
|
||||||
|
|
||||||
constructor(props: ParticipantProperties) {
|
constructor(props: ParticipantProperties) {
|
||||||
super(props);
|
super(props);
|
||||||
const participant = props.participant;
|
const participant = props.participant;
|
||||||
this._meetRole = extractParticipantRole(participant.metadata);
|
this._meetOriginalRole = extractParticipantRole(participant.metadata);
|
||||||
|
this._meetRole = this._meetOriginalRole;
|
||||||
}
|
}
|
||||||
|
|
||||||
set meetRole(role: ParticipantRole) {
|
set meetRole(role: ParticipantRole) {
|
||||||
this._meetRole = role;
|
this._meetRole = role;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the current role of the participant is moderator.
|
||||||
|
* @returns True if the current role is moderator, false otherwise.
|
||||||
|
*/
|
||||||
isModerator(): boolean {
|
isModerator(): boolean {
|
||||||
return this._meetRole === ParticipantRole.MODERATOR;
|
return this._meetRole === ParticipantRole.MODERATOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the original role of the participant is moderator.
|
||||||
|
* @returns True if the original role is moderator, false otherwise.
|
||||||
|
*/
|
||||||
|
isOriginalModerator(): boolean {
|
||||||
|
return this._meetOriginalRole === ParticipantRole.MODERATOR;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const extractParticipantRole = (metadata: any): ParticipantRole => {
|
const extractParticipantRole = (metadata: any): ParticipantRole => {
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
@if (showMeeting) {
|
@if (showMeeting) {
|
||||||
<ov-videoconference
|
<ov-videoconference
|
||||||
[token]="participantToken"
|
[token]="participantToken"
|
||||||
|
|
||||||
[prejoin]="true"
|
[prejoin]="true"
|
||||||
[prejoinDisplayParticipantName]="false"
|
[prejoinDisplayParticipantName]="false"
|
||||||
[videoEnabled]="features().videoEnabled"
|
[videoEnabled]="features().videoEnabled"
|
||||||
@ -39,9 +38,9 @@
|
|||||||
(onRecordingStopRequested)="onRecordingStopRequested($event)"
|
(onRecordingStopRequested)="onRecordingStopRequested($event)"
|
||||||
(onViewRecordingsClicked)="onViewRecordingsClicked()"
|
(onViewRecordingsClicked)="onViewRecordingsClicked()"
|
||||||
>
|
>
|
||||||
@if (features().canModerateRoom) {
|
<ng-container *ovToolbarAdditionalButtons>
|
||||||
<div *ovToolbarAdditionalButtons>
|
<!-- Copy Link Button -->
|
||||||
<!-- Copy Link Button -->
|
@if (features().canModerateRoom) {
|
||||||
<button
|
<button
|
||||||
id="copy-speaker-link"
|
id="copy-speaker-link"
|
||||||
mat-icon-button
|
mat-icon-button
|
||||||
@ -74,32 +73,34 @@
|
|||||||
<span>End meeting for all</span>
|
<span>End meeting for all</span>
|
||||||
</button>
|
</button>
|
||||||
</mat-menu>
|
</mat-menu>
|
||||||
</div>
|
}
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
<div *ovParticipantPanelAfterLocalParticipant>
|
<ng-container *ovParticipantPanelAfterLocalParticipant>
|
||||||
|
@if (features().canModerateRoom) {
|
||||||
<div class="share-meeting-link-container">
|
<div class="share-meeting-link-container">
|
||||||
<ov-share-meeting-link
|
<ov-share-meeting-link
|
||||||
[meetingUrl]="hostname + '/room/' + roomId"
|
[meetingUrl]="hostname + '/room/' + roomId"
|
||||||
(copyClicked)="copySpeakerLink()"
|
(copyClicked)="copySpeakerLink()"
|
||||||
></ov-share-meeting-link>
|
></ov-share-meeting-link>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
}
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
<ng-container *ovLayoutAdditionalElements>
|
<ng-container *ovLayoutAdditionalElements>
|
||||||
@if (remoteParticipants.length === 0) {
|
@if (features().canModerateRoom && remoteParticipants.length === 0) {
|
||||||
<div class="main-share-meeting-link-container fade-in-delayed-more">
|
<div class="main-share-meeting-link-container fade-in-delayed-more">
|
||||||
<ov-share-meeting-link
|
<ov-share-meeting-link
|
||||||
[title]="'Start collaborating'"
|
[title]="'Start collaborating'"
|
||||||
[subtitle]="'Share this link to bring others into the meeting'"
|
[subtitle]="'Share this link to bring others into the meeting'"
|
||||||
[titleSize]="'xl'"
|
[titleSize]="'xl'"
|
||||||
[titleWeight]="'bold'"
|
[titleWeight]="'bold'"
|
||||||
[meetingUrl]="hostname + '/room/' + roomId"
|
[meetingUrl]="hostname + '/room/' + roomId"
|
||||||
(copyClicked)="copySpeakerLink()"
|
(copyClicked)="copySpeakerLink()"
|
||||||
></ov-share-meeting-link>
|
></ov-share-meeting-link>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</ng-container>
|
</ng-container>
|
||||||
}
|
|
||||||
|
|
||||||
<ng-container *ovParticipantPanelItem="let participant">
|
<ng-container *ovParticipantPanelItem="let participant">
|
||||||
<!-- If Meet participant is moderator -->
|
<!-- If Meet participant is moderator -->
|
||||||
@ -130,25 +131,52 @@
|
|||||||
}
|
}
|
||||||
<div *ovParticipantPanelItemElements>
|
<div *ovParticipantPanelItemElements>
|
||||||
<!-- Button to make moderator if not -->
|
<!-- Button to make moderator if not -->
|
||||||
@if (!participant.isModerator()) {
|
@if (localParticipant!.isOriginalModerator()) {
|
||||||
|
@if (participant.isModerator() && !participant.isOriginalModerator()) {
|
||||||
|
<button
|
||||||
|
mat-icon-button
|
||||||
|
(click)="unmakeModerator(participant)"
|
||||||
|
matTooltip="Remove participant moderator"
|
||||||
|
class="remove-moderator-btn"
|
||||||
|
>
|
||||||
|
<mat-icon class="material-symbols-outlined">remove_moderator</mat-icon>
|
||||||
|
</button>
|
||||||
|
} @else {
|
||||||
|
@if (!participant.isModerator()) {
|
||||||
|
<button
|
||||||
|
mat-icon-button
|
||||||
|
(click)="makeModerator(participant)"
|
||||||
|
matTooltip="Make participant moderator"
|
||||||
|
class="make-moderator-btn"
|
||||||
|
>
|
||||||
|
<mat-icon class="material-symbols-outlined">add_moderator</mat-icon>
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} @else {
|
||||||
|
@if (!participant.isModerator()) {
|
||||||
|
<button
|
||||||
|
mat-icon-button
|
||||||
|
(click)="makeModerator(participant)"
|
||||||
|
matTooltip="Make participant moderator"
|
||||||
|
class="make-moderator-btn"
|
||||||
|
>
|
||||||
|
<mat-icon class="material-symbols-outlined">add_moderator</mat-icon>
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
<!-- Button to kick participant -->
|
||||||
|
@if (!participant.isOriginalModerator()) {
|
||||||
<button
|
<button
|
||||||
mat-icon-button
|
mat-icon-button
|
||||||
(click)="makeModerator(participant)"
|
(click)="kickParticipant(participant)"
|
||||||
matTooltip="Make participant moderator"
|
matTooltip="Kick participant"
|
||||||
class="make-moderator-btn"
|
class="force-disconnect-btn"
|
||||||
>
|
>
|
||||||
<mat-icon class="material-symbols-outlined">add_moderator</mat-icon>
|
<mat-icon>call_end</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
}
|
}
|
||||||
<!-- Button to kick participant -->
|
|
||||||
<button
|
|
||||||
mat-icon-button
|
|
||||||
(click)="kickParticipant(participant)"
|
|
||||||
matTooltip="Kick participant"
|
|
||||||
class="force-disconnect-btn"
|
|
||||||
>
|
|
||||||
<mat-icon>call_end</mat-icon>
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</ov-participant-panel-item>
|
</ov-participant-panel-item>
|
||||||
}
|
}
|
||||||
@ -172,7 +200,7 @@
|
|||||||
</ng-container>
|
</ng-container>
|
||||||
</ov-videoconference>
|
</ov-videoconference>
|
||||||
} @else {
|
} @else {
|
||||||
<!-- Move this logic to prejoin meeting page -->
|
<!-- Move this logic to lobby meeting page -->
|
||||||
<div class="ov-page-container">
|
<div class="ov-page-container">
|
||||||
<div class="room-access-container fade-in">
|
<div class="room-access-container fade-in">
|
||||||
<!-- Header Section -->
|
<!-- Header Section -->
|
||||||
|
|||||||
@ -492,6 +492,10 @@ export class MeetingComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Makes a participant as moderator.
|
||||||
|
* @param participant The participant to make as moderator.
|
||||||
|
*/
|
||||||
async makeModerator(participant: CustomParticipantModel) {
|
async makeModerator(participant: CustomParticipantModel) {
|
||||||
if (!this.participantService.isModeratorParticipant()) return;
|
if (!this.participantService.isModeratorParticipant()) return;
|
||||||
|
|
||||||
@ -507,6 +511,25 @@ export class MeetingComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unmakes a participant as moderator.
|
||||||
|
* @param participant The participant to unmake as moderator.
|
||||||
|
*/
|
||||||
|
async unmakeModerator(participant: CustomParticipantModel) {
|
||||||
|
if (!this.participantService.isModeratorParticipant()) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
await this.meetingService.changeParticipantRole(
|
||||||
|
this.roomId,
|
||||||
|
participant.identity,
|
||||||
|
ParticipantRole.SPEAKER
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error unmaking participant moderator:', error);
|
||||||
|
this.notificationService.showSnackbar('Failed to unmake participant moderator');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async copyModeratorLink() {
|
async copyModeratorLink() {
|
||||||
this.clipboard.copy(this.room!.moderatorRoomUrl);
|
this.clipboard.copy(this.room!.moderatorRoomUrl);
|
||||||
this.notificationService.showSnackbar('Moderator link copied to clipboard');
|
this.notificationService.showSnackbar('Moderator link copied to clipboard');
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user