frontend: implement room deletion service with confirmation dialog and error handling
This commit is contained in:
parent
5b9fa3149c
commit
f49fd863b7
@ -15,7 +15,7 @@ import { MatSortModule, Sort } from '@angular/material/sort';
|
||||
import { MatTableModule } from '@angular/material/table';
|
||||
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||
import { MEET_ROOM_SORT_FIELDS, MeetRoom, MeetRoomSortField, MeetRoomStatus, SortOrder } from '@openvidu-meet/typings';
|
||||
import { MeetRoom, MeetRoomSortField, MeetRoomStatus, SortOrder } from '@openvidu-meet/typings';
|
||||
import { setsAreEqual } from '../../../../shared/utils/array.utils';
|
||||
import { RoomUiUtils } from '../../utils/ui';
|
||||
|
||||
|
||||
@ -4,15 +4,15 @@ import { CommonModule } from '@angular/common';
|
||||
import { Component, computed, input, output } from '@angular/core';
|
||||
import { ReactiveFormsModule } from '@angular/forms';
|
||||
import { MatStepperModule } from '@angular/material/stepper';
|
||||
import { WizardStep } from '../../models';
|
||||
import { Observable } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { WizardStep } from '../../models';
|
||||
|
||||
@Component({
|
||||
selector: 'ov-step-indicator',
|
||||
imports: [CommonModule, MatStepperModule, ReactiveFormsModule],
|
||||
templateUrl: './step-indicator.component.html',
|
||||
styleUrl: './step-indicator.component.scss'
|
||||
selector: 'ov-step-indicator',
|
||||
imports: [CommonModule, MatStepperModule, ReactiveFormsModule],
|
||||
templateUrl: './step-indicator.component.html',
|
||||
styleUrl: './step-indicator.component.scss'
|
||||
})
|
||||
export class StepIndicatorComponent {
|
||||
steps = input.required<WizardStep[]>();
|
||||
|
||||
@ -3,13 +3,19 @@ import { Component, OnInit, signal } from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatCardModule } from '@angular/material/card';
|
||||
import { MatChipsModule } from '@angular/material/chips';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
||||
import { MatTabsModule } from '@angular/material/tabs';
|
||||
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||
import { ActivatedRoute, Router, RouterModule } from '@angular/router';
|
||||
import { MeetRecordingInfo, MeetRoom, MeetRoomMember, MeetRoomStatus, SortOrder } from '@openvidu-meet/typings';
|
||||
import {
|
||||
MeetRecordingInfo,
|
||||
MeetRoom,
|
||||
MeetRoomDeletionSuccessCode,
|
||||
MeetRoomMember,
|
||||
MeetRoomStatus,
|
||||
SortOrder
|
||||
} from '@openvidu-meet/typings';
|
||||
import { ILogger, LoggerService } from 'openvidu-components-angular';
|
||||
import { BreadcrumbComponent, BreadcrumbItem } from '../../../../shared/components/breadcrumb/breadcrumb.component';
|
||||
import { NavigationService } from '../../../../shared/services/navigation.service';
|
||||
@ -17,8 +23,13 @@ import { NotificationService } from '../../../../shared/services/notification.se
|
||||
import { RecordingListsComponent } from '../../../recordings/components/recording-lists/recording-lists.component';
|
||||
import { RecordingTableAction, RecordingTableFilter } from '../../../recordings/models/recording-list.model';
|
||||
import { RecordingService } from '../../../recordings/services/recording.service';
|
||||
import {
|
||||
MemberTableAction,
|
||||
MemberTableFilter,
|
||||
RoomMembersListsComponent
|
||||
} from '../../../room-members/components/room-members-list/room-members-list.component';
|
||||
import { RoomMemberService } from '../../../room-members/services/room-member.service';
|
||||
import { DeleteRoomDialogComponent } from '../../components/delete-room-dialog/delete-room-dialog.component';
|
||||
import { RoomDeletionService } from '../../services/room-deletion.service';
|
||||
import { RoomService } from '../../services/room.service';
|
||||
import { RoomUiUtils } from '../../utils/ui';
|
||||
|
||||
@ -34,7 +45,8 @@ import { RoomUiUtils } from '../../utils/ui';
|
||||
MatTabsModule,
|
||||
RouterModule,
|
||||
BreadcrumbComponent,
|
||||
RecordingListsComponent
|
||||
RecordingListsComponent,
|
||||
RoomMembersListsComponent
|
||||
],
|
||||
templateUrl: './room-detail.component.html',
|
||||
styleUrl: './room-detail.component.scss'
|
||||
@ -47,6 +59,8 @@ export class RoomDetailComponent implements OnInit {
|
||||
// Room Members tab
|
||||
roomMembers = signal<MeetRoomMember[]>([]);
|
||||
loadingMembers = signal(false);
|
||||
hasMoreMembers = false;
|
||||
private nextMembersPageToken?: string;
|
||||
|
||||
// Recordings tab
|
||||
recordings = signal<MeetRecordingInfo[]>([]);
|
||||
@ -66,12 +80,12 @@ export class RoomDetailComponent implements OnInit {
|
||||
private route: ActivatedRoute,
|
||||
private router: Router,
|
||||
private roomService: RoomService,
|
||||
private roomDeletionService: RoomDeletionService,
|
||||
private roomMemberService: RoomMemberService,
|
||||
private recordingService: RecordingService,
|
||||
private notificationService: NotificationService,
|
||||
protected navigationService: NavigationService,
|
||||
private clipboard: Clipboard,
|
||||
private dialog: MatDialog,
|
||||
protected loggerService: LoggerService
|
||||
) {
|
||||
this.log = this.loggerService.get('OpenVidu Meet - RoomDetailComponent');
|
||||
@ -106,7 +120,7 @@ export class RoomDetailComponent implements OnInit {
|
||||
]);
|
||||
|
||||
// Load initial data for tabs
|
||||
await Promise.all([this.loadRoomMembers(roomId), this.loadRecordings(roomId)]);
|
||||
await Promise.all([this.loadRoomMembers(roomId, undefined), this.loadRecordings(roomId)]);
|
||||
} catch (error) {
|
||||
this.log.e('Error loading room details:', error);
|
||||
this.notificationService.showSnackbar('Failed to load room details');
|
||||
@ -116,15 +130,26 @@ export class RoomDetailComponent implements OnInit {
|
||||
}
|
||||
}
|
||||
|
||||
private async loadRoomMembers(roomId: string) {
|
||||
private async loadRoomMembers(roomId: string, filters?: MemberTableFilter, refresh = false) {
|
||||
try {
|
||||
this.loadingMembers.set(true);
|
||||
const response = await this.roomMemberService.listRoomMembers(roomId, {
|
||||
maxItems: 100,
|
||||
sortField: 'membershipDate',
|
||||
sortOrder: SortOrder.DESC
|
||||
maxItems: 50,
|
||||
nextPageToken: !refresh ? this.nextMembersPageToken : undefined,
|
||||
sortField: filters?.sortField ?? 'membershipDate',
|
||||
sortOrder: filters?.sortOrder ?? SortOrder.DESC,
|
||||
...(filters?.nameFilter ? { name: filters.nameFilter } : {})
|
||||
});
|
||||
this.roomMembers.set(response.members);
|
||||
|
||||
if (!refresh) {
|
||||
const currentMembers = this.roomMembers();
|
||||
this.roomMembers.set([...currentMembers, ...response.members]);
|
||||
} else {
|
||||
this.roomMembers.set(response.members);
|
||||
}
|
||||
|
||||
this.nextMembersPageToken = response.pagination.nextPageToken;
|
||||
this.hasMoreMembers = response.pagination.isTruncated;
|
||||
} catch (error) {
|
||||
this.log.e('Error loading room members:', error);
|
||||
this.notificationService.showSnackbar('Failed to load room members');
|
||||
@ -133,6 +158,89 @@ export class RoomDetailComponent implements OnInit {
|
||||
}
|
||||
}
|
||||
|
||||
async loadMoreRoomMembers(filters: MemberTableFilter) {
|
||||
if (!this.hasMoreMembers || this.loadingMembers()) return;
|
||||
const roomId = this.room()?.roomId;
|
||||
if (roomId) {
|
||||
await this.loadRoomMembers(roomId, filters);
|
||||
}
|
||||
}
|
||||
|
||||
async refreshRoomMembers(filters: MemberTableFilter) {
|
||||
const roomId = this.room()?.roomId;
|
||||
if (roomId) {
|
||||
this.nextMembersPageToken = undefined;
|
||||
await this.loadRoomMembers(roomId, filters, true);
|
||||
}
|
||||
}
|
||||
|
||||
async onMemberAction(action: MemberTableAction) {
|
||||
switch (action.action) {
|
||||
case 'copyLink': {
|
||||
const member = action.members[0];
|
||||
if (member?.accessUrl) {
|
||||
this.clipboard.copy(member.accessUrl);
|
||||
this.notificationService.showSnackbar('Member access URL copied to clipboard');
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'delete': {
|
||||
const member = action.members[0];
|
||||
if (!member) break;
|
||||
this.notificationService.showDialog({
|
||||
title: 'Remove Member',
|
||||
icon: 'person_remove',
|
||||
message: `Are you sure you want to remove <b>${member.name}</b> from this room?`,
|
||||
confirmText: 'Remove',
|
||||
cancelText: 'Cancel',
|
||||
confirmCallback: async () => {
|
||||
try {
|
||||
const roomId = this.room()?.roomId;
|
||||
if (!roomId) return;
|
||||
await this.roomMemberService.deleteRoomMember(roomId, member.memberId);
|
||||
this.roomMembers.set(this.roomMembers().filter((m) => m.memberId !== member.memberId));
|
||||
this.notificationService.showSnackbar('Member removed successfully');
|
||||
} catch (error) {
|
||||
this.log.e('Error removing member:', error);
|
||||
this.notificationService.showSnackbar('Failed to remove member');
|
||||
}
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
case 'bulkDelete': {
|
||||
const memberIds = action.members.map((m) => m.memberId);
|
||||
const roomId = this.room()?.roomId;
|
||||
if (!roomId || memberIds.length === 0) break;
|
||||
this.notificationService.showDialog({
|
||||
title: 'Remove Members',
|
||||
icon: 'group_remove',
|
||||
message: `Are you sure you want to remove <b>${memberIds.length}</b> members from this room?`,
|
||||
confirmText: 'Remove all',
|
||||
cancelText: 'Cancel',
|
||||
confirmCallback: async () => {
|
||||
try {
|
||||
await this.roomMemberService.bulkDeleteRoomMembers(roomId, memberIds);
|
||||
this.roomMembers.set(this.roomMembers().filter((m) => !memberIds.includes(m.memberId)));
|
||||
this.notificationService.showSnackbar('Members removed successfully');
|
||||
} catch (error) {
|
||||
this.log.e('Error removing members:', error);
|
||||
this.notificationService.showSnackbar('Failed to remove members');
|
||||
}
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async onAddMember(): Promise<void> {
|
||||
const roomId = this.room()?.roomId;
|
||||
if (roomId) {
|
||||
await this.navigationService.navigateTo(`/rooms/${roomId}/members/new`);
|
||||
}
|
||||
}
|
||||
|
||||
private async loadRecordings(roomId: string, refresh = false) {
|
||||
try {
|
||||
this.loadingRecordings.set(true);
|
||||
@ -219,31 +327,34 @@ export class RoomDetailComponent implements OnInit {
|
||||
await this.navigationService.navigateTo(`/rooms/${room.roomId}/edit`);
|
||||
}
|
||||
|
||||
async deleteRoom() {
|
||||
deleteRoom() {
|
||||
const room = this.room();
|
||||
if (!room) return;
|
||||
|
||||
const dialogRef = this.dialog.open(DeleteRoomDialogComponent, {
|
||||
data: {
|
||||
rooms: [room],
|
||||
hasMeetings: room.status === MeetRoomStatus.ACTIVE_MEETING,
|
||||
hasRecordings: false // You may need to check this separately
|
||||
},
|
||||
width: '500px',
|
||||
disableClose: true
|
||||
});
|
||||
|
||||
const result = await dialogRef.afterClosed().toPromise();
|
||||
|
||||
if (result?.confirmed) {
|
||||
try {
|
||||
await this.roomService.deleteRoom(room.roomId, result.deletionPolicy);
|
||||
this.notificationService.showSnackbar('Room deleted successfully');
|
||||
await this.navigationService.navigateTo('/rooms');
|
||||
} catch (error) {
|
||||
this.log.e('Error deleting room:', error);
|
||||
this.notificationService.showSnackbar('Failed to delete room');
|
||||
this.roomDeletionService.deleteRoomWithConfirmation({
|
||||
roomId: room.roomId,
|
||||
log: this.log,
|
||||
onSuccess: async ({ successCode, message, room: updatedRoom }) => {
|
||||
await this.handleSuccessfulDeletion(successCode, message, updatedRoom);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private async handleSuccessfulDeletion(
|
||||
successCode: MeetRoomDeletionSuccessCode,
|
||||
message: string,
|
||||
updatedRoom?: MeetRoom
|
||||
) {
|
||||
if (updatedRoom) {
|
||||
// Room was not deleted but updated (e.g., closed due to active meeting)
|
||||
if (successCode === MeetRoomDeletionSuccessCode.ROOM_WITH_ACTIVE_MEETING_CLOSED) {
|
||||
updatedRoom.status = MeetRoomStatus.CLOSED;
|
||||
}
|
||||
this.room.set(updatedRoom);
|
||||
} else {
|
||||
// Room was deleted, navigate back to the rooms list
|
||||
await this.navigationService.navigateTo('/rooms');
|
||||
}
|
||||
this.notificationService.showSnackbar(this.roomDeletionService.removeRoomIdFromMessage(message));
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,7 +17,6 @@ import { MatTooltipModule } from '@angular/material/tooltip';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import {
|
||||
MeetRoom,
|
||||
MeetRoomDeletionErrorCode,
|
||||
MeetRoomDeletionPolicyWithMeeting,
|
||||
MeetRoomDeletionPolicyWithRecordings,
|
||||
MeetRoomDeletionSuccessCode,
|
||||
@ -36,6 +35,7 @@ import {
|
||||
RoomTableAction,
|
||||
RoomTableFilter
|
||||
} from '../../components/rooms-lists/rooms-lists.component';
|
||||
import { RoomDeletionService } from '../../services/room-deletion.service';
|
||||
import { RoomService } from '../../services/room.service';
|
||||
|
||||
@Component({
|
||||
@ -84,6 +84,7 @@ export class RoomsComponent implements OnInit {
|
||||
constructor(
|
||||
protected loggerService: LoggerService,
|
||||
private roomService: RoomService,
|
||||
private roomDeletionService: RoomDeletionService,
|
||||
private notificationService: NotificationService,
|
||||
protected navigationService: NavigationService,
|
||||
private clipboard: Clipboard,
|
||||
@ -270,7 +271,7 @@ export class RoomsComponent implements OnInit {
|
||||
|
||||
// Update room in the list
|
||||
this.rooms.set(this.rooms().map((r) => (r.roomId === updatedRoom.roomId ? updatedRoom : r)));
|
||||
this.notificationService.showSnackbar(this.removeRoomIdFromMessage(message));
|
||||
this.notificationService.showSnackbar(this.roomDeletionService.removeRoomIdFromMessage(message));
|
||||
} catch (error) {
|
||||
this.notificationService.showSnackbar('Failed to close room');
|
||||
this.log.e('Error closing room:', error);
|
||||
@ -278,39 +279,12 @@ export class RoomsComponent implements OnInit {
|
||||
}
|
||||
|
||||
private deleteRoom({ roomId }: MeetRoom) {
|
||||
const deleteCallback = async () => {
|
||||
try {
|
||||
const {
|
||||
successCode,
|
||||
message,
|
||||
room: updatedRoom
|
||||
} = await this.roomService.deleteRoom(
|
||||
roomId,
|
||||
MeetRoomDeletionPolicyWithMeeting.FAIL,
|
||||
MeetRoomDeletionPolicyWithRecordings.FAIL
|
||||
);
|
||||
this.roomDeletionService.deleteRoomWithConfirmation({
|
||||
roomId,
|
||||
log: this.log,
|
||||
onSuccess: ({ room: updatedRoom, successCode, message }) => {
|
||||
this.handleSuccessfulDeletion(roomId, successCode, message, updatedRoom);
|
||||
} catch (error: any) {
|
||||
// Check if errorCode exists and is a valid MeetRoomDeletionErrorCode
|
||||
const errorCode = error.error?.error;
|
||||
if (errorCode && this.isValidMeetRoomDeletionErrorCode(errorCode)) {
|
||||
const errorMessage = this.removeRoomIdFromMessage(error.error.message);
|
||||
this.showDeletionErrorDialogWithOptions(roomId, errorMessage);
|
||||
} else {
|
||||
this.notificationService.showSnackbar('Failed to delete room');
|
||||
this.log.e('Error deleting room:', error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.notificationService.showDialog({
|
||||
title: 'Delete Room',
|
||||
icon: 'delete_outline',
|
||||
message: `Are you sure you want to delete the room <b>${roomId}</b>?`,
|
||||
confirmText: 'Delete',
|
||||
cancelText: 'Cancel',
|
||||
confirmCallback: deleteCallback
|
||||
});
|
||||
}
|
||||
|
||||
@ -332,40 +306,7 @@ export class RoomsComponent implements OnInit {
|
||||
this.rooms.set(this.rooms().filter((r) => r.roomId !== roomId));
|
||||
}
|
||||
|
||||
this.notificationService.showSnackbar(this.removeRoomIdFromMessage(message));
|
||||
}
|
||||
|
||||
private showDeletionErrorDialogWithOptions(roomId: string, errorMessage: string) {
|
||||
const deleteWithPoliciesCallback = async (
|
||||
meetingPolicy: MeetRoomDeletionPolicyWithMeeting,
|
||||
recordingPolicy: MeetRoomDeletionPolicyWithRecordings
|
||||
) => {
|
||||
try {
|
||||
const {
|
||||
successCode,
|
||||
message,
|
||||
room: updatedRoom
|
||||
} = await this.roomService.deleteRoom(roomId, meetingPolicy, recordingPolicy);
|
||||
this.handleSuccessfulDeletion(roomId, successCode, message, updatedRoom);
|
||||
} catch (error) {
|
||||
// If it fails again, just show a snackbar
|
||||
this.notificationService.showSnackbar('Failed to delete room');
|
||||
this.log.e('Error in second deletion attempt:', error);
|
||||
}
|
||||
};
|
||||
|
||||
const dialogOptions: DeleteRoomDialogOptions = {
|
||||
title: 'Error Deleting Room',
|
||||
message: errorMessage,
|
||||
confirmText: 'Delete with Options',
|
||||
showWithMeetingPolicy: true,
|
||||
showWithRecordingsPolicy: true,
|
||||
confirmCallback: deleteWithPoliciesCallback
|
||||
};
|
||||
this.dialog.open(DeleteRoomDialogComponent, {
|
||||
data: dialogOptions,
|
||||
disableClose: true
|
||||
});
|
||||
this.notificationService.showSnackbar(this.roomDeletionService.removeRoomIdFromMessage(message));
|
||||
}
|
||||
|
||||
private bulkDeleteRooms(rooms: MeetRoom[]) {
|
||||
@ -390,7 +331,7 @@ export class RoomsComponent implements OnInit {
|
||||
this.handleSuccessfulBulkDeletion(successful);
|
||||
|
||||
const hasRoomDeletionError = failed.some((result) =>
|
||||
this.isValidMeetRoomDeletionErrorCode(result.error)
|
||||
this.roomDeletionService.isValidDeletionErrorCode(result.error)
|
||||
);
|
||||
if (hasRoomDeletionError) {
|
||||
this.showBulkDeletionErrorDialogWithOptions(failed, errorMessage);
|
||||
@ -507,30 +448,4 @@ export class RoomsComponent implements OnInit {
|
||||
});
|
||||
}
|
||||
|
||||
private isValidMeetRoomDeletionErrorCode(errorCode: string): boolean {
|
||||
const validErrorCodes = [
|
||||
MeetRoomDeletionErrorCode.ROOM_HAS_ACTIVE_MEETING,
|
||||
MeetRoomDeletionErrorCode.ROOM_HAS_RECORDINGS,
|
||||
MeetRoomDeletionErrorCode.ROOM_WITH_ACTIVE_MEETING_HAS_RECORDINGS,
|
||||
MeetRoomDeletionErrorCode.ROOM_WITH_ACTIVE_MEETING_HAS_RECORDINGS_CANNOT_SCHEDULE_DELETION,
|
||||
MeetRoomDeletionErrorCode.ROOM_WITH_RECORDINGS_HAS_ACTIVE_MEETING
|
||||
];
|
||||
return validErrorCodes.includes(errorCode as MeetRoomDeletionErrorCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the room ID from API response messages to create generic messages.
|
||||
*
|
||||
* @param message - The original message from the API response
|
||||
* @returns The message without the specific room ID
|
||||
*/
|
||||
private removeRoomIdFromMessage(message: string): string {
|
||||
// Pattern to match room ID in single quotes: 'room-id'
|
||||
const roomIdPattern = /'[^']+'/g;
|
||||
let filteredMessage = message.replace(roomIdPattern, '');
|
||||
|
||||
// Clean up any double spaces that might result from the replacement
|
||||
filteredMessage = filteredMessage.replace(/\s+/g, ' ').trim();
|
||||
return filteredMessage;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
export * from './room-deletion.service';
|
||||
export * from './room-feature.service';
|
||||
export * from './room.service';
|
||||
export * from './wizard-state.service';
|
||||
|
||||
@ -0,0 +1,130 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import {
|
||||
MeetRoom,
|
||||
MeetRoomDeletionErrorCode,
|
||||
MeetRoomDeletionPolicyWithMeeting,
|
||||
MeetRoomDeletionPolicyWithRecordings,
|
||||
MeetRoomDeletionSuccessCode
|
||||
} from '@openvidu-meet/typings';
|
||||
import { ILogger } from 'openvidu-components-angular';
|
||||
import { DeleteRoomDialogOptions } from '../../../shared/models/notification.model';
|
||||
import { NotificationService } from '../../../shared/services/notification.service';
|
||||
import { DeleteRoomDialogComponent } from '../components/delete-room-dialog/delete-room-dialog.component';
|
||||
import { RoomService } from './room.service';
|
||||
|
||||
interface RoomDeletionResult {
|
||||
roomId: string;
|
||||
successCode: MeetRoomDeletionSuccessCode;
|
||||
message: string;
|
||||
room?: MeetRoom;
|
||||
}
|
||||
|
||||
interface RoomDeletionOptions {
|
||||
roomId: string;
|
||||
log: ILogger;
|
||||
onSuccess: (result: RoomDeletionResult) => void | Promise<void>;
|
||||
}
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class RoomDeletionService {
|
||||
constructor(
|
||||
private roomService: RoomService,
|
||||
private notificationService: NotificationService,
|
||||
private dialog: MatDialog
|
||||
) {}
|
||||
|
||||
deleteRoomWithConfirmation({ roomId, log, onSuccess }: RoomDeletionOptions): void {
|
||||
const deleteCallback = async () => {
|
||||
await this.deleteRoomWithDefaultPolicies(roomId, log, onSuccess);
|
||||
};
|
||||
|
||||
this.notificationService.showDialog({
|
||||
title: 'Delete Room',
|
||||
icon: 'delete_outline',
|
||||
message: `Are you sure you want to delete the room <b>${roomId}</b>?`,
|
||||
confirmText: 'Delete',
|
||||
cancelText: 'Cancel',
|
||||
confirmCallback: deleteCallback
|
||||
});
|
||||
}
|
||||
|
||||
isValidDeletionErrorCode(errorCode: string): boolean {
|
||||
const validErrorCodes = [
|
||||
MeetRoomDeletionErrorCode.ROOM_HAS_ACTIVE_MEETING,
|
||||
MeetRoomDeletionErrorCode.ROOM_HAS_RECORDINGS,
|
||||
MeetRoomDeletionErrorCode.ROOM_WITH_ACTIVE_MEETING_HAS_RECORDINGS,
|
||||
MeetRoomDeletionErrorCode.ROOM_WITH_ACTIVE_MEETING_HAS_RECORDINGS_CANNOT_SCHEDULE_DELETION,
|
||||
MeetRoomDeletionErrorCode.ROOM_WITH_RECORDINGS_HAS_ACTIVE_MEETING
|
||||
];
|
||||
return validErrorCodes.includes(errorCode as MeetRoomDeletionErrorCode);
|
||||
}
|
||||
|
||||
removeRoomIdFromMessage(message: string): string {
|
||||
const roomIdPattern = /'[^']+'/g;
|
||||
let filteredMessage = message.replace(roomIdPattern, '');
|
||||
filteredMessage = filteredMessage.replace(/\s+/g, ' ').trim();
|
||||
return filteredMessage;
|
||||
}
|
||||
|
||||
private async deleteRoomWithDefaultPolicies(
|
||||
roomId: string,
|
||||
log: ILogger,
|
||||
onSuccess: (result: RoomDeletionResult) => void | Promise<void>
|
||||
) {
|
||||
try {
|
||||
const { successCode, message, room } = await this.roomService.deleteRoom(
|
||||
roomId,
|
||||
MeetRoomDeletionPolicyWithMeeting.FAIL,
|
||||
MeetRoomDeletionPolicyWithRecordings.FAIL
|
||||
);
|
||||
|
||||
await onSuccess({ roomId, successCode, message, room });
|
||||
} catch (error: any) {
|
||||
const errorCode = error.error?.error;
|
||||
if (errorCode && this.isValidDeletionErrorCode(errorCode)) {
|
||||
const errorMessage = this.removeRoomIdFromMessage(error.error.message);
|
||||
this.showDeletionErrorDialogWithOptions(roomId, errorMessage, log, onSuccess);
|
||||
} else {
|
||||
this.notificationService.showSnackbar('Failed to delete room');
|
||||
log.e('Error deleting room:', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private showDeletionErrorDialogWithOptions(
|
||||
roomId: string,
|
||||
errorMessage: string,
|
||||
log: ILogger,
|
||||
onSuccess: (result: RoomDeletionResult) => void | Promise<void>
|
||||
): void {
|
||||
const deleteWithPoliciesCallback = async (
|
||||
meetingPolicy: MeetRoomDeletionPolicyWithMeeting,
|
||||
recordingPolicy: MeetRoomDeletionPolicyWithRecordings
|
||||
) => {
|
||||
try {
|
||||
const { successCode, message, room } = await this.roomService.deleteRoom(roomId, meetingPolicy, recordingPolicy);
|
||||
await onSuccess({ roomId, successCode, message, room });
|
||||
} catch (error) {
|
||||
this.notificationService.showSnackbar('Failed to delete room');
|
||||
log.e('Error in second deletion attempt:', error);
|
||||
}
|
||||
};
|
||||
|
||||
const dialogOptions: DeleteRoomDialogOptions = {
|
||||
title: 'Error Deleting Room',
|
||||
message: errorMessage,
|
||||
confirmText: 'Delete with Options',
|
||||
showWithMeetingPolicy: true,
|
||||
showWithRecordingsPolicy: true,
|
||||
confirmCallback: deleteWithPoliciesCallback
|
||||
};
|
||||
|
||||
this.dialog.open(DeleteRoomDialogComponent, {
|
||||
data: dialogOptions,
|
||||
disableClose: true
|
||||
});
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user