frontend: add toggle functionality for room status with UI updates
This commit is contained in:
parent
1af8f77b7b
commit
089877959a
@ -349,6 +349,16 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
<mat-divider id="actions-divider-{{ room.roomId }}"></mat-divider>
|
<mat-divider id="actions-divider-{{ room.roomId }}"></mat-divider>
|
||||||
|
|
||||||
|
<button
|
||||||
|
mat-menu-item
|
||||||
|
(click)="toggleRoomStatus(room)"
|
||||||
|
[ngClass]="getRoomToggleIconClass(room)"
|
||||||
|
id="toggle-room-status-btn-{{ room.roomId }}"
|
||||||
|
>
|
||||||
|
<mat-icon>{{ getRoomToggleIcon(room) }}</mat-icon>
|
||||||
|
<span>{{ getRoomToggleLabel(room) }}</span>
|
||||||
|
</button>
|
||||||
<button
|
<button
|
||||||
mat-menu-item
|
mat-menu-item
|
||||||
(click)="deleteRoom(room)"
|
(click)="deleteRoom(room)"
|
||||||
|
|||||||
@ -225,6 +225,7 @@
|
|||||||
&:hover {
|
&:hover {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.primary-action {
|
&.primary-action {
|
||||||
color: var(--ov-meet-color-primary);
|
color: var(--ov-meet-color-primary);
|
||||||
}
|
}
|
||||||
@ -247,6 +248,22 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.close-room-icon {
|
||||||
|
color: var(--ov-meet-color-warning) !important;
|
||||||
|
|
||||||
|
.mat-icon {
|
||||||
|
color: var(--ov-meet-color-warning) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.open-room-icon {
|
||||||
|
color: var(--ov-meet-color-success) !important;
|
||||||
|
|
||||||
|
.mat-icon {
|
||||||
|
color: var(--ov-meet-color-success) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.delete-action {
|
.delete-action {
|
||||||
@extend .ov-delete-action;
|
@extend .ov-delete-action;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -35,6 +35,8 @@ export interface RoomTableAction {
|
|||||||
| 'copyModeratorLink'
|
| 'copyModeratorLink'
|
||||||
| 'copySpeakerLink'
|
| 'copySpeakerLink'
|
||||||
| 'viewRecordings'
|
| 'viewRecordings'
|
||||||
|
| 'reopen'
|
||||||
|
| 'close'
|
||||||
| 'delete'
|
| 'delete'
|
||||||
| 'bulkDelete';
|
| 'bulkDelete';
|
||||||
}
|
}
|
||||||
@ -263,6 +265,14 @@ export class RoomsListsComponent implements OnInit, OnChanges {
|
|||||||
this.roomAction.emit({ rooms: [room], action: 'viewRecordings' });
|
this.roomAction.emit({ rooms: [room], action: 'viewRecordings' });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toggleRoomStatus(room: MeetRoom) {
|
||||||
|
if (room.status !== MeetRoomStatus.CLOSED) {
|
||||||
|
this.roomAction.emit({ rooms: [room], action: 'close' });
|
||||||
|
} else {
|
||||||
|
this.roomAction.emit({ rooms: [room], action: 'reopen' });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
deleteRoom(room: MeetRoom) {
|
deleteRoom(room: MeetRoom) {
|
||||||
this.roomAction.emit({ rooms: [room], action: 'delete' });
|
this.roomAction.emit({ rooms: [room], action: 'delete' });
|
||||||
}
|
}
|
||||||
@ -410,4 +420,18 @@ export class RoomsListsComponent implements OnInit, OnChanges {
|
|||||||
getAutoDeletionClass(room: MeetRoom): string {
|
getAutoDeletionClass(room: MeetRoom): string {
|
||||||
return room.autoDeletionDate ? 'auto-deletion-scheduled' : 'auto-deletion-disabled';
|
return room.autoDeletionDate ? 'auto-deletion-scheduled' : 'auto-deletion-disabled';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ===== ROOM TOGGLE =====
|
||||||
|
|
||||||
|
getRoomToggleIcon(room: MeetRoom): string {
|
||||||
|
return room.status !== MeetRoomStatus.CLOSED ? 'lock' : 'meeting_room';
|
||||||
|
}
|
||||||
|
|
||||||
|
getRoomToggleLabel(room: MeetRoom): string {
|
||||||
|
return room.status !== MeetRoomStatus.CLOSED ? 'Close Room' : 'Open Room';
|
||||||
|
}
|
||||||
|
|
||||||
|
getRoomToggleIconClass(room: MeetRoom): string {
|
||||||
|
return room.status !== MeetRoomStatus.CLOSED ? 'close-room-icon' : 'open-room-icon';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,7 +16,7 @@ import { MatTooltipModule } from '@angular/material/tooltip';
|
|||||||
import { RouterModule } from '@angular/router';
|
import { RouterModule } from '@angular/router';
|
||||||
import { RoomsListsComponent, RoomTableAction } from '@lib/components';
|
import { RoomsListsComponent, RoomTableAction } from '@lib/components';
|
||||||
import { NavigationService, NotificationService, RoomService } from '@lib/services';
|
import { NavigationService, NotificationService, RoomService } from '@lib/services';
|
||||||
import { MeetingEndAction, MeetRoom, MeetRoomFilters } from '@lib/typings/ce';
|
import { MeetingEndAction, MeetRoom, MeetRoomFilters, MeetRoomStatus } from '@lib/typings/ce';
|
||||||
import { ILogger, LoggerService } from 'openvidu-components-angular';
|
import { ILogger, LoggerService } from 'openvidu-components-angular';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@ -108,6 +108,12 @@ export class RoomsComponent implements OnInit {
|
|||||||
case 'viewRecordings':
|
case 'viewRecordings':
|
||||||
await this.viewRecordings(action.rooms[0]);
|
await this.viewRecordings(action.rooms[0]);
|
||||||
break;
|
break;
|
||||||
|
case 'reopen':
|
||||||
|
this.reopenRoom(action.rooms[0]);
|
||||||
|
break;
|
||||||
|
case 'close':
|
||||||
|
this.closeRoom(action.rooms[0]);
|
||||||
|
break;
|
||||||
case 'delete':
|
case 'delete':
|
||||||
this.deleteRoom(action.rooms[0]);
|
this.deleteRoom(action.rooms[0]);
|
||||||
break;
|
break;
|
||||||
@ -265,6 +271,40 @@ export class RoomsComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async reopenRoom(room: MeetRoom) {
|
||||||
|
try {
|
||||||
|
const { room: updatedRoom } = await this.roomService.updateRoomStatus(room.roomId, MeetRoomStatus.OPEN);
|
||||||
|
|
||||||
|
// Update room in the list
|
||||||
|
this.rooms.set(this.rooms().map((r) => (r.roomId === updatedRoom.roomId ? updatedRoom : r)));
|
||||||
|
this.notificationService.showSnackbar('Room reopened successfully');
|
||||||
|
} catch (error) {
|
||||||
|
this.notificationService.showSnackbar('Failed to reopen room');
|
||||||
|
this.log.e('Error reopening room:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async closeRoom(room: MeetRoom) {
|
||||||
|
try {
|
||||||
|
const { statusCode, room: updatedRoom } = await this.roomService.updateRoomStatus(
|
||||||
|
room.roomId,
|
||||||
|
MeetRoomStatus.CLOSED
|
||||||
|
);
|
||||||
|
|
||||||
|
// Update room in the list
|
||||||
|
this.rooms.set(this.rooms().map((r) => (r.roomId === updatedRoom.roomId ? updatedRoom : r)));
|
||||||
|
|
||||||
|
if (statusCode === 202) {
|
||||||
|
this.notificationService.showSnackbar('Room scheduled to be closed when the meeting ends');
|
||||||
|
} else {
|
||||||
|
this.notificationService.showSnackbar('Room closed successfully');
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
this.notificationService.showSnackbar('Failed to close room');
|
||||||
|
this.log.e('Error closing room:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private deleteRoom({ roomId }: MeetRoom) {
|
private deleteRoom({ roomId }: MeetRoom) {
|
||||||
const deleteCallback = async () => {
|
const deleteCallback = async () => {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@ -42,7 +42,7 @@ export class GlobalPreferencesService {
|
|||||||
|
|
||||||
async saveSecurityPreferences(preferences: SecurityPreferences) {
|
async saveSecurityPreferences(preferences: SecurityPreferences) {
|
||||||
const path = `${this.PREFERENCES_API}/security`;
|
const path = `${this.PREFERENCES_API}/security`;
|
||||||
await this.httpService.putRequest<SecurityPreferences>(path, preferences);
|
await this.httpService.putRequest(path, preferences);
|
||||||
this.securityPreferences = preferences;
|
this.securityPreferences = preferences;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,7 +58,7 @@ export class GlobalPreferencesService {
|
|||||||
|
|
||||||
async saveWebhookPreferences(preferences: WebhookPreferences) {
|
async saveWebhookPreferences(preferences: WebhookPreferences) {
|
||||||
const path = `${this.PREFERENCES_API}/webhooks`;
|
const path = `${this.PREFERENCES_API}/webhooks`;
|
||||||
await this.httpService.putRequest<WebhookPreferences>(path, preferences);
|
await this.httpService.putRequest(path, preferences);
|
||||||
}
|
}
|
||||||
|
|
||||||
async testWebhookUrl(url: string): Promise<void> {
|
async testWebhookUrl(url: string): Promise<void> {
|
||||||
|
|||||||
@ -24,8 +24,14 @@ export class HttpService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async putRequest<T>(path: string, body: any = {}, headers?: Record<string, string>): Promise<T> {
|
async putRequest<T>(path: string, body: any = {}, headers?: Record<string, string>): Promise<T> {
|
||||||
const options = headers ? { headers: new HttpHeaders(headers) } : {};
|
const options = {
|
||||||
return lastValueFrom(this.http.put<T>(path, body, options));
|
observe: 'response' as const,
|
||||||
|
...(headers ? { headers: new HttpHeaders(headers) } : {})
|
||||||
|
};
|
||||||
|
return lastValueFrom(this.http.put<T>(path, body, options)).then((response) => ({
|
||||||
|
...(response.body as T),
|
||||||
|
statusCode: response.status
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
async patchRequest<T>(path: string, body: any = {}, headers?: Record<string, string>): Promise<T> {
|
async patchRequest<T>(path: string, body: any = {}, headers?: Record<string, string>): Promise<T> {
|
||||||
|
|||||||
@ -5,7 +5,8 @@ import {
|
|||||||
MeetRoomFilters,
|
MeetRoomFilters,
|
||||||
MeetRoomOptions,
|
MeetRoomOptions,
|
||||||
MeetRoomPreferences,
|
MeetRoomPreferences,
|
||||||
MeetRoomRoleAndPermissions
|
MeetRoomRoleAndPermissions,
|
||||||
|
MeetRoomStatus
|
||||||
} from '@lib/typings/ce';
|
} from '@lib/typings/ce';
|
||||||
import { LoggerService } from 'openvidu-components-angular';
|
import { LoggerService } from 'openvidu-components-angular';
|
||||||
|
|
||||||
@ -104,11 +105,23 @@ export class RoomService {
|
|||||||
* @return A promise that resolves to the MeetRoom object
|
* @return A promise that resolves to the MeetRoom object
|
||||||
*/
|
*/
|
||||||
async getRoom(roomId: string): Promise<MeetRoom> {
|
async getRoom(roomId: string): Promise<MeetRoom> {
|
||||||
let path = `${this.ROOMS_API}/${roomId}`;
|
const path = `${this.ROOMS_API}/${roomId}`;
|
||||||
const headers = this.participantService.getParticipantRoleHeader();
|
const headers = this.participantService.getParticipantRoleHeader();
|
||||||
return this.httpService.getRequest(path, headers);
|
return this.httpService.getRequest(path, headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the status of a room.
|
||||||
|
*
|
||||||
|
* @param roomId - The unique identifier of the room
|
||||||
|
* @param status - The new status to be set
|
||||||
|
* @return A promise that resolves to an object containing the updated room and a status code
|
||||||
|
*/
|
||||||
|
async updateRoomStatus(roomId: string, status: MeetRoomStatus): Promise<{ statusCode: number; room: MeetRoom }> {
|
||||||
|
const path = `${this.ROOMS_API}/${roomId}/status`;
|
||||||
|
return this.httpService.putRequest(path, { status });
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes a room by its ID.
|
* Deletes a room by its ID.
|
||||||
*
|
*
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user