mirror of
https://github.com/Kareadita/Kavita.git
synced 2025-05-24 00:52:23 -04:00
Invite & Library Edit - Missing SideNav Code (#2322)
This commit is contained in:
parent
7c8fdd9ea8
commit
a3afa04be4
@ -459,7 +459,7 @@ public class AccountController : BaseApiController
|
||||
if (adminUser == null) return Unauthorized();
|
||||
if (!await _unitOfWork.UserRepository.IsUserAdminAsync(adminUser)) return Unauthorized(await _localizationService.Translate(User.GetUserId(), "permission-denied"));
|
||||
|
||||
var user = await _unitOfWork.UserRepository.GetUserByIdAsync(dto.UserId);
|
||||
var user = await _unitOfWork.UserRepository.GetUserByIdAsync(dto.UserId, AppUserIncludes.SideNavStreams);
|
||||
if (user == null) return BadRequest(await _localizationService.Translate(User.GetUserId(), "no-user"));
|
||||
|
||||
// Check if username is changing
|
||||
@ -509,6 +509,7 @@ public class AccountController : BaseApiController
|
||||
{
|
||||
lib.AppUsers ??= new List<AppUser>();
|
||||
lib.AppUsers.Remove(user);
|
||||
user.RemoveSideNavFromLibrary(lib);
|
||||
}
|
||||
|
||||
libraries = (await _unitOfWork.LibraryRepository.GetLibraryForIdsAsync(dto.Libraries, LibraryIncludes.AppUser)).ToList();
|
||||
@ -518,6 +519,7 @@ public class AccountController : BaseApiController
|
||||
{
|
||||
lib.AppUsers ??= new List<AppUser>();
|
||||
lib.AppUsers.Add(user);
|
||||
user.CreateSideNavFromLibrary(lib);
|
||||
}
|
||||
|
||||
user.AgeRestriction = hasAdminRole ? AgeRating.NotApplicable : dto.AgeRestriction.AgeRating;
|
||||
@ -528,6 +530,9 @@ public class AccountController : BaseApiController
|
||||
if (!_unitOfWork.HasChanges() || await _unitOfWork.CommitAsync())
|
||||
{
|
||||
await _eventHub.SendMessageToAsync(MessageFactory.UserUpdate, MessageFactory.UserUpdateEvent(user.Id, user.UserName), user.Id);
|
||||
await _eventHub.SendMessageToAsync(MessageFactory.SideNavUpdate, MessageFactory.SideNavUpdateEvent(user.Id), user.Id);
|
||||
// If we adjust library access, dashboards should re-render
|
||||
await _eventHub.SendMessageToAsync(MessageFactory.DashboardUpdate, MessageFactory.DashboardUpdateEvent(user.Id), user.Id);
|
||||
return Ok();
|
||||
}
|
||||
|
||||
@ -627,8 +632,10 @@ public class AccountController : BaseApiController
|
||||
{
|
||||
lib.AppUsers ??= new List<AppUser>();
|
||||
lib.AppUsers.Add(user);
|
||||
user.CreateSideNavFromLibrary(lib);
|
||||
}
|
||||
|
||||
_unitOfWork.UserRepository.Update(user);
|
||||
user.AgeRestriction = hasAdminRole ? AgeRating.NotApplicable : dto.AgeRestriction.AgeRating;
|
||||
user.AgeRestrictionIncludeUnknowns = hasAdminRole || dto.AgeRestriction.IncludeUnknowns;
|
||||
|
||||
@ -649,6 +656,7 @@ public class AccountController : BaseApiController
|
||||
await _unitOfWork.CommitAsync();
|
||||
}
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
var emailLink = await _accountService.GenerateEmailLink(Request, user.ConfirmationToken, "confirm-email", dto.Email);
|
||||
|
@ -109,16 +109,7 @@ public class LibraryController : BaseApiController
|
||||
|
||||
foreach (var user in userNeedingNewLibrary)
|
||||
{
|
||||
var maxCount = user.SideNavStreams.Select(s => s.Order).Max();
|
||||
user.SideNavStreams.Add(new AppUserSideNavStream()
|
||||
{
|
||||
Name = library.Name,
|
||||
Order = maxCount + 1,
|
||||
IsProvided = false,
|
||||
StreamType = SideNavStreamType.Library,
|
||||
LibraryId = library.Id,
|
||||
Visible = true,
|
||||
});
|
||||
user.CreateSideNavFromLibrary(library);
|
||||
_unitOfWork.UserRepository.Update(user);
|
||||
}
|
||||
|
||||
@ -201,7 +192,7 @@ public class LibraryController : BaseApiController
|
||||
[HttpPost("grant-access")]
|
||||
public async Task<ActionResult<MemberDto>> UpdateUserLibraries(UpdateLibraryForUserDto updateLibraryForUserDto)
|
||||
{
|
||||
var user = await _unitOfWork.UserRepository.GetUserByUsernameAsync(updateLibraryForUserDto.Username);
|
||||
var user = await _unitOfWork.UserRepository.GetUserByUsernameAsync(updateLibraryForUserDto.Username, AppUserIncludes.SideNavStreams);
|
||||
if (user == null) return BadRequest(await _localizationService.Translate(User.GetUserId(), "user-doesnt-exist"));
|
||||
|
||||
var libraryString = string.Join(',', updateLibraryForUserDto.SelectedLibraries.Select(x => x.Name));
|
||||
@ -217,10 +208,12 @@ public class LibraryController : BaseApiController
|
||||
{
|
||||
// Remove
|
||||
library.AppUsers.Remove(user);
|
||||
user.RemoveSideNavFromLibrary(library);
|
||||
}
|
||||
else if (!libraryContainsUser && libraryIsSelected)
|
||||
{
|
||||
library.AppUsers.Add(user);
|
||||
user.CreateSideNavFromLibrary(library);
|
||||
}
|
||||
}
|
||||
|
||||
@ -235,6 +228,11 @@ public class LibraryController : BaseApiController
|
||||
_logger.LogInformation("Added: {SelectedLibraries} to {Username}",libraryString, updateLibraryForUserDto.Username);
|
||||
// Bust cache
|
||||
await _libraryCacheProvider.RemoveByPrefixAsync(CacheKey);
|
||||
|
||||
// TODO: Update a user's SideNav based on library access
|
||||
|
||||
_unitOfWork.UserRepository.Update(user);
|
||||
|
||||
return Ok(_mapper.Map<MemberDto>(user));
|
||||
}
|
||||
|
||||
|
@ -929,6 +929,12 @@ public class SeriesRepository : ISeriesRepository
|
||||
query ??= _context.Series
|
||||
.AsNoTracking();
|
||||
|
||||
// When the user has no access, just return instantly
|
||||
if (userLibraries.Count == 0)
|
||||
{
|
||||
return query.Where(s => false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// First setup any FilterField.Libraries in the statements, as these don't have any traditional query statements applied here
|
||||
|
46
API/Extensions/AppUserExtensions.cs
Normal file
46
API/Extensions/AppUserExtensions.cs
Normal file
@ -0,0 +1,46 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using API.Entities;
|
||||
using API.Helpers;
|
||||
|
||||
namespace API.Extensions;
|
||||
|
||||
public static class AppUserExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Adds a new SideNavStream to the user's SideNavStreams. This user should have these streams already loaded
|
||||
/// </summary>
|
||||
/// <param name="user"></param>
|
||||
/// <param name="library"></param>
|
||||
public static void CreateSideNavFromLibrary(this AppUser user, Library library)
|
||||
{
|
||||
user.SideNavStreams ??= new List<AppUserSideNavStream>();
|
||||
var maxCount = user.SideNavStreams.Select(s => s.Order).DefaultIfEmpty().Max();
|
||||
|
||||
if (user.SideNavStreams.FirstOrDefault(s => s.LibraryId == library.Id) != null) return;
|
||||
|
||||
user.SideNavStreams.Add(new AppUserSideNavStream()
|
||||
{
|
||||
Name = library.Name,
|
||||
Order = maxCount + 1,
|
||||
IsProvided = false,
|
||||
StreamType = SideNavStreamType.Library,
|
||||
LibraryId = library.Id,
|
||||
Visible = true,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public static void RemoveSideNavFromLibrary(this AppUser user, Library library)
|
||||
{
|
||||
user.SideNavStreams ??= new List<AppUserSideNavStream>();
|
||||
|
||||
// Find the library and remove it
|
||||
var item = user.SideNavStreams.FirstOrDefault(s => s.LibraryId == library.Id);
|
||||
if (item == null) return;
|
||||
user.SideNavStreams.Remove(item);
|
||||
|
||||
OrderableHelper.ReorderItems(user.SideNavStreams);
|
||||
|
||||
}
|
||||
}
|
60
API/Helpers/OrderableHelper.cs
Normal file
60
API/Helpers/OrderableHelper.cs
Normal file
@ -0,0 +1,60 @@
|
||||
using System.Collections.Generic;
|
||||
using API.Entities;
|
||||
|
||||
namespace API.Helpers;
|
||||
|
||||
public static class OrderableHelper
|
||||
{
|
||||
public static void ReorderItems(List<AppUserDashboardStream> items, int itemId, int toPosition)
|
||||
{
|
||||
var item = items.Find(r => r.Id == itemId);
|
||||
if (item != null)
|
||||
{
|
||||
items.Remove(item);
|
||||
items.Insert(toPosition, item);
|
||||
}
|
||||
|
||||
for (var i = 0; i < items.Count; i++)
|
||||
{
|
||||
items[i].Order = i;
|
||||
}
|
||||
}
|
||||
|
||||
public static void ReorderItems(List<AppUserSideNavStream> items, int itemId, int toPosition)
|
||||
{
|
||||
var item = items.Find(r => r.Id == itemId);
|
||||
if (item != null)
|
||||
{
|
||||
items.Remove(item);
|
||||
items.Insert(toPosition, item);
|
||||
}
|
||||
|
||||
for (var i = 0; i < items.Count; i++)
|
||||
{
|
||||
items[i].Order = i;
|
||||
}
|
||||
}
|
||||
|
||||
public static void ReorderItems(IList<AppUserSideNavStream> items)
|
||||
{
|
||||
for (var i = 0; i < items.Count; i++)
|
||||
{
|
||||
items[i].Order = i;
|
||||
}
|
||||
}
|
||||
|
||||
public static void ReorderItems(List<ReadingListItem> items, int readingListItemId, int toPosition)
|
||||
{
|
||||
var item = items.Find(r => r.Id == readingListItemId);
|
||||
if (item != null)
|
||||
{
|
||||
items.Remove(item);
|
||||
items.Insert(toPosition, item);
|
||||
}
|
||||
|
||||
for (var i = 0; i < items.Count; i++)
|
||||
{
|
||||
items[i].Order = i;
|
||||
}
|
||||
}
|
||||
}
|
@ -236,28 +236,13 @@ public class ReadingListService : IReadingListService
|
||||
public async Task<bool> UpdateReadingListItemPosition(UpdateReadingListPosition dto)
|
||||
{
|
||||
var items = (await _unitOfWork.ReadingListRepository.GetReadingListItemsByIdAsync(dto.ReadingListId)).ToList();
|
||||
ReorderItems(items, dto.ReadingListItemId, dto.ToPosition);
|
||||
OrderableHelper.ReorderItems(items, dto.ReadingListItemId, dto.ToPosition);
|
||||
|
||||
if (!_unitOfWork.HasChanges()) return true;
|
||||
|
||||
return await _unitOfWork.CommitAsync();
|
||||
}
|
||||
|
||||
private static void ReorderItems(List<ReadingListItem> items, int readingListItemId, int toPosition)
|
||||
{
|
||||
var item = items.Find(r => r.Id == readingListItemId);
|
||||
if (item != null)
|
||||
{
|
||||
items.Remove(item);
|
||||
items.Insert(toPosition, item);
|
||||
}
|
||||
|
||||
for (var i = 0; i < items.Count; i++)
|
||||
{
|
||||
items[i].Order = i;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a certain reading list item from a reading list
|
||||
/// </summary>
|
||||
@ -477,7 +462,7 @@ public class ReadingListService : IReadingListService
|
||||
}
|
||||
else
|
||||
{
|
||||
ReorderItems(items, readingListItem.Id, order);
|
||||
OrderableHelper.ReorderItems(items, readingListItem.Id, order);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@ using API.DTOs.Dashboard;
|
||||
using API.DTOs.SideNav;
|
||||
using API.Entities;
|
||||
using API.Entities.Enums;
|
||||
using API.Helpers;
|
||||
using API.SignalR;
|
||||
using Kavita.Common;
|
||||
using Kavita.Common.Helpers;
|
||||
@ -127,7 +128,7 @@ public class StreamService : IStreamService
|
||||
if (stream.Order == dto.ToPosition) return;
|
||||
|
||||
var list = user!.DashboardStreams.ToList();
|
||||
ReorderItems(list, stream.Id, dto.ToPosition);
|
||||
OrderableHelper.ReorderItems(list, stream.Id, dto.ToPosition);
|
||||
user.DashboardStreams = list;
|
||||
|
||||
_unitOfWork.UserRepository.Update(user);
|
||||
@ -263,7 +264,7 @@ public class StreamService : IStreamService
|
||||
if (stream.Order == dto.ToPosition) return;
|
||||
|
||||
var list = user!.SideNavStreams.ToList();
|
||||
ReorderItems(list, stream.Id, dto.ToPosition);
|
||||
OrderableHelper.ReorderItems(list, stream.Id, dto.ToPosition);
|
||||
user.SideNavStreams = list;
|
||||
_unitOfWork.UserRepository.Update(user);
|
||||
|
||||
@ -340,33 +341,5 @@ public class StreamService : IStreamService
|
||||
await _unitOfWork.CommitAsync();
|
||||
}
|
||||
|
||||
private static void ReorderItems(List<AppUserDashboardStream> items, int itemId, int toPosition)
|
||||
{
|
||||
var item = items.Find(r => r.Id == itemId);
|
||||
if (item != null)
|
||||
{
|
||||
items.Remove(item);
|
||||
items.Insert(toPosition, item);
|
||||
}
|
||||
|
||||
for (var i = 0; i < items.Count; i++)
|
||||
{
|
||||
items[i].Order = i;
|
||||
}
|
||||
}
|
||||
|
||||
private static void ReorderItems(List<AppUserSideNavStream> items, int itemId, int toPosition)
|
||||
{
|
||||
var item = items.Find(r => r.Id == itemId);
|
||||
if (item != null)
|
||||
{
|
||||
items.Remove(item);
|
||||
items.Insert(toPosition, item);
|
||||
}
|
||||
|
||||
for (var i = 0; i < items.Count; i++)
|
||||
{
|
||||
items[i].Order = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,5 @@
|
||||
import {ChangeDetectionStrategy, ChangeDetectorRef, Component, inject, OnInit} from '@angular/core';
|
||||
import {ActivatedRoute, RouterLink} from '@angular/router';
|
||||
import {ToastrService} from 'ngx-toastr';
|
||||
import {ServerService} from 'src/app/_services/server.service';
|
||||
import {Title} from '@angular/platform-browser';
|
||||
import {NavService} from '../../_services/nav.service';
|
||||
import {SentenceCasePipe} from '../../pipe/sentence-case.pipe';
|
||||
@ -20,7 +18,7 @@ import {NgbNav, NgbNavContent, NgbNavItem, NgbNavItemRole, NgbNavLink, NgbNavOut
|
||||
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";
|
||||
|
||||
enum TabID {
|
||||
General = '',
|
||||
@ -66,8 +64,7 @@ export class DashboardComponent implements OnInit {
|
||||
return TabID;
|
||||
}
|
||||
|
||||
constructor(public route: ActivatedRoute, private serverService: ServerService,
|
||||
private toastr: ToastrService, private titleService: Title, public navService: NavService) {
|
||||
constructor(public route: ActivatedRoute, private titleService: Title, public navService: NavService) {
|
||||
this.route.fragment.subscribe(frag => {
|
||||
const tab = this.tabs.filter(item => item.fragment === frag);
|
||||
if (tab.length > 0) {
|
||||
@ -81,6 +78,6 @@ export class DashboardComponent implements OnInit {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.titleService.setTitle('Kavita - ' + this.translocoService.translate('admin-dashboard.title'));
|
||||
this.titleService.setTitle('Kavita - ' + translate('admin-dashboard.title'));
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
"name": "GPL-3.0",
|
||||
"url": "https://github.com/Kareadita/Kavita/blob/develop/LICENSE"
|
||||
},
|
||||
"version": "0.7.8.11"
|
||||
"version": "0.7.8.12"
|
||||
},
|
||||
"servers": [
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user