Reworked some of the logic to be less round trips to db.
Fixed a localization "off" issue. Don't allow users to rename the Default Reading Profile.
This commit is contained in:
parent
82f557490a
commit
29c29976f1
9 changed files with 112 additions and 79 deletions
|
|
@ -15,6 +15,7 @@ using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace API.Controllers;
|
namespace API.Controllers;
|
||||||
|
|
||||||
|
[Route("api/reading-profile")]
|
||||||
public class ReadingProfileController(ILogger<ReadingProfileController> logger, IUnitOfWork unitOfWork,
|
public class ReadingProfileController(ILogger<ReadingProfileController> logger, IUnitOfWork unitOfWork,
|
||||||
IReadingProfileService readingProfileService): BaseApiController
|
IReadingProfileService readingProfileService): BaseApiController
|
||||||
{
|
{
|
||||||
|
|
@ -26,8 +27,7 @@ public class ReadingProfileController(ILogger<ReadingProfileController> logger,
|
||||||
[HttpGet("all")]
|
[HttpGet("all")]
|
||||||
public async Task<ActionResult<IList<UserReadingProfileDto>>> GetAllReadingProfiles()
|
public async Task<ActionResult<IList<UserReadingProfileDto>>> GetAllReadingProfiles()
|
||||||
{
|
{
|
||||||
var profiles = await unitOfWork.AppUserReadingProfileRepository.GetProfilesDtoForUser(User.GetUserId());
|
return Ok(await unitOfWork.AppUserReadingProfileRepository.GetProfilesDtoForUser(User.GetUserId(), true));
|
||||||
return Ok(profiles);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -95,16 +95,14 @@ public class ReadingProfileController(ILogger<ReadingProfileController> logger,
|
||||||
/// Updates the given reading profile, must belong to the current user
|
/// Updates the given reading profile, must belong to the current user
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="dto"></param>
|
/// <param name="dto"></param>
|
||||||
/// <returns></returns>
|
/// <returns>The updated reading profile</returns>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// This does not update connected series, and libraries.
|
/// This does not update connected series and libraries.
|
||||||
/// Deletes all implicit profiles for series linked to this profile
|
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public async Task<ActionResult<UserReadingProfileDto>> UpdateReadingProfile([FromBody] UserReadingProfileDto dto)
|
public async Task<ActionResult<UserReadingProfileDto>> UpdateReadingProfile(UserReadingProfileDto dto)
|
||||||
{
|
{
|
||||||
var newProfile = await readingProfileService.UpdateReadingProfile(User.GetUserId(), dto);
|
return Ok(await readingProfileService.UpdateReadingProfile(User.GetUserId(), dto));
|
||||||
return Ok(newProfile);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
||||||
|
|
@ -29,20 +29,20 @@ public interface IAppUserReadingProfileRepository
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="userId"></param>
|
/// <param name="userId"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<IList<AppUserReadingProfile>> GetProfilesForUser(int userId);
|
Task<IList<AppUserReadingProfile>> GetProfilesForUser(int userId, bool skipImplicit = false);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns all non-implicit reading profiles for the user
|
/// Returns all reading profiles for the user
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="userId"></param>
|
/// <param name="userId"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<IList<UserReadingProfileDto>> GetProfilesDtoForUser(int userId);
|
Task<IList<UserReadingProfileDto>> GetProfilesDtoForUser(int userId, bool skipImplicit = false);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Find a profile by name, belonging to a specific user
|
/// Is there a user reading profile with this name (normalized)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="userId"></param>
|
/// <param name="userId"></param>
|
||||||
/// <param name="name"></param>
|
/// <param name="name"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<AppUserReadingProfile?> GetProfileByName(int userId, string name);
|
Task<bool> IsProfileNameInUse(int userId, string name);
|
||||||
|
|
||||||
void Add(AppUserReadingProfile readingProfile);
|
void Add(AppUserReadingProfile readingProfile);
|
||||||
void Update(AppUserReadingProfile readingProfile);
|
void Update(AppUserReadingProfile readingProfile);
|
||||||
|
|
@ -59,29 +59,35 @@ public class AppUserReadingProfileRepository(DataContext context, IMapper mapper
|
||||||
.FirstOrDefaultAsync();
|
.FirstOrDefaultAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<IList<AppUserReadingProfile>> GetProfilesForUser(int userId)
|
public async Task<IList<AppUserReadingProfile>> GetProfilesForUser(int userId, bool skipImplicit = false)
|
||||||
{
|
{
|
||||||
return await context.AppUserReadingProfiles
|
return await context.AppUserReadingProfiles
|
||||||
.Where(rp => rp.AppUserId == userId)
|
.Where(rp => rp.AppUserId == userId)
|
||||||
|
.WhereIf(skipImplicit, rp => rp.Kind != ReadingProfileKind.Implicit)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<IList<UserReadingProfileDto>> GetProfilesDtoForUser(int userId)
|
/// <summary>
|
||||||
|
/// Returns all Reading Profiles for the User
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="userId"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<IList<UserReadingProfileDto>> GetProfilesDtoForUser(int userId, bool skipImplicit = false)
|
||||||
{
|
{
|
||||||
return await context.AppUserReadingProfiles
|
return await context.AppUserReadingProfiles
|
||||||
.Where(rp => rp.AppUserId == userId)
|
.Where(rp => rp.AppUserId == userId)
|
||||||
.Where(rp => rp.Kind !=ReadingProfileKind.Implicit)
|
.WhereIf(skipImplicit, rp => rp.Kind != ReadingProfileKind.Implicit)
|
||||||
.ProjectTo<UserReadingProfileDto>(mapper.ConfigurationProvider)
|
.ProjectTo<UserReadingProfileDto>(mapper.ConfigurationProvider)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<AppUserReadingProfile?> GetProfileByName(int userId, string name)
|
public async Task<bool> IsProfileNameInUse(int userId, string name)
|
||||||
{
|
{
|
||||||
var normalizedName = name.ToNormalized();
|
var normalizedName = name.ToNormalized();
|
||||||
|
|
||||||
return await context.AppUserReadingProfiles
|
return await context.AppUserReadingProfiles
|
||||||
.Where(rp => rp.NormalizedName == normalizedName && rp.AppUserId == userId)
|
.Where(rp => rp.NormalizedName == normalizedName && rp.AppUserId == userId)
|
||||||
.FirstOrDefaultAsync();
|
.AnyAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Add(AppUserReadingProfile readingProfile)
|
public void Add(AppUserReadingProfile readingProfile)
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ public enum ReadingProfileKind
|
||||||
/// </summary>
|
/// </summary>
|
||||||
User,
|
User,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Automatically generated by Kavita to tracked changes made in the readers
|
/// Automatically generated by Kavita to track changes made in the readers. Can be converted to a User Reading Profile.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Implicit
|
Implicit
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,13 +33,6 @@ public interface IReadingProfileService
|
||||||
/// <param name="dto"></param>
|
/// <param name="dto"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<UserReadingProfileDto> CreateReadingProfile(int userId, UserReadingProfileDto dto);
|
Task<UserReadingProfileDto> CreateReadingProfile(int userId, UserReadingProfileDto dto);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Promotes the implicit profile to a user profile. Removes the series from other profiles
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="userId"></param>
|
|
||||||
/// <param name="profileId"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
Task<UserReadingProfileDto> PromoteImplicitProfile(int userId, int profileId);
|
Task<UserReadingProfileDto> PromoteImplicitProfile(int userId, int profileId);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -123,22 +116,18 @@ public interface IReadingProfileService
|
||||||
|
|
||||||
public class ReadingProfileService(IUnitOfWork unitOfWork, ILocalizationService localizationService, IMapper mapper): IReadingProfileService
|
public class ReadingProfileService(IUnitOfWork unitOfWork, ILocalizationService localizationService, IMapper mapper): IReadingProfileService
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
public async Task<UserReadingProfileDto> GetReadingProfileDtoForSeries(int userId, int seriesId, bool skipImplicit = false)
|
/// Tries to resolve the Reading Profile for a given Series. Will first check (optionally) Implicit profiles, then check for a bound Series profile, then a bound
|
||||||
{
|
/// Library profile, then default to the default profile.
|
||||||
return mapper.Map<UserReadingProfileDto>(await GetReadingProfileForSeries(userId, seriesId, skipImplicit));
|
/// </summary>
|
||||||
}
|
/// <param name="userId"></param>
|
||||||
|
/// <param name="seriesId"></param>
|
||||||
|
/// <param name="skipImplicit"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
/// <exception cref="KavitaException"></exception>
|
||||||
public async Task<AppUserReadingProfile> GetReadingProfileForSeries(int userId, int seriesId, bool skipImplicit = false)
|
public async Task<AppUserReadingProfile> GetReadingProfileForSeries(int userId, int seriesId, bool skipImplicit = false)
|
||||||
{
|
{
|
||||||
var profiles = await unitOfWork.AppUserReadingProfileRepository.GetProfilesForUser(userId);
|
var profiles = await unitOfWork.AppUserReadingProfileRepository.GetProfilesForUser(userId, skipImplicit);
|
||||||
|
|
||||||
if (!skipImplicit)
|
|
||||||
{
|
|
||||||
var implicitSeriesProfile = profiles
|
|
||||||
.FirstOrDefault(p => p.SeriesIds.Contains(seriesId) && p.Kind == ReadingProfileKind.Implicit);
|
|
||||||
if (implicitSeriesProfile != null) return implicitSeriesProfile;
|
|
||||||
}
|
|
||||||
|
|
||||||
var seriesProfile = profiles
|
var seriesProfile = profiles
|
||||||
.FirstOrDefault(p => p.SeriesIds.Contains(seriesId) && p.Kind != ReadingProfileKind.Implicit);
|
.FirstOrDefault(p => p.SeriesIds.Contains(seriesId) && p.Kind != ReadingProfileKind.Implicit);
|
||||||
|
|
@ -155,6 +144,11 @@ public class ReadingProfileService(IUnitOfWork unitOfWork, ILocalizationService
|
||||||
return profiles.First(p => p.Kind == ReadingProfileKind.Default);
|
return profiles.First(p => p.Kind == ReadingProfileKind.Default);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<UserReadingProfileDto> GetReadingProfileDtoForSeries(int userId, int seriesId, bool skipImplicit = false)
|
||||||
|
{
|
||||||
|
return mapper.Map<UserReadingProfileDto>(await GetReadingProfileForSeries(userId, seriesId, skipImplicit));
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<UserReadingProfileDto> UpdateParent(int userId, int seriesId, UserReadingProfileDto dto)
|
public async Task<UserReadingProfileDto> UpdateParent(int userId, int seriesId, UserReadingProfileDto dto)
|
||||||
{
|
{
|
||||||
var parentProfile = await GetReadingProfileForSeries(userId, seriesId, true);
|
var parentProfile = await GetReadingProfileForSeries(userId, seriesId, true);
|
||||||
|
|
@ -176,8 +170,6 @@ public class ReadingProfileService(IUnitOfWork unitOfWork, ILocalizationService
|
||||||
UpdateReaderProfileFields(profile, dto);
|
UpdateReaderProfileFields(profile, dto);
|
||||||
unitOfWork.AppUserReadingProfileRepository.Update(profile);
|
unitOfWork.AppUserReadingProfileRepository.Update(profile);
|
||||||
|
|
||||||
// await DeleteImplicateReadingProfilesForSeries(userId, profile.SeriesIds);
|
|
||||||
|
|
||||||
await unitOfWork.CommitAsync();
|
await unitOfWork.CommitAsync();
|
||||||
return mapper.Map<UserReadingProfileDto>(profile);
|
return mapper.Map<UserReadingProfileDto>(profile);
|
||||||
}
|
}
|
||||||
|
|
@ -187,11 +179,11 @@ public class ReadingProfileService(IUnitOfWork unitOfWork, ILocalizationService
|
||||||
var user = await unitOfWork.UserRepository.GetUserByIdAsync(userId, AppUserIncludes.UserPreferences);
|
var user = await unitOfWork.UserRepository.GetUserByIdAsync(userId, AppUserIncludes.UserPreferences);
|
||||||
if (user == null) throw new UnauthorizedAccessException();
|
if (user == null) throw new UnauthorizedAccessException();
|
||||||
|
|
||||||
var other = await unitOfWork.AppUserReadingProfileRepository.GetProfileByName(userId, dto.Name);
|
if (await unitOfWork.AppUserReadingProfileRepository.IsProfileNameInUse(userId, dto.Name)) throw new KavitaException("name-already-in-use");
|
||||||
if (other != null) throw new KavitaException("name-already-in-use");
|
|
||||||
|
|
||||||
var newProfile = new AppUserReadingProfileBuilder(user.Id).Build();
|
var newProfile = new AppUserReadingProfileBuilder(user.Id).Build();
|
||||||
UpdateReaderProfileFields(newProfile, dto);
|
UpdateReaderProfileFields(newProfile, dto);
|
||||||
|
|
||||||
unitOfWork.AppUserReadingProfileRepository.Add(newProfile);
|
unitOfWork.AppUserReadingProfileRepository.Add(newProfile);
|
||||||
user.ReadingProfiles.Add(newProfile);
|
user.ReadingProfiles.Add(newProfile);
|
||||||
|
|
||||||
|
|
@ -200,27 +192,61 @@ public class ReadingProfileService(IUnitOfWork unitOfWork, ILocalizationService
|
||||||
return mapper.Map<UserReadingProfileDto>(newProfile);
|
return mapper.Map<UserReadingProfileDto>(newProfile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Promotes the implicit profile to a user profile. Removes the series from other profiles.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="userId"></param>
|
||||||
|
/// <param name="profileId"></param>
|
||||||
|
/// <returns></returns>
|
||||||
public async Task<UserReadingProfileDto> PromoteImplicitProfile(int userId, int profileId)
|
public async Task<UserReadingProfileDto> PromoteImplicitProfile(int userId, int profileId)
|
||||||
{
|
{
|
||||||
var profile = await unitOfWork.AppUserReadingProfileRepository.GetUserProfile(userId, profileId);
|
|
||||||
if (profile == null) throw new KavitaException("profile-does-not-exist");
|
|
||||||
|
|
||||||
if (profile.Kind != ReadingProfileKind.Implicit) throw new KavitaException("cannot-promote-non-implicit-profile");
|
// Get all the user's profiles including the implicit
|
||||||
|
var allUserProfiles = await unitOfWork.AppUserReadingProfileRepository.GetProfilesForUser(userId, false);
|
||||||
|
var profileToPromote = allUserProfiles.First(r => r.Id == profileId);
|
||||||
|
var seriesId = profileToPromote.SeriesIds[0]; // An Implicit series can only be bound to 1 Series
|
||||||
|
|
||||||
// Implicit profiles are only bound to one profile
|
// Check if there are any reading profiles (Series) already bound to the series
|
||||||
var series = await unitOfWork.SeriesRepository.GetSeriesByIdAsync(profile.SeriesIds[0]);
|
var existingSeriesProfile = allUserProfiles.FirstOrDefault(r => r.SeriesIds.Contains(seriesId) && r.Kind == ReadingProfileKind.User);
|
||||||
|
if (existingSeriesProfile != null)
|
||||||
|
{
|
||||||
|
existingSeriesProfile.SeriesIds.Remove(seriesId);
|
||||||
|
unitOfWork.AppUserReadingProfileRepository.Update(existingSeriesProfile);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert the implicit profile into a proper Series
|
||||||
|
var series = await unitOfWork.SeriesRepository.GetSeriesByIdAsync(seriesId);
|
||||||
if (series == null) throw new KavitaException("series-doesnt-exist"); // Shouldn't happen
|
if (series == null) throw new KavitaException("series-doesnt-exist"); // Shouldn't happen
|
||||||
|
|
||||||
await RemoveSeriesFromUserProfiles(userId, [series.Id]);
|
profileToPromote.Kind = ReadingProfileKind.User;
|
||||||
|
profileToPromote.Name = await localizationService.Translate(userId, "generated-reading-profile-name", series.Name);
|
||||||
|
profileToPromote.NormalizedName = profileToPromote.Name.ToNormalized();
|
||||||
|
unitOfWork.AppUserReadingProfileRepository.Update(profileToPromote);
|
||||||
|
|
||||||
profile.Kind = ReadingProfileKind.User;
|
|
||||||
profile.Name = await localizationService.Translate(userId, "generated-reading-profile-name", series.Name);
|
|
||||||
profile.NormalizedName = profile.Name.ToNormalized();
|
|
||||||
|
|
||||||
unitOfWork.AppUserReadingProfileRepository.Update(profile);
|
|
||||||
await unitOfWork.CommitAsync();
|
await unitOfWork.CommitAsync();
|
||||||
|
|
||||||
return mapper.Map<UserReadingProfileDto>(profile);
|
return mapper.Map<UserReadingProfileDto>(profileToPromote);
|
||||||
|
|
||||||
|
|
||||||
|
// var profile = await unitOfWork.AppUserReadingProfileRepository.GetUserProfile(userId, profileId);
|
||||||
|
// if (profile == null) throw new KavitaException("profile-does-not-exist");
|
||||||
|
//
|
||||||
|
// if (profile.Kind != ReadingProfileKind.Implicit) throw new KavitaException("cannot-promote-non-implicit-profile");
|
||||||
|
//
|
||||||
|
// // Implicit profiles are only bound to one profile
|
||||||
|
// var series = await unitOfWork.SeriesRepository.GetSeriesByIdAsync(profile.SeriesIds[0]);
|
||||||
|
// if (series == null) throw new KavitaException("series-doesnt-exist"); // Shouldn't happen
|
||||||
|
//
|
||||||
|
// await RemoveSeriesFromUserProfiles(userId, [series.Id]);
|
||||||
|
//
|
||||||
|
// profile.Kind = ReadingProfileKind.User;
|
||||||
|
// profile.Name = await localizationService.Translate(userId, "generated-reading-profile-name", series.Name);
|
||||||
|
// profile.NormalizedName = profile.Name.ToNormalized();
|
||||||
|
//
|
||||||
|
// unitOfWork.AppUserReadingProfileRepository.Update(profile);
|
||||||
|
// await unitOfWork.CommitAsync();
|
||||||
|
//
|
||||||
|
// return mapper.Map<UserReadingProfileDto>(profile);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<UserReadingProfileDto> UpdateImplicitReadingProfile(int userId, int seriesId, UserReadingProfileDto dto)
|
public async Task<UserReadingProfileDto> UpdateImplicitReadingProfile(int userId, int seriesId, UserReadingProfileDto dto)
|
||||||
|
|
@ -368,6 +394,7 @@ public class ReadingProfileService(IUnitOfWork unitOfWork, ILocalizationService
|
||||||
.Where(rp => rp.SeriesIds.Intersect(seriesIds).Any())
|
.Where(rp => rp.SeriesIds.Intersect(seriesIds).Any())
|
||||||
.Where(rp => rp.Kind == ReadingProfileKind.User)
|
.Where(rp => rp.Kind == ReadingProfileKind.User)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
unitOfWork.AppUserReadingProfileRepository.RemoveRange(userProfiles);
|
unitOfWork.AppUserReadingProfileRepository.RemoveRange(userProfiles);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { Injectable } from '@angular/core';
|
import {Injectable} from '@angular/core';
|
||||||
import {HttpClient} from "@angular/common/http";
|
import {HttpClient} from "@angular/common/http";
|
||||||
import {environment} from "../../environments/environment";
|
import {environment} from "../../environments/environment";
|
||||||
import {ReadingProfile} from "../_models/preferences/reading-profiles";
|
import {ReadingProfile} from "../_models/preferences/reading-profiles";
|
||||||
|
|
@ -17,51 +17,51 @@ export class ReadingProfileService {
|
||||||
}
|
}
|
||||||
|
|
||||||
updateProfile(profile: ReadingProfile) {
|
updateProfile(profile: ReadingProfile) {
|
||||||
return this.httpClient.post<ReadingProfile>(this.baseUrl + "ReadingProfile", profile);
|
return this.httpClient.post<ReadingProfile>(this.baseUrl + 'reading-profile', profile);
|
||||||
}
|
}
|
||||||
|
|
||||||
updateParentProfile(seriesId: number, profile: ReadingProfile) {
|
updateParentProfile(seriesId: number, profile: ReadingProfile) {
|
||||||
return this.httpClient.post<ReadingProfile>(this.baseUrl + `ReadingProfile/update-parent?seriesId=${seriesId}`, profile);
|
return this.httpClient.post<ReadingProfile>(this.baseUrl + `reading-profile/update-parent?seriesId=${seriesId}`, profile);
|
||||||
}
|
}
|
||||||
|
|
||||||
createProfile(profile: ReadingProfile) {
|
createProfile(profile: ReadingProfile) {
|
||||||
return this.httpClient.post<ReadingProfile>(this.baseUrl + "ReadingProfile/create", profile);
|
return this.httpClient.post<ReadingProfile>(this.baseUrl + 'reading-profile/create', profile);
|
||||||
}
|
}
|
||||||
|
|
||||||
promoteProfile(profileId: number) {
|
promoteProfile(profileId: number) {
|
||||||
return this.httpClient.post<ReadingProfile>(this.baseUrl + "ReadingProfile/promote?profileId=" + profileId, {});
|
return this.httpClient.post<ReadingProfile>(this.baseUrl + "reading-profile/promote?profileId=" + profileId, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
updateImplicit(profile: ReadingProfile, seriesId: number) {
|
updateImplicit(profile: ReadingProfile, seriesId: number) {
|
||||||
return this.httpClient.post<ReadingProfile>(this.baseUrl + "ReadingProfile/series?seriesId="+seriesId, profile);
|
return this.httpClient.post<ReadingProfile>(this.baseUrl + "reading-profile/series?seriesId="+seriesId, profile);
|
||||||
}
|
}
|
||||||
|
|
||||||
all() {
|
all() {
|
||||||
return this.httpClient.get<ReadingProfile[]>(this.baseUrl + "ReadingProfile/all");
|
return this.httpClient.get<ReadingProfile[]>(this.baseUrl + 'reading-profile/all');
|
||||||
}
|
}
|
||||||
|
|
||||||
delete(id: number) {
|
delete(id: number) {
|
||||||
return this.httpClient.delete(this.baseUrl + "ReadingProfile?profileId="+id);
|
return this.httpClient.delete(this.baseUrl + `reading-profile?profileId=${id}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
addToSeries(id: number, seriesId: number) {
|
addToSeries(id: number, seriesId: number) {
|
||||||
return this.httpClient.post(this.baseUrl + `ReadingProfile/series/${seriesId}?profileId=${id}`, {});
|
return this.httpClient.post(this.baseUrl + `reading-profile/series/${seriesId}?profileId=${id}`, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
clearSeriesProfiles(seriesId: number) {
|
clearSeriesProfiles(seriesId: number) {
|
||||||
return this.httpClient.delete(this.baseUrl + `ReadingProfile/series/${seriesId}`, {});
|
return this.httpClient.delete(this.baseUrl + `reading-profile/series/${seriesId}`, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
addToLibrary(id: number, libraryId: number) {
|
addToLibrary(id: number, libraryId: number) {
|
||||||
return this.httpClient.post(this.baseUrl + `ReadingProfile/library/${libraryId}?profileId=${id}`, {});
|
return this.httpClient.post(this.baseUrl + `reading-profile/library/${libraryId}?profileId=${id}`, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
clearLibraryProfiles(libraryId: number) {
|
clearLibraryProfiles(libraryId: number) {
|
||||||
return this.httpClient.delete(this.baseUrl + `ReadingProfile/library/${libraryId}`, {});
|
return this.httpClient.delete(this.baseUrl + `reading-profile/library/${libraryId}`, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
bulkAddToSeries(id: number, seriesIds: number[]) {
|
bulkAddToSeries(id: number, seriesIds: number[]) {
|
||||||
return this.httpClient.post(this.baseUrl + `ReadingProfile/bulk?profileId=${id}`, seriesIds);
|
return this.httpClient.post(this.baseUrl + `reading-profile/bulk?profileId=${id}`, seriesIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -432,8 +432,9 @@ export class ReaderSettingsComponent implements OnInit {
|
||||||
this.readingProfileService.promoteProfile(this.readingProfile.id).subscribe(newProfile => {
|
this.readingProfileService.promoteProfile(this.readingProfile.id).subscribe(newProfile => {
|
||||||
this.readingProfile = newProfile;
|
this.readingProfile = newProfile;
|
||||||
this.parentReadingProfile = newProfile; // profile is no longer implicit
|
this.parentReadingProfile = newProfile; // profile is no longer implicit
|
||||||
this.toastr.success(translate("manga-reader.reading-profile-promoted"));
|
|
||||||
this.cdRef.markForCheck();
|
this.cdRef.markForCheck();
|
||||||
|
|
||||||
|
this.toastr.success(translate("manga-reader.reading-profile-promoted"));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -44,19 +44,20 @@
|
||||||
<form [formGroup]="readingProfileForm">
|
<form [formGroup]="readingProfileForm">
|
||||||
|
|
||||||
<div class="mb-2 d-flex justify-content-between align-items-center">
|
<div class="mb-2 d-flex justify-content-between align-items-center">
|
||||||
<app-setting-item [title]="''" [showEdit]="false">
|
<app-setting-item [title]="''" [showEdit]="false" [canEdit]="selectedProfile.kind !== ReadingProfileKind.Default">
|
||||||
<ng-template #view>
|
<ng-template #view>
|
||||||
{{readingProfileForm.get('name')!.value}}
|
{{readingProfileForm.get('name')!.value}}
|
||||||
</ng-template>
|
</ng-template>
|
||||||
<ng-template #edit>
|
<ng-template #edit>
|
||||||
<input class="form-control" type="text" formControlName="name">
|
<input class="form-control" type="text" formControlName="name" [disabled]="selectedProfile.kind === ReadingProfileKind.Default">
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</app-setting-item>
|
</app-setting-item>
|
||||||
|
|
||||||
@if (selectedProfile.id !== 0) {
|
@if (selectedProfile.id !== 0) {
|
||||||
<div class="d-flex justify-content-between">
|
<div class="d-flex justify-content-between">
|
||||||
<button class="btn btn-danger" (click)="delete(selectedProfile!)" [disabled]="selectedProfile.kind === ReadingProfileKind.Default">
|
<button type="button" class="btn btn-danger" (click)="delete(selectedProfile!)" [disabled]="selectedProfile.kind === ReadingProfileKind.Default">
|
||||||
<i class="fa fa-trash" aria-hidden="true"></i>
|
<i class="fa fa-trash" aria-hidden="true"></i>
|
||||||
|
<span class="visually-hidden">{{t('delete')}}</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
@ -233,12 +234,12 @@
|
||||||
<app-setting-item [title]="t('width-override-label')" [subtitle]="t('width-override-tooltip')">
|
<app-setting-item [title]="t('width-override-label')" [subtitle]="t('width-override-tooltip')">
|
||||||
<ng-template #view>
|
<ng-template #view>
|
||||||
<label for="width-override-slider" class="form-label">
|
<label for="width-override-slider" class="form-label">
|
||||||
{{ widthOverrideLabel }}
|
{{ widthOverrideLabel | sentenceCase }}
|
||||||
</label>
|
</label>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
<ng-template #edit>
|
<ng-template #edit>
|
||||||
<div class="d-flex justify-content-between align-items-center">
|
<div class="d-flex justify-content-between align-items-center">
|
||||||
<span>{{ widthOverrideLabel }}</span>
|
<span>{{ widthOverrideLabel | sentenceCase }}</span>
|
||||||
<button class="btn btn-secondary" (click)="widthOverride.setValue(null)">
|
<button class="btn btn-secondary" (click)="widthOverride.setValue(null)">
|
||||||
{{t('reset')}}
|
{{t('reset')}}
|
||||||
</button>
|
</button>
|
||||||
|
|
|
||||||
|
|
@ -158,7 +158,7 @@ export class ManageReadingProfilesComponent implements OnInit {
|
||||||
get widthOverrideLabel() {
|
get widthOverrideLabel() {
|
||||||
const rawVal = this.readingProfileForm?.get('widthOverride')!.value;
|
const rawVal = this.readingProfileForm?.get('widthOverride')!.value;
|
||||||
if (!rawVal) {
|
if (!rawVal) {
|
||||||
return translate('off');
|
return translate('reader-settings.off');
|
||||||
}
|
}
|
||||||
|
|
||||||
const val = parseInt(rawVal);
|
const val = parseInt(rawVal);
|
||||||
|
|
|
||||||
|
|
@ -1978,7 +1978,7 @@
|
||||||
"height": "Height",
|
"height": "Height",
|
||||||
"width": "Width",
|
"width": "Width",
|
||||||
"width-override-label": "Width Override",
|
"width-override-label": "Width Override",
|
||||||
"off": "Off",
|
"off": "{{reader-settings.off}}",
|
||||||
"original": "Original",
|
"original": "Original",
|
||||||
"auto-close-menu-label": "{{manage-reading-profiles.auto-close-menu-label}}",
|
"auto-close-menu-label": "{{manage-reading-profiles.auto-close-menu-label}}",
|
||||||
"swipe-enabled-label": "Swipe Enabled",
|
"swipe-enabled-label": "Swipe Enabled",
|
||||||
|
|
@ -2886,8 +2886,8 @@
|
||||||
"pdf-theme-tooltip": "Color theme of the reader",
|
"pdf-theme-tooltip": "Color theme of the reader",
|
||||||
|
|
||||||
"reading-profile-series-settings-title": "Series",
|
"reading-profile-series-settings-title": "Series",
|
||||||
|
"reading-profile-library-settings-title": "Library",
|
||||||
"reading-profile-library-settings-title": "Library"
|
"delete": "{{common.delete}}"
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue