mirror of
https://github.com/Kareadita/Kavita.git
synced 2025-07-07 10:14:12 -04:00
Release Shakeout Day 2 (#1594)
* Fixed a bad color on the PWA titlebar * Added more unit tests, cleaned up some dead code, and made it so when age restriction is Not Applicable, the Unknowns field disables * Don't show an empty menu when user has no permissions * Fixed deleting a library with relation causing library deleting to fail * Consolidated some includes code into one method for Series Repo * Small fixes
This commit is contained in:
parent
ef662d3235
commit
26d32cbf28
@ -1,4 +1,5 @@
|
|||||||
using System.Collections.Generic;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Data.Common;
|
using System.Data.Common;
|
||||||
using System.IO.Abstractions.TestingHelpers;
|
using System.IO.Abstractions.TestingHelpers;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@ -125,7 +126,7 @@ public class SeriesServiceTests
|
|||||||
return fileSystem;
|
return fileSystem;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static UpdateRelatedSeriesDto InstantiateRelationsDto(Series series)
|
private static UpdateRelatedSeriesDto CreateRelationsDto(Series series)
|
||||||
{
|
{
|
||||||
return new UpdateRelatedSeriesDto()
|
return new UpdateRelatedSeriesDto()
|
||||||
{
|
{
|
||||||
@ -1178,7 +1179,7 @@ public class SeriesServiceTests
|
|||||||
|
|
||||||
var series1 = await _unitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Related);
|
var series1 = await _unitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Related);
|
||||||
// Add relations
|
// Add relations
|
||||||
var addRelationDto = InstantiateRelationsDto(series1);
|
var addRelationDto = CreateRelationsDto(series1);
|
||||||
addRelationDto.Adaptations.Add(2);
|
addRelationDto.Adaptations.Add(2);
|
||||||
addRelationDto.Sequels.Add(3);
|
addRelationDto.Sequels.Add(3);
|
||||||
await _seriesService.UpdateRelatedSeries(addRelationDto);
|
await _seriesService.UpdateRelatedSeries(addRelationDto);
|
||||||
@ -1225,7 +1226,7 @@ public class SeriesServiceTests
|
|||||||
|
|
||||||
var series1 = await _unitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Related);
|
var series1 = await _unitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Related);
|
||||||
// Add relations
|
// Add relations
|
||||||
var addRelationDto = InstantiateRelationsDto(series1);
|
var addRelationDto = CreateRelationsDto(series1);
|
||||||
addRelationDto.Adaptations.Add(2);
|
addRelationDto.Adaptations.Add(2);
|
||||||
addRelationDto.Sequels.Add(3);
|
addRelationDto.Sequels.Add(3);
|
||||||
await _seriesService.UpdateRelatedSeries(addRelationDto);
|
await _seriesService.UpdateRelatedSeries(addRelationDto);
|
||||||
@ -1233,7 +1234,7 @@ public class SeriesServiceTests
|
|||||||
Assert.Equal(3, series1.Relations.Single(s => s.TargetSeriesId == 3).TargetSeriesId);
|
Assert.Equal(3, series1.Relations.Single(s => s.TargetSeriesId == 3).TargetSeriesId);
|
||||||
|
|
||||||
// Remove relations
|
// Remove relations
|
||||||
var removeRelationDto = InstantiateRelationsDto(series1);
|
var removeRelationDto = CreateRelationsDto(series1);
|
||||||
await _seriesService.UpdateRelatedSeries(removeRelationDto);
|
await _seriesService.UpdateRelatedSeries(removeRelationDto);
|
||||||
Assert.Empty(series1.Relations.Where(s => s.TargetSeriesId == 1));
|
Assert.Empty(series1.Relations.Where(s => s.TargetSeriesId == 1));
|
||||||
Assert.Empty(series1.Relations.Where(s => s.TargetSeriesId == 2));
|
Assert.Empty(series1.Relations.Where(s => s.TargetSeriesId == 2));
|
||||||
@ -1284,7 +1285,7 @@ public class SeriesServiceTests
|
|||||||
series1.Relations.Add(relation);
|
series1.Relations.Add(relation);
|
||||||
|
|
||||||
// Create a new dto with the previous relation as well
|
// Create a new dto with the previous relation as well
|
||||||
var relationDto = InstantiateRelationsDto(series1);
|
var relationDto = CreateRelationsDto(series1);
|
||||||
relationDto.Adaptations.Add(2);
|
relationDto.Adaptations.Add(2);
|
||||||
|
|
||||||
await _seriesService.UpdateRelatedSeries(relationDto);
|
await _seriesService.UpdateRelatedSeries(relationDto);
|
||||||
@ -1339,7 +1340,7 @@ public class SeriesServiceTests
|
|||||||
await _context.SaveChangesAsync();
|
await _context.SaveChangesAsync();
|
||||||
var series1 = await _unitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Related);
|
var series1 = await _unitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Related);
|
||||||
// Add relations
|
// Add relations
|
||||||
var addRelationDto = InstantiateRelationsDto(series1);
|
var addRelationDto = CreateRelationsDto(series1);
|
||||||
addRelationDto.Editions.Add(2);
|
addRelationDto.Editions.Add(2);
|
||||||
addRelationDto.Prequels.Add(3);
|
addRelationDto.Prequels.Add(3);
|
||||||
addRelationDto.Sequels.Add(4);
|
addRelationDto.Sequels.Add(4);
|
||||||
@ -1353,5 +1354,172 @@ public class SeriesServiceTests
|
|||||||
Assert.NotEmpty(_seriesService.GetRelatedSeries(1, 5).Result.Parent);
|
Assert.NotEmpty(_seriesService.GetRelatedSeries(1, 5).Result.Parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task SeriesRelation_ShouldAllowDeleteOnLibrary()
|
||||||
|
{
|
||||||
|
await ResetDb();
|
||||||
|
_context.Library.Add(new Library()
|
||||||
|
{
|
||||||
|
AppUsers = new List<AppUser>()
|
||||||
|
{
|
||||||
|
new AppUser()
|
||||||
|
{
|
||||||
|
UserName = "majora2007"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Name = "Test LIb",
|
||||||
|
Type = LibraryType.Book,
|
||||||
|
Series = new List<Series>()
|
||||||
|
{
|
||||||
|
new Series()
|
||||||
|
{
|
||||||
|
Name = "Test Series",
|
||||||
|
Volumes = new List<Volume>(){}
|
||||||
|
},
|
||||||
|
new Series()
|
||||||
|
{
|
||||||
|
Name = "Test Series Prequels",
|
||||||
|
Volumes = new List<Volume>(){}
|
||||||
|
},
|
||||||
|
new Series()
|
||||||
|
{
|
||||||
|
Name = "Test Series Sequels",
|
||||||
|
Volumes = new List<Volume>(){}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
await _context.SaveChangesAsync();
|
||||||
|
|
||||||
|
var series1 = await _unitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Related);
|
||||||
|
// Add relations
|
||||||
|
var addRelationDto = CreateRelationsDto(series1);
|
||||||
|
addRelationDto.Adaptations.Add(2);
|
||||||
|
addRelationDto.Sequels.Add(3);
|
||||||
|
await _seriesService.UpdateRelatedSeries(addRelationDto);
|
||||||
|
|
||||||
|
var library = await _unitOfWork.LibraryRepository.GetLibraryForIdAsync(1);
|
||||||
|
_unitOfWork.LibraryRepository.Delete(library);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await _unitOfWork.CommitAsync();
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
Assert.False(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.Null(await _unitOfWork.LibraryRepository.GetLibraryForIdAsync(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task SeriesRelation_ShouldAllowDeleteOnLibrary_WhenSeriesCrossLibraries()
|
||||||
|
{
|
||||||
|
await ResetDb();
|
||||||
|
_context.Library.Add(new Library()
|
||||||
|
{
|
||||||
|
AppUsers = new List<AppUser>()
|
||||||
|
{
|
||||||
|
new AppUser()
|
||||||
|
{
|
||||||
|
UserName = "majora2007"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Name = "Test LIb",
|
||||||
|
Type = LibraryType.Book,
|
||||||
|
Series = new List<Series>()
|
||||||
|
{
|
||||||
|
new Series()
|
||||||
|
{
|
||||||
|
Name = "Test Series",
|
||||||
|
Volumes = new List<Volume>()
|
||||||
|
{
|
||||||
|
new Volume()
|
||||||
|
{
|
||||||
|
Chapters = new List<Chapter>()
|
||||||
|
{
|
||||||
|
new Chapter()
|
||||||
|
{
|
||||||
|
Files = new List<MangaFile>()
|
||||||
|
{
|
||||||
|
new MangaFile()
|
||||||
|
{
|
||||||
|
Pages = 1,
|
||||||
|
FilePath = "fake file"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new Series()
|
||||||
|
{
|
||||||
|
Name = "Test Series Prequels",
|
||||||
|
Volumes = new List<Volume>(){}
|
||||||
|
},
|
||||||
|
new Series()
|
||||||
|
{
|
||||||
|
Name = "Test Series Sequels",
|
||||||
|
Volumes = new List<Volume>(){}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
_context.Library.Add(new Library()
|
||||||
|
{
|
||||||
|
AppUsers = new List<AppUser>()
|
||||||
|
{
|
||||||
|
new AppUser()
|
||||||
|
{
|
||||||
|
UserName = "majora2007"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Name = "Test LIb 2",
|
||||||
|
Type = LibraryType.Book,
|
||||||
|
Series = new List<Series>()
|
||||||
|
{
|
||||||
|
new Series()
|
||||||
|
{
|
||||||
|
Name = "Test Series 2",
|
||||||
|
Volumes = new List<Volume>(){}
|
||||||
|
},
|
||||||
|
new Series()
|
||||||
|
{
|
||||||
|
Name = "Test Series Prequels 2",
|
||||||
|
Volumes = new List<Volume>(){}
|
||||||
|
},
|
||||||
|
new Series()
|
||||||
|
{
|
||||||
|
Name = "Test Series Sequels 2",
|
||||||
|
Volumes = new List<Volume>(){}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
await _context.SaveChangesAsync();
|
||||||
|
|
||||||
|
var series1 = await _unitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Related);
|
||||||
|
// Add relations
|
||||||
|
var addRelationDto = CreateRelationsDto(series1);
|
||||||
|
addRelationDto.Adaptations.Add(4); // cross library link
|
||||||
|
await _seriesService.UpdateRelatedSeries(addRelationDto);
|
||||||
|
|
||||||
|
var library = await _unitOfWork.LibraryRepository.GetLibraryForIdAsync(1, LibraryIncludes.Series);
|
||||||
|
_unitOfWork.LibraryRepository.Delete(library);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await _unitOfWork.CommitAsync();
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
Assert.False(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.Null(await _unitOfWork.LibraryRepository.GetLibraryForIdAsync(1));
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
@ -248,19 +248,24 @@ public class LibraryController : BaseApiController
|
|||||||
if (TaskScheduler.HasScanTaskRunningForLibrary(libraryId))
|
if (TaskScheduler.HasScanTaskRunningForLibrary(libraryId))
|
||||||
{
|
{
|
||||||
// TODO: Figure out how to cancel a job
|
// TODO: Figure out how to cancel a job
|
||||||
|
|
||||||
_logger.LogInformation("User is attempting to delete a library while a scan is in progress");
|
_logger.LogInformation("User is attempting to delete a library while a scan is in progress");
|
||||||
return BadRequest(
|
return BadRequest(
|
||||||
"You cannot delete a library while a scan is in progress. Please wait for scan to continue then try to delete");
|
"You cannot delete a library while a scan is in progress. Please wait for scan to continue then try to delete");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Due to a bad schema that I can't figure out how to fix, we need to erase all RelatedSeries before we delete the library
|
// Due to a bad schema that I can't figure out how to fix, we need to erase all RelatedSeries before we delete the library
|
||||||
foreach (var s in await _unitOfWork.SeriesRepository.GetSeriesForLibraryIdAsync(library.Id))
|
// Aka SeriesRelation has an invalid foreign key
|
||||||
|
foreach (var s in await _unitOfWork.SeriesRepository.GetSeriesForLibraryIdAsync(library.Id,
|
||||||
|
SeriesIncludes.Related))
|
||||||
{
|
{
|
||||||
s.Relations = new List<SeriesRelation>();
|
s.Relations = new List<SeriesRelation>();
|
||||||
_unitOfWork.SeriesRepository.Update(s);
|
_unitOfWork.SeriesRepository.Update(s);
|
||||||
}
|
}
|
||||||
|
await _unitOfWork.CommitAsync();
|
||||||
|
|
||||||
_unitOfWork.LibraryRepository.Delete(library);
|
_unitOfWork.LibraryRepository.Delete(library);
|
||||||
|
|
||||||
await _unitOfWork.CommitAsync();
|
await _unitOfWork.CommitAsync();
|
||||||
|
|
||||||
if (chapterIds.Any())
|
if (chapterIds.Any())
|
||||||
|
@ -165,7 +165,7 @@ namespace API.Data.Migrations
|
|||||||
|
|
||||||
b.HasIndex("AppUserId");
|
b.HasIndex("AppUserId");
|
||||||
|
|
||||||
b.ToTable("AppUserBookmark");
|
b.ToTable("AppUserBookmark", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("API.Entities.AppUserPreferences", b =>
|
modelBuilder.Entity("API.Entities.AppUserPreferences", b =>
|
||||||
@ -256,7 +256,7 @@ namespace API.Data.Migrations
|
|||||||
|
|
||||||
b.HasIndex("ThemeId");
|
b.HasIndex("ThemeId");
|
||||||
|
|
||||||
b.ToTable("AppUserPreferences");
|
b.ToTable("AppUserPreferences", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("API.Entities.AppUserProgress", b =>
|
modelBuilder.Entity("API.Entities.AppUserProgress", b =>
|
||||||
@ -295,7 +295,7 @@ namespace API.Data.Migrations
|
|||||||
|
|
||||||
b.HasIndex("SeriesId");
|
b.HasIndex("SeriesId");
|
||||||
|
|
||||||
b.ToTable("AppUserProgresses");
|
b.ToTable("AppUserProgresses", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("API.Entities.AppUserRating", b =>
|
modelBuilder.Entity("API.Entities.AppUserRating", b =>
|
||||||
@ -322,7 +322,7 @@ namespace API.Data.Migrations
|
|||||||
|
|
||||||
b.HasIndex("SeriesId");
|
b.HasIndex("SeriesId");
|
||||||
|
|
||||||
b.ToTable("AppUserRating");
|
b.ToTable("AppUserRating", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("API.Entities.AppUserRole", b =>
|
modelBuilder.Entity("API.Entities.AppUserRole", b =>
|
||||||
@ -413,7 +413,7 @@ namespace API.Data.Migrations
|
|||||||
|
|
||||||
b.HasIndex("VolumeId");
|
b.HasIndex("VolumeId");
|
||||||
|
|
||||||
b.ToTable("Chapter");
|
b.ToTable("Chapter", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("API.Entities.CollectionTag", b =>
|
modelBuilder.Entity("API.Entities.CollectionTag", b =>
|
||||||
@ -448,7 +448,7 @@ namespace API.Data.Migrations
|
|||||||
b.HasIndex("Id", "Promoted")
|
b.HasIndex("Id", "Promoted")
|
||||||
.IsUnique();
|
.IsUnique();
|
||||||
|
|
||||||
b.ToTable("CollectionTag");
|
b.ToTable("CollectionTag", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("API.Entities.Device", b =>
|
modelBuilder.Entity("API.Entities.Device", b =>
|
||||||
@ -485,7 +485,7 @@ namespace API.Data.Migrations
|
|||||||
|
|
||||||
b.HasIndex("AppUserId");
|
b.HasIndex("AppUserId");
|
||||||
|
|
||||||
b.ToTable("Device");
|
b.ToTable("Device", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("API.Entities.FolderPath", b =>
|
modelBuilder.Entity("API.Entities.FolderPath", b =>
|
||||||
@ -507,7 +507,7 @@ namespace API.Data.Migrations
|
|||||||
|
|
||||||
b.HasIndex("LibraryId");
|
b.HasIndex("LibraryId");
|
||||||
|
|
||||||
b.ToTable("FolderPath");
|
b.ToTable("FolderPath", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("API.Entities.Genre", b =>
|
modelBuilder.Entity("API.Entities.Genre", b =>
|
||||||
@ -530,7 +530,7 @@ namespace API.Data.Migrations
|
|||||||
b.HasIndex("NormalizedTitle", "ExternalTag")
|
b.HasIndex("NormalizedTitle", "ExternalTag")
|
||||||
.IsUnique();
|
.IsUnique();
|
||||||
|
|
||||||
b.ToTable("Genre");
|
b.ToTable("Genre", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("API.Entities.Library", b =>
|
modelBuilder.Entity("API.Entities.Library", b =>
|
||||||
@ -559,7 +559,7 @@ namespace API.Data.Migrations
|
|||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
||||||
|
|
||||||
b.ToTable("Library");
|
b.ToTable("Library", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("API.Entities.MangaFile", b =>
|
modelBuilder.Entity("API.Entities.MangaFile", b =>
|
||||||
@ -593,7 +593,7 @@ namespace API.Data.Migrations
|
|||||||
|
|
||||||
b.HasIndex("ChapterId");
|
b.HasIndex("ChapterId");
|
||||||
|
|
||||||
b.ToTable("MangaFile");
|
b.ToTable("MangaFile", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("API.Entities.Metadata.SeriesMetadata", b =>
|
modelBuilder.Entity("API.Entities.Metadata.SeriesMetadata", b =>
|
||||||
@ -689,7 +689,7 @@ namespace API.Data.Migrations
|
|||||||
b.HasIndex("Id", "SeriesId")
|
b.HasIndex("Id", "SeriesId")
|
||||||
.IsUnique();
|
.IsUnique();
|
||||||
|
|
||||||
b.ToTable("SeriesMetadata");
|
b.ToTable("SeriesMetadata", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("API.Entities.Metadata.SeriesRelation", b =>
|
modelBuilder.Entity("API.Entities.Metadata.SeriesRelation", b =>
|
||||||
@ -713,7 +713,7 @@ namespace API.Data.Migrations
|
|||||||
|
|
||||||
b.HasIndex("TargetSeriesId");
|
b.HasIndex("TargetSeriesId");
|
||||||
|
|
||||||
b.ToTable("SeriesRelation");
|
b.ToTable("SeriesRelation", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("API.Entities.Person", b =>
|
modelBuilder.Entity("API.Entities.Person", b =>
|
||||||
@ -733,7 +733,7 @@ namespace API.Data.Migrations
|
|||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
||||||
|
|
||||||
b.ToTable("Person");
|
b.ToTable("Person", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("API.Entities.ReadingList", b =>
|
modelBuilder.Entity("API.Entities.ReadingList", b =>
|
||||||
@ -776,7 +776,7 @@ namespace API.Data.Migrations
|
|||||||
|
|
||||||
b.HasIndex("AppUserId");
|
b.HasIndex("AppUserId");
|
||||||
|
|
||||||
b.ToTable("ReadingList");
|
b.ToTable("ReadingList", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("API.Entities.ReadingListItem", b =>
|
modelBuilder.Entity("API.Entities.ReadingListItem", b =>
|
||||||
@ -810,7 +810,7 @@ namespace API.Data.Migrations
|
|||||||
|
|
||||||
b.HasIndex("VolumeId");
|
b.HasIndex("VolumeId");
|
||||||
|
|
||||||
b.ToTable("ReadingListItem");
|
b.ToTable("ReadingListItem", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("API.Entities.Series", b =>
|
modelBuilder.Entity("API.Entities.Series", b =>
|
||||||
@ -897,7 +897,7 @@ namespace API.Data.Migrations
|
|||||||
|
|
||||||
b.HasIndex("LibraryId");
|
b.HasIndex("LibraryId");
|
||||||
|
|
||||||
b.ToTable("Series");
|
b.ToTable("Series", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("API.Entities.ServerSetting", b =>
|
modelBuilder.Entity("API.Entities.ServerSetting", b =>
|
||||||
@ -914,7 +914,7 @@ namespace API.Data.Migrations
|
|||||||
|
|
||||||
b.HasKey("Key");
|
b.HasKey("Key");
|
||||||
|
|
||||||
b.ToTable("ServerSetting");
|
b.ToTable("ServerSetting", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("API.Entities.SiteTheme", b =>
|
modelBuilder.Entity("API.Entities.SiteTheme", b =>
|
||||||
@ -946,7 +946,7 @@ namespace API.Data.Migrations
|
|||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
||||||
|
|
||||||
b.ToTable("SiteTheme");
|
b.ToTable("SiteTheme", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("API.Entities.Tag", b =>
|
modelBuilder.Entity("API.Entities.Tag", b =>
|
||||||
@ -969,7 +969,7 @@ namespace API.Data.Migrations
|
|||||||
b.HasIndex("NormalizedTitle", "ExternalTag")
|
b.HasIndex("NormalizedTitle", "ExternalTag")
|
||||||
.IsUnique();
|
.IsUnique();
|
||||||
|
|
||||||
b.ToTable("Tag");
|
b.ToTable("Tag", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("API.Entities.Volume", b =>
|
modelBuilder.Entity("API.Entities.Volume", b =>
|
||||||
@ -1015,7 +1015,7 @@ namespace API.Data.Migrations
|
|||||||
|
|
||||||
b.HasIndex("SeriesId");
|
b.HasIndex("SeriesId");
|
||||||
|
|
||||||
b.ToTable("Volume");
|
b.ToTable("Volume", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("AppUserLibrary", b =>
|
modelBuilder.Entity("AppUserLibrary", b =>
|
||||||
@ -1030,7 +1030,7 @@ namespace API.Data.Migrations
|
|||||||
|
|
||||||
b.HasIndex("LibrariesId");
|
b.HasIndex("LibrariesId");
|
||||||
|
|
||||||
b.ToTable("AppUserLibrary");
|
b.ToTable("AppUserLibrary", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("ChapterGenre", b =>
|
modelBuilder.Entity("ChapterGenre", b =>
|
||||||
@ -1045,7 +1045,7 @@ namespace API.Data.Migrations
|
|||||||
|
|
||||||
b.HasIndex("GenresId");
|
b.HasIndex("GenresId");
|
||||||
|
|
||||||
b.ToTable("ChapterGenre");
|
b.ToTable("ChapterGenre", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("ChapterPerson", b =>
|
modelBuilder.Entity("ChapterPerson", b =>
|
||||||
@ -1060,7 +1060,7 @@ namespace API.Data.Migrations
|
|||||||
|
|
||||||
b.HasIndex("PeopleId");
|
b.HasIndex("PeopleId");
|
||||||
|
|
||||||
b.ToTable("ChapterPerson");
|
b.ToTable("ChapterPerson", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("ChapterTag", b =>
|
modelBuilder.Entity("ChapterTag", b =>
|
||||||
@ -1075,7 +1075,7 @@ namespace API.Data.Migrations
|
|||||||
|
|
||||||
b.HasIndex("TagsId");
|
b.HasIndex("TagsId");
|
||||||
|
|
||||||
b.ToTable("ChapterTag");
|
b.ToTable("ChapterTag", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("CollectionTagSeriesMetadata", b =>
|
modelBuilder.Entity("CollectionTagSeriesMetadata", b =>
|
||||||
@ -1090,7 +1090,7 @@ namespace API.Data.Migrations
|
|||||||
|
|
||||||
b.HasIndex("SeriesMetadatasId");
|
b.HasIndex("SeriesMetadatasId");
|
||||||
|
|
||||||
b.ToTable("CollectionTagSeriesMetadata");
|
b.ToTable("CollectionTagSeriesMetadata", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("GenreSeriesMetadata", b =>
|
modelBuilder.Entity("GenreSeriesMetadata", b =>
|
||||||
@ -1105,7 +1105,7 @@ namespace API.Data.Migrations
|
|||||||
|
|
||||||
b.HasIndex("SeriesMetadatasId");
|
b.HasIndex("SeriesMetadatasId");
|
||||||
|
|
||||||
b.ToTable("GenreSeriesMetadata");
|
b.ToTable("GenreSeriesMetadata", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<int>", b =>
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<int>", b =>
|
||||||
@ -1204,7 +1204,7 @@ namespace API.Data.Migrations
|
|||||||
|
|
||||||
b.HasIndex("SeriesMetadatasId");
|
b.HasIndex("SeriesMetadatasId");
|
||||||
|
|
||||||
b.ToTable("PersonSeriesMetadata");
|
b.ToTable("PersonSeriesMetadata", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("SeriesMetadataTag", b =>
|
modelBuilder.Entity("SeriesMetadataTag", b =>
|
||||||
@ -1219,7 +1219,7 @@ namespace API.Data.Migrations
|
|||||||
|
|
||||||
b.HasIndex("TagsId");
|
b.HasIndex("TagsId");
|
||||||
|
|
||||||
b.ToTable("SeriesMetadataTag");
|
b.ToTable("SeriesMetadataTag", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("API.Entities.AppUserBookmark", b =>
|
modelBuilder.Entity("API.Entities.AppUserBookmark", b =>
|
||||||
|
@ -33,7 +33,7 @@ public interface ILibraryRepository
|
|||||||
void Delete(Library library);
|
void Delete(Library library);
|
||||||
Task<IEnumerable<LibraryDto>> GetLibraryDtosAsync();
|
Task<IEnumerable<LibraryDto>> GetLibraryDtosAsync();
|
||||||
Task<bool> LibraryExists(string libraryName);
|
Task<bool> LibraryExists(string libraryName);
|
||||||
Task<Library> GetLibraryForIdAsync(int libraryId, LibraryIncludes includes);
|
Task<Library> GetLibraryForIdAsync(int libraryId, LibraryIncludes includes = LibraryIncludes.None);
|
||||||
Task<IEnumerable<LibraryDto>> GetLibraryDtosForUsernameAsync(string userName);
|
Task<IEnumerable<LibraryDto>> GetLibraryDtosForUsernameAsync(string userName);
|
||||||
Task<IEnumerable<Library>> GetLibrariesAsync(LibraryIncludes includes = LibraryIncludes.None);
|
Task<IEnumerable<Library>> GetLibrariesAsync(LibraryIncludes includes = LibraryIncludes.None);
|
||||||
Task<bool> DeleteLibrary(int libraryId);
|
Task<bool> DeleteLibrary(int libraryId);
|
||||||
@ -203,14 +203,14 @@ public class LibraryRepository : ILibraryRepository
|
|||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Library> GetLibraryForIdAsync(int libraryId, LibraryIncludes includes)
|
public async Task<Library> GetLibraryForIdAsync(int libraryId, LibraryIncludes includes = LibraryIncludes.None)
|
||||||
{
|
{
|
||||||
|
|
||||||
var query = _context.Library
|
var query = _context.Library
|
||||||
.Where(x => x.Id == libraryId);
|
.Where(x => x.Id == libraryId);
|
||||||
|
|
||||||
query = AddIncludesToQuery(query, includes);
|
query = AddIncludesToQuery(query, includes);
|
||||||
return await query.SingleAsync();
|
return await query.SingleOrDefaultAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IQueryable<Library> AddIncludesToQuery(IQueryable<Library> query, LibraryIncludes includeFlags)
|
private static IQueryable<Library> AddIncludesToQuery(IQueryable<Library> query, LibraryIncludes includeFlags)
|
||||||
|
@ -63,9 +63,8 @@ public interface ISeriesRepository
|
|||||||
/// <param name="searchQuery"></param>
|
/// <param name="searchQuery"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<SearchResultGroupDto> SearchSeries(int userId, bool isAdmin, int[] libraryIds, string searchQuery);
|
Task<SearchResultGroupDto> SearchSeries(int userId, bool isAdmin, int[] libraryIds, string searchQuery);
|
||||||
Task<IEnumerable<Series>> GetSeriesForLibraryIdAsync(int libraryId);
|
Task<IEnumerable<Series>> GetSeriesForLibraryIdAsync(int libraryId, SeriesIncludes includes = SeriesIncludes.None);
|
||||||
Task<SeriesDto> GetSeriesDtoByIdAsync(int seriesId, int userId);
|
Task<SeriesDto> GetSeriesDtoByIdAsync(int seriesId, int userId);
|
||||||
Task<bool> DeleteSeriesAsync(int seriesId);
|
|
||||||
Task<Series> GetSeriesByIdAsync(int seriesId, SeriesIncludes includes = SeriesIncludes.Volumes | SeriesIncludes.Metadata);
|
Task<Series> GetSeriesByIdAsync(int seriesId, SeriesIncludes includes = SeriesIncludes.Volumes | SeriesIncludes.Metadata);
|
||||||
Task<IList<Series>> GetSeriesByIdsAsync(IList<int> seriesIds);
|
Task<IList<Series>> GetSeriesByIdsAsync(IList<int> seriesIds);
|
||||||
Task<int[]> GetChapterIdsForSeriesAsync(IList<int> seriesIds);
|
Task<int[]> GetChapterIdsForSeriesAsync(IList<int> seriesIds);
|
||||||
@ -160,12 +159,14 @@ public class SeriesRepository : ISeriesRepository
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public async Task<IEnumerable<Series>> GetSeriesForLibraryIdAsync(int libraryId)
|
public async Task<IEnumerable<Series>> GetSeriesForLibraryIdAsync(int libraryId, SeriesIncludes includes = SeriesIncludes.None)
|
||||||
{
|
{
|
||||||
return await _context.Series
|
var query = _context.Series
|
||||||
.Where(s => s.LibraryId == libraryId)
|
.Where(s => s.LibraryId == libraryId);
|
||||||
.OrderBy(s => s.SortName)
|
|
||||||
.ToListAsync();
|
query = AddIncludesToQuery(query, includes);
|
||||||
|
|
||||||
|
return await query.OrderBy(s => s.SortName).ToListAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -418,15 +419,6 @@ public class SeriesRepository : ISeriesRepository
|
|||||||
return seriesList[0];
|
return seriesList[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> DeleteSeriesAsync(int seriesId)
|
|
||||||
{
|
|
||||||
var series = await _context.Series.Where(s => s.Id == seriesId).SingleOrDefaultAsync();
|
|
||||||
if (series != null) _context.Series.Remove(series);
|
|
||||||
|
|
||||||
return await _context.SaveChangesAsync() > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns Volumes, Metadata (Incl Genres and People), and Collection Tags
|
/// Returns Volumes, Metadata (Incl Genres and People), and Collection Tags
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -439,29 +431,7 @@ public class SeriesRepository : ISeriesRepository
|
|||||||
.Where(s => s.Id == seriesId)
|
.Where(s => s.Id == seriesId)
|
||||||
.AsSplitQuery();
|
.AsSplitQuery();
|
||||||
|
|
||||||
if (includes.HasFlag(SeriesIncludes.Volumes))
|
query = AddIncludesToQuery(query, includes);
|
||||||
{
|
|
||||||
query = query.Include(s => s.Volumes);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (includes.HasFlag(SeriesIncludes.Related))
|
|
||||||
{
|
|
||||||
query = query.Include(s => s.Relations)
|
|
||||||
.ThenInclude(r => r.TargetSeries)
|
|
||||||
.Include(s => s.RelationOf);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (includes.HasFlag(SeriesIncludes.Metadata))
|
|
||||||
{
|
|
||||||
query = query.Include(s => s.Metadata)
|
|
||||||
.ThenInclude(m => m.CollectionTags)
|
|
||||||
.Include(s => s.Metadata)
|
|
||||||
.ThenInclude(m => m.Genres)
|
|
||||||
.Include(s => s.Metadata)
|
|
||||||
.ThenInclude(m => m.People)
|
|
||||||
.Include(s => s.Metadata)
|
|
||||||
.ThenInclude(m => m.Tags);
|
|
||||||
}
|
|
||||||
|
|
||||||
return await query.SingleOrDefaultAsync();
|
return await query.SingleOrDefaultAsync();
|
||||||
}
|
}
|
||||||
@ -1561,27 +1531,37 @@ public class SeriesRepository : ISeriesRepository
|
|||||||
|
|
||||||
private static IQueryable<Series> AddIncludesToQuery(IQueryable<Series> query, SeriesIncludes includeFlags)
|
private static IQueryable<Series> AddIncludesToQuery(IQueryable<Series> query, SeriesIncludes includeFlags)
|
||||||
{
|
{
|
||||||
|
// TODO: Move this to an Extension Method
|
||||||
if (includeFlags.HasFlag(SeriesIncludes.Library))
|
if (includeFlags.HasFlag(SeriesIncludes.Library))
|
||||||
{
|
{
|
||||||
query = query.Include(u => u.Library);
|
query = query.Include(u => u.Library);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (includeFlags.HasFlag(SeriesIncludes.Volumes))
|
||||||
|
{
|
||||||
|
query = query.Include(s => s.Volumes);
|
||||||
|
}
|
||||||
|
|
||||||
if (includeFlags.HasFlag(SeriesIncludes.Related))
|
if (includeFlags.HasFlag(SeriesIncludes.Related))
|
||||||
{
|
{
|
||||||
query = query.Include(u => u.Relations);
|
query = query.Include(s => s.Relations)
|
||||||
|
.ThenInclude(r => r.TargetSeries)
|
||||||
|
.Include(s => s.RelationOf);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (includeFlags.HasFlag(SeriesIncludes.Metadata))
|
if (includeFlags.HasFlag(SeriesIncludes.Metadata))
|
||||||
{
|
{
|
||||||
query = query.Include(u => u.Metadata);
|
query = query.Include(s => s.Metadata)
|
||||||
}
|
.ThenInclude(m => m.CollectionTags)
|
||||||
|
.Include(s => s.Metadata)
|
||||||
if (includeFlags.HasFlag(SeriesIncludes.Volumes))
|
.ThenInclude(m => m.Genres)
|
||||||
{
|
.Include(s => s.Metadata)
|
||||||
query = query.Include(u => u.Volumes);
|
.ThenInclude(m => m.People)
|
||||||
|
.Include(s => s.Metadata)
|
||||||
|
.ThenInclude(m => m.Tags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return query;
|
return query.AsSplitQuery();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,16 +27,4 @@ public class Library : IEntityDate
|
|||||||
public ICollection<FolderPath> Folders { get; set; }
|
public ICollection<FolderPath> Folders { get; set; }
|
||||||
public ICollection<AppUser> AppUsers { get; set; }
|
public ICollection<AppUser> AppUsers { get; set; }
|
||||||
public ICollection<Series> Series { get; set; }
|
public ICollection<Series> Series { get; set; }
|
||||||
|
|
||||||
// Methods
|
|
||||||
/// <summary>
|
|
||||||
/// Has there been any modifications to the FolderPath's directory since the <see cref="FolderPath.LastScanned"/> date
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
public bool AnyModificationsSinceLastScan()
|
|
||||||
{
|
|
||||||
// NOTE: I don't think we can do this due to NTFS
|
|
||||||
return Folders.All(folder => File.GetLastWriteTimeUtc(folder.Path) > folder.LastScanned);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,12 @@ export class CardActionablesComponent implements OnInit {
|
|||||||
if (!user) return;
|
if (!user) return;
|
||||||
this.isAdmin = this.accountService.hasAdminRole(user);
|
this.isAdmin = this.accountService.hasAdminRole(user);
|
||||||
this.canDownload = this.accountService.hasDownloadRole(user);
|
this.canDownload = this.accountService.hasDownloadRole(user);
|
||||||
|
|
||||||
|
// We want to avoid an empty menu when user doesn't have access to anything
|
||||||
|
const validActions = this.actions.filter(a => a.children.length > 0 || a.dynamicList);
|
||||||
|
if (!this.isAdmin && validActions.filter(a => !a.requiresAdmin).length === 0) {
|
||||||
|
this.actions = [];
|
||||||
|
}
|
||||||
this.cdRef.markForCheck();
|
this.cdRef.markForCheck();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -56,6 +56,11 @@ export class RestrictionSelectorComponent implements OnInit, OnChanges {
|
|||||||
ageRating: parseInt(e, 10),
|
ageRating: parseInt(e, 10),
|
||||||
includeUnknowns: this.restrictionForm?.get('ageRestrictionIncludeUnknowns')?.value
|
includeUnknowns: this.restrictionForm?.get('ageRestrictionIncludeUnknowns')?.value
|
||||||
});
|
});
|
||||||
|
if (parseInt(e, 10) === AgeRating.NotApplicable) {
|
||||||
|
this.restrictionForm!.get('ageRestrictionIncludeUnknowns')?.disable();
|
||||||
|
} else {
|
||||||
|
this.restrictionForm!.get('ageRestrictionIncludeUnknowns')?.enable();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.restrictionForm.get('ageRestrictionIncludeUnknowns')?.valueChanges.subscribe(e => {
|
this.restrictionForm.get('ageRestrictionIncludeUnknowns')?.valueChanges.subscribe(e => {
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
<link rel="shortcut icon" href="assets/icons/favicon.ico">
|
<link rel="shortcut icon" href="assets/icons/favicon.ico">
|
||||||
<meta name="msapplication-TileColor" content="#4ac694">
|
<meta name="msapplication-TileColor" content="#4ac694">
|
||||||
<meta name="msapplication-config" content="assets/icons/browserconfig.xml">
|
<meta name="msapplication-config" content="assets/icons/browserconfig.xml">
|
||||||
<meta name="theme-color" content="#ffffff">
|
<meta name="theme-color" content="#000000">
|
||||||
<meta name="apple-mobile-web-app-status-bar-style" content="black">
|
<meta name="apple-mobile-web-app-status-bar-style" content="black">
|
||||||
|
|
||||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||||
|
Loading…
x
Reference in New Issue
Block a user