REFACTOR: UI UserService

This commit is contained in:
Patrick Haßel 2024-11-06 12:45:34 +01:00
parent 19fd6cee7b
commit b07fc824af
7 changed files with 51 additions and 47 deletions

View File

@ -0,0 +1,7 @@
export class UserLogoutEvent {
static fromJson(_: any): UserLogoutEvent {
return new UserLogoutEvent();
}
}

View File

@ -3,13 +3,14 @@ import {ApiService} from "../common/api.service";
import {UserPrivate} from "./UserPrivate"; import {UserPrivate} from "./UserPrivate";
import {Next} from "../common/types"; import {Next} from "../common/types";
import {UserPublic} from "./UserPublic"; import {UserPublic} from "./UserPublic";
import {EventType, Router} from "@angular/router"; import {Router} from "@angular/router";
import {BehaviorSubject, filter, map, Subject, Subscription} from "rxjs"; import {filter, map, Subject, Subscription} from "rxjs";
import {Group} from "../group/Group"; import {Group} from "../group/Group";
import {StompService} from "@stomp/ng2-stompjs"; import {StompService} from "@stomp/ng2-stompjs";
import {Numbers} from "../tools/Numbers/Numbers"; import {Numbers} from "../tools/Numbers/Numbers";
import {GroupDeletedEvent} from "../group/events/GroupDeletedEvent"; import {GroupDeletedEvent} from "../group/events/GroupDeletedEvent";
import {GroupLeftEvent} from "../group/events/GroupLeftEvent"; import {GroupLeftEvent} from "../group/events/GroupLeftEvent";
import {UserLogoutEvent} from "./events/UserLogoutEvent";
function userPushMessageFromJson(json: any): object { function userPushMessageFromJson(json: any): object {
const type = json['_type_']; const type = json['_type_'];
@ -18,6 +19,8 @@ function userPushMessageFromJson(json: any): object {
return Numbers.fromJson(json['payload']); return Numbers.fromJson(json['payload']);
case 'UserPrivateDto': case 'UserPrivateDto':
return UserPrivate.fromJson(json['payload']); return UserPrivate.fromJson(json['payload']);
case 'UserLogoutEvent':
return UserLogoutEvent.fromJson(json['payload']);
case 'GroupDto': case 'GroupDto':
return Group.fromJson(json['payload']); return Group.fromJson(json['payload']);
case 'GroupDeletedEvent': case 'GroupDeletedEvent':
@ -33,14 +36,14 @@ function userPushMessageFromJson(json: any): object {
}) })
export class UserService { export class UserService {
private readonly subject: BehaviorSubject<UserPrivate | null> = new BehaviorSubject<UserPrivate | null>(null);
private readonly pushSubject: Subject<any> = new Subject<any>(); private readonly pushSubject: Subject<any> = new Subject<any>();
private userSubscriptions: Subscription[] = []; private readonly subs: Subscription[] = [];
private _user: UserPrivate | null = null;
get user(): UserPrivate | null { get user(): UserPrivate | null {
return this.subject.value; return this._user;
} }
constructor( constructor(
@ -48,12 +51,26 @@ export class UserService {
protected readonly api: ApiService, protected readonly api: ApiService,
protected readonly stompService: StompService, protected readonly stompService: StompService,
) { ) {
this.router.events.subscribe(e => { this.stompService.connected$.subscribe(() => this.fetchUser());
if (e.type === EventType.NavigationEnd || e.type === EventType.NavigationSkipped) {
this.refresh(); this.fetchUser()
this.subscribePush(UserPrivate, user => this.setUser(user));
this.subscribePush(UserLogoutEvent, _ => this.setUser(null));
}
private fetchUser() {
this.api.getSingle(['User', 'whoAmI'], UserPrivate.fromJson, user => this.setUser(user));
}
private setUser(user: UserPrivate | null) {
if (!this.user?.is(user)) {
this.subs.forEach(sub => sub.unsubscribe());
this.subs.length = 0;
if (user) {
this.subs.push(this.stompService.subscribe('User/' + user.privateUuid).pipe(map(m => userPushMessageFromJson(JSON.parse(m.body)))).subscribe(m => this.pushSubject.next(m)));
} }
}); }
this.stompService.connected$.subscribe(() => this.refresh()); this._user = user;
} }
getByPublicUuid(publicUuid: any, next: Next<UserPublic>) { getByPublicUuid(publicUuid: any, next: Next<UserPublic>) {
@ -76,29 +93,10 @@ export class UserService {
this.router.navigate(['User', user.publicUuid]); this.router.navigate(['User', user.publicUuid]);
} }
refresh() {
this.api.getSingle(['User', 'whoAmI'], UserPrivate.fromJsonOrNull, user => this.setUser(user));
}
subscribe(next: Next<UserPrivate | null>): Subscription {
return this.subject.subscribe(next);
}
iOwn(group: Group): boolean { iOwn(group: Group): boolean {
return group.owner.is(this.user); return group.owner.is(this.user);
} }
private setUser(user: UserPrivate | null) {
if (user === null || this.subject.value?.privateUuid !== user.privateUuid) {
this.userSubscriptions.forEach(subscription => subscription.unsubscribe());
this.userSubscriptions.length = 0;
if (user) {
this.userSubscriptions.push(this.api.subscribe(["User", user.privateUuid], userPushMessageFromJson, message => this.pushSubject.next(message)));
}
}
this.subject.next(user);
}
iAm(user: UserPublic | UserPrivate | null) { iAm(user: UserPublic | UserPrivate | null) {
return this.user !== null && this.user.is(user); return this.user !== null && this.user.is(user);
} }
@ -111,5 +109,4 @@ export class UserService {
) )
.subscribe(next); .subscribe(next);
} }
} }

