frontend: Extract login logic from RoomGeneratorComponent to LoginComponent and refactor code

This commit is contained in:
juancarmore 2025-03-17 19:32:42 +01:00
parent a7c4b84a03
commit 592356bec3
8 changed files with 519 additions and 252 deletions

View File

@ -0,0 +1,72 @@
<div class="section1" [style]="{ '--background-image-url': 'url(' + backgroundImageUrl + ')' }">
<mat-toolbar id="header"> </mat-toolbar>
<div class="openvidu-slogan-container">
<a href="https://openvidu.io/" target="_blank">
<img id="form-img" [src]="openviduLogoUrl" />
</a>
<h4 id="slogan-text">Videoconference rooms in one click</h4>
</div>
<div class="form-container">
<div class="grid">
<form [formGroup]="loginForm" novalidate (ngSubmit)="login()" id="form-login" class="form login">
<div class="form-field" id="login-username">
<label for="login-username" [ngClass]="{ error: loginErrorMessage }">
<mat-icon matTooltip="Username">person</mat-icon>
<span class="hidden">Username</span>
</label>
<input
formControlName="username"
autocomplete="off"
type="text"
name="username"
class="form-input"
placeholder="Username"
/>
</div>
<div class="form-field" id="login-password">
<label for="login-password" [ngClass]="{ error: loginErrorMessage }">
<mat-icon matTooltip="Password">lock</mat-icon>
<span class="hidden">Password</span>
</label>
<input
formControlName="password"
type="password"
name="password"
class="form-input"
placeholder="Password"
/>
</div>
@if (loginErrorMessage) {
<div class="loginError" id="login-error">{{ loginErrorMessage }}</div>
}
<div class="form-field">
<button mat-button id="join-btn" type="submit" [disabled]="loginForm.invalid">Login</button>
</div>
</form>
</div>
</div>
<mat-toolbar class="footer">
<span>
Photo by
<a
rel="noopener noreferrer"
target="_blank"
href="https://unsplash.com/@danielleone?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText"
>
Daniel Leone
</a>
on
<a
href="https://unsplash.com/s/photos/mountain?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText"
target="_blank"
>
Unsplash
</a>
</span>
<div id="meet-version">
<span>{{ version }}</span>
</div>
</mat-toolbar>
</div>

View File

