mirror of
https://github.com/BrenBroZAYT/gameyfin.git
synced 2026-06-13 16:40:01 +00:00
Added missing files
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
<div fxLayoutAlign="center center">
|
||||
<div>
|
||||
<mat-tab-group>
|
||||
<mat-tab label="Game mappings">
|
||||
<table mat-table [dataSource]="mappedGames" class="mat-elevation-z8">
|
||||
<ng-container matColumnDef="path">
|
||||
<th mat-header-cell *matHeaderCellDef> Path </th>
|
||||
<td mat-cell *matCellDef="let element"> {{element.path}} </td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="game">
|
||||
<th mat-header-cell *matHeaderCellDef> Game </th>
|
||||
<td mat-cell *matCellDef="let element"> {{element.title}} ({{getFullYearFromTimestamp(element.releaseDate)}})</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="actions">
|
||||
<th mat-header-cell *matHeaderCellDef>
|
||||
<button mat-icon-button (click)="refreshMappedGamesList()">
|
||||
<mat-icon>refresh</mat-icon>
|
||||
</button>
|
||||
</th>
|
||||
<td mat-cell *matCellDef="let element">
|
||||
<button mat-icon-button (click)="confirmGameMapping(element)" [disabled]="element.confirmedMatch">
|
||||
<mat-icon>check</mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button (click)="openCorrectMappingDialog(element)">
|
||||
<mat-icon>edit</mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button (click)="deleteGameMapping(element)">
|
||||
<mat-icon>delete</mat-icon>
|
||||
</button>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<tr mat-header-row *matHeaderRowDef="gameMappingTableColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: gameMappingTableColumns;"></tr>
|
||||
</table>
|
||||
</mat-tab>
|
||||
|
||||
|
||||
<mat-tab label="Unmapped files">
|
||||
<table mat-table [dataSource]="unmappedFiles" class="mat-elevation-z8">
|
||||
<ng-container matColumnDef="path">
|
||||
<th mat-header-cell *matHeaderCellDef> Path </th>
|
||||
<td mat-cell *matCellDef="let element"> {{element.path}} </td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="actions">
|
||||
<th mat-header-cell *matHeaderCellDef>
|
||||
<button mat-icon-button (click)="refreshUnmappedFilesList()">
|
||||
<mat-icon>refresh</mat-icon>
|
||||
</button>
|
||||
</th>
|
||||
<td mat-cell *matCellDef="let element">
|
||||
<button mat-icon-button (click)="openMapUnmappedFileDialog(element)">
|
||||
<mat-icon>edit</mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button (click)="deleteUnmappedFile(element)">
|
||||
<mat-icon>delete</mat-icon>
|
||||
</button>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<tr mat-header-row *matHeaderRowDef="unmappedGameTableColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: unmappedGameTableColumns;"></tr>
|
||||
</table>
|
||||
</mat-tab>
|
||||
</mat-tab-group>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -0,0 +1,3 @@
|
||||
td, th {
|
||||
padding: 16px !important;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { LibraryManagementComponent } from './library-management.component';
|
||||
|
||||
describe('LibraryManagementComponent', () => {
|
||||
let component: LibraryManagementComponent;
|
||||
let fixture: ComponentFixture<LibraryManagementComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ LibraryManagementComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(LibraryManagementComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,64 @@
|
||||
import {Component, OnInit} from '@angular/core';
|
||||
import {DetectedGameDto} from "../../models/dtos/DetectedGameDto";
|
||||
import {GamesService} from "../../services/games.service";
|
||||
import {LibraryManagementService} from "../../services/library-management.service";
|
||||
import {UnmappedFileDto} from "../../models/dtos/UnmappedFileDto";
|
||||
import {LibraryService} from "../../services/library.service";
|
||||
import {DialogService} from "../../services/dialog.service";
|
||||
|
||||
@Component({
|
||||
selector: 'app-library-management',
|
||||
templateUrl: './library-management.component.html',
|
||||
styleUrls: ['./library-management.component.scss']
|
||||
})
|
||||
export class LibraryManagementComponent implements OnInit {
|
||||
|
||||
gameMappingTableColumns: string[] = ["path", "game", "actions"];
|
||||
unmappedGameTableColumns: string[] = ["path", "actions"];
|
||||
|
||||
mappedGames!: DetectedGameDto[];
|
||||
unmappedFiles!: UnmappedFileDto[];
|
||||
|
||||
constructor(private gameService: GamesService,
|
||||
private libraryManagementService: LibraryManagementService,
|
||||
private dialogService: DialogService) {
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.refreshMappedGamesList();
|
||||
this.refreshUnmappedFilesList();
|
||||
}
|
||||
|
||||
refreshMappedGamesList(): void {
|
||||
this.gameService.getAllGames().subscribe(games => this.mappedGames = games);
|
||||
}
|
||||
|
||||
getFullYearFromTimestamp(timestamp: number): number {
|
||||
return new Date(timestamp).getFullYear();
|
||||
}
|
||||
|
||||
confirmGameMapping(mappedGame: DetectedGameDto): void {
|
||||
this.libraryManagementService.confirmGameMapping(mappedGame.slug).subscribe(() => mappedGame.confirmedMatch = true);
|
||||
}
|
||||
|
||||
deleteGameMapping(mappedGame: DetectedGameDto): void {
|
||||
this.libraryManagementService.deleteGame(mappedGame.slug).subscribe(() => this.mappedGames = this.mappedGames.filter(game => game !== mappedGame));
|
||||
}
|
||||
|
||||
openCorrectMappingDialog(mappedGame: DetectedGameDto): void {
|
||||
this.dialogService.correctGameMappingDialog(mappedGame);
|
||||
}
|
||||
|
||||
refreshUnmappedFilesList(): void {
|
||||
this.libraryManagementService.getUnmappedFiles().subscribe(unmappedFiles => this.unmappedFiles = unmappedFiles);
|
||||
}
|
||||
|
||||
deleteUnmappedFile(unmappedFile: UnmappedFileDto): void {
|
||||
this.libraryManagementService.deleteUnmappedFile(unmappedFile.id).subscribe(() => this.unmappedFiles = this.unmappedFiles.filter(uf => uf !== unmappedFile));
|
||||
}
|
||||
|
||||
openMapUnmappedFileDialog(unmappedFile: UnmappedFileDto): void {
|
||||
this.dialogService.mapUnmappedGameDialog(unmappedFile);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<h3 mat-dialog-title>Map game to IGDB slug</h3>
|
||||
<mat-dialog-content>
|
||||
<form fxLayout="column" fxLayoutAlign="space-evenly stretch">
|
||||
|
||||
<p>Path: {{path}}</p>
|
||||
<mat-form-field>
|
||||
<input matInput type="text" placeholder="IGDB Slug" [formControl]="newSlugInput" [value]="currentSlug"/>
|
||||
</mat-form-field>
|
||||
|
||||
</form>
|
||||
</mat-dialog-content>
|
||||
<mat-dialog-actions align="end">
|
||||
<button mat-raised-button mat-dialog-close color="accent">Cancel</button>
|
||||
<button mat-raised-button (click)="submit()">OK</button>
|
||||
</mat-dialog-actions>
|
||||
@@ -0,0 +1,23 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { MapGameDialogComponent } from './map-game-dialog.component';
|
||||
|
||||
describe('MapGameDialogComponent', () => {
|
||||
let component: MapGameDialogComponent;
|
||||
let fixture: ComponentFixture<MapGameDialogComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ MapGameDialogComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(MapGameDialogComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,37 @@
|
||||
import {Component, Inject, OnInit} from '@angular/core';
|
||||
import {FormBuilder, FormControl} from "@angular/forms";
|
||||
import {LibraryManagementService} from "../../services/library-management.service";
|
||||
import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog";
|
||||
import {PathToSlugDto} from "../../models/dtos/PathToSlugDto";
|
||||
|
||||
@Component({
|
||||
selector: 'app-map-game-dialog',
|
||||
templateUrl: './map-game-dialog.component.html',
|
||||
styleUrls: ['./map-game-dialog.component.scss']
|
||||
})
|
||||
export class MapGameDialogComponent implements OnInit {
|
||||
|
||||
path: string;
|
||||
currentSlug?: string;
|
||||
newSlugInput: FormControl;
|
||||
|
||||
constructor(private fb: FormBuilder,
|
||||
private libraryManagementService: LibraryManagementService,
|
||||
public dialogRef: MatDialogRef<MapGameDialogComponent>,
|
||||
@Inject(MAT_DIALOG_DATA) data: any) {
|
||||
this.path = data.path;
|
||||
this.currentSlug = data.slug;
|
||||
this.newSlugInput = new FormControl(this.currentSlug);
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
|
||||
close() {
|
||||
this.dialogRef.close();
|
||||
}
|
||||
|
||||
submit(): void {
|
||||
this.libraryManagementService.mapGame(new PathToSlugDto(this.newSlugInput.value, this.path)).subscribe(() => this.close())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { LibraryManagementService } from './library-management.service';
|
||||
|
||||
describe('LibraryManagementService', () => {
|
||||
let service: LibraryManagementService;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({});
|
||||
service = TestBed.inject(LibraryManagementService);
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
expect(service).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,39 @@
|
||||
import {Injectable} from '@angular/core';
|
||||
import {HttpClient} from "@angular/common/http";
|
||||
import {Observable} from "rxjs";
|
||||
import {DetectedGameDto} from "../models/dtos/DetectedGameDto";
|
||||
import {PathToSlugDto} from "../models/dtos/PathToSlugDto";
|
||||
import {UnmappedFileDto} from "../models/dtos/UnmappedFileDto";
|
||||
import {LibraryManagementApi} from "../api/LibraryManagementApi";
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class LibraryManagementService implements LibraryManagementApi {
|
||||
|
||||
private readonly apiPath = '/library-management';
|
||||
|
||||
constructor(private http: HttpClient) {
|
||||
}
|
||||
|
||||
mapGame(pathToSlugDto: PathToSlugDto): Observable<DetectedGameDto> {
|
||||
return this.http.post<DetectedGameDto>(`${this.apiPath}/map-path`, pathToSlugDto);
|
||||
}
|
||||
|
||||
getUnmappedFiles(): Observable<UnmappedFileDto[]> {
|
||||
return this.http.get<UnmappedFileDto[]>(`${this.apiPath}/unmapped-files`);
|
||||
}
|
||||
|
||||
confirmGameMapping(slug: string): Observable<DetectedGameDto> {
|
||||
return this.http.get<DetectedGameDto>(`${this.apiPath}/confirm-game/${slug}`);
|
||||
}
|
||||
|
||||
deleteGame(slug: string): Observable<Response> {
|
||||
return this.http.delete<Response>(`${this.apiPath}/delete-game/${slug}`);
|
||||
}
|
||||
|
||||
deleteUnmappedFile(id: number): Observable<Response> {
|
||||
return this.http.delete<Response>(`${this.apiPath}/delete-unmapped-file/${id}`);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user