Skip to content

Commit

Permalink
Re-arrange fields and methods declaration JC-674
Browse files Browse the repository at this point in the history
  • Loading branch information
manpham-saritasa committed Sep 7, 2024
1 parent 1867a69 commit 4999a22
Show file tree
Hide file tree
Showing 10 changed files with 86 additions and 89 deletions.
4 changes: 2 additions & 2 deletions apps/angular/src/app/features/auth/login/login.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,6 @@ type LoginForm = {
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class LoginComponent {
private readonly fb = inject(NonNullableFormBuilder);

/** Login form. */
protected readonly loginForm: FormGroup<LoginForm>;

Expand All @@ -63,6 +61,8 @@ export class LoginComponent {

private readonly router = inject(Router);

private readonly fb = inject(NonNullableFormBuilder);

public constructor() {
this.loginForm = this.initializeForm();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,6 @@ type RegistrationForm = {
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class RegistrationComponent {
private readonly fb = inject(NonNullableFormBuilder);

private readonly destroyRef = inject(DestroyRef);

private readonly userService = inject(UserService);

private readonly router = inject(Router);

/** Register form group. */
protected readonly registrationForm: FormGroup<RegistrationForm>;

Expand All @@ -69,6 +61,14 @@ export class RegistrationComponent {
/** Loading state. */
protected readonly isLoading$ = new BehaviorSubject(false);

private readonly fb = inject(NonNullableFormBuilder);

private readonly destroyRef = inject(DestroyRef);

private readonly userService = inject(UserService);

private readonly router = inject(Router);

public constructor() {
this.registrationForm = this.initializeForm();
}
Expand Down
2 changes: 1 addition & 1 deletion apps/angular/src/core/mappers/api-error-response.mapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const DEFAULT_ERROR_MESSAGE = 'Something went wrong. Please try again later.';
const AUTH_ERROR_CODES = ['no_active_account'];
const AUTH_ERROR_ATTRS = ['email', 'password', 'first_name', 'last_name', 'avatar'];

/** Api response mapper. */
/** Api error response mapper. */
@Injectable({ providedIn: 'root' })
export class ApiErrorResponseMapper implements TMapperFromDto<ApiErrorResponseDto, ApiErrorResponse> {

Expand Down
2 changes: 1 addition & 1 deletion apps/angular/src/core/mappers/registration.mapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { RegistrationDto } from '@js-camp/core/dtos/registration.dto';
import { TMapperToDto } from '@js-camp/core/models/mapper';
import { Registration } from '@js-camp/core/models/registration';

/** Login mapper. */
/** Registration mapper. */
@Injectable({
providedIn: 'root',
})
Expand Down
62 changes: 31 additions & 31 deletions apps/angular/src/core/services/form-error.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,37 @@ export class FormErrorService {
}
}

/**
* Get the errors of the control.
* @param control Form control.
*/
public getErrors(control: AbstractControl): string {
const errors = { ...control.errors, ...control.parent?.errors };
if (!errors) {
return '';
}

return Object.keys(errors)
.map(errorKey => this.getErrorMessage(errorKey))
.join(' ');
}

/**
* Clears errors for a specific field or the entire form.
* @param form Form group.
* @param fieldName Specific field name.
*/
public clearErrors(form: FormGroup, fieldName?: string): void {
if (fieldName) {
const control = this.findFieldControl(form, fieldName);
if (control) {
control.setErrors(null);
}
} else {
form.updateValueAndValidity();
}
}

private displayResponseError(form: FormGroup, apiErrorResponse: ApiErrorResponse): void {
if (apiErrorResponse.errors.length === 0) {
this.notificationService.showMessage(ERROR_MESSAGES['default']);
Expand Down Expand Up @@ -83,35 +114,4 @@ export class FormErrorService {
const control = this.findFieldControl(form, fieldName);
return control != null;
}

/**
* Get the errors of the control.
* @param control Form control.
*/
public getErrors(control: AbstractControl): string {
const errors = { ...control.errors, ...control.parent?.errors };
if (!errors) {
return '';
}

return Object.keys(errors)
.map(errorKey => this.getErrorMessage(errorKey))
.join(' ');
}

/**
* Clears errors for a specific field or the entire form.
* @param form Form group.
* @param fieldName Specific field name.
*/
public clearErrors(form: FormGroup, fieldName?: string): void {
if (fieldName) {
const control = this.findFieldControl(form, fieldName);
if (control) {
control.setErrors(null);
}
} else {
form.updateValueAndValidity();
}
}
}
1 change: 0 additions & 1 deletion apps/angular/src/core/services/notification.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ const DEFAULT_MILLISECOND = 1000;
providedIn: 'root',
})
export class NotificationService {
/** Snackbar instance. */
private readonly snackBar = inject(MatSnackBar);

/**
Expand Down
25 changes: 12 additions & 13 deletions apps/angular/src/core/services/storage.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { BehaviorSubject, Observable, defer, filter, fromEvent, map, merge, of,
providedIn: 'root',
})
export class StorageService {
/** Emits the key of the changed value. */
private readonly valueChangedSubject$ = new BehaviorSubject<string>('');

private readonly localStorage = window.localStorage;
Expand Down Expand Up @@ -38,6 +37,18 @@ export class StorageService {
);
}

/**
* Removed data from storage.
* @param key Key.
*/
public remove(key: string): Observable<void> {
return defer(() => {
this.localStorage.removeItem(key);
this.valueChangedSubject$.next(key);
return of(undefined);
});
}

private watchStorageChangeByKey(keyToWatch: string): Observable<void> {
const otherPageChange$ = fromEvent(window, 'storage').pipe(
filter((event): event is StorageEvent => event instanceof StorageEvent),
Expand Down Expand Up @@ -66,16 +77,4 @@ export class StorageService {
return null;
}
}

/**
* Removed data from storage.
* @param key Key.
*/
public remove(key: string): Observable<void> {
return defer(() => {
this.localStorage.removeItem(key);
this.valueChangedSubject$.next(key);
return of(undefined);
});
}
}
4 changes: 2 additions & 2 deletions apps/angular/src/core/services/user-secret-storage.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ const USER_SECRET_STORAGE_KEY = 'user';
providedIn: 'root',
})
export class UserSecretStorageService {
private readonly storageService = inject(StorageService);

/** Secret info of current user. */
public readonly currentSecret$: Observable<UserSecret | null>;

private readonly storageService = inject(StorageService);

public constructor() {
this.currentSecret$ = this.storageService.get(USER_SECRET_STORAGE_KEY);
}
Expand Down
50 changes: 25 additions & 25 deletions apps/angular/src/core/services/user.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,40 +32,21 @@ import { UserSecretStorageService } from './user-secret-storage.service';
providedIn: 'root',
})
export class UserService {
private readonly authService = inject(AuthService);

private readonly userApiService = inject(UserApiService);

private readonly userSecretStorage = inject(UserSecretStorageService);

/** Current user. `null` when a user is not logged in. */
public readonly currentUser$: Observable<User | null>;

/** Whether the current user is authorized. */
public readonly isAuthorized$: Observable<boolean>;

public constructor() {
this.currentUser$ = this.initCurrentUserStream();
this.isAuthorized$ = this.currentUser$.pipe(map(user => user != null));
}
private readonly authService = inject(AuthService);

private saveSecretAndWaitForAuthorized(): OperatorFunction<UserSecret, void> {
return pipe(
switchMap(secret => {
const saveUserSecretSideEffect$ = this.userSecretStorage.saveSecret(secret).pipe(ignoreElements());
private readonly userApiService = inject(UserApiService);

return merge(this.isAuthorized$, saveUserSecretSideEffect$);
}),
first(isAuthorized => isAuthorized),
map(() => undefined),
);
}
private readonly userSecretStorage = inject(UserSecretStorageService);

private initCurrentUserStream(): Observable<User | null> {
return this.userSecretStorage.currentSecret$.pipe(
switchMap(secret => (secret ? this.userApiService.getCurrentUser() : of(null))),
shareReplay({ bufferSize: 1, refCount: false }),
);
public constructor() {
this.currentUser$ = this.initCurrentUserStream();
this.isAuthorized$ = this.currentUser$.pipe(map(user => user != null));
}

/**
Expand Down Expand Up @@ -100,4 +81,23 @@ export class UserService {
map(() => undefined),
);
}

private saveSecretAndWaitForAuthorized(): OperatorFunction<UserSecret, void> {
return pipe(
switchMap(secret => {
const saveUserSecretSideEffect$ = this.userSecretStorage.saveSecret(secret).pipe(ignoreElements());

return merge(this.isAuthorized$, saveUserSecretSideEffect$);
}),
first(isAuthorized => isAuthorized),
map(() => undefined),
);
}

private initCurrentUserStream(): Observable<User | null> {
return this.userSecretStorage.currentSecret$.pipe(
switchMap(secret => (secret ? this.userApiService.getCurrentUser() : of(null))),
shareReplay({ bufferSize: 1, refCount: false }),
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import { tap } from 'rxjs';
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class PasswordInputComponent implements OnInit {

/** Password form control. */
@Input()
public control = new FormControl();
Expand All @@ -44,16 +43,16 @@ export class PasswordInputComponent implements OnInit {
@Input()
public id = '';

private readonly changeDetector = inject(ChangeDetectorRef);

private readonly destroyRef = inject(DestroyRef);

/** Form error. */
protected readonly formErrorService = inject(FormErrorService);

/** Hide password flag. */
protected readonly hidePassword = signal(true);

private readonly changeDetector = inject(ChangeDetectorRef);

private readonly destroyRef = inject(DestroyRef);

/** Side effect to ensure checking the input when its status changed. */
public ngOnInit(): void {
this.control.statusChanges
Expand Down

0 comments on commit 4999a22

Please sign in to comment.