View File

@ -2,8 +2,8 @@
<div class="mainMenuItem" routerLinkActive="mainMenuItemActive" routerLink="/SolarSystem">Planeten</div> <div class="mainMenuItem" routerLinkActive="mainMenuItemActive" routerLink="/SolarSystem">Planeten</div>
<div class="mainMenuItem" routerLinkActive="mainMenuItemActive" routerLink="/VoltageDrop">Kabel</div> <div class="mainMenuItem" routerLinkActive="mainMenuItemActive" routerLink="/VoltageDrop">Kabel</div>
<div class="mainMenuItem" routerLinkActive="mainMenuItemActive" routerLink="/Groups">Gruppen</div> <div class="mainMenuItem" routerLinkActive="mainMenuItemActive" routerLink="/Groups">Gruppen</div>
<ng-container *ngIf="user !== null"> <ng-container *ngIf="userService.user !== null">
<div class="mainMenuItem mainMenuItemRight" routerLinkActive="mainMenuItemActive" routerLink="/Profile">{{ user.name }}</div> <div class="mainMenuItem mainMenuItemRight" routerLinkActive="mainMenuItemActive" routerLink="/Profile">{{ userService.user.name }}</div>
</ng-container> </ng-container>
</div> </div>
<router-outlet (activate)="onActivate($event)"/> <router-outlet (activate)="onActivate($event)"/>

View File

