From f54eb5865b4a16bd915b219960cef635c812cd9f Mon Sep 17 00:00:00 2001 From: Joseph Milazzo Date: Wed, 22 Jun 2022 12:25:52 -0500 Subject: [PATCH] All Around Polish (#1328) * Added --card-list-item-bg-color for the card list items * Updated the card list item progress to match how cards render * Implemented the ability to configure how many backups are retained. * Fixed a bug where odd jump keys could cause a bad index error for jump bar * Commented out more code for the pagination route if we go with that. * Reverted a move of DisableConcurrentExecution to interface, as it seems to not work there. * Updated manga format utility code to pipes * Fixed bulk selection on series detail page * Fixed bulk selection on all other pages * Changed card item to OnPush * Updated image component to OnPush * Updated Series Card to OnPush * Updated Series Detail to OnPush * Lots of changes here. Integrated parentscroll support on card detail layout. Added jump bar (custom js implementation) on collection, reading list and all series pages. Updated UserParams to default to no pagination. Lots of cleanup all around * Updated some notes on a module use * Some code cleanup * Fixed up a broken test due to the mapper not being configured in the test. * Applied TabID pattern to edit collection tags * Applied css from series detail to collection detail page to remove double scrollbar * Implemented the ability to sort by Time To Read. * Throw an error to the UI when we extract an archive and it contains invalid characters in the filename for the Server OS. * Tweaked how the page scrolls for jumpbar on collection detail. We will have to polish another release * Cleaned up the styling on directory picker * Put some code in but it doesn't work for scroll to top on virtual scrolling. I'll do it later. * Fixed a container bug --- API.Tests/Services/CleanupServiceTests.cs | 8 +- API/Controllers/ReadingListController.cs | 5 +- API/Controllers/ServerController.cs | 2 +- API/Controllers/SettingsController.cs | 13 +- API/DTOs/Filtering/SortField.cs | 18 ++- API/DTOs/ReadingLists/ReadingListDto.cs | 4 + API/DTOs/Settings/ServerSettingDTO.cs | 9 +- API/Data/Repositories/SeriesRepository.cs | 2 + API/Data/Repositories/SettingsRepository.cs | 1 + API/Data/Seed.cs | 1 + API/Entities/Enums/ServerSettingKey.cs | 5 + .../ApplicationServiceExtensions.cs | 2 +- API/Helpers/AutoMapperProfiles.cs | 3 +- .../Converters/ServerSettingConverter.cs | 3 + API/Helpers/UserParams.cs | 2 +- API/Services/ArchiveService.cs | 4 +- API/Services/BookmarkService.cs | 1 + API/Services/MetadataService.cs | 2 + API/Services/Tasks/CleanupService.cs | 4 +- .../Metadata/WordCountAnalyzerService.cs | 2 + API/Services/Tasks/ScannerService.cs | 8 +- UI/Web/src/app/_models/reading-list.ts | 4 + UI/Web/src/app/_models/series-filter.ts | 3 +- .../src/app/_models/system/directory-dto.ts | 4 + UI/Web/src/app/_services/account.service.ts | 3 +- UI/Web/src/app/_services/scroll.service.ts | 2 +- .../directory-picker.component.html | 12 +- .../directory-picker.component.scss | 6 + .../directory-picker.component.ts | 5 + .../src/app/admin/_models/server-settings.ts | 1 + .../manage-settings.component.html | 22 ++- .../manage-settings.component.scss | 4 + .../manage-settings.component.ts | 2 + .../app/all-series/all-series.component.html | 2 +- .../app/all-series/all-series.component.ts | 35 ++++- .../edit-collection-tags.component.html | 8 +- .../edit-collection-tags.component.ts | 13 +- .../edit-series-modal.component.html | 2 +- .../card-detail-layout.component.html | 53 +------ .../card-detail-layout.component.ts | 133 +++--------------- .../cards/card-item/card-item.component.html | 5 +- .../cards/card-item/card-item.component.ts | 31 ++-- UI/Web/src/app/cards/cards.module.ts | 2 +- .../cards/list-item/list-item.component.html | 4 +- .../cards/list-item/list-item.component.scss | 15 +- .../series-card/series-card.component.ts | 22 ++- .../series-info-cards.component.html | 4 +- .../all-collections.component.html | 1 + .../all-collections.component.ts | 26 ++++ .../collection-detail.component.html | 39 ++--- .../collection-detail.component.scss | 22 +++ .../collection-detail.component.ts | 58 ++++++-- .../library-detail.component.html | 2 - .../library-detail.component.ts | 31 +--- .../metadata-filter.component.html | 1 + .../nav/nav-header/nav-header.component.ts | 34 ++++- UI/Web/src/app/pipe/manga-format-icon.pipe.ts | 27 ++++ UI/Web/src/app/pipe/manga-format.pipe.ts | 27 ++++ UI/Web/src/app/pipe/pipe.module.ts | 10 +- .../reading-list-detail.component.html | 23 +-- .../reading-list-detail.component.scss | 8 +- .../reading-list-detail.component.ts | 3 +- .../reading-lists.component.html | 1 - .../reading-lists/reading-lists.component.ts | 2 +- .../series-detail.component.html | 116 +++++++-------- .../series-detail.component.scss | 2 +- .../series-detail/series-detail.component.ts | 58 ++++++-- .../app/shared/_services/utility.service.ts | 42 +----- .../src/app/shared/image/image.component.ts | 8 +- .../series-format.component.html | 2 +- .../sidenav/side-nav/side-nav.component.html | 2 +- .../sidenav/side-nav/side-nav.component.ts | 16 ++- UI/Web/src/theme/components/_card.scss | 2 +- UI/Web/src/theme/themes/dark.scss | 3 + 74 files changed, 626 insertions(+), 436 deletions(-) create mode 100644 UI/Web/src/app/pipe/manga-format-icon.pipe.ts create mode 100644 UI/Web/src/app/pipe/manga-format.pipe.ts diff --git a/API.Tests/Services/CleanupServiceTests.cs b/API.Tests/Services/CleanupServiceTests.cs index 08d5f29a7..a7575577c 100644 --- a/API.Tests/Services/CleanupServiceTests.cs +++ b/API.Tests/Services/CleanupServiceTests.cs @@ -6,8 +6,11 @@ using System.IO.Abstractions.TestingHelpers; using System.Linq; using System.Threading.Tasks; using API.Data; +using API.DTOs.Settings; using API.Entities; using API.Entities.Enums; +using API.Helpers; +using API.Helpers.Converters; using API.Services; using API.Services.Tasks; using API.SignalR; @@ -48,7 +51,10 @@ public class CleanupServiceTests _context = new DataContext(contextOptions); Task.Run(SeedDb).GetAwaiter().GetResult(); - _unitOfWork = new UnitOfWork(_context, Substitute.For(), null); + var config = new MapperConfiguration(cfg => cfg.AddProfile()); + var mapper = config.CreateMapper(); + + _unitOfWork = new UnitOfWork(_context, mapper, null); } #region Setup diff --git a/API/Controllers/ReadingListController.cs b/API/Controllers/ReadingListController.cs index 1b72b20d2..a4285431e 100644 --- a/API/Controllers/ReadingListController.cs +++ b/API/Controllers/ReadingListController.cs @@ -72,8 +72,9 @@ namespace API.Controllers { var userId = await _unitOfWork.UserRepository.GetUserIdByUsernameAsync(User.GetUsername()); var items = await _unitOfWork.ReadingListRepository.GetReadingListItemDtosByIdAsync(readingListId, userId); + return Ok(items); - return Ok(await _unitOfWork.ReadingListRepository.AddReadingProgressModifiers(userId, items.ToList())); + //return Ok(await _unitOfWork.ReadingListRepository.AddReadingProgressModifiers(userId, items.ToList())); } /// @@ -463,7 +464,7 @@ namespace API.Controllers var existingChapterExists = readingList.Items.Select(rli => rli.ChapterId).ToHashSet(); var chaptersForSeries = (await _unitOfWork.ChapterRepository.GetChaptersByIdsAsync(chapterIds)) - .OrderBy(c => float.Parse(c.Volume.Name)) + .OrderBy(c => Parser.Parser.MinNumberFromRange(c.Volume.Name)) .ThenBy(x => double.Parse(x.Number), _chapterSortComparerForInChapterSorting); var index = lastOrder + 1; diff --git a/API/Controllers/ServerController.cs b/API/Controllers/ServerController.cs index 7fabb2a82..f49a7e092 100644 --- a/API/Controllers/ServerController.cs +++ b/API/Controllers/ServerController.cs @@ -118,7 +118,7 @@ namespace API.Controllers try { var (fileBytes, zipPath) = await _archiveService.CreateZipForDownload(files, "logs"); - return File(fileBytes, "application/zip", Path.GetFileName(zipPath)); + return File(fileBytes, "application/zip", Path.GetFileName(zipPath), true); } catch (KavitaException ex) { diff --git a/API/Controllers/SettingsController.cs b/API/Controllers/SettingsController.cs index c6937c3c4..a712a39cc 100644 --- a/API/Controllers/SettingsController.cs +++ b/API/Controllers/SettingsController.cs @@ -54,9 +54,6 @@ namespace API.Controllers public async Task> GetSettings() { var settingsDto = await _unitOfWork.SettingsRepository.GetSettingsDtoAsync(); - // TODO: Is this needed as it gets updated in the DB on startup - settingsDto.Port = Configuration.Port; - settingsDto.LoggingLevel = Configuration.LogLevel; return Ok(settingsDto); } @@ -212,6 +209,16 @@ namespace API.Controllers _unitOfWork.SettingsRepository.Update(setting); } + if (setting.Key == ServerSettingKey.TotalBackups && updateSettingsDto.TotalBackups + string.Empty != setting.Value) + { + if (updateSettingsDto.TotalBackups > 30 || updateSettingsDto.TotalBackups < 1) + { + return BadRequest("Total Backups must be between 1 and 30"); + } + setting.Value = updateSettingsDto.TotalBackups + string.Empty; + _unitOfWork.SettingsRepository.Update(setting); + } + if (setting.Key == ServerSettingKey.EmailServiceUrl && updateSettingsDto.EmailServiceUrl + string.Empty != setting.Value) { setting.Value = string.IsNullOrEmpty(updateSettingsDto.EmailServiceUrl) ? EmailService.DefaultApiUrl : updateSettingsDto.EmailServiceUrl; diff --git a/API/DTOs/Filtering/SortField.cs b/API/DTOs/Filtering/SortField.cs index 3d78494bd..fbb1d511a 100644 --- a/API/DTOs/Filtering/SortField.cs +++ b/API/DTOs/Filtering/SortField.cs @@ -2,8 +2,24 @@ public enum SortField { + /// + /// Sort Name of Series + /// SortName = 1, + /// + /// Date entity was created/imported into Kavita + /// CreatedDate = 2, + /// + /// Date entity was last modified (tag update, etc) + /// LastModifiedDate = 3, - LastChapterAdded = 4 + /// + /// Date series had a chapter added to it + /// + LastChapterAdded = 4, + /// + /// Time it takes to read. Uses Average. + /// + TimeToRead = 5 } diff --git a/API/DTOs/ReadingLists/ReadingListDto.cs b/API/DTOs/ReadingLists/ReadingListDto.cs index 3eb5ded79..ba446d17a 100644 --- a/API/DTOs/ReadingLists/ReadingListDto.cs +++ b/API/DTOs/ReadingLists/ReadingListDto.cs @@ -10,5 +10,9 @@ /// public bool Promoted { get; set; } public bool CoverImageLocked { get; set; } + /// + /// This is used to tell the UI if it should request a Cover Image or not. If null or empty, it has not been set. + /// + public string CoverImage { get; set; } = string.Empty; } } diff --git a/API/DTOs/Settings/ServerSettingDTO.cs b/API/DTOs/Settings/ServerSettingDTO.cs index 153d52a69..8de3a692f 100644 --- a/API/DTOs/Settings/ServerSettingDTO.cs +++ b/API/DTOs/Settings/ServerSettingDTO.cs @@ -1,4 +1,5 @@ -using API.Services; +using System.Collections.Generic; +using API.Services; namespace API.DTOs.Settings { @@ -44,5 +45,11 @@ namespace API.DTOs.Settings /// If the Swagger UI Should be exposed. Does not require authentication, but does require a JWT. /// public bool EnableSwaggerUi { get; set; } + + /// + /// The amount of Backups before cleanup + /// + /// Value should be between 1 and 30 + public int TotalBackups { get; set; } = 30; } } diff --git a/API/Data/Repositories/SeriesRepository.cs b/API/Data/Repositories/SeriesRepository.cs index f90b0f301..b42bce75c 100644 --- a/API/Data/Repositories/SeriesRepository.cs +++ b/API/Data/Repositories/SeriesRepository.cs @@ -753,6 +753,7 @@ public class SeriesRepository : ISeriesRepository SortField.CreatedDate => query.OrderBy(s => s.Created), SortField.LastModifiedDate => query.OrderBy(s => s.LastModified), SortField.LastChapterAdded => query.OrderBy(s => s.LastChapterAdded), + SortField.TimeToRead => query.OrderBy(s => s.AvgHoursToRead), _ => query }; } @@ -764,6 +765,7 @@ public class SeriesRepository : ISeriesRepository SortField.CreatedDate => query.OrderByDescending(s => s.Created), SortField.LastModifiedDate => query.OrderByDescending(s => s.LastModified), SortField.LastChapterAdded => query.OrderByDescending(s => s.LastChapterAdded), + SortField.TimeToRead => query.OrderByDescending(s => s.AvgHoursToRead), _ => query }; } diff --git a/API/Data/Repositories/SettingsRepository.cs b/API/Data/Repositories/SettingsRepository.cs index be66cbe62..b94204d56 100644 --- a/API/Data/Repositories/SettingsRepository.cs +++ b/API/Data/Repositories/SettingsRepository.cs @@ -5,6 +5,7 @@ using API.DTOs.Settings; using API.Entities; using API.Entities.Enums; using AutoMapper; +using AutoMapper.QueryableExtensions; using Microsoft.EntityFrameworkCore; namespace API.Data.Repositories; diff --git a/API/Data/Seed.cs b/API/Data/Seed.cs index 1ae69895e..893256357 100644 --- a/API/Data/Seed.cs +++ b/API/Data/Seed.cs @@ -102,6 +102,7 @@ namespace API.Data new() {Key = ServerSettingKey.EmailServiceUrl, Value = EmailService.DefaultApiUrl}, new() {Key = ServerSettingKey.ConvertBookmarkToWebP, Value = "false"}, new() {Key = ServerSettingKey.EnableSwaggerUi, Value = "false"}, + new() {Key = ServerSettingKey.TotalBackups, Value = "30"}, }.ToArray()); foreach (var defaultSetting in DefaultSettings) diff --git a/API/Entities/Enums/ServerSettingKey.cs b/API/Entities/Enums/ServerSettingKey.cs index 55c13b629..b387f1d85 100644 --- a/API/Entities/Enums/ServerSettingKey.cs +++ b/API/Entities/Enums/ServerSettingKey.cs @@ -86,5 +86,10 @@ namespace API.Entities.Enums /// [Description("EnableSwaggerUi")] EnableSwaggerUi = 15, + /// + /// Total Number of Backups to maintain before cleaning. Default 30, min 1. + /// + [Description("TotalBackups")] + TotalBackups = 16, } } diff --git a/API/Extensions/ApplicationServiceExtensions.cs b/API/Extensions/ApplicationServiceExtensions.cs index 2ebaec592..1b637b25f 100644 --- a/API/Extensions/ApplicationServiceExtensions.cs +++ b/API/Extensions/ApplicationServiceExtensions.cs @@ -62,7 +62,7 @@ namespace API.Extensions } private static void AddSqLite(this IServiceCollection services, IConfiguration config, - IWebHostEnvironment env) + IHostEnvironment env) { services.AddDbContext(options => { diff --git a/API/Helpers/AutoMapperProfiles.cs b/API/Helpers/AutoMapperProfiles.cs index c6682fa85..a15913374 100644 --- a/API/Helpers/AutoMapperProfiles.cs +++ b/API/Helpers/AutoMapperProfiles.cs @@ -138,7 +138,8 @@ namespace API.Helpers CreateMap(); - + CreateMap, ServerSettingDto>() + .ConvertUsing(); CreateMap, ServerSettingDto>() .ConvertUsing(); diff --git a/API/Helpers/Converters/ServerSettingConverter.cs b/API/Helpers/Converters/ServerSettingConverter.cs index 12759c739..862b9a10c 100644 --- a/API/Helpers/Converters/ServerSettingConverter.cs +++ b/API/Helpers/Converters/ServerSettingConverter.cs @@ -54,6 +54,9 @@ namespace API.Helpers.Converters case ServerSettingKey.EnableSwaggerUi: destination.EnableSwaggerUi = bool.Parse(row.Value); break; + case ServerSettingKey.TotalBackups: + destination.TotalBackups = int.Parse(row.Value); + break; } } diff --git a/API/Helpers/UserParams.cs b/API/Helpers/UserParams.cs index 4dc4c5aa3..87cc28471 100644 --- a/API/Helpers/UserParams.cs +++ b/API/Helpers/UserParams.cs @@ -4,7 +4,7 @@ { private const int MaxPageSize = int.MaxValue; public int PageNumber { get; init; } = 1; - private readonly int _pageSize = 30; + private readonly int _pageSize = MaxPageSize; /// /// If set to 0, will set as MaxInt diff --git a/API/Services/ArchiveService.cs b/API/Services/ArchiveService.cs index b5a19d18a..8aa57d45b 100644 --- a/API/Services/ArchiveService.cs +++ b/API/Services/ArchiveService.cs @@ -412,7 +412,6 @@ namespace API.Services private void ExtractArchiveEntries(ZipArchive archive, string extractPath) { - // TODO: In cases where we try to extract, but there are InvalidPathChars, we need to inform the user (throw exception, let middleware inform user) var needsFlattening = ArchiveNeedsFlattening(archive); if (!archive.HasFiles() && !needsFlattening) return; @@ -476,7 +475,8 @@ namespace API.Services catch (Exception e) { _logger.LogWarning(e, "[ExtractArchive] There was a problem extracting {ArchivePath} to {ExtractPath}",archivePath, extractPath); - return; + throw new KavitaException( + $"There was an error when extracting {archivePath}. Check the file exists, has read permissions or the server OS can support all path characters."); } _logger.LogDebug("Extracted archive to {ExtractPath} in {ElapsedMilliseconds} milliseconds", extractPath, sw.ElapsedMilliseconds); } diff --git a/API/Services/BookmarkService.cs b/API/Services/BookmarkService.cs index b1c0e02cc..3dad57ada 100644 --- a/API/Services/BookmarkService.cs +++ b/API/Services/BookmarkService.cs @@ -174,6 +174,7 @@ public class BookmarkService : IBookmarkService /// /// This is a long-running job that will convert all bookmarks into WebP. Do not invoke anyway except via Hangfire. /// + [DisableConcurrentExecution(timeoutInSeconds: 2 * 60 * 60), AutomaticRetry(Attempts = 0)] public async Task ConvertAllBookmarkToWebP() { var bookmarkDirectory = diff --git a/API/Services/MetadataService.cs b/API/Services/MetadataService.cs index e73055350..7bb34e159 100644 --- a/API/Services/MetadataService.cs +++ b/API/Services/MetadataService.cs @@ -198,6 +198,8 @@ public class MetadataService : IMetadataService /// This can be heavy on memory first run /// /// Force updating cover image even if underlying file has not been modified or chapter already has a cover image + [DisableConcurrentExecution(timeoutInSeconds: 60 * 60 * 60)] + [AutomaticRetry(Attempts = 0, OnAttemptsExceeded = AttemptsExceededAction.Delete)] public async Task RefreshMetadata(int libraryId, bool forceUpdate = false) { var library = await _unitOfWork.LibraryRepository.GetLibraryForIdAsync(libraryId, LibraryIncludes.None); diff --git a/API/Services/Tasks/CleanupService.cs b/API/Services/Tasks/CleanupService.cs index 8b015d568..4420adedb 100644 --- a/API/Services/Tasks/CleanupService.cs +++ b/API/Services/Tasks/CleanupService.cs @@ -147,11 +147,11 @@ namespace API.Services.Tasks } /// - /// Removes Database backups older than 30 days. If all backups are older than 30 days, the latest is kept. + /// Removes Database backups older than configured total backups. If all backups are older than total backups days, only the latest is kept. /// public async Task CleanupBackups() { - const int dayThreshold = 30; // TODO: We can make this a config option + var dayThreshold = (await _unitOfWork.SettingsRepository.GetSettingsDtoAsync()).TotalBackups; _logger.LogInformation("Beginning cleanup of Database backups at {Time}", DateTime.Now); var backupDirectory = (await _unitOfWork.SettingsRepository.GetSettingAsync(ServerSettingKey.BackupDirectory)).Value; diff --git a/API/Services/Tasks/Metadata/WordCountAnalyzerService.cs b/API/Services/Tasks/Metadata/WordCountAnalyzerService.cs index f4675051b..2b5327244 100644 --- a/API/Services/Tasks/Metadata/WordCountAnalyzerService.cs +++ b/API/Services/Tasks/Metadata/WordCountAnalyzerService.cs @@ -45,6 +45,8 @@ public class WordCountAnalyzerService : IWordCountAnalyzerService } + [DisableConcurrentExecution(timeoutInSeconds: 60 * 60 * 60)] + [AutomaticRetry(Attempts = 0, OnAttemptsExceeded = AttemptsExceededAction.Delete)] public async Task ScanLibrary(int libraryId, bool forceUpdate = false) { var sw = Stopwatch.StartNew(); diff --git a/API/Services/Tasks/ScannerService.cs b/API/Services/Tasks/ScannerService.cs index f06850ae7..00caa39f2 100644 --- a/API/Services/Tasks/ScannerService.cs +++ b/API/Services/Tasks/ScannerService.cs @@ -69,6 +69,8 @@ public class ScannerService : IScannerService _wordCountAnalyzerService = wordCountAnalyzerService; } + [DisableConcurrentExecution(60 * 60 * 60)] + [AutomaticRetry(Attempts = 3, OnAttemptsExceeded = AttemptsExceededAction.Delete)] public async Task ScanSeries(int libraryId, int seriesId, CancellationToken token) { var sw = new Stopwatch(); @@ -250,7 +252,8 @@ public class ScannerService : IScannerService return true; } - + [DisableConcurrentExecution(60 * 60 * 60)] + [AutomaticRetry(Attempts = 0, OnAttemptsExceeded = AttemptsExceededAction.Delete)] public async Task ScanLibraries() { _logger.LogInformation("Starting Scan of All Libraries"); @@ -269,7 +272,8 @@ public class ScannerService : IScannerService /// ie) all entities will be rechecked for new cover images and comicInfo.xml changes /// /// - + [DisableConcurrentExecution(60 * 60 * 60)] + [AutomaticRetry(Attempts = 0, OnAttemptsExceeded = AttemptsExceededAction.Delete)] public async Task ScanLibrary(int libraryId) { Library library; diff --git a/UI/Web/src/app/_models/reading-list.ts b/UI/Web/src/app/_models/reading-list.ts index da7932acc..3a1dd7297 100644 --- a/UI/Web/src/app/_models/reading-list.ts +++ b/UI/Web/src/app/_models/reading-list.ts @@ -21,4 +21,8 @@ export interface ReadingList { promoted: boolean; coverImageLocked: boolean; items: Array; + /** + * If this is empty or null, the cover image isn't set. Do not use this externally. + */ + coverImage: string; } \ No newline at end of file diff --git a/UI/Web/src/app/_models/series-filter.ts b/UI/Web/src/app/_models/series-filter.ts index c2b823ce3..e346ccd4f 100644 --- a/UI/Web/src/app/_models/series-filter.ts +++ b/UI/Web/src/app/_models/series-filter.ts @@ -41,7 +41,8 @@ export enum SortField { SortName = 1, Created = 2, LastModified = 3, - LastChapterAdded = 4 + LastChapterAdded = 4, + TimeToRead = 5 } export interface ReadStatus { diff --git a/UI/Web/src/app/_models/system/directory-dto.ts b/UI/Web/src/app/_models/system/directory-dto.ts index 346993f80..d666e59b8 100644 --- a/UI/Web/src/app/_models/system/directory-dto.ts +++ b/UI/Web/src/app/_models/system/directory-dto.ts @@ -1,4 +1,8 @@ export interface DirectoryDto { name: string; fullPath: string; + /** + * This is only on the UI to disable paths + */ + disabled: boolean; } \ No newline at end of file diff --git a/UI/Web/src/app/_services/account.service.ts b/UI/Web/src/app/_services/account.service.ts index e15249e5b..5a1bf5283 100644 --- a/UI/Web/src/app/_services/account.service.ts +++ b/UI/Web/src/app/_services/account.service.ts @@ -35,7 +35,8 @@ export class AccountService implements OnDestroy { constructor(private httpClient: HttpClient, private router: Router, private messageHub: MessageHubService, private themeService: ThemeService) { messageHub.messages$.pipe(filter(evt => evt.event === EVENTS.UserUpdate), - map(evt => evt.payload as UserUpdateEvent), + map(evt => evt.payload as UserUpdateEvent), + filter(userUpdateEvent => userUpdateEvent.userName === this.currentUser?.username), switchMap(() => this.refreshToken())) .subscribe(() => {}); } diff --git a/UI/Web/src/app/_services/scroll.service.ts b/UI/Web/src/app/_services/scroll.service.ts index 7c4b07ea2..7137c5aeb 100644 --- a/UI/Web/src/app/_services/scroll.service.ts +++ b/UI/Web/src/app/_services/scroll.service.ts @@ -1,4 +1,4 @@ -import { ElementRef, Injectable } from '@angular/core'; +import { Injectable } from '@angular/core'; @Injectable({ providedIn: 'root' diff --git a/UI/Web/src/app/admin/_modals/directory-picker/directory-picker.component.html b/UI/Web/src/app/admin/_modals/directory-picker/directory-picker.component.html index 4618a7c2d..d7c9b08f0 100644 --- a/UI/Web/src/app/admin/_modals/directory-picker/directory-picker.component.html +++ b/UI/Web/src/app/admin/_modals/directory-picker/directory-picker.component.html @@ -3,14 +3,6 @@