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
-16
View File
@@ -1,16 +0,0 @@
# This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
# For additional information regarding the format and rule options, please see:
# https://github.com/browserslist/browserslist#queries
# For the full list of supported browsers by the Angular framework, please see:
# https://angular.io/guide/browser-support
# You can see what browsers were selected by your queries by running:
# npx browserslist
last 1 Chrome version
last 1 Firefox version
last 2 Edge major versions
last 2 Safari major versions
last 2 iOS major versions
Firefox ESR
+3119 -11891
View File
File diff suppressed because it is too large Load Diff
+18 -18
View File
@@ -10,27 +10,27 @@
}, },
"private": true, "private": true,
"dependencies": { "dependencies": {
"@angular/animations": "^14.0.0", "@angular/animations": "^15.2.6",
"@angular/cdk": "^14.1.0", "@angular/cdk": "^15.2.6",
"@angular/common": "^14.0.0", "@angular/common": "^15.2.6",
"@angular/compiler": "^14.0.0", "@angular/compiler": "^15.2.6",
"@angular/core": "^14.0.0", "@angular/core": "^15.2.6",
"@angular/flex-layout": "^14.0.0-beta.40", "@angular/flex-layout": "^15.0.0-beta.42",
"@angular/forms": "^14.0.0", "@angular/forms": "^15.2.6",
"@angular/material": "^14.1.0", "@angular/material": "^15.2.6",
"@angular/platform-browser": "^14.0.0", "@angular/platform-browser": "^15.2.6",
"@angular/platform-browser-dynamic": "^14.0.0", "@angular/platform-browser-dynamic": "^15.2.6",
"@angular/router": "^14.0.0", "@angular/router": "^15.2.6",
"@angular/youtube-player": "^14.2.7", "@angular/youtube-player": "^15.2.6",
"mat-table-filter": "^10.2.0", "mat-table-filter": "^15.0.0",
"rxjs": "~7.5.0", "rxjs": "~7.8.0",
"tslib": "^2.3.0", "tslib": "^2.3.0",
"zone.js": "~0.11.8" "zone.js": "~0.11.8"
}, },
"devDependencies": { "devDependencies": {
"@angular-devkit/build-angular": "^14.0.7", "@angular-devkit/build-angular": "^15.2.5",
"@angular/cli": "~14.0.7", "@angular/cli": "~15.2.5",
"@angular/compiler-cli": "^14.0.0", "@angular/compiler-cli": "^15.2.6",
"@types/jasmine": "~4.0.0", "@types/jasmine": "~4.0.0",
"jasmine-core": "~4.1.0", "jasmine-core": "~4.1.0",
"karma": "~6.4.1", "karma": "~6.4.1",
@@ -38,6 +38,6 @@
"karma-coverage": "~2.2.0", "karma-coverage": "~2.2.0",
"karma-jasmine": "~5.1.0", "karma-jasmine": "~5.1.0",
"karma-jasmine-html-reporter": "~2.0.0", "karma-jasmine-html-reporter": "~2.0.0",
"typescript": "~4.7.2" "typescript": "^4.9.0"
} }
} }
@@ -3,29 +3,31 @@
<div fxLayout="column" fxFlex="0 1 75" fxLayoutGap="16px" fxFlex.lt-lg="95"> <div fxLayout="column" fxFlex="0 1 75" fxLayoutGap="16px" fxFlex.lt-lg="95">
<div fxLayout="row" fxLayout.lt-lg="column" fxLayoutGap="16px"> <div fxLayout="row" fxLayout.lt-lg="column" fxLayoutGap="16px">
<mat-card fxFlex="100" fxLayout="row" fxLayout.lt-lg="column" fxLayoutGap="16px"> <mat-card>
<div fxLayoutAlign="start" fxLayoutAlign.lt-lg="center"> <mat-card-content fxLayout="row" fxLayout.lt-lg="column" fxLayoutGap="16px">
<img src="v1/images/{{game.coverId}}" style="max-height: 352px" alt="Game cover"> <div fxLayoutAlign="start" fxLayoutAlign.lt-lg="center">
</div> <img src="v1/images/{{game.coverId}}" style="max-height: 352px" alt="Game cover">
<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>
<div *ngIf="companiesWithLogo.length > 0"> <div fxLayout="column" fxLayoutGap="8px" fxLayoutAlign="space-between">
<h2>Developed by</h2> <div fxLayoutGap="8px">
<div fxLayout="row wrap" fxLayoutGap="8px grid"> <h1 style="display: inline-block">{{game.title}}</h1>
<div *ngFor="let company of companiesWithLogo" class="company-logos"> <h3 style="display: inline-block; font-style: italic">{{game.releaseDate | date: 'yyyy'}}</h3>
<img src="v1/images/{{company.logoId}}" alt="{{company.name}}" [matTooltip]="company.name">
<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>
</div> </div>
</div> </mat-card-content>
</mat-card> </mat-card>
<div fxFlex><!-- Spacer --></div> <div fxFlex><!-- Spacer --></div>
@@ -33,10 +35,10 @@
<div fxLayout="column" fxFlex="40" fxLayoutGap="16px"> <div fxLayout="column" fxFlex="40" fxLayoutGap="16px">
<div fxLayout="row" fxLayoutAlign="start center" 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> <mat-icon>refresh</mat-icon>
</button> </button>
<button mat-raised-button color="primary" (click)="downloadGame()"> <button mat-fab color="primary" (click)="downloadGame()">
<mat-icon>download</mat-icon> <mat-icon>download</mat-icon>
</button> </button>
<b style="font-size: 24px">Download ({{bytesAsHumanReadableString(game.diskSize)}})</b> <b style="font-size: 24px">Download ({{bytesAsHumanReadableString(game.diskSize)}})</b>
@@ -45,26 +47,26 @@
<div fxLayout="column" fxLayoutGap="24px"> <div fxLayout="column" fxLayoutGap="24px">
<div *ngIf="game.genres !== undefined && game.genres.length > 0"> <div *ngIf="game.genres !== undefined && game.genres.length > 0">
<h2>Genres</h2> <h2>Genres</h2>
<mat-chip-list> <mat-chip-listbox>
<mat-chip *ngFor="let genre of game.genres" <mat-chip-option *ngFor="let genre of game.genres"
(click)="goToLibraryWithFilter('genres', genre.slug)">{{genre.name}}</mat-chip> (click)="goToLibraryWithFilter('genres', genre.slug)">{{genre.name}}</mat-chip-option>
</mat-chip-list> </mat-chip-listbox>
</div> </div>
<div *ngIf="game.themes !== undefined && game.themes.length > 0"> <div *ngIf="game.themes !== undefined && game.themes.length > 0">
<h2>Themes</h2> <h2>Themes</h2>
<mat-chip-list> <mat-chip-listbox>
<mat-chip *ngFor="let theme of game.themes" <mat-chip-option *ngFor="let theme of game.themes"
(click)="goToLibraryWithFilter('themes', theme.slug)">{{theme.name}}</mat-chip> (click)="goToLibraryWithFilter('themes', theme.slug)">{{theme.name}}</mat-chip-option>
</mat-chip-list> </mat-chip-listbox>
</div> </div>
<div *ngIf="game.platforms !== undefined && game.platforms.length > 0"> <div *ngIf="game.platforms !== undefined && game.platforms.length > 0">
<h2>Platforms</h2> <h2>Platforms</h2>
<mat-chip-list> <mat-chip-listbox>
<mat-chip *ngFor="let platform of game.platforms" [disabled]="game.library == undefined || !hasPlatform(game.library, platform)" <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> (click)="goToLibraryWithFilter('platforms', platform.slug)">{{platform.name}}</mat-chip-option>
</mat-chip-list> </mat-chip-listbox>
</div> </div>
</div> </div>
@@ -1,8 +1,4 @@
.mat-card { .company-logos img {
// min-height: max-content; 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" <div fxFlex.gt-md="0 1 15" fxLayout="column" fxLayoutGap="16px" fxLayoutAlign.lt-lg="start center"
fxFlex.lt-lg="100" [ngClass.gt-md]="'sticky'"> 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" <button mat-icon-button *ngIf="searchTerm.length > 0" matTooltip="Clear search input"
(click)="clearSearchTerm()"> (click)="clearSearchTerm()">
<mat-icon>close</mat-icon> <mat-icon>close</mat-icon>
</button> </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> <mat-icon>search</mat-icon>
</button> </button>
<mat-form-field fxFlex> <mat-form-field appearance="outline" subscriptSizing="dynamic" fxFlex>
<input type="text" matInput [matAutocomplete]="librarySearchAutocomplete" [(ngModel)]="searchTerm" <input matInput [matAutocomplete]="librarySearchAutocomplete" [(ngModel)]="searchTerm"
(ngModelChange)="refreshLibraryView()"> (ngModelChange)="refreshLibraryView()">
<mat-autocomplete #librarySearchAutocomplete="matAutocomplete"> <mat-autocomplete #librarySearchAutocomplete="matAutocomplete" hideSingleSelectionIndicator panelWidth="auto">
<mat-option *ngFor="let game of games" [value]="game.title"> <mat-option *ngFor="let game of games" [value]="game.title">
{{game.title}} {{game.title}}
</mat-option> </mat-option>
</mat-autocomplete> </mat-autocomplete>
</mat-form-field> </mat-form-field>
</mat-card> </div>
<mat-card fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="20px" class="mat-card-48"> <mat-card>
<h3 class="filter-category-title" style="white-space: nowrap; padding-left: 6px">Sort by: </h3> <mat-card-content fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="20px">
<mat-select [(value)]="selectedSortOption" (valueChange)="refreshLibraryView()"> <h3 class="filter-category-title" style="white-space: nowrap; padding-left: 6px">Sort by: </h3>
<mat-option *ngFor="let sortOption of sortOptions" [value]="sortOption"> <mat-select [(value)]="selectedSortOption" (valueChange)="refreshLibraryView()" hideSingleSelectionIndicator>
{{sortOption.title}} <mat-option *ngFor="let sortOption of sortOptions" [value]="sortOption">
</mat-option> {{sortOption.title}}
</mat-select> </mat-option>
</mat-select>
</mat-card-content>
</mat-card> </mat-card>
<mat-expansion-panel [expanded]="filterExpansionState.gamemodes"> <mat-expansion-panel [expanded]="filterExpansionState.gamemodes">
@@ -38,16 +38,14 @@
margin-bottom: 0; margin-bottom: 0;
} }
.mat-card-48 { /*TODO(mdc-migration): The following rule targets internal classes of checkbox that may no longer apply for the MDC version.*/
height: 48px; ::ng-deep .mat-mdc-text-field-wrapper {
}
::ng-deep .mat-checkbox-frame {
$config: mat.get-color-config($dark-theme); $config: mat.get-color-config($dark-theme);
$primary-palette: map.get($config, 'primary'); $primary-palette: map.get($config, 'primary');
border-color: mat.get-color-from-palette($primary-palette, 500) !important; 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 { ::ng-deep .mat-form-field-underline {
$config: mat.get-color-config($dark-theme); $config: mat.get-color-config($dark-theme);
$primary-palette: map.get($config, 'primary'); $primary-palette: map.get($config, 'primary');
@@ -1,10 +1,12 @@
import {AfterViewInit, Component, Input, OnChanges, SimpleChanges, ViewChild} from '@angular/core'; import {AfterViewInit, Component, Input, OnChanges, SimpleChanges, ViewChild} from '@angular/core';
import {MatPaginator} from '@angular/material/paginator'; import {MatPaginator} from '@angular/material/paginator';
import {MatSort} from '@angular/material/sort'; 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 {LibraryDto} from "../../models/dtos/LibraryDto";
import {LibraryScanRequestDto} from "../../models/dtos/LibraryScanRequestDto"; import {LibraryScanRequestDto} from "../../models/dtos/LibraryScanRequestDto";
import {GamesService} from "../../services/games.service";
import {LibraryManagementService} from "../../services/library-management.service"; import {LibraryManagementService} from "../../services/library-management.service";
import {DialogService} from "../../services/dialog.service"; import {DialogService} from "../../services/dialog.service";
import {MatSnackBar} from '@angular/material/snack-bar'; import {MatSnackBar} from '@angular/material/snack-bar';
@@ -25,8 +25,12 @@ export class ProgressBarColorDirective implements OnChanges{
updateColor(): void{ updateColor(): void{
// update dynamic style with the uniqueAttr // update dynamic style with the uniqueAttr
this.styleEl.innerText = ` this.styleEl.innerText = `
[${this.uniqueAttr}] .mat-progress-bar-fill::after { [${this.uniqueAttr}] .mdc-linear-progress__bar-inner {
background-color: ${this.progressBarColor}; 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 // 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. // have to load a single css file for Angular Material in your app.
// Be sure that you only ever include this mixin once! // 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 mat.core();
// Include theme styles for core and each component used in your app. // Include theme styles for core and each component used in your app.
-12
View File
@@ -7,20 +7,8 @@ import {
platformBrowserDynamicTesting platformBrowserDynamicTesting
} from '@angular/platform-browser-dynamic/testing'; } 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. // First, initialize the Angular testing environment.
getTestBed().initTestEnvironment( getTestBed().initTestEnvironment(
BrowserDynamicTestingModule, BrowserDynamicTestingModule,
platformBrowserDynamicTesting(), platformBrowserDynamicTesting(),
); );
// Then we find all the tests.
const context = require.context('./', true, /\.spec\.ts$/);
// And load the modules.
context.keys().forEach(context);
+3 -2
View File
@@ -18,12 +18,13 @@
"resolveJsonModule": true, "resolveJsonModule": true,
"allowSyntheticDefaultImports": true, "allowSyntheticDefaultImports": true,
"importHelpers": true, "importHelpers": true,
"target": "es2020", "target": "ES2022",
"module": "es2020", "module": "es2020",
"lib": [ "lib": [
"es2020", "es2020",
"dom" "dom"
] ],
"useDefineForClassFields": false
}, },
"angularCompilerOptions": { "angularCompilerOptions": {
"enableI18nLegacyMessageIdFormat": false, "enableI18nLegacyMessageIdFormat": false,