frontend: enhance room status display and meeting end actions in rooms list
This commit is contained in:
parent
e20713288c
commit
2466acabce
@ -182,22 +182,36 @@
|
||||
<ng-container matColumnDef="status">
|
||||
<th mat-header-cell *matHeaderCellDef id="status-header">Status</th>
|
||||
<td mat-cell *matCellDef="let room" id="status-cell-{{ room.roomId }}">
|
||||
<div
|
||||
class="status-badge"
|
||||
[style.color]="getStatusColor(room)"
|
||||
[matTooltip]="getStatusTooltip(room)"
|
||||
id="status-badge-{{ room.roomId }}"
|
||||
>
|
||||
<mat-icon
|
||||
class="status-icon"
|
||||
<div class="status-container" id="status-container-{{ room.roomId }}">
|
||||
<div
|
||||
class="status-badge"
|
||||
[style.color]="getStatusColor(room)"
|
||||
id="status-icon-{{ room.roomId }}"
|
||||
[matTooltip]="getStatusTooltip(room)"
|
||||
id="status-badge-{{ room.roomId }}"
|
||||
>
|
||||
{{ getStatusIcon(room) }}
|
||||
</mat-icon>
|
||||
<span class="status-label" id="status-label-{{ room.roomId }}">{{
|
||||
getRoomStatus(room)
|
||||
}}</span>
|
||||
<mat-icon
|
||||
class="status-icon"
|
||||
[style.color]="getStatusColor(room)"
|
||||
id="status-icon-{{ room.roomId }}"
|
||||
>
|
||||
{{ getStatusIcon(room) }}
|
||||
</mat-icon>
|
||||
<span class="status-label" id="status-label-{{ room.roomId }}">{{
|
||||
getRoomStatus(room)
|
||||
}}</span>
|
||||
</div>
|
||||
|
||||
<!-- Meeting End Action Info Icon -->
|
||||
@if (hasMeetingEndAction(room)) {
|
||||
<mat-icon
|
||||
class="meeting-end-info-icon"
|
||||
[ngClass]="getMeetingEndActionClass(room)"
|
||||
[matTooltip]="getMeetingEndActionTooltip(room)"
|
||||
id="meeting-end-info-icon-{{ room.roomId }}"
|
||||
>
|
||||
info_outline
|
||||
</mat-icon>
|
||||
}
|
||||
</div>
|
||||
</td>
|
||||
</ng-container>
|
||||
@ -227,52 +241,34 @@
|
||||
<td mat-cell *matCellDef="let room" id="auto-deletion-cell-{{ room.roomId }}">
|
||||
<div class="auto-deletion-content" id="auto-deletion-content-{{ room.roomId }}">
|
||||
<div class="auto-deletion-info" id="auto-deletion-info-{{ room.roomId }}">
|
||||
@if (hasAutoDeletion(room)) {
|
||||
<div
|
||||
class="deletion-badge"
|
||||
[ngClass]="getAutoDeletionClass(room)"
|
||||
[matTooltip]="getAutoDeletionTooltip(room)"
|
||||
id="deletion-badge-{{ room.roomId }}"
|
||||
<div
|
||||
class="deletion-badge"
|
||||
[ngClass]="getAutoDeletionClass(room)"
|
||||
[matTooltip]="getAutoDeletionTooltip(room)"
|
||||
id="deletion-badge-{{ room.roomId }}"
|
||||
>
|
||||
<mat-icon
|
||||
class="deletion-icon material-symbols-outlined"
|
||||
id="deletion-icon-{{ room.roomId }}"
|
||||
>{{ getAutoDeletionIcon(room) }}</mat-icon
|
||||
>
|
||||
<mat-icon
|
||||
class="deletion-icon material-symbols-outlined"
|
||||
id="deletion-icon-{{ room.roomId }}"
|
||||
>{{ getAutoDeletionIcon(room) }}</mat-icon
|
||||
>
|
||||
<span class="deletion-text" id="deletion-text-{{ room.roomId }}">{{
|
||||
getAutoDeletionStatus(room)
|
||||
}}</span>
|
||||
</div>
|
||||
<span class="deletion-text" id="deletion-text-{{ room.roomId }}">{{
|
||||
getAutoDeletionStatus(room)
|
||||
}}</span>
|
||||
</div>
|
||||
|
||||
@if (!room.markedForDeletion) {
|
||||
<div class="deletion-date-time" id="deletion-date-time-{{ room.roomId }}">
|
||||
<div class="deletion-date" id="deletion-date-container-{{ room.roomId }}">
|
||||
<span class="date" id="deletion-date-{{ room.roomId }}">{{
|
||||
room.autoDeletionDate | date: 'mediumDate'
|
||||
}}</span>
|
||||
</div>
|
||||
<div class="deletion-time" id="deletion-time-container-{{ room.roomId }}">
|
||||
<span class="time" id="deletion-time-{{ room.roomId }}">{{
|
||||
room.autoDeletionDate | date: 'shortTime'
|
||||
}}</span>
|
||||
</div>
|
||||
@if (hasAutoDeletion(room)) {
|
||||
<div class="deletion-date-time" id="deletion-date-time-{{ room.roomId }}">
|
||||
<div class="deletion-date" id="deletion-date-container-{{ room.roomId }}">
|
||||
<span class="date" id="deletion-date-{{ room.roomId }}">{{
|
||||
room.autoDeletionDate | date: 'mediumDate'
|
||||
}}</span>
|
||||
</div>
|
||||
<div class="deletion-time" id="deletion-time-container-{{ room.roomId }}">
|
||||
<span class="time" id="deletion-time-{{ room.roomId }}">{{
|
||||
room.autoDeletionDate | date: 'shortTime'
|
||||
}}</span>
|
||||
</div>
|
||||
}
|
||||
} @else {
|
||||
<div
|
||||
class="deletion-badge"
|
||||
[ngClass]="getAutoDeletionClass(room)"
|
||||
[matTooltip]="getAutoDeletionTooltip(room)"
|
||||
id="deletion-badge-{{ room.roomId }}"
|
||||
>
|
||||
<mat-icon
|
||||
class="deletion-icon material-symbols-outlined"
|
||||
id="deletion-icon-{{ room.roomId }}"
|
||||
>{{ getAutoDeletionIcon(room) }}</mat-icon
|
||||
>
|
||||
<span class="deletion-text" id="deletion-text-{{ room.roomId }}">{{
|
||||
getAutoDeletionStatus(room)
|
||||
}}</span>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
@ -333,7 +329,7 @@
|
||||
<span>View Recordings</span>
|
||||
</button>
|
||||
|
||||
@if (!room.markedForDeletion) {
|
||||
@if (canOpenRoom(room)) {
|
||||
<button
|
||||
mat-menu-item
|
||||
(click)="copyModeratorLink(room)"
|
||||
@ -350,18 +346,18 @@
|
||||
<mat-icon>content_copy</mat-icon>
|
||||
<span>Copy Speaker Link</span>
|
||||
</button>
|
||||
|
||||
<mat-divider id="actions-divider-{{ room.roomId }}"></mat-divider>
|
||||
<button
|
||||
mat-menu-item
|
||||
(click)="deleteRoom(room)"
|
||||
class="delete-action"
|
||||
id="delete-room-btn-{{ room.roomId }}"
|
||||
>
|
||||
<mat-icon>delete</mat-icon>
|
||||
<span>Delete room</span>
|
||||
</button>
|
||||
}
|
||||
|
||||
<mat-divider id="actions-divider-{{ room.roomId }}"></mat-divider>
|
||||
<button
|
||||
mat-menu-item
|
||||
(click)="deleteRoom(room)"
|
||||
class="delete-action"
|
||||
id="delete-room-btn-{{ room.roomId }}"
|
||||
>
|
||||
<mat-icon>delete</mat-icon>
|
||||
<span>Delete room</span>
|
||||
</button>
|
||||
</mat-menu>
|
||||
</div>
|
||||
</td>
|
||||
@ -372,7 +368,6 @@
|
||||
mat-row
|
||||
*matRowDef="let row; columns: displayedColumns"
|
||||
[class.selected-row]="isRoomSelected(row)"
|
||||
[class.marked-for-deletion]="row.markedForDeletion"
|
||||
id="table-row-{{ row.roomId }}"
|
||||
></tr>
|
||||
</table>
|
||||
|
||||
@ -109,16 +109,6 @@
|
||||
@extend .actions-cell;
|
||||
}
|
||||
}
|
||||
|
||||
.mat-mdc-row {
|
||||
&.marked-for-deletion {
|
||||
background-color: rgba(244, 67, 54, 0.05);
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(244, 67, 54, 0.1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.room-info {
|
||||
@ -133,6 +123,13 @@
|
||||
}
|
||||
}
|
||||
|
||||
.status-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--ov-meet-spacing-sm);
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.status-badge {
|
||||
@extend .ov-status-badge;
|
||||
padding: var(--ov-meet-spacing-xs) var(--ov-meet-spacing-sm);
|
||||
@ -145,6 +142,18 @@
|
||||
}
|
||||
}
|
||||
|
||||
.meeting-end-info-icon {
|
||||
@include ov-icon(sm);
|
||||
|
||||
&.meeting-end-close {
|
||||
color: var(--ov-meet-color-warning);
|
||||
}
|
||||
|
||||
&.meeting-end-delete {
|
||||
color: var(--ov-meet-color-error);
|
||||
}
|
||||
}
|
||||
|
||||
.date-info {
|
||||
@extend .ov-date-info;
|
||||
}
|
||||
@ -183,15 +192,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.auto-deletion-pending {
|
||||
color: var(--ov-meet-color-warn);
|
||||
|
||||
.deletion-icon {
|
||||
color: var(--ov-meet-color-warn);
|
||||
}
|
||||
}
|
||||
|
||||
.auto-deletion-not-scheduled {
|
||||
.auto-deletion-disabled {
|
||||
color: var(--ov-meet-text-hint);
|
||||
|
||||
.deletion-icon {
|
||||
|
||||
@ -24,8 +24,7 @@ import { MatSelectModule } from '@angular/material/select';
|
||||
import { MatTableModule } from '@angular/material/table';
|
||||
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||
import { MeetRoom } from '@lib/typings/ce';
|
||||
import { debounceTime, distinctUntilChanged } from 'rxjs';
|
||||
import { MeetingEndAction, MeetRoom, MeetRoomStatus } from '@lib/typings/ce';
|
||||
|
||||
export interface RoomTableAction {
|
||||
rooms: MeetRoom[];
|
||||
@ -128,8 +127,9 @@ export class RoomsListsComponent implements OnInit, OnChanges {
|
||||
// Status options
|
||||
statusOptions = [
|
||||
{ value: '', label: 'All statuses' },
|
||||
{ value: 'active', label: 'Active' },
|
||||
{ value: 'inactive', label: 'Inactive' }
|
||||
{ value: 'open', label: 'Open' },
|
||||
{ value: 'active_meeting', label: 'Active Meeting' },
|
||||
{ value: 'closed', label: 'Closed' }
|
||||
];
|
||||
|
||||
constructor() {}
|
||||
@ -228,8 +228,8 @@ export class RoomsListsComponent implements OnInit, OnChanges {
|
||||
return this.selectedRooms().has(room.roomId);
|
||||
}
|
||||
|
||||
canSelectRoom(room: MeetRoom): boolean {
|
||||
return !room.markedForDeletion; // Only active rooms can be selected
|
||||
canSelectRoom(_room: MeetRoom): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
getSelectedRooms(): MeetRoom[] {
|
||||
@ -308,72 +308,106 @@ export class RoomsListsComponent implements OnInit, OnChanges {
|
||||
this.statusFilterControl.setValue('');
|
||||
}
|
||||
|
||||
// ===== STATUS UTILITY METHODS =====
|
||||
|
||||
getRoomStatus(room: MeetRoom): string {
|
||||
return room.markedForDeletion ? 'INACTIVE' : 'ACTIVE';
|
||||
}
|
||||
|
||||
// ===== PERMISSION AND CAPABILITY METHODS =====
|
||||
|
||||
canOpenRoom(room: MeetRoom): boolean {
|
||||
return !room.markedForDeletion;
|
||||
return room.status !== MeetRoomStatus.CLOSED;
|
||||
}
|
||||
|
||||
canEditRoom(room: MeetRoom): boolean {
|
||||
return !room.markedForDeletion;
|
||||
canEditRoom(_room: MeetRoom): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
// ===== UI HELPER METHODS =====
|
||||
|
||||
getStatusIcon(room: MeetRoom): string {
|
||||
return room.markedForDeletion ? 'delete_outline' : 'check_circle';
|
||||
// ===== STATUS =====
|
||||
|
||||
getRoomStatus(room: MeetRoom): string {
|
||||
return room.status.toUpperCase().replace(/_/g, ' ');
|
||||
}
|
||||
|
||||
getStatusColor(room: MeetRoom): string {
|
||||
if (room.markedForDeletion) {
|
||||
return 'var(--ov-meet-color-error)';
|
||||
getStatusIcon(room: MeetRoom): string {
|
||||
switch (room.status) {
|
||||
case MeetRoomStatus.OPEN:
|
||||
return 'meeting_room';
|
||||
case MeetRoomStatus.ACTIVE_MEETING:
|
||||
return 'videocam';
|
||||
case MeetRoomStatus.CLOSED:
|
||||
return 'lock';
|
||||
}
|
||||
return 'var(--ov-meet-color-success)';
|
||||
}
|
||||
|
||||
getStatusTooltip(room: MeetRoom): string {
|
||||
return room.markedForDeletion
|
||||
? 'Room is inactive and marked for deletion'
|
||||
: 'Room is active and accepting participants';
|
||||
switch (room.status) {
|
||||
case MeetRoomStatus.OPEN:
|
||||
return 'Room is open and ready to accept participants';
|
||||
case MeetRoomStatus.ACTIVE_MEETING:
|
||||
return 'A meeting is currently ongoing in this room';
|
||||
case MeetRoomStatus.CLOSED:
|
||||
return 'Room is closed and not accepting participants';
|
||||
}
|
||||
}
|
||||
|
||||
getStatusColor(room: MeetRoom): string {
|
||||
switch (room.status) {
|
||||
case MeetRoomStatus.OPEN:
|
||||
return 'var(--ov-meet-color-success)';
|
||||
case MeetRoomStatus.ACTIVE_MEETING:
|
||||
return 'var(--ov-meet-color-primary)';
|
||||
case MeetRoomStatus.CLOSED:
|
||||
return 'var(--ov-meet-color-warning)';
|
||||
}
|
||||
}
|
||||
|
||||
// ===== MEETING END ACTION INFO =====
|
||||
|
||||
hasMeetingEndAction(room: MeetRoom): boolean {
|
||||
return room.status === MeetRoomStatus.ACTIVE_MEETING && room.meetingEndAction !== MeetingEndAction.NONE;
|
||||
}
|
||||
|
||||
getMeetingEndActionTooltip(room: MeetRoom): string {
|
||||
switch (room.meetingEndAction) {
|
||||
case MeetingEndAction.CLOSE:
|
||||
return 'The room will be closed when the meeting ends';
|
||||
case MeetingEndAction.DELETE:
|
||||
return 'The room and its recordings will be deleted when the meeting ends';
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
getMeetingEndActionClass(room: MeetRoom): string {
|
||||
switch (room.meetingEndAction) {
|
||||
case MeetingEndAction.CLOSE:
|
||||
return 'meeting-end-close';
|
||||
case MeetingEndAction.DELETE:
|
||||
return 'meeting-end-delete';
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
// ===== AUTO-DELETION =====
|
||||
|
||||
hasAutoDeletion(room: MeetRoom): boolean {
|
||||
return !!room.autoDeletionDate;
|
||||
}
|
||||
|
||||
getAutoDeletionStatus(room: MeetRoom): string {
|
||||
if (room.markedForDeletion) {
|
||||
return 'Immediate';
|
||||
}
|
||||
return room.autoDeletionDate ? 'Scheduled' : 'Disabled';
|
||||
return room.autoDeletionDate ? 'SCHEDULED' : 'DISABLED';
|
||||
}
|
||||
|
||||
getAutoDeletionIcon(room: MeetRoom): string {
|
||||
if (room.markedForDeletion) {
|
||||
return 'acute';
|
||||
}
|
||||
return room.autoDeletionDate ? 'auto_delete' : 'close';
|
||||
}
|
||||
|
||||
getAutoDeletionClass(room: MeetRoom): string {
|
||||
if (room.markedForDeletion) {
|
||||
return 'auto-deletion-pending';
|
||||
}
|
||||
return room.autoDeletionDate ? 'auto-deletion-scheduled' : 'auto-deletion-not-scheduled';
|
||||
}
|
||||
|
||||
getAutoDeletionTooltip(room: MeetRoom): string {
|
||||
if (room.markedForDeletion) {
|
||||
return 'Deletes when last participant leaves';
|
||||
}
|
||||
return room.autoDeletionDate
|
||||
? 'Auto-deletion scheduled'
|
||||
: 'No auto-deletion. Room remains until manually deleted';
|
||||
}
|
||||
|
||||
getAutoDeletionClass(room: MeetRoom): string {
|
||||
return room.autoDeletionDate ? 'auto-deletion-scheduled' : 'auto-deletion-disabled';
|
||||
}
|
||||
}
|
||||
|
||||
@ -30,7 +30,7 @@
|
||||
<div class="stat-content">
|
||||
<div class="stat-number">{{ stats.totalRooms }}</div>
|
||||
<div class="stat-label">Total Rooms</div>
|
||||
<div class="stat-detail">{{ stats.activeRooms }} active</div>
|
||||
<div class="stat-detail">{{ stats.activeRooms }} with active meetings</div>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
<mat-card-actions>
|
||||
|
||||
@ -5,7 +5,7 @@ import { MatCardModule } from '@angular/material/card';
|
||||
import { MatGridListModule } from '@angular/material/grid-list';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { NavigationService, RecordingService, RoomService } from '@lib/services';
|
||||
import { MeetRecordingStatus, MeetRoom } from '@lib/typings/ce';
|
||||
import { MeetRecordingStatus, MeetRoom, MeetRoomStatus } from '@lib/typings/ce';
|
||||
|
||||
interface OverviewStats {
|
||||
totalRooms: number;
|
||||
@ -56,7 +56,7 @@ export class OverviewComponent implements OnInit {
|
||||
|
||||
this.stats = {
|
||||
totalRooms: rooms.length,
|
||||
activeRooms: rooms.filter((room: MeetRoom) => !room.markedForDeletion).length,
|
||||
activeRooms: rooms.filter((room: MeetRoom) => room.status === MeetRoomStatus.ACTIVE_MEETING).length,
|
||||
totalRecordings: recordings.length,
|
||||
playableRecordings: recordings.filter((recording) => recording.status === MeetRecordingStatus.COMPLETE)
|
||||
.length,
|
||||
|
||||
@ -16,7 +16,7 @@ import { MatTooltipModule } from '@angular/material/tooltip';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { RoomsListsComponent, RoomTableAction } from '@lib/components';
|
||||
import { NavigationService, NotificationService, RoomService } from '@lib/services';
|
||||
import { MeetRoom, MeetRoomFilters } from '@lib/typings/ce';
|
||||
import { MeetingEndAction, MeetRoom, MeetRoomFilters } from '@lib/typings/ce';
|
||||
import { ILogger, LoggerService } from 'openvidu-components-angular';
|
||||
|
||||
@Component({
|
||||
@ -273,7 +273,9 @@ export class RoomsComponent implements OnInit {
|
||||
// If the room is marked for deletion, we don't remove it from the list immediately
|
||||
const currentRooms = this.rooms();
|
||||
this.rooms.set(
|
||||
currentRooms.map((r) => (r.roomId === roomId ? { ...r, markedForDeletion: true } : r))
|
||||
currentRooms.map((r) =>
|
||||
r.roomId === roomId ? { ...r, meetingEndAction: MeetingEndAction.DELETE } : r
|
||||
)
|
||||
);
|
||||
// this.dataSource.data = this.rooms();
|
||||
this.notificationService.showSnackbar('Room marked for deletion');
|
||||
@ -331,7 +333,7 @@ export class RoomsComponent implements OnInit {
|
||||
// We don't remove them from the list immediately
|
||||
this.rooms.set(
|
||||
currentRooms.map((r) =>
|
||||
roomIds.includes(r.roomId) ? { ...r, markedForDeletion: true } : r
|
||||
roomIds.includes(r.roomId) ? { ...r, meetingEndAction: MeetingEndAction.DELETE } : r
|
||||
)
|
||||
);
|
||||
this.notificationService.showSnackbar('All rooms marked for deletion');
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user