@ -0,0 +1,255 @@
$loginBorderRadius: 0.35rem;
$loginColor: #e6e6e6;
$loginError: #770000;
$loginInputBackgroundColor: #434a52;
$loginInputHoverBackgroundColor: #3c4249;
$loginLabelBackgroundColor: #363b41;
$loginSubmitBackgroundColor: #0087a9;
$loginSubmitDisabledBackgroundColor: #264b55;
$loginSubmitColor: #eee;
$loginSubmitDisabledColor: #bdbdbd;
$loginSubmitHoverBackgroundColor: #006a85;
$iconFill: #606468;
$formGap: 0.375rem;
.section1 {
background:
linear-gradient(rgba(255, 255, 255, 0.2), rgba(255, 255, 255, 0.2)),
var(--background-image-url) top center no-repeat;
background-size: cover;
height: 100%;
text-align: center;
position: relative;
color: $loginColor;
}
#header,
.footer {
background-color: transparent;
color: $loginColor;
}
.loginError {
font-size: 14px;
color: $loginError;
text-shadow: 0.2px 0px #ffffff;
text-align: left;
font-weight: 600;
}
.loginError mat-icon {
vertical-align: bottom;
padding-right: 4px;
}
.footer {
position: absolute;
bottom: 0;
font-size: 9px;
height: auto;
}
.footer a {
color: $loginColor;
}
#meet-version,
#logout-content {
right: 15px;
position: absolute;
font-size: 13px;
}
h4 {
font-size: 25px;
font-weight: 300;
color: #ffffff;
position: relative;
padding-bottom: 5px;
}
/* Extra small devices (phones, 600px and down) */
@media only screen and (max-width: 600px) {
#header_img,
.ovVersion,
.footer {
display: none;
}
}
.openvidu-slogan-container {
margin-top: 80px;
}
#form-img {
max-width: 290px;
margin-right: 10px;
margin-top: 10px;
padding: 15px;
}
/* Extra large devices (large laptops and desktops, 1200px and up) */
@media only screen and (min-width: 1200px) {
.section1 {
background-attachment: fixed;
}
}
.grid {
inline-size: 90%;
margin-inline: auto;
max-inline-size: 26rem;
}
.hidden {
border: 0;
clip: rect(0 0 0 0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
}
.icons {
display: none;
}
.icon {
block-size: 1em;
display: inline-block;
fill: $iconFill;
inline-size: 1em;
vertical-align: middle;
}
input {
background-image: none;
border: 0;
color: inherit;
font: inherit;
margin: 0;
outline: 0;
padding: 0;
transition: background-color 0.3s;
}
input[type='submit'] {
cursor: pointer;
}
.form {
display: grid;
gap: $formGap;
}
.form input[type='password'],
.form input[type='text'],
.form button[type='submit'] {
inline-size: 100%;
}
.form-field {
display: flex;
}
.form-input {
flex: 1;
}
.login {
color: $loginColor;
}
.login label.error {
background-color: $loginError;
}
.login label,
.login input[type='text'],
.login input[type='password'] {
border-radius: $loginBorderRadius;
padding: 0.85rem;
}
#room-name-input {
border-radius: 0;
}
.login button[type='submit'] {
border-radius: $loginBorderRadius;
padding: 0.4rem;
cursor: pointer;
}
.login button:disabled[type='submit'] {
cursor: auto;
color: $loginSubmitDisabledColor !important;
background-color: $loginSubmitDisabledBackgroundColor !important;
}
.login label {
background-color: $loginLabelBackgroundColor;
border-bottom-right-radius: 0;
border-top-right-radius: 0;
padding-inline: 1.25rem;
}
.login input[type='password'],
.login input[type='text'] {
background-color: $loginInputBackgroundColor;
border-bottom-left-radius: 0;
border-top-left-radius: 0;
font-size: 16px;
}
.login input[type='password']:focus,
.login input[type='password']:hover,
.login input[type='text']:focus,
.login input[type='text']:hover {
background-color: $loginInputHoverBackgroundColor;
}
.login button[type='submit'] {
background-color: $loginSubmitBackgroundColor;
color: $loginSubmitColor;
font-weight: 500;
text-transform: uppercase;
}
.login button[type='submit']:focus,
.login button[type='submit']:hover {
background-color: $loginSubmitHoverBackgroundColor;
}
#clear-room-name-btn {
height: auto;
background-color: $loginInputBackgroundColor;
border-radius: 0;
color: $loginColor;
mat-icon {
vertical-align: middle;
}
}
#room-name-generator-btn {
height: auto;
background-color: $loginInputBackgroundColor;
border-radius: $loginBorderRadius;
border-bottom-left-radius: 0;
border-top-left-radius: 0;
color: $loginColor;
mat-icon {
vertical-align: middle;
}
&:hover {
background-color: $loginInputHoverBackgroundColor;
}
}
p {
margin-block: 1.5rem;
}
.text--center {
text-align: center;
}

View File

