mirror of
https://github.com/BrenBroZAYT/gameyfin.git
synced 2026-06-16 16:20:04 +00:00
Finished implementation of frontend functionality.
Styling and bugfixing next
This commit is contained in:
@@ -1,6 +1,4 @@
|
||||
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 {
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
import {PathToSlugDto} from "../models/dtos/PathToSlugDto";
|
||||
import {Observable} from "rxjs";
|
||||
import {DetectedGameDto} from "../models/dtos/DetectedGameDto";
|
||||
import {UnmappedFileDto} from "../models/dtos/UnmappedFileDto";
|
||||
|
||||
export interface LibraryManagementApi {
|
||||
mapGame(pathToSlugDto: PathToSlugDto): Observable<DetectedGameDto>;
|
||||
getUnmappedFiles(): Observable<UnmappedFileDto[]>;
|
||||
confirmGameMapping(slug: string): Observable<DetectedGameDto>;
|
||||
deleteGame(slug: string): Observable<Response>;
|
||||
deleteUnmappedFile(id: number): Observable<Response>;
|
||||
}
|
||||
@@ -1,11 +1,10 @@
|
||||
import {NgModule} from '@angular/core';
|
||||
import {RouterModule, Routes} from '@angular/router';
|
||||
import {FullpageLayoutComponent} from "./layouts/fullpage-layout/fullpage-layout.component";
|
||||
import {PageNotFoundComponent} from "./components/page-not-found/page-not-found.component";
|
||||
import {NavbarLayoutComponent} from "./layouts/navbar-layout/navbar-layout.component";
|
||||
import {NotImplementedComponent} from "./components/not-implemented/not-implemented.component";
|
||||
import {LibraryOverviewComponent} from "./components/library-overview/library-overview.component";
|
||||
import {GameDetailViewComponent} from "./components/game-detail-view/game-detail-view.component";
|
||||
import {LibraryManagementComponent} from "./components/library-management/library-management.component";
|
||||
|
||||
const appRoutes: Routes = [
|
||||
{
|
||||
@@ -21,19 +20,12 @@ const appRoutes: Routes = [
|
||||
component: GameDetailViewComponent
|
||||
},
|
||||
{
|
||||
path: '',
|
||||
redirectTo: '/library',
|
||||
pathMatch: 'full'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '',
|
||||
component: FullpageLayoutComponent,
|
||||
children: [
|
||||
path: 'library-management',
|
||||
component: LibraryManagementComponent
|
||||
},
|
||||
{
|
||||
path: '',
|
||||
redirectTo: '/login',
|
||||
redirectTo: '/library',
|
||||
pathMatch: 'full'
|
||||
}
|
||||
]
|
||||
|
||||
@@ -2,10 +2,8 @@ import {NgModule} from '@angular/core';
|
||||
import {BrowserModule} from '@angular/platform-browser';
|
||||
|
||||
import {AppComponent} from './app.component';
|
||||
import {FullpageLayoutComponent} from "./layouts/fullpage-layout/fullpage-layout.component";
|
||||
import {NavbarLayoutComponent} from "./layouts/navbar-layout/navbar-layout.component";
|
||||
import {PageNotFoundComponent} from "./components/page-not-found/page-not-found.component";
|
||||
import {NotImplementedComponent} from "./components/not-implemented/not-implemented.component";
|
||||
import {HeaderComponent} from "./components/header/header.component";
|
||||
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
|
||||
import {FormsModule, ReactiveFormsModule} from "@angular/forms";
|
||||
@@ -35,53 +33,57 @@ import {MatSnackBarModule} from '@angular/material/snack-bar';
|
||||
import {MatGridListModule} from "@angular/material/grid-list";
|
||||
import {GameScreenshotComponent} from './components/game-screenshot/game-screenshot.component';
|
||||
import {YouTubePlayerModule} from "@angular/youtube-player";
|
||||
import { GameVideoComponent } from './components/game-video/game-video.component';
|
||||
import {GameVideoComponent} from './components/game-video/game-video.component';
|
||||
import {MatChipsModule} from "@angular/material/chips";
|
||||
import { LibraryManagementComponent } from './components/library-management/library-management.component';
|
||||
import {MatTooltipModule} from "@angular/material/tooltip";
|
||||
import {MapGameDialogComponent} from "./components/map-game-dialog/map-game-dialog.component";
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
AppComponent,
|
||||
HeaderComponent,
|
||||
FullpageLayoutComponent,
|
||||
NavbarLayoutComponent,
|
||||
PageNotFoundComponent,
|
||||
NotImplementedComponent,
|
||||
ErrorDialogComponent,
|
||||
LibraryOverviewComponent,
|
||||
GameCoverComponent,
|
||||
GameDetailViewComponent,
|
||||
GameScreenshotComponent,
|
||||
GameVideoComponent
|
||||
GameVideoComponent,
|
||||
LibraryManagementComponent,
|
||||
MapGameDialogComponent
|
||||
],
|
||||
imports: [
|
||||
BrowserModule,
|
||||
AppRoutingModule,
|
||||
BrowserAnimationsModule,
|
||||
FormsModule,
|
||||
MatFormFieldModule,
|
||||
MatCardModule,
|
||||
MatTabsModule,
|
||||
MatToolbarModule,
|
||||
MatMenuModule,
|
||||
MatIconModule,
|
||||
HttpClientModule,
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
MatDialogModule,
|
||||
MatButtonModule,
|
||||
MatInputModule,
|
||||
FlexModule,
|
||||
MatProgressSpinnerModule,
|
||||
MatTableModule,
|
||||
MatPaginatorModule,
|
||||
MatSortModule,
|
||||
MatSnackBarModule,
|
||||
MatGridListModule,
|
||||
FlexLayoutModule,
|
||||
GridModule,
|
||||
YouTubePlayerModule,
|
||||
MatChipsModule,
|
||||
MatTooltipModule
|
||||
],
|
||||
imports: [
|
||||
BrowserModule,
|
||||
AppRoutingModule,
|
||||
BrowserAnimationsModule,
|
||||
FormsModule,
|
||||
MatFormFieldModule,
|
||||
MatCardModule,
|
||||
MatTabsModule,
|
||||
MatToolbarModule,
|
||||
MatMenuModule,
|
||||
MatIconModule,
|
||||
HttpClientModule,
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
MatDialogModule,
|
||||
MatButtonModule,
|
||||
MatInputModule,
|
||||
FlexModule,
|
||||
MatProgressSpinnerModule,
|
||||
MatTableModule,
|
||||
MatPaginatorModule,
|
||||
MatSortModule,
|
||||
MatSnackBarModule,
|
||||
MatGridListModule,
|
||||
FlexLayoutModule,
|
||||
GridModule,
|
||||
YouTubePlayerModule,
|
||||
MatChipsModule
|
||||
],
|
||||
providers: [
|
||||
{
|
||||
provide: HTTP_INTERCEPTORS,
|
||||
|
||||
@@ -5,7 +5,11 @@
|
||||
|
||||
<span class="spacer"></span>
|
||||
|
||||
<button mat-icon-button (click)="reloadLibrary()">
|
||||
<button mat-icon-button (click)="reloadLibrary()" *ngIf="onLibraryManagementScreen()">
|
||||
<mat-icon>youtube_searched_for</mat-icon>
|
||||
</button>
|
||||
|
||||
<button mat-icon-button (click)="goToLibraryManagementScreen()">
|
||||
<mat-icon>settings</mat-icon>
|
||||
</button>
|
||||
</mat-toolbar>
|
||||
|
||||
@@ -19,7 +19,7 @@ export class HeaderComponent {
|
||||
reloadLibrary(): void {
|
||||
this.libraryService.scanLibrary().pipe(timeInterval()).subscribe({
|
||||
next: value => this.snackBar.open(`Library scan completed in ${Math.trunc(value.interval / 1000)} seconds.`, undefined, {duration: 2000}),
|
||||
error: error => this.snackBar.open(`Error while scanning library: ${error}`, undefined, {duration: 5000})
|
||||
error: error => this.snackBar.open(`Error while scanning library: ${error.error.message}`, undefined, {duration: 5000})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -27,8 +27,16 @@ export class HeaderComponent {
|
||||
this.router.navigate(['/']);
|
||||
}
|
||||
|
||||
goToLibraryManagementScreen(): void {
|
||||
this.router.navigate(['/library-management']);
|
||||
}
|
||||
|
||||
notOnLibraryScreen(): boolean {
|
||||
return !(this.router.url === "/library");
|
||||
}
|
||||
|
||||
onLibraryManagementScreen(): boolean {
|
||||
return this.router.url === "/library-management";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
<h2 fxLayoutAlign="center center">This component is currently not implemented.</h2>
|
||||
@@ -1,25 +0,0 @@
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
|
||||
import { NotImplementedComponent } from './not-implemented.component';
|
||||
|
||||
describe('NotImplementedComponent', () => {
|
||||
let component: NotImplementedComponent;
|
||||
let fixture: ComponentFixture<NotImplementedComponent>;
|
||||
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ NotImplementedComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(NotImplementedComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -1,15 +0,0 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-not-implemented',
|
||||
templateUrl: './not-implemented.component.html',
|
||||
styleUrls: ['./not-implemented.component.scss']
|
||||
})
|
||||
export class NotImplementedComponent implements OnInit {
|
||||
|
||||
constructor() { }
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
import {Component, OnInit} from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-fullpage-layout',
|
||||
template: `
|
||||
<div fxLayout="column" fxFlexFill>
|
||||
<div fxFlex>
|
||||
<router-outlet class="hidden-router"></router-outlet>
|
||||
</div>
|
||||
</div>
|
||||
`,
|
||||
styles: []
|
||||
})
|
||||
export class FullpageLayoutComponent implements OnInit {
|
||||
|
||||
constructor() {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import {FormControl} from "@angular/forms";
|
||||
|
||||
export class PathToSlugDto {
|
||||
slug: string;
|
||||
path: string;
|
||||
|
||||
constructor(slug: string, path: string) {
|
||||
this.slug = slug;
|
||||
this.path = path;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
export class UnmappedFileDto {
|
||||
id!: number;
|
||||
path!: string;
|
||||
}
|
||||
@@ -1,6 +1,9 @@
|
||||
import {Injectable} from '@angular/core';
|
||||
import {MatDialog, MatDialogConfig} from '@angular/material/dialog';
|
||||
import {ErrorDialogComponent} from '../components/error-dialog/error-dialog.component';
|
||||
import {DetectedGameDto} from "../models/dtos/DetectedGameDto";
|
||||
import {MapGameDialogComponent} from "../components/map-game-dialog/map-game-dialog.component";
|
||||
import {UnmappedFileDto} from "../models/dtos/UnmappedFileDto";
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
@@ -24,4 +27,33 @@ export class DialogService {
|
||||
this.dialog.open(ErrorDialogComponent, dialogConfig);
|
||||
}
|
||||
|
||||
public correctGameMappingDialog(game: DetectedGameDto): void {
|
||||
const dialogConfig = new MatDialogConfig();
|
||||
|
||||
dialogConfig.disableClose = true;
|
||||
dialogConfig.autoFocus = true;
|
||||
dialogConfig.closeOnNavigation = true;
|
||||
|
||||
dialogConfig.data = {
|
||||
path: game.path,
|
||||
slug: game.slug
|
||||
};
|
||||
|
||||
this.dialog.open(MapGameDialogComponent, dialogConfig);
|
||||
}
|
||||
|
||||
public mapUnmappedGameDialog(unmappedFile: UnmappedFileDto): void {
|
||||
const dialogConfig = new MatDialogConfig();
|
||||
|
||||
dialogConfig.disableClose = true;
|
||||
dialogConfig.autoFocus = true;
|
||||
dialogConfig.closeOnNavigation = true;
|
||||
|
||||
dialogConfig.data = {
|
||||
path: unmappedFile.path
|
||||
};
|
||||
|
||||
this.dialog.open(MapGameDialogComponent, dialogConfig);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import {Injectable} from '@angular/core';
|
||||
import {GamesApi} from "../api/GamesApi";
|
||||
import {HttpClient} from "@angular/common/http";
|
||||
import {Observable} from "rxjs";
|
||||
import {map, Observable} from "rxjs";
|
||||
import {DetectedGameDto} from "../models/dtos/DetectedGameDto";
|
||||
import {GameOverviewDto} from "../models/dtos/GameOverviewDto";
|
||||
|
||||
@@ -16,7 +16,7 @@ export class GamesService implements GamesApi {
|
||||
}
|
||||
|
||||
getAllGames(): Observable<DetectedGameDto[]> {
|
||||
return this.http.get<DetectedGameDto[]>(this.apiPath);
|
||||
return this.http.get<DetectedGameDto[]>(this.apiPath).pipe(map(games => games.sort((g1, g2) => g1.title.localeCompare(g2.title))));
|
||||
}
|
||||
|
||||
getGame(slug: String): Observable<DetectedGameDto> {
|
||||
|
||||
Reference in New Issue
Block a user