mirror of
https://github.com/Kareadita/Kavita.git
synced 2025-07-09 03:04:19 -04:00
More Bugfixes from Side Nav (#1162)
* Fixed a bug where the bottom of the page could be cut off * Adjusted all the headings to h2, which looks better * Refactored GetSeriesDetail to actually map the names inside the code so the UI just displays. * Put in some basic improvements to OPDS by using Series Detail type layout, but this only reduces one click. * Fixed a bug where offset from scrollbar fix causes readers to be cutoff.
This commit is contained in:
parent
5220d2b300
commit
bff49c0e7a
@ -202,7 +202,7 @@ public class SeriesServiceTests
|
|||||||
|
|
||||||
Assert.NotEmpty(detail.Volumes);
|
Assert.NotEmpty(detail.Volumes);
|
||||||
Assert.Equal(2, detail.Volumes.Count()); // Volume 0 shouldn't be sent in Volumes
|
Assert.Equal(2, detail.Volumes.Count()); // Volume 0 shouldn't be sent in Volumes
|
||||||
Assert.All(detail.Volumes, dto => Assert.Contains(dto.Name, new[] {"2", "3"}));
|
Assert.All(detail.Volumes, dto => Assert.Contains(dto.Name, new[] {"Volume 2", "Volume 3"})); // Volumes get names mapped
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
@ -28,6 +28,7 @@ public class OpdsController : BaseApiController
|
|||||||
private readonly IDirectoryService _directoryService;
|
private readonly IDirectoryService _directoryService;
|
||||||
private readonly ICacheService _cacheService;
|
private readonly ICacheService _cacheService;
|
||||||
private readonly IReaderService _readerService;
|
private readonly IReaderService _readerService;
|
||||||
|
private readonly ISeriesService _seriesService;
|
||||||
|
|
||||||
|
|
||||||
private readonly XmlSerializer _xmlSerializer;
|
private readonly XmlSerializer _xmlSerializer;
|
||||||
@ -61,13 +62,14 @@ public class OpdsController : BaseApiController
|
|||||||
|
|
||||||
public OpdsController(IUnitOfWork unitOfWork, IDownloadService downloadService,
|
public OpdsController(IUnitOfWork unitOfWork, IDownloadService downloadService,
|
||||||
IDirectoryService directoryService, ICacheService cacheService,
|
IDirectoryService directoryService, ICacheService cacheService,
|
||||||
IReaderService readerService)
|
IReaderService readerService, ISeriesService seriesService)
|
||||||
{
|
{
|
||||||
_unitOfWork = unitOfWork;
|
_unitOfWork = unitOfWork;
|
||||||
_downloadService = downloadService;
|
_downloadService = downloadService;
|
||||||
_directoryService = directoryService;
|
_directoryService = directoryService;
|
||||||
_cacheService = cacheService;
|
_cacheService = cacheService;
|
||||||
_readerService = readerService;
|
_readerService = readerService;
|
||||||
|
_seriesService = seriesService;
|
||||||
|
|
||||||
_xmlSerializer = new XmlSerializer(typeof(Feed));
|
_xmlSerializer = new XmlSerializer(typeof(Feed));
|
||||||
_xmlOpenSearchSerializer = new XmlSerializer(typeof(OpenSearchDescription));
|
_xmlOpenSearchSerializer = new XmlSerializer(typeof(OpenSearchDescription));
|
||||||
@ -314,16 +316,17 @@ public class OpdsController : BaseApiController
|
|||||||
var items = (await _unitOfWork.ReadingListRepository.GetReadingListItemDtosByIdAsync(readingListId, userId)).ToList();
|
var items = (await _unitOfWork.ReadingListRepository.GetReadingListItemDtosByIdAsync(readingListId, userId)).ToList();
|
||||||
foreach (var item in items)
|
foreach (var item in items)
|
||||||
{
|
{
|
||||||
feed.Entries.Add(new FeedEntry()
|
feed.Entries.Add(CreateChapter(apiKey, $"{item.SeriesName} Chapter {item.ChapterNumber}", item.ChapterId, item.VolumeId, item.SeriesId));
|
||||||
{
|
// new FeedEntry()
|
||||||
Id = item.ChapterId.ToString(),
|
// {
|
||||||
Title = $"{item.SeriesName} Chapter {item.ChapterNumber}",
|
// Id = item.ChapterId.ToString(),
|
||||||
Links = new List<FeedLink>()
|
// Title = $"{item.SeriesName} Chapter {item.ChapterNumber}",
|
||||||
{
|
// Links = new List<FeedLink>()
|
||||||
CreateLink(FeedLinkRelation.SubSection, FeedLinkType.AtomNavigation, Prefix + $"{apiKey}/series/{item.SeriesId}/volume/{item.VolumeId}/chapter/{item.ChapterId}"),
|
// {
|
||||||
CreateLink(FeedLinkRelation.Image, FeedLinkType.Image, $"/api/image/chapter-cover?chapterId={item.ChapterId}")
|
// CreateLink(FeedLinkRelation.SubSection, FeedLinkType.AtomNavigation, Prefix + $"{apiKey}/series/{item.SeriesId}/volume/{item.VolumeId}/chapter/{item.ChapterId}"),
|
||||||
}
|
// CreateLink(FeedLinkRelation.Image, FeedLinkType.Image, $"/api/image/chapter-cover?chapterId={item.ChapterId}")
|
||||||
});
|
// }
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
return CreateXmlResult(SerializeXml(feed));
|
return CreateXmlResult(SerializeXml(feed));
|
||||||
@ -521,15 +524,30 @@ public class OpdsController : BaseApiController
|
|||||||
return BadRequest("OPDS is not enabled on this server");
|
return BadRequest("OPDS is not enabled on this server");
|
||||||
var userId = await GetUser(apiKey);
|
var userId = await GetUser(apiKey);
|
||||||
var series = await _unitOfWork.SeriesRepository.GetSeriesDtoByIdAsync(seriesId, userId);
|
var series = await _unitOfWork.SeriesRepository.GetSeriesDtoByIdAsync(seriesId, userId);
|
||||||
var volumes = await _unitOfWork.VolumeRepository.GetVolumesDtoAsync(seriesId, userId);
|
|
||||||
var feed = CreateFeed(series.Name + " - Volumes", $"{apiKey}/series/{series.Id}", apiKey);
|
var feed = CreateFeed(series.Name + " - Storyline", $"{apiKey}/series/{series.Id}", apiKey);
|
||||||
SetFeedId(feed, $"series-{series.Id}");
|
SetFeedId(feed, $"series-{series.Id}");
|
||||||
feed.Links.Add(CreateLink(FeedLinkRelation.Image, FeedLinkType.Image, $"/api/image/series-cover?seriesId={seriesId}"));
|
feed.Links.Add(CreateLink(FeedLinkRelation.Image, FeedLinkType.Image, $"/api/image/series-cover?seriesId={seriesId}"));
|
||||||
foreach (var volumeDto in volumes)
|
|
||||||
|
// NOTE: I want to try and use ReaderService to get SeriesDetails.
|
||||||
|
var seriesDetail = await _seriesService.GetSeriesDetail(seriesId, userId);
|
||||||
|
foreach (var volume in seriesDetail.Volumes)
|
||||||
{
|
{
|
||||||
feed.Entries.Add(CreateVolume(volumeDto, seriesId, apiKey));
|
feed.Entries.Add(CreateVolume(volume, seriesId, apiKey)); // We might want to emulate a volume but make this a chapter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach (var storylineChapter in seriesDetail.StorylineChapters.Where(c => !c.IsSpecial))
|
||||||
|
{
|
||||||
|
feed.Entries.Add(CreateChapter(apiKey, storylineChapter.Title, storylineChapter.Id, storylineChapter.VolumeId, seriesId));
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var special in seriesDetail.Specials)
|
||||||
|
{
|
||||||
|
feed.Entries.Add(CreateChapter(apiKey, special.Title, special.Id, special.VolumeId, seriesId));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return CreateXmlResult(SerializeXml(feed));
|
return CreateXmlResult(SerializeXml(feed));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -698,6 +716,23 @@ public class OpdsController : BaseApiController
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static FeedEntry CreateChapter(string apiKey, string title, int chapterId, int volumeId, int seriesId)
|
||||||
|
{
|
||||||
|
|
||||||
|
return new FeedEntry()
|
||||||
|
{
|
||||||
|
Id = chapterId.ToString(),
|
||||||
|
Title = title,
|
||||||
|
Links = new List<FeedLink>()
|
||||||
|
{
|
||||||
|
CreateLink(FeedLinkRelation.SubSection, FeedLinkType.AtomNavigation,
|
||||||
|
Prefix + $"{apiKey}/series/{seriesId}/volume/{volumeId}/chapter/{chapterId}"),
|
||||||
|
CreateLink(FeedLinkRelation.Image, FeedLinkType.Image,
|
||||||
|
$"/api/image/chapter-cover?chapterId={chapterId}")
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
private FeedEntry CreateChapter(int seriesId, int volumeId, int chapterId, MangaFile mangaFile, SeriesDto series, Volume volume, ChapterDto chapter, string apiKey)
|
private FeedEntry CreateChapter(int seriesId, int volumeId, int chapterId, MangaFile mangaFile, SeriesDto series, Volume volume, ChapterDto chapter, string apiKey)
|
||||||
{
|
{
|
||||||
var fileSize =
|
var fileSize =
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@ -14,7 +13,6 @@ using API.Entities.Enums;
|
|||||||
using API.Helpers;
|
using API.Helpers;
|
||||||
using API.SignalR;
|
using API.SignalR;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.VisualBasic;
|
|
||||||
|
|
||||||
namespace API.Services;
|
namespace API.Services;
|
||||||
|
|
||||||
@ -460,22 +458,40 @@ public class SeriesService : ISeriesService
|
|||||||
{
|
{
|
||||||
volume.Name += $" - {firstChapter.TitleName}";
|
volume.Name += $" - {firstChapter.TitleName}";
|
||||||
}
|
}
|
||||||
|
|
||||||
processedVolumes.Add(volume);
|
processedVolumes.Add(volume);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
processedVolumes = volumes.Where(v => v.Number > 0).ToList();
|
processedVolumes = volumes.Where(v => v.Number > 0).ToList();
|
||||||
|
processedVolumes.ForEach(v => v.Name = $"Volume {v.Name}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var specials = new List<ChapterDto>();
|
var specials = new List<ChapterDto>();
|
||||||
foreach (var chapter in chapters.Where(c => c.IsSpecial))
|
foreach (var chapter in chapters)
|
||||||
{
|
{
|
||||||
chapter.Title = Parser.Parser.CleanSpecialTitle(chapter.Title);
|
if (chapter.IsSpecial)
|
||||||
specials.Add(chapter);
|
{
|
||||||
|
chapter.Title = Parser.Parser.CleanSpecialTitle(chapter.Title);
|
||||||
|
specials.Add(chapter);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var title = libraryType switch
|
||||||
|
{
|
||||||
|
LibraryType.Book => $"Book {chapter.Title}",
|
||||||
|
LibraryType.Comic => $"Issue #{chapter.Title}",
|
||||||
|
LibraryType.Manga => $"Chapter {chapter.Title}",
|
||||||
|
_ => "Chapter "
|
||||||
|
};
|
||||||
|
chapter.Title = title;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Don't show chapter 0 (aka single volume chapters) in the Chapters tab or books that are just single numbers (they show as volumes)
|
// Don't show chapter 0 (aka single volume chapters) in the Chapters tab or books that are just single numbers (they show as volumes)
|
||||||
IEnumerable<ChapterDto> retChapters;
|
IEnumerable<ChapterDto> retChapters;
|
||||||
if (libraryType == LibraryType.Book)
|
if (libraryType == LibraryType.Book)
|
||||||
@ -497,7 +513,7 @@ public class SeriesService : ISeriesService
|
|||||||
Volumes = processedVolumes,
|
Volumes = processedVolumes,
|
||||||
StorylineChapters = volumes
|
StorylineChapters = volumes
|
||||||
.Where(v => v.Number == 0)
|
.Where(v => v.Number == 0)
|
||||||
.SelectMany(v => v.Chapters)
|
.SelectMany(v => v.Chapters.Where(c => !c.IsSpecial))
|
||||||
.OrderBy(c => float.Parse(c.Number), new ChapterSortComparer())
|
.OrderBy(c => float.Parse(c.Number), new ChapterSortComparer())
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { DOCUMENT } from '@angular/common';
|
||||||
|
import { Inject, Injectable, Renderer2, RendererFactory2 } from '@angular/core';
|
||||||
import { ReplaySubject, take } from 'rxjs';
|
import { ReplaySubject, take } from 'rxjs';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
@ -25,7 +26,10 @@ export class NavService {
|
|||||||
*/
|
*/
|
||||||
sideNavVisibility$ = this.sideNavVisibilitySource.asObservable();
|
sideNavVisibility$ = this.sideNavVisibilitySource.asObservable();
|
||||||
|
|
||||||
constructor() {
|
private renderer: Renderer2;
|
||||||
|
|
||||||
|
constructor(@Inject(DOCUMENT) private document: Document, rendererFactory: RendererFactory2) {
|
||||||
|
this.renderer = rendererFactory.createRenderer(null, null);
|
||||||
this.showNavBar();
|
this.showNavBar();
|
||||||
const sideNavState = (localStorage.getItem(this.localStorageSideNavKey) === 'true') || false;
|
const sideNavState = (localStorage.getItem(this.localStorageSideNavKey) === 'true') || false;
|
||||||
this.sideNavCollapseSource.next(sideNavState);
|
this.sideNavCollapseSource.next(sideNavState);
|
||||||
@ -36,6 +40,7 @@ export class NavService {
|
|||||||
* Shows the top nav bar. This should be visible on all pages except the reader.
|
* Shows the top nav bar. This should be visible on all pages except the reader.
|
||||||
*/
|
*/
|
||||||
showNavBar() {
|
showNavBar() {
|
||||||
|
this.renderer.setStyle(this.document.querySelector('body'), 'margin-top', '56px');
|
||||||
this.navbarVisibleSource.next(true);
|
this.navbarVisibleSource.next(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,6 +48,7 @@ export class NavService {
|
|||||||
* Hides the top nav bar.
|
* Hides the top nav bar.
|
||||||
*/
|
*/
|
||||||
hideNavBar() {
|
hideNavBar() {
|
||||||
|
this.renderer.setStyle(this.document.querySelector('body'), 'margin-top', '0px');
|
||||||
this.navbarVisibleSource.next(false);
|
this.navbarVisibleSource.next(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<app-side-nav-companion-bar>
|
<app-side-nav-companion-bar>
|
||||||
<h1 title>
|
<h2 title>
|
||||||
Admin Dashboard
|
Admin Dashboard
|
||||||
</h1>
|
</h2>
|
||||||
</app-side-nav-companion-bar>
|
</app-side-nav-companion-bar>
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<ul ngbNav #nav="ngbNav" [(activeId)]="active" class="nav nav-tabs">
|
<ul ngbNav #nav="ngbNav" [(activeId)]="active" class="nav nav-tabs">
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
<app-side-nav-companion-bar [hasFilter]="true" (filterOpen)="filterOpen.emit($event)">
|
<app-side-nav-companion-bar [hasFilter]="true" (filterOpen)="filterOpen.emit($event)">
|
||||||
<h1 title>
|
<h2 title>
|
||||||
<app-card-actionables [actions]="actions"></app-card-actionables>
|
<app-card-actionables [actions]="actions"></app-card-actionables>
|
||||||
All Series
|
All Series
|
||||||
</h1>
|
</h2>
|
||||||
<h6 subtitle style="margin-left:40px;">{{pagination?.totalItems}} Series</h6>
|
<h6 subtitle style="margin-left:40px;">{{pagination?.totalItems}} Series</h6>
|
||||||
</app-side-nav-companion-bar>
|
</app-side-nav-companion-bar>
|
||||||
<app-bulk-operations [actionCallback]="bulkActionCallback"></app-bulk-operations>
|
<app-bulk-operations [actionCallback]="bulkActionCallback"></app-bulk-operations>
|
||||||
|
@ -2,12 +2,15 @@
|
|||||||
<div [ngClass]="{'closed' : !(navService?.sideNavCollapsed$ | async), 'content-wrapper': navService.sideNavVisibility$ | async}">
|
<div [ngClass]="{'closed' : !(navService?.sideNavCollapsed$ | async), 'content-wrapper': navService.sideNavVisibility$ | async}">
|
||||||
<a id="content"></a>
|
<a id="content"></a>
|
||||||
<app-side-nav *ngIf="navService.sideNavVisibility$ | async"></app-side-nav>
|
<app-side-nav *ngIf="navService.sideNavVisibility$ | async"></app-side-nav>
|
||||||
<div class="container-fluid" style="padding-top: 10px; padding-bottom: 10px;" *ngIf="navService.sideNavVisibility$ | async else noSideNav">
|
<div class="container-fluid">
|
||||||
<div class="companion-bar" [ngClass]="{'companion-bar-content': (navService?.sideNavCollapsed$ | async)}">
|
<div style="padding-top: 10px; padding-bottom: 65px;" *ngIf="navService.sideNavVisibility$ | async else noSideNav">
|
||||||
<router-outlet></router-outlet>
|
<div class="companion-bar" [ngClass]="{'companion-bar-content': (navService?.sideNavCollapsed$ | async)}">
|
||||||
|
<router-outlet></router-outlet>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<ng-template #noSideNav>
|
||||||
|
<router-outlet></router-outlet>
|
||||||
|
</ng-template>
|
||||||
</div>
|
</div>
|
||||||
<ng-template #noSideNav>
|
|
||||||
<router-outlet></router-outlet>
|
|
||||||
</ng-template>
|
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
<app-side-nav-companion-bar [hasFilter]="false" (filterOpen)="filterOpen.emit($event)">
|
<app-side-nav-companion-bar [hasFilter]="false" (filterOpen)="filterOpen.emit($event)">
|
||||||
<h1 title>
|
<h2 title>
|
||||||
<app-card-actionables [actions]="collectionTagActions"></app-card-actionables>
|
<app-card-actionables [actions]="collectionTagActions"></app-card-actionables>
|
||||||
Collections
|
Collections
|
||||||
</h1>
|
</h2>
|
||||||
<h6 subtitle style="margin-left:40px;">{{collections.length}} Items</h6>
|
<h6 subtitle style="margin-left:40px;">{{collections.length}} Items</h6>
|
||||||
</app-side-nav-companion-bar>
|
</app-side-nav-companion-bar>
|
||||||
<app-card-detail-layout
|
<app-card-detail-layout
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
<app-side-nav-companion-bar [hasFilter]="true" (filterOpen)="filterOpen.emit($event)">
|
<app-side-nav-companion-bar [hasFilter]="true" (filterOpen)="filterOpen.emit($event)">
|
||||||
<h1 title>
|
<h2 title>
|
||||||
<app-card-actionables [actions]="actions"></app-card-actionables>
|
<app-card-actionables [actions]="actions"></app-card-actionables>
|
||||||
{{libraryName}}
|
{{libraryName}}
|
||||||
</h1>
|
</h2>
|
||||||
<h6 subtitle style="margin-left:40px;">{{pagination?.totalItems}} Series</h6>
|
<h6 subtitle style="margin-left:40px;">{{pagination?.totalItems}} Series</h6>
|
||||||
<div main>
|
<div main>
|
||||||
<!-- TODO: Implement Tabs here for Recommended and Library view -->
|
<!-- TODO: Implement Tabs here for Recommended and Library view -->
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<app-side-nav-companion-bar [hasFilter]="true" (filterOpen)="filterOpen.emit($event)">
|
<app-side-nav-companion-bar [hasFilter]="true" (filterOpen)="filterOpen.emit($event)">
|
||||||
<h1 title>
|
<h2 title>
|
||||||
On Deck
|
On Deck
|
||||||
</h1>
|
</h2>
|
||||||
</app-side-nav-companion-bar>
|
</app-side-nav-companion-bar>
|
||||||
<app-bulk-operations [actionCallback]="bulkActionCallback"></app-bulk-operations>
|
<app-bulk-operations [actionCallback]="bulkActionCallback"></app-bulk-operations>
|
||||||
<app-card-detail-layout
|
<app-card-detail-layout
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
<app-side-nav-companion-bar [showGoBack]="true">
|
<app-side-nav-companion-bar [showGoBack]="true">
|
||||||
<h1 title>
|
<h2 title>
|
||||||
<span *ngIf="actions.length > 0">
|
<span *ngIf="actions.length > 0">
|
||||||
<app-card-actionables (actionHandler)="performAction($event)" [actions]="actions" [labelBy]="readingList.title"></app-card-actionables>
|
<app-card-actionables (actionHandler)="performAction($event)" [actions]="actions" [labelBy]="readingList.title"></app-card-actionables>
|
||||||
</span>
|
</span>
|
||||||
{{readingList.title}} <span *ngIf="readingList?.promoted">(<i class="fa fa-angle-double-up" aria-hidden="true"></i>)</span>
|
{{readingList.title}} <span *ngIf="readingList?.promoted">(<i class="fa fa-angle-double-up" aria-hidden="true"></i>)</span>
|
||||||
<span class="badge bg-primary rounded-pill" attr.aria-label="{{items.length}} total items">{{items.length}}</span>
|
<span class="badge bg-primary rounded-pill" attr.aria-label="{{items.length}} total items">{{items.length}}</span>
|
||||||
</h1>
|
</h2>
|
||||||
</app-side-nav-companion-bar>
|
</app-side-nav-companion-bar>
|
||||||
<div class="container-fluid mt-2" *ngIf="readingList">
|
<div class="container-fluid mt-2" *ngIf="readingList">
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
<app-side-nav-companion-bar [showGoBack]="true" pageHeader="Home">
|
<app-side-nav-companion-bar [showGoBack]="true" pageHeader="Home">
|
||||||
<h1 title>
|
<h2 title>
|
||||||
<app-card-actionables [actions]="actions"></app-card-actionables>
|
<app-card-actionables [actions]="actions"></app-card-actionables>
|
||||||
Reading Lists
|
Reading Lists
|
||||||
</h1>
|
</h2>
|
||||||
<h6 subtitle>{{pagination?.totalItems}} Items</h6>
|
<h6 subtitle>{{pagination?.totalItems}} Items</h6>
|
||||||
</app-side-nav-companion-bar>
|
</app-side-nav-companion-bar>
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<app-side-nav-companion-bar [hasFilter]="true" (filterOpen)="filterOpen.emit($event)">
|
<app-side-nav-companion-bar [hasFilter]="true" (filterOpen)="filterOpen.emit($event)">
|
||||||
<h1 title>
|
<h2 title>
|
||||||
Recently Added
|
Recently Added
|
||||||
</h1>
|
</h2>
|
||||||
</app-side-nav-companion-bar>
|
</app-side-nav-companion-bar>
|
||||||
<app-bulk-operations [actionCallback]="bulkActionCallback"></app-bulk-operations>
|
<app-bulk-operations [actionCallback]="bulkActionCallback"></app-bulk-operations>
|
||||||
<app-card-detail-layout
|
<app-card-detail-layout
|
||||||
|
@ -67,7 +67,7 @@
|
|||||||
<ng-template ngbNavContent>
|
<ng-template ngbNavContent>
|
||||||
<div class="row g-0">
|
<div class="row g-0">
|
||||||
<ng-container *ngFor="let chapter of specials; let idx = index; trackBy: trackByChapterIdentity">
|
<ng-container *ngFor="let chapter of specials; let idx = index; trackBy: trackByChapterIdentity">
|
||||||
<app-card-item class="col-auto p-2" *ngIf="chapter.isSpecial" [entity]="chapter" [title]="chapter.title || chapter.range" (click)="openChapter(chapter)"
|
<app-card-item class="col-auto p-2" [entity]="chapter" [title]="chapter.title || chapter.range" (click)="openChapter(chapter)"
|
||||||
[imageUrl]="imageService.getChapterCoverImage(chapter.id)"
|
[imageUrl]="imageService.getChapterCoverImage(chapter.id)"
|
||||||
[read]="chapter.pagesRead" [total]="chapter.pages" [actions]="chapterActions" (selection)="bulkSelectionService.handleCardSelection('special', idx, chapters.length, $event)" [selected]="bulkSelectionService.isCardSelected('special', idx)" [allowSelection]="true"></app-card-item>
|
[read]="chapter.pagesRead" [total]="chapter.pages" [actions]="chapterActions" (selection)="bulkSelectionService.handleCardSelection('special', idx, chapters.length, $event)" [selected]="bulkSelectionService.isCardSelected('special', idx)" [allowSelection]="true"></app-card-item>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
@ -79,12 +79,12 @@
|
|||||||
<ng-template ngbNavContent>
|
<ng-template ngbNavContent>
|
||||||
<div class="row g-0">
|
<div class="row g-0">
|
||||||
<ng-container *ngFor="let volume of volumes; let idx = index; trackBy: trackByVolumeIdentity">
|
<ng-container *ngFor="let volume of volumes; let idx = index; trackBy: trackByVolumeIdentity">
|
||||||
<app-card-item class="col-auto p-2" *ngIf="volume.number != 0" [entity]="volume" [title]="formatVolumeTitle(volume)" (click)="openVolume(volume)"
|
<app-card-item class="col-auto p-2" *ngIf="volume.number != 0" [entity]="volume" [title]="volume.name" (click)="openVolume(volume)"
|
||||||
[imageUrl]="imageService.getVolumeCoverImage(volume.id) + '&offset=' + coverImageOffset"
|
[imageUrl]="imageService.getVolumeCoverImage(volume.id) + '&offset=' + coverImageOffset"
|
||||||
[read]="volume.pagesRead" [total]="volume.pages" [actions]="volumeActions" (selection)="bulkSelectionService.handleCardSelection('volume', idx, volumes.length, $event)" [selected]="bulkSelectionService.isCardSelected('volume', idx)" [allowSelection]="true"></app-card-item>
|
[read]="volume.pagesRead" [total]="volume.pages" [actions]="volumeActions" (selection)="bulkSelectionService.handleCardSelection('volume', idx, volumes.length, $event)" [selected]="bulkSelectionService.isCardSelected('volume', idx)" [allowSelection]="true"></app-card-item>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<ng-container *ngFor="let chapter of storyChapters; let idx = index; trackBy: trackByChapterIdentity">
|
<ng-container *ngFor="let chapter of storyChapters; let idx = index; trackBy: trackByChapterIdentity">
|
||||||
<app-card-item class="col-auto p-2" *ngIf="!chapter.isSpecial" [entity]="chapter" [title]="formatChapterTitle(chapter)" (click)="openChapter(chapter)"
|
<app-card-item class="col-auto p-2" *ngIf="!chapter.isSpecial" [entity]="chapter" [title]="chapter.title" (click)="openChapter(chapter)"
|
||||||
[imageUrl]="imageService.getChapterCoverImage(chapter.id) + '&offset=' + coverImageOffset"
|
[imageUrl]="imageService.getChapterCoverImage(chapter.id) + '&offset=' + coverImageOffset"
|
||||||
[read]="chapter.pagesRead" [total]="chapter.pages" [actions]="chapterActions" (selection)="bulkSelectionService.handleCardSelection('chapter', idx, storyChapters.length, $event)" [selected]="bulkSelectionService.isCardSelected('chapter', idx)" [allowSelection]="true"></app-card-item>
|
[read]="chapter.pagesRead" [total]="chapter.pages" [actions]="chapterActions" (selection)="bulkSelectionService.handleCardSelection('chapter', idx, storyChapters.length, $event)" [selected]="bulkSelectionService.isCardSelected('chapter', idx)" [allowSelection]="true"></app-card-item>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
@ -96,7 +96,7 @@
|
|||||||
<ng-template ngbNavContent>
|
<ng-template ngbNavContent>
|
||||||
<div class="row g-0">
|
<div class="row g-0">
|
||||||
<ng-container *ngFor="let volume of volumes; let idx = index; trackBy: trackByVolumeIdentity">
|
<ng-container *ngFor="let volume of volumes; let idx = index; trackBy: trackByVolumeIdentity">
|
||||||
<app-card-item class="col-auto p-2" [entity]="volume" [title]="formatVolumeTitle(volume)" (click)="openVolume(volume)"
|
<app-card-item class="col-auto p-2" [entity]="volume" [title]="volume.name" (click)="openVolume(volume)"
|
||||||
[imageUrl]="imageService.getVolumeCoverImage(volume.id) + '&offset=' + coverImageOffset"
|
[imageUrl]="imageService.getVolumeCoverImage(volume.id) + '&offset=' + coverImageOffset"
|
||||||
[read]="volume.pagesRead" [total]="volume.pages" [actions]="volumeActions" (selection)="bulkSelectionService.handleCardSelection('volume', idx, volumes.length, $event)" [selected]="bulkSelectionService.isCardSelected('volume', idx)" [allowSelection]="true"></app-card-item>
|
[read]="volume.pagesRead" [total]="volume.pages" [actions]="volumeActions" (selection)="bulkSelectionService.handleCardSelection('volume', idx, volumes.length, $event)" [selected]="bulkSelectionService.isCardSelected('volume', idx)" [allowSelection]="true"></app-card-item>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
@ -108,7 +108,7 @@
|
|||||||
<ng-template ngbNavContent>
|
<ng-template ngbNavContent>
|
||||||
<div class="row g-0">
|
<div class="row g-0">
|
||||||
<ng-container *ngFor="let chapter of chapters; let idx = index; trackBy: trackByChapterIdentity">
|
<ng-container *ngFor="let chapter of chapters; let idx = index; trackBy: trackByChapterIdentity">
|
||||||
<app-card-item class="col-auto p-2" *ngIf="!chapter.isSpecial" [entity]="chapter" [title]="formatChapterTitle(chapter)" (click)="openChapter(chapter)"
|
<app-card-item class="col-auto p-2" *ngIf="!chapter.isSpecial" [entity]="chapter" [title]="chapter.title" (click)="openChapter(chapter)"
|
||||||
[imageUrl]="imageService.getChapterCoverImage(chapter.id) + '&offset=' + coverImageOffset"
|
[imageUrl]="imageService.getChapterCoverImage(chapter.id) + '&offset=' + coverImageOffset"
|
||||||
[read]="chapter.pagesRead" [total]="chapter.pages" [actions]="chapterActions" (selection)="bulkSelectionService.handleCardSelection('chapter', idx, chapters.length, $event)" [selected]="bulkSelectionService.isCardSelected('chapter', idx)" [allowSelection]="true"></app-card-item>
|
[read]="chapter.pagesRead" [total]="chapter.pages" [actions]="chapterActions" (selection)="bulkSelectionService.handleCardSelection('chapter', idx, chapters.length, $event)" [selected]="bulkSelectionService.isCardSelected('chapter', idx)" [allowSelection]="true"></app-card-item>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<app-side-nav-companion-bar>
|
<app-side-nav-companion-bar>
|
||||||
<h1 title>
|
<h2 title>
|
||||||
User Dashboard
|
User Dashboard
|
||||||
</h1>
|
</h2>
|
||||||
</app-side-nav-companion-bar>
|
</app-side-nav-companion-bar>
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<ul ngbNav #nav="ngbNav" [(activeId)]="active" class="nav nav-tabs">
|
<ul ngbNav #nav="ngbNav" [(activeId)]="active" class="nav nav-tabs">
|
||||||
|
@ -8,7 +8,7 @@ body {
|
|||||||
color-scheme: var(--color-scheme);
|
color-scheme: var(--color-scheme);
|
||||||
max-height: 100%;
|
max-height: 100%;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
margin-top: 56px;
|
//margin-top: 56px; // Set by nav service
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user