@ -0,0 +1,22 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { LoginComponent } from './login.component';
describe('LoginComponent', () => {
let component: LoginComponent;
let fixture: ComponentFixture<LoginComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [LoginComponent]
}).compileComponents();
fixture = TestBed.createComponent(LoginComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,58 @@
import { NgClass } from '@angular/common';
import { Component } from '@angular/core';
import { FormControl, FormGroup, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms';
import { MatButton } from '@angular/material/button';
import { MatIcon } from '@angular/material/icon';
import { MatToolbar } from '@angular/material/toolbar';
import { MatTooltip } from '@angular/material/tooltip';
import { Router } from '@angular/router';
import { ContextService, AuthService } from '../../services/index';
import { HttpErrorResponse } from '@angular/common/http';
@Component({
selector: 'app-login',
standalone: true,
imports: [MatToolbar, MatTooltip, MatIcon, FormsModule, ReactiveFormsModule, NgClass, MatButton],
templateUrl: './login.component.html',
styleUrl: './login.component.scss'
})
export class LoginComponent {
version = '';
openviduLogoUrl = '';
backgroundImageUrl = '';
loginForm = new FormGroup({
username: new FormControl('', [Validators.required, Validators.minLength(4)]),
password: new FormControl('', [Validators.required, Validators.minLength(4)])
});
loginErrorMessage: string | undefined;
constructor(
private router: Router,
private authService: AuthService,
private contextService: ContextService
) {}
async ngOnInit() {
this.version = this.contextService.getVersion();
this.openviduLogoUrl = this.contextService.getOpenViduLogoUrl();
this.backgroundImageUrl = this.contextService.getBackgroundImageUrl();
}
async login() {
this.loginErrorMessage = undefined;
const { username, password } = this.loginForm.value;
try {
// TODO: Replace with user login
await this.authService.adminLogin(username!, password!);
this.router.navigate(['']);
} catch (error) {
if ((error as HttpErrorResponse).status === 429) {
this.loginErrorMessage = 'Too many login attempts. Please try again later';
} else {
this.loginErrorMessage = 'Invalid username or password';
}
}
}
}

View File

@ -1,6 +1,6 @@
<div class="section1" [style]="{ '--background-image-url': 'url(' + backgroundImageUrl + ')' }">
<mat-toolbar id="header">
@if (isUserLogged) {
@if (username) {
<div id="logout-content">
<span>Hi {{ username }}, do you want to logout?</span>
<button matTooltip="Logout" mat-icon-button id="logout-btn" (click)="logout()">
@ -15,115 +15,56 @@
</a>
<h4 id="slogan-text">Videoconference rooms in one click</h4>
</div>
@if (!loading) {
<div class="form-container">
<div class="grid">
@if (isPrivateAccess && !isUserLogged) {
<form [formGroup]="loginForm" novalidate (ngSubmit)="login()" id="form-login" class="form login">
<div class="form-field" id="login-username">
<label for="login-username" [ngClass]="{ error: loginError }">
<mat-icon matTooltip="Username">person</mat-icon>
<span class="hidden">Username</span>
</label>
<input
formControlName="username"
autocomplete="off"
type="text"
name="username"
class="form-input"
placeholder="Username"
/>
</div>
<div class="form-field" id="login-password">
<label for="login-password" [ngClass]="{ error: loginError }">
<mat-icon matTooltip="Password">lock</mat-icon>
<span class="hidden">Password</span>
</label>
<input
formControlName="password"
type="password"
name="password"
class="form-input"
placeholder="Password"
/>
</div>
@if (loginError) {
<div class="roomError" id="login-error">Authentication failed. Try again.</div>
}
<div class="form-field">
<button mat-button id="join-btn" type="submit" [disabled]="loginForm.invalid">Login</button>
</div>
@if (serverConnectionError) {
<div class="roomError" id="serverConnectionError">
<mat-icon>error</mat-icon>
<span>Server connection failed!</span>
</div>
}
</form>
}
@if (isUserLogged || !isPrivateAccess) {
<form
[formGroup]="roomForm"
novalidate
(ngSubmit)="goToVideoRoom()"
id="form-room"
class="form login"
<div class="form-container">
<div class="grid">
<form [formGroup]="roomForm" novalidate (ngSubmit)="goToVideoRoom()" id="form-room" class="form room-prefix">
<div class="form-field">
<label for="room-name-input" [ngClass]="{ error: roomForm.get('roomNamePrefix')?.invalid }">
<mat-icon matTooltip="Room name prefix">video_camera_front</mat-icon>
<span class="hidden">Room name prefix</span></label
>
<div class="form-field">
<label for="room-name-input" [ngClass]="{ error: roomForm.get('roomNamePrefix')?.invalid }">
<mat-icon matTooltip="Room name">video_camera_front</mat-icon>
<span class="hidden">Room Name</span></label
>
<input
formControlName="roomNamePrefix"
autocomplete="off"
id="room-name-input"
type="text"
name="roomNamePrefix"
class="form-input"
placeholder="Room Name"
(keydown)="keyDown($event)"
/>
@if (roomForm.get('roomNamePrefix')?.value) {
<button
matSuffix
mat-icon-button
aria-label="Clear"
id="clear-room-name-btn"
(click)="clearRoomName()"
>
<mat-icon>close</mat-icon>
</button>
}
<button
matTooltip="Generate room name prefix"
mat-icon-button
id="room-name-generator-btn"
(click)="generateRoomName($event)"
>
<mat-icon>cached</mat-icon>
</button>
</div>
@if (roomForm.get('roomNamePrefix')?.hasError('required')) {
<div class="roomError" id="requiredNameError">Room name is required</div>
}
@if (roomForm.get('roomNamePrefix')?.hasError('minlength')) {
<div class="roomError" id="shortNameError">Room name is too short!</div>
}
<div class="form-field">
<button mat-button id="join-btn" type="submit" [disabled]="roomForm.invalid">JOIN</button>
</div>
@if (serverConnectionError) {
<div class="roomError" id="serverConnectionError">
<mat-icon>error</mat-icon>
<span>Server connection failed!</span>
</div>
}
</form>
<input
formControlName="roomNamePrefix"
autocomplete="off"
id="room-name-input"
type="text"
name="roomNamePrefix"
class="form-input"
placeholder="Room name prefix"
/>
@if (roomForm.get('roomNamePrefix')?.value) {
<button
matSuffix
mat-icon-button
aria-label="Clear"
id="clear-room-name-btn"
(click)="clearRoomName()"
>
<mat-icon>close</mat-icon>
</button>
}
<button
matTooltip="Generate room name prefix"
mat-icon-button
id="room-name-generator-btn"
(click)="generateRoomName($event)"
>
<mat-icon>cached</mat-icon>
</button>
</div>
@if (roomForm.get('roomNamePrefix')?.hasError('required')) {
<div class="roomError" id="requiredNameError">Room name is required</div>
}
</div>
@if (roomForm.get('roomNamePrefix')?.hasError('minlength')) {
<div class="roomError" id="shortNameError">Room name is too short!</div>
}
<div class="form-field">
<button mat-button id="join-btn" type="submit" [disabled]="roomForm.invalid">JOIN</button>
</div>
</form>
</div>
}
</div>
<mat-toolbar class="footer">
<span>

View File

@ -1,16 +1,16 @@
$loginBorderRadus: 0.35rem;
$loginColor: #e6e6e6;
$loginError: #770000;
$loginInputBackgroundColor: #434a52;
$loginInputHoverBackgroundColor: #3c4249;
$loginLabelBackgroundColor: #363b41;
$loginSubmitBackgroundColor: #0087a9;
$loginSubmitDisabledBackgroundColor: #264b55;
$formBorderRadius: 0.35rem;
$formColor: #e6e6e6;
$formError: #770000;
$formInputBackgroundColor: #434a52;
$formInputHoverBackgroundColor: #3c4249;
$formLabelBackgroundColor: #363b41;
$formSubmitBackgroundColor: #0087a9;
$formSubmitDisabledBackgroundColor: #264b55;
$loginSubmitColor: #eee;
$loginSubmitDisabledColor: #bdbdbd;
$formSubmitColor: #eee;
$formSubmitDisabledColor: #bdbdbd;
$loginSubmitHoverBackgroundColor: #006a85;
$formSubmitHoverBackgroundColor: #006a85;
$iconFill: #606468;
$formGap: 0.375rem;
@ -22,18 +22,18 @@ $formGap: 0.375rem;
height: 100%;
text-align: center;
position: relative;
color: $loginColor;
color: $formColor;
}
#header,
.footer {
background-color: transparent;
color: $loginColor;
color: $formColor;
}
.roomError {
font-size: 14px;
color: $loginError;
color: $formError;
text-shadow: 0.2px 0px #ffffff;
text-align: left;
font-weight: 600;
@ -52,7 +52,7 @@ $formGap: 0.375rem;
}
.footer a {
color: $loginColor;
color: $formColor;
}
#meet-version,
@ -160,89 +160,90 @@ input[type='submit'] {
flex: 1;
}
.login {
color: $loginColor;
.room-prefix {
color: $formColor;
}
.login label.error {
background-color: $loginError;
.room-prefix label.error {
background-color: $formError;
}
.login label,
.login input[type='text'],
.login input[type='password'] {
border-radius: $loginBorderRadus;
.room-prefix label,
.room-prefix input[type='text'],
.room-prefix input[type='password'] {
border-radius: $formBorderRadius;
padding: 0.85rem;
}
#room-name-input {
border-radius: 0;
}
.login button[type='submit'] {
border-radius: $loginBorderRadus;
.room-prefix button[type='submit'] {
border-radius: $formBorderRadius;
padding: 0.4rem;
cursor: pointer;
}
.login button:disabled[type='submit'] {
.room-prefix button:disabled[type='submit'] {
cursor: auto;
color: $loginSubmitDisabledColor !important;
background-color: $loginSubmitDisabledBackgroundColor !important;
color: $formSubmitDisabledColor !important;
background-color: $formSubmitDisabledBackgroundColor !important;
}
.login label {
background-color: $loginLabelBackgroundColor;
.room-prefix label {
background-color: $formLabelBackgroundColor;
border-bottom-right-radius: 0;
border-top-right-radius: 0;
padding-inline: 1.25rem;
}
.login input[type='password'],
.login input[type='text'] {
background-color: $loginInputBackgroundColor;
.room-prefix input[type='password'],
.room-prefix input[type='text'] {
background-color: $formInputBackgroundColor;
border-bottom-left-radius: 0;
border-top-left-radius: 0;
font-size: 16px;
}
.login input[type='password']:focus,
.login input[type='password']:hover,
.login input[type='text']:focus,
.login input[type='text']:hover {
background-color: $loginInputHoverBackgroundColor;
.room-prefix input[type='password']:focus,
.room-prefix input[type='password']:hover,
.room-prefix input[type='text']:focus,
.room-prefix input[type='text']:hover {
background-color: $formInputHoverBackgroundColor;
}
.login button[type='submit'] {
background-color: $loginSubmitBackgroundColor;
color: $loginSubmitColor;
.room-prefix button[type='submit'] {
background-color: $formSubmitBackgroundColor;
color: $formSubmitColor;
font-weight: 500;
text-transform: uppercase;
}
.login button[type='submit']:focus,
.login button[type='submit']:hover {
background-color: $loginSubmitHoverBackgroundColor;
.room-prefix button[type='submit']:focus,
.room-prefix button[type='submit']:hover {
background-color: $formSubmitHoverBackgroundColor;
}
#clear-room-name-btn {
height: auto;
background-color: $loginInputBackgroundColor;
background-color: $formInputBackgroundColor;
border-radius: 0;
color: $loginColor;
color: $formColor;
mat-icon {
vertical-align: middle;
}
}
#room-name-generator-btn {
height: auto;
background-color: $loginInputBackgroundColor;
border-radius: $loginBorderRadus;
background-color: $formInputBackgroundColor;
border-radius: $formBorderRadius;
border-bottom-left-radius: 0;
border-top-left-radius: 0;
color: $loginColor;
color: $formColor;
mat-icon {
vertical-align: middle;
}
&:hover {
background-color: $loginInputHoverBackgroundColor;
background-color: $formInputHoverBackgroundColor;
}
}

View File

@ -1,19 +1,11 @@
import { Component, OnDestroy, OnInit } from '@angular/core';
import {
FormBuilder,
FormGroup,
UntypedFormBuilder,
Validators,
FormsModule,
ReactiveFormsModule
} from '@angular/forms';
import { Component, OnInit } from '@angular/core';
import { FormGroup, Validators, FormsModule, ReactiveFormsModule, FormControl } from '@angular/forms';
import { MatIcon } from '@angular/material/icon';
import { MatTooltip } from '@angular/material/tooltip';
import { MatIconButton, MatButton } from '@angular/material/button';
import { NgClass } from '@angular/common';
import { MatToolbar } from '@angular/material/toolbar';
import { ActivatedRoute, Router } from '@angular/router';
import { Subscription } from 'rxjs';
import { Router } from '@angular/router';
import { ContextService, HttpService } from '../../services/index';
import { OpenViduMeetRoom, OpenViduMeetRoomOptions } from '../../typings/ce/room';
import { animals, colors, Config, uniqueNamesGenerator } from 'unique-names-generator';
@ -25,68 +17,29 @@ import { animals, colors, Config, uniqueNamesGenerator } from 'unique-names-gene
standalone: true,
imports: [MatToolbar, MatIconButton, MatTooltip, MatIcon, FormsModule, ReactiveFormsModule, NgClass, MatButton]
})
export class RoomCreatorComponent implements OnInit, OnDestroy {
export class RoomCreatorComponent implements OnInit {
version = '';
openviduLogoUrl = '';
backgroundImageUrl = '';
roomForm: FormGroup;
loginForm: FormGroup;
isPrivateAccess = false;
roomForm = new FormGroup({
roomNamePrefix: new FormControl(this.getRandomName(), [Validators.required, Validators.minLength(6)])
});
username = '';
loginError = false;
serverConnectionError = false;
isUserLogged = false;
loading = true;
private queryParamSubscription!: Subscription;
constructor(
private router: Router,
public formBuilder: UntypedFormBuilder,
private httpService: HttpService,
// private callService: ConfigService,
private fb: FormBuilder,
private route: ActivatedRoute,
private contextService: ContextService
) {
this.loginForm = this.fb.group({
username: [
/*this.storageService.getParticipantName() ??*/ '',
[Validators.required, Validators.minLength(4)]
],
password: ['', [Validators.required, Validators.minLength(4)]]
});
this.roomForm = this.fb.group({
roomNamePrefix: [this.getRandomName(), [Validators.required, Validators.minLength(6)]]
});
}
) {}
async ngOnInit() {
this.version = this.contextService.getVersion();
this.openviduLogoUrl = this.contextService.getOpenViduLogoUrl();
this.backgroundImageUrl = this.contextService.getBackgroundImageUrl();
this.subscribeToQueryParams();
try {
// await this.callService.initialize();
// this.isPrivateAccess = this.callService.isPrivateAccess();
if (this.isPrivateAccess) {
this.isUserLogged = true;
this.loginError = false;
}
} catch (error) {
this.isUserLogged = false;
// this.serverConnectionError = true;
this.loginError = true;
} finally {
this.loading = false;
}
}
ngOnDestroy(): void {
if (this.queryParamSubscription) this.queryParamSubscription.unsubscribe();
// TODO: Retrieve actual username
this.username = 'user';
}
generateRoomName(event: any) {
@ -98,34 +51,9 @@ export class RoomCreatorComponent implements OnInit, OnDestroy {
this.roomForm.get('roomNamePrefix')?.setValue('');
}
keyDown(event: KeyboardEvent) {
if (event.keyCode === 13) {
event.preventDefault();
this.goToVideoRoom();
}
}
async login() {
// Invoked when login form is valid
this.loginError = false;
this.username = this.loginForm.get('username')?.value;
const password = this.loginForm.get('password')?.value;
try {
await this.httpService.userLogin({ username: this.username, password });
this.isUserLogged = true;
} catch (error) {
this.isUserLogged = false;
this.loginError = true;
console.error('Error doing login ', error);
}
}
async logout() {
try {
await this.httpService.userLogout();
this.loginError = false;
this.isUserLogged = false;
} catch (error) {
console.error('Error doing logout ', error);
}
@ -137,7 +65,7 @@ export class RoomCreatorComponent implements OnInit, OnDestroy {
return;
}
const roomNamePrefix = this.roomForm.get('roomNamePrefix')?.value.replace(/ /g, '-');
const roomNamePrefix = this.roomForm.get('roomNamePrefix')?.value!.replace(/ /g, '-');
try {
// TODO: Fix expiration date
@ -148,8 +76,6 @@ export class RoomCreatorComponent implements OnInit, OnDestroy {
const room: OpenViduMeetRoom = await this.httpService.createRoom(options);
this.roomForm.get('roomNamePrefix')?.setValue(roomNamePrefix);
const accessRoomUrl = new URL(room.moderatorRoomUrl);
const secret = accessRoomUrl.searchParams.get('secret');
const roomName = accessRoomUrl.pathname;
@ -160,16 +86,6 @@ export class RoomCreatorComponent implements OnInit, OnDestroy {
}
}
private subscribeToQueryParams(): void {
// this.queryParamSubscription = this.route.queryParams.subscribe((params) => {
// const roomName = params['roomName'];
// if (roomName) {
// this.loginError = true;
// this.roomForm.get('roomNamePrefix')?.setValue(roomName.replace(/[^\w-]/g, ''));
// }
// });
}
private getRandomName(): string {
const configName: Config = {
dictionaries: [colors, animals],

View File

@ -25,9 +25,11 @@ import {
SecurityPreferencesComponent,
VideoRoomComponent
} from '../pages';
import { LoginComponent } from '@lib/pages/login/login.component';
export const baseRoutes: Routes = [
{ path: '', component: RoomCreatorComponent },
{ path: 'login', component: LoginComponent },
{ path: 'disconnected', component: DisconnectedComponent },
{ path: 'unauthorized', component: UnauthorizedComponent },
{