Adding a chip per genre (only loading genres once)

This commit is contained in:
Zoe Roux 2020-09-14 23:34:47 +02:00
parent 8d5ee797ec
commit e4621bbdea
5 changed files with 202 additions and 94 deletions

View File

@ -40,6 +40,7 @@ import {MatAutocompleteModule} from "@angular/material/autocomplete";
import {MatExpansionModule} from "@angular/material/expansion";
import {InfiniteScrollModule} from "ngx-infinite-scroll";
import {ShowGridComponent} from "./components/show-grid/show-grid.component";
import {MatBadgeModule} from "@angular/material/badge";
@NgModule({
@ -87,7 +88,8 @@ import {ShowGridComponent} from "./components/show-grid/show-grid.component";
MatChipsModule,
MatAutocompleteModule,
MatExpansionModule,
InfiniteScrollModule
InfiniteScrollModule,
MatBadgeModule
],
bootstrap: [AppComponent]
})

View File

@ -1,6 +1,9 @@
<div class="container-fluid justify-content-center" *ngIf="this.sortEnabled">
<button mat-icon-button matTooltipPosition="below" matTooltip="Filter">
<mat-icon>filter_list</mat-icon>
<button mat-icon-button matTooltipPosition="below" matTooltip="Filter" [matMenuTriggerFor]="filterMenu">
<mat-icon [matBadge]="this.filters.length.toString()" [matBadgeHidden]="this.filters.length == 0"
matBadgeColor="warn" matBadgeSize="small">
filter_list
</mat-icon>
</button>
<button mat-button matTooltipPosition="below" matTooltip="Sort" [matMenuTriggerFor]="sortMenu">
<mat-icon>sort</mat-icon> Sort by {{this.sortType}}
@ -9,6 +12,12 @@
</button>
</div>
<mat-menu #filterMenu="matMenu">
<mat-chip-list>
<mat-chip *ngFor="let genre of this.genres">{{genre.name}}</mat-chip>
</mat-chip-list>
</mat-menu>
<mat-menu #sortMenu="matMenu">
<div *ngFor="let type of this.sortKeys">
<button *ngIf="type != this.sortType; else elseBlock;" mat-menu-item (click)="sort(type, true)">

View File

