frontend: Implement basic room creation component and integrate with room wizard
- Added RoomBasicCreationComponent for creating a room with optional name prefix. - Integrated basic creation into RoomWizardComponent, allowing users to switch to advanced mode. - Updated wizard navigation to include 'back' functionality and adjusted visibility of navigation buttons. - Created RoomDetailsComponent for configuring room details, including auto-deletion date and time. - Enhanced styling for new components and ensured responsive design. - Updated wizard state service to manage new steps and handle edit mode appropriately.
This commit is contained in:
parent
2c87a3b8d8
commit
91c9690953
@ -14,6 +14,20 @@
|
|||||||
</button>
|
</button>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@if (config.showBack) {
|
||||||
|
<!-- Back Button -->
|
||||||
|
<button
|
||||||
|
mat-stroked-button
|
||||||
|
class="back-btn"
|
||||||
|
id="wizard-back-btn"
|
||||||
|
(click)="onBack()"
|
||||||
|
[attr.aria-label]="'Go back'"
|
||||||
|
>
|
||||||
|
<mat-icon class="leading-icon">arrow_back</mat-icon>
|
||||||
|
{{ backButtonText }}
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
|
||||||
<div class="spacer"></div>
|
<div class="spacer"></div>
|
||||||
|
|
||||||
<!-- Navigation Group -->
|
<!-- Navigation Group -->
|
||||||
|
|||||||
@ -15,7 +15,7 @@
|
|||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cancel-btn {
|
.cancel-btn, .back-btn {
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,7 +38,7 @@
|
|||||||
margin-right: 0;
|
margin-right: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.cancel-btn {
|
&.cancel-btn, &.back-btn {
|
||||||
color: var(--ov-meet-text-secondary);
|
color: var(--ov-meet-text-secondary);
|
||||||
border-color: var(--ov-meet-border-color-strong);
|
border-color: var(--ov-meet-border-color-strong);
|
||||||
|
|
||||||
@ -127,7 +127,7 @@
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: var(--ov-meet-spacing-md);
|
gap: var(--ov-meet-spacing-md);
|
||||||
|
|
||||||
.cancel-btn {
|
.cancel-btn, .back-btn {
|
||||||
margin-right: 0;
|
margin-right: 0;
|
||||||
order: 3;
|
order: 3;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@ -171,7 +171,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&.loading {
|
&.loading {
|
||||||
button:not(.cancel-btn) {
|
button:not(.cancel-btn):not(.back-btn) {
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
opacity: 0.7;
|
opacity: 0.7;
|
||||||
|
|
||||||
|
|||||||
@ -17,7 +17,8 @@ export class WizardNavComponent {
|
|||||||
@Input() config: WizardNavigationConfig = {
|
@Input() config: WizardNavigationConfig = {
|
||||||
showPrevious: false,
|
showPrevious: false,
|
||||||
showNext: true,
|
showNext: true,
|
||||||
showCancel: true,
|
showCancel: false,
|
||||||
|
showBack: true,
|
||||||
showFinish: false,
|
showFinish: false,
|
||||||
showSkipAndFinish: false,
|
showSkipAndFinish: false,
|
||||||
disableFinish: false,
|
disableFinish: false,
|
||||||
@ -27,6 +28,8 @@ export class WizardNavComponent {
|
|||||||
finishLabel: 'Finish'
|
finishLabel: 'Finish'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@Input() backButtonText: string = 'Back';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Current step identifier for context
|
* Current step identifier for context
|
||||||
*/
|
*/
|
||||||
@ -38,6 +41,7 @@ export class WizardNavComponent {
|
|||||||
@Output() previous = new EventEmitter<WizardNavigationEvent>();
|
@Output() previous = new EventEmitter<WizardNavigationEvent>();
|
||||||
@Output() next = new EventEmitter<WizardNavigationEvent>();
|
@Output() next = new EventEmitter<WizardNavigationEvent>();
|
||||||
@Output() cancel = new EventEmitter<WizardNavigationEvent>();
|
@Output() cancel = new EventEmitter<WizardNavigationEvent>();
|
||||||
|
@Output() back = new EventEmitter<WizardNavigationEvent>();
|
||||||
@Output() finish = new EventEmitter<WizardNavigationEvent>();
|
@Output() finish = new EventEmitter<WizardNavigationEvent>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -78,6 +82,16 @@ export class WizardNavComponent {
|
|||||||
this.navigate.emit(event);
|
this.navigate.emit(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onBack() {
|
||||||
|
if (!this.config.showBack) return;
|
||||||
|
const event: WizardNavigationEvent = {
|
||||||
|
action: 'back',
|
||||||
|
currentStepIndex: this.currentStepId
|
||||||
|
};
|
||||||
|
this.back.emit(event);
|
||||||
|
this.navigate.emit(event);
|
||||||
|
}
|
||||||
|
|
||||||
onFinish() {
|
onFinish() {
|
||||||
if (!this.config.showFinish) return;
|
if (!this.config.showFinish) return;
|
||||||
|
|
||||||
|
|||||||
@ -19,7 +19,10 @@ export interface WizardNavigationConfig {
|
|||||||
// Button visibility flags
|
// Button visibility flags
|
||||||
showPrevious: boolean;
|
showPrevious: boolean;
|
||||||
showNext: boolean;
|
showNext: boolean;
|
||||||
|
// Cancel button visibility
|
||||||
showCancel: boolean;
|
showCancel: boolean;
|
||||||
|
// Used for going back to the previous page
|
||||||
|
showBack: boolean;
|
||||||
showFinish: boolean;
|
showFinish: boolean;
|
||||||
showSkipAndFinish: boolean; // Used for quick create actions
|
showSkipAndFinish: boolean; // Used for quick create actions
|
||||||
disableFinish?: boolean;
|
disableFinish?: boolean;
|
||||||
@ -36,6 +39,6 @@ export interface WizardNavigationConfig {
|
|||||||
* Event interface for wizard navigation actions
|
* Event interface for wizard navigation actions
|
||||||
*/
|
*/
|
||||||
export interface WizardNavigationEvent {
|
export interface WizardNavigationEvent {
|
||||||
action: 'next' | 'previous' | 'cancel' | 'finish';
|
action: 'next' | 'previous' | 'cancel' | 'finish' | 'back';
|
||||||
currentStepIndex?: number;
|
currentStepIndex?: number;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,53 @@
|
|||||||
|
<div class="room-basic-creation-page fade-in">
|
||||||
|
<!-- Header Section -->
|
||||||
|
<header class="page-header">
|
||||||
|
<mat-icon class="ov-room-icon page-icon">video_chat</mat-icon>
|
||||||
|
<div class="page-title-group">
|
||||||
|
<h2 class="page-title">Create Room</h2>
|
||||||
|
<p class="page-description">
|
||||||
|
Create a new video room with optional name prefix. For advanced options, use the room wizard.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<!-- Form Section -->
|
||||||
|
<main class="page-content">
|
||||||
|
<form [formGroup]="roomCreationForm" class="room-basic-creation-form" (ngSubmit)="onCreateRoom()">
|
||||||
|
<!-- Room Prefix Field -->
|
||||||
|
<mat-form-field appearance="outline" class="form-field">
|
||||||
|
<mat-label>Room Name Prefix</mat-label>
|
||||||
|
<input matInput formControlName="roomIdPrefix" placeholder="e.g. demo-room" />
|
||||||
|
<mat-icon matSuffix class="ov-settings-icon">label</mat-icon>
|
||||||
|
<mat-hint>Optional prefix for room names. Leave empty for default naming.</mat-hint>
|
||||||
|
@if (roomCreationForm.get('roomIdPrefix')?.hasError('maxlength')) {
|
||||||
|
<mat-error> Room name prefix cannot exceed 50 characters </mat-error>
|
||||||
|
}
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<!-- Action Buttons -->
|
||||||
|
<div class="action-buttons">
|
||||||
|
<button
|
||||||
|
mat-button
|
||||||
|
color="primary"
|
||||||
|
type="submit"
|
||||||
|
[disabled]="!isFormValid"
|
||||||
|
class="create-button"
|
||||||
|
>
|
||||||
|
<mat-icon>add</mat-icon>
|
||||||
|
<span>Create Room</span>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button
|
||||||
|
mat-stroked-button
|
||||||
|
type="button"
|
||||||
|
(click)="onOpenAdvancedMode()"
|
||||||
|
class="advanced-button"
|
||||||
|
matTooltip="Open room wizard for advanced configuration"
|
||||||
|
>
|
||||||
|
<mat-icon>handyman</mat-icon>
|
||||||
|
<span>Advanced Setup</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
@ -0,0 +1,174 @@
|
|||||||
|
@import '../../../../../../../../src/assets/styles/design-tokens';
|
||||||
|
|
||||||
|
.room-basic-creation-page {
|
||||||
|
@include ov-page-content;
|
||||||
|
@include ov-container;
|
||||||
|
|
||||||
|
padding: var(--ov-meet-spacing-xl);
|
||||||
|
max-width: 600px;
|
||||||
|
margin: 0 auto;
|
||||||
|
|
||||||
|
.page-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: var(--ov-meet-spacing-md);
|
||||||
|
margin-bottom: var(--ov-meet-spacing-xl);
|
||||||
|
|
||||||
|
.page-icon {
|
||||||
|
@include ov-icon(xxl);
|
||||||
|
color: var(--ov-meet-icon-rooms);
|
||||||
|
margin-top: var(--ov-meet-spacing-xs);
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-title-group {
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
.page-title {
|
||||||
|
margin: 0 0 var(--ov-meet-spacing-sm) 0;
|
||||||
|
font-size: var(--ov-meet-font-size-xxl);
|
||||||
|
font-weight: var(--ov-meet-font-weight-medium);
|
||||||
|
color: var(--ov-meet-text-primary);
|
||||||
|
line-height: var(--ov-meet-line-height-tight);
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-description {
|
||||||
|
margin: 0;
|
||||||
|
font-size: var(--ov-meet-font-size-lg);
|
||||||
|
color: var(--ov-meet-text-secondary);
|
||||||
|
line-height: var(--ov-meet-line-height-normal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-content {
|
||||||
|
.room-basic-creation-form {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: var(--ov-meet-spacing-xl);
|
||||||
|
|
||||||
|
.form-field {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
// Material form field customization using existing system
|
||||||
|
::ng-deep {
|
||||||
|
.mat-mdc-form-field-outline {
|
||||||
|
border-radius: var(--ov-meet-radius-sm);
|
||||||
|
}
|
||||||
|
|
||||||
|
.mat-mdc-form-field-label {
|
||||||
|
color: var(--ov-meet-text-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.mat-mdc-form-field-hint {
|
||||||
|
color: var(--ov-meet-text-hint);
|
||||||
|
font-size: var(--ov-meet-font-size-xs);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Icon styling in form fields
|
||||||
|
.mat-mdc-form-field-icon-suffix {
|
||||||
|
mat-icon {
|
||||||
|
@include ov-icon(sm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-buttons {
|
||||||
|
display: flex;
|
||||||
|
gap: var(--ov-meet-spacing-md);
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: var(--ov-meet-spacing-lg);
|
||||||
|
|
||||||
|
.create-button {
|
||||||
|
@include ov-button-base;
|
||||||
|
flex: 1;
|
||||||
|
max-width: 200px;
|
||||||
|
background-color: var(--ov-meet-color-success);
|
||||||
|
color: var(--ov-meet-text-on-primary);
|
||||||
|
box-shadow: var(--ov-meet-shadow-sm);
|
||||||
|
|
||||||
|
mat-icon {
|
||||||
|
@include ov-icon(sm);
|
||||||
|
margin-right: var(--ov-meet-spacing-xs);
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
font-size: var(--ov-meet-font-size-md);
|
||||||
|
font-weight: var(--ov-meet-font-weight-medium);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.advanced-button {
|
||||||
|
@include ov-button-base;
|
||||||
|
flex: 1;
|
||||||
|
max-width: 200px;
|
||||||
|
|
||||||
|
mat-icon {
|
||||||
|
@include ov-icon(sm);
|
||||||
|
margin-right: var(--ov-meet-spacing-xs);
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
font-size: var(--ov-meet-font-size-md);
|
||||||
|
font-weight: var(--ov-meet-font-weight-normal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@include ov-mobile-down {
|
||||||
|
padding: var(--ov-meet-spacing-lg);
|
||||||
|
|
||||||
|
.page-header {
|
||||||
|
flex-direction: column;
|
||||||
|
text-align: center;
|
||||||
|
gap: var(--ov-meet-spacing-sm);
|
||||||
|
|
||||||
|
.page-icon {
|
||||||
|
align-self: center;
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-title-group {
|
||||||
|
.page-title {
|
||||||
|
font-size: var(--ov-meet-font-size-xl);
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-description {
|
||||||
|
font-size: var(--ov-meet-font-size-md);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-content {
|
||||||
|
.room-basic-creation-form {
|
||||||
|
.action-buttons {
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.create-button,
|
||||||
|
.advanced-button {
|
||||||
|
max-width: none;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@include ov-tablet-down {
|
||||||
|
.page-content {
|
||||||
|
.room-basic-creation-form {
|
||||||
|
.action-buttons {
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.create-button,
|
||||||
|
.advanced-button {
|
||||||
|
max-width: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,61 @@
|
|||||||
|
import { Component, OnDestroy, Output, EventEmitter } from '@angular/core';
|
||||||
|
import { FormBuilder, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
|
||||||
|
import { MatButtonModule } from '@angular/material/button';
|
||||||
|
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatInputModule } from '@angular/material/input';
|
||||||
|
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||||
|
import { Subject, takeUntil } from 'rxjs';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ov-room-basic-creation',
|
||||||
|
standalone: true,
|
||||||
|
imports: [
|
||||||
|
ReactiveFormsModule,
|
||||||
|
MatButtonModule,
|
||||||
|
MatIconModule,
|
||||||
|
MatInputModule,
|
||||||
|
MatFormFieldModule,
|
||||||
|
MatTooltipModule
|
||||||
|
],
|
||||||
|
templateUrl: './room-basic-creation.component.html',
|
||||||
|
styleUrl: './room-basic-creation.component.scss'
|
||||||
|
})
|
||||||
|
export class RoomBasicCreationComponent implements OnDestroy {
|
||||||
|
@Output() createRoom = new EventEmitter<string | undefined>();
|
||||||
|
@Output() openAdvancedMode = new EventEmitter<void>();
|
||||||
|
|
||||||
|
roomCreationForm: FormGroup;
|
||||||
|
|
||||||
|
private destroy$ = new Subject<void>();
|
||||||
|
|
||||||
|
constructor(private fb: FormBuilder) {
|
||||||
|
this.roomCreationForm = this.fb.group({
|
||||||
|
roomIdPrefix: ['', [Validators.maxLength(50)]]
|
||||||
|
});
|
||||||
|
|
||||||
|
this.roomCreationForm.valueChanges.pipe(takeUntil(this.destroy$)).subscribe((value) => {
|
||||||
|
// Optional: Save form data to local storage or service if needed
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
this.destroy$.next();
|
||||||
|
this.destroy$.complete();
|
||||||
|
}
|
||||||
|
|
||||||
|
onCreateRoom() {
|
||||||
|
if (this.roomCreationForm.valid) {
|
||||||
|
const formValue = this.roomCreationForm.value;
|
||||||
|
this.createRoom.emit(formValue.roomIdPrefix || undefined);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onOpenAdvancedMode() {
|
||||||
|
this.openAdvancedMode.emit();
|
||||||
|
}
|
||||||
|
|
||||||
|
get isFormValid(): boolean {
|
||||||
|
return this.roomCreationForm.valid && !this.roomCreationForm.pending;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -6,6 +6,7 @@
|
|||||||
editMode ? 'Edit your room settings' : 'Create and configure your video room in a few simple steps'
|
editMode ? 'Edit your room settings' : 'Create and configure your video room in a few simple steps'
|
||||||
}}
|
}}
|
||||||
</p>
|
</p>
|
||||||
|
@if (!isBasicCreation()) {
|
||||||
<ov-step-indicator
|
<ov-step-indicator
|
||||||
[steps]="steps()"
|
[steps]="steps()"
|
||||||
[currentStepIndex]="currentStepIndex()"
|
[currentStepIndex]="currentStepIndex()"
|
||||||
@ -14,6 +15,7 @@
|
|||||||
(stepClick)="onStepClick($event)"
|
(stepClick)="onStepClick($event)"
|
||||||
>
|
>
|
||||||
</ov-step-indicator>
|
</ov-step-indicator>
|
||||||
|
}
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<main class="wizard-content">
|
<main class="wizard-content">
|
||||||
@ -41,9 +43,17 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
} @else {
|
} @else {
|
||||||
|
@if (isBasicCreation()) {
|
||||||
|
<!-- Basic Room Creation -->
|
||||||
|
<ov-room-basic-creation
|
||||||
|
(createRoom)="createRoom($event)"
|
||||||
|
(openAdvancedMode)="onOpenAdvancedMode()"
|
||||||
|
></ov-room-basic-creation>
|
||||||
|
} @else {
|
||||||
|
<!-- Room Wizard Steps -->
|
||||||
@switch (currentStep()?.id) {
|
@switch (currentStep()?.id) {
|
||||||
@case ('basic') {
|
@case ('roomDetails') {
|
||||||
<ov-room-wizard-basic-info></ov-room-wizard-basic-info>
|
<ov-room-wizard-room-details></ov-room-wizard-room-details>
|
||||||
}
|
}
|
||||||
@case ('recording') {
|
@case ('recording') {
|
||||||
<ov-recording-preferences></ov-recording-preferences>
|
<ov-recording-preferences></ov-recording-preferences>
|
||||||
@ -59,19 +69,34 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
</section>
|
</section>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<footer class="wizard-footer">
|
<footer class="wizard-footer">
|
||||||
|
@if (isBasicCreation()) {
|
||||||
|
<div class="basic-nav">
|
||||||
|
<nav class="wizard-navigation">
|
||||||
|
<button mat-stroked-button class="cancel-button" (click)="onCancel()">
|
||||||
|
<mat-icon>close</mat-icon>
|
||||||
|
<span>Cancel</span>
|
||||||
|
</button>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
} @else {
|
||||||
<ov-wizard-nav
|
<ov-wizard-nav
|
||||||
|
class="wizard-nav"
|
||||||
[config]="navigationConfig()"
|
[config]="navigationConfig()"
|
||||||
[currentStepId]="currentStepIndex()"
|
[currentStepId]="currentStepIndex()"
|
||||||
|
[backButtonText]="'Back to simple mode'"
|
||||||
(previous)="onPrevious()"
|
(previous)="onPrevious()"
|
||||||
(next)="onNext()"
|
(next)="onNext()"
|
||||||
(cancel)="onCancel()"
|
(cancel)="onCancel()"
|
||||||
|
(back)="onBack()"
|
||||||
(finish)="onFinish()"
|
(finish)="onFinish()"
|
||||||
>
|
>
|
||||||
</ov-wizard-nav>
|
</ov-wizard-nav>
|
||||||
|
}
|
||||||
</footer>
|
</footer>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -5,6 +5,7 @@
|
|||||||
@include ov-page-content;
|
@include ov-page-content;
|
||||||
min-height: 600px;
|
min-height: 600px;
|
||||||
gap: 0;
|
gap: 0;
|
||||||
|
padding-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wizard-header {
|
.wizard-header {
|
||||||
@ -37,7 +38,30 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.wizard-footer {
|
.wizard-footer {
|
||||||
margin-top: auto;
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
.basic-nav,
|
||||||
|
.wizard-nav {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 650px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.basic-nav .wizard-navigation {
|
||||||
|
padding: var(--ov-meet-spacing-md) 0 0 0;
|
||||||
|
}
|
||||||
|
.cancel-button {
|
||||||
|
@include ov-button-base;
|
||||||
|
border-radius: var(--ov-meet-radius-sm);
|
||||||
|
min-width: 120px;
|
||||||
|
color: var(--ov-meet-text-secondary);
|
||||||
|
border-color: var(--ov-meet-border-color-strong);
|
||||||
|
&:hover {
|
||||||
|
background-color: var(--ov-meet-surface-hover);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.toggle-label {
|
.toggle-label {
|
||||||
|
|||||||
@ -9,11 +9,12 @@ import { StepIndicatorComponent, WizardNavComponent } from '@lib/components';
|
|||||||
import { WizardNavigationConfig, WizardStep } from '@lib/models';
|
import { WizardNavigationConfig, WizardStep } from '@lib/models';
|
||||||
import { NavigationService, NotificationService, RoomService, RoomWizardStateService } from '@lib/services';
|
import { NavigationService, NotificationService, RoomService, RoomWizardStateService } from '@lib/services';
|
||||||
import { MeetRoomOptions } from '@lib/typings/ce';
|
import { MeetRoomOptions } from '@lib/typings/ce';
|
||||||
import { RoomWizardBasicInfoComponent } from './steps/basic-info/basic-info.component';
|
import { RoomWizardRoomDetailsComponent } from './steps/room-details/room-details.component';
|
||||||
import { RecordingLayoutComponent } from './steps/recording-layout/recording-layout.component';
|
import { RecordingLayoutComponent } from './steps/recording-layout/recording-layout.component';
|
||||||
import { RecordingPreferencesComponent } from './steps/recording-preferences/recording-preferences.component';
|
import { RecordingPreferencesComponent } from './steps/recording-preferences/recording-preferences.component';
|
||||||
import { RecordingTriggerComponent } from './steps/recording-trigger/recording-trigger.component';
|
import { RecordingTriggerComponent } from './steps/recording-trigger/recording-trigger.component';
|
||||||
import { RoomPreferencesComponent } from './steps/room-preferences/room-preferences.component';
|
import { RoomPreferencesComponent } from './steps/room-preferences/room-preferences.component';
|
||||||
|
import { RoomBasicCreationComponent } from '../room-basic-creation/room-basic-creation.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ov-room-wizard',
|
selector: 'ov-room-wizard',
|
||||||
@ -26,7 +27,8 @@ import { RoomPreferencesComponent } from './steps/room-preferences/room-preferen
|
|||||||
MatIconModule,
|
MatIconModule,
|
||||||
MatProgressSpinnerModule,
|
MatProgressSpinnerModule,
|
||||||
MatSlideToggleModule,
|
MatSlideToggleModule,
|
||||||
RoomWizardBasicInfoComponent,
|
RoomBasicCreationComponent,
|
||||||
|
RoomWizardRoomDetailsComponent,
|
||||||
RecordingPreferencesComponent,
|
RecordingPreferencesComponent,
|
||||||
RecordingTriggerComponent,
|
RecordingTriggerComponent,
|
||||||
RecordingLayoutComponent,
|
RecordingLayoutComponent,
|
||||||
@ -38,9 +40,9 @@ import { RoomPreferencesComponent } from './steps/room-preferences/room-preferen
|
|||||||
export class RoomWizardComponent implements OnInit {
|
export class RoomWizardComponent implements OnInit {
|
||||||
editMode: boolean = false;
|
editMode: boolean = false;
|
||||||
roomId?: string;
|
roomId?: string;
|
||||||
existingRoomData?: MeetRoomOptions;
|
existingRoomData?: MeetRoomOptions; // Edit mode
|
||||||
isCreatingRoom = signal(false);
|
isCreatingRoom = signal(false);
|
||||||
|
isBasicCreation = signal(true);
|
||||||
steps: Signal<WizardStep[]>;
|
steps: Signal<WizardStep[]>;
|
||||||
currentStep: Signal<WizardStep | undefined>;
|
currentStep: Signal<WizardStep | undefined>;
|
||||||
currentStepIndex: Signal<number>;
|
currentStepIndex: Signal<number>;
|
||||||
@ -89,6 +91,9 @@ export class RoomWizardComponent implements OnInit {
|
|||||||
try {
|
try {
|
||||||
const { roomIdPrefix, autoDeletionDate, preferences } = await this.roomService.getRoom(this.roomId);
|
const { roomIdPrefix, autoDeletionDate, preferences } = await this.roomService.getRoom(this.roomId);
|
||||||
this.existingRoomData = { roomIdPrefix, autoDeletionDate, preferences };
|
this.existingRoomData = { roomIdPrefix, autoDeletionDate, preferences };
|
||||||
|
if (this.existingRoomData) {
|
||||||
|
this.isBasicCreation.set(false);
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error loading room data:', error);
|
console.error('Error loading room data:', error);
|
||||||
// Navigate back to rooms list if room not found
|
// Navigate back to rooms list if room not found
|
||||||
@ -96,10 +101,19 @@ export class RoomWizardComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onOpenAdvancedMode() {
|
||||||
|
this.isBasicCreation.set(false);
|
||||||
|
this.wizardService.goToStep(0); // Reset to first step
|
||||||
|
}
|
||||||
|
|
||||||
onPrevious() {
|
onPrevious() {
|
||||||
this.wizardService.goToPreviousStep();
|
this.wizardService.goToPreviousStep();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onBack() {
|
||||||
|
this.isBasicCreation.set(true);
|
||||||
|
}
|
||||||
|
|
||||||
onNext() {
|
onNext() {
|
||||||
this.wizardService.goToNextStep();
|
this.wizardService.goToNextStep();
|
||||||
}
|
}
|
||||||
@ -113,6 +127,22 @@ export class RoomWizardComponent implements OnInit {
|
|||||||
await this.navigationService.navigateTo('rooms', undefined, true);
|
await this.navigationService.navigateTo('rooms', undefined, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async createRoom(roomIdPrefix?: string) {
|
||||||
|
try {
|
||||||
|
// Call the room service to create a new room
|
||||||
|
const { moderatorRoomUrl } = await this.roomService.createRoom({ roomIdPrefix });
|
||||||
|
await this.navigationService.redirectTo(moderatorRoomUrl);
|
||||||
|
} catch (error) {
|
||||||
|
const errorMessage = `Failed to create room ${roomIdPrefix}`;
|
||||||
|
this.notificationService.showSnackbar(errorMessage);
|
||||||
|
console.error(errorMessage, error);
|
||||||
|
} finally {
|
||||||
|
this.wizardService.resetWizard();
|
||||||
|
// Deactivate loading state
|
||||||
|
this.isCreatingRoom.set(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async onFinish() {
|
async onFinish() {
|
||||||
const roomOptions = this.wizardService.roomOptions();
|
const roomOptions = this.wizardService.roomOptions();
|
||||||
console.log('Wizard completed with data:', roomOptions);
|
console.log('Wizard completed with data:', roomOptions);
|
||||||
|
|||||||
@ -1,25 +1,25 @@
|
|||||||
<div class="basic-info-step fade-in">
|
<div class="room-details-step fade-in">
|
||||||
<!-- Header Section -->
|
<!-- Header Section -->
|
||||||
<header class="step-header">
|
<header class="step-header">
|
||||||
<mat-icon class="ov-room-icon step-icon">video_chat</mat-icon>
|
<mat-icon class="ov-room-icon step-icon">video_chat</mat-icon>
|
||||||
<div class="step-title-group">
|
<div class="step-title-group">
|
||||||
<h3 class="step-title">Basic Information</h3>
|
<h3 class="step-title">Room Details</h3>
|
||||||
<p class="step-description">
|
<p class="step-description">
|
||||||
Configure your room's basic settings including name prefix and automatic deletion date
|
Configure your room's details including name prefix and automatic deletion date
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<!-- Form Section -->
|
<!-- Form Section -->
|
||||||
<main class="step-content">
|
<main class="step-content">
|
||||||
<form [formGroup]="basicInfoForm" class="basic-info-form">
|
<form [formGroup]="roomDetailsForm" class="room-details-form">
|
||||||
<!-- Room Prefix Field -->
|
<!-- Room Prefix Field -->
|
||||||
<mat-form-field appearance="outline" class="form-field">
|
<mat-form-field appearance="outline" class="form-field">
|
||||||
<mat-label>Room Name Prefix</mat-label>
|
<mat-label>Room Name Prefix</mat-label>
|
||||||
<input matInput formControlName="roomIdPrefix" placeholder="e.g. demo-room" />
|
<input matInput formControlName="roomIdPrefix" placeholder="e.g. demo-room" />
|
||||||
<mat-icon matSuffix class="ov-settings-icon">label</mat-icon>
|
<mat-icon matSuffix class="ov-settings-icon">label</mat-icon>
|
||||||
<mat-hint>Optional prefix for room names. Leave empty for default naming.</mat-hint>
|
<mat-hint>Optional prefix for room names. Leave empty for default naming.</mat-hint>
|
||||||
@if (basicInfoForm.get('roomIdPrefix')?.hasError('maxlength')) {
|
@if (roomDetailsForm.get('roomIdPrefix')?.hasError('maxlength')) {
|
||||||
<mat-error> Room name prefix cannot exceed 50 characters </mat-error>
|
<mat-error> Room name prefix cannot exceed 50 characters </mat-error>
|
||||||
}
|
}
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
@ -42,7 +42,7 @@
|
|||||||
matSuffix
|
matSuffix
|
||||||
mat-icon-button
|
mat-icon-button
|
||||||
type="button"
|
type="button"
|
||||||
[disabled]="basicInfoForm.get('autoDeletionDate')?.disabled"
|
[disabled]="roomDetailsForm.get('autoDeletionDate')?.disabled"
|
||||||
(click)="clearDeletionDate()"
|
(click)="clearDeletionDate()"
|
||||||
matTooltip="Clear date selection"
|
matTooltip="Clear date selection"
|
||||||
class="clear-date-button"
|
class="clear-date-button"
|
||||||
@ -60,7 +60,7 @@
|
|||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
<!-- Time Selection (only shown when date is selected) -->
|
<!-- Time Selection (only shown when date is selected) -->
|
||||||
@if (basicInfoForm.get('autoDeletionDate')?.value) {
|
@if (roomDetailsForm.get('autoDeletionDate')?.value) {
|
||||||
<div class="time-selection-container">
|
<div class="time-selection-container">
|
||||||
<div class="time-selection-row">
|
<div class="time-selection-row">
|
||||||
<mat-form-field appearance="outline" class="time-field">
|
<mat-form-field appearance="outline" class="time-field">
|
||||||
@ -89,7 +89,7 @@
|
|||||||
<mat-icon matSuffix class="ov-settings-icon">access_time</mat-icon>
|
<mat-icon matSuffix class="ov-settings-icon">access_time</mat-icon>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</div>
|
</div>
|
||||||
@if (!basicInfoForm.hasError('minFutureDateTime')) {
|
@if (!roomDetailsForm.hasError('minFutureDateTime')) {
|
||||||
<div class="time-hint">
|
<div class="time-hint">
|
||||||
<mat-icon class="hint-icon material-symbols-outlined material-icons">auto_delete</mat-icon>
|
<mat-icon class="hint-icon material-symbols-outlined material-icons">auto_delete</mat-icon>
|
||||||
<span>Room will be deleted at {{ getFormattedDateTime() }}</span>
|
<span>Room will be deleted at {{ getFormattedDateTime() }}</span>
|
||||||
@ -1,6 +1,6 @@
|
|||||||
@import '../../../../../../../../../../src/assets/styles/design-tokens';
|
@import '../../../../../../../../../../src/assets/styles/design-tokens';
|
||||||
|
|
||||||
.basic-info-step {
|
.room-details-step {
|
||||||
@include ov-page-content;
|
@include ov-page-content;
|
||||||
@include ov-container;
|
@include ov-container;
|
||||||
|
|
||||||
@ -41,7 +41,7 @@
|
|||||||
.step-content {
|
.step-content {
|
||||||
// margin-bottom: var(--ov-meet-spacing-xl);
|
// margin-bottom: var(--ov-meet-spacing-xl);
|
||||||
|
|
||||||
.basic-info-form {
|
.room-details-form {
|
||||||
@include ov-grid-responsive(280px);
|
@include ov-grid-responsive(280px);
|
||||||
gap: var(--ov-meet-spacing-lg);
|
gap: var(--ov-meet-spacing-lg);
|
||||||
|
|
||||||
@ -144,7 +144,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.step-content {
|
.step-content {
|
||||||
.basic-info-form {
|
.room-details-form {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: var(--ov-meet-spacing-md);
|
gap: var(--ov-meet-spacing-md);
|
||||||
@ -170,7 +170,7 @@
|
|||||||
|
|
||||||
@include ov-tablet-down {
|
@include ov-tablet-down {
|
||||||
.step-content {
|
.step-content {
|
||||||
.basic-info-form {
|
.room-details-form {
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,18 +1,18 @@
|
|||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
import { RoomWizardBasicInfoComponent } from './basic-info.component';
|
import { RoomWizardRoomDetailsComponent } from './room-details.component';
|
||||||
|
|
||||||
describe('BasicInfoComponent', () => {
|
describe('BasicInfoComponent', () => {
|
||||||
let component: RoomWizardBasicInfoComponent;
|
let component: RoomWizardRoomDetailsComponent;
|
||||||
let fixture: ComponentFixture<RoomWizardBasicInfoComponent>;
|
let fixture: ComponentFixture<RoomWizardRoomDetailsComponent>;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
imports: [RoomWizardBasicInfoComponent]
|
imports: [RoomWizardRoomDetailsComponent]
|
||||||
})
|
})
|
||||||
.compileComponents();
|
.compileComponents();
|
||||||
|
|
||||||
fixture = TestBed.createComponent(RoomWizardBasicInfoComponent);
|
fixture = TestBed.createComponent(RoomWizardRoomDetailsComponent);
|
||||||
component = fixture.componentInstance;
|
component = fixture.componentInstance;
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
});
|
});
|
||||||
@ -13,7 +13,7 @@ import { MeetRoomOptions } from '@lib/typings/ce';
|
|||||||
import { Subject, takeUntil } from 'rxjs';
|
import { Subject, takeUntil } from 'rxjs';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ov-room-wizard-basic-info',
|
selector: 'ov-room-wizard-room-details',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [
|
imports: [
|
||||||
ReactiveFormsModule,
|
ReactiveFormsModule,
|
||||||
@ -26,11 +26,11 @@ import { Subject, takeUntil } from 'rxjs';
|
|||||||
MatSelectModule,
|
MatSelectModule,
|
||||||
MatTooltipModule
|
MatTooltipModule
|
||||||
],
|
],
|
||||||
templateUrl: './basic-info.component.html',
|
templateUrl: './room-details.component.html',
|
||||||
styleUrl: './basic-info.component.scss'
|
styleUrl: './room-details.component.scss'
|
||||||
})
|
})
|
||||||
export class RoomWizardBasicInfoComponent implements OnDestroy {
|
export class RoomWizardRoomDetailsComponent implements OnDestroy {
|
||||||
basicInfoForm: FormGroup;
|
roomDetailsForm: FormGroup;
|
||||||
|
|
||||||
// Arrays for time selection
|
// Arrays for time selection
|
||||||
hours = Array.from({ length: 24 }, (_, i) => ({ value: i, display: i.toString().padStart(2, '0') }));
|
hours = Array.from({ length: 24 }, (_, i) => ({ value: i, display: i.toString().padStart(2, '0') }));
|
||||||
@ -40,9 +40,9 @@ export class RoomWizardBasicInfoComponent implements OnDestroy {
|
|||||||
|
|
||||||
constructor(private wizardService: RoomWizardStateService) {
|
constructor(private wizardService: RoomWizardStateService) {
|
||||||
const currentStep = this.wizardService.currentStep();
|
const currentStep = this.wizardService.currentStep();
|
||||||
this.basicInfoForm = currentStep!.formGroup;
|
this.roomDetailsForm = currentStep!.formGroup;
|
||||||
|
|
||||||
this.basicInfoForm.valueChanges.pipe(takeUntil(this.destroy$)).subscribe((value) => {
|
this.roomDetailsForm.valueChanges.pipe(takeUntil(this.destroy$)).subscribe((value) => {
|
||||||
this.saveFormData(value);
|
this.saveFormData(value);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -71,7 +71,7 @@ export class RoomWizardBasicInfoComponent implements OnDestroy {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Always save to wizard state (including when values are cleared)
|
// Always save to wizard state (including when values are cleared)
|
||||||
this.wizardService.updateStepData('basic', stepData);
|
this.wizardService.updateStepData('roomDetails', stepData);
|
||||||
}
|
}
|
||||||
|
|
||||||
get minDate(): Date {
|
get minDate(): Date {
|
||||||
@ -81,11 +81,11 @@ export class RoomWizardBasicInfoComponent implements OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get hasDateSelected(): boolean {
|
get hasDateSelected(): boolean {
|
||||||
return !!this.basicInfoForm.get('autoDeletionDate')?.value;
|
return !!this.roomDetailsForm.get('autoDeletionDate')?.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
getFormattedDateTime(): string {
|
getFormattedDateTime(): string {
|
||||||
const formValue = this.basicInfoForm.value;
|
const formValue = this.roomDetailsForm.value;
|
||||||
if (!formValue.autoDeletionDate) {
|
if (!formValue.autoDeletionDate) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
@ -109,7 +109,7 @@ export class RoomWizardBasicInfoComponent implements OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
clearDeletionDate() {
|
clearDeletionDate() {
|
||||||
this.basicInfoForm.patchValue({
|
this.roomDetailsForm.patchValue({
|
||||||
autoDeletionDate: null,
|
autoDeletionDate: null,
|
||||||
autoDeletionHour: 23,
|
autoDeletionHour: 23,
|
||||||
autoDeletionMinute: 59
|
autoDeletionMinute: 59
|
||||||
@ -1,219 +0,0 @@
|
|||||||
// @import '../../../../../../../src/assets/styles/design-tokens';
|
|
||||||
|
|
||||||
// Use page loading utility
|
|
||||||
// .loading-container {
|
|
||||||
// @extend .ov-page-loading;
|
|
||||||
|
|
||||||
// .loading-content .loading-header .loading-title .loading-icon {
|
|
||||||
// color: var(--ov-meet-icon-rooms);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Use table page actions utility
|
|
||||||
// .rooms-actions {
|
|
||||||
// @extend .ov-table-page-actions;
|
|
||||||
|
|
||||||
// .create-room-btn {
|
|
||||||
// @include ov-button-base;
|
|
||||||
|
|
||||||
// mat-icon {
|
|
||||||
// @include ov-icon(md);
|
|
||||||
// margin-right: var(--ov-meet-spacing-sm);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Use search field utility
|
|
||||||
// .search-bar {
|
|
||||||
// .search-field {
|
|
||||||
// @extend .ov-search-field;
|
|
||||||
// min-width: 400px;
|
|
||||||
// max-width: 500px;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Use table page container utility
|
|
||||||
// .rooms-table-container {
|
|
||||||
// @extend .ov-table-page-container;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Responsive table utilities
|
|
||||||
// .table-wrapper {
|
|
||||||
// &.desktop-view {
|
|
||||||
// display: block;
|
|
||||||
|
|
||||||
// @include ov-tablet-down {
|
|
||||||
// display: none;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// &.mobile-view {
|
|
||||||
// display: none;
|
|
||||||
|
|
||||||
// @include ov-tablet-down {
|
|
||||||
// display: block;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Use data table utility
|
|
||||||
// .rooms-table {
|
|
||||||
// @extend .ov-data-table;
|
|
||||||
|
|
||||||
// .mat-mdc-header-cell {
|
|
||||||
// &.room-header {
|
|
||||||
// @extend .primary-header;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// &.actions-header {
|
|
||||||
// @extend .actions-header;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// .mat-mdc-cell {
|
|
||||||
// &.room-cell {
|
|
||||||
// @extend .primary-cell;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// &.actions-cell {
|
|
||||||
// @extend .actions-cell;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Use mobile card utilities
|
|
||||||
// .mobile-rooms-list {
|
|
||||||
// display: flex;
|
|
||||||
// flex-direction: column;
|
|
||||||
// gap: var(--ov-meet-spacing-md);
|
|
||||||
|
|
||||||
// .room-mobile-card {
|
|
||||||
// @include ov-card;
|
|
||||||
// @include ov-theme-transition;
|
|
||||||
|
|
||||||
// &:hover {
|
|
||||||
// @include ov-hover-lift(-2px);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// .room-card-header {
|
|
||||||
// display: flex;
|
|
||||||
// justify-content: space-between;
|
|
||||||
// align-items: flex-start;
|
|
||||||
// margin-bottom: var(--ov-meet-spacing-sm);
|
|
||||||
|
|
||||||
// .room-title {
|
|
||||||
// @extend .primary-text;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// .room-status {
|
|
||||||
// @extend .ov-status-badge;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// .room-card-content {
|
|
||||||
// display: flex;
|
|
||||||
// flex-direction: column;
|
|
||||||
// gap: var(--ov-meet-spacing-xs);
|
|
||||||
|
|
||||||
// .room-detail {
|
|
||||||
// display: flex;
|
|
||||||
// justify-content: space-between;
|
|
||||||
// font-size: var(--ov-meet-font-size-sm);
|
|
||||||
|
|
||||||
// .detail-label {
|
|
||||||
// color: var(--ov-meet-text-secondary);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// .detail-value {
|
|
||||||
// color: var(--ov-meet-text-primary);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// .room-card-actions {
|
|
||||||
// @extend .ov-action-buttons;
|
|
||||||
// margin-top: var(--ov-meet-spacing-md);
|
|
||||||
// padding-top: var(--ov-meet-spacing-md);
|
|
||||||
// border-top: 1px solid var(--ov-meet-border-color-light);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Use info display and status utilities
|
|
||||||
// .room-info {
|
|
||||||
// @extend .ov-info-display;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// .status-badge {
|
|
||||||
// @extend .ov-status-badge;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// .participant-count {
|
|
||||||
// @extend .ov-date-info;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// .creation-date {
|
|
||||||
// @extend .ov-date-info;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Use action buttons utility
|
|
||||||
// .action-buttons {
|
|
||||||
// @extend .ov-action-buttons;
|
|
||||||
|
|
||||||
// .mat-mdc-icon-button {
|
|
||||||
// &.primary-action {
|
|
||||||
// color: var(--ov-meet-color-primary);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// &.room-preferences-btn {
|
|
||||||
// color: var(--ov-meet-icon-settings);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// &.copy-link-btn {
|
|
||||||
// color: var(--ov-meet-text-secondary);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// &.view-recordings-btn {
|
|
||||||
// color: var(--ov-meet-icon-recordings);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// &.delete-room-btn {
|
|
||||||
// color: var(--ov-meet-color-error);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Use empty state utility
|
|
||||||
// .no-rooms-state {
|
|
||||||
// @extend .ov-empty-state;
|
|
||||||
|
|
||||||
// .empty-icon {
|
|
||||||
// @include ov-icon(xl);
|
|
||||||
// color: var(--ov-meet-text-hint);
|
|
||||||
// margin-bottom: var(--ov-meet-spacing-lg);
|
|
||||||
// display: block;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// .getting-started-actions {
|
|
||||||
// display: flex;
|
|
||||||
// flex-direction: column;
|
|
||||||
// gap: var(--ov-meet-spacing-md);
|
|
||||||
// align-items: center;
|
|
||||||
|
|
||||||
// button {
|
|
||||||
// @include ov-button-base;
|
|
||||||
|
|
||||||
// mat-icon {
|
|
||||||
// @include ov-icon(md);
|
|
||||||
// margin-right: var(--ov-meet-spacing-sm);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Use focus utilities
|
|
||||||
// .mat-mdc-checkbox,
|
|
||||||
// .mat-mdc-icon-button,
|
|
||||||
// .mat-mdc-button {
|
|
||||||
// @extend .ov-focus-visible;
|
|
||||||
// }
|
|
||||||
@ -65,10 +65,10 @@ export class RoomWizardStateService {
|
|||||||
// Define wizard steps
|
// Define wizard steps
|
||||||
const baseSteps: WizardStep[] = [
|
const baseSteps: WizardStep[] = [
|
||||||
{
|
{
|
||||||
id: 'basic',
|
id: 'roomDetails',
|
||||||
label: 'Room Details',
|
label: 'Room Details',
|
||||||
isCompleted: editMode, // In edit mode, mark as completed but not editable
|
isCompleted: editMode, // In edit mode, mark as completed but not editable
|
||||||
isActive: !editMode, // Start with basic step active in create mode
|
isActive: !editMode, // Start with roomDetails step active in create mode
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
formGroup: this.formBuilder.group(
|
formGroup: this.formBuilder.group(
|
||||||
{
|
{
|
||||||
@ -174,7 +174,7 @@ export class RoomWizardStateService {
|
|||||||
];
|
];
|
||||||
|
|
||||||
this._steps.set(baseSteps);
|
this._steps.set(baseSteps);
|
||||||
const initialStepIndex = editMode ? 1 : 0; // Skip basic step in edit mode
|
const initialStepIndex = editMode ? 1 : 0; // Skip roomDetails step in edit mode
|
||||||
this._currentStepIndex.set(initialStepIndex);
|
this._currentStepIndex.set(initialStepIndex);
|
||||||
|
|
||||||
// Update step visibility after index is set
|
// Update step visibility after index is set
|
||||||
@ -192,7 +192,7 @@ export class RoomWizardStateService {
|
|||||||
let updatedOptions: MeetRoomOptions;
|
let updatedOptions: MeetRoomOptions;
|
||||||
|
|
||||||
switch (stepId) {
|
switch (stepId) {
|
||||||
case 'basic':
|
case 'roomDetails':
|
||||||
updatedOptions = {
|
updatedOptions = {
|
||||||
...currentOptions
|
...currentOptions
|
||||||
};
|
};
|
||||||
@ -360,9 +360,10 @@ export class RoomWizardStateService {
|
|||||||
return {
|
return {
|
||||||
showPrevious: !isFirstStep,
|
showPrevious: !isFirstStep,
|
||||||
showNext: !isLastStep,
|
showNext: !isLastStep,
|
||||||
showCancel: true,
|
showCancel: false,
|
||||||
|
showBack: true,
|
||||||
showFinish: isLastStep,
|
showFinish: isLastStep,
|
||||||
showSkipAndFinish: !isEditMode && isFirstStep,
|
showSkipAndFinish: false, // Skip and finish is not used in this wizard
|
||||||
disableFinish: isSomeStepInvalid,
|
disableFinish: isSomeStepInvalid,
|
||||||
nextLabel: 'Next',
|
nextLabel: 'Next',
|
||||||
previousLabel: 'Previous',
|
previousLabel: 'Previous',
|
||||||
@ -373,13 +374,13 @@ export class RoomWizardStateService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the wizard is in edit mode.
|
* Checks if the wizard is in edit mode.
|
||||||
* Edit mode is determined by whether the basic step is completed and its form is disabled.
|
* Edit mode is determined by whether the roomDetails step is completed and its form is disabled.
|
||||||
* @returns True if in edit mode, false otherwise
|
* @returns True if in edit mode, false otherwise
|
||||||
*/
|
*/
|
||||||
private isEditMode(): boolean {
|
private isEditMode(): boolean {
|
||||||
const visibleSteps = this._visibleSteps();
|
const visibleSteps = this._visibleSteps();
|
||||||
const basicStep = visibleSteps.find((step) => step.id === 'basic');
|
const roomDetailsStep = visibleSteps.find((step) => step.id === 'roomDetails');
|
||||||
const isEditMode = !!basicStep && basicStep.isCompleted && basicStep.formGroup.disabled;
|
const isEditMode = !!roomDetailsStep && roomDetailsStep.isCompleted && roomDetailsStep.formGroup.disabled;
|
||||||
return isEditMode;
|
return isEditMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user