Skip to content

Commit

Permalink
Show instance customizations, cache statistics and instance, allow re…
Browse files Browse the repository at this point in the history
…trieval of own user class, etc.
  • Loading branch information
jvyden committed Aug 5, 2023
1 parent ecf947a commit aa33e41
Show file tree
Hide file tree
Showing 10 changed files with 123 additions and 30 deletions.
51 changes: 40 additions & 11 deletions src/app/api/api-client.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {HttpClient} from "@angular/common/http";
import {EventEmitter, Injectable} from "@angular/core";
import {catchError, Observable, of, switchMap} from "rxjs";
import {catchError, Observable, of, switchMap, tap} from "rxjs";
import {environment} from "src/environments/environment";
import {BannerService} from "../banners/banner.service";
import {ApiAuthenticationRequest} from "./types/auth/auth-request";
Expand All @@ -22,20 +22,25 @@ import {UserUpdateRequest} from "./types/user-update-request";
import {ActivityPage} from "./types/activity/activity-page";
import {ApiListResponse} from "./types/response/api-list-response";
import {IpVerificationRequest} from "./types/auth/ip-verification-request";
import {OwnUser} from "./types/own-user";
import {Instance} from "./types/instance";

@Injectable({providedIn: 'root'})
export class ApiClient {
private _userId: string | undefined = undefined;
user: User | undefined = undefined;
user: OwnUser | undefined = undefined;

resetToken: string | undefined = undefined;

private categories: Category[] | undefined;

userWatcher: EventEmitter<User | undefined>
userWatcher: EventEmitter<OwnUser | undefined>

private statistics: Statistics | undefined;
private instance: Instance | undefined;

constructor(private httpClient: HttpClient, private bannerService: BannerService, private router: Router) {
this.userWatcher = new EventEmitter<User | undefined>();
this.userWatcher = new EventEmitter<OwnUser | undefined>();

const storedToken: string | null = localStorage.getItem('game_token');

Expand Down Expand Up @@ -99,7 +104,7 @@ export class ApiClient {
return result;
}

onUserUpdate(user: User | undefined): void {
onUserUpdate(user: OwnUser | undefined): void {
console.log("Handling user change: " + user)
if (user !== undefined) {
this.bannerService.pushSuccess(`Hi, ${user.username}!`, 'You have been successfully signed in.')
Expand All @@ -116,6 +121,32 @@ export class ApiClient {
}
}

public GetServerStatistics(): Observable<Statistics> {
if(this.statistics !== undefined) {
return new Observable<Statistics>(observer => {
observer.next(this.statistics!)
});
}

return this.makeRequest<Statistics>("GET", "statistics")
.pipe(tap(data => {
this.statistics = data;
}))
}

public GetInstanceInformation(): Observable<Instance> {
if(this.instance !== undefined) {
return new Observable<Instance>(observer => {
observer.next(this.instance!)
});
}

return this.makeRequest<Instance>("GET", "instance")
.pipe(tap(data => {
this.instance = data;
}))
}

public LogIn(username: string, passwordSha512: string): boolean {
if (this._userId !== undefined) throw Error("Cannot sign in when already signed in as someone."); // should never happen hopefully

Expand Down Expand Up @@ -172,7 +203,7 @@ export class ApiClient {
}

private GetMyUser(callback: Function | null = null) {
this.makeRequest<User>("GET", "users/me")
this.makeRequest<OwnUser>("GET", "users/me")
.pipe(catchError((err) => {
console.error(err);
return of(undefined);
Expand Down Expand Up @@ -243,10 +274,6 @@ export class ApiClient {
return this.makeRequest<Level>("GET", "levels/id/" + id)
}

public GetServerStatistics(): Observable<Statistics> {
return this.makeRequest<Statistics>("GET", "statistics")
}

public GetUsersRoom(userUuid: string): Observable<Room> {
return this.makeRequest<Room>("GET", "rooms/uuid/" + userUuid)
}
Expand Down Expand Up @@ -280,7 +307,7 @@ export class ApiClient {
}

public UpdateUser(data: UserUpdateRequest): void {
this.makeRequest<User>("PATCH", "users/me", data)
this.makeRequest<OwnUser>("PATCH", "users/me", data)
.subscribe(data => {
this.bannerService.pushSuccess("User updated", "Your profile was successfully updated.");
this.user = data;
Expand Down Expand Up @@ -311,6 +338,8 @@ export class ApiClient {
public AddAnnouncement(title: string, body: string) {
this.makeRequest("POST", "admin/announcements", {title, text: body})
.subscribe();

this.instance?.announcements.push({title, text: body})
}
}

Expand Down
4 changes: 4 additions & 0 deletions src/app/api/types/announcement.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export interface Announcement {
title: string;
text: string;
}
15 changes: 15 additions & 0 deletions src/app/api/types/instance.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import {Announcement} from "./announcement";

export interface Instance {
instanceName: string;
instanceDescription: string;

softwareName: string;
softwareVersion: string;
softwareType: string;

registrationEnabled: boolean;
maximumAssetSafetyLevel: number;

announcements: Announcement[];
}
6 changes: 6 additions & 0 deletions src/app/api/types/own-user.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import {User} from "./user";

export interface OwnUser extends User {
allowIpAuthentication: boolean;
role: number;
}
9 changes: 7 additions & 2 deletions src/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@ import {
faFireAlt,
faGear,
faSignIn,
faUser
faUser, faWrench
} from '@fortawesome/free-solid-svg-icons';
import {ApiClient, GetAssetImageLink} from './api/api-client';
import { User } from './api/types/user';
import { HeaderLink } from './header-link';
import { BannerService } from './banners/banner.service';
import {NgxMasonryOptions} from "ngx-masonry";
import {OwnUser} from "./api/types/own-user";

const fadeLength: string = "50ms";

Expand Down Expand Up @@ -72,13 +73,17 @@ export class AppComponent {
this.handleUserUpdate(undefined)
}

handleUserUpdate(data: User | undefined) {
handleUserUpdate(data: OwnUser | undefined) {
this.user = data;
this.rightSideRouterLinks = [];

if (data !== undefined) {
this.login.nativeElement.hidden = true;

if(data.role >= 127) {
this.rightSideRouterLinks.push(new HeaderLink("", "/admin", faWrench))
}

this.rightSideRouterLinks.push(new HeaderLink("", "/notifications", faBell))
this.rightSideRouterLinks.push(new HeaderLink("", "/settings", faGear))
}
Expand Down
8 changes: 6 additions & 2 deletions src/app/pages/admin-panel/admin-panel.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,13 @@
</div>
<div class="w-full">
<p class="text-xl font-bold">Preview</p>
<announcement [title]="previewAnnouncement.title" [body]="previewAnnouncement.body"></announcement>
<announcement [title]="previewAnnouncement.title" [body]="previewAnnouncement.text"></announcement>
<divider></divider>
<p class="text-xl font-bold">Live Announcements</p>
<p-gentle>There doesn't seem to be anything here.</p-gentle>
<p-gentle *ngIf="instance?.announcements?.length === 0">There doesn't seem to be anything here.</p-gentle>

<div class="flex flex-col gap-2.5">
<announcement *ngFor="let announcement of instance?.announcements" [title]="announcement.title" [body]="announcement.text"></announcement>
</div>
</div>
</div>
26 changes: 22 additions & 4 deletions src/app/pages/admin-panel/admin-panel.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ import { Component } from '@angular/core';
import {faPencil} from "@fortawesome/free-solid-svg-icons/faPencil";
import {ApiClient} from "../../api/api-client";
import {faBullhorn} from "@fortawesome/free-solid-svg-icons";
import {AnnouncementComponent} from "../../components/announcement/announcement.component";
import {Router} from "@angular/router";
import {OwnUser} from "../../api/types/own-user";
import {Announcement} from "../../api/types/announcement";
import {Instance} from "../../api/types/instance";

@Component({
selector: 'app-admin-panel',
Expand All @@ -14,9 +17,24 @@ export class AdminPanelComponent {

protected readonly faPencil = faPencil;

public previewAnnouncement: {title: string, body: string} = {title: "Title", body: "Body"};
public previewAnnouncement: Announcement = {title: "Title", text: "Body"};
public instance: Instance | undefined = undefined;

constructor(private apiClient: ApiClient) {
constructor(private apiClient: ApiClient, router: Router) {
this.apiClient.userWatcher.subscribe((data) => {
this.redirectIfNotAdmin(data, router);
})

this.apiClient.GetInstanceInformation().subscribe(data => {
this.instance = data;
})
}

private redirectIfNotAdmin(data: OwnUser | undefined, router: Router) {
if(data === undefined || data.role < 127) {
router.navigate(['/']);
return;
}
}

postAnnouncement() {
Expand All @@ -31,7 +49,7 @@ export class AdminPanelComponent {
const bodyInput: HTMLInputElement = (<HTMLInputElement>document.getElementById(this.announcementBodyId));

this.previewAnnouncement.title = titleInput.value;
this.previewAnnouncement.body = bodyInput.value;
this.previewAnnouncement.text = bodyInput.value;
}

protected readonly faBullhorn = faBullhorn;
Expand Down
12 changes: 11 additions & 1 deletion src/app/pages/main/main.component.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<div class="text-center bg-form-background md:rounded-md py-32 bg-hero bg-cover">
<page-header class="text-4xl">Welcome to Refresh!</page-header>
<page-header class="text-4xl">Welcome to {{instance?.instanceName ?? "Refresh"}}!</page-header>
<p *ngIf="instance">{{instance.instanceDescription}}</p><br>

<div *ngIf="apiClient.user !== undefined">
<p>Welcome back, <b>{{apiClient.user!.username}}</b>.</p>
Expand All @@ -8,3 +9,12 @@

<p>There are currently <b>{{statistics?.currentIngamePlayersCount ?? 0}}</b> players online across <b>{{statistics?.currentRoomCount ?? 0}}</b> rooms.</p>
</div>

<div *ngIf="(instance?.announcements?.length ?? 0) > 0">
<divider></divider>
<page-header class="text-2xl">Server Announcements</page-header>

<div class="flex flex-col gap-2.5">
<announcement *ngFor="let announcement of instance?.announcements" [title]="announcement.title" [body]="announcement.text"></announcement>
</div>
</div>
15 changes: 8 additions & 7 deletions src/app/pages/main/main.component.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,27 @@
import { HttpErrorResponse } from '@angular/common/http';
import {Component, OnInit} from '@angular/core';
import { catchError, of } from 'rxjs';
import { ApiClient } from 'src/app/api/api-client';
import { Statistics } from 'src/app/api/types/statistics';
import {Instance} from "../../api/types/instance";

@Component({
selector: 'app-main',
templateUrl: './main.component.html',
})
export class MainComponent implements OnInit {
statistics: Statistics | undefined
statistics: Statistics | undefined;
instance: Instance | undefined;

constructor(public apiClient: ApiClient) {}

ngOnInit(): void {
this.apiClient.GetServerStatistics()
.pipe(catchError((error: HttpErrorResponse, _) => {
console.warn(error);
return of(undefined);
}))
.subscribe(data => {
this.statistics = data;
});

this.apiClient.GetInstanceInformation()
.subscribe(data => {
this.instance = data;
});
}
}
7 changes: 4 additions & 3 deletions src/app/pages/settings/settings.component.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import {Component, OnInit} from '@angular/core';
import {faPencil} from "@fortawesome/free-solid-svg-icons/faPencil";
import {ApiClient} from "../../api/api-client";
import {User} from "../../api/types/user";
import {UserUpdateRequest} from "../../api/types/user-update-request";
import {faKey} from "@fortawesome/free-solid-svg-icons";
import {OwnUser} from "../../api/types/own-user";

@Component({
selector: 'app-settings',
Expand All @@ -27,11 +27,12 @@ export class SettingsComponent implements OnInit {
setTimeout(() => {this.updateInputs(this.apiClient.user);}, 0);
}

updateInputs(data: User | undefined) {
updateInputs(data: OwnUser | undefined) {
const descriptionInput: HTMLInputElement = (<HTMLInputElement>document.getElementById(this.descriptionId));
descriptionInput.value = data?.description ?? "";

// TODO: allow ip input isn't sent serverside
const allowIpInput: HTMLInputElement = (<HTMLInputElement>document.getElementById(this.allowIpId));
allowIpInput.checked = data?.allowIpAuthentication ?? false;
}

saveChanges() {
Expand Down

0 comments on commit aa33e41

Please sign in to comment.