Skip to content

Commit

Permalink
Merge branch 'feature/revamped-ux' of https://github.com/Kareadita/Ka…
Browse files Browse the repository at this point in the history
…vita into feature/revamped-ux
  • Loading branch information
therobbiedavis committed Aug 9, 2024
2 parents 7bf198a + 308b421 commit fcc64f4
Show file tree
Hide file tree
Showing 20 changed files with 89 additions and 51 deletions.
3 changes: 2 additions & 1 deletion UI/Web/src/app/_models/wiki.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,6 @@ export enum WikiLink {
Library = 'https://wiki.kavitareader.com/guides/admin-settings/libraries',
UpdateNative = 'https://wiki.kavitareader.com/guides/updating/updating-native',
UpdateDocker = 'https://wiki.kavitareader.com/guides/updating/updating-docker',
OpdsClients = 'https://wiki.kavitareader.com/guides/opds#opds-capable-clients'
OpdsClients = 'https://wiki.kavitareader.com/guides/opds#opds-capable-clients',
Guides = 'https://wiki.kavitareader.com/guides'
}
6 changes: 3 additions & 3 deletions UI/Web/src/app/_services/action.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -469,7 +469,7 @@ export class ActionService implements OnDestroy {
this.readingListModalRef.componentInstance.seriesId = seriesId;
this.readingListModalRef.componentInstance.volumeIds = volumes.map(v => v.id);
this.readingListModalRef.componentInstance.chapterIds = chapters?.map(c => c.id);
this.readingListModalRef.componentInstance.title = 'Multiple Selections';
this.readingListModalRef.componentInstance.title = translate('action.multiple-selections');
this.readingListModalRef.componentInstance.type = ADD_FLOW.Multiple;


Expand Down Expand Up @@ -509,7 +509,7 @@ export class ActionService implements OnDestroy {
if (this.readingListModalRef != null) { return; }
this.readingListModalRef = this.modalService.open(AddToListModalComponent, { scrollable: true, size: 'md', fullscreen: 'md' });
this.readingListModalRef.componentInstance.seriesIds = series.map(v => v.id);
this.readingListModalRef.componentInstance.title = 'Multiple Selections';
this.readingListModalRef.componentInstance.title = translate('action.multiple-selections');
this.readingListModalRef.componentInstance.type = ADD_FLOW.Multiple_Series;


Expand Down Expand Up @@ -537,7 +537,7 @@ export class ActionService implements OnDestroy {
if (this.collectionModalRef != null) { return; }
this.collectionModalRef = this.modalService.open(BulkAddToCollectionComponent, { scrollable: true, size: 'md', windowClass: 'collection', fullscreen: 'md' });
this.collectionModalRef.componentInstance.seriesIds = series.map(v => v.id);
this.collectionModalRef.componentInstance.title = 'New Collection';
this.collectionModalRef.componentInstance.title = translate('action.new-collection');

this.collectionModalRef.closed.pipe(take(1)).subscribe(() => {
this.collectionModalRef = null;
Expand Down
6 changes: 5 additions & 1 deletion UI/Web/src/app/_services/nav.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ export class NavService {
private readonly accountService = inject(AccountService);
private readonly router = inject(Router);
private readonly destroyRef = inject(DestroyRef);
//private readonly onDestroy = new Subject<void>();

public localStorageSideNavKey = 'kavita--sidenav--expanded';

Expand Down Expand Up @@ -137,4 +136,9 @@ export class NavService {
localStorage.setItem(this.localStorageSideNavKey, newVal + '');
});
}

collapseSideNav(state: boolean) {
this.sideNavCollapseSource.next(state);
localStorage.setItem(this.localStorageSideNavKey, state + '');
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@

<app-user-scrobble-history></app-user-scrobble-history>
<div class="setting-section-break"></div>
<div class="mt-4">
<app-user-holds></app-user-holds>
</div>

@if(accountService.isAdmin$ | async) {
<div class="setting-section-break"></div>
<div class="mt-4">
<app-manage-scrobble-errors (scrobbleCount)="updateScrobbleErrorCount($event)"></app-manage-scrobble-errors>
</div>
Expand Down
3 changes: 2 additions & 1 deletion UI/Web/src/app/app.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@
<a id="content"></a>
@if (navService.sideNavVisibility$ | async) {
<div>
<div class="companion-bar" [ngClass]="{'companion-bar-content': (navService.sideNavCollapsed$ | async) === false || (navService.usePreferenceSideNav$ | async)}">
<div class="companion-bar" [ngClass]="{'companion-bar-content': (navService.sideNavCollapsed$ | async) === false || (navService.usePreferenceSideNav$ | async),
'companion-bar-collapsed': ((navService.sideNavCollapsed$ | async) && (navService.usePreferenceSideNav$ | async))}">
<router-outlet></router-outlet>
</div>
</div>
Expand Down
4 changes: 4 additions & 0 deletions UI/Web/src/app/app.component.scss
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@
margin-left: 40px;
}

.companion-bar-collapsed {
margin-left: 0 !important;
}

.companion-bar-content {
margin-left: 190px;
width: auto;
Expand Down
5 changes: 2 additions & 3 deletions UI/Web/src/app/app.component.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import {
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
DestroyRef,
HostListener,
Expand All @@ -14,7 +13,7 @@ import {AccountService} from './_services/account.service';
import {LibraryService} from './_services/library.service';
import {NavService} from './_services/nav.service';
import {NgbModal, NgbModalConfig, NgbOffcanvas, NgbRatingConfig} from '@ng-bootstrap/ng-bootstrap';
import {AsyncPipe, DOCUMENT, NgClass, NgIf} from '@angular/common';
import {AsyncPipe, DOCUMENT, NgClass} from '@angular/common';
import {filter, interval, Observable, switchMap} from 'rxjs';
import {ThemeService} from "./_services/theme.service";
import {SideNavComponent} from './sidenav/_components/side-nav/side-nav.component';
Expand All @@ -30,7 +29,7 @@ import {Breakpoint, UtilityService} from "./shared/_services/utility.service";
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
standalone: true,
imports: [NgClass, NgIf, SideNavComponent, RouterOutlet, AsyncPipe, NavHeaderComponent, PreferenceNavComponent],
imports: [NgClass, SideNavComponent, RouterOutlet, AsyncPipe, NavHeaderComponent, PreferenceNavComponent],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class AppComponent implements OnInit {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ <h4 class="modal-title" id="modal-basic-title">{{t('title')}}</h4>
</div>
<form style="width: 100%" [formGroup]="listForm">
<div class="modal-body">
@if (lists.length >= 5) {
@if (lists.length >= MaxItems) {
<div class="mb-3">
<label for="filter" class="form-label">{{t('filter-label')}}</label>
<div class="input-group">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
.clickable:hover, .clickable:focus {
background-color: lightgreen;
background-color: var(--list-group-hover-bg-color, --primary-color);
}

.collection {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export class BulkAddToCollectionComponent implements OnInit, AfterViewInit {
private readonly collectionService = inject(CollectionTagService);
private readonly toastr = inject(ToastrService);
private readonly cdRef = inject(ChangeDetectorRef);
protected readonly MaxItems = 8;

@Input({required: true}) title!: string;
/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
<ng-container *transloco="let t; read: 'import-mal-collection-modal'">
<p>{{t('description')}}</p>

@if (stacks.length === 0) {
<p>{{t('nothing-found')}}</p>
}

<ul>
@for(stack of stacks; track stack.url) {
<li class="mb-2">
Expand All @@ -17,8 +21,6 @@
} @empty {
@if (isLoading) {
<app-loading [loading]="isLoading"></app-loading>
} @else {
<p>{{t('nothing-found')}}</p>
}
}
</ul>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,8 @@
<div class="container-fluid">
<a class="visually-hidden-focusable focus-visible" href="javascript:void(0);" (click)="moveFocus()">{{t('skip-alt')}}</a>

@if(navService.usePreferenceSideNav$ | async) {
<a class="side-nav-toggle" routerLink="/home"><i class="fa-solid fa-house"></i></a>
} @else {
@if (navService.sideNavVisibility$ | async) {
<a class="side-nav-toggle" (click)="hideSideNav()"><i class="fas fa-bars"></i></a>
}
@if (navService.sideNavVisibility$ | async) {
<a class="side-nav-toggle" (click)="hideSideNav()"><i class="fas fa-bars"></i></a>
}


Expand Down Expand Up @@ -192,8 +188,8 @@
</button>
<div ngbDropdownMenu>
<a ngbDropdownItem routerLink="/all-filters/">{{t('all-filters')}}</a>
<a ngbDropdownItem href="https://wiki.kavitareader.com" rel="noopener noreferrer" target="_blank">{{t('help')}}</a>
<a ngbDropdownItem routerLink="/announcements/">{{t('announcements')}}</a>
<a ngbDropdownItem [href]="WikiLink.Guides" rel="noopener noreferrer" target="_blank">{{t('help')}}</a>
<a ngbDropdownItem (click)="logout()">{{t('logout')}}</a>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import {CollectionOwnerComponent} from "../../../collections/_components/collect
import {PromotedIconComponent} from "../../../shared/_components/promoted-icon/promoted-icon.component";
import {SettingsTabId} from "../../../sidenav/preference-nav/preference-nav.component";
import {Breakpoint, UtilityService} from "../../../shared/_services/utility.service";
import {WikiLink} from "../../../_models/wiki";

@Component({
selector: 'app-nav-header',
Expand All @@ -72,6 +73,10 @@ export class NavHeaderComponent implements OnInit {
protected readonly utilityService = inject(UtilityService);

protected readonly FilterField = FilterField;
protected readonly WikiLink = WikiLink;
protected readonly ScrobbleProvider = ScrobbleProvider;
protected readonly SettingsTabId = SettingsTabId;
protected readonly Breakpoint = Breakpoint;

@ViewChild('search') searchViewRef!: any;

Expand Down Expand Up @@ -285,8 +290,4 @@ export class NavHeaderComponent implements OnInit {
this.navService.toggleSideNav();
}


protected readonly ScrobbleProvider = ScrobbleProvider;
protected readonly SettingsTabId = SettingsTabId;
protected readonly Breakpoint = Breakpoint;
}
Original file line number Diff line number Diff line change
Expand Up @@ -945,11 +945,14 @@ export class SeriesDetailComponent implements OnInit, AfterContentChecked {
if (closeResult.success) {
window.scrollTo(0, 0);
this.loadSeries(this.seriesId, closeResult.updateExternal);
} else if (closeResult.updateExternal) {
this.loadSeries(this.seriesId, closeResult.updateExternal);
}

if (closeResult.coverImageUpdate) {
this.toastr.info(this.translocoService.translate('series-detail.cover-change'));
}

});
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
@if (link === undefined || link.length === 0) {
<div class="side-nav-item" [ngClass]="{'closed': ((navService.sideNavCollapsed$ | async) && (navService.usePreferenceSideNav$ | async) === false), 'active': highlighted}">
<div class="side-nav-item" [ngClass]="{'closed': ((navService.sideNavCollapsed$ | async)), 'active': highlighted}">
<ng-container [ngTemplateOutlet]="inner"></ng-container>
</div>
} @else {
@if (external) {
<a [id]="id" class="side-nav-item" [href]="link" [ngClass]="{'closed': ((navService.sideNavCollapsed$ | async) && (navService.usePreferenceSideNav$ | async) === false), 'active': highlighted}" rel="noopener noreferrer" target="_blank">
<a [id]="id" class="side-nav-item" [href]="link" [ngClass]="{'closed': ((navService.sideNavCollapsed$ | async)), 'active': highlighted}" rel="noopener noreferrer" target="_blank">
<ng-container [ngTemplateOutlet]="inner"></ng-container>
</a>
} @else {
@if (queryParams && queryParams !== {}) {
<a [id]="id" class="side-nav-item" href="javascript:void(0);" [ngClass]="{'closed': ((navService.sideNavCollapsed$ | async) && (navService.usePreferenceSideNav$ | async) === false), 'active': highlighted}" (click)="openLink()">
<a [id]="id" class="side-nav-item" href="javascript:void(0);" [ngClass]="{'closed': ((navService.sideNavCollapsed$ | async)), 'active': highlighted}" (click)="openLink()">
<ng-container [ngTemplateOutlet]="inner"></ng-container>
</a>
} @else if (fragment) {
<a [id]="id" class="side-nav-item" href="javascript:void(0);" [ngClass]="{'closed': ((navService.sideNavCollapsed$ | async) && (navService.usePreferenceSideNav$ | async) === false), 'active': highlighted}" [routerLink]="link" [fragment]="fragment">
<a [id]="id" class="side-nav-item" href="javascript:void(0);" [ngClass]="{'closed': ((navService.sideNavCollapsed$ | async)), 'active': highlighted}" [routerLink]="link" [fragment]="fragment">
<ng-container [ngTemplateOutlet]="inner"></ng-container>
</a>
} @else {
<a [id]="id" class="side-nav-item" href="javascript:void(0);" [ngClass]="{'closed': ((navService.sideNavCollapsed$ | async) && (navService.usePreferenceSideNav$ | async) === false), 'active': highlighted}" [routerLink]="link" [queryParams]="queryParams">
<a [id]="id" class="side-nav-item" href="javascript:void(0);" [ngClass]="{'closed': ((navService.sideNavCollapsed$ | async)), 'active': highlighted}" [routerLink]="link" [queryParams]="queryParams">
<ng-container [ngTemplateOutlet]="inner"></ng-container>
</a>
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
<ng-container *transloco="let t; read:'settings'">
@if (accountService.currentUser$ | async; as user) {
<div class="side-nav no-donate">

@for(section of sections; track section.title + section.children.length; let idx = $index;) {
@if (hasAnyChildren(user, section)) {
<h5 class="side-nav-header mt-3 mb-2 ms-3" [ngClass]="{'mt-4': idx > 0}">{{t(section.title)}}</h5>
@for(item of section.children; track item.fragment) {
@if (accountService.hasAnyRole(user, item.roles)) {
<app-side-nav-item [id]="'nav-item-' + item.fragment" [noIcon]="true" link="/settings" [fragment]="item.fragment" [title]="item.fragment | settingFragment" [badgeCount]="item.badgeCount$ | async"></app-side-nav-item>
@if((navService.sideNavCollapsed$ | async) === false) {
<div class="side-nav no-donate">

@for(section of sections; track section.title + section.children.length; let idx = $index;) {
@if (hasAnyChildren(user, section)) {
<h5 class="side-nav-header mt-3 mb-2 ms-3" [ngClass]="{'mt-4': idx > 0}">{{t(section.title)}}</h5>
@for(item of section.children; track item.fragment) {
@if (accountService.hasAnyRole(user, item.roles)) {
<app-side-nav-item [id]="'nav-item-' + item.fragment" [noIcon]="true" link="/settings" [fragment]="item.fragment" [title]="item.fragment | settingFragment" [badgeCount]="item.badgeCount$ | async"></app-side-nav-item>
}
}
}
}
}

</div>
</div>
}

}

</ng-container>
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ export class PreferenceNavComponent implements AfterViewInit {
{
title: 'account-section-title',
children: [
new SideNavItem(SettingsTabId.Account, [Role.Admin]),
new SideNavItem(SettingsTabId.Account, []),
new SideNavItem(SettingsTabId.Preferences),
new SideNavItem(SettingsTabId.Customize),
new SideNavItem(SettingsTabId.Clients),
Expand Down Expand Up @@ -153,6 +153,9 @@ export class PreferenceNavComponent implements AfterViewInit {
hasActiveLicense = false;

constructor() {

this.navService.collapseSideNav(false);

this.accountService.hasValidLicense$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(res => {
if (res) {
this.hasActiveLicense = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { DecimalPipe } from '@angular/common';
import { IconAndTitleComponent } from '../../../shared/icon-and-title/icon-and-title.component';
import {AccountService} from "../../../_services/account.service";
import {CompactNumberPipe} from "../../../_pipes/compact-number.pipe";
import {TranslocoDirective} from "@ngneat/transloco";
import {translate, TranslocoDirective} from "@ngneat/transloco";

@Component({
selector: 'app-user-stats-info-cards',
Expand All @@ -33,17 +33,23 @@ export class UserStatsInfoCardsComponent {
const numberPipe = new CompactNumberPipe();
this.statsService.getPagesPerYear().subscribe(yearCounts => {
const ref = this.modalService.open(GenericListModalComponent, { scrollable: true });
ref.componentInstance.items = yearCounts.map(t => `${t.name}: ${numberPipe.transform(t.value)} pages`);
ref.componentInstance.title = 'Pages Read By Year';
ref.componentInstance.items = yearCounts.map(t => {
const countStr = translate('user-stats-info-cards.pages-count', {num: numberPipe.transform(t.value)});
return `${t.name}: ${countStr})`;
});
ref.componentInstance.title = translate('user-stats-info-cards.pages-read-by-year-title');
});
}

openWordByYearList() {
const numberPipe = new CompactNumberPipe();
this.statsService.getWordsPerYear().subscribe(yearCounts => {
const ref = this.modalService.open(GenericListModalComponent, { scrollable: true });
ref.componentInstance.items = yearCounts.map(t => `${t.name}: ${numberPipe.transform(t.value)} words`);
ref.componentInstance.title = 'Words Read By Year';
ref.componentInstance.items = yearCounts.map(t => {
const countStr = translate('user-stats-info-cards.words-count', {num: numberPipe.transform(t.value)});
return `${t.name}: ${countStr})`;
});
ref.componentInstance.title = translate('user-stats-info-cards.words-read-by-year-title');
});
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {ChangeDetectionStrategy, ChangeDetectorRef, Component, DestroyRef, inject} from '@angular/core';
import {CommonModule} from '@angular/common';
import {AsyncPipe} from '@angular/common';
import {ScrobblingService} from "../../_services/scrobbling.service";
import {shareReplay} from "rxjs/operators";
import {takeUntilDestroyed} from "@angular/core/rxjs-interop";
Expand All @@ -8,15 +8,20 @@ import {ScrobbleEventTypePipe} from "../../_pipes/scrobble-event-type.pipe";
import {
NgbAccordionBody,
NgbAccordionCollapse,
NgbAccordionDirective, NgbAccordionHeader,
NgbAccordionDirective,
NgbAccordionHeader,
NgbAccordionItem
} from "@ng-bootstrap/ng-bootstrap";
import {TranslocoDirective} from "@ngneat/transloco";
import {ListItemComponent} from "../../cards/list-item/list-item.component";
import {ImageService} from "../../_services/image.service";
import {ImageComponent} from "../../shared/image/image.component";

@Component({
selector: 'app-user-holds',
standalone: true,
imports: [CommonModule, ScrobbleEventTypePipe, NgbAccordionDirective, NgbAccordionCollapse, NgbAccordionBody, NgbAccordionItem, NgbAccordionHeader, TranslocoDirective],
imports: [ScrobbleEventTypePipe, NgbAccordionDirective, NgbAccordionCollapse, NgbAccordionBody,
NgbAccordionItem, NgbAccordionHeader, TranslocoDirective, AsyncPipe, ListItemComponent, ImageComponent],
templateUrl: './scrobbling-holds.component.html',
styleUrls: ['./scrobbling-holds.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
Expand All @@ -25,5 +30,6 @@ export class ScrobblingHoldsComponent {
private readonly cdRef = inject(ChangeDetectorRef);
private readonly scrobblingService = inject(ScrobblingService);
private readonly destroyRef = inject(DestroyRef);
holds$ = this.scrobblingService.getHolds().pipe(takeUntilDestroyed(this.destroyRef), shareReplay());
protected readonly imageService = inject(ImageService);
holds$ = this.scrobblingService.getHolds().pipe(takeUntilDestroyed(this.destroyRef), shareReplay({bufferSize: 1, refCount: true}));
}
Loading

0 comments on commit fcc64f4

Please sign in to comment.