Library Recomendations (#1236)
* Updated cover regex for finding cover images in archives to ignore back_cover or back-cover * Fixed an issue where Tags wouldn't save due to not pulling them from the DB. * Refactored All series to it's own lazy loaded module * Modularized Dashboard and library detail. Had to change main dashboard page to be libraries. Subject to change. * Refactored login component into registration module * Series Detail module created * Refactored nav stuff into it's own module, not lazy loaded, but self contained. * Refactored theme component into a dev only module so we don't incur load for temp testing modules * Finished off modularization code. Only missing thing is to re-introduce some dashboard functionality for library view. * Implemented a basic recommendation page for library detail
This commit is contained in:
parent
743a3ba935
commit
f237aa7ab7
77 changed files with 1077 additions and 501 deletions
18
UI/Web/src/app/dev-only/dev-only-routing.module.ts
Normal file
18
UI/Web/src/app/dev-only/dev-only-routing.module.ts
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
import { ThemeTestComponent } from './theme-test/theme-test.component';
|
||||
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: ThemeTestComponent,
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes), ],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class DevOnlyRoutingModule { }
|
||||
37
UI/Web/src/app/dev-only/dev-only.module.ts
Normal file
37
UI/Web/src/app/dev-only/dev-only.module.ts
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { NgbAccordionModule, NgbNavModule } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { CardsModule } from '../cards/cards.module';
|
||||
import { TypeaheadModule } from '../typeahead/typeahead.module';
|
||||
import { ThemeTestComponent } from './theme-test/theme-test.component';
|
||||
import { SharedModule } from '../shared/shared.module';
|
||||
import { PipeModule } from '../pipe/pipe.module';
|
||||
import { DevOnlyRoutingModule } from './dev-only-routing.module';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
|
||||
/**
|
||||
* This module contains components that aren't meant to ship with main code. They are there to test things out. This module may be deleted in future updates.
|
||||
*/
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
ThemeTestComponent
|
||||
],
|
||||
imports: [
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
|
||||
|
||||
TypeaheadModule,
|
||||
CardsModule,
|
||||
NgbAccordionModule,
|
||||
NgbNavModule,
|
||||
|
||||
|
||||
SharedModule,
|
||||
PipeModule,
|
||||
|
||||
DevOnlyRoutingModule
|
||||
]
|
||||
})
|
||||
export class DevOnlyModule { }
|
||||
188
UI/Web/src/app/dev-only/theme-test/theme-test.component.html
Normal file
188
UI/Web/src/app/dev-only/theme-test/theme-test.component.html
Normal file
|
|
@ -0,0 +1,188 @@
|
|||
<h1>Themes</h1>
|
||||
<button class="btn btn-primary" (click)="themeService?.setTheme('dark')">Dark</button>
|
||||
<button class="btn btn-primary" (click)="themeService?.setTheme('light')">Light</button>
|
||||
<button class="btn btn-primary" (click)="themeService?.setTheme('E-Ink')">E-ink</button>
|
||||
<button class="btn btn-primary" (click)="themeService?.setTheme('custom')">Custom</button>
|
||||
|
||||
|
||||
|
||||
<h2>Buttons</h2>
|
||||
<button class="btn btn-primary">Primary</button>
|
||||
<button class="btn btn-secondary">secondary</button>
|
||||
<button class="btn btn-secondary alt">secondary alt</button>
|
||||
<button class="btn btn-outline-primary">outline primary</button>
|
||||
<button class="btn btn-outline-secondary">outline secondary</button>
|
||||
<button class="btn btn-link">btn link</button>
|
||||
<button class="btn btn-icon">
|
||||
<i class="fa fa-angle-left"></i> Icon
|
||||
</button>
|
||||
|
||||
<h2>Toastr</h2>
|
||||
|
||||
<button class="btn btn-primary" (click)="toastr.success('Test')">Success</button>
|
||||
<button class="btn btn-danger" (click)="toastr.error('Test')">Error</button>
|
||||
<button class="btn btn-secondary" (click)="toastr.warning('Test')">Warning</button>
|
||||
<button class="btn btn-link" (click)="toastr.info('Test')">Info</button>
|
||||
|
||||
<h2>Inputs</h2>
|
||||
<p>Inputs should always have class="form-control" on them</p>
|
||||
<label>Normal</label>
|
||||
<input type="text" class="form-control">
|
||||
<label>Readonly</label>
|
||||
<input type="text" readonly class="form-control">
|
||||
<label>Placeholder</label>
|
||||
<input type="text" placeholder="Hello, I'm a placeholder" class="form-control">
|
||||
<label>Disabled</label>
|
||||
<input type="text" placeholder="Hello, I'm a placeholder" [disabled]="true" class="form-control">
|
||||
|
||||
<h2>Checkbox</h2>
|
||||
<div class="mb-3">
|
||||
<label for="stat-collection" class="form-label" aria-describedby="collection-info">Allow Anonymous Usage Collection</label>
|
||||
<div class="form-check">
|
||||
<input id="stat-collection" type="checkbox" aria-label="Stat Collection" class="form-check-input">
|
||||
<label for="stat-collection" class="form-check-label">Normal Checkbox</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="stat-collection" class="form-label" aria-describedby="collection-info">Allow Anonymous Usage Collection</label>
|
||||
<div class="form-check">
|
||||
<input id="stat-collection" type="checkbox" aria-label="Stat Collection" class="form-check-input" [disabled]="true">
|
||||
<label for="stat-collection" class="form-check-label">Disabled Checkbox</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2>Radio</h2>
|
||||
<p>Labels should have form-check-label on them and inputs form-check-input</p>
|
||||
<div class="mb-3">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="radio" id="site-dark-mode" [value]="true" aria-labelledby="site-dark-mode-label">
|
||||
<label class="form-check-label" for="site-dark-mode">True</label>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="radio" id="site-not-dark-mode2" [value]="false" aria-labelledby="site-dark-mode-label">
|
||||
<label class="form-check-label" for="site-not-dark-mode2">False</label>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="radio" id="site-not-dark-mode3" [disabled]="true" [value]="false" aria-labelledby="site-dark-mode-label">
|
||||
<label class="form-check-label" for="site-not-dark-mode3">Disabled</label>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="radio" id="site-not-dark-mode4" readonly [value]="false" aria-labelledby="site-dark-mode-label">
|
||||
<label class="form-check-label" for="site-not-dark-mode4">Readonly</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<h2>Nav tabs</h2>
|
||||
<h3>Tabs</h3>
|
||||
<ul ngbNav #nav="ngbNav" [(activeId)]="active" class="nav-tabs nav-pills">
|
||||
<li *ngFor="let tab of tabs" [ngbNavItem]="tab">
|
||||
<a ngbNavLink routerLink=".">{{ tab.title | sentenceCase }}</a>
|
||||
<ng-template ngbNavContent>
|
||||
<ng-container>
|
||||
Tab 1
|
||||
</ng-container>
|
||||
<ng-container>
|
||||
Tab 2
|
||||
</ng-container>
|
||||
</ng-template>
|
||||
</li>
|
||||
</ul>
|
||||
<div [ngbNavOutlet]="nav" class="mt-3"></div>
|
||||
|
||||
<h3>Tabs</h3>
|
||||
<nav role="navigation">
|
||||
<ul ngbNav #nav="ngbNav" [(activeId)]="active" class="nav nav-pills justify-content-center mt-3" role="tab">
|
||||
<li *ngFor="let tab of tabs" [ngbNavItem]="tab" class="nav-item">
|
||||
<a ngbNavLink routerLink="." [fragment]="tab.fragment">{{ tab.title | titlecase }}</a>
|
||||
<ng-template ngbNavContent>
|
||||
<ng-container>
|
||||
Tab 1
|
||||
</ng-container>
|
||||
<ng-container>
|
||||
Tab 2
|
||||
</ng-container>
|
||||
</ng-template>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
<div [ngbNavOutlet]="nav" class="mt-3"></div>
|
||||
|
||||
<h2>Tag Badge</h2>
|
||||
<div class="g-2">
|
||||
<app-tag-badge [selectionMode]="TagBadgeCursor.Selectable">Selectable</app-tag-badge>
|
||||
<app-tag-badge [selectionMode]="TagBadgeCursor.Clickable">Clickable</app-tag-badge>
|
||||
<app-tag-badge [selectionMode]="TagBadgeCursor.NotAllowed">Non Allowed</app-tag-badge>
|
||||
</div>
|
||||
|
||||
<h2>Person Badge with Expander</h2>
|
||||
<div class="g-2">
|
||||
<app-person-badge></app-person-badge>
|
||||
<app-badge-expander [items]="people" [itemsTillExpander]="1">
|
||||
<ng-template #badgeExpanderItem let-item let-position="idx">
|
||||
<app-person-badge a11y-click="13,32" class="col-auto" [person]="item"></app-person-badge>
|
||||
</ng-template>
|
||||
</app-badge-expander>
|
||||
</div>
|
||||
|
||||
<h2>Switch</h2>
|
||||
<form>
|
||||
<div class="mb-3">
|
||||
<label id="auto-close-label" class="form-label"></label>
|
||||
<div class="mb-3">
|
||||
<div class="form-check form-switch">
|
||||
<input type="checkbox" id="auto-close" class="form-check-input" aria-labelledby="auto-close-label">
|
||||
<label class="form-check-label" for="auto-close">Auto Close Menu</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<h2>Dropdown/List Group</h2>
|
||||
<div class="dropdown" >
|
||||
<ul class="list-group" role="listbox" id="dropdown">
|
||||
<li class="list-group-item">Item 1</li>
|
||||
<li class="list-group-item">Item 2</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<h2>Accordion</h2>
|
||||
<ngb-accordion [closeOthers]="true" activeIds="reading-panel" #acc="ngbAccordion">
|
||||
<ngb-panel id="reading-panel" title="Reading">
|
||||
<ng-template ngbPanelHeader>
|
||||
<h2 class="accordion-header">
|
||||
<button class="accordion-button" ngbPanelToggle type="button" [attr.aria-expanded]="acc.isExpanded('reading-panel')" aria-controls="collapseOne">
|
||||
Reading
|
||||
</button>
|
||||
</h2>
|
||||
</ng-template>
|
||||
<ng-template ngbPanelContent>
|
||||
<p>This is the body of the accordion...........This is the body of the accordion asdfasdf asThis is the body of the accordion asdfasdf asThis is the body of the accordion asdfasdf asThis is the body of the accordion asdfasdf asThis is the body of the accordion asdfasdf as</p>
|
||||
</ng-template>
|
||||
</ngb-panel>
|
||||
|
||||
<ngb-panel id="reading-panel2">
|
||||
<ng-template ngbPanelHeader>
|
||||
<h2 class="accordion-header">
|
||||
<button class="accordion-button" ngbPanelToggle type="button" [attr.aria-expanded]="acc.isExpanded('reading-panel')" aria-controls="collapseOne">
|
||||
Header 2
|
||||
</button>
|
||||
</h2>
|
||||
</ng-template>
|
||||
<ng-template ngbPanelContent>
|
||||
<p>This is the body of the accordion asdfasdf as
|
||||
dfas
|
||||
f asdfasdfasdf asdfasdfaaff asdf
|
||||
as fd
|
||||
asfasf asdfasdfafd
|
||||
</p>
|
||||
</ng-template>
|
||||
</ngb-panel>
|
||||
</ngb-accordion>
|
||||
|
||||
|
||||
<h2>Cards</h2>
|
||||
<app-card-item [entity]="seriesNotRead"></app-card-item>
|
||||
<app-card-item [entity]="seriesNotRead" [count]="10"></app-card-item>
|
||||
<app-card-item [entity]="seriesWithProgress"></app-card-item>
|
||||
84
UI/Web/src/app/dev-only/theme-test/theme-test.component.ts
Normal file
84
UI/Web/src/app/dev-only/theme-test/theme-test.component.ts
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
import { Component, OnInit } from '@angular/core';
|
||||
import { ToastrService } from 'ngx-toastr';
|
||||
import { TagBadgeCursor } from '../../shared/tag-badge/tag-badge.component';
|
||||
import { ThemeService } from '../../_services/theme.service';
|
||||
import { MangaFormat } from '../../_models/manga-format';
|
||||
import { Person, PersonRole } from '../../_models/person';
|
||||
import { Series } from '../../_models/series';
|
||||
import { NavService } from '../../_services/nav.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-theme-test',
|
||||
templateUrl: './theme-test.component.html',
|
||||
styleUrls: ['./theme-test.component.scss']
|
||||
})
|
||||
export class ThemeTestComponent implements OnInit {
|
||||
|
||||
tabs: Array<{title: string, fragment: string}> = [
|
||||
{title: 'General', fragment: ''},
|
||||
{title: 'Users', fragment: 'users'},
|
||||
{title: 'Libraries', fragment: 'libraries'},
|
||||
{title: 'System', fragment: 'system'},
|
||||
{title: 'Changelog', fragment: 'changelog'},
|
||||
];
|
||||
active = this.tabs[0];
|
||||
|
||||
people: Array<Person> = [
|
||||
{id: 1, name: 'Joe', role: PersonRole.Artist},
|
||||
{id: 2, name: 'Joe 2', role: PersonRole.Artist},
|
||||
];
|
||||
|
||||
seriesNotRead: Series = {
|
||||
id: 1,
|
||||
name: 'Test Series',
|
||||
pages: 0,
|
||||
pagesRead: 10,
|
||||
format: MangaFormat.ARCHIVE,
|
||||
libraryId: 1,
|
||||
coverImageLocked: false,
|
||||
created: '',
|
||||
latestReadDate: '',
|
||||
localizedName: '',
|
||||
originalName: '',
|
||||
sortName: '',
|
||||
userRating: 0,
|
||||
userReview: '',
|
||||
volumes: [],
|
||||
localizedNameLocked: false,
|
||||
nameLocked: false,
|
||||
sortNameLocked: false,
|
||||
lastChapterAdded: '',
|
||||
}
|
||||
|
||||
seriesWithProgress: Series = {
|
||||
id: 1,
|
||||
name: 'Test Series',
|
||||
pages: 5,
|
||||
pagesRead: 10,
|
||||
format: MangaFormat.ARCHIVE,
|
||||
libraryId: 1,
|
||||
coverImageLocked: false,
|
||||
created: '',
|
||||
latestReadDate: '',
|
||||
localizedName: '',
|
||||
originalName: '',
|
||||
sortName: '',
|
||||
userRating: 0,
|
||||
userReview: '',
|
||||
volumes: [],
|
||||
localizedNameLocked: false,
|
||||
nameLocked: false,
|
||||
sortNameLocked: false,
|
||||
lastChapterAdded: '',
|
||||
}
|
||||
|
||||
get TagBadgeCursor(): typeof TagBadgeCursor {
|
||||
return TagBadgeCursor;
|
||||
}
|
||||
|
||||
constructor(public toastr: ToastrService, public navService: NavService, public themeService: ThemeService) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue