Stablize the Styles (#1128)
* Fixed a bug where adding multiple series to reading list would throw an error on UI, but it was successful. * When a series has a reading list, we now show the connection on Series detail. * Removed all baseurl code from UI and not-connected component since we no longer use it. * Fixed tag badges not showing a border. Added last read time to the series detail page * Fixed up error interceptor to remove no-connection code * Changed implementation for series detail. Book libraries will never send chapters back. Volume 0 volumes will not be sent in volumes ever. Fixed up more renaming logic on books to send more accurate representations to the UI. * Cleaned up the selected tab and tab display logic * Fixed a bad where statement in reading lists for series * Fixed up tab logic again * Fixed a small margin on search backdrop * Made badge expander button smaller to align with badges * Fixed a few UIs due to .form-group and .form-row being removed * Updated Theme component page to help with style testing * Added more components to theme tester * Cleaned up some styling * Fixed opacity on search item hover
This commit is contained in:
parent
cb9b54b8de
commit
864d693790
38 changed files with 425 additions and 187 deletions
|
@ -49,6 +49,15 @@ namespace API.Controllers
|
|||
return Ok(items);
|
||||
}
|
||||
|
||||
[HttpGet("lists-for-series")]
|
||||
public async Task<ActionResult<IEnumerable<ReadingListDto>>> GetListsForSeries(int seriesId)
|
||||
{
|
||||
var userId = await _unitOfWork.UserRepository.GetUserIdByUsernameAsync(User.GetUsername());
|
||||
var items = await _unitOfWork.ReadingListRepository.GetReadingListDtosForSeriesAndUserAsync(userId, seriesId, true);
|
||||
|
||||
return Ok(items);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fetches all reading list items for a given list including rich metadata around series, volume, chapters, and progress
|
||||
/// </summary>
|
||||
|
|
|
@ -18,6 +18,10 @@ namespace API.DTOs
|
|||
/// </summary>
|
||||
public int PagesRead { get; set; }
|
||||
/// <summary>
|
||||
/// DateTime representing last time the series was Read. Calculated at API-time.
|
||||
/// </summary>
|
||||
public DateTime LatestReadDate { get; set; }
|
||||
/// <summary>
|
||||
/// Rating from logged in user. Calculated at API-time.
|
||||
/// </summary>
|
||||
public int UserRating { get; set; }
|
||||
|
|
|
@ -19,6 +19,9 @@ public interface IReadingListRepository
|
|||
Task<IEnumerable<ReadingListItemDto>> AddReadingProgressModifiers(int userId, IList<ReadingListItemDto> items);
|
||||
Task<ReadingListDto> GetReadingListDtoByTitleAsync(string title);
|
||||
Task<IEnumerable<ReadingListItem>> GetReadingListItemsByIdAsync(int readingListId);
|
||||
|
||||
Task<IEnumerable<ReadingListDto>> GetReadingListDtosForSeriesAndUserAsync(int userId, int seriesId,
|
||||
bool includePromoted);
|
||||
void Remove(ReadingListItem item);
|
||||
void BulkRemove(IEnumerable<ReadingListItem> items);
|
||||
void Update(ReadingList list);
|
||||
|
@ -62,6 +65,18 @@ public class ReadingListRepository : IReadingListRepository
|
|||
return await PagedList<ReadingListDto>.CreateAsync(query, userParams.PageNumber, userParams.PageSize);
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<ReadingListDto>> GetReadingListDtosForSeriesAndUserAsync(int userId, int seriesId, bool includePromoted)
|
||||
{
|
||||
var query = _context.ReadingList
|
||||
.Where(l => l.AppUserId == userId || (includePromoted && l.Promoted ))
|
||||
.Where(l => l.Items.Any(i => i.SeriesId == seriesId))
|
||||
.OrderBy(l => l.LastModified)
|
||||
.ProjectTo<ReadingListDto>(_mapper.ConfigurationProvider)
|
||||
.AsNoTracking();
|
||||
|
||||
return await query.ToListAsync();
|
||||
}
|
||||
|
||||
public async Task<ReadingList> GetReadingListByIdAsync(int readingListId)
|
||||
{
|
||||
return await _context.ReadingList
|
||||
|
|
|
@ -469,6 +469,7 @@ public class SeriesRepository : ISeriesRepository
|
|||
if (rating == null) continue;
|
||||
s.UserRating = rating.Rating;
|
||||
s.UserReview = rating.Review;
|
||||
s.LatestReadDate = userProgress.Max(p => p.LastModified);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using API.Comparators;
|
||||
|
@ -217,14 +218,34 @@ public class SeriesService : ISeriesService
|
|||
var chapters = volumes.SelectMany(v => v.Chapters).ToList();
|
||||
|
||||
// For books, the Name of the Volume is remapped to the actual name of the book, rather than Volume number.
|
||||
var processedVolumes = new List<VolumeDto>();
|
||||
if (libraryType == LibraryType.Book)
|
||||
{
|
||||
foreach (var volume in volumes)
|
||||
{
|
||||
var firstChapter = volume.Chapters.First();
|
||||
if (!string.IsNullOrEmpty(firstChapter.TitleName)) volume.Name += $" - {firstChapter.TitleName}";
|
||||
// On Books, skip volumes that are specials, since these will be shown
|
||||
if (firstChapter.IsSpecial) continue;
|
||||
if (string.IsNullOrEmpty(firstChapter.TitleName))
|
||||
{
|
||||
if (!firstChapter.Range.Equals(Parser.Parser.DefaultVolume))
|
||||
{
|
||||
var title = Path.GetFileNameWithoutExtension(firstChapter.Range);
|
||||
if (string.IsNullOrEmpty(title)) continue;
|
||||
volume.Name += $" - {title}";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
volume.Name += $" - {firstChapter.TitleName}";
|
||||
}
|
||||
processedVolumes.Add(volume);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
processedVolumes = volumes.Where(v => v.Number > 0).ToList();
|
||||
}
|
||||
|
||||
|
||||
var specials = new List<ChapterDto>();
|
||||
|
@ -233,14 +254,26 @@ public class SeriesService : ISeriesService
|
|||
chapter.Title = Parser.Parser.CleanSpecialTitle(chapter.Title);
|
||||
specials.Add(chapter);
|
||||
}
|
||||
|
||||
// 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;
|
||||
if (libraryType == LibraryType.Book)
|
||||
{
|
||||
retChapters = Array.Empty<ChapterDto>();
|
||||
} else
|
||||
{
|
||||
retChapters = chapters
|
||||
.Where(ShouldIncludeChapter)
|
||||
.OrderBy(c => float.Parse(c.Number), new ChapterSortComparer());
|
||||
}
|
||||
|
||||
|
||||
|
||||
return new SeriesDetailDto()
|
||||
{
|
||||
Specials = specials,
|
||||
// Don't show chapter 0 (aka single volume chapters) in the Chapters tab or books that are just single numbers (they show as volumes)
|
||||
Chapters = chapters
|
||||
.Where(ShouldIncludeChapter)
|
||||
.OrderBy(c => float.Parse(c.Number), new ChapterSortComparer()),
|
||||
Volumes = volumes,
|
||||
Chapters = retChapters,
|
||||
Volumes = processedVolumes,
|
||||
StorylineChapters = volumes
|
||||
.Where(v => v.Number == 0)
|
||||
.SelectMany(v => v.Chapters)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue