Bookmarking Pages within the Reader (#469)
# Added - Added: Added the ability to bookmark certain pages within the manga (image) reader and later download them from the series context menu. # Fixed - Fixed: Fixed an issue where after adding a new folder to an existing library, a scan wouldn't be kicked off - Fixed: In some cases, after clicking the background of a modal, the modal would close, but state wouldn't be handled as if cancel was pushed # Changed - Changed: Admin contextual actions on cards will now be separated by a line to help differentiate. - Changed: Performance enhancement on an API used before reading # Dev - Bumped dependencies to latest versions ============================================= * Bumped versions of dependencies and refactored bookmark to progress. * Refactored method names in UI from bookmark to progress to prepare for new bookmark entity * Basic code is done, user can now bookmark a page (currently image reader only). * Comments and pipes * Some accessibility for new bookmark button * Fixed up the APIs to work correctly, added a new modal to quickly explore bookmarks (not implemented, not final). * Cleanup on the UI side to get the modal to look decent * Added dismissed handlers for modals where appropriate * Refactored UI to only show number of bookmarks across files to simplify delivery. Admin actionables are now separated by hr vs non-admin actions. * Basic API implemented, now to implement the ability to actually extract files. * Implemented the ability to download bookmarks. * Fixed a bug where adding a new folder to an existing library would not trigger a scan library task. * Fixed an issue that could cause bookmarked pages to get copied out of order. * Added handler from series-card component
This commit is contained in:
parent
d1d7df9291
commit
e9ec6671d5
49 changed files with 1860 additions and 241 deletions
7
API/Data/BookmarkRepository.cs
Normal file
7
API/Data/BookmarkRepository.cs
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
namespace API.Data
|
||||
{
|
||||
public class BookmarkRepository
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -8,7 +8,7 @@ using Microsoft.EntityFrameworkCore.ChangeTracking;
|
|||
|
||||
namespace API.Data
|
||||
{
|
||||
public sealed class DataContext : IdentityDbContext<AppUser, AppRole, int,
|
||||
public sealed class DataContext : IdentityDbContext<AppUser, AppRole, int,
|
||||
IdentityUserClaim<int>, AppUserRole, IdentityUserLogin<int>,
|
||||
IdentityRoleClaim<int>, IdentityUserToken<int>>
|
||||
{
|
||||
|
|
@ -17,10 +17,10 @@ namespace API.Data
|
|||
ChangeTracker.Tracked += OnEntityTracked;
|
||||
ChangeTracker.StateChanged += OnEntityStateChanged;
|
||||
}
|
||||
|
||||
|
||||
public DbSet<Library> Library { get; set; }
|
||||
public DbSet<Series> Series { get; set; }
|
||||
|
||||
|
||||
public DbSet<Chapter> Chapter { get; set; }
|
||||
public DbSet<Volume> Volume { get; set; }
|
||||
public DbSet<AppUser> AppUser { get; set; }
|
||||
|
|
@ -31,18 +31,19 @@ namespace API.Data
|
|||
public DbSet<AppUserPreferences> AppUserPreferences { get; set; }
|
||||
public DbSet<SeriesMetadata> SeriesMetadata { get; set; }
|
||||
public DbSet<CollectionTag> CollectionTag { get; set; }
|
||||
public DbSet<AppUserBookmark> AppUserBookmark { get; set; }
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder builder)
|
||||
{
|
||||
base.OnModelCreating(builder);
|
||||
|
||||
|
||||
|
||||
builder.Entity<AppUser>()
|
||||
.HasMany(ur => ur.UserRoles)
|
||||
.WithOne(u => u.User)
|
||||
.HasForeignKey(ur => ur.UserId)
|
||||
.IsRequired();
|
||||
|
||||
|
||||
builder.Entity<AppRole>()
|
||||
.HasMany(ur => ur.UserRoles)
|
||||
.WithOne(u => u.Role)
|
||||
|
|
@ -50,7 +51,7 @@ namespace API.Data
|
|||
.IsRequired();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void OnEntityTracked(object sender, EntityTrackedEventArgs e)
|
||||
{
|
||||
if (!e.FromQuery && e.Entry.State == EntityState.Added && e.Entry.Entity is IEntityDate entity)
|
||||
|
|
@ -58,7 +59,7 @@ namespace API.Data
|
|||
entity.Created = DateTime.Now;
|
||||
entity.LastModified = DateTime.Now;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void OnEntityStateChanged(object sender, EntityStateChangedEventArgs e)
|
||||
|
|
@ -67,4 +68,4 @@ namespace API.Data
|
|||
entity.LastModified = DateTime.Now;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
913
API/Data/Migrations/20210809210326_BookmarkPages.Designer.cs
generated
Normal file
913
API/Data/Migrations/20210809210326_BookmarkPages.Designer.cs
generated
Normal file
|
|
@ -0,0 +1,913 @@
|
|||
// <auto-generated />
|
||||
using System;
|
||||
using API.Data;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
|
||||
namespace API.Data.Migrations
|
||||
{
|
||||
[DbContext(typeof(DataContext))]
|
||||
[Migration("20210809210326_BookmarkPages")]
|
||||
partial class BookmarkPages
|
||||
{
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "5.0.8");
|
||||
|
||||
modelBuilder.Entity("API.Entities.AppRole", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("ConcurrencyStamp")
|
||||
.IsConcurrencyToken()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("NormalizedName")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("NormalizedName")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("RoleNameIndex");
|
||||
|
||||
b.ToTable("AspNetRoles");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.AppUser", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("AccessFailedCount")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("ConcurrencyStamp")
|
||||
.IsConcurrencyToken()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("Created")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<bool>("EmailConfirmed")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime>("LastActive")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<bool>("LockoutEnabled")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTimeOffset?>("LockoutEnd")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("NormalizedEmail")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("NormalizedUserName")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("PasswordHash")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("PhoneNumber")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<bool>("PhoneNumberConfirmed")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint>("RowVersion")
|
||||
.IsConcurrencyToken()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("SecurityStamp")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<bool>("TwoFactorEnabled")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("UserName")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("NormalizedEmail")
|
||||
.HasDatabaseName("EmailIndex");
|
||||
|
||||
b.HasIndex("NormalizedUserName")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("UserNameIndex");
|
||||
|
||||
b.ToTable("AspNetUsers");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.AppUserBookmark", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("AppUserId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("ChapterId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("Page")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("SeriesId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("VolumeId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AppUserId");
|
||||
|
||||
b.ToTable("AppUserBookmark");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.AppUserPreferences", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("AppUserId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool>("AutoCloseMenu")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool>("BookReaderDarkMode")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("BookReaderFontFamily")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("BookReaderFontSize")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("BookReaderLineSpacing")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("BookReaderMargin")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("BookReaderReadingDirection")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool>("BookReaderTapToPaginate")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("PageSplitOption")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("ReaderMode")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("ReadingDirection")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("ScalingOption")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool>("SiteDarkMode")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AppUserId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("AppUserPreferences");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.AppUserProgress", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("AppUserId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("BookScrollId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("ChapterId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime>("Created")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("LastModified")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("PagesRead")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("SeriesId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("VolumeId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AppUserId");
|
||||
|
||||
b.ToTable("AppUserProgresses");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.AppUserRating", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("AppUserId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("Rating")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Review")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("SeriesId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AppUserId");
|
||||
|
||||
b.ToTable("AppUserRating");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.AppUserRole", b =>
|
||||
{
|
||||
b.Property<int>("UserId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("RoleId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("UserId", "RoleId");
|
||||
|
||||
b.HasIndex("RoleId");
|
||||
|
||||
b.ToTable("AspNetUserRoles");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.Chapter", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<byte[]>("CoverImage")
|
||||
.HasColumnType("BLOB");
|
||||
|
||||
b.Property<DateTime>("Created")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<bool>("IsSpecial")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime>("LastModified")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Number")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("Pages")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Range")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("VolumeId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("VolumeId");
|
||||
|
||||
b.ToTable("Chapter");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.CollectionTag", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<byte[]>("CoverImage")
|
||||
.HasColumnType("BLOB");
|
||||
|
||||
b.Property<string>("NormalizedTitle")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<bool>("Promoted")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint>("RowVersion")
|
||||
.IsConcurrencyToken()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Summary")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Id", "Promoted")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("CollectionTag");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.FolderPath", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime>("LastScanned")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("LibraryId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Path")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("LibraryId");
|
||||
|
||||
b.ToTable("FolderPath");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.Library", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("CoverImage")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("Created")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("LastModified")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("Type")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Library");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.MangaFile", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("ChapterId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("FilePath")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("Format")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime>("LastModified")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("Pages")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("ChapterId");
|
||||
|
||||
b.ToTable("MangaFile");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.Series", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<byte[]>("CoverImage")
|
||||
.HasColumnType("BLOB");
|
||||
|
||||
b.Property<DateTime>("Created")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("Format")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime>("LastModified")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("LibraryId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("LocalizedName")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("NormalizedName")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("OriginalName")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("Pages")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("SortName")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Summary")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("LibraryId");
|
||||
|
||||
b.HasIndex("Name", "NormalizedName", "LocalizedName", "LibraryId", "Format")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Series");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.SeriesMetadata", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint>("RowVersion")
|
||||
.IsConcurrencyToken()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("SeriesId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("SeriesId")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("Id", "SeriesId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("SeriesMetadata");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.ServerSetting", b =>
|
||||
{
|
||||
b.Property<int>("Key")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint>("RowVersion")
|
||||
.IsConcurrencyToken()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Value")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Key");
|
||||
|
||||
b.ToTable("ServerSetting");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.Volume", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<byte[]>("CoverImage")
|
||||
.HasColumnType("BLOB");
|
||||
|
||||
b.Property<DateTime>("Created")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("LastModified")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("Number")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("Pages")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("SeriesId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("SeriesId");
|
||||
|
||||
b.ToTable("Volume");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("AppUserLibrary", b =>
|
||||
{
|
||||
b.Property<int>("AppUsersId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("LibrariesId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("AppUsersId", "LibrariesId");
|
||||
|
||||
b.HasIndex("LibrariesId");
|
||||
|
||||
b.ToTable("AppUserLibrary");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("CollectionTagSeriesMetadata", b =>
|
||||
{
|
||||
b.Property<int>("CollectionTagsId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("SeriesMetadatasId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("CollectionTagsId", "SeriesMetadatasId");
|
||||
|
||||
b.HasIndex("SeriesMetadatasId");
|
||||
|
||||
b.ToTable("CollectionTagSeriesMetadata");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<int>", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("ClaimType")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ClaimValue")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("RoleId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("RoleId");
|
||||
|
||||
b.ToTable("AspNetRoleClaims");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<int>", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("ClaimType")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ClaimValue")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("UserId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("AspNetUserClaims");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<int>", b =>
|
||||
{
|
||||
b.Property<string>("LoginProvider")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ProviderKey")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ProviderDisplayName")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("UserId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("LoginProvider", "ProviderKey");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("AspNetUserLogins");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<int>", b =>
|
||||
{
|
||||
b.Property<int>("UserId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("LoginProvider")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Value")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("UserId", "LoginProvider", "Name");
|
||||
|
||||
b.ToTable("AspNetUserTokens");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.AppUserBookmark", b =>
|
||||
{
|
||||
b.HasOne("API.Entities.AppUser", "AppUser")
|
||||
.WithMany("Bookmarks")
|
||||
.HasForeignKey("AppUserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("AppUser");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.AppUserPreferences", b =>
|
||||
{
|
||||
b.HasOne("API.Entities.AppUser", "AppUser")
|
||||
.WithOne("UserPreferences")
|
||||
.HasForeignKey("API.Entities.AppUserPreferences", "AppUserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("AppUser");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.AppUserProgress", b =>
|
||||
{
|
||||
b.HasOne("API.Entities.AppUser", "AppUser")
|
||||
.WithMany("Progresses")
|
||||
.HasForeignKey("AppUserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("AppUser");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.AppUserRating", b =>
|
||||
{
|
||||
b.HasOne("API.Entities.AppUser", "AppUser")
|
||||
.WithMany("Ratings")
|
||||
.HasForeignKey("AppUserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("AppUser");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.AppUserRole", b =>
|
||||
{
|
||||
b.HasOne("API.Entities.AppRole", "Role")
|
||||
.WithMany("UserRoles")
|
||||
.HasForeignKey("RoleId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("API.Entities.AppUser", "User")
|
||||
.WithMany("UserRoles")
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Role");
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.Chapter", b =>
|
||||
{
|
||||
b.HasOne("API.Entities.Volume", "Volume")
|
||||
.WithMany("Chapters")
|
||||
.HasForeignKey("VolumeId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Volume");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.FolderPath", b =>
|
||||
{
|
||||
b.HasOne("API.Entities.Library", "Library")
|
||||
.WithMany("Folders")
|
||||
.HasForeignKey("LibraryId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Library");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.MangaFile", b =>
|
||||
{
|
||||
b.HasOne("API.Entities.Chapter", "Chapter")
|
||||
.WithMany("Files")
|
||||
.HasForeignKey("ChapterId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Chapter");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.Series", b =>
|
||||
{
|
||||
b.HasOne("API.Entities.Library", "Library")
|
||||
.WithMany("Series")
|
||||
.HasForeignKey("LibraryId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Library");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.SeriesMetadata", b =>
|
||||
{
|
||||
b.HasOne("API.Entities.Series", "Series")
|
||||
.WithOne("Metadata")
|
||||
.HasForeignKey("API.Entities.SeriesMetadata", "SeriesId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Series");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.Volume", b =>
|
||||
{
|
||||
b.HasOne("API.Entities.Series", "Series")
|
||||
.WithMany("Volumes")
|
||||
.HasForeignKey("SeriesId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Series");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("AppUserLibrary", b =>
|
||||
{
|
||||
b.HasOne("API.Entities.AppUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("AppUsersId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("API.Entities.Library", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("LibrariesId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("CollectionTagSeriesMetadata", b =>
|
||||
{
|
||||
b.HasOne("API.Entities.CollectionTag", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("CollectionTagsId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("API.Entities.SeriesMetadata", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("SeriesMetadatasId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<int>", b =>
|
||||
{
|
||||
b.HasOne("API.Entities.AppRole", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("RoleId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<int>", b =>
|
||||
{
|
||||
b.HasOne("API.Entities.AppUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<int>", b =>
|
||||
{
|
||||
b.HasOne("API.Entities.AppUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<int>", b =>
|
||||
{
|
||||
b.HasOne("API.Entities.AppUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.AppRole", b =>
|
||||
{
|
||||
b.Navigation("UserRoles");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.AppUser", b =>
|
||||
{
|
||||
b.Navigation("Bookmarks");
|
||||
|
||||
b.Navigation("Progresses");
|
||||
|
||||
b.Navigation("Ratings");
|
||||
|
||||
b.Navigation("UserPreferences");
|
||||
|
||||
b.Navigation("UserRoles");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.Chapter", b =>
|
||||
{
|
||||
b.Navigation("Files");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.Library", b =>
|
||||
{
|
||||
b.Navigation("Folders");
|
||||
|
||||
b.Navigation("Series");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.Series", b =>
|
||||
{
|
||||
b.Navigation("Metadata");
|
||||
|
||||
b.Navigation("Volumes");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.Volume", b =>
|
||||
{
|
||||
b.Navigation("Chapters");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
44
API/Data/Migrations/20210809210326_BookmarkPages.cs
Normal file
44
API/Data/Migrations/20210809210326_BookmarkPages.cs
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
namespace API.Data.Migrations
|
||||
{
|
||||
public partial class BookmarkPages : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "AppUserBookmark",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
Page = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
VolumeId = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
SeriesId = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
ChapterId = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
AppUserId = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_AppUserBookmark", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_AppUserBookmark_AspNetUsers_AppUserId",
|
||||
column: x => x.AppUserId,
|
||||
principalTable: "AspNetUsers",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AppUserBookmark_AppUserId",
|
||||
table: "AppUserBookmark",
|
||||
column: "AppUserId");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "AppUserBookmark");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -14,7 +14,7 @@ namespace API.Data.Migrations
|
|||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "5.0.4");
|
||||
.HasAnnotation("ProductVersion", "5.0.8");
|
||||
|
||||
modelBuilder.Entity("API.Entities.AppRole", b =>
|
||||
{
|
||||
|
|
@ -118,6 +118,34 @@ namespace API.Data.Migrations
|
|||
b.ToTable("AspNetUsers");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.AppUserBookmark", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("AppUserId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("ChapterId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("Page")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("SeriesId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("VolumeId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AppUserId");
|
||||
|
||||
b.ToTable("AppUserBookmark");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.AppUserPreferences", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
|
|
@ -641,6 +669,17 @@ namespace API.Data.Migrations
|
|||
b.ToTable("AspNetUserTokens");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.AppUserBookmark", b =>
|
||||
{
|
||||
b.HasOne("API.Entities.AppUser", "AppUser")
|
||||
.WithMany("Bookmarks")
|
||||
.HasForeignKey("AppUserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("AppUser");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.AppUserPreferences", b =>
|
||||
{
|
||||
b.HasOne("API.Entities.AppUser", "AppUser")
|
||||
|
|
@ -832,6 +871,8 @@ namespace API.Data.Migrations
|
|||
|
||||
modelBuilder.Entity("API.Entities.AppUser", b =>
|
||||
{
|
||||
b.Navigation("Bookmarks");
|
||||
|
||||
b.Navigation("Progresses");
|
||||
|
||||
b.Navigation("Ratings");
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ namespace API.Data
|
|||
}
|
||||
|
||||
public ISeriesRepository SeriesRepository => new SeriesRepository(_context, _mapper);
|
||||
public IUserRepository UserRepository => new UserRepository(_context, _userManager);
|
||||
public IUserRepository UserRepository => new UserRepository(_context, _userManager, _mapper);
|
||||
public ILibraryRepository LibraryRepository => new LibraryRepository(_context, _mapper);
|
||||
|
||||
public IVolumeRepository VolumeRepository => new VolumeRepository(_context, _mapper);
|
||||
|
|
@ -56,4 +56,4 @@ namespace API.Data
|
|||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ using API.Constants;
|
|||
using API.DTOs;
|
||||
using API.Entities;
|
||||
using API.Interfaces;
|
||||
using AutoMapper;
|
||||
using AutoMapper.QueryableExtensions;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
|
|
@ -14,18 +16,20 @@ namespace API.Data
|
|||
{
|
||||
private readonly DataContext _context;
|
||||
private readonly UserManager<AppUser> _userManager;
|
||||
private readonly IMapper _mapper;
|
||||
|
||||
public UserRepository(DataContext context, UserManager<AppUser> userManager)
|
||||
public UserRepository(DataContext context, UserManager<AppUser> userManager, IMapper mapper)
|
||||
{
|
||||
_context = context;
|
||||
_userManager = userManager;
|
||||
_mapper = mapper;
|
||||
}
|
||||
|
||||
public void Update(AppUser user)
|
||||
{
|
||||
_context.Entry(user).State = EntityState.Modified;
|
||||
}
|
||||
|
||||
|
||||
public void Update(AppUserPreferences preferences)
|
||||
{
|
||||
_context.Entry(preferences).State = EntityState.Modified;
|
||||
|
|
@ -45,6 +49,7 @@ namespace API.Data
|
|||
{
|
||||
return await _context.Users
|
||||
.Include(u => u.Progresses)
|
||||
.Include(u => u.Bookmarks)
|
||||
.SingleOrDefaultAsync(x => x.UserName == username);
|
||||
}
|
||||
|
||||
|
|
@ -71,6 +76,36 @@ namespace API.Data
|
|||
.SingleOrDefaultAsync(p => p.AppUser.UserName == username);
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<BookmarkDto>> GetBookmarkDtosForSeries(int userId, int seriesId)
|
||||
{
|
||||
return await _context.AppUserBookmark
|
||||
.Where(x => x.AppUserId == userId && x.SeriesId == seriesId)
|
||||
.OrderBy(x => x.Page)
|
||||
.AsNoTracking()
|
||||
.ProjectTo<BookmarkDto>(_mapper.ConfigurationProvider)
|
||||
.ToListAsync();
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<BookmarkDto>> GetBookmarkDtosForVolume(int userId, int volumeId)
|
||||
{
|
||||
return await _context.AppUserBookmark
|
||||
.Where(x => x.AppUserId == userId && x.VolumeId == volumeId)
|
||||
.OrderBy(x => x.Page)
|
||||
.AsNoTracking()
|
||||
.ProjectTo<BookmarkDto>(_mapper.ConfigurationProvider)
|
||||
.ToListAsync();
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<BookmarkDto>> GetBookmarkDtosForChapter(int userId, int chapterId)
|
||||
{
|
||||
return await _context.AppUserBookmark
|
||||
.Where(x => x.AppUserId == userId && x.ChapterId == chapterId)
|
||||
.OrderBy(x => x.Page)
|
||||
.AsNoTracking()
|
||||
.ProjectTo<BookmarkDto>(_mapper.ConfigurationProvider)
|
||||
.ToListAsync();
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<MemberDto>> GetMembersAsync()
|
||||
{
|
||||
return await _context.Users
|
||||
|
|
@ -97,4 +132,4 @@ namespace API.Data
|
|||
.ToListAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using API.DTOs;
|
||||
using API.DTOs.Reader;
|
||||
using API.Entities;
|
||||
using API.Interfaces;
|
||||
using AutoMapper;
|
||||
|
|
@ -38,7 +40,6 @@ namespace API.Data
|
|||
.SingleOrDefaultAsync(c => c.Id == chapterId);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns Chapters for a volume id.
|
||||
/// </summary>
|
||||
|
|
@ -79,13 +80,30 @@ namespace API.Data
|
|||
return chapter;
|
||||
}
|
||||
|
||||
public async Task<IList<MangaFile>> GetFilesForChapter(int chapterId)
|
||||
/// <summary>
|
||||
/// Returns non-tracked files for a given chapterId
|
||||
/// </summary>
|
||||
/// <param name="chapterId"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<IList<MangaFile>> GetFilesForChapterAsync(int chapterId)
|
||||
{
|
||||
return await _context.MangaFile
|
||||
.Where(c => chapterId == c.ChapterId)
|
||||
.AsNoTracking()
|
||||
.ToListAsync();
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns non-tracked files for a set of chapterIds
|
||||
/// </summary>
|
||||
/// <param name="chapterIds"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<IList<MangaFile>> GetFilesForChaptersAsync(IReadOnlyList<int> chapterIds)
|
||||
{
|
||||
return await _context.MangaFile
|
||||
.Where(c => chapterIds.Contains(c.ChapterId))
|
||||
.AsNoTracking()
|
||||
.ToListAsync();
|
||||
}
|
||||
|
||||
public async Task<IList<MangaFile>> GetFilesForVolume(int volumeId)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue