mirror of
https://github.com/Kareadita/Kavita.git
synced 2025-08-11 09:13:42 -04:00
Polish Round 4 (#2429)
This commit is contained in:
parent
cd7f876140
commit
ee72727841
@ -19,3 +19,6 @@ trim_trailing_whitespace = false
|
|||||||
|
|
||||||
[*.yml]
|
[*.yml]
|
||||||
indent_size = 2
|
indent_size = 2
|
||||||
|
|
||||||
|
[*.csproj]
|
||||||
|
indent_size = 2
|
||||||
|
@ -62,7 +62,7 @@ public class DefaultParserTests
|
|||||||
[Theory]
|
[Theory]
|
||||||
[InlineData("/manga/Btooom!/Vol.1/Chapter 1/1.cbz", "Btooom!")]
|
[InlineData("/manga/Btooom!/Vol.1/Chapter 1/1.cbz", "Btooom!")]
|
||||||
[InlineData("/manga/Btooom!/Vol.1 Chapter 2/1.cbz", "Btooom!")]
|
[InlineData("/manga/Btooom!/Vol.1 Chapter 2/1.cbz", "Btooom!")]
|
||||||
[InlineData("/manga/Monster #8 (Digital)/Ch. 001-016 [MangaPlus] [Digital] [amit34521]/Monster #8 Ch. 001 [MangaPlus] [Digital] [amit34521]/13.jpg", "Monster")]
|
[InlineData("/manga/Monster #8 (Digital)/Ch. 001-016 [MangaPlus] [Digital] [amit34521]/Monster #8 Ch. 001 [MangaPlus] [Digital] [amit34521]/13.jpg", "manga")]
|
||||||
[InlineData("/manga/Monster (Digital)/Ch. 001-016 [MangaPlus] [Digital] [amit34521]/Monster Ch. 001 [MangaPlus] [Digital] [amit34521]/13.jpg", "Monster")]
|
[InlineData("/manga/Monster (Digital)/Ch. 001-016 [MangaPlus] [Digital] [amit34521]/Monster Ch. 001 [MangaPlus] [Digital] [amit34521]/13.jpg", "Monster")]
|
||||||
[InlineData("/manga/Foo 50/Specials/Foo 50 SP01.cbz", "Foo 50")]
|
[InlineData("/manga/Foo 50/Specials/Foo 50 SP01.cbz", "Foo 50")]
|
||||||
[InlineData("/manga/Foo 50 (kiraa)/Specials/Foo 50 SP01.cbz", "Foo 50")]
|
[InlineData("/manga/Foo 50 (kiraa)/Specials/Foo 50 SP01.cbz", "Foo 50")]
|
||||||
@ -293,7 +293,7 @@ public class DefaultParserTests
|
|||||||
var expectedInfo2 = new ParserInfo
|
var expectedInfo2 = new ParserInfo
|
||||||
{
|
{
|
||||||
Series = "Monster #8", Volumes = "0", Edition = "",
|
Series = "Monster #8", Volumes = "0", Edition = "",
|
||||||
Chapters = "1", Filename = "13.jpg", Format = MangaFormat.Image,
|
Chapters = "8", Filename = "13.jpg", Format = MangaFormat.Image,
|
||||||
FullFilePath = filepath, IsSpecial = false
|
FullFilePath = filepath, IsSpecial = false
|
||||||
};
|
};
|
||||||
var actual2 = _defaultParser.Parse(filepath, @"E:\Manga\Monster #8");
|
var actual2 = _defaultParser.Parse(filepath, @"E:\Manga\Monster #8");
|
||||||
@ -314,7 +314,7 @@ public class DefaultParserTests
|
|||||||
Assert.Equal(expectedInfo2.FullFilePath, actual2.FullFilePath);
|
Assert.Equal(expectedInfo2.FullFilePath, actual2.FullFilePath);
|
||||||
_testOutputHelper.WriteLine("FullFilePath ✓");
|
_testOutputHelper.WriteLine("FullFilePath ✓");
|
||||||
|
|
||||||
filepath = @"E:\Manga\Extra layer for no reason\Just Images the second\Vol19\ch186\Vol. 19 p106.gif";
|
filepath = @"E:\Manga\Extra layer for no reason\Just Images the second\Vol19\ch. 186\Vol. 19 p106.gif";
|
||||||
expectedInfo2 = new ParserInfo
|
expectedInfo2 = new ParserInfo
|
||||||
{
|
{
|
||||||
Series = "Just Images the second", Volumes = "19", Edition = "",
|
Series = "Just Images the second", Volumes = "19", Edition = "",
|
||||||
@ -340,7 +340,7 @@ public class DefaultParserTests
|
|||||||
Assert.Equal(expectedInfo2.FullFilePath, actual2.FullFilePath);
|
Assert.Equal(expectedInfo2.FullFilePath, actual2.FullFilePath);
|
||||||
_testOutputHelper.WriteLine("FullFilePath ✓");
|
_testOutputHelper.WriteLine("FullFilePath ✓");
|
||||||
|
|
||||||
filepath = @"E:\Manga\Extra layer for no reason\Just Images the second\Blank Folder\Vol19\ch186\Vol. 19 p106.gif";
|
filepath = @"E:\Manga\Extra layer for no reason\Just Images the second\Blank Folder\Vol19\ch. 186\Vol. 19 p106.gif";
|
||||||
expectedInfo2 = new ParserInfo
|
expectedInfo2 = new ParserInfo
|
||||||
{
|
{
|
||||||
Series = "Just Images the second", Volumes = "19", Edition = "",
|
Series = "Just Images the second", Volumes = "19", Edition = "",
|
||||||
|
@ -657,7 +657,7 @@ public class SeriesServiceTests : AbstractDbTest
|
|||||||
{
|
{
|
||||||
SeriesId = 1,
|
SeriesId = 1,
|
||||||
Publishers = new List<PersonDto>() {new () {Id = 0, Name = "Existing Person", Role = PersonRole.Publisher}},
|
Publishers = new List<PersonDto>() {new () {Id = 0, Name = "Existing Person", Role = PersonRole.Publisher}},
|
||||||
PublishersLocked = true
|
PublisherLocked = true
|
||||||
},
|
},
|
||||||
CollectionTags = new List<CollectionTagDto>()
|
CollectionTags = new List<CollectionTagDto>()
|
||||||
});
|
});
|
||||||
|
@ -53,6 +53,10 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.13">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="12.0.1" />
|
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="12.0.1" />
|
||||||
<PackageReference Include="Docnet.Core" Version="2.6.0" />
|
<PackageReference Include="Docnet.Core" Version="2.6.0" />
|
||||||
<PackageReference Include="EasyCaching.InMemory" Version="1.9.2" />
|
<PackageReference Include="EasyCaching.InMemory" Version="1.9.2" />
|
||||||
@ -60,28 +64,15 @@
|
|||||||
<PackageReference Include="Flurl" Version="3.0.7" />
|
<PackageReference Include="Flurl" Version="3.0.7" />
|
||||||
<PackageReference Include="Flurl.Http" Version="3.2.4" />
|
<PackageReference Include="Flurl.Http" Version="3.2.4" />
|
||||||
<PackageReference Include="Hangfire" Version="1.8.6" />
|
<PackageReference Include="Hangfire" Version="1.8.6" />
|
||||||
<PackageReference Include="Hangfire.AspNetCore" Version="1.8.6" />
|
|
||||||
<PackageReference Include="Hangfire.InMemory" Version="0.6.0" />
|
<PackageReference Include="Hangfire.InMemory" Version="0.6.0" />
|
||||||
<PackageReference Include="Hangfire.MaximumConcurrentExecutions" Version="1.1.0" />
|
<PackageReference Include="Hangfire.MaximumConcurrentExecutions" Version="1.1.0" />
|
||||||
<PackageReference Include="Hangfire.MemoryStorage.Core" Version="1.4.0" />
|
<PackageReference Include="Hangfire.MemoryStorage.Core" Version="1.4.0" />
|
||||||
<PackageReference Include="Hangfire.Storage.SQLite" Version="0.3.4" />
|
<PackageReference Include="Hangfire.Storage.SQLite" Version="0.3.4" />
|
||||||
<PackageReference Include="HtmlAgilityPack" Version="1.11.54" />
|
<PackageReference Include="HtmlAgilityPack" Version="1.11.54" />
|
||||||
<PackageReference Include="MarkdownDeep.NET.Core" Version="1.5.0.4" />
|
<PackageReference Include="MarkdownDeep.NET.Core" Version="1.5.0.4" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="7.0.13" />
|
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="7.0.13" />
|
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="7.0.13" />
|
|
||||||
<PackageReference Include="Microsoft.AspNetCore.SignalR" Version="1.1.0" />
|
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.13">
|
|
||||||
<PrivateAssets>all</PrivateAssets>
|
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
|
||||||
</PackageReference>
|
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="7.0.13" />
|
|
||||||
<PackageReference Include="EasyCaching.InMemory" Version="1.9.2" />
|
|
||||||
<PackageReference Include="ExCSS" Version="4.2.4" />
|
|
||||||
<PackageReference Include="Hangfire" Version="1.8.6" />
|
|
||||||
<PackageReference Include="Hangfire.AspNetCore" Version="1.8.6" />
|
<PackageReference Include="Hangfire.AspNetCore" Version="1.8.6" />
|
||||||
<PackageReference Include="Hangfire.InMemory" Version="0.6.0" />
|
<PackageReference Include="Microsoft.AspNetCore.SignalR" Version="1.1.0" />
|
||||||
<PackageReference Include="HtmlAgilityPack" Version="1.11.54" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="7.0.13" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="7.0.13" />
|
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="7.0.13" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="7.0.13" />
|
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="7.0.13" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="7.0.13" />
|
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="7.0.13" />
|
||||||
|
@ -437,8 +437,7 @@ public class SeriesController : BaseApiController
|
|||||||
[HttpGet("metadata")]
|
[HttpGet("metadata")]
|
||||||
public async Task<ActionResult<SeriesMetadataDto>> GetSeriesMetadata(int seriesId)
|
public async Task<ActionResult<SeriesMetadataDto>> GetSeriesMetadata(int seriesId)
|
||||||
{
|
{
|
||||||
var metadata = await _unitOfWork.SeriesRepository.GetSeriesMetadata(seriesId);
|
return Ok(await _unitOfWork.SeriesRepository.GetSeriesMetadata(seriesId));
|
||||||
return Ok(metadata);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -75,16 +75,16 @@ public class SeriesMetadataDto
|
|||||||
public bool PublicationStatusLocked { get; set; }
|
public bool PublicationStatusLocked { get; set; }
|
||||||
public bool GenresLocked { get; set; }
|
public bool GenresLocked { get; set; }
|
||||||
public bool TagsLocked { get; set; }
|
public bool TagsLocked { get; set; }
|
||||||
public bool WritersLocked { get; set; }
|
public bool WriterLocked { get; set; }
|
||||||
public bool CharactersLocked { get; set; }
|
public bool CharacterLocked { get; set; }
|
||||||
public bool ColoristsLocked { get; set; }
|
public bool ColoristLocked { get; set; }
|
||||||
public bool EditorsLocked { get; set; }
|
public bool EditorLocked { get; set; }
|
||||||
public bool InkersLocked { get; set; }
|
public bool InkerLocked { get; set; }
|
||||||
public bool LetterersLocked { get; set; }
|
public bool LettererLocked { get; set; }
|
||||||
public bool PencillersLocked { get; set; }
|
public bool PencillerLocked { get; set; }
|
||||||
public bool PublishersLocked { get; set; }
|
public bool PublisherLocked { get; set; }
|
||||||
public bool TranslatorsLocked { get; set; }
|
public bool TranslatorLocked { get; set; }
|
||||||
public bool CoverArtistsLocked { get; set; }
|
public bool CoverArtistLocked { get; set; }
|
||||||
public bool ReleaseYearLocked { get; set; }
|
public bool ReleaseYearLocked { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
@ -73,12 +73,14 @@ public class AccountService : IAccountService
|
|||||||
basePart = serverSettings.HostName;
|
basePart = serverSettings.HostName;
|
||||||
if (!serverSettings.BaseUrl.Equals(Configuration.DefaultBaseUrl))
|
if (!serverSettings.BaseUrl.Equals(Configuration.DefaultBaseUrl))
|
||||||
{
|
{
|
||||||
basePart += serverSettings.BaseUrl.Substring(0, serverSettings.BaseUrl.Length - 1);
|
var removeCount = serverSettings.BaseUrl.EndsWith("/") ? 2 : 1;
|
||||||
|
basePart += serverSettings.BaseUrl.Substring(0, serverSettings.BaseUrl.Length - removeCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (withHost) return $"{basePart}/registration/{routePart}?token={HttpUtility.UrlEncode(token)}&email={HttpUtility.UrlEncode(email)}".Replace("//", "/");
|
if (withHost) return $"{basePart}/registration/{routePart}?token={HttpUtility.UrlEncode(token)}&email={HttpUtility.UrlEncode(email)}";
|
||||||
return $"registration/{routePart}?token={HttpUtility.UrlEncode(token)}&email={HttpUtility.UrlEncode(email)}".Replace("//", "/");
|
return $"registration/{routePart}?token={HttpUtility.UrlEncode(token)}&email={HttpUtility.UrlEncode(email)}"
|
||||||
|
.Replace("//", "/");
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<IEnumerable<ApiException>> ChangeUserPassword(AppUser user, string newPassword)
|
public async Task<IEnumerable<ApiException>> ChangeUserPassword(AppUser user, string newPassword)
|
||||||
|
@ -107,6 +107,7 @@ public class SeriesService : ISeriesService
|
|||||||
var series = await _unitOfWork.SeriesRepository.GetSeriesByIdAsync(seriesId);
|
var series = await _unitOfWork.SeriesRepository.GetSeriesByIdAsync(seriesId);
|
||||||
if (series == null) return false;
|
if (series == null) return false;
|
||||||
var allCollectionTags = (await _unitOfWork.CollectionTagRepository.GetAllTagsAsync()).ToList();
|
var allCollectionTags = (await _unitOfWork.CollectionTagRepository.GetAllTagsAsync()).ToList();
|
||||||
|
// TODO: This is Diesel's performance problem with Komf. For some systems, this is too heavy of a call if komf is spamming updates.
|
||||||
var allGenres = (await _unitOfWork.GenreRepository.GetAllGenresAsync()).ToList();
|
var allGenres = (await _unitOfWork.GenreRepository.GetAllGenresAsync()).ToList();
|
||||||
var allPeople = (await _unitOfWork.PersonRepository.GetAllPeople()).ToList();
|
var allPeople = (await _unitOfWork.PersonRepository.GetAllPeople()).ToList();
|
||||||
var allTags = (await _unitOfWork.TagRepository.GetAllTagsAsync()).ToList();
|
var allTags = (await _unitOfWork.TagRepository.GetAllTagsAsync()).ToList();
|
||||||
@ -219,16 +220,16 @@ public class SeriesService : ISeriesService
|
|||||||
series.Metadata.LanguageLocked = updateSeriesMetadataDto.SeriesMetadata.LanguageLocked;
|
series.Metadata.LanguageLocked = updateSeriesMetadataDto.SeriesMetadata.LanguageLocked;
|
||||||
series.Metadata.GenresLocked = updateSeriesMetadataDto.SeriesMetadata.GenresLocked;
|
series.Metadata.GenresLocked = updateSeriesMetadataDto.SeriesMetadata.GenresLocked;
|
||||||
series.Metadata.TagsLocked = updateSeriesMetadataDto.SeriesMetadata.TagsLocked;
|
series.Metadata.TagsLocked = updateSeriesMetadataDto.SeriesMetadata.TagsLocked;
|
||||||
series.Metadata.CharacterLocked = updateSeriesMetadataDto.SeriesMetadata.CharactersLocked;
|
series.Metadata.CharacterLocked = updateSeriesMetadataDto.SeriesMetadata.CharacterLocked;
|
||||||
series.Metadata.ColoristLocked = updateSeriesMetadataDto.SeriesMetadata.ColoristsLocked;
|
series.Metadata.ColoristLocked = updateSeriesMetadataDto.SeriesMetadata.ColoristLocked;
|
||||||
series.Metadata.EditorLocked = updateSeriesMetadataDto.SeriesMetadata.EditorsLocked;
|
series.Metadata.EditorLocked = updateSeriesMetadataDto.SeriesMetadata.EditorLocked;
|
||||||
series.Metadata.InkerLocked = updateSeriesMetadataDto.SeriesMetadata.InkersLocked;
|
series.Metadata.InkerLocked = updateSeriesMetadataDto.SeriesMetadata.InkerLocked;
|
||||||
series.Metadata.LettererLocked = updateSeriesMetadataDto.SeriesMetadata.LetterersLocked;
|
series.Metadata.LettererLocked = updateSeriesMetadataDto.SeriesMetadata.LettererLocked;
|
||||||
series.Metadata.PencillerLocked = updateSeriesMetadataDto.SeriesMetadata.PencillersLocked;
|
series.Metadata.PencillerLocked = updateSeriesMetadataDto.SeriesMetadata.PencillerLocked;
|
||||||
series.Metadata.PublisherLocked = updateSeriesMetadataDto.SeriesMetadata.PublishersLocked;
|
series.Metadata.PublisherLocked = updateSeriesMetadataDto.SeriesMetadata.PublisherLocked;
|
||||||
series.Metadata.TranslatorLocked = updateSeriesMetadataDto.SeriesMetadata.TranslatorsLocked;
|
series.Metadata.TranslatorLocked = updateSeriesMetadataDto.SeriesMetadata.TranslatorLocked;
|
||||||
series.Metadata.CoverArtistLocked = updateSeriesMetadataDto.SeriesMetadata.CoverArtistsLocked;
|
series.Metadata.CoverArtistLocked = updateSeriesMetadataDto.SeriesMetadata.CoverArtistLocked;
|
||||||
series.Metadata.WriterLocked = updateSeriesMetadataDto.SeriesMetadata.WritersLocked;
|
series.Metadata.WriterLocked = updateSeriesMetadataDto.SeriesMetadata.WriterLocked;
|
||||||
series.Metadata.SummaryLocked = updateSeriesMetadataDto.SeriesMetadata.SummaryLocked;
|
series.Metadata.SummaryLocked = updateSeriesMetadataDto.SeriesMetadata.SummaryLocked;
|
||||||
series.Metadata.ReleaseYearLocked = updateSeriesMetadataDto.SeriesMetadata.ReleaseYearLocked;
|
series.Metadata.ReleaseYearLocked = updateSeriesMetadataDto.SeriesMetadata.ReleaseYearLocked;
|
||||||
|
|
||||||
|
@ -119,19 +119,46 @@ public class DefaultParser : IDefaultParser
|
|||||||
{
|
{
|
||||||
ret.Volumes = Parser.DefaultVolume;
|
ret.Volumes = Parser.DefaultVolume;
|
||||||
ret.Chapters = Parser.DefaultChapter;
|
ret.Chapters = Parser.DefaultChapter;
|
||||||
// Next we need to see if the image has a folder between rootPath and filePath.
|
var directoryName = _directoryService.FileSystem.DirectoryInfo.New(rootPath).Name;
|
||||||
// if so, take that folder as a volume 0 chapter 0 special and group everything under there (if we can't parse a volume/chapter)
|
ret.Series = directoryName;
|
||||||
|
|
||||||
ParseFromFallbackFolders(filePath, rootPath, LibraryType.Image, ref ret);
|
ParseFromFallbackFolders(filePath, rootPath, LibraryType.Image, ref ret);
|
||||||
if ((string.IsNullOrEmpty(ret.Chapters) || ret.Chapters == Parser.DefaultChapter) &&
|
|
||||||
(string.IsNullOrEmpty(ret.Volumes) || ret.Volumes == Parser.DefaultVolume))
|
|
||||||
|
if (IsEmptyOrDefault(ret.Volumes, ret.Chapters))
|
||||||
{
|
{
|
||||||
ret.IsSpecial = true;
|
ret.IsSpecial = true;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var parsedVolume = Parser.ParseVolume(ret.Filename);
|
||||||
|
var parsedChapter = Parser.ParseChapter(ret.Filename);
|
||||||
|
if (IsEmptyOrDefault(ret.Volumes, string.Empty) && !parsedVolume.Equals(Parser.DefaultVolume))
|
||||||
|
{
|
||||||
|
ret.Volumes = parsedVolume;
|
||||||
|
}
|
||||||
|
if (IsEmptyOrDefault(string.Empty, ret.Chapters) && !parsedChapter.Equals(Parser.DefaultChapter))
|
||||||
|
{
|
||||||
|
ret.Chapters = parsedChapter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Override the series name, as fallback folders needs it to try and parse folder name
|
||||||
|
if (string.IsNullOrEmpty(ret.Series) || ret.Series.Equals(directoryName))
|
||||||
|
{
|
||||||
|
ret.Series = Parser.CleanTitle(directoryName, replaceSpecials: false);
|
||||||
|
}
|
||||||
|
|
||||||
ret.Series = _directoryService.FileSystem.DirectoryInfo.New(rootPath).Name;
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static bool IsEmptyOrDefault(string volumes, string chapters)
|
||||||
|
{
|
||||||
|
return (string.IsNullOrEmpty(chapters) || chapters == Parser.DefaultChapter) &&
|
||||||
|
(string.IsNullOrEmpty(volumes) || volumes == Parser.DefaultVolume);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Fills out <see cref="ParserInfo"/> by trying to parse volume, chapters, and series from folders
|
/// Fills out <see cref="ParserInfo"/> by trying to parse volume, chapters, and series from folders
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -193,7 +220,7 @@ public class DefaultParser : IDefaultParser
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(series) && (string.IsNullOrEmpty(ret.Series) || !folder.Contains(ret.Series)))
|
if (!string.IsNullOrEmpty(series) && (string.IsNullOrEmpty(ret.Series) && !folder.Contains(ret.Series)))
|
||||||
{
|
{
|
||||||
ret.Series = series;
|
ret.Series = series;
|
||||||
break;
|
break;
|
||||||
|
@ -843,13 +843,15 @@ public static class Parser
|
|||||||
/// <param name="isComic"></param>
|
/// <param name="isComic"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
|
|
||||||
public static string CleanTitle(string title, bool isComic = false)
|
public static string CleanTitle(string title, bool isComic = false, bool replaceSpecials = true)
|
||||||
{
|
{
|
||||||
|
|
||||||
title = ReplaceUnderscores(title);
|
title = ReplaceUnderscores(title);
|
||||||
|
|
||||||
title = RemoveEditionTagHolders(title);
|
title = RemoveEditionTagHolders(title);
|
||||||
|
|
||||||
|
if (replaceSpecials)
|
||||||
|
{
|
||||||
if (isComic)
|
if (isComic)
|
||||||
{
|
{
|
||||||
title = RemoveComicSpecialTags(title);
|
title = RemoveComicSpecialTags(title);
|
||||||
@ -859,6 +861,8 @@ public static class Parser
|
|||||||
{
|
{
|
||||||
title = RemoveMangaSpecialTags(title);
|
title = RemoveMangaSpecialTags(title);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
title = title.Trim(SpacesAndSeparators);
|
title = title.Trim(SpacesAndSeparators);
|
||||||
|
|
||||||
|
@ -293,6 +293,9 @@ public class ProcessSeries : IProcessSeries
|
|||||||
|
|
||||||
|
|
||||||
if ((maxChapter == 0 || maxChapter > series.Metadata.TotalCount) && maxVolume <= series.Metadata.TotalCount)
|
if ((maxChapter == 0 || maxChapter > series.Metadata.TotalCount) && maxVolume <= series.Metadata.TotalCount)
|
||||||
|
{
|
||||||
|
series.Metadata.MaxCount = maxVolume;
|
||||||
|
} else if (maxVolume == series.Metadata.TotalCount)
|
||||||
{
|
{
|
||||||
series.Metadata.MaxCount = maxVolume;
|
series.Metadata.MaxCount = maxVolume;
|
||||||
}
|
}
|
||||||
|
170
UI/Web/package-lock.json
generated
170
UI/Web/package-lock.json
generated
@ -8,16 +8,16 @@
|
|||||||
"name": "kavita-webui",
|
"name": "kavita-webui",
|
||||||
"version": "0.4.2",
|
"version": "0.4.2",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@angular/animations": "^17.0.1",
|
"@angular/animations": "^17.0.2",
|
||||||
"@angular/cdk": "^17.0.0",
|
"@angular/cdk": "^17.0.0",
|
||||||
"@angular/common": "^17.0.1",
|
"@angular/common": "^17.0.2",
|
||||||
"@angular/compiler": "^17.0.1",
|
"@angular/compiler": "^17.0.2",
|
||||||
"@angular/core": "^17.0.1",
|
"@angular/core": "^17.0.2",
|
||||||
"@angular/forms": "^17.0.1",
|
"@angular/forms": "^17.0.2",
|
||||||
"@angular/localize": "^17.0.1",
|
"@angular/localize": "^17.0.2",
|
||||||
"@angular/platform-browser": "^17.0.1",
|
"@angular/platform-browser": "^17.0.2",
|
||||||
"@angular/platform-browser-dynamic": "^17.0.1",
|
"@angular/platform-browser-dynamic": "^17.0.2",
|
||||||
"@angular/router": "^17.0.1",
|
"@angular/router": "^17.0.2",
|
||||||
"@fortawesome/fontawesome-free": "^6.4.2",
|
"@fortawesome/fontawesome-free": "^6.4.2",
|
||||||
"@iharbeck/ngx-virtual-scroller": "^16.0.0",
|
"@iharbeck/ngx-virtual-scroller": "^16.0.0",
|
||||||
"@iplab/ngx-file-upload": "^16.0.2",
|
"@iplab/ngx-file-upload": "^16.0.2",
|
||||||
@ -29,7 +29,7 @@
|
|||||||
"@ngneat/transloco-persist-translations": "^5.0.0",
|
"@ngneat/transloco-persist-translations": "^5.0.0",
|
||||||
"@ngneat/transloco-preload-langs": "^5.0.0",
|
"@ngneat/transloco-preload-langs": "^5.0.0",
|
||||||
"@popperjs/core": "^2.11.7",
|
"@popperjs/core": "^2.11.7",
|
||||||
"@swimlane/ngx-charts": "^20.1.2",
|
"@swimlane/ngx-charts": "^20.5.0",
|
||||||
"@tweenjs/tween.js": "^21.0.0",
|
"@tweenjs/tween.js": "^21.0.0",
|
||||||
"bootstrap": "^5.3.2",
|
"bootstrap": "^5.3.2",
|
||||||
"charts.css": "^1.1.0",
|
"charts.css": "^1.1.0",
|
||||||
@ -52,13 +52,13 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@angular-devkit/build-angular": "^17.0.0",
|
"@angular-devkit/build-angular": "^17.0.0",
|
||||||
"@angular-eslint/builder": "^17.0.0",
|
"@angular-eslint/builder": "^17.0.1",
|
||||||
"@angular-eslint/eslint-plugin": "^17.0.0",
|
"@angular-eslint/eslint-plugin": "^17.0.0",
|
||||||
"@angular-eslint/eslint-plugin-template": "^17.0.0",
|
"@angular-eslint/eslint-plugin-template": "^17.0.0",
|
||||||
"@angular-eslint/schematics": "^17.0.1",
|
"@angular-eslint/schematics": "^17.0.1",
|
||||||
"@angular-eslint/template-parser": "^17.0.1",
|
"@angular-eslint/template-parser": "^17.0.1",
|
||||||
"@angular/cli": "^17.0.0",
|
"@angular/cli": "^17.0.0",
|
||||||
"@angular/compiler-cli": "^17.0.1",
|
"@angular/compiler-cli": "^17.0.2",
|
||||||
"@types/d3": "^7.4.3",
|
"@types/d3": "^7.4.3",
|
||||||
"@types/file-saver": "^2.0.7",
|
"@types/file-saver": "^2.0.7",
|
||||||
"@types/luxon": "^3.3.4",
|
"@types/luxon": "^3.3.4",
|
||||||
@ -744,9 +744,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@angular-eslint/builder": {
|
"node_modules/@angular-eslint/builder": {
|
||||||
"version": "17.0.0",
|
"version": "17.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/@angular-eslint/builder/-/builder-17.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/@angular-eslint/builder/-/builder-17.0.1.tgz",
|
||||||
"integrity": "sha512-cquqJH0R/IIh2PElcGXdo9FTcrkwO78H2MXk9ChGFBjQrYjihFLhFm12VuQsih7X6bJjA0cmr2PL1KbtgjMk1Q==",
|
"integrity": "sha512-bNXi5tdqIFdNDHxphDRUUbzA+7v6emOX2B/PFLG2pe+K6/JpHS0auwY/nq7hCroH7pMS5HZ+Q4i90q0GN/DWPg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@nx/devkit": "17.0.3",
|
"@nx/devkit": "17.0.3",
|
||||||
@ -842,9 +842,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@angular/animations": {
|
"node_modules/@angular/animations": {
|
||||||
"version": "17.0.1",
|
"version": "17.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/@angular/animations/-/animations-17.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@angular/animations/-/animations-17.0.2.tgz",
|
||||||
"integrity": "sha512-Uee6E8zyU6XjDfKFozybcf+JZy0nUFQ1bUEmRwFP5HvYJSSJ5YiUDokNiVxyn9znwZ7zKHlM6Bq9ZY9cCmeKKQ==",
|
"integrity": "sha512-32RHWhTgFLMonI3kRdstACay/nvetfxXjdwcTtABjcvBoND7nD9GMhkISQdgS+hcR/IhgXxaPidq8f2UAY5DBw==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"tslib": "^2.3.0"
|
"tslib": "^2.3.0"
|
||||||
},
|
},
|
||||||
@ -852,7 +852,7 @@
|
|||||||
"node": "^18.13.0 || >=20.9.0"
|
"node": "^18.13.0 || >=20.9.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@angular/core": "17.0.1"
|
"@angular/core": "17.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@angular/cdk": {
|
"node_modules/@angular/cdk": {
|
||||||
@ -939,9 +939,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/@angular/common": {
|
"node_modules/@angular/common": {
|
||||||
"version": "17.0.1",
|
"version": "17.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/@angular/common/-/common-17.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@angular/common/-/common-17.0.2.tgz",
|
||||||
"integrity": "sha512-AvvhZc+PhX5lVEW/Vorxe3Zf1rIEJJvfduRuRv+nsjijo3ZGjdgYjTYEx4ighZgH60RLIAuwyBE24gPkT2Pm7g==",
|
"integrity": "sha512-hCW0njHgrcwTWNoKZDwf02DnhYLVWNXM2FMw66MKpfxTp7McSyaXjGBU9/hchW3dZJ0xTwyxoyoqJFoHYvg0yg==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"tslib": "^2.3.0"
|
"tslib": "^2.3.0"
|
||||||
},
|
},
|
||||||
@ -949,14 +949,14 @@
|
|||||||
"node": "^18.13.0 || >=20.9.0"
|
"node": "^18.13.0 || >=20.9.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@angular/core": "17.0.1",
|
"@angular/core": "17.0.2",
|
||||||
"rxjs": "^6.5.3 || ^7.4.0"
|
"rxjs": "^6.5.3 || ^7.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@angular/compiler": {
|
"node_modules/@angular/compiler": {
|
||||||
"version": "17.0.1",
|
"version": "17.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-17.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-17.0.2.tgz",
|
||||||
"integrity": "sha512-qlKqCvjoxPHJ1e8+UMaBl/n9zzrmGXI5eWMVhULSvQnQvPWkwNlUh5XFeoSFcTEQxORjaO2/08Z31DmTJAqlPA==",
|
"integrity": "sha512-ewUFbKhMEhAmw2dGfk0ImhTlyrO2y4pJSKIZdFrkR1d0HiJX8bCHUdTiiR/2jeP7w2eamjXj15Rptb+iZZes2Q==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"tslib": "^2.3.0"
|
"tslib": "^2.3.0"
|
||||||
},
|
},
|
||||||
@ -964,7 +964,7 @@
|
|||||||
"node": "^18.13.0 || >=20.9.0"
|
"node": "^18.13.0 || >=20.9.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@angular/core": "17.0.1"
|
"@angular/core": "17.0.2"
|
||||||
},
|
},
|
||||||
"peerDependenciesMeta": {
|
"peerDependenciesMeta": {
|
||||||
"@angular/core": {
|
"@angular/core": {
|
||||||
@ -973,9 +973,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@angular/compiler-cli": {
|
"node_modules/@angular/compiler-cli": {
|
||||||
"version": "17.0.1",
|
"version": "17.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-17.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-17.0.2.tgz",
|
||||||
"integrity": "sha512-Rnvh2V2CYhG7NR5VI4cESGKk9jyqLat0HoqXa06v3TtbjkiZyjjwh0SyZ8NYOBMkQeWiQTHGcgxGvjKD3L3qqA==",
|
"integrity": "sha512-IUYL3Yz5RbR0Z0/x7it4GK3sMb2qVihxu0tlgfUW53P1Vi6nU/Zda0bCJTu6Z64qEtS8zwCwF1Ekomuq6UaiKg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/core": "7.23.2",
|
"@babel/core": "7.23.2",
|
||||||
@ -996,14 +996,14 @@
|
|||||||
"node": "^18.13.0 || >=20.9.0"
|
"node": "^18.13.0 || >=20.9.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@angular/compiler": "17.0.1",
|
"@angular/compiler": "17.0.2",
|
||||||
"typescript": ">=5.2 <5.3"
|
"typescript": ">=5.2 <5.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@angular/core": {
|
"node_modules/@angular/core": {
|
||||||
"version": "17.0.1",
|
"version": "17.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/@angular/core/-/core-17.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@angular/core/-/core-17.0.2.tgz",
|
||||||
"integrity": "sha512-yVwU+oz0G8g6Q5ORyOCpgqMPdSiCdfW+uQhjI37WROnXHja3jY843AqrYTKE6mMx1r6q9h1wbDy+x2E61OWP7A==",
|
"integrity": "sha512-MjDxWeyn3Txi0qo/V/I+B/gndh0uptQ0XWgBRwOx6Wcr5zRGeZIFlXBxPpyXnGTlJkeyErsTN7FfFCZ4C3kCPA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"tslib": "^2.3.0"
|
"tslib": "^2.3.0"
|
||||||
},
|
},
|
||||||
@ -1016,9 +1016,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@angular/forms": {
|
"node_modules/@angular/forms": {
|
||||||
"version": "17.0.1",
|
"version": "17.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/@angular/forms/-/forms-17.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@angular/forms/-/forms-17.0.2.tgz",
|
||||||
"integrity": "sha512-FpmUf2kgzwZXVbFB4VrwbnrO0m88QLUBsDsbLfQVQQwb7KxwSaftUu/aIrjst1gFCdl9k0Vqtrq2gwLZKzdSGQ==",
|
"integrity": "sha512-w1QKifaVG4daxUktcBNZqBtOH1vn8t0YiwDR3woEdUYt0XYKMipfDzQfyIK+6fIVPOJUd42pRns1nbWJQHOInA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"tslib": "^2.3.0"
|
"tslib": "^2.3.0"
|
||||||
},
|
},
|
||||||
@ -1026,16 +1026,16 @@
|
|||||||
"node": "^18.13.0 || >=20.9.0"
|
"node": "^18.13.0 || >=20.9.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@angular/common": "17.0.1",
|
"@angular/common": "17.0.2",
|
||||||
"@angular/core": "17.0.1",
|
"@angular/core": "17.0.2",
|
||||||
"@angular/platform-browser": "17.0.1",
|
"@angular/platform-browser": "17.0.2",
|
||||||
"rxjs": "^6.5.3 || ^7.4.0"
|
"rxjs": "^6.5.3 || ^7.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@angular/localize": {
|
"node_modules/@angular/localize": {
|
||||||
"version": "17.0.1",
|
"version": "17.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/@angular/localize/-/localize-17.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@angular/localize/-/localize-17.0.2.tgz",
|
||||||
"integrity": "sha512-pNLLnEbXjoW1agKwA4cBcM/HnqGuwQMpIhx9H46Y/oC2JkAvTCMVyXLbZUESeXmhysC9x2JDmF+Awhu7JzVVCA==",
|
"integrity": "sha512-ct8xEy8Xk+PRfjrHLu7uywSQDzozmzlz6ptUCuYkRHrS4rJabXn3c0Sz4w+mh9B58qrK6KM+JSmXEZngEMXMTw==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/core": "7.23.2",
|
"@babel/core": "7.23.2",
|
||||||
"fast-glob": "3.3.1",
|
"fast-glob": "3.3.1",
|
||||||
@ -1050,14 +1050,14 @@
|
|||||||
"node": "^18.13.0 || >=20.9.0"
|
"node": "^18.13.0 || >=20.9.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@angular/compiler": "17.0.1",
|
"@angular/compiler": "17.0.2",
|
||||||
"@angular/compiler-cli": "17.0.1"
|
"@angular/compiler-cli": "17.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@angular/platform-browser": {
|
"node_modules/@angular/platform-browser": {
|
||||||
"version": "17.0.1",
|
"version": "17.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-17.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-17.0.2.tgz",
|
||||||
"integrity": "sha512-JpvU0YDEM5KYdHtxC0Kdzk/hdwvZPq5vju5lTmIjTVa2OOabApOrQ6cq1MpKlrvjv1rw8MClHIM0l5Y0g9KH5g==",
|
"integrity": "sha512-eTnPILEA/eAMkVUR/+g6fWhhMTmnmOzcZSGX/bBgQcvOhayZrDDxA6/Qf+jIB4RwC0wd3KA9zT5BCMmNojoUsg==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"tslib": "^2.3.0"
|
"tslib": "^2.3.0"
|
||||||
},
|
},
|
||||||
@ -1065,9 +1065,9 @@
|
|||||||
"node": "^18.13.0 || >=20.9.0"
|
"node": "^18.13.0 || >=20.9.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@angular/animations": "17.0.1",
|
"@angular/animations": "17.0.2",
|
||||||
"@angular/common": "17.0.1",
|
"@angular/common": "17.0.2",
|
||||||
"@angular/core": "17.0.1"
|
"@angular/core": "17.0.2"
|
||||||
},
|
},
|
||||||
"peerDependenciesMeta": {
|
"peerDependenciesMeta": {
|
||||||
"@angular/animations": {
|
"@angular/animations": {
|
||||||
@ -1076,9 +1076,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@angular/platform-browser-dynamic": {
|
"node_modules/@angular/platform-browser-dynamic": {
|
||||||
"version": "17.0.1",
|
"version": "17.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-17.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-17.0.2.tgz",
|
||||||
"integrity": "sha512-xEcbB/ukXc65LaX4JBQYEM7D5Z8LcUIZniSJFneY7deZt3wNiKgmPZrPoXUyDV26QULh7N0IADEzvbcMF60AFQ==",
|
"integrity": "sha512-clcHqHcfD00/TlTixDbJ3q4EQxpm0t2ZFG76rRFmGrmE5tKYUPfaofIa3hQCxy3q269MAYuF16wALhUtrEWyUA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"tslib": "^2.3.0"
|
"tslib": "^2.3.0"
|
||||||
},
|
},
|
||||||
@ -1086,16 +1086,16 @@
|
|||||||
"node": "^18.13.0 || >=20.9.0"
|
"node": "^18.13.0 || >=20.9.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@angular/common": "17.0.1",
|
"@angular/common": "17.0.2",
|
||||||
"@angular/compiler": "17.0.1",
|
"@angular/compiler": "17.0.2",
|
||||||
"@angular/core": "17.0.1",
|
"@angular/core": "17.0.2",
|
||||||
"@angular/platform-browser": "17.0.1"
|
"@angular/platform-browser": "17.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@angular/router": {
|
"node_modules/@angular/router": {
|
||||||
"version": "17.0.1",
|
"version": "17.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/@angular/router/-/router-17.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@angular/router/-/router-17.0.2.tgz",
|
||||||
"integrity": "sha512-73PCDDsRAjemODMRndZhwEN6Tb9rVVbDfMWgLQ4HgfgKnjek8P9BoYf8rOf3qV5fXf3c1Sm9MmKtaPv+l5lU9Q==",
|
"integrity": "sha512-A1Ulv4qBAtJyK5g1yBlK1qZHe+KaaL5vMPAaPWUxICH8lHEodDkJlbYAUI2e4VL2BN7zBmdOep6tlBKPmHY3mw==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"tslib": "^2.3.0"
|
"tslib": "^2.3.0"
|
||||||
},
|
},
|
||||||
@ -1103,9 +1103,9 @@
|
|||||||
"node": "^18.13.0 || >=20.9.0"
|
"node": "^18.13.0 || >=20.9.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@angular/common": "17.0.1",
|
"@angular/common": "17.0.2",
|
||||||
"@angular/core": "17.0.1",
|
"@angular/core": "17.0.2",
|
||||||
"@angular/platform-browser": "17.0.1",
|
"@angular/platform-browser": "17.0.2",
|
||||||
"rxjs": "^6.5.3 || ^7.4.0"
|
"rxjs": "^6.5.3 || ^7.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -4251,9 +4251,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/@swimlane/ngx-charts": {
|
"node_modules/@swimlane/ngx-charts": {
|
||||||
"version": "20.4.1",
|
"version": "20.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/@swimlane/ngx-charts/-/ngx-charts-20.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/@swimlane/ngx-charts/-/ngx-charts-20.5.0.tgz",
|
||||||
"integrity": "sha512-DyTQe0fcqLDoLEZca45gkdjxP8iLH7kh4pCkr+TCFIkmgEdfQ5DpavNBOOVO0qd5J5uV/tbtSnkYWSx8JkbFpg==",
|
"integrity": "sha512-PNBIHdu/R3ceD7jnw1uCBVOj4k3T6IxfdW6xsDsglGkZyoWMEEq4tLoEurjLEKzmDtRv9c35kVNOXy0lkOuXeA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"d3-array": "^3.1.1",
|
"d3-array": "^3.1.1",
|
||||||
"d3-brush": "^3.0.0",
|
"d3-brush": "^3.0.0",
|
||||||
@ -4262,6 +4262,7 @@
|
|||||||
"d3-format": "^3.1.0",
|
"d3-format": "^3.1.0",
|
||||||
"d3-hierarchy": "^3.1.0",
|
"d3-hierarchy": "^3.1.0",
|
||||||
"d3-interpolate": "^3.0.1",
|
"d3-interpolate": "^3.0.1",
|
||||||
|
"d3-sankey": "^0.12.3",
|
||||||
"d3-scale": "^4.0.2",
|
"d3-scale": "^4.0.2",
|
||||||
"d3-selection": "^3.0.0",
|
"d3-selection": "^3.0.0",
|
||||||
"d3-shape": "^3.2.0",
|
"d3-shape": "^3.2.0",
|
||||||
@ -7166,6 +7167,41 @@
|
|||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/d3-sankey": {
|
||||||
|
"version": "0.12.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-sankey/-/d3-sankey-0.12.3.tgz",
|
||||||
|
"integrity": "sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"d3-array": "1 - 2",
|
||||||
|
"d3-shape": "^1.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/d3-sankey/node_modules/d3-array": {
|
||||||
|
"version": "2.12.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz",
|
||||||
|
"integrity": "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"internmap": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/d3-sankey/node_modules/d3-path": {
|
||||||
|
"version": "1.0.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz",
|
||||||
|
"integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg=="
|
||||||
|
},
|
||||||
|
"node_modules/d3-sankey/node_modules/d3-shape": {
|
||||||
|
"version": "1.3.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz",
|
||||||
|
"integrity": "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==",
|
||||||
|
"dependencies": {
|
||||||
|
"d3-path": "1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/d3-sankey/node_modules/internmap": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/internmap/-/internmap-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw=="
|
||||||
|
},
|
||||||
"node_modules/d3-scale": {
|
"node_modules/d3-scale": {
|
||||||
"version": "4.0.2",
|
"version": "4.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz",
|
||||||
|
@ -13,16 +13,16 @@
|
|||||||
},
|
},
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@angular/animations": "^17.0.1",
|
"@angular/animations": "^17.0.2",
|
||||||
"@angular/cdk": "^17.0.0",
|
"@angular/cdk": "^17.0.0",
|
||||||
"@angular/common": "^17.0.1",
|
"@angular/common": "^17.0.2",
|
||||||
"@angular/compiler": "^17.0.1",
|
"@angular/compiler": "^17.0.2",
|
||||||
"@angular/core": "^17.0.1",
|
"@angular/core": "^17.0.2",
|
||||||
"@angular/forms": "^17.0.1",
|
"@angular/forms": "^17.0.2",
|
||||||
"@angular/localize": "^17.0.1",
|
"@angular/localize": "^17.0.2",
|
||||||
"@angular/platform-browser": "^17.0.1",
|
"@angular/platform-browser": "^17.0.2",
|
||||||
"@angular/platform-browser-dynamic": "^17.0.1",
|
"@angular/platform-browser-dynamic": "^17.0.2",
|
||||||
"@angular/router": "^17.0.1",
|
"@angular/router": "^17.0.2",
|
||||||
"@fortawesome/fontawesome-free": "^6.4.2",
|
"@fortawesome/fontawesome-free": "^6.4.2",
|
||||||
"@iharbeck/ngx-virtual-scroller": "^16.0.0",
|
"@iharbeck/ngx-virtual-scroller": "^16.0.0",
|
||||||
"@iplab/ngx-file-upload": "^16.0.2",
|
"@iplab/ngx-file-upload": "^16.0.2",
|
||||||
@ -34,7 +34,7 @@
|
|||||||
"@ngneat/transloco-persist-translations": "^5.0.0",
|
"@ngneat/transloco-persist-translations": "^5.0.0",
|
||||||
"@ngneat/transloco-preload-langs": "^5.0.0",
|
"@ngneat/transloco-preload-langs": "^5.0.0",
|
||||||
"@popperjs/core": "^2.11.7",
|
"@popperjs/core": "^2.11.7",
|
||||||
"@swimlane/ngx-charts": "^20.1.2",
|
"@swimlane/ngx-charts": "^20.5.0",
|
||||||
"@tweenjs/tween.js": "^21.0.0",
|
"@tweenjs/tween.js": "^21.0.0",
|
||||||
"bootstrap": "^5.3.2",
|
"bootstrap": "^5.3.2",
|
||||||
"charts.css": "^1.1.0",
|
"charts.css": "^1.1.0",
|
||||||
@ -57,13 +57,13 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@angular-devkit/build-angular": "^17.0.0",
|
"@angular-devkit/build-angular": "^17.0.0",
|
||||||
"@angular-eslint/builder": "^17.0.0",
|
"@angular-eslint/builder": "^17.0.1",
|
||||||
"@angular-eslint/eslint-plugin": "^17.0.0",
|
"@angular-eslint/eslint-plugin": "^17.0.0",
|
||||||
"@angular-eslint/eslint-plugin-template": "^17.0.0",
|
"@angular-eslint/eslint-plugin-template": "^17.0.0",
|
||||||
"@angular-eslint/schematics": "^17.0.1",
|
"@angular-eslint/schematics": "^17.0.1",
|
||||||
"@angular-eslint/template-parser": "^17.0.1",
|
"@angular-eslint/template-parser": "^17.0.1",
|
||||||
"@angular/cli": "^17.0.0",
|
"@angular/cli": "^17.0.0",
|
||||||
"@angular/compiler-cli": "^17.0.1",
|
"@angular/compiler-cli": "^17.0.2",
|
||||||
"@types/d3": "^7.4.3",
|
"@types/d3": "^7.4.3",
|
||||||
"@types/file-saver": "^2.0.7",
|
"@types/file-saver": "^2.0.7",
|
||||||
"@types/luxon": "^3.3.4",
|
"@types/luxon": "^3.3.4",
|
||||||
|
@ -34,16 +34,16 @@ export interface SeriesMetadata {
|
|||||||
summaryLocked: boolean;
|
summaryLocked: boolean;
|
||||||
genresLocked: boolean;
|
genresLocked: boolean;
|
||||||
tagsLocked: boolean;
|
tagsLocked: boolean;
|
||||||
writersLocked: boolean;
|
writerLocked: boolean;
|
||||||
coverArtistsLocked: boolean;
|
coverArtistLocked: boolean;
|
||||||
publishersLocked: boolean;
|
publisherLocked: boolean;
|
||||||
charactersLocked: boolean;
|
characterLocked: boolean;
|
||||||
pencillersLocked: boolean;
|
pencillerLocked: boolean;
|
||||||
inkersLocked: boolean;
|
inkerLocked: boolean;
|
||||||
coloristsLocked: boolean;
|
coloristLocked: boolean;
|
||||||
letterersLocked: boolean;
|
lettererLocked: boolean;
|
||||||
editorsLocked: boolean;
|
editorLocked: boolean;
|
||||||
translatorsLocked: boolean;
|
translatorLocked: boolean;
|
||||||
ageRatingLocked: boolean;
|
ageRatingLocked: boolean;
|
||||||
releaseYearLocked: boolean;
|
releaseYearLocked: boolean;
|
||||||
languageLocked: boolean;
|
languageLocked: boolean;
|
||||||
|
@ -23,7 +23,7 @@ export class UtcToLocalTimePipe implements PipeTransform {
|
|||||||
case 'short':
|
case 'short':
|
||||||
return dateTime.toLocaleString(DateTime.DATETIME_SHORT);
|
return dateTime.toLocaleString(DateTime.DATETIME_SHORT);
|
||||||
case 'shortDate':
|
case 'shortDate':
|
||||||
return dateTime.toLocaleString(DateTime.DATE_MED);
|
return dateTime.toLocaleString(DateTime.DATE_SHORT);
|
||||||
case 'shortTime':
|
case 'shortTime':
|
||||||
return dateTime.toLocaleString(DateTime.TIME_SIMPLE);
|
return dateTime.toLocaleString(DateTime.TIME_SIMPLE);
|
||||||
case 'full':
|
case 'full':
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="typeahead-focus" class="form-label">{{t('path-label')}}</label>
|
<label for="typeahead-focus" class="form-label">{{t('path-label')}}</label>
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input id="typeahead-focus" type="text" class="form-control" [(ngModel)]="path" [ngbTypeahead]="search"
|
<input id="typeahead-focus" type="text" class="form-control" style="width: 100%" [(ngModel)]="path" [ngbTypeahead]="search"
|
||||||
(focus)="focus$.next($any($event).target.value)" (click)="click$.next($any($event).target.value)"
|
(focus)="focus$.next($any($event).target.value)" (click)="click$.next($any($event).target.value)"
|
||||||
(ngModelChange)="updateTable()" #instance="ngbTypeahead" [placeholder]="t('path-placeholder')"
|
(ngModelChange)="updateTable()" #instance="ngbTypeahead" [placeholder]="t('path-placeholder')"
|
||||||
[resultTemplate]="rt" />
|
[resultTemplate]="rt" />
|
||||||
|
@ -37,7 +37,7 @@ export class DirectoryPickerComponent implements OnInit {
|
|||||||
|
|
||||||
|
|
||||||
path: string = '';
|
path: string = '';
|
||||||
@ViewChild('instance', {static: true}) instance!: NgbTypeahead;
|
@ViewChild('instance', {static: false}) instance!: NgbTypeahead;
|
||||||
focus$ = new Subject<string>();
|
focus$ = new Subject<string>();
|
||||||
click$ = new Subject<string>();
|
click$ = new Subject<string>();
|
||||||
searching: boolean = false;
|
searching: boolean = false;
|
||||||
|
@ -24,9 +24,6 @@
|
|||||||
<ng-container *ngIf="tab.fragment === TabID.Libraries">
|
<ng-container *ngIf="tab.fragment === TabID.Libraries">
|
||||||
<app-manage-library></app-manage-library>
|
<app-manage-library></app-manage-library>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<ng-container *ngIf="tab.fragment === TabID.Logs">
|
|
||||||
<app-manage-logs></app-manage-logs>
|
|
||||||
</ng-container>
|
|
||||||
<ng-container *ngIf="tab.fragment === TabID.System">
|
<ng-container *ngIf="tab.fragment === TabID.System">
|
||||||
<app-manage-system></app-manage-system>
|
<app-manage-system></app-manage-system>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
@ -38,7 +38,10 @@ enum TabID {
|
|||||||
templateUrl: './dashboard.component.html',
|
templateUrl: './dashboard.component.html',
|
||||||
styleUrls: ['./dashboard.component.scss'],
|
styleUrls: ['./dashboard.component.scss'],
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [SideNavCompanionBarComponent, NgbNav, NgFor, NgbNavItem, NgbNavItemRole, NgbNavLink, RouterLink, NgbNavContent, NgIf, ManageSettingsComponent, ManageEmailSettingsComponent, ManageMediaSettingsComponent, ManageUsersComponent, ManageLibraryComponent, ManageLogsComponent, ManageSystemComponent, ServerStatsComponent, ManageTasksSettingsComponent, LicenseComponent, NgbNavOutlet, SentenceCasePipe, TranslocoDirective],
|
imports: [SideNavCompanionBarComponent, NgbNav, NgFor, NgbNavItem, NgbNavItemRole, NgbNavLink, RouterLink,
|
||||||
|
NgbNavContent, NgIf, ManageSettingsComponent, ManageEmailSettingsComponent, ManageMediaSettingsComponent,
|
||||||
|
ManageUsersComponent, ManageLibraryComponent, ManageSystemComponent, ServerStatsComponent,
|
||||||
|
ManageTasksSettingsComponent, LicenseComponent, NgbNavOutlet, SentenceCasePipe, TranslocoDirective],
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush
|
changeDetection: ChangeDetectionStrategy.OnPush
|
||||||
})
|
})
|
||||||
export class DashboardComponent implements OnInit {
|
export class DashboardComponent implements OnInit {
|
||||||
@ -47,7 +50,6 @@ export class DashboardComponent implements OnInit {
|
|||||||
{title: 'general-tab', fragment: TabID.General},
|
{title: 'general-tab', fragment: TabID.General},
|
||||||
{title: 'users-tab', fragment: TabID.Users},
|
{title: 'users-tab', fragment: TabID.Users},
|
||||||
{title: 'libraries-tab', fragment: TabID.Libraries},
|
{title: 'libraries-tab', fragment: TabID.Libraries},
|
||||||
//{title: 'logs-tab', fragment: TabID.Logs},
|
|
||||||
{title: 'media-tab', fragment: TabID.Media},
|
{title: 'media-tab', fragment: TabID.Media},
|
||||||
{title: 'email-tab', fragment: TabID.Email},
|
{title: 'email-tab', fragment: TabID.Email},
|
||||||
{title: 'tasks-tab', fragment: TabID.Tasks},
|
{title: 'tasks-tab', fragment: TabID.Tasks},
|
||||||
|
@ -44,7 +44,7 @@ import {SeriesFilterV2} from "../../../_models/metadata/v2/series-filter-v2";
|
|||||||
})
|
})
|
||||||
export class AllSeriesComponent implements OnInit {
|
export class AllSeriesComponent implements OnInit {
|
||||||
|
|
||||||
title!: string;
|
title: string = translate('side-nav.all-series');
|
||||||
series: Series[] = [];
|
series: Series[] = [];
|
||||||
loadingSeries = false;
|
loadingSeries = false;
|
||||||
pagination: Pagination = new Pagination();
|
pagination: Pagination = new Pagination();
|
||||||
@ -115,10 +115,8 @@ export class AllSeriesComponent implements OnInit {
|
|||||||
|
|
||||||
this.filterUtilityService.filterPresetsFromUrl(this.route.snapshot).subscribe(filter => {
|
this.filterUtilityService.filterPresetsFromUrl(this.route.snapshot).subscribe(filter => {
|
||||||
this.filter = filter;
|
this.filter = filter;
|
||||||
|
|
||||||
this.title = this.route.snapshot.queryParamMap.get('title') || this.filter.name || this.title;
|
this.title = this.route.snapshot.queryParamMap.get('title') || this.filter.name || this.title;
|
||||||
this.titleService.setTitle('Kavita - ' + this.title);
|
this.titleService.setTitle('Kavita - ' + this.title);
|
||||||
|
|
||||||
this.filterActiveCheck = this.filterUtilityService.createSeriesV2Filter();
|
this.filterActiveCheck = this.filterUtilityService.createSeriesV2Filter();
|
||||||
this.filterActiveCheck!.statements.push(this.filterUtilityService.createSeriesV2DefaultStatement());
|
this.filterActiveCheck!.statements.push(this.filterUtilityService.createSeriesV2DefaultStatement());
|
||||||
this.filterSettings.presetsV2 = this.filter;
|
this.filterSettings.presetsV2 = this.filter;
|
||||||
@ -128,7 +126,6 @@ export class AllSeriesComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.title = translate('all-series.title');
|
|
||||||
this.hubService.messages$.pipe(debounceTime(6000), takeUntilDestroyed(this.destroyRef)).subscribe((event: Message<any>) => {
|
this.hubService.messages$.pipe(debounceTime(6000), takeUntilDestroyed(this.destroyRef)).subscribe((event: Message<any>) => {
|
||||||
if (event.event !== EVENTS.SeriesAdded) return;
|
if (event.event !== EVENTS.SeriesAdded) return;
|
||||||
this.loadPage();
|
this.loadPage();
|
||||||
|
@ -81,6 +81,7 @@ const routes: Routes = [
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{path: '', pathMatch: 'full', redirectTo: 'home'},
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -91,9 +92,10 @@ const routes: Routes = [
|
|||||||
path: 'login',
|
path: 'login',
|
||||||
loadChildren: () => import('./_routes/registration.router.module').then(m => m.routes) // TODO: Refactor so we just use /registration/login going forward
|
loadChildren: () => import('./_routes/registration.router.module').then(m => m.routes) // TODO: Refactor so we just use /registration/login going forward
|
||||||
},
|
},
|
||||||
{path: '**', pathMatch: 'full', redirectTo: 'home'},
|
|
||||||
{path: 'libraries', pathMatch: 'full', redirectTo: 'home'},
|
{path: 'libraries', pathMatch: 'full', redirectTo: 'home'},
|
||||||
{path: '**', pathMatch: 'prefix', redirectTo: 'home'},
|
{path: '**', pathMatch: 'prefix', redirectTo: 'home'},
|
||||||
|
{path: '**', pathMatch: 'full', redirectTo: 'home'},
|
||||||
|
{path: '', pathMatch: 'full', redirectTo: 'home'},
|
||||||
];
|
];
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
|
@ -1617,9 +1617,7 @@ export class BookReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||||||
// Responsible for handling pagination only
|
// Responsible for handling pagination only
|
||||||
handleContainerClick(event: MouseEvent) {
|
handleContainerClick(event: MouseEvent) {
|
||||||
|
|
||||||
console.log('target: ', event.target);
|
if (this.drawerOpen || ['action-bar'].some(className => (event.target as Element).classList.contains(className))) {
|
||||||
if (this.actionBarVisible || ['action-bar'].some(className => (event.target as Element).classList.contains(className))) {
|
|
||||||
//console.log('exiting early')
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,8 +187,8 @@
|
|||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="writer" class="form-label">{{t('writer-label')}}</label>
|
<label for="writer" class="form-label">{{t('writer-label')}}</label>
|
||||||
<app-typeahead (selectedData)="updatePerson($event, PersonRole.Writer)" [settings]="getPersonsSettings(PersonRole.Writer)"
|
<app-typeahead (selectedData)="updatePerson($event, PersonRole.Writer)" [settings]="getPersonsSettings(PersonRole.Writer)"
|
||||||
[(locked)]="metadata.writersLocked" (onUnlock)="metadata.writersLocked = false"
|
[(locked)]="metadata.writerLocked" (onUnlock)="metadata.writerLocked = false"
|
||||||
(newItemAdded)="metadata.writersLocked = true" (selectedData)="metadata.writersLocked = true">
|
(newItemAdded)="metadata.writerLocked = true" (selectedData)="metadata.writerLocked = true">
|
||||||
<ng-template #badgeItem let-item let-position="idx">
|
<ng-template #badgeItem let-item let-position="idx">
|
||||||
{{item.name}}
|
{{item.name}}
|
||||||
</ng-template>
|
</ng-template>
|
||||||
@ -202,8 +202,8 @@
|
|||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="cover-artist" class="form-label">{{t('cover-artist-label')}}</label>
|
<label for="cover-artist" class="form-label">{{t('cover-artist-label')}}</label>
|
||||||
<app-typeahead (selectedData)="updatePerson($event, PersonRole.CoverArtist)" [settings]="getPersonsSettings(PersonRole.CoverArtist)"
|
<app-typeahead (selectedData)="updatePerson($event, PersonRole.CoverArtist)" [settings]="getPersonsSettings(PersonRole.CoverArtist)"
|
||||||
[(locked)]="metadata.coverArtistsLocked" (onUnlock)="metadata.coverArtistsLocked = false"
|
[(locked)]="metadata.coverArtistLocked" (onUnlock)="metadata.coverArtistLocked = false"
|
||||||
(newItemAdded)="metadata.coverArtistsLocked = true" (selectedData)="metadata.coverArtistsLocked = true">
|
(newItemAdded)="metadata.coverArtistLocked = true" (selectedData)="metadata.coverArtistLocked = true">
|
||||||
<ng-template #badgeItem let-item let-position="idx">
|
<ng-template #badgeItem let-item let-position="idx">
|
||||||
{{item.name}}
|
{{item.name}}
|
||||||
</ng-template>
|
</ng-template>
|
||||||
@ -219,8 +219,8 @@
|
|||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="publisher" class="form-label">{{t('publisher-label')}}</label>
|
<label for="publisher" class="form-label">{{t('publisher-label')}}</label>
|
||||||
<app-typeahead (selectedData)="updatePerson($event, PersonRole.Publisher)" [settings]="getPersonsSettings(PersonRole.Publisher)"
|
<app-typeahead (selectedData)="updatePerson($event, PersonRole.Publisher)" [settings]="getPersonsSettings(PersonRole.Publisher)"
|
||||||
[(locked)]="metadata.publishersLocked" (onUnlock)="metadata.publishersLocked = false"
|
[(locked)]="metadata.publisherLocked" (onUnlock)="metadata.publisherLocked = false"
|
||||||
(newItemAdded)="metadata.publishersLocked = true" (selectedData)="metadata.publishersLocked = true">
|
(newItemAdded)="metadata.publisherLocked = true" (selectedData)="metadata.publisherLocked = true">
|
||||||
<ng-template #badgeItem let-item let-position="idx">
|
<ng-template #badgeItem let-item let-position="idx">
|
||||||
{{item.name}}
|
{{item.name}}
|
||||||
</ng-template>
|
</ng-template>
|
||||||
@ -234,8 +234,8 @@
|
|||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="penciller" class="form-label">{{t('penciller-label')}}</label>
|
<label for="penciller" class="form-label">{{t('penciller-label')}}</label>
|
||||||
<app-typeahead (selectedData)="updatePerson($event, PersonRole.Penciller)" [settings]="getPersonsSettings(PersonRole.Penciller)"
|
<app-typeahead (selectedData)="updatePerson($event, PersonRole.Penciller)" [settings]="getPersonsSettings(PersonRole.Penciller)"
|
||||||
[(locked)]="metadata.pencillersLocked" (onUnlock)="metadata.pencillersLocked = false"
|
[(locked)]="metadata.pencillerLocked" (onUnlock)="metadata.pencillerLocked = false"
|
||||||
(newItemAdded)="metadata.pencillersLocked = true" (selectedData)="metadata.pencillersLocked = true">
|
(newItemAdded)="metadata.pencillerLocked = true" (selectedData)="metadata.pencillerLocked = true">
|
||||||
<ng-template #badgeItem let-item let-position="idx">
|
<ng-template #badgeItem let-item let-position="idx">
|
||||||
{{item.name}}
|
{{item.name}}
|
||||||
</ng-template>
|
</ng-template>
|
||||||
@ -251,8 +251,8 @@
|
|||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="letterer" class="form-label">{{t('letterer-label')}}</label>
|
<label for="letterer" class="form-label">{{t('letterer-label')}}</label>
|
||||||
<app-typeahead (selectedData)="updatePerson($event, PersonRole.Letterer)" [settings]="getPersonsSettings(PersonRole.Letterer)"
|
<app-typeahead (selectedData)="updatePerson($event, PersonRole.Letterer)" [settings]="getPersonsSettings(PersonRole.Letterer)"
|
||||||
[(locked)]="metadata.letterersLocked" (onUnlock)="metadata.letterersLocked = false"
|
[(locked)]="metadata.lettererLocked" (onUnlock)="metadata.lettererLocked = false"
|
||||||
(newItemAdded)="metadata.letterersLocked = true" (selectedData)="metadata.letterersLocked = true">
|
(newItemAdded)="metadata.lettererLocked = true" (selectedData)="metadata.lettererLocked = true">
|
||||||
<ng-template #badgeItem let-item let-position="idx">
|
<ng-template #badgeItem let-item let-position="idx">
|
||||||
{{item.name}}
|
{{item.name}}
|
||||||
</ng-template>
|
</ng-template>
|
||||||
@ -266,8 +266,8 @@
|
|||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="inker" class="form-label">{{t('inker-label')}}</label>
|
<label for="inker" class="form-label">{{t('inker-label')}}</label>
|
||||||
<app-typeahead (selectedData)="updatePerson($event, PersonRole.Inker)" [settings]="getPersonsSettings(PersonRole.Inker)"
|
<app-typeahead (selectedData)="updatePerson($event, PersonRole.Inker)" [settings]="getPersonsSettings(PersonRole.Inker)"
|
||||||
[(locked)]="metadata.inkersLocked" (onUnlock)="metadata.inkersLocked = false"
|
[(locked)]="metadata.inkerLocked" (onUnlock)="metadata.inkerLocked = false"
|
||||||
(newItemAdded)="metadata.inkersLocked = true" (selectedData)="metadata.inkersLocked = true">
|
(newItemAdded)="metadata.inkerLocked = true" (selectedData)="metadata.inkerLocked = true">
|
||||||
<ng-template #badgeItem let-item let-position="idx">
|
<ng-template #badgeItem let-item let-position="idx">
|
||||||
{{item.name}}
|
{{item.name}}
|
||||||
</ng-template>
|
</ng-template>
|
||||||
@ -284,8 +284,8 @@
|
|||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="editor" class="form-label">{{t('editor-label')}}</label>
|
<label for="editor" class="form-label">{{t('editor-label')}}</label>
|
||||||
<app-typeahead (selectedData)="updatePerson($event, PersonRole.Editor)" [settings]="getPersonsSettings(PersonRole.Editor)"
|
<app-typeahead (selectedData)="updatePerson($event, PersonRole.Editor)" [settings]="getPersonsSettings(PersonRole.Editor)"
|
||||||
[(locked)]="metadata.editorsLocked" (onUnlock)="metadata.editorsLocked = false"
|
[(locked)]="metadata.editorLocked" (onUnlock)="metadata.editorLocked = false"
|
||||||
(newItemAdded)="metadata.editorsLocked = true" (selectedData)="metadata.editorsLocked = true">
|
(newItemAdded)="metadata.editorLocked = true" (selectedData)="metadata.editorLocked = true">
|
||||||
<ng-template #badgeItem let-item let-position="idx">
|
<ng-template #badgeItem let-item let-position="idx">
|
||||||
{{item.name}}
|
{{item.name}}
|
||||||
</ng-template>
|
</ng-template>
|
||||||
@ -299,8 +299,8 @@
|
|||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="colorist" class="form-label">{{t('colorist-label')}}</label>
|
<label for="colorist" class="form-label">{{t('colorist-label')}}</label>
|
||||||
<app-typeahead (selectedData)="updatePerson($event, PersonRole.Colorist)" [settings]="getPersonsSettings(PersonRole.Colorist)"
|
<app-typeahead (selectedData)="updatePerson($event, PersonRole.Colorist)" [settings]="getPersonsSettings(PersonRole.Colorist)"
|
||||||
[(locked)]="metadata.coloristsLocked" (onUnlock)="metadata.coloristsLocked = false"
|
[(locked)]="metadata.coloristLocked" (onUnlock)="metadata.coloristLocked = false"
|
||||||
(newItemAdded)="metadata.coloristsLocked = true" (selectedData)="metadata.coloristsLocked = true">
|
(newItemAdded)="metadata.coloristLocked = true" (selectedData)="metadata.coloristLocked = true">
|
||||||
<ng-template #badgeItem let-item let-position="idx">
|
<ng-template #badgeItem let-item let-position="idx">
|
||||||
{{item.name}}
|
{{item.name}}
|
||||||
</ng-template>
|
</ng-template>
|
||||||
@ -317,8 +317,8 @@
|
|||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="character" class="form-label">{{t('character-label')}}</label>
|
<label for="character" class="form-label">{{t('character-label')}}</label>
|
||||||
<app-typeahead (selectedData)="updatePerson($event, PersonRole.Character)" [settings]="getPersonsSettings(PersonRole.Character)"
|
<app-typeahead (selectedData)="updatePerson($event, PersonRole.Character)" [settings]="getPersonsSettings(PersonRole.Character)"
|
||||||
[(locked)]="metadata.charactersLocked" (onUnlock)="metadata.charactersLocked = false"
|
[(locked)]="metadata.characterLocked" (onUnlock)="metadata.characterLocked = false"
|
||||||
(newItemAdded)="metadata.charactersLocked = true" (selectedData)="metadata.charactersLocked = true">
|
(newItemAdded)="metadata.characterLocked = true" (selectedData)="metadata.characterLocked = true">
|
||||||
<ng-template #badgeItem let-item let-position="idx">
|
<ng-template #badgeItem let-item let-position="idx">
|
||||||
{{item.name}}
|
{{item.name}}
|
||||||
</ng-template>
|
</ng-template>
|
||||||
@ -332,8 +332,8 @@
|
|||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="translator" class="form-label">{{t('translator-label')}}</label>
|
<label for="translator" class="form-label">{{t('translator-label')}}</label>
|
||||||
<app-typeahead (selectedData)="updatePerson($event, PersonRole.Translator)" [settings]="getPersonsSettings(PersonRole.Translator)"
|
<app-typeahead (selectedData)="updatePerson($event, PersonRole.Translator)" [settings]="getPersonsSettings(PersonRole.Translator)"
|
||||||
[(locked)]="metadata.translatorsLocked" (onUnlock)="metadata.translatorsLocked = false"
|
[(locked)]="metadata.translatorLocked" (onUnlock)="metadata.translatorLocked = false"
|
||||||
(newItemAdded)="metadata.translatorsLocked = true" (selectedData)="metadata.translatorsLocked = true">
|
(newItemAdded)="metadata.translatorLocked = true" (selectedData)="metadata.translatorLocked = true">
|
||||||
<ng-template #badgeItem let-item let-position="idx">
|
<ng-template #badgeItem let-item let-position="idx">
|
||||||
{{item.name}}
|
{{item.name}}
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
@ -4,6 +4,7 @@ import {ImageComponent} from "../../shared/image/image.component";
|
|||||||
import {NextExpectedChapter} from "../../_models/series-detail/next-expected-chapter";
|
import {NextExpectedChapter} from "../../_models/series-detail/next-expected-chapter";
|
||||||
import {UtcToLocalTimePipe} from "../../_pipes/utc-to-local-time.pipe";
|
import {UtcToLocalTimePipe} from "../../_pipes/utc-to-local-time.pipe";
|
||||||
import {SafeHtmlPipe} from "../../_pipes/safe-html.pipe";
|
import {SafeHtmlPipe} from "../../_pipes/safe-html.pipe";
|
||||||
|
import {translate} from "@ngneat/transloco";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-next-expected-card',
|
selector: 'app-next-expected-card',
|
||||||
@ -39,7 +40,7 @@ export class NextExpectedCardComponent {
|
|||||||
|
|
||||||
if (this.entity.expectedDate) {
|
if (this.entity.expectedDate) {
|
||||||
const utcPipe = new UtcToLocalTimePipe();
|
const utcPipe = new UtcToLocalTimePipe();
|
||||||
this.title = '~ ' + utcPipe.transform(this.entity.expectedDate, 'shortDate');
|
this.title = translate('next-expected-card.title', {date: utcPipe.transform(this.entity.expectedDate, 'shortDate')});
|
||||||
}
|
}
|
||||||
this.cdRef.markForCheck();
|
this.cdRef.markForCheck();
|
||||||
}
|
}
|
||||||
|
@ -83,7 +83,7 @@ export class ReadingListDetailComponent implements OnInit {
|
|||||||
this.router.navigateByUrl('/home');
|
this.router.navigateByUrl('/home');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.titleService.setTitle('Kavita - ' + translate('side-nav.reading-lists'));
|
|
||||||
this.listId = parseInt(listId, 10);
|
this.listId = parseInt(listId, 10);
|
||||||
this.characters$ = this.readingListService.getCharacters(this.listId);
|
this.characters$ = this.readingListService.getCharacters(this.listId);
|
||||||
|
|
||||||
@ -94,6 +94,8 @@ export class ReadingListDetailComponent implements OnInit {
|
|||||||
const libraries = results[0];
|
const libraries = results[0];
|
||||||
const readingList = results[1];
|
const readingList = results[1];
|
||||||
|
|
||||||
|
this.titleService.setTitle('Kavita - ' + readingList.title);
|
||||||
|
|
||||||
libraries.forEach(lib => {
|
libraries.forEach(lib => {
|
||||||
this.libraryTypes[lib.id] = lib.type;
|
this.libraryTypes[lib.id] = lib.type;
|
||||||
});
|
});
|
||||||
|
@ -17,9 +17,9 @@ import { CardItemComponent } from '../../../cards/card-item/card-item.component'
|
|||||||
import { CardDetailLayoutComponent } from '../../../cards/card-detail-layout/card-detail-layout.component';
|
import { CardDetailLayoutComponent } from '../../../cards/card-detail-layout/card-detail-layout.component';
|
||||||
import { NgIf, DecimalPipe } from '@angular/common';
|
import { NgIf, DecimalPipe } from '@angular/common';
|
||||||
import { SideNavCompanionBarComponent } from '../../../sidenav/_components/side-nav-companion-bar/side-nav-companion-bar.component';
|
import { SideNavCompanionBarComponent } from '../../../sidenav/_components/side-nav-companion-bar/side-nav-companion-bar.component';
|
||||||
import {TranslocoDirective, TranslocoService} from "@ngneat/transloco";
|
import {translate, TranslocoDirective, TranslocoService} from "@ngneat/transloco";
|
||||||
import {CardActionablesComponent} from "../../../_single-module/card-actionables/card-actionables.component";
|
import {CardActionablesComponent} from "../../../_single-module/card-actionables/card-actionables.component";
|
||||||
import {CollectionTag} from "../../../_models/collection-tag";
|
import {Title} from "@angular/platform-browser";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-reading-lists',
|
selector: 'app-reading-lists',
|
||||||
@ -43,13 +43,14 @@ export class ReadingListsComponent implements OnInit {
|
|||||||
translocoService = inject(TranslocoService);
|
translocoService = inject(TranslocoService);
|
||||||
constructor(private readingListService: ReadingListService, public imageService: ImageService, private actionFactoryService: ActionFactoryService,
|
constructor(private readingListService: ReadingListService, public imageService: ImageService, private actionFactoryService: ActionFactoryService,
|
||||||
private accountService: AccountService, private toastr: ToastrService, private router: Router, private actionService: ActionService,
|
private accountService: AccountService, private toastr: ToastrService, private router: Router, private actionService: ActionService,
|
||||||
private jumpbarService: JumpbarService, private readonly cdRef: ChangeDetectorRef, private ngbModal: NgbModal) { }
|
private jumpbarService: JumpbarService, private readonly cdRef: ChangeDetectorRef, private ngbModal: NgbModal, private titleService: Title) { }
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.accountService.currentUser$.pipe(take(1)).subscribe(user => {
|
this.accountService.currentUser$.pipe(take(1)).subscribe(user => {
|
||||||
if (user) {
|
if (user) {
|
||||||
this.isAdmin = this.accountService.hasAdminRole(user);
|
this.isAdmin = this.accountService.hasAdminRole(user);
|
||||||
this.loadPage();
|
this.loadPage();
|
||||||
|
this.titleService.setTitle('Kavita - ' + translate('side-nav.reading-lists'));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -64,7 +64,7 @@ export class ImportCblModalComponent {
|
|||||||
{title: this.translocoService.translate('import-cbl-modal.import-step'), index: Step.Import, active: true, icon: 'fa-solid fa-file-arrow-up'},
|
{title: this.translocoService.translate('import-cbl-modal.import-step'), index: Step.Import, active: true, icon: 'fa-solid fa-file-arrow-up'},
|
||||||
{title: this.translocoService.translate('import-cbl-modal.validate-cbl-step'), index: Step.Validate, active: false, icon: 'fa-solid fa-spell-check'},
|
{title: this.translocoService.translate('import-cbl-modal.validate-cbl-step'), index: Step.Validate, active: false, icon: 'fa-solid fa-spell-check'},
|
||||||
{title: this.translocoService.translate('import-cbl-modal.dry-run-step'), index: Step.DryRun, active: false, icon: 'fa-solid fa-gears'},
|
{title: this.translocoService.translate('import-cbl-modal.dry-run-step'), index: Step.DryRun, active: false, icon: 'fa-solid fa-gears'},
|
||||||
{title: this.translocoService.translate('import-cbl-final-import.import-step'), index: Step.Finalize, active: false, icon: 'fa-solid fa-floppy-disk'},
|
{title: this.translocoService.translate('import-cbl-modal.final-import-step'), index: Step.Finalize, active: false, icon: 'fa-solid fa-floppy-disk'},
|
||||||
];
|
];
|
||||||
currentStepIndex = this.steps[0].index;
|
currentStepIndex = this.steps[0].index;
|
||||||
|
|
||||||
|
@ -80,7 +80,7 @@
|
|||||||
<p *ngIf="isAddLibrary" class="alert alert-secondary" role="alert">{{t('cover-description')}}</p>
|
<p *ngIf="isAddLibrary" class="alert alert-secondary" role="alert">{{t('cover-description')}}</p>
|
||||||
<p>{{t('cover-description-extra')}}</p>
|
<p>{{t('cover-description-extra')}}</p>
|
||||||
<app-cover-image-chooser [(imageUrls)]="imageUrls" (imageSelected)="updateCoverImageIndex($event)"
|
<app-cover-image-chooser [(imageUrls)]="imageUrls" (imageSelected)="updateCoverImageIndex($event)"
|
||||||
(selectedBase64Url)="applyCoverImage($event)" [showReset]="library.coverImage !== null"
|
(selectedBase64Url)="applyCoverImage($event)" [showReset]="library?.coverImage !== null"
|
||||||
(resetClicked)="resetCoverImage()"></app-cover-image-chooser>
|
(resetClicked)="resetCoverImage()"></app-cover-image-chooser>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</li>
|
</li>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
.confirm-icon {
|
.confirm-icon {
|
||||||
color: var(--primary-color);
|
color: var(--primary-color);
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
margin-bottom: 10px;
|
vertical-align: middle;
|
||||||
}
|
}
|
@ -9,12 +9,14 @@
|
|||||||
<li *ngFor="let tab of tabs" [ngbNavItem]="tab">
|
<li *ngFor="let tab of tabs" [ngbNavItem]="tab">
|
||||||
<a ngbNavLink routerLink="." [fragment]="tab.fragment">{{ t(tab.title) }}</a>
|
<a ngbNavLink routerLink="." [fragment]="tab.fragment">{{ t(tab.title) }}</a>
|
||||||
<ng-template ngbNavContent>
|
<ng-template ngbNavContent>
|
||||||
<ng-container *ngIf="tab.fragment === FragmentID.Account">
|
@defer (when tab.fragment === FragmentID.Account; prefetch on idle) {
|
||||||
<app-change-email></app-change-email>
|
<app-change-email></app-change-email>
|
||||||
<app-change-password></app-change-password>
|
<app-change-password></app-change-password>
|
||||||
<app-change-age-restriction></app-change-age-restriction>
|
<app-change-age-restriction></app-change-age-restriction>
|
||||||
<app-anilist-key></app-anilist-key>
|
<app-anilist-key></app-anilist-key>
|
||||||
</ng-container>
|
}
|
||||||
|
|
||||||
|
@defer (when tab.fragment === FragmentID.Preferences; prefetch on idle) {
|
||||||
<ng-container *ngIf="tab.fragment === FragmentID.Preferences">
|
<ng-container *ngIf="tab.fragment === FragmentID.Preferences">
|
||||||
<p>
|
<p>
|
||||||
{{t('pref-description')}}
|
{{t('pref-description')}}
|
||||||
@ -411,34 +413,32 @@
|
|||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
<ng-container *ngIf="tab.fragment === FragmentID.Clients">
|
|
||||||
|
@defer (when tab.fragment === FragmentID.Clients; prefetch on idle) {
|
||||||
<div class="alert alert-warning" role="alert" *ngIf="!opdsEnabled">{{t('clients-opds-alert')}}</div>
|
<div class="alert alert-warning" role="alert" *ngIf="!opdsEnabled">{{t('clients-opds-alert')}}</div>
|
||||||
<p>{{t('clients-opds-description')}}</p>
|
<p>{{t('clients-opds-description')}}</p>
|
||||||
<app-api-key [tooltipText]="t('clients-api-key-tooltip')" [hideData]="true"></app-api-key>
|
<app-api-key [tooltipText]="t('clients-api-key-tooltip')" [hideData]="true"></app-api-key>
|
||||||
<app-api-key [title]="t('clients-opds-url-tooltip')" [hideData]="true" [showRefresh]="false" [transform]="makeUrl"></app-api-key>
|
<app-api-key [title]="t('clients-opds-url-tooltip')" [hideData]="true" [showRefresh]="false" [transform]="makeUrl"></app-api-key>
|
||||||
</ng-container>
|
}
|
||||||
<!-- @defer (when tab.fragment === FragmentID.Theme; prefetch on idle) {-->
|
@defer (when tab.fragment === FragmentID.Theme; prefetch on idle) {
|
||||||
<!-- <app-theme-manager></app-theme-manager>-->
|
|
||||||
<!-- }-->
|
|
||||||
<!-- @placeholder {-->
|
|
||||||
<!-- <app-loading [loading]="true"></app-loading>-->
|
|
||||||
<!-- }-->
|
|
||||||
<ng-container *ngIf="tab.fragment === FragmentID.Theme">
|
|
||||||
<app-theme-manager></app-theme-manager>
|
<app-theme-manager></app-theme-manager>
|
||||||
</ng-container>
|
}
|
||||||
|
|
||||||
<ng-container *ngIf="tab.fragment === FragmentID.Devices">
|
@defer (when tab.fragment === FragmentID.Devices; prefetch on idle) {
|
||||||
<app-manage-devices></app-manage-devices>
|
<app-manage-devices></app-manage-devices>
|
||||||
</ng-container>
|
}
|
||||||
<ng-container *ngIf="tab.fragment === FragmentID.Stats">
|
|
||||||
|
@defer (when tab.fragment === FragmentID.Stats; prefetch on idle) {
|
||||||
<app-user-stats></app-user-stats>
|
<app-user-stats></app-user-stats>
|
||||||
</ng-container>
|
}
|
||||||
<ng-container *ngIf="tab.fragment === FragmentID.Scrobbling">
|
|
||||||
|
@defer (when tab.fragment === FragmentID.Scrobbling; prefetch on idle) {
|
||||||
<app-user-scrobble-history></app-user-scrobble-history>
|
<app-user-scrobble-history></app-user-scrobble-history>
|
||||||
<app-user-holds></app-user-holds>
|
<app-user-holds></app-user-holds>
|
||||||
</ng-container>
|
}
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -49,11 +49,6 @@ import { SideNavCompanionBarComponent } from '../../sidenav/_components/side-nav
|
|||||||
import {LocalizationService} from "../../_services/localization.service";
|
import {LocalizationService} from "../../_services/localization.service";
|
||||||
import {Language} from "../../_models/metadata/language";
|
import {Language} from "../../_models/metadata/language";
|
||||||
import {translate, TranslocoDirective} from "@ngneat/transloco";
|
import {translate, TranslocoDirective} from "@ngneat/transloco";
|
||||||
import {
|
|
||||||
provideTranslocoPersistTranslations,
|
|
||||||
TranslocoPersistTranslations
|
|
||||||
} from "@ngneat/transloco-persist-translations";
|
|
||||||
import {HttpLoader} from "../../../httpLoader";
|
|
||||||
import {LoadingComponent} from "../../shared/loading/loading.component";
|
import {LoadingComponent} from "../../shared/loading/loading.component";
|
||||||
|
|
||||||
enum AccordionPanelID {
|
enum AccordionPanelID {
|
||||||
@ -333,4 +328,6 @@ export class UserPreferencesComponent implements OnInit, OnDestroy {
|
|||||||
d.text = translate('preferences.' + o.text);
|
d.text = translate('preferences.' + o.text);
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected readonly undefined = undefined;
|
||||||
}
|
}
|
||||||
|
@ -1707,6 +1707,10 @@
|
|||||||
"add-to-want-to-read": "{{actionable.add-to-want-to-read}}"
|
"add-to-want-to-read": "{{actionable.add-to-want-to-read}}"
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"next-expected-card": {
|
||||||
|
"title": "~{{date}}"
|
||||||
|
},
|
||||||
|
|
||||||
"server-stats": {
|
"server-stats": {
|
||||||
"total-series-label": "Total Series",
|
"total-series-label": "Total Series",
|
||||||
"total-series-tooltip": "Total Series: {{count}}",
|
"total-series-tooltip": "Total Series: {{count}}",
|
||||||
|
20
openapi.json
20
openapi.json
@ -17860,34 +17860,34 @@
|
|||||||
"tagsLocked": {
|
"tagsLocked": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
"writersLocked": {
|
"writerLocked": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
"charactersLocked": {
|
"characterLocked": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
"coloristsLocked": {
|
"coloristLocked": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
"editorsLocked": {
|
"editorLocked": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
"inkersLocked": {
|
"inkerLocked": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
"letterersLocked": {
|
"lettererLocked": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
"pencillersLocked": {
|
"pencillerLocked": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
"publishersLocked": {
|
"publisherLocked": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
"translatorsLocked": {
|
"translatorLocked": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
"coverArtistsLocked": {
|
"coverArtistLocked": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
"releaseYearLocked": {
|
"releaseYearLocked": {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user