Update frontend to Angular v15 (#110)

* Update Typescript to 4.9.0

* Update Angular to v15

* Update Angular Flex Layout to v15

* Update Angular CDK to v15

* Update Angular CDK to v15

* Update Angular Material to v15

* WIP: Update Angular Material to v15

* Fix progress bar colors

* Fix company logos size

* Update angular minor version

* Update mat-table-filter
Update @angular/youtube-player

* Update rxjs

* Fix search-bar layout
Fix autocomplete layout
Change mat-icon-button to mat-fab in game-detail-view

* Fix sort selector drop-down checkmark
This commit is contained in:
Simon
2023-04-10 01:32:02 +02:00
committed by GitHub
parent 2231077935
commit a79a7ff8e8
12 changed files with 3216 additions and 12001 deletions
@@ -3,29 +3,31 @@
<div fxLayout="column" fxFlex="0 1 75" fxLayoutGap="16px" fxFlex.lt-lg="95">
<div fxLayout="row" fxLayout.lt-lg="column" fxLayoutGap="16px">
<mat-card fxFlex="100" fxLayout="row" fxLayout.lt-lg="column" fxLayoutGap="16px">
<div fxLayoutAlign="start" fxLayoutAlign.lt-lg="center">
<img src="v1/images/{{game.coverId}}" style="max-height: 352px" alt="Game cover">
</div>
<div fxLayout="column" fxLayoutGap="8px" fxLayoutAlign="space-between">
<div fxLayoutGap="8px">
<h1 style="display: inline-block">{{game.title}}</h1>
<h3 style="display: inline-block; font-style: italic">{{game.releaseDate | date: 'yyyy'}}</h3>
<h2>Description</h2>
<p>{{game.summary}}</p>
<mat-card>
<mat-card-content fxLayout="row" fxLayout.lt-lg="column" fxLayoutGap="16px">
<div fxLayoutAlign="start" fxLayoutAlign.lt-lg="center">
<img src="v1/images/{{game.coverId}}" style="max-height: 352px" alt="Game cover">
</div>
<div *ngIf="companiesWithLogo.length > 0">
<h2>Developed by</h2>
<div fxLayout="row wrap" fxLayoutGap="8px grid">
<div *ngFor="let company of companiesWithLogo" class="company-logos">
<img src="v1/images/{{company.logoId}}" alt="{{company.name}}" [matTooltip]="company.name">
<div fxLayout="column" fxLayoutGap="8px" fxLayoutAlign="space-between">
<div fxLayoutGap="8px">
<h1 style="display: inline-block">{{game.title}}</h1>
<h3 style="display: inline-block; font-style: italic">{{game.releaseDate | date: 'yyyy'}}</h3>
<h2>Description</h2>
<p>{{game.summary}}</p>
</div>
<div *ngIf="companiesWithLogo.length > 0">
<h2>Developed by</h2>
<div fxLayout="row wrap" fxLayoutGap="8px grid">
<div *ngFor="let company of companiesWithLogo" class="company-logos">
<img src="v1/images/{{company.logoId}}" alt="{{company.name}}" [matTooltip]="company.name">
</div>
</div>
</div>
</div>
</div>
</mat-card-content>
</mat-card>
<div fxFlex><!-- Spacer --></div>
@@ -33,10 +35,10 @@
<div fxLayout="column" fxFlex="40" fxLayoutGap="16px">
<div fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="16px">
<button mat-raised-button color="secondary" (click)="refreshGame()" title="Refresh metadata">
<button mat-fab color="secondary" (click)="refreshGame()" title="Refresh metadata">
<mat-icon>refresh</mat-icon>
</button>
<button mat-raised-button color="primary" (click)="downloadGame()">
<button mat-fab color="primary" (click)="downloadGame()">
<mat-icon>download</mat-icon>
</button>
<b style="font-size: 24px">Download ({{bytesAsHumanReadableString(game.diskSize)}})</b>
@@ -45,26 +47,26 @@
<div fxLayout="column" fxLayoutGap="24px">
<div *ngIf="game.genres !== undefined && game.genres.length > 0">
<h2>Genres</h2>
<mat-chip-list>
<mat-chip *ngFor="let genre of game.genres"
(click)="goToLibraryWithFilter('genres', genre.slug)">{{genre.name}}</mat-chip>
</mat-chip-list>
<mat-chip-listbox>
<mat-chip-option *ngFor="let genre of game.genres"
(click)="goToLibraryWithFilter('genres', genre.slug)">{{genre.name}}</mat-chip-option>
</mat-chip-listbox>
</div>
<div *ngIf="game.themes !== undefined && game.themes.length > 0">
<h2>Themes</h2>
<mat-chip-list>
<mat-chip *ngFor="let theme of game.themes"
(click)="goToLibraryWithFilter('themes', theme.slug)">{{theme.name}}</mat-chip>
</mat-chip-list>
<mat-chip-listbox>
<mat-chip-option *ngFor="let theme of game.themes"
(click)="goToLibraryWithFilter('themes', theme.slug)">{{theme.name}}</mat-chip-option>
</mat-chip-listbox>
</div>
<div *ngIf="game.platforms !== undefined && game.platforms.length > 0">
<h2>Platforms</h2>
<mat-chip-list>
<mat-chip *ngFor="let platform of game.platforms" [disabled]="game.library == undefined || !hasPlatform(game.library, platform)"
(click)="goToLibraryWithFilter('platforms', platform.slug)">{{platform.name}}</mat-chip>
</mat-chip-list>
<mat-chip-listbox>
<mat-chip-option *ngFor="let platform of game.platforms" [disabled]="game.library == undefined || !hasPlatform(game.library, platform)"
(click)="goToLibraryWithFilter('platforms', platform.slug)">{{platform.name}}</mat-chip-option>
</mat-chip-listbox>
</div>
</div>
@@ -1,8 +1,4 @@
.mat-card {
// min-height: max-content;
.company-logos img {
max-height: 52px;
max-width: 260px;
}
.company-logos img {
max-height: 52px;
max-width: 260px;
}
@@ -26,34 +26,37 @@
<div fxFlex.gt-md="0 1 15" fxLayout="column" fxLayoutGap="16px" fxLayoutAlign.lt-lg="start center"
fxFlex.lt-lg="100" [ngClass.gt-md]="'sticky'">
<mat-card fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="6px" class="mat-card-48">
<div fxLayout="row" fxLayoutAlign="start center">
<button mat-icon-button *ngIf="searchTerm.length > 0" matTooltip="Clear search input"
(click)="clearSearchTerm()">
<mat-icon>close</mat-icon>
</button>
<button mat-icon-button *ngIf="searchTerm.length === 0" matTooltip="Search for games by title">
<button mat-icon-button *ngIf="searchTerm.length === 0" matTooltip="Search for games by title"
style="pointer-events: none">
<mat-icon>search</mat-icon>
</button>
<mat-form-field fxFlex>
<input type="text" matInput [matAutocomplete]="librarySearchAutocomplete" [(ngModel)]="searchTerm"
<mat-form-field appearance="outline" subscriptSizing="dynamic" fxFlex>
<input matInput [matAutocomplete]="librarySearchAutocomplete" [(ngModel)]="searchTerm"
(ngModelChange)="refreshLibraryView()">
<mat-autocomplete #librarySearchAutocomplete="matAutocomplete">
<mat-autocomplete #librarySearchAutocomplete="matAutocomplete" hideSingleSelectionIndicator panelWidth="auto">
<mat-option *ngFor="let game of games" [value]="game.title">
{{game.title}}
</mat-option>
</mat-autocomplete>
</mat-form-field>
</mat-card>
</div>
<mat-card fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="20px" class="mat-card-48">
<h3 class="filter-category-title" style="white-space: nowrap; padding-left: 6px">Sort by: </h3>
<mat-select [(value)]="selectedSortOption" (valueChange)="refreshLibraryView()">
<mat-option *ngFor="let sortOption of sortOptions" [value]="sortOption">
{{sortOption.title}}
</mat-option>
</mat-select>
<mat-card>
<mat-card-content fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="20px">
<h3 class="filter-category-title" style="white-space: nowrap; padding-left: 6px">Sort by: </h3>
<mat-select [(value)]="selectedSortOption" (valueChange)="refreshLibraryView()" hideSingleSelectionIndicator>
<mat-option *ngFor="let sortOption of sortOptions" [value]="sortOption">
{{sortOption.title}}
</mat-option>
</mat-select>
</mat-card-content>
</mat-card>
<mat-expansion-panel [expanded]="filterExpansionState.gamemodes">
@@ -38,16 +38,14 @@
margin-bottom: 0;
}
.mat-card-48 {
height: 48px;
}
::ng-deep .mat-checkbox-frame {
/*TODO(mdc-migration): The following rule targets internal classes of checkbox that may no longer apply for the MDC version.*/
::ng-deep .mat-mdc-text-field-wrapper {
$config: mat.get-color-config($dark-theme);
$primary-palette: map.get($config, 'primary');
border-color: mat.get-color-from-palette($primary-palette, 500) !important;
}
/*TODO(mdc-migration): The following rule targets internal classes of form-field that may no longer apply for the MDC version.*/
::ng-deep .mat-form-field-underline {
$config: mat.get-color-config($dark-theme);
$primary-palette: map.get($config, 'primary');
@@ -1,10 +1,12 @@
import {AfterViewInit, Component, Input, OnChanges, SimpleChanges, ViewChild} from '@angular/core';
import {MatPaginator} from '@angular/material/paginator';
import {MatSort} from '@angular/material/sort';
import {MatTable, MatTableDataSource} from '@angular/material/table';
import {
MatTable,
MatTableDataSource
} from '@angular/material/table';
import {LibraryDto} from "../../models/dtos/LibraryDto";
import {LibraryScanRequestDto} from "../../models/dtos/LibraryScanRequestDto";
import {GamesService} from "../../services/games.service";
import {LibraryManagementService} from "../../services/library-management.service";
import {DialogService} from "../../services/dialog.service";
import {MatSnackBar} from '@angular/material/snack-bar';
@@ -25,8 +25,12 @@ export class ProgressBarColorDirective implements OnChanges{
updateColor(): void{
// update dynamic style with the uniqueAttr
this.styleEl.innerText = `
[${this.uniqueAttr}] .mat-progress-bar-fill::after {
background-color: ${this.progressBarColor};
[${this.uniqueAttr}] .mdc-linear-progress__bar-inner {
border-color: ${this.progressBarColor};
}
[${this.uniqueAttr}] .mdc-linear-progress__buffer-bar {
background-color: ${this.progressBarColor}55 !important;
}
`;
}
+9
View File
@@ -9,6 +9,15 @@
// Include the common styles for Angular Material. We include this here so that you only
// have to load a single css file for Angular Material in your app.
// Be sure that you only ever include this mixin once!
// TODO(v15): As of v15 mat.legacy-core no longer includes default typography styles.
// The following line adds:
// 1. Default typography styles for all components
// 2. Styles for typography hierarchy classes (e.g. .mat-headline-1)
// If you specify typography styles for the components you use elsewhere, you should delete this line.
// If you don't need the default component typographies but still want the hierarchy styles,
// you can delete this line and instead use:
// `@include mat.legacy-typography-hierarchy(mat.define-typography-config());`
@include mat.all-component-typographies();
@include mat.core();
// Include theme styles for core and each component used in your app.
-12
View File
@@ -7,20 +7,8 @@ import {
platformBrowserDynamicTesting
} from '@angular/platform-browser-dynamic/testing';
declare const require: {
context(path: string, deep?: boolean, filter?: RegExp): {
<T>(id: string): T;
keys(): string[];
};
};
// First, initialize the Angular testing environment.
getTestBed().initTestEnvironment(
BrowserDynamicTestingModule,
platformBrowserDynamicTesting(),
);
// Then we find all the tests.
const context = require.context('./', true, /\.spec\.ts$/);
// And load the modules.
context.keys().forEach(context);