mirror of
https://github.com/BrenBroZAYT/gameyfin.git
synced 2026-06-16 16:20:04 +00:00
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:
@@ -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
|
|
||||||
Generated
+3119
-11891
File diff suppressed because it is too large
Load Diff
+18
-18
@@ -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');
|
||||||
|
|||||||
+4
-2
@@ -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,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.
|
||||||
|
|||||||
@@ -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);
|
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
Reference in New Issue
Block a user