@ -2,7 +2,6 @@ import {Component, OnDestroy, OnInit} from '@angular/core';
import {Router, RouterLink, RouterLinkActive, RouterOutlet} from '@angular/router'; import {Router, RouterLink, RouterLinkActive, RouterOutlet} from '@angular/router';
import {NgIf} from "@angular/common"; import {NgIf} from "@angular/common";
import {UserService} from "./api/User/user.service"; import {UserService} from "./api/User/user.service";
import {UserPrivate} from "./api/User/UserPrivate";
import {Subscription} from "rxjs"; import {Subscription} from "rxjs";
@Component({ @Component({
@ -14,12 +13,10 @@ import {Subscription} from "rxjs";
}) })
export class AppComponent implements OnInit, OnDestroy { export class AppComponent implements OnInit, OnDestroy {
private readonly subscriptions: Subscription[] = []; private readonly subs: Subscription[] = [];
protected menuVisible = true; protected menuVisible = true;
protected user: UserPrivate | null = null;
constructor( constructor(
protected readonly router: Router, protected readonly router: Router,
protected readonly userService: UserService, protected readonly userService: UserService,
@ -32,16 +29,12 @@ export class AppComponent implements OnInit, OnDestroy {
} }
ngOnInit(): void { ngOnInit(): void {
this.subscriptions.push(this.userService.subscribe(user => { // -
if (this.user !== null && user === null) {
this.router.navigate(['']);
}
this.user = user;
}));
} }
ngOnDestroy(): void { ngOnDestroy(): void {
this.subscriptions.forEach(subscription => subscription.unsubscribe()); this.subs.forEach(sub => sub.unsubscribe());
this.subs.length = 0;
} }
} }

View File

@ -95,12 +95,16 @@ export class GroupComponent implements OnInit, OnDestroy {
ngOnDestroy(): void { ngOnDestroy(): void {
this.subs.forEach(sub => sub.unsubscribe()); this.subs.forEach(sub => sub.unsubscribe());
this.subs.length=0;
this.userSubs.forEach(sub => sub.unsubscribe()); this.userSubs.forEach(sub => sub.unsubscribe());
this.userSubs.length=0;
} }
private setGroup(group: Group) { private setGroup(group: Group) {
this.group = group; this.group = group;
this.userSubs.forEach(sub => sub.unsubscribe()); this.userSubs.forEach(sub => sub.unsubscribe());
this.userSubs.length = 0;
if (this.group !== null) { if (this.group !== null) {
this.group.users.forEach(_ => this.userSubs.push(this.userService.subscribePush(UserPublic, u => this.updateUser(u)))); this.group.users.forEach(_ => this.userSubs.push(this.userService.subscribePush(UserPublic, u => this.updateUser(u))));
} }

View File

@ -42,6 +42,7 @@ export class GroupsComponent implements OnInit, OnDestroy {
ngOnDestroy(): void { ngOnDestroy(): void {
this.subs.forEach(sub => sub.unsubscribe()); this.subs.forEach(sub => sub.unsubscribe());
this.subs.length = 0;
} }
private updateGroups() { private updateGroups() {

View File

@ -7,6 +7,7 @@ import {GroupListComponent} from "../group/shared/group-list/group-list.componen
import {Group} from "../../api/group/Group"; import {Group} from "../../api/group/Group";
import {Subscription} from "rxjs"; import {Subscription} from "rxjs";
import {GroupService} from "../../api/group/group.service"; import {GroupService} from "../../api/group/group.service";
import {UserPrivate} from "../../api/User/UserPrivate";
const USER_NAME_MIN_LENGTH = 2; const USER_NAME_MIN_LENGTH = 2;
@ -31,7 +32,7 @@ export class ProfileComponent implements OnInit, OnDestroy {
protected readonly USER_PASSWORD_MIN_LENGTH = USER_PASSWORD_MIN_LENGTH; protected readonly USER_PASSWORD_MIN_LENGTH = USER_PASSWORD_MIN_LENGTH;
private readonly subscriptions: Subscription[] = []; private readonly subs: Subscription[] = [];
protected password0: string = ""; protected password0: string = "";
@ -50,13 +51,14 @@ export class ProfileComponent implements OnInit, OnDestroy {
} }
ngOnInit(): void { ngOnInit(): void {
this.subscriptions.push(this.userService.subscribe(_ => { this.subs.push(this.userService.subscribePush(UserPrivate, _ => {
this.groupService.findAllJoined(groups => this.groups = groups); this.groupService.findAllJoined(groups => this.groups = groups);
})); }));
} }
ngOnDestroy(): void { ngOnDestroy(): void {
this.subscriptions.forEach(subscription => subscription.unsubscribe()); this.subs.forEach(sub => sub.unsubscribe());
this.subs.length = 0;
} }
protected nameValidator(name: string): boolean { protected nameValidator(name: string): boolean {