diff --git a/frontend/projects/shared-meet-components/src/lib/pages/console/rooms/room-wizard/room-wizard.component.scss b/frontend/projects/shared-meet-components/src/lib/pages/console/rooms/room-wizard/room-wizard.component.scss
index 548c478..022dd2e 100644
--- a/frontend/projects/shared-meet-components/src/lib/pages/console/rooms/room-wizard/room-wizard.component.scss
+++ b/frontend/projects/shared-meet-components/src/lib/pages/console/rooms/room-wizard/room-wizard.component.scss
@@ -32,9 +32,16 @@
max-width: 600px;
min-height: 450px;
max-height: 450px;
+ overflow-y: auto;
display: flex;
flex-direction: column;
- justify-content: center;
+ justify-content: flex-start;
+}
+
+.step-content > :first-child {
+ margin: auto 0;
+ width: 100%;
+ min-height: min-content;
}
.wizard-footer {
diff --git a/frontend/projects/shared-meet-components/src/lib/pages/console/rooms/room-wizard/steps/room-details/room-details.component.html b/frontend/projects/shared-meet-components/src/lib/pages/console/rooms/room-wizard/steps/room-details/room-details.component.html
index 54de660..6365f8e 100644
--- a/frontend/projects/shared-meet-components/src/lib/pages/console/rooms/room-wizard/steps/room-details/room-details.component.html
+++ b/frontend/projects/shared-meet-components/src/lib/pages/console/rooms/room-wizard/steps/room-details/room-details.component.html
@@ -4,9 +4,7 @@
video_chat
Room Details
-
- Configure your room's details including name and automatic deletion date
-
+
Configure your room's details including name and automatic deletion date
@@ -59,8 +57,8 @@
@@ -89,6 +87,7 @@
access_time
+
@if (!roomDetailsForm.hasError('minFutureDateTime')) {
auto_delete
@@ -97,6 +96,46 @@
} @else {
Deletion date and time must be at least one hour in the future
}
+
+
+
+
+ policy
+ Auto-deletion Policies
+
+
+ Configure how the room should be handled during auto-deletion if there are active meetings
+ or recordings.
+
+
+
+
+ With Active Meeting Policy
+
+ @for (option of meetingPolicyOptions; track option.value) {
+
+ {{ option.label }}
+
+ }
+
+ groups
+ {{ getMeetingPolicyDescription() }}
+
+
+
+ With Recordings Policy
+
+ @for (option of recordingPolicyOptions; track option.value) {
+
+ {{ option.label }}
+
+ }
+
+ video_library
+ {{ getRecordingPolicyDescription() }}
+
+
+
}
diff --git a/frontend/projects/shared-meet-components/src/lib/pages/console/rooms/room-wizard/steps/room-details/room-details.component.scss b/frontend/projects/shared-meet-components/src/lib/pages/console/rooms/room-wizard/steps/room-details/room-details.component.scss
index cc1f22d..41a78ea 100644
--- a/frontend/projects/shared-meet-components/src/lib/pages/console/rooms/room-wizard/steps/room-details/room-details.component.scss
+++ b/frontend/projects/shared-meet-components/src/lib/pages/console/rooms/room-wizard/steps/room-details/room-details.component.scss
@@ -108,6 +108,51 @@
}
}
+ // Auto-deletion policies styling
+ .auto-deletion-policies {
+ margin-top: var(--ov-meet-spacing-lg);
+
+ .policies-title {
+ display: flex;
+ align-items: center;
+ gap: var(--ov-meet-spacing-xs);
+ margin: 0 0 var(--ov-meet-spacing-xs) 0;
+ font-size: var(--ov-meet-font-size-md);
+ font-weight: var(--ov-meet-font-weight-medium);
+ color: var(--ov-meet-text-primary);
+
+ .policies-icon {
+ @include ov-icon(sm);
+ color: var(--ov-meet-primary);
+ }
+ }
+
+ .policies-description {
+ margin: 0 0 var(--ov-meet-spacing-md) 0;
+ font-size: var(--ov-meet-font-size-sm);
+ color: var(--ov-meet-text-secondary);
+ line-height: var(--ov-meet-line-height-relaxed);
+ }
+
+ .policies-row {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ gap: var(--ov-meet-spacing-md);
+
+ .policy-field {
+ width: 100%;
+
+ ::ng-deep {
+ .mat-mdc-form-field-hint {
+ font-size: var(--ov-meet-font-size-xs);
+ color: var(--ov-meet-text-hint);
+ line-height: var(--ov-meet-line-height-tight);
+ }
+ }
+ }
+ }
+ }
+
.time-hint {
display: flex;
align-items: center;
@@ -163,6 +208,13 @@
display: none; // Hide separator in mobile vertical layout
}
}
+
+ .auto-deletion-policies {
+ .policies-row {
+ grid-template-columns: 1fr;
+ gap: var(--ov-meet-spacing-sm);
+ }
+ }
}
}
}
diff --git a/frontend/projects/shared-meet-components/src/lib/pages/console/rooms/room-wizard/steps/room-details/room-details.component.ts b/frontend/projects/shared-meet-components/src/lib/pages/console/rooms/room-wizard/steps/room-details/room-details.component.ts
index 7705bc7..f22a266 100644
--- a/frontend/projects/shared-meet-components/src/lib/pages/console/rooms/room-wizard/steps/room-details/room-details.component.ts
+++ b/frontend/projects/shared-meet-components/src/lib/pages/console/rooms/room-wizard/steps/room-details/room-details.component.ts
@@ -9,7 +9,12 @@ import { MatInputModule } from '@angular/material/input';
import { MatSelectModule } from '@angular/material/select';
import { MatTooltipModule } from '@angular/material/tooltip';
import { RoomWizardStateService } from '@lib/services';
-import { MeetRoomOptions } from '@lib/typings/ce';
+import {
+ MeetRoomAutoDeletionPolicy,
+ MeetRoomDeletionPolicyWithMeeting,
+ MeetRoomDeletionPolicyWithRecordings,
+ MeetRoomOptions
+} from '@lib/typings/ce';
import { Subject, takeUntil } from 'rxjs';
@Component({
@@ -36,6 +41,32 @@ export class RoomWizardRoomDetailsComponent implements OnDestroy {
hours = Array.from({ length: 24 }, (_, i) => ({ value: i, display: i.toString().padStart(2, '0') }));
minutes = Array.from({ length: 60 }, (_, i) => ({ value: i, display: i.toString().padStart(2, '0') }));
+ meetingPolicyOptions = [
+ {
+ value: MeetRoomDeletionPolicyWithMeeting.FORCE,
+ label: 'Force',
+ description:
+ 'The meeting will be ended, and the room will be deleted without waiting for participants to leave.'
+ },
+ {
+ value: MeetRoomDeletionPolicyWithMeeting.WHEN_MEETING_ENDS,
+ label: 'When meeting ends',
+ description: 'The room will be deleted when the meeting ends.'
+ }
+ ];
+ recordingPolicyOptions = [
+ {
+ value: MeetRoomDeletionPolicyWithRecordings.FORCE,
+ label: 'Force',
+ description: 'The room and its recordings will be deleted.'
+ },
+ {
+ value: MeetRoomDeletionPolicyWithRecordings.CLOSE,
+ label: 'Close',
+ description: 'The room will be closed instead of deleted, maintaining its recordings.'
+ }
+ ];
+
private destroy$ = new Subject
();
constructor(private wizardService: RoomWizardStateService) {
@@ -54,20 +85,29 @@ export class RoomWizardRoomDetailsComponent implements OnDestroy {
private saveFormData(formValue: any) {
let autoDeletionDateTime: number | undefined = undefined;
+ let autoDeletionPolicy: MeetRoomAutoDeletionPolicy | undefined = undefined;
- // If date is selected, combine it with time
+ // If date is selected
if (formValue.autoDeletionDate) {
+ // Combine date with time
const date = new Date(formValue.autoDeletionDate);
date.setHours(formValue.autoDeletionHour || 23);
date.setMinutes(formValue.autoDeletionMinute || 59);
date.setSeconds(0);
date.setMilliseconds(0);
autoDeletionDateTime = date.getTime();
+
+ // Set auto deletion policy
+ autoDeletionPolicy = {
+ withMeeting: formValue.autoDeletionPolicyWithMeeting,
+ withRecordings: formValue.autoDeletionPolicyWithRecordings
+ };
}
const stepData: Partial = {
roomName: formValue.roomName,
- autoDeletionDate: autoDeletionDateTime
+ autoDeletionDate: autoDeletionDateTime,
+ autoDeletionPolicy
};
// Always save to wizard state (including when values are cleared)
@@ -115,4 +155,16 @@ export class RoomWizardRoomDetailsComponent implements OnDestroy {
autoDeletionMinute: 59
});
}
+
+ getMeetingPolicyDescription(): string {
+ const selectedValue = this.roomDetailsForm.get('autoDeletionPolicyWithMeeting')?.value;
+ const option = this.meetingPolicyOptions.find((opt) => opt.value === selectedValue);
+ return option?.description || '';
+ }
+
+ getRecordingPolicyDescription(): string {
+ const selectedValue = this.roomDetailsForm.get('autoDeletionPolicyWithRecordings')?.value;
+ const option = this.recordingPolicyOptions.find((opt) => opt.value === selectedValue);
+ return option?.description || '';
+ }
}
diff --git a/frontend/projects/shared-meet-components/src/lib/services/wizard-state.service.ts b/frontend/projects/shared-meet-components/src/lib/services/wizard-state.service.ts
index 5e8fa47..8fdab93 100644
--- a/frontend/projects/shared-meet-components/src/lib/services/wizard-state.service.ts
+++ b/frontend/projects/shared-meet-components/src/lib/services/wizard-state.service.ts
@@ -1,7 +1,13 @@
import { computed, Injectable, signal } from '@angular/core';
import { AbstractControl, FormBuilder, ValidationErrors, Validators } from '@angular/forms';
import { WizardNavigationConfig, WizardStep } from '@lib/models';
-import { MeetRecordingAccess, MeetRoomOptions, MeetRoomPreferences } from '@lib/typings/ce';
+import {
+ MeetRecordingAccess,
+ MeetRoomDeletionPolicyWithMeeting,
+ MeetRoomDeletionPolicyWithRecordings,
+ MeetRoomOptions,
+ MeetRoomPreferences
+} from '@lib/typings/ce';
// Default room preferences following the app's defaults
const DEFAULT_PREFERENCES: MeetRoomPreferences = {
@@ -101,6 +107,22 @@ export class RoomWizardStateService {
disabled: editMode
},
editMode ? [] : [Validators.min(0), Validators.max(59)]
+ ],
+ autoDeletionPolicyWithMeeting: [
+ {
+ value:
+ initialRoomOptions.autoDeletionPolicy?.withMeeting ||
+ MeetRoomDeletionPolicyWithMeeting.WHEN_MEETING_ENDS,
+ disabled: editMode
+ }
+ ],
+ autoDeletionPolicyWithRecordings: [
+ {
+ value:
+ initialRoomOptions.autoDeletionPolicy?.withRecordings ||
+ MeetRoomDeletionPolicyWithRecordings.CLOSE,
+ disabled: editMode
+ }
]
},
{
@@ -204,6 +226,9 @@ export class RoomWizardStateService {
if ('autoDeletionDate' in stepData) {
updatedOptions.autoDeletionDate = stepData.autoDeletionDate;
}
+ if ('autoDeletionPolicy' in stepData) {
+ updatedOptions.autoDeletionPolicy = stepData.autoDeletionPolicy;
+ }
break;
case 'recording':