@ -1,12 +1,14 @@
import {Component, Input} from '@angular/core';
import {ActivatedRoute} from '@angular/router';
import {DomSanitizer} from '@angular/platform-browser';
import { Genre } from "../../../models/resources/genre";
import {LibraryItem} from "../../../models/resources/library-item";
import {Page} from "../../../models/page";
import {HttpClient} from "@angular/common/http";
import {Show, ShowRole} from "../../../models/resources/show";
import {Collection} from "../../../models/resources/collection";
import {ItemsUtils} from "../../misc/items-utils";
import { PreLoaderService } from "../../services/pre-loader.service";
@Component({
selector: 'app-items-grid',
@ -20,15 +22,22 @@ export class ItemsGridComponent
sortType: string = "title";
sortKeys: string[] = ["title", "start year", "end year"]
sortUp: boolean = true;
filters: string[] = [];
genres: Genre[];
constructor(private route: ActivatedRoute,
private sanitizer: DomSanitizer,
private loader: PreLoaderService,
public client: HttpClient)
{
this.route.data.subscribe((data) =>
{
this.page = data.items;
});
this.loader.load<Genre>("/api/genres?limit=0").subscribe(data =>
{
this.genres = data;
});
}
getThumb(slug: string)

View File

@ -0,0 +1,27 @@
import { HttpClient } from "@angular/common/http";
import { Injectable } from '@angular/core';
import { Page } from "../../models/page";
import { Observable, of } from "rxjs"
import { map } from "rxjs/operators"
@Injectable({
providedIn: 'root'
})
export class PreLoaderService
{
private cache: [string, any[]][] = [];
constructor(private http: HttpClient) { }
load<T>(route: string): Observable<T[]>
{
let loaded = this.cache.find(x => x[0] == route);
if (loaded != null)
return of(loaded[1]);
return this.http.get<Page<T>>(route).pipe(map(newData =>
{
this.cache.push([route, newData.items]);
return newData.items;
}));
}
}

View File

@ -1,92 +1,153 @@
{
"extends": "tslint:recommended",
"rules": {
"array-type": false,
"arrow-parens": false,
"deprecation": {
"severity": "warning"
},
"component-class-suffix": true,
"contextual-lifecycle": true,
"directive-class-suffix": true,
"directive-selector": [
true,
"attribute",
"app",
"camelCase"
],
"component-selector": [
true,
"element",
"app",
"kebab-case"
],
"import-blacklist": [
true,
"rxjs/Rx"
],
"interface-name": false,
"max-classes-per-file": false,
"max-line-length": [
true,
140
],
"member-access": false,
"member-ordering": [
true,
{
"order": [
"static-field",
"instance-field",
"static-method",
"instance-method"
]
}
],
"no-consecutive-blank-lines": false,
"no-console": [
true,
"debug",
"info",
"time",
"timeEnd",
"trace"
],
"no-empty": false,
"no-inferrable-types": [
true,
"ignore-params"
],
"no-non-null-assertion": true,
"no-redundant-jsdoc": true,
"no-switch-case-fall-through": true,
"no-use-before-declare": true,
"no-var-requires": false,
"object-literal-key-quotes": [
true,
"as-needed"
],
"object-literal-sort-keys": false,
"ordered-imports": false,
"quotemark": [
true,
"single"
],
"trailing-comma": false,
"no-conflicting-lifecycle": true,
"no-host-metadata-property": true,
"no-input-rename": true,
"no-inputs-metadata-property": true,
"no-output-native": true,
"no-output-on-prefix": true,
"no-output-rename": true,
"no-outputs-metadata-property": true,
"template-banana-in-box": true,
"template-no-negated-async": true,
"use-lifecycle-interface": true,
"use-pipe-transform-interface": true
},
"rulesDirectory": [
"codelyzer"
]
"extends": "tslint:recommended",
"rulesDirectory": [
"codelyzer"
],
"rules": {
"align": {
"options": [
"parameters",
"statements"
]
},
"array-type": false,
"arrow-return-shorthand": true,
"curly": true,
"deprecation": {
"severity": "warning"
},
"eofline": true,
"import-blacklist": [
true,
"rxjs/Rx"
],
"import-spacing": true,
"indent": {
"options": [
"tabs"
]
},
"max-classes-per-file": false,
"max-line-length": [
true,
120
],
"member-ordering": [
true,
{
"order": [
"static-field",
"instance-field",
"static-method",
"instance-method"
]
}
],
"no-console": [
true,
"debug",
"info",
"time",
"timeEnd",
"trace"
],
"no-empty": false,
"no-inferrable-types": [
true,
"ignore-params"
],
"no-non-null-assertion": true,
"no-redundant-jsdoc": true,
"no-switch-case-fall-through": true,
"no-var-requires": false,
"object-literal-key-quotes": [
true,
"as-needed"
],
"quotemark": [
true,
"double"
],
"semicolon": {
"options": [
"always"
]
},
"space-before-function-paren": {
"options": {
"anonymous": "never",
"asyncArrow": "always",
"constructor": "never",
"method": "never",
"named": "never"
}
},
"typedef": [
true,
"call-signature"
],
"typedef-whitespace": {
"options": [
{
"call-signature": "nospace",
"index-signature": "nospace",
"parameter": "nospace",
"property-declaration": "nospace",
"variable-declaration": "nospace"
},
{
"call-signature": "onespace",
"index-signature": "onespace",
"parameter": "onespace",
"property-declaration": "onespace",
"variable-declaration": "onespace"
}
]
},
"variable-name": {
"options": [
"ban-keywords",
"check-format",
"allow-pascal-case"
]
},
"whitespace": {
"options": [
"check-branch",
"check-decl",
"check-operator",
"check-separator",
"check-type",
"check-typecast",
"check-module"
]
},
"component-class-suffix": true,
"contextual-lifecycle": true,
"directive-class-suffix": true,
"no-conflicting-lifecycle": true,
"no-host-metadata-property": true,
"no-input-rename": true,
"no-inputs-metadata-property": true,
"no-output-native": true,
"no-output-on-prefix": true,
"no-output-rename": true,
"no-outputs-metadata-property": true,
"template-banana-in-box": true,
"template-no-negated-async": true,
"use-lifecycle-interface": true,
"use-pipe-transform-interface": true,
"directive-selector": [
true,
"attribute",
"app",
"camelCase"
],
"component-selector": [
true,
"element",
"app",
"kebab-case"
]
}
}