mirror of
https://github.com/BrenBroZAYT/gameyfin.git
synced 2026-06-17 16:20:03 +00:00
Finished implementation of frontend functionality.
Styling and bugfixing next
This commit is contained in:
@@ -32,22 +32,8 @@ public class SecurityConfiguration {
|
|||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
protected SecurityFilterChain httpSecurity(HttpSecurity http) throws Exception {
|
protected SecurityFilterChain httpSecurity(HttpSecurity http) throws Exception {
|
||||||
|
|
||||||
// TODO: Try to enable CSRF
|
|
||||||
http.csrf().disable();
|
http.csrf().disable();
|
||||||
|
|
||||||
// Allow GET-Requests on *all* URLs (Frontend will handle 404 and permission)
|
|
||||||
// except paths under "/v1/library-management"
|
|
||||||
http.authorizeRequests()
|
|
||||||
.antMatchers("**").permitAll()
|
|
||||||
.antMatchers("/v1/library-management").authenticated()
|
|
||||||
.anyRequest().denyAll();
|
|
||||||
|
|
||||||
http.httpBasic(Customizer.withDefaults());
|
http.httpBasic(Customizer.withDefaults());
|
||||||
|
|
||||||
http.exceptionHandling()
|
|
||||||
.authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED));
|
|
||||||
|
|
||||||
return http.build();
|
return http.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import de.grimsi.gameyfin.service.DownloadService;
|
|||||||
import de.grimsi.gameyfin.service.LibraryService;
|
import de.grimsi.gameyfin.service.LibraryService;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
@@ -17,6 +18,7 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/v1/library")
|
@RequestMapping("/v1/library")
|
||||||
|
@PreAuthorize("hasAuthority('ADMIN_API_ACCESS')")
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class LibraryController {
|
public class LibraryController {
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,11 @@ public class LibraryManagementController {
|
|||||||
gameService.deleteGame(slug);
|
gameService.deleteGame(slug);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@DeleteMapping(value = "/delete-unmapped-file/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||||
|
public void deleteUnmappedFile(@PathVariable Long id) {
|
||||||
|
gameService.deleteUnmappedFile(id);
|
||||||
|
}
|
||||||
|
|
||||||
@GetMapping(value = "/confirm-game/{slug}", produces = MediaType.APPLICATION_JSON_VALUE)
|
@GetMapping(value = "/confirm-game/{slug}", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||||
public DetectedGame confirmMatch(@PathVariable String slug, @RequestParam(required = false, defaultValue = "true") boolean confirm) {
|
public DetectedGame confirmMatch(@PathVariable String slug, @RequestParam(required = false, defaultValue = "true") boolean confirm) {
|
||||||
return gameService.confirmGame(slug, confirm);
|
return gameService.confirmGame(slug, confirm);
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ import de.grimsi.gameyfin.entities.DetectedGame;
|
|||||||
import de.grimsi.gameyfin.entities.UnmappableFile;
|
import de.grimsi.gameyfin.entities.UnmappableFile;
|
||||||
import de.grimsi.gameyfin.igdb.IgdbWrapper;
|
import de.grimsi.gameyfin.igdb.IgdbWrapper;
|
||||||
import de.grimsi.gameyfin.mapper.GameMapper;
|
import de.grimsi.gameyfin.mapper.GameMapper;
|
||||||
import de.grimsi.gameyfin.repositories.UnmappableFileRepository;
|
|
||||||
import de.grimsi.gameyfin.repositories.DetectedGameRepository;
|
import de.grimsi.gameyfin.repositories.DetectedGameRepository;
|
||||||
|
import de.grimsi.gameyfin.repositories.UnmappableFileRepository;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
@@ -52,9 +52,19 @@ public class GameService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void deleteGame(String slug) {
|
public void deleteGame(String slug) {
|
||||||
|
DetectedGame gameToBeDeleted = getDetectedGame(slug);
|
||||||
|
|
||||||
|
// Add the path of the game to be deleted to the unmappable files
|
||||||
|
// so it doesn't get re-indexed on the next library scan
|
||||||
|
unmappableFileRepository.save(new UnmappableFile(gameToBeDeleted.getPath()));
|
||||||
|
|
||||||
detectedGameRepository.deleteById(slug);
|
detectedGameRepository.deleteById(slug);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void deleteUnmappedFile(Long id) {
|
||||||
|
unmappableFileRepository.deleteById(id);
|
||||||
|
}
|
||||||
|
|
||||||
public DetectedGame confirmGame(String slug, boolean confirm) {
|
public DetectedGame confirmGame(String slug, boolean confirm) {
|
||||||
DetectedGame g = getDetectedGame(slug);
|
DetectedGame g = getDetectedGame(slug);
|
||||||
g.setConfirmedMatch(confirm);
|
g.setConfirmedMatch(confirm);
|
||||||
@@ -63,17 +73,17 @@ public class GameService {
|
|||||||
|
|
||||||
public DetectedGame mapPathToGame(String path, String slug) {
|
public DetectedGame mapPathToGame(String path, String slug) {
|
||||||
|
|
||||||
if(detectedGameRepository.existsBySlug(slug))
|
if (detectedGameRepository.existsBySlug(slug))
|
||||||
throw new ResponseStatusException(HttpStatus.CONFLICT, "Game with slug '%s' already exists in database.".formatted(slug));
|
throw new ResponseStatusException(HttpStatus.CONFLICT, "Game with slug '%s' already exists in database.".formatted(slug));
|
||||||
|
|
||||||
Optional<UnmappableFile> optionalUnmappableFile = unmappableFileRepository.findByPath(path);
|
Optional<UnmappableFile> optionalUnmappableFile = unmappableFileRepository.findByPath(path);
|
||||||
Optional<DetectedGame> optionalDetectedGame = detectedGameRepository.findByPath(path);
|
Optional<DetectedGame> optionalDetectedGame = detectedGameRepository.findByPath(path);
|
||||||
|
|
||||||
if(optionalUnmappableFile.isPresent()) {
|
if (optionalUnmappableFile.isPresent()) {
|
||||||
return mapUnmappableFile(optionalUnmappableFile.get(), slug);
|
return mapUnmappableFile(optionalUnmappableFile.get(), slug);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(optionalDetectedGame.isPresent()) {
|
if (optionalDetectedGame.isPresent()) {
|
||||||
return mapDetectedGame(optionalDetectedGame.get(), slug);
|
return mapDetectedGame(optionalDetectedGame.get(), slug);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,11 @@ public class FilenameUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static String getFilenameWithoutExtension(Path p) {
|
public static String getFilenameWithoutExtension(Path p) {
|
||||||
|
|
||||||
|
// If the path points to a folder, return the folder name
|
||||||
|
// Folders like "Counter Strike 1.6" would otherwise be returned as "Counter Strike 1"
|
||||||
|
if(p.toFile().isDirectory()) return FilenameUtils.getName(p.toString());
|
||||||
|
|
||||||
return FilenameUtils.getBaseName(p.toString());
|
return FilenameUtils.getBaseName(p.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
gameyfin:
|
gameyfin:
|
||||||
user: admin
|
user: admin
|
||||||
password: 112
|
password: 112
|
||||||
root: C:\Projects\privat\gameyfin-library
|
#root: C:\Projects\privat\gameyfin-library
|
||||||
#root: \\NAS-Simon\Öffentlich\Spiele
|
root: \\NAS-Simon\Öffentlich\Spiele
|
||||||
cache: ${gameyfin.root}\.gameyfin\cache
|
cache: ${gameyfin.root}\.gameyfin\cache
|
||||||
db: ${gameyfin.root}\.gameyfin\db
|
db: ${gameyfin.root}\.gameyfin\db
|
||||||
#db: ./data
|
#db: ./data
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
server:
|
|
||||||
error.include-stacktrace: never
|
|
||||||
|
|
||||||
spring:
|
|
||||||
mvc:
|
|
||||||
async.request-timeout: -1
|
|
||||||
jackson.default-property-inclusion: non_null
|
|
||||||
jpa:
|
|
||||||
database-platform: org.hibernate.dialect.H2Dialect
|
|
||||||
hibernate.ddl-auto: update
|
|
||||||
open-in-view: true
|
|
||||||
properties:
|
|
||||||
hibernate:
|
|
||||||
event.merge.entity_copy_observer: allow
|
|
||||||
@@ -1,6 +1,4 @@
|
|||||||
import {Observable} from "rxjs";
|
import {Observable} from "rxjs";
|
||||||
import {DetectedGameDto} from "../models/dtos/DetectedGameDto";
|
|
||||||
import {GameOverviewDto} from "../models/dtos/GameOverviewDto";
|
|
||||||
import {HttpResponse} from "@angular/common/http";
|
import {HttpResponse} from "@angular/common/http";
|
||||||
|
|
||||||
export interface LibraryApi {
|
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 {NgModule} from '@angular/core';
|
||||||
import {RouterModule, Routes} from '@angular/router';
|
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 {PageNotFoundComponent} from "./components/page-not-found/page-not-found.component";
|
||||||
import {NavbarLayoutComponent} from "./layouts/navbar-layout/navbar-layout.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 {LibraryOverviewComponent} from "./components/library-overview/library-overview.component";
|
||||||
import {GameDetailViewComponent} from "./components/game-detail-view/game-detail-view.component";
|
import {GameDetailViewComponent} from "./components/game-detail-view/game-detail-view.component";
|
||||||
|
import {LibraryManagementComponent} from "./components/library-management/library-management.component";
|
||||||
|
|
||||||
const appRoutes: Routes = [
|
const appRoutes: Routes = [
|
||||||
{
|
{
|
||||||
@@ -21,19 +20,12 @@ const appRoutes: Routes = [
|
|||||||
component: GameDetailViewComponent
|
component: GameDetailViewComponent
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '',
|
path: 'library-management',
|
||||||
redirectTo: '/library',
|
component: LibraryManagementComponent
|
||||||
pathMatch: 'full'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
component: FullpageLayoutComponent,
|
redirectTo: '/library',
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: '',
|
|
||||||
redirectTo: '/login',
|
|
||||||
pathMatch: 'full'
|
pathMatch: 'full'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -2,10 +2,8 @@ import {NgModule} from '@angular/core';
|
|||||||
import {BrowserModule} from '@angular/platform-browser';
|
import {BrowserModule} from '@angular/platform-browser';
|
||||||
|
|
||||||
import {AppComponent} from './app.component';
|
import {AppComponent} from './app.component';
|
||||||
import {FullpageLayoutComponent} from "./layouts/fullpage-layout/fullpage-layout.component";
|
|
||||||
import {NavbarLayoutComponent} from "./layouts/navbar-layout/navbar-layout.component";
|
import {NavbarLayoutComponent} from "./layouts/navbar-layout/navbar-layout.component";
|
||||||
import {PageNotFoundComponent} from "./components/page-not-found/page-not-found.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 {HeaderComponent} from "./components/header/header.component";
|
||||||
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
|
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
|
||||||
import {FormsModule, ReactiveFormsModule} from "@angular/forms";
|
import {FormsModule, ReactiveFormsModule} from "@angular/forms";
|
||||||
@@ -35,23 +33,26 @@ import {MatSnackBarModule} from '@angular/material/snack-bar';
|
|||||||
import {MatGridListModule} from "@angular/material/grid-list";
|
import {MatGridListModule} from "@angular/material/grid-list";
|
||||||
import {GameScreenshotComponent} from './components/game-screenshot/game-screenshot.component';
|
import {GameScreenshotComponent} from './components/game-screenshot/game-screenshot.component';
|
||||||
import {YouTubePlayerModule} from "@angular/youtube-player";
|
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 {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({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
AppComponent,
|
AppComponent,
|
||||||
HeaderComponent,
|
HeaderComponent,
|
||||||
FullpageLayoutComponent,
|
|
||||||
NavbarLayoutComponent,
|
NavbarLayoutComponent,
|
||||||
PageNotFoundComponent,
|
PageNotFoundComponent,
|
||||||
NotImplementedComponent,
|
|
||||||
ErrorDialogComponent,
|
ErrorDialogComponent,
|
||||||
LibraryOverviewComponent,
|
LibraryOverviewComponent,
|
||||||
GameCoverComponent,
|
GameCoverComponent,
|
||||||
GameDetailViewComponent,
|
GameDetailViewComponent,
|
||||||
GameScreenshotComponent,
|
GameScreenshotComponent,
|
||||||
GameVideoComponent
|
GameVideoComponent,
|
||||||
|
LibraryManagementComponent,
|
||||||
|
MapGameDialogComponent
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
@@ -80,7 +81,8 @@ import {MatChipsModule} from "@angular/material/chips";
|
|||||||
FlexLayoutModule,
|
FlexLayoutModule,
|
||||||
GridModule,
|
GridModule,
|
||||||
YouTubePlayerModule,
|
YouTubePlayerModule,
|
||||||
MatChipsModule
|
MatChipsModule,
|
||||||
|
MatTooltipModule
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -5,7 +5,11 @@
|
|||||||
|
|
||||||
<span class="spacer"></span>
|
<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>
|
<mat-icon>youtube_searched_for</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
<button mat-icon-button (click)="goToLibraryManagementScreen()">
|
||||||
|
<mat-icon>settings</mat-icon>
|
||||||
|
</button>
|
||||||
</mat-toolbar>
|
</mat-toolbar>
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ export class HeaderComponent {
|
|||||||
reloadLibrary(): void {
|
reloadLibrary(): void {
|
||||||
this.libraryService.scanLibrary().pipe(timeInterval()).subscribe({
|
this.libraryService.scanLibrary().pipe(timeInterval()).subscribe({
|
||||||
next: value => this.snackBar.open(`Library scan completed in ${Math.trunc(value.interval / 1000)} seconds.`, undefined, {duration: 2000}),
|
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(['/']);
|
this.router.navigate(['/']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
goToLibraryManagementScreen(): void {
|
||||||
|
this.router.navigate(['/library-management']);
|
||||||
|
}
|
||||||
|
|
||||||
notOnLibraryScreen(): boolean {
|
notOnLibraryScreen(): boolean {
|
||||||
return !(this.router.url === "/library");
|
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 {Injectable} from '@angular/core';
|
||||||
import {MatDialog, MatDialogConfig} from '@angular/material/dialog';
|
import {MatDialog, MatDialogConfig} from '@angular/material/dialog';
|
||||||
import {ErrorDialogComponent} from '../components/error-dialog/error-dialog.component';
|
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({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
@@ -24,4 +27,33 @@ export class DialogService {
|
|||||||
this.dialog.open(ErrorDialogComponent, dialogConfig);
|
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 {Injectable} from '@angular/core';
|
||||||
import {GamesApi} from "../api/GamesApi";
|
import {GamesApi} from "../api/GamesApi";
|
||||||
import {HttpClient} from "@angular/common/http";
|
import {HttpClient} from "@angular/common/http";
|
||||||
import {Observable} from "rxjs";
|
import {map, Observable} from "rxjs";
|
||||||
import {DetectedGameDto} from "../models/dtos/DetectedGameDto";
|
import {DetectedGameDto} from "../models/dtos/DetectedGameDto";
|
||||||
import {GameOverviewDto} from "../models/dtos/GameOverviewDto";
|
import {GameOverviewDto} from "../models/dtos/GameOverviewDto";
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@ export class GamesService implements GamesApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getAllGames(): Observable<DetectedGameDto[]> {
|
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> {
|
getGame(slug: String): Observable<DetectedGameDto> {
|
||||||
|
|||||||
Reference in New Issue
Block a user