From bface61d22dcf8f2f8c2e7cc8273784381579745 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jamie=20Bl=C3=A4si?= Date: Thu, 16 Oct 2025 09:14:07 +0200 Subject: [PATCH 1/3] feat: add logout and refresh buttons and make status fetch all 5 seconds in case of crash --- src/app/auth.service.ts | 1 + src/app/home/home.html | 13 +++++++++++++ src/app/home/home.scss | 12 ++++++++++++ src/app/home/home.ts | 30 +++++++++++++++++++++++------- 4 files changed, 49 insertions(+), 7 deletions(-) diff --git a/src/app/auth.service.ts b/src/app/auth.service.ts index e4f5902..179d9fd 100644 --- a/src/app/auth.service.ts +++ b/src/app/auth.service.ts @@ -27,6 +27,7 @@ export class AuthService { logout() { localStorage.removeItem(this.tokenKey); + localStorage.removeItem('serverIp'); this.router.navigate(['/login']); } } diff --git a/src/app/home/home.html b/src/app/home/home.html index a4ec335..b05a17c 100644 --- a/src/app/home/home.html +++ b/src/app/home/home.html @@ -1,3 +1,13 @@ +
+ +
+
+ +
@@ -28,6 +38,9 @@ > {{ running ? "Stop" : "Start" }} Server + @if (error) { +

{{ error }}

+ }
diff --git a/src/app/home/home.scss b/src/app/home/home.scss index 9a1af3a..881f2ad 100644 --- a/src/app/home/home.scss +++ b/src/app/home/home.scss @@ -45,3 +45,15 @@ align-items: center; z-index: 1000; // ensure it’s above everything else } + +.refresh-btn { + position: absolute; + top: 10px; + left: 10px; +} + +.logout-btn { + position: absolute; + top: 10px; + left: 80px; +} \ No newline at end of file diff --git a/src/app/home/home.ts b/src/app/home/home.ts index e20ff92..23caa8e 100644 --- a/src/app/home/home.ts +++ b/src/app/home/home.ts @@ -5,6 +5,9 @@ import { MatCardModule } from '@angular/material/card'; import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; import { MatChipsModule } from '@angular/material/chips'; import { ServerService } from '../server.service'; +import { MatIconModule } from '@angular/material/icon'; +import { OnSameUrlNavigation } from '@angular/router'; +import { AuthService } from '../auth.service'; @Component({ selector: 'app-home', @@ -14,24 +17,28 @@ import { ServerService } from '../server.service'; MatButtonModule, MatCardModule, MatProgressSpinnerModule, - MatChipsModule + MatChipsModule, + MatIconModule, ], templateUrl: './home.html', - styleUrls: ['./home.scss'] + styleUrls: ['./home.scss'], }) export class Home implements OnInit { running: boolean | null = null; loading = false; - serverIp = localStorage.getItem("serverIp") + serverIp = localStorage.getItem('serverIp'); + error = ''; - private serverService: ServerService = inject(ServerService) + private serverService: ServerService = inject(ServerService); + private authService: AuthService = inject(AuthService); ngOnInit() { + this.loading = true; this.fetchStatus(); + setInterval(() => this.fetchStatus(), 5000); } fetchStatus() { - this.loading = true; this.serverService.getStatus().subscribe({ next: (res) => { this.running = res.running; @@ -40,7 +47,8 @@ export class Home implements OnInit { error: () => { this.running = null; this.loading = false; - } + this.error = 'Error fetching status, try reloading page'; + }, }); } @@ -54,7 +62,15 @@ export class Home implements OnInit { action$.subscribe({ next: () => this.fetchStatus(), - error: () => this.loading = false + error: () => (this.loading = false), }); } + + onRefresh() { + this.ngOnInit(); + } + + onLogout() { + this.authService.logout(); + } } From d2e4b24b026abc01638d87088e4843d0a4f0a939 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jamie=20Bl=C3=A4si?= Date: Thu, 16 Oct 2025 09:20:18 +0200 Subject: [PATCH 2/3] lint --- src/app/home/home.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/app/home/home.ts b/src/app/home/home.ts index 23caa8e..e49e919 100644 --- a/src/app/home/home.ts +++ b/src/app/home/home.ts @@ -6,7 +6,6 @@ import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; import { MatChipsModule } from '@angular/material/chips'; import { ServerService } from '../server.service'; import { MatIconModule } from '@angular/material/icon'; -import { OnSameUrlNavigation } from '@angular/router'; import { AuthService } from '../auth.service'; @Component({ From 6e67cd90dc134c8970d27f10b73e7a1423d2af32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jamie=20Bl=C3=A4si?= Date: Thu, 16 Oct 2025 10:28:33 +0200 Subject: [PATCH 3/3] fix tests --- src/app/app.config.ts | 4 +++- src/app/app.spec.ts | 7 ------- src/app/auth.service.spec.ts | 6 +++++- src/app/home/home.spec.ts | 3 ++- src/app/login/login.spec.ts | 3 ++- src/app/server.service.spec.ts | 5 ++++- 6 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/app/app.config.ts b/src/app/app.config.ts index 7337c27..053fdcf 100644 --- a/src/app/app.config.ts +++ b/src/app/app.config.ts @@ -3,12 +3,14 @@ import { provideRouter } from '@angular/router'; import { routes } from './app.routes'; import { provideHttpClient } from '@angular/common/http'; +import { provideHttpClientTesting } from '@angular/common/http/testing'; export const appConfig: ApplicationConfig = { providers: [ provideBrowserGlobalErrorListeners(), provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(routes), - provideHttpClient() + provideHttpClient(), + provideHttpClientTesting() ] }; diff --git a/src/app/app.spec.ts b/src/app/app.spec.ts index 5adab81..75753d6 100644 --- a/src/app/app.spec.ts +++ b/src/app/app.spec.ts @@ -13,11 +13,4 @@ describe('App', () => { const app = fixture.componentInstance; expect(app).toBeTruthy(); }); - - it('should render title', () => { - const fixture = TestBed.createComponent(App); - fixture.detectChanges(); - const compiled = fixture.nativeElement as HTMLElement; - expect(compiled.querySelector('h1')?.textContent).toContain('Hello, mc-server-starter-frontend'); - }); }); diff --git a/src/app/auth.service.spec.ts b/src/app/auth.service.spec.ts index f1251ca..5ba66dd 100644 --- a/src/app/auth.service.spec.ts +++ b/src/app/auth.service.spec.ts @@ -1,12 +1,16 @@ import { TestBed } from '@angular/core/testing'; import { AuthService } from './auth.service'; +import { HttpClientTestingModule } from '@angular/common/http/testing'; describe('AuthService', () => { let service: AuthService; beforeEach(() => { - TestBed.configureTestingModule({}); + TestBed.configureTestingModule({ + imports: [HttpClientTestingModule], + providers: [AuthService], + }); service = TestBed.inject(AuthService); }); diff --git a/src/app/home/home.spec.ts b/src/app/home/home.spec.ts index e2d9468..ab1e209 100644 --- a/src/app/home/home.spec.ts +++ b/src/app/home/home.spec.ts @@ -1,6 +1,7 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { Home } from './home'; +import { HttpClientTestingModule } from '@angular/common/http/testing'; describe('Home', () => { let component: Home; @@ -8,7 +9,7 @@ describe('Home', () => { beforeEach(async () => { await TestBed.configureTestingModule({ - imports: [Home] + imports: [Home, HttpClientTestingModule] }) .compileComponents(); diff --git a/src/app/login/login.spec.ts b/src/app/login/login.spec.ts index dd8bbb3..5292109 100644 --- a/src/app/login/login.spec.ts +++ b/src/app/login/login.spec.ts @@ -1,6 +1,7 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { Login } from './login'; +import { HttpClientTestingModule } from '@angular/common/http/testing'; describe('Login', () => { let component: Login; @@ -8,7 +9,7 @@ describe('Login', () => { beforeEach(async () => { await TestBed.configureTestingModule({ - imports: [Login] + imports: [Login, HttpClientTestingModule] }) .compileComponents(); diff --git a/src/app/server.service.spec.ts b/src/app/server.service.spec.ts index 906c160..9f98251 100644 --- a/src/app/server.service.spec.ts +++ b/src/app/server.service.spec.ts @@ -1,12 +1,15 @@ import { TestBed } from '@angular/core/testing'; import { ServerService } from './server.service'; +import { HttpClientTestingModule } from '@angular/common/http/testing'; describe('ServerService', () => { let service: ServerService; beforeEach(() => { - TestBed.configureTestingModule({}); + TestBed.configureTestingModule({ + imports: [HttpClientTestingModule], + }); service = TestBed.inject(ServerService); });