mirror of
https://github.com/BrenBroZAYT/gameyfin.git
synced 2026-06-13 16:40:01 +00:00
WIP: Implement frontend
This commit is contained in:
@@ -28,7 +28,7 @@ public class LibraryController {
|
||||
if(downloadImages) downloadImages();
|
||||
}
|
||||
|
||||
@GetMapping(value = "/download_images")
|
||||
@GetMapping(value = "/download-images")
|
||||
public void downloadImages() {
|
||||
filesystemService.downloadGameCovers();
|
||||
filesystemService.downloadGameScreenshots();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
gameyfin:
|
||||
root: C:\Projects\privat\gameyfin-library
|
||||
#root: \\NAS-Simon\Öffentlich\Spiele
|
||||
#root: C:\Projects\privat\gameyfin-library
|
||||
root: \\NAS-Simon\Öffentlich\Spiele
|
||||
cache: ${gameyfin.root}\.gameyfin\cache
|
||||
db: ${gameyfin.root}\.gameyfin\db # Currently unused
|
||||
igdb:
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
import {Observable} from "rxjs";
|
||||
import {DetectedGameDto} from "../models/dtos/DetectedGameDto";
|
||||
import {GameOverviewDto} from "../models/dtos/GameOverviewDto";
|
||||
import {HttpResponse} from "@angular/common/http";
|
||||
|
||||
export interface LibraryApi {
|
||||
scanLibrary(): Observable<HttpResponse<Response>>;
|
||||
downloadImages(): Observable<HttpResponse<Response>>;
|
||||
getFiles(): Observable<string[]>;
|
||||
}
|
||||
@@ -31,6 +31,8 @@ import {MatPaginatorModule} from "@angular/material/paginator";
|
||||
import {MatSortModule} from "@angular/material/sort";
|
||||
import { GameCoverComponent } from './components/game-cover/game-cover.component';
|
||||
import { GameDetailViewComponent } from './components/game-detail-view/game-detail-view.component';
|
||||
import {MatSnackBarModule} from '@angular/material/snack-bar';
|
||||
import {MatGridListModule} from "@angular/material/grid-list";
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
@@ -66,7 +68,9 @@ import { GameDetailViewComponent } from './components/game-detail-view/game-deta
|
||||
MatProgressSpinnerModule,
|
||||
MatTableModule,
|
||||
MatPaginatorModule,
|
||||
MatSortModule
|
||||
MatSortModule,
|
||||
MatSnackBarModule,
|
||||
MatGridListModule
|
||||
],
|
||||
providers: [
|
||||
{
|
||||
|
||||
@@ -6,6 +6,6 @@
|
||||
@include mat.elevation(4);
|
||||
|
||||
&:hover {
|
||||
@include mat.elevation(12);
|
||||
@include mat.elevation(24);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,2 +1,8 @@
|
||||
<mat-toolbar role="heading">
|
||||
|
||||
<span class="spacer"></span>
|
||||
|
||||
<button mat-icon-button (click)="reloadLibrary()">
|
||||
<mat-icon>youtube_searched_for</mat-icon>
|
||||
</button>
|
||||
</mat-toolbar>
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import {Component, OnInit} from '@angular/core';
|
||||
import {NavMenuItem} from '../../models/objects/NavMenuItem';
|
||||
import {Title} from '@angular/platform-browser';
|
||||
import {Config} from '../../config/Config';
|
||||
import {Icon} from '../../models/enums/Icon';
|
||||
import {DropDownMenuItem} from "../../models/objects/DropDownMenuItem";
|
||||
import {LibraryService} from "../../services/library.service";
|
||||
import {MatSnackBar} from '@angular/material/snack-bar';
|
||||
import {timeInterval} from "rxjs";
|
||||
|
||||
@Component({
|
||||
selector: 'app-header',
|
||||
@@ -12,29 +11,19 @@ import {DropDownMenuItem} from "../../models/objects/DropDownMenuItem";
|
||||
})
|
||||
export class HeaderComponent implements OnInit {
|
||||
|
||||
tabNavItems: NavMenuItem[] = [
|
||||
new NavMenuItem('Servers', Icon.dns, '/servers', true),
|
||||
new NavMenuItem('Games', Icon.controller, '/games', true),
|
||||
new NavMenuItem('Info', Icon.info, '/info', true),
|
||||
new NavMenuItem('Config', Icon.settings, '/config', true),
|
||||
];
|
||||
|
||||
dropDownItems: DropDownMenuItem[] = [
|
||||
new DropDownMenuItem('Log out', Icon.lock_open, () => {
|
||||
alert("Logout not implemented");
|
||||
}, true)
|
||||
];
|
||||
|
||||
activeItem: NavMenuItem | undefined;
|
||||
|
||||
constructor(private titleService: Title) {
|
||||
constructor(private libraryService: LibraryService,
|
||||
private snackBar: MatSnackBar) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
|
||||
setActiveItem(item: NavMenuItem) {
|
||||
this.activeItem = item;
|
||||
this.titleService.setTitle(`${Config.baseTitle} - ${item.title}`);
|
||||
reloadLibrary() {
|
||||
this.libraryService.scanLibrary().pipe(timeInterval()).subscribe({
|
||||
next: value => this.snackBar.open(`Library scan completed in ${Math.trunc(value.interval/1000)} seconds.`),
|
||||
error: error => this.snackBar.open(`Error while scanning library: ${error}`)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,3 +10,16 @@
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.content > mat-card {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.column-label {
|
||||
margin-right: 8px;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
@@ -3,12 +3,16 @@
|
||||
<mat-spinner></mat-spinner>
|
||||
<h2>Loading library...</h2>
|
||||
</div>
|
||||
<div fxLayout="row" fxLayoutAlign="center center">
|
||||
<div *ngIf="!this.loading && this.detectedGames.length === 0">
|
||||
<h2>Your game library is empty!</h2>
|
||||
</div>
|
||||
<div fxLayout="row" fxLayoutGap="12px" [style.margin-top.px]="12" *ngIf="!this.loading && this.detectedGames.length > 0">
|
||||
<game-cover fxLayout="column" *ngFor="let game of detectedGames" [game]="game"></game-cover>
|
||||
|
||||
<div fxLayout="row" fxLayoutAlign="center center" *ngIf="!this.loading && this.detectedGames.length === 0">
|
||||
<h2>Your game library is empty!</h2>
|
||||
</div>
|
||||
|
||||
<div class="content">
|
||||
<div fxLayout="row wrap" fxLayoutGap="16px grid">
|
||||
<div fxFlex="25% 1" fxFlex.xs="100%" fxFlex.sm="33%" *ngFor="let game of detectedGames">
|
||||
<game-cover [game]="game"></game-cover>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { GamesService } from './games.service';
|
||||
|
||||
describe('GameserverApiService', () => {
|
||||
let service: GamesService;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({});
|
||||
service = TestBed.inject(GamesService);
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
expect(service).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,30 @@
|
||||
import {Injectable} from '@angular/core';
|
||||
import {GamesApi} from "../api/GamesApi";
|
||||
import {HttpClient, HttpResponse} from "@angular/common/http";
|
||||
import {Observable} from "rxjs";
|
||||
import {DetectedGameDto} from "../models/dtos/DetectedGameDto";
|
||||
import {GameOverviewDto} from "../models/dtos/GameOverviewDto";
|
||||
import {LibraryApi} from "../api/LibraryApi";
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class LibraryService implements LibraryApi {
|
||||
|
||||
private readonly apiPath = '/library';
|
||||
|
||||
constructor(private http: HttpClient) {
|
||||
}
|
||||
|
||||
scanLibrary(): Observable<HttpResponse<Response>> {
|
||||
return this.http.get<HttpResponse<Response>>(`${this.apiPath}/scan`);
|
||||
}
|
||||
|
||||
downloadImages(): Observable<HttpResponse<Response>> {
|
||||
return this.http.get<HttpResponse<Response>>(`${this.apiPath}/download-images`);
|
||||
}
|
||||
|
||||
getFiles(): Observable<string[]> {
|
||||
return this.http.get<string[]>(`${this.apiPath}/files`);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user