mirror of
https://github.com/Kareadita/Kavita.git
synced 2025-07-09 03:04:19 -04:00
Release Testing Day 2 (#1493)
* Added a no data section to collection detail. * Remove an optimization for skipping the whole library scan as it wasn't reliable * When resetting password, ensure the input is colored correctly * Fixed setting new password after resetting, throwing an error despite it actually being successful. Fixed incorrect messaging for Password Reset page. * Fixed a bug where reset password would show the side nav button and skew the page. Updated a lot of references to use Typed version for formcontrols. * Removed a migration from 0.5.0, 6 releases ago. * Added a null check so we don't throw an exception when connecting with signalR on unauthenticated users.
This commit is contained in:
parent
8e21a7091f
commit
2cd94e7db4
@ -579,17 +579,26 @@ namespace API.Controllers
|
|||||||
[HttpPost("confirm-password-reset")]
|
[HttpPost("confirm-password-reset")]
|
||||||
public async Task<ActionResult<string>> ConfirmForgotPassword(ConfirmPasswordResetDto dto)
|
public async Task<ActionResult<string>> ConfirmForgotPassword(ConfirmPasswordResetDto dto)
|
||||||
{
|
{
|
||||||
var user = await _unitOfWork.UserRepository.GetUserByEmailAsync(dto.Email);
|
try
|
||||||
if (user == null)
|
|
||||||
{
|
{
|
||||||
return BadRequest("Invalid Details");
|
var user = await _unitOfWork.UserRepository.GetUserByEmailAsync(dto.Email);
|
||||||
|
if (user == null)
|
||||||
|
{
|
||||||
|
return BadRequest("Invalid Details");
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = await _userManager.VerifyUserTokenAsync(user, TokenOptions.DefaultProvider,
|
||||||
|
"ResetPassword", dto.Token);
|
||||||
|
if (!result) return BadRequest("Unable to reset password, your email token is not correct.");
|
||||||
|
|
||||||
|
var errors = await _accountService.ChangeUserPassword(user, dto.Password);
|
||||||
|
return errors.Any() ? BadRequest(errors) : Ok("Password updated");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "There was an unexpected error when confirming new password");
|
||||||
|
return BadRequest("There was an unexpected error when confirming new password");
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = await _userManager.VerifyUserTokenAsync(user, TokenOptions.DefaultProvider, "ResetPassword", dto.Token);
|
|
||||||
if (!result) return BadRequest("Unable to reset password, your email token is not correct.");
|
|
||||||
|
|
||||||
var errors = await _accountService.ChangeUserPassword(user, dto.Password);
|
|
||||||
return errors.Any() ? BadRequest(errors) : Ok("Password updated");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,105 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using API.Comparators;
|
|
||||||
using API.Entities.Enums;
|
|
||||||
using API.Services;
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
|
|
||||||
namespace API.Data;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Responsible to migrate existing bookmarks to files. Introduced in v0.4.9.27
|
|
||||||
/// </summary>
|
|
||||||
public static class MigrateBookmarks
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// This will migrate existing bookmarks to bookmark folder based.
|
|
||||||
/// If the bookmarks folder already exists, this will not run.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>Bookmark directory is configurable. This will always use the default bookmark directory.</remarks>
|
|
||||||
/// <param name="directoryService"></param>
|
|
||||||
/// <param name="unitOfWork"></param>
|
|
||||||
/// <param name="logger"></param>
|
|
||||||
/// <param name="cacheService"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public static async Task Migrate(IDirectoryService directoryService, IUnitOfWork unitOfWork,
|
|
||||||
ILogger<Program> logger, ICacheService cacheService)
|
|
||||||
{
|
|
||||||
var bookmarkDirectory = (await unitOfWork.SettingsRepository.GetSettingAsync(ServerSettingKey.BookmarkDirectory))
|
|
||||||
.Value;
|
|
||||||
if (string.IsNullOrEmpty(bookmarkDirectory))
|
|
||||||
{
|
|
||||||
bookmarkDirectory = directoryService.BookmarkDirectory;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (directoryService.Exists(bookmarkDirectory)) return;
|
|
||||||
|
|
||||||
logger.LogInformation("Bookmark migration is needed....This may take some time");
|
|
||||||
|
|
||||||
var allBookmarks = (await unitOfWork.UserRepository.GetAllBookmarksAsync()).ToList();
|
|
||||||
|
|
||||||
var uniqueChapterIds = allBookmarks.Select(b => b.ChapterId).Distinct().ToList();
|
|
||||||
var uniqueUserIds = allBookmarks.Select(b => b.AppUserId).Distinct().ToList();
|
|
||||||
foreach (var userId in uniqueUserIds)
|
|
||||||
{
|
|
||||||
foreach (var chapterId in uniqueChapterIds)
|
|
||||||
{
|
|
||||||
var chapterBookmarks = allBookmarks.Where(b => b.ChapterId == chapterId).ToList();
|
|
||||||
var chapterPages = chapterBookmarks
|
|
||||||
.Select(b => b.Page).ToList();
|
|
||||||
var seriesId = chapterBookmarks
|
|
||||||
.Select(b => b.SeriesId).First();
|
|
||||||
var mangaFiles = await unitOfWork.ChapterRepository.GetFilesForChapterAsync(chapterId);
|
|
||||||
var chapterExtractPath = directoryService.FileSystem.Path.Join(directoryService.TempDirectory, $"bookmark_c{chapterId}_u{userId}_s{seriesId}");
|
|
||||||
|
|
||||||
var numericComparer = new NumericComparer();
|
|
||||||
if (!mangaFiles.Any()) continue;
|
|
||||||
|
|
||||||
switch (mangaFiles.First().Format)
|
|
||||||
{
|
|
||||||
case MangaFormat.Image:
|
|
||||||
directoryService.ExistOrCreate(chapterExtractPath);
|
|
||||||
directoryService.CopyFilesToDirectory(mangaFiles.Select(f => f.FilePath), chapterExtractPath);
|
|
||||||
break;
|
|
||||||
case MangaFormat.Archive:
|
|
||||||
case MangaFormat.Pdf:
|
|
||||||
cacheService.ExtractChapterFiles(chapterExtractPath, mangaFiles.ToList());
|
|
||||||
break;
|
|
||||||
case MangaFormat.Epub:
|
|
||||||
continue;
|
|
||||||
default:
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
var files = directoryService.GetFilesWithExtension(chapterExtractPath, Services.Tasks.Scanner.Parser.Parser.ImageFileExtensions);
|
|
||||||
// Filter out images that aren't in bookmarks
|
|
||||||
Array.Sort(files, numericComparer);
|
|
||||||
foreach (var chapterPage in chapterPages)
|
|
||||||
{
|
|
||||||
var file = files.ElementAt(chapterPage);
|
|
||||||
var bookmark = allBookmarks.FirstOrDefault(b =>
|
|
||||||
b.ChapterId == chapterId && b.SeriesId == seriesId && b.AppUserId == userId &&
|
|
||||||
b.Page == chapterPage);
|
|
||||||
if (bookmark == null) continue;
|
|
||||||
|
|
||||||
var filename = directoryService.FileSystem.Path.GetFileName(file);
|
|
||||||
var newLocation = directoryService.FileSystem.Path.Join(
|
|
||||||
ReaderService.FormatBookmarkFolderPath(String.Empty, userId, seriesId, chapterId),
|
|
||||||
filename);
|
|
||||||
bookmark.FileName = newLocation;
|
|
||||||
directoryService.CopyFileToDirectory(file,
|
|
||||||
ReaderService.FormatBookmarkFolderPath(bookmarkDirectory, userId, seriesId, chapterId));
|
|
||||||
unitOfWork.UserRepository.Update(bookmark);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Clear temp after each user to avoid too much space being eaten
|
|
||||||
directoryService.ClearDirectory(directoryService.TempDirectory);
|
|
||||||
}
|
|
||||||
|
|
||||||
await unitOfWork.CommitAsync();
|
|
||||||
// Run CleanupService as we cache a ton of files
|
|
||||||
directoryService.ClearDirectory(directoryService.TempDirectory);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
@ -406,30 +406,6 @@ public class ScannerService : IScannerService
|
|||||||
var libraryFolderPaths = library.Folders.Select(fp => fp.Path).ToList();
|
var libraryFolderPaths = library.Folders.Select(fp => fp.Path).ToList();
|
||||||
if (!await CheckMounts(library.Name, libraryFolderPaths)) return;
|
if (!await CheckMounts(library.Name, libraryFolderPaths)) return;
|
||||||
|
|
||||||
// If all library Folder paths haven't been modified since last scan, abort
|
|
||||||
// Unless the user did something on the library (delete series) and thus we can bypass this check
|
|
||||||
var wasLibraryUpdatedSinceLastScan = (library.LastModified.Truncate(TimeSpan.TicksPerMinute) >
|
|
||||||
library.LastScanned.Truncate(TimeSpan.TicksPerMinute))
|
|
||||||
&& library.LastScanned != DateTime.MinValue;
|
|
||||||
if (!forceUpdate && !wasLibraryUpdatedSinceLastScan)
|
|
||||||
{
|
|
||||||
var haveFoldersChangedSinceLastScan = library.Folders
|
|
||||||
.All(f => _directoryService.GetLastWriteTime(f.Path).Truncate(TimeSpan.TicksPerMinute) > f.LastScanned.Truncate(TimeSpan.TicksPerMinute));
|
|
||||||
|
|
||||||
// If nothing changed && library folder's have all been scanned at least once
|
|
||||||
if (!haveFoldersChangedSinceLastScan && library.Folders.All(f => f.LastScanned > DateTime.MinValue))
|
|
||||||
{
|
|
||||||
_logger.LogInformation("[ScannerService] {LibraryName} scan has no work to do. All folders have not been changed since last scan", library.Name);
|
|
||||||
await _eventHub.SendMessageAsync(MessageFactory.Info,
|
|
||||||
MessageFactory.InfoEvent($"{library.Name} scan has no work to do",
|
|
||||||
$"All folders have not been changed since last scan ({library.Folders.Max(f => f.LastScanned).ToString(CultureInfo.CurrentCulture)}). Scan will be aborted."));
|
|
||||||
|
|
||||||
BackgroundJob.Enqueue(() => _metadataService.GenerateCoversForLibrary(library.Id, false));
|
|
||||||
BackgroundJob.Enqueue(() => _wordCountAnalyzerService.ScanLibrary(library.Id, false));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Validations are done, now we can start actual scan
|
// Validations are done, now we can start actual scan
|
||||||
_logger.LogInformation("[ScannerService] Beginning file scan on {LibraryName}", library.Name);
|
_logger.LogInformation("[ScannerService] Beginning file scan on {LibraryName}", library.Name);
|
||||||
|
@ -38,6 +38,7 @@ namespace API.SignalR.Presence
|
|||||||
public async Task UserConnected(string username, string connectionId)
|
public async Task UserConnected(string username, string connectionId)
|
||||||
{
|
{
|
||||||
var user = await _unitOfWork.UserRepository.GetUserByUsernameAsync(username);
|
var user = await _unitOfWork.UserRepository.GetUserByUsernameAsync(username);
|
||||||
|
if (user == null) return;
|
||||||
var isAdmin = await _unitOfWork.UserRepository.IsUserAdminAsync(user);
|
var isAdmin = await _unitOfWork.UserRepository.IsUserAdminAsync(user);
|
||||||
lock (OnlineUsers)
|
lock (OnlineUsers)
|
||||||
{
|
{
|
||||||
|
@ -185,8 +185,6 @@ namespace API
|
|||||||
var themeService = serviceProvider.GetRequiredService<IThemeService>();
|
var themeService = serviceProvider.GetRequiredService<IThemeService>();
|
||||||
var dataContext = serviceProvider.GetRequiredService<DataContext>();
|
var dataContext = serviceProvider.GetRequiredService<DataContext>();
|
||||||
|
|
||||||
await MigrateBookmarks.Migrate(directoryService, unitOfWork,
|
|
||||||
logger, cacheService);
|
|
||||||
|
|
||||||
// Only run this if we are upgrading
|
// Only run this if we are upgrading
|
||||||
await MigrateChangePasswordRoles.Migrate(unitOfWork, userManager);
|
await MigrateChangePasswordRoles.Migrate(unitOfWork, userManager);
|
||||||
|
@ -165,7 +165,7 @@ export class AccountService implements OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
confirmResetPasswordEmail(model: {email: string, token: string, password: string}) {
|
confirmResetPasswordEmail(model: {email: string, token: string, password: string}) {
|
||||||
return this.httpClient.post(this.baseUrl + 'account/confirm-password-reset', model);
|
return this.httpClient.post(this.baseUrl + 'account/confirm-password-reset', model, {responseType: 'json' as 'text'});
|
||||||
}
|
}
|
||||||
|
|
||||||
resetPassword(username: string, password: string, oldPassword: string) {
|
resetPassword(username: string, password: string, oldPassword: string) {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Component, Input, OnInit } from '@angular/core';
|
import { Component, Input, OnInit } from '@angular/core';
|
||||||
import { UntypedFormControl, UntypedFormGroup, Validators } from '@angular/forms';
|
import { FormControl, FormGroup, Validators } from '@angular/forms';
|
||||||
import { NgbActiveModal, NgbModal } from '@ng-bootstrap/ng-bootstrap';
|
import { NgbActiveModal, NgbModal } from '@ng-bootstrap/ng-bootstrap';
|
||||||
import { ToastrService } from 'ngx-toastr';
|
import { ToastrService } from 'ngx-toastr';
|
||||||
import { ConfirmService } from 'src/app/shared/confirm.service';
|
import { ConfirmService } from 'src/app/shared/confirm.service';
|
||||||
@ -17,9 +17,9 @@ export class LibraryEditorModalComponent implements OnInit {
|
|||||||
|
|
||||||
@Input() library: Library | undefined = undefined;
|
@Input() library: Library | undefined = undefined;
|
||||||
|
|
||||||
libraryForm: UntypedFormGroup = new UntypedFormGroup({
|
libraryForm: FormGroup = new FormGroup({
|
||||||
name: new UntypedFormControl('', [Validators.required]),
|
name: new FormControl('', [Validators.required]),
|
||||||
type: new UntypedFormControl(0, [Validators.required])
|
type: new FormControl(0, [Validators.required])
|
||||||
});
|
});
|
||||||
|
|
||||||
selectedFolders: string[] = [];
|
selectedFolders: string[] = [];
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Component, Input, OnInit } from '@angular/core';
|
import { Component, Input, OnInit } from '@angular/core';
|
||||||
import { UntypedFormGroup, UntypedFormControl, Validators } from '@angular/forms';
|
import { FormGroup, FormControl, Validators } from '@angular/forms';
|
||||||
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
|
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
|
||||||
import { Library } from 'src/app/_models/library';
|
import { Library } from 'src/app/_models/library';
|
||||||
import { Member } from 'src/app/_models/member';
|
import { Member } from 'src/app/_models/member';
|
||||||
@ -19,7 +19,7 @@ export class EditUserComponent implements OnInit {
|
|||||||
selectedLibraries: Array<number> = [];
|
selectedLibraries: Array<number> = [];
|
||||||
isSaving: boolean = false;
|
isSaving: boolean = false;
|
||||||
|
|
||||||
userForm: UntypedFormGroup = new UntypedFormGroup({});
|
userForm: FormGroup = new FormGroup({});
|
||||||
|
|
||||||
public get email() { return this.userForm.get('email'); }
|
public get email() { return this.userForm.get('email'); }
|
||||||
public get username() { return this.userForm.get('username'); }
|
public get username() { return this.userForm.get('username'); }
|
||||||
@ -28,8 +28,8 @@ export class EditUserComponent implements OnInit {
|
|||||||
constructor(public modal: NgbActiveModal, private accountService: AccountService) { }
|
constructor(public modal: NgbActiveModal, private accountService: AccountService) { }
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.userForm.addControl('email', new UntypedFormControl(this.member.email, [Validators.required, Validators.email]));
|
this.userForm.addControl('email', new FormControl(this.member.email, [Validators.required, Validators.email]));
|
||||||
this.userForm.addControl('username', new UntypedFormControl(this.member.username, [Validators.required]));
|
this.userForm.addControl('username', new FormControl(this.member.username, [Validators.required]));
|
||||||
|
|
||||||
this.userForm.get('email')?.disable();
|
this.userForm.get('email')?.disable();
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { UntypedFormControl, UntypedFormGroup, Validators } from '@angular/forms';
|
import { FormControl, FormGroup, Validators } from '@angular/forms';
|
||||||
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
|
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
|
||||||
import { ToastrService } from 'ngx-toastr';
|
import { ToastrService } from 'ngx-toastr';
|
||||||
import { ConfirmService } from 'src/app/shared/confirm.service';
|
import { ConfirmService } from 'src/app/shared/confirm.service';
|
||||||
@ -19,7 +19,7 @@ export class InviteUserComponent implements OnInit {
|
|||||||
* Maintains if the backend is sending an email
|
* Maintains if the backend is sending an email
|
||||||
*/
|
*/
|
||||||
isSending: boolean = false;
|
isSending: boolean = false;
|
||||||
inviteForm: UntypedFormGroup = new UntypedFormGroup({});
|
inviteForm: FormGroup = new FormGroup({});
|
||||||
selectedRoles: Array<string> = [];
|
selectedRoles: Array<string> = [];
|
||||||
selectedLibraries: Array<number> = [];
|
selectedLibraries: Array<number> = [];
|
||||||
emailLink: string = '';
|
emailLink: string = '';
|
||||||
@ -32,7 +32,7 @@ export class InviteUserComponent implements OnInit {
|
|||||||
private confirmService: ConfirmService, private toastr: ToastrService) { }
|
private confirmService: ConfirmService, private toastr: ToastrService) { }
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.inviteForm.addControl('email', new UntypedFormControl('', [Validators.required]));
|
this.inviteForm.addControl('email', new FormControl('', [Validators.required]));
|
||||||
}
|
}
|
||||||
|
|
||||||
close() {
|
close() {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { UntypedFormControl, UntypedFormGroup, Validators } from '@angular/forms';
|
import { FormControl, FormGroup, Validators } from '@angular/forms';
|
||||||
import { ToastrService } from 'ngx-toastr';
|
import { ToastrService } from 'ngx-toastr';
|
||||||
import { take } from 'rxjs';
|
import { take } from 'rxjs';
|
||||||
import { SettingsService, EmailTestResult } from '../settings.service';
|
import { SettingsService, EmailTestResult } from '../settings.service';
|
||||||
@ -13,14 +13,14 @@ import { ServerSettings } from '../_models/server-settings';
|
|||||||
export class ManageEmailSettingsComponent implements OnInit {
|
export class ManageEmailSettingsComponent implements OnInit {
|
||||||
|
|
||||||
serverSettings!: ServerSettings;
|
serverSettings!: ServerSettings;
|
||||||
settingsForm: UntypedFormGroup = new UntypedFormGroup({});
|
settingsForm: FormGroup = new FormGroup({});
|
||||||
|
|
||||||
constructor(private settingsService: SettingsService, private toastr: ToastrService) { }
|
constructor(private settingsService: SettingsService, private toastr: ToastrService) { }
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.settingsService.getServerSettings().pipe(take(1)).subscribe((settings: ServerSettings) => {
|
this.settingsService.getServerSettings().pipe(take(1)).subscribe((settings: ServerSettings) => {
|
||||||
this.serverSettings = settings;
|
this.serverSettings = settings;
|
||||||
this.settingsForm.addControl('emailServiceUrl', new UntypedFormControl(this.serverSettings.emailServiceUrl, [Validators.required]));
|
this.settingsForm.addControl('emailServiceUrl', new FormControl(this.serverSettings.emailServiceUrl, [Validators.required]));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { UntypedFormGroup, UntypedFormControl, Validators } from '@angular/forms';
|
import { FormGroup, FormControl, Validators } from '@angular/forms';
|
||||||
import { ToastrService } from 'ngx-toastr';
|
import { ToastrService } from 'ngx-toastr';
|
||||||
import { take } from 'rxjs';
|
import { take } from 'rxjs';
|
||||||
import { SettingsService } from '../settings.service';
|
import { SettingsService } from '../settings.service';
|
||||||
@ -13,14 +13,14 @@ import { ServerSettings } from '../_models/server-settings';
|
|||||||
export class ManageMediaSettingsComponent implements OnInit {
|
export class ManageMediaSettingsComponent implements OnInit {
|
||||||
|
|
||||||
serverSettings!: ServerSettings;
|
serverSettings!: ServerSettings;
|
||||||
settingsForm: UntypedFormGroup = new UntypedFormGroup({});
|
settingsForm: FormGroup = new FormGroup({});
|
||||||
|
|
||||||
constructor(private settingsService: SettingsService, private toastr: ToastrService) { }
|
constructor(private settingsService: SettingsService, private toastr: ToastrService) { }
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.settingsService.getServerSettings().pipe(take(1)).subscribe((settings: ServerSettings) => {
|
this.settingsService.getServerSettings().pipe(take(1)).subscribe((settings: ServerSettings) => {
|
||||||
this.serverSettings = settings;
|
this.serverSettings = settings;
|
||||||
this.settingsForm.addControl('convertBookmarkToWebP', new UntypedFormControl(this.serverSettings.convertBookmarkToWebP, [Validators.required]));
|
this.settingsForm.addControl('convertBookmarkToWebP', new FormControl(this.serverSettings.convertBookmarkToWebP, [Validators.required]));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { UntypedFormControl, UntypedFormGroup, Validators } from '@angular/forms';
|
import { FormControl, FormGroup, Validators } from '@angular/forms';
|
||||||
import { ToastrService } from 'ngx-toastr';
|
import { ToastrService } from 'ngx-toastr';
|
||||||
import { take } from 'rxjs/operators';
|
import { take } from 'rxjs/operators';
|
||||||
import { ServerService } from 'src/app/_services/server.service';
|
import { ServerService } from 'src/app/_services/server.service';
|
||||||
@ -14,7 +14,7 @@ import { ServerSettings } from '../_models/server-settings';
|
|||||||
})
|
})
|
||||||
export class ManageSystemComponent implements OnInit {
|
export class ManageSystemComponent implements OnInit {
|
||||||
|
|
||||||
settingsForm: UntypedFormGroup = new UntypedFormGroup({});
|
settingsForm: FormGroup = new FormGroup({});
|
||||||
serverSettings!: ServerSettings;
|
serverSettings!: ServerSettings;
|
||||||
serverInfo!: ServerInfo;
|
serverInfo!: ServerInfo;
|
||||||
|
|
||||||
@ -30,12 +30,12 @@ export class ManageSystemComponent implements OnInit {
|
|||||||
|
|
||||||
this.settingsService.getServerSettings().pipe(take(1)).subscribe((settings: ServerSettings) => {
|
this.settingsService.getServerSettings().pipe(take(1)).subscribe((settings: ServerSettings) => {
|
||||||
this.serverSettings = settings;
|
this.serverSettings = settings;
|
||||||
this.settingsForm.addControl('cacheDirectory', new UntypedFormControl(this.serverSettings.cacheDirectory, [Validators.required]));
|
this.settingsForm.addControl('cacheDirectory', new FormControl(this.serverSettings.cacheDirectory, [Validators.required]));
|
||||||
this.settingsForm.addControl('taskScan', new UntypedFormControl(this.serverSettings.taskScan, [Validators.required]));
|
this.settingsForm.addControl('taskScan', new FormControl(this.serverSettings.taskScan, [Validators.required]));
|
||||||
this.settingsForm.addControl('taskBackup', new UntypedFormControl(this.serverSettings.taskBackup, [Validators.required]));
|
this.settingsForm.addControl('taskBackup', new FormControl(this.serverSettings.taskBackup, [Validators.required]));
|
||||||
this.settingsForm.addControl('port', new UntypedFormControl(this.serverSettings.port, [Validators.required]));
|
this.settingsForm.addControl('port', new FormControl(this.serverSettings.port, [Validators.required]));
|
||||||
this.settingsForm.addControl('loggingLevel', new UntypedFormControl(this.serverSettings.loggingLevel, [Validators.required]));
|
this.settingsForm.addControl('loggingLevel', new FormControl(this.serverSettings.loggingLevel, [Validators.required]));
|
||||||
this.settingsForm.addControl('allowStatCollection', new UntypedFormControl(this.serverSettings.allowStatCollection, [Validators.required]));
|
this.settingsForm.addControl('allowStatCollection', new FormControl(this.serverSettings.allowStatCollection, [Validators.required]));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { UntypedFormGroup, UntypedFormControl, Validators } from '@angular/forms';
|
import { FormGroup, FormControl, Validators } from '@angular/forms';
|
||||||
import { ToastrService } from 'ngx-toastr';
|
import { ToastrService } from 'ngx-toastr';
|
||||||
import { ConfirmService } from 'src/app/shared/confirm.service';
|
import { ConfirmService } from 'src/app/shared/confirm.service';
|
||||||
import { SettingsService } from '../settings.service';
|
import { SettingsService } from '../settings.service';
|
||||||
@ -28,7 +28,7 @@ interface AdhocTask {
|
|||||||
export class ManageTasksSettingsComponent implements OnInit {
|
export class ManageTasksSettingsComponent implements OnInit {
|
||||||
|
|
||||||
serverSettings!: ServerSettings;
|
serverSettings!: ServerSettings;
|
||||||
settingsForm: UntypedFormGroup = new UntypedFormGroup({});
|
settingsForm: FormGroup = new FormGroup({});
|
||||||
taskFrequencies: Array<string> = [];
|
taskFrequencies: Array<string> = [];
|
||||||
logLevels: Array<string> = [];
|
logLevels: Array<string> = [];
|
||||||
|
|
||||||
@ -89,8 +89,8 @@ export class ManageTasksSettingsComponent implements OnInit {
|
|||||||
this.taskFrequencies = result.frequencies;
|
this.taskFrequencies = result.frequencies;
|
||||||
this.logLevels = result.levels;
|
this.logLevels = result.levels;
|
||||||
this.serverSettings = result.settings;
|
this.serverSettings = result.settings;
|
||||||
this.settingsForm.addControl('taskScan', new UntypedFormControl(this.serverSettings.taskScan, [Validators.required]));
|
this.settingsForm.addControl('taskScan', new FormControl(this.serverSettings.taskScan, [Validators.required]));
|
||||||
this.settingsForm.addControl('taskBackup', new UntypedFormControl(this.serverSettings.taskBackup, [Validators.required]));
|
this.settingsForm.addControl('taskBackup', new FormControl(this.serverSettings.taskBackup, [Validators.required]));
|
||||||
});
|
});
|
||||||
|
|
||||||
this.reoccuringTasks$ = this.serverService.getReoccuringJobs().pipe(shareReplay());
|
this.reoccuringTasks$ = this.serverService.getReoccuringJobs().pipe(shareReplay());
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { DOCUMENT } from '@angular/common';
|
import { DOCUMENT } from '@angular/common';
|
||||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Inject, Input, OnDestroy, OnInit, Output } from '@angular/core';
|
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Inject, Input, OnDestroy, OnInit, Output } from '@angular/core';
|
||||||
import { UntypedFormControl, UntypedFormGroup } from '@angular/forms';
|
import { FormControl, FormGroup } from '@angular/forms';
|
||||||
import { Subject, take, takeUntil } from 'rxjs';
|
import { Subject, take, takeUntil } from 'rxjs';
|
||||||
import { BookPageLayoutMode } from 'src/app/_models/book-page-layout-mode';
|
import { BookPageLayoutMode } from 'src/app/_models/book-page-layout-mode';
|
||||||
import { BookTheme } from 'src/app/_models/preferences/book-theme';
|
import { BookTheme } from 'src/app/_models/preferences/book-theme';
|
||||||
@ -110,7 +110,7 @@ export class ReaderSettingsComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
isFullscreen: boolean = false;
|
isFullscreen: boolean = false;
|
||||||
|
|
||||||
settingsForm: UntypedFormGroup = new UntypedFormGroup({});
|
settingsForm: FormGroup = new FormGroup({});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* System provided themes
|
* System provided themes
|
||||||
@ -163,7 +163,7 @@ export class ReaderSettingsComponent implements OnInit, OnDestroy {
|
|||||||
this.readingDirectionModel = this.user.preferences.bookReaderReadingDirection;
|
this.readingDirectionModel = this.user.preferences.bookReaderReadingDirection;
|
||||||
|
|
||||||
|
|
||||||
this.settingsForm.addControl('bookReaderFontFamily', new UntypedFormControl(this.user.preferences.bookReaderFontFamily, []));
|
this.settingsForm.addControl('bookReaderFontFamily', new FormControl(this.user.preferences.bookReaderFontFamily, []));
|
||||||
this.settingsForm.get('bookReaderFontFamily')!.valueChanges.pipe(takeUntil(this.onDestroy)).subscribe(fontName => {
|
this.settingsForm.get('bookReaderFontFamily')!.valueChanges.pipe(takeUntil(this.onDestroy)).subscribe(fontName => {
|
||||||
const familyName = this.fontFamilies.filter(f => f.title === fontName)[0].family;
|
const familyName = this.fontFamilies.filter(f => f.title === fontName)[0].family;
|
||||||
if (familyName === 'default') {
|
if (familyName === 'default') {
|
||||||
@ -175,36 +175,36 @@ export class ReaderSettingsComponent implements OnInit, OnDestroy {
|
|||||||
this.styleUpdate.emit(this.pageStyles);
|
this.styleUpdate.emit(this.pageStyles);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.settingsForm.addControl('bookReaderFontSize', new UntypedFormControl(this.user.preferences.bookReaderFontSize, []));
|
this.settingsForm.addControl('bookReaderFontSize', new FormControl(this.user.preferences.bookReaderFontSize, []));
|
||||||
this.settingsForm.get('bookReaderFontSize')?.valueChanges.pipe(takeUntil(this.onDestroy)).subscribe(value => {
|
this.settingsForm.get('bookReaderFontSize')?.valueChanges.pipe(takeUntil(this.onDestroy)).subscribe(value => {
|
||||||
this.pageStyles['font-size'] = value + '%';
|
this.pageStyles['font-size'] = value + '%';
|
||||||
this.styleUpdate.emit(this.pageStyles);
|
this.styleUpdate.emit(this.pageStyles);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.settingsForm.addControl('bookReaderTapToPaginate', new UntypedFormControl(this.user.preferences.bookReaderTapToPaginate, []));
|
this.settingsForm.addControl('bookReaderTapToPaginate', new FormControl(this.user.preferences.bookReaderTapToPaginate, []));
|
||||||
this.settingsForm.get('bookReaderTapToPaginate')?.valueChanges.pipe(takeUntil(this.onDestroy)).subscribe(value => {
|
this.settingsForm.get('bookReaderTapToPaginate')?.valueChanges.pipe(takeUntil(this.onDestroy)).subscribe(value => {
|
||||||
this.clickToPaginateChanged.emit(value);
|
this.clickToPaginateChanged.emit(value);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.settingsForm.addControl('bookReaderLineSpacing', new UntypedFormControl(this.user.preferences.bookReaderLineSpacing, []));
|
this.settingsForm.addControl('bookReaderLineSpacing', new FormControl(this.user.preferences.bookReaderLineSpacing, []));
|
||||||
this.settingsForm.get('bookReaderLineSpacing')?.valueChanges.pipe(takeUntil(this.onDestroy)).subscribe(value => {
|
this.settingsForm.get('bookReaderLineSpacing')?.valueChanges.pipe(takeUntil(this.onDestroy)).subscribe(value => {
|
||||||
this.pageStyles['line-height'] = value + '%';
|
this.pageStyles['line-height'] = value + '%';
|
||||||
this.styleUpdate.emit(this.pageStyles);
|
this.styleUpdate.emit(this.pageStyles);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.settingsForm.addControl('bookReaderMargin', new UntypedFormControl(this.user.preferences.bookReaderMargin, []));
|
this.settingsForm.addControl('bookReaderMargin', new FormControl(this.user.preferences.bookReaderMargin, []));
|
||||||
this.settingsForm.get('bookReaderMargin')?.valueChanges.pipe(takeUntil(this.onDestroy)).subscribe(value => {
|
this.settingsForm.get('bookReaderMargin')?.valueChanges.pipe(takeUntil(this.onDestroy)).subscribe(value => {
|
||||||
this.pageStyles['margin-left'] = value + '%';
|
this.pageStyles['margin-left'] = value + '%';
|
||||||
this.pageStyles['margin-right'] = value + '%';
|
this.pageStyles['margin-right'] = value + '%';
|
||||||
this.styleUpdate.emit(this.pageStyles);
|
this.styleUpdate.emit(this.pageStyles);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.settingsForm.addControl('layoutMode', new UntypedFormControl(this.user.preferences.bookReaderLayoutMode || BookPageLayoutMode.Default, []));
|
this.settingsForm.addControl('layoutMode', new FormControl(this.user.preferences.bookReaderLayoutMode || BookPageLayoutMode.Default, []));
|
||||||
this.settingsForm.get('layoutMode')?.valueChanges.pipe(takeUntil(this.onDestroy)).subscribe((layoutMode: BookPageLayoutMode) => {
|
this.settingsForm.get('layoutMode')?.valueChanges.pipe(takeUntil(this.onDestroy)).subscribe((layoutMode: BookPageLayoutMode) => {
|
||||||
this.layoutModeUpdate.emit(layoutMode);
|
this.layoutModeUpdate.emit(layoutMode);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.settingsForm.addControl('bookReaderImmersiveMode', new UntypedFormControl(this.user.preferences.bookReaderImmersiveMode, []));
|
this.settingsForm.addControl('bookReaderImmersiveMode', new FormControl(this.user.preferences.bookReaderImmersiveMode, []));
|
||||||
this.settingsForm.get('bookReaderImmersiveMode')?.valueChanges.pipe(takeUntil(this.onDestroy)).subscribe((immersiveMode: boolean) => {
|
this.settingsForm.get('bookReaderImmersiveMode')?.valueChanges.pipe(takeUntil(this.onDestroy)).subscribe((immersiveMode: boolean) => {
|
||||||
if (immersiveMode) {
|
if (immersiveMode) {
|
||||||
this.settingsForm.get('bookReaderTapToPaginate')?.setValue(true);
|
this.settingsForm.get('bookReaderTapToPaginate')?.setValue(true);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, Input, OnInit, ViewChild, ViewEncapsulation } from '@angular/core';
|
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, Input, OnInit, ViewChild, ViewEncapsulation } from '@angular/core';
|
||||||
import { UntypedFormGroup, UntypedFormControl } from '@angular/forms';
|
import { FormGroup, FormControl } from '@angular/forms';
|
||||||
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
|
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
|
||||||
import { ToastrService } from 'ngx-toastr';
|
import { ToastrService } from 'ngx-toastr';
|
||||||
import { CollectionTag } from 'src/app/_models/collection-tag';
|
import { CollectionTag } from 'src/app/_models/collection-tag';
|
||||||
@ -26,7 +26,7 @@ export class BulkAddToCollectionComponent implements OnInit {
|
|||||||
*/
|
*/
|
||||||
lists: Array<CollectionTag> = [];
|
lists: Array<CollectionTag> = [];
|
||||||
loading: boolean = false;
|
loading: boolean = false;
|
||||||
listForm: UntypedFormGroup = new UntypedFormGroup({});
|
listForm: FormGroup = new FormGroup({});
|
||||||
|
|
||||||
collectionTitleTrackby = (index: number, item: CollectionTag) => `${item.title}`;
|
collectionTitleTrackby = (index: number, item: CollectionTag) => `${item.title}`;
|
||||||
|
|
||||||
@ -38,8 +38,8 @@ export class BulkAddToCollectionComponent implements OnInit {
|
|||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
|
|
||||||
this.listForm.addControl('title', new UntypedFormControl(this.title, []));
|
this.listForm.addControl('title', new FormControl(this.title, []));
|
||||||
this.listForm.addControl('filterQuery', new UntypedFormControl('', []));
|
this.listForm.addControl('filterQuery', new FormControl('', []));
|
||||||
|
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
this.cdRef.markForCheck();
|
this.cdRef.markForCheck();
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnInit } from '@angular/core';
|
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnInit } from '@angular/core';
|
||||||
import { UntypedFormControl, UntypedFormGroup } from '@angular/forms';
|
import { FormControl, FormGroup } from '@angular/forms';
|
||||||
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
|
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
|
||||||
import { ToastrService } from 'ngx-toastr';
|
import { ToastrService } from 'ngx-toastr';
|
||||||
import { forkJoin } from 'rxjs';
|
import { forkJoin } from 'rxjs';
|
||||||
@ -37,7 +37,7 @@ export class EditCollectionTagsComponent implements OnInit {
|
|||||||
pagination!: Pagination;
|
pagination!: Pagination;
|
||||||
selectAll: boolean = true;
|
selectAll: boolean = true;
|
||||||
libraryNames!: any;
|
libraryNames!: any;
|
||||||
collectionTagForm!: UntypedFormGroup;
|
collectionTagForm!: FormGroup;
|
||||||
tabs = [{title: 'General', id: TabID.General}, {title: 'Cover Image', id: TabID.CoverImage}];
|
tabs = [{title: 'General', id: TabID.General}, {title: 'Cover Image', id: TabID.CoverImage}];
|
||||||
active = TabID.General;
|
active = TabID.General;
|
||||||
imageUrls: Array<string> = [];
|
imageUrls: Array<string> = [];
|
||||||
@ -65,10 +65,10 @@ export class EditCollectionTagsComponent implements OnInit {
|
|||||||
if (this.pagination == undefined) {
|
if (this.pagination == undefined) {
|
||||||
this.pagination = {totalPages: 1, totalItems: 200, itemsPerPage: 200, currentPage: 0};
|
this.pagination = {totalPages: 1, totalItems: 200, itemsPerPage: 200, currentPage: 0};
|
||||||
}
|
}
|
||||||
this.collectionTagForm = new UntypedFormGroup({
|
this.collectionTagForm = new FormGroup({
|
||||||
summary: new UntypedFormControl(this.tag.summary, []),
|
summary: new FormControl(this.tag.summary, []),
|
||||||
coverImageLocked: new UntypedFormControl(this.tag.coverImageLocked, []),
|
coverImageLocked: new FormControl(this.tag.coverImageLocked, []),
|
||||||
coverImageIndex: new UntypedFormControl(0, []),
|
coverImageIndex: new FormControl(0, []),
|
||||||
|
|
||||||
});
|
});
|
||||||
this.imageUrls.push(this.imageService.randomize(this.imageService.getCollectionCoverImage(this.tag.id)));
|
this.imageUrls.push(this.imageService.randomize(this.imageService.getCollectionCoverImage(this.tag.id)));
|
||||||
|
@ -37,5 +37,17 @@
|
|||||||
(selection)="bulkSelectionService.handleCardSelection('series', position, series.length, $event)" [selected]="bulkSelectionService.isCardSelected('series', position)" [allowSelection]="true"
|
(selection)="bulkSelectionService.handleCardSelection('series', position, series.length, $event)" [selected]="bulkSelectionService.isCardSelected('series', position)" [allowSelection]="true"
|
||||||
></app-series-card>
|
></app-series-card>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
|
||||||
|
<div *ngIf="!filterActive && series.length === 0">
|
||||||
|
<ng-template #noData>
|
||||||
|
There are no items. Try adding a series.
|
||||||
|
</ng-template>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div *ngIf="filterActive && series.length === 0">
|
||||||
|
<ng-template #noData>
|
||||||
|
No items match your current filter.
|
||||||
|
</ng-template>
|
||||||
|
</div>
|
||||||
</app-card-detail-layout>
|
</app-card-detail-layout>
|
||||||
</div>
|
</div>
|
@ -1,5 +1,5 @@
|
|||||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ContentChild, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core';
|
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ContentChild, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core';
|
||||||
import { UntypedFormControl, UntypedFormGroup } from '@angular/forms';
|
import { FormControl, FormGroup } from '@angular/forms';
|
||||||
import { NgbCollapse } from '@ng-bootstrap/ng-bootstrap';
|
import { NgbCollapse } from '@ng-bootstrap/ng-bootstrap';
|
||||||
import { distinctUntilChanged, forkJoin, map, Observable, of, ReplaySubject, Subject, takeUntil } from 'rxjs';
|
import { distinctUntilChanged, forkJoin, map, Observable, of, ReplaySubject, Subject, takeUntil } from 'rxjs';
|
||||||
import { UtilityService } from '../shared/_services/utility.service';
|
import { UtilityService } from '../shared/_services/utility.service';
|
||||||
@ -66,9 +66,9 @@ export class MetadataFilterComponent implements OnInit, OnDestroy {
|
|||||||
libraries: Array<FilterItem<Library>> = [];
|
libraries: Array<FilterItem<Library>> = [];
|
||||||
|
|
||||||
|
|
||||||
readProgressGroup!: UntypedFormGroup;
|
readProgressGroup!: FormGroup;
|
||||||
sortGroup!: UntypedFormGroup;
|
sortGroup!: FormGroup;
|
||||||
seriesNameGroup!: UntypedFormGroup;
|
seriesNameGroup!: FormGroup;
|
||||||
isAscendingSort: boolean = true;
|
isAscendingSort: boolean = true;
|
||||||
|
|
||||||
updateApplied: number = 0;
|
updateApplied: number = 0;
|
||||||
@ -106,18 +106,18 @@ export class MetadataFilterComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.filter = this.seriesService.createSeriesFilter();
|
this.filter = this.seriesService.createSeriesFilter();
|
||||||
this.readProgressGroup = new UntypedFormGroup({
|
this.readProgressGroup = new FormGroup({
|
||||||
read: new UntypedFormControl({value: this.filter.readStatus.read, disabled: this.filterSettings.readProgressDisabled}, []),
|
read: new FormControl({value: this.filter.readStatus.read, disabled: this.filterSettings.readProgressDisabled}, []),
|
||||||
notRead: new UntypedFormControl({value: this.filter.readStatus.notRead, disabled: this.filterSettings.readProgressDisabled}, []),
|
notRead: new FormControl({value: this.filter.readStatus.notRead, disabled: this.filterSettings.readProgressDisabled}, []),
|
||||||
inProgress: new UntypedFormControl({value: this.filter.readStatus.inProgress, disabled: this.filterSettings.readProgressDisabled}, []),
|
inProgress: new FormControl({value: this.filter.readStatus.inProgress, disabled: this.filterSettings.readProgressDisabled}, []),
|
||||||
});
|
});
|
||||||
|
|
||||||
this.sortGroup = new UntypedFormGroup({
|
this.sortGroup = new FormGroup({
|
||||||
sortField: new UntypedFormControl({value: this.filter.sortOptions?.sortField || SortField.SortName, disabled: this.filterSettings.sortDisabled}, []),
|
sortField: new FormControl({value: this.filter.sortOptions?.sortField || SortField.SortName, disabled: this.filterSettings.sortDisabled}, []),
|
||||||
});
|
});
|
||||||
|
|
||||||
this.seriesNameGroup = new UntypedFormGroup({
|
this.seriesNameGroup = new FormGroup({
|
||||||
seriesNameQuery: new UntypedFormControl({value: this.filter.seriesNameQuery || '', disabled: this.filterSettings.searchNameDisabled}, [])
|
seriesNameQuery: new FormControl({value: this.filter.seriesNameQuery || '', disabled: this.filterSettings.searchNameDisabled}, [])
|
||||||
});
|
});
|
||||||
|
|
||||||
this.readProgressGroup.valueChanges.pipe(takeUntil(this.onDestroy)).subscribe(changes => {
|
this.readProgressGroup.valueChanges.pipe(takeUntil(this.onDestroy)).subscribe(changes => {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ContentChild, ElementRef, EventEmitter, HostListener, Input, OnDestroy, OnInit, Output, TemplateRef, ViewChild } from '@angular/core';
|
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ContentChild, ElementRef, EventEmitter, HostListener, Input, OnDestroy, OnInit, Output, TemplateRef, ViewChild } from '@angular/core';
|
||||||
import { UntypedFormControl, UntypedFormGroup } from '@angular/forms';
|
import { FormControl, FormGroup } from '@angular/forms';
|
||||||
import { Subject } from 'rxjs';
|
import { Subject } from 'rxjs';
|
||||||
import { debounceTime, takeUntil } from 'rxjs/operators';
|
import { debounceTime, takeUntil } from 'rxjs/operators';
|
||||||
import { KEY_CODES } from '../../shared/_services/utility.service';
|
import { KEY_CODES } from '../../shared/_services/utility.service';
|
||||||
@ -66,7 +66,7 @@ export class GroupedTypeaheadComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
hasFocus: boolean = false;
|
hasFocus: boolean = false;
|
||||||
isLoading: boolean = false;
|
isLoading: boolean = false;
|
||||||
typeaheadForm: UntypedFormGroup = new UntypedFormGroup({});
|
typeaheadForm: FormGroup = new FormGroup({});
|
||||||
|
|
||||||
prevSearchTerm: string = '';
|
prevSearchTerm: string = '';
|
||||||
|
|
||||||
@ -106,7 +106,7 @@ export class GroupedTypeaheadComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.typeaheadForm.addControl('typeahead', new UntypedFormControl(this.initialValue, []));
|
this.typeaheadForm.addControl('typeahead', new FormControl(this.initialValue, []));
|
||||||
this.cdRef.markForCheck();
|
this.cdRef.markForCheck();
|
||||||
|
|
||||||
this.typeaheadForm.valueChanges.pipe(debounceTime(this.debounceTime), takeUntil(this.onDestroy)).subscribe(change => {
|
this.typeaheadForm.valueChanges.pipe(debounceTime(this.debounceTime), takeUntil(this.onDestroy)).subscribe(change => {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { AfterViewInit, Component, ElementRef, Input, OnInit, ViewChild } from '@angular/core';
|
import { AfterViewInit, Component, ElementRef, Input, OnInit, ViewChild } from '@angular/core';
|
||||||
import { UntypedFormControl, UntypedFormGroup } from '@angular/forms';
|
import { FormControl, FormGroup } from '@angular/forms';
|
||||||
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
|
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
|
||||||
import { ToastrService } from 'ngx-toastr';
|
import { ToastrService } from 'ngx-toastr';
|
||||||
import { ReadingList } from 'src/app/_models/reading-list';
|
import { ReadingList } from 'src/app/_models/reading-list';
|
||||||
@ -56,7 +56,7 @@ export class AddToListModalComponent implements OnInit, AfterViewInit {
|
|||||||
*/
|
*/
|
||||||
lists: Array<any> = [];
|
lists: Array<any> = [];
|
||||||
loading: boolean = false;
|
loading: boolean = false;
|
||||||
listForm: UntypedFormGroup = new UntypedFormGroup({});
|
listForm: FormGroup = new FormGroup({});
|
||||||
|
|
||||||
@ViewChild('title') inputElem!: ElementRef<HTMLInputElement>;
|
@ViewChild('title') inputElem!: ElementRef<HTMLInputElement>;
|
||||||
|
|
||||||
@ -65,8 +65,8 @@ export class AddToListModalComponent implements OnInit, AfterViewInit {
|
|||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
|
|
||||||
this.listForm.addControl('title', new UntypedFormControl(this.title, []));
|
this.listForm.addControl('title', new FormControl(this.title, []));
|
||||||
this.listForm.addControl('filterQuery', new UntypedFormControl('', []));
|
this.listForm.addControl('filterQuery', new FormControl('', []));
|
||||||
|
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
this.readingListService.getReadingLists(false).subscribe(lists => {
|
this.readingListService.getReadingLists(false).subscribe(lists => {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Component, Input, OnInit } from '@angular/core';
|
import { Component, Input, OnInit } from '@angular/core';
|
||||||
import { UntypedFormGroup, UntypedFormControl, Validators } from '@angular/forms';
|
import { FormGroup, FormControl, Validators } from '@angular/forms';
|
||||||
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
|
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
|
||||||
import { ToastrService } from 'ngx-toastr';
|
import { ToastrService } from 'ngx-toastr';
|
||||||
import { forkJoin } from 'rxjs';
|
import { forkJoin } from 'rxjs';
|
||||||
@ -18,7 +18,7 @@ import { UploadService } from 'src/app/_services/upload.service';
|
|||||||
export class EditReadingListModalComponent implements OnInit {
|
export class EditReadingListModalComponent implements OnInit {
|
||||||
|
|
||||||
@Input() readingList!: ReadingList;
|
@Input() readingList!: ReadingList;
|
||||||
reviewGroup!: UntypedFormGroup;
|
reviewGroup!: FormGroup;
|
||||||
|
|
||||||
coverImageIndex: number = 0;
|
coverImageIndex: number = 0;
|
||||||
/**
|
/**
|
||||||
@ -41,9 +41,9 @@ export class EditReadingListModalComponent implements OnInit {
|
|||||||
private imageService: ImageService) { }
|
private imageService: ImageService) { }
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.reviewGroup = new UntypedFormGroup({
|
this.reviewGroup = new FormGroup({
|
||||||
title: new UntypedFormControl(this.readingList.title, [Validators.required]),
|
title: new FormControl(this.readingList.title, [Validators.required]),
|
||||||
summary: new UntypedFormControl(this.readingList.summary, [])
|
summary: new FormControl(this.readingList.summary, [])
|
||||||
});
|
});
|
||||||
|
|
||||||
this.imageUrls.push(this.imageService.randomize(this.imageService.getReadingListCoverImage(this.readingList.id)));
|
this.imageUrls.push(this.imageService.randomize(this.imageService.getReadingListCoverImage(this.readingList.id)));
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnInit } from '@angular/core';
|
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnInit } from '@angular/core';
|
||||||
import { UntypedFormControl, UntypedFormGroup, Validators } from '@angular/forms';
|
import { FormControl, FormGroup, Validators } from '@angular/forms';
|
||||||
import { SafeUrl } from '@angular/platform-browser';
|
import { SafeUrl } from '@angular/platform-browser';
|
||||||
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
|
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
|
||||||
import { ToastrService } from 'ngx-toastr';
|
import { ToastrService } from 'ngx-toastr';
|
||||||
@ -17,7 +17,7 @@ export class AddEmailToAccountMigrationModalComponent implements OnInit {
|
|||||||
@Input() password!: string;
|
@Input() password!: string;
|
||||||
|
|
||||||
isSaving: boolean = false;
|
isSaving: boolean = false;
|
||||||
registerForm: UntypedFormGroup = new UntypedFormGroup({});
|
registerForm: FormGroup = new FormGroup({});
|
||||||
emailLink: string = '';
|
emailLink: string = '';
|
||||||
emailLinkUrl: SafeUrl | undefined;
|
emailLinkUrl: SafeUrl | undefined;
|
||||||
error: string = '';
|
error: string = '';
|
||||||
@ -27,9 +27,9 @@ export class AddEmailToAccountMigrationModalComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.registerForm.addControl('username', new UntypedFormControl(this.username, [Validators.required]));
|
this.registerForm.addControl('username', new FormControl(this.username, [Validators.required]));
|
||||||
this.registerForm.addControl('email', new UntypedFormControl('', [Validators.required, Validators.email]));
|
this.registerForm.addControl('email', new FormControl('', [Validators.required, Validators.email]));
|
||||||
this.registerForm.addControl('password', new UntypedFormControl(this.password, [Validators.required]));
|
this.registerForm.addControl('password', new FormControl(this.password, [Validators.required]));
|
||||||
this.cdRef.markForCheck();
|
this.cdRef.markForCheck();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component } from '@angular/core';
|
import { ChangeDetectionStrategy, ChangeDetectorRef, Component } from '@angular/core';
|
||||||
import { UntypedFormControl, UntypedFormGroup, Validators } from '@angular/forms';
|
import { FormControl, FormGroup, Validators } from '@angular/forms';
|
||||||
import { ActivatedRoute, Router } from '@angular/router';
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
import { ToastrService } from 'ngx-toastr';
|
import { ToastrService } from 'ngx-toastr';
|
||||||
import { ThemeService } from 'src/app/_services/theme.service';
|
import { ThemeService } from 'src/app/_services/theme.service';
|
||||||
@ -18,10 +18,10 @@ export class ConfirmEmailComponent {
|
|||||||
*/
|
*/
|
||||||
token: string = '';
|
token: string = '';
|
||||||
|
|
||||||
registerForm: UntypedFormGroup = new UntypedFormGroup({
|
registerForm: FormGroup = new FormGroup({
|
||||||
email: new UntypedFormControl('', [Validators.required, Validators.email]),
|
email: new FormControl('', [Validators.required, Validators.email]),
|
||||||
username: new UntypedFormControl('', [Validators.required]),
|
username: new FormControl('', [Validators.required]),
|
||||||
password: new UntypedFormControl('', [Validators.required, Validators.maxLength(32), Validators.minLength(6)]),
|
password: new FormControl('', [Validators.required, Validators.maxLength(32), Validators.minLength(6)]),
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<app-splash-container>
|
<app-splash-container>
|
||||||
<ng-container title><h2>Password Reset</h2></ng-container>
|
<ng-container title><h2>Password Reset</h2></ng-container>
|
||||||
<ng-container body>
|
<ng-container body>
|
||||||
<p>Enter the email of your account. We will send you an email </p>
|
<p>Enter the new password</p>
|
||||||
<form [formGroup]="registerForm" (ngSubmit)="submit()">
|
<form [formGroup]="registerForm" (ngSubmit)="submit()">
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="password" class="form-label">Password</label> <i class="fa fa-info-circle" placement="right" [ngbTooltip]="passwordTooltip" role="button" tabindex="0"></i>
|
<label for="password" class="form-label">Password</label> <i class="fa fa-info-circle" placement="right" [ngbTooltip]="passwordTooltip" role="button" tabindex="0"></i>
|
||||||
|
@ -0,0 +1,4 @@
|
|||||||
|
input {
|
||||||
|
background-color: #fff !important;
|
||||||
|
color: black !important;
|
||||||
|
}
|
@ -1,8 +1,9 @@
|
|||||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component } from '@angular/core';
|
import { ChangeDetectionStrategy, ChangeDetectorRef, Component } from '@angular/core';
|
||||||
import { UntypedFormGroup, UntypedFormControl, Validators } from '@angular/forms';
|
import { FormGroup, FormControl, Validators } from '@angular/forms';
|
||||||
import { ActivatedRoute, Router } from '@angular/router';
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
import { ToastrService } from 'ngx-toastr';
|
import { ToastrService } from 'ngx-toastr';
|
||||||
import { AccountService } from 'src/app/_services/account.service';
|
import { AccountService } from 'src/app/_services/account.service';
|
||||||
|
import { NavService } from 'src/app/_services/nav.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-confirm-reset-password',
|
selector: 'app-confirm-reset-password',
|
||||||
@ -13,14 +14,18 @@ import { AccountService } from 'src/app/_services/account.service';
|
|||||||
export class ConfirmResetPasswordComponent {
|
export class ConfirmResetPasswordComponent {
|
||||||
|
|
||||||
token: string = '';
|
token: string = '';
|
||||||
registerForm: UntypedFormGroup = new UntypedFormGroup({
|
registerForm: FormGroup = new FormGroup({
|
||||||
email: new UntypedFormControl('', [Validators.required, Validators.email]),
|
email: new FormControl('', [Validators.required, Validators.email]),
|
||||||
password: new UntypedFormControl('', [Validators.required, Validators.maxLength(32), Validators.minLength(6)]),
|
password: new FormControl('', [Validators.required, Validators.maxLength(32), Validators.minLength(6)]),
|
||||||
});
|
});
|
||||||
|
|
||||||
constructor(private route: ActivatedRoute, private router: Router,
|
constructor(private route: ActivatedRoute, private router: Router,
|
||||||
private accountService: AccountService, private toastr: ToastrService,
|
private accountService: AccountService, private toastr: ToastrService,
|
||||||
private readonly cdRef: ChangeDetectorRef) {
|
private readonly cdRef: ChangeDetectorRef, private navService: NavService) {
|
||||||
|
|
||||||
|
this.navService.showNavBar();
|
||||||
|
this.navService.hideSideNav();
|
||||||
|
|
||||||
|
|
||||||
const token = this.route.snapshot.queryParamMap.get('token');
|
const token = this.route.snapshot.queryParamMap.get('token');
|
||||||
const email = this.route.snapshot.queryParamMap.get('email');
|
const email = this.route.snapshot.queryParamMap.get('email');
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
|
import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
|
||||||
import { UntypedFormGroup, UntypedFormControl, Validators } from '@angular/forms';
|
import { FormGroup, FormControl, Validators } from '@angular/forms';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
import { ToastrService } from 'ngx-toastr';
|
import { ToastrService } from 'ngx-toastr';
|
||||||
import { take } from 'rxjs/operators';
|
import { take } from 'rxjs/operators';
|
||||||
@ -17,10 +17,10 @@ import { MemberService } from 'src/app/_services/member.service';
|
|||||||
})
|
})
|
||||||
export class RegisterComponent implements OnInit {
|
export class RegisterComponent implements OnInit {
|
||||||
|
|
||||||
registerForm: UntypedFormGroup = new UntypedFormGroup({
|
registerForm: FormGroup = new FormGroup({
|
||||||
email: new UntypedFormControl('', [Validators.required, Validators.email]),
|
email: new FormControl('', [Validators.required, Validators.email]),
|
||||||
username: new UntypedFormControl('', [Validators.required]),
|
username: new FormControl('', [Validators.required]),
|
||||||
password: new UntypedFormControl('', [Validators.required, Validators.maxLength(32), Validators.minLength(6)]),
|
password: new FormControl('', [Validators.required, Validators.maxLength(32), Validators.minLength(6)]),
|
||||||
});
|
});
|
||||||
|
|
||||||
constructor(private router: Router, private accountService: AccountService,
|
constructor(private router: Router, private accountService: AccountService,
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnInit } from '@angular/core';
|
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnInit } from '@angular/core';
|
||||||
import { UntypedFormGroup, UntypedFormControl, Validators } from '@angular/forms';
|
import { FormGroup, FormControl, Validators } from '@angular/forms';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
|
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
|
||||||
import { ToastrService } from 'ngx-toastr';
|
import { ToastrService } from 'ngx-toastr';
|
||||||
@ -20,9 +20,9 @@ import { NavService } from '../../_services/nav.service';
|
|||||||
export class UserLoginComponent implements OnInit {
|
export class UserLoginComponent implements OnInit {
|
||||||
|
|
||||||
//model: any = {username: '', password: ''};
|
//model: any = {username: '', password: ''};
|
||||||
loginForm: UntypedFormGroup = new UntypedFormGroup({
|
loginForm: FormGroup = new FormGroup({
|
||||||
username: new UntypedFormControl('', [Validators.required]),
|
username: new FormControl('', [Validators.required]),
|
||||||
password: new UntypedFormControl('', [Validators.required])
|
password: new FormControl('', [Validators.required])
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnInit } from '@angular/core';
|
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnInit } from '@angular/core';
|
||||||
import { UntypedFormControl, UntypedFormGroup } from '@angular/forms';
|
import { FormControl, FormGroup } from '@angular/forms';
|
||||||
import { NgbModal, NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
|
import { NgbModal, NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
|
||||||
import { Series } from 'src/app/_models/series';
|
import { Series } from 'src/app/_models/series';
|
||||||
import { SeriesService } from 'src/app/_services/series.service';
|
import { SeriesService } from 'src/app/_services/series.service';
|
||||||
@ -13,14 +13,14 @@ import { SeriesService } from 'src/app/_services/series.service';
|
|||||||
export class ReviewSeriesModalComponent implements OnInit {
|
export class ReviewSeriesModalComponent implements OnInit {
|
||||||
|
|
||||||
@Input() series!: Series;
|
@Input() series!: Series;
|
||||||
reviewGroup!: UntypedFormGroup;
|
reviewGroup!: FormGroup;
|
||||||
|
|
||||||
constructor(public modal: NgbActiveModal, private seriesService: SeriesService, private readonly cdRef: ChangeDetectorRef) {}
|
constructor(public modal: NgbActiveModal, private seriesService: SeriesService, private readonly cdRef: ChangeDetectorRef) {}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.reviewGroup = new UntypedFormGroup({
|
this.reviewGroup = new FormGroup({
|
||||||
review: new UntypedFormControl(this.series.userReview, []),
|
review: new FormControl(this.series.userReview, []),
|
||||||
rating: new UntypedFormControl(this.series.userRating, [])
|
rating: new FormControl(this.series.userRating, [])
|
||||||
});
|
});
|
||||||
this.cdRef.markForCheck();
|
this.cdRef.markForCheck();
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ import { NavService } from '../_services/nav.service';
|
|||||||
import { RelatedSeries } from '../_models/series-detail/related-series';
|
import { RelatedSeries } from '../_models/series-detail/related-series';
|
||||||
import { RelationKind } from '../_models/series-detail/relation-kind';
|
import { RelationKind } from '../_models/series-detail/relation-kind';
|
||||||
import { CardDetailDrawerComponent } from '../cards/card-detail-drawer/card-detail-drawer.component';
|
import { CardDetailDrawerComponent } from '../cards/card-detail-drawer/card-detail-drawer.component';
|
||||||
import { FormGroup, UntypedFormControl, UntypedFormGroup } from '@angular/forms';
|
import { FormGroup, FormControl } from '@angular/forms';
|
||||||
import { PageLayoutMode } from '../_models/page-layout-mode';
|
import { PageLayoutMode } from '../_models/page-layout-mode';
|
||||||
import { DOCUMENT } from '@angular/common';
|
import { DOCUMENT } from '@angular/common';
|
||||||
import { User } from '../_models/user';
|
import { User } from '../_models/user';
|
||||||
@ -151,8 +151,8 @@ export class SeriesDetailComponent implements OnInit, OnDestroy, AfterContentChe
|
|||||||
renderMode: PageLayoutMode = PageLayoutMode.Cards;
|
renderMode: PageLayoutMode = PageLayoutMode.Cards;
|
||||||
|
|
||||||
pageExtrasGroup = new FormGroup({
|
pageExtrasGroup = new FormGroup({
|
||||||
'sortingOption': new UntypedFormControl(this.sortingOptions[0].value, []),
|
'sortingOption': new FormControl(this.sortingOptions[0].value, []),
|
||||||
'renderMode': new UntypedFormControl(this.renderMode, []),
|
'renderMode': new FormControl(this.renderMode, []),
|
||||||
});
|
});
|
||||||
|
|
||||||
isAscendingSort: boolean = false; // TODO: Get this from User preferences
|
isAscendingSort: boolean = false; // TODO: Get this from User preferences
|
||||||
@ -299,7 +299,8 @@ export class SeriesDetailComponent implements OnInit, OnDestroy, AfterContentChe
|
|||||||
this.changeDetectionRef.markForCheck();
|
this.changeDetectionRef.markForCheck();
|
||||||
this.loadSeries(this.seriesId);
|
this.loadSeries(this.seriesId);
|
||||||
|
|
||||||
this.pageExtrasGroup.get('renderMode')?.valueChanges.pipe(takeUntil(this.onDestroy)).subscribe((val: PageLayoutMode) => {
|
this.pageExtrasGroup.get('renderMode')?.valueChanges.pipe(takeUntil(this.onDestroy)).subscribe((val: PageLayoutMode | null) => {
|
||||||
|
if (val == null) return;
|
||||||
this.renderMode = val;
|
this.renderMode = val;
|
||||||
this.changeDetectionRef.markForCheck();
|
this.changeDetectionRef.markForCheck();
|
||||||
});
|
});
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { UntypedFormControl } from '@angular/forms';
|
import { FormControl } from '@angular/forms';
|
||||||
|
|
||||||
export type SelectionCompareFn<T> = (a: T, b: T) => boolean;
|
export type SelectionCompareFn<T> = (a: T, b: T) => boolean;
|
||||||
|
|
||||||
@ -48,7 +48,7 @@ export class TypeaheadSettings<T> {
|
|||||||
/**
|
/**
|
||||||
* Optional form Control to tie model to.
|
* Optional form Control to tie model to.
|
||||||
*/
|
*/
|
||||||
formControl?: UntypedFormControl;
|
formControl?: FormControl;
|
||||||
/**
|
/**
|
||||||
* If true, typeahead will remove already selected items from fetchFn results. Only appies when multiple=true
|
* If true, typeahead will remove already selected items from fetchFn results. Only appies when multiple=true
|
||||||
*/
|
*/
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { trigger, state, style, transition, animate } from '@angular/animations';
|
import { trigger, state, style, transition, animate } from '@angular/animations';
|
||||||
import { DOCUMENT } from '@angular/common';
|
import { DOCUMENT } from '@angular/common';
|
||||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ContentChild, ElementRef, EventEmitter, HostListener, Inject, Input, OnDestroy, OnInit, Output, Renderer2, RendererStyleFlags2, TemplateRef, ViewChild } from '@angular/core';
|
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ContentChild, ElementRef, EventEmitter, HostListener, Inject, Input, OnDestroy, OnInit, Output, Renderer2, RendererStyleFlags2, TemplateRef, ViewChild } from '@angular/core';
|
||||||
import { UntypedFormControl, UntypedFormGroup } from '@angular/forms';
|
import { FormControl, FormGroup } from '@angular/forms';
|
||||||
import { Observable, of, ReplaySubject, Subject } from 'rxjs';
|
import { Observable, of, ReplaySubject, Subject } from 'rxjs';
|
||||||
import { auditTime, distinctUntilChanged, filter, map, shareReplay, switchMap, take, takeUntil, tap } from 'rxjs/operators';
|
import { auditTime, distinctUntilChanged, filter, map, shareReplay, switchMap, take, takeUntil, tap } from 'rxjs/operators';
|
||||||
import { KEY_CODES } from '../shared/_services/utility.service';
|
import { KEY_CODES } from '../shared/_services/utility.service';
|
||||||
@ -189,8 +189,8 @@ export class TypeaheadComponent implements OnInit, OnDestroy {
|
|||||||
showAddItem: boolean = false;
|
showAddItem: boolean = false;
|
||||||
filteredOptions!: Observable<string[]>;
|
filteredOptions!: Observable<string[]>;
|
||||||
isLoadingOptions: boolean = false;
|
isLoadingOptions: boolean = false;
|
||||||
typeaheadControl!: UntypedFormControl;
|
typeaheadControl!: FormControl;
|
||||||
typeaheadForm!: UntypedFormGroup;
|
typeaheadForm!: FormGroup;
|
||||||
|
|
||||||
private readonly onDestroy = new Subject<void>();
|
private readonly onDestroy = new Subject<void>();
|
||||||
|
|
||||||
@ -230,9 +230,9 @@ export class TypeaheadComponent implements OnInit, OnDestroy {
|
|||||||
if (this.settings.hasOwnProperty('formControl') && this.settings.formControl) {
|
if (this.settings.hasOwnProperty('formControl') && this.settings.formControl) {
|
||||||
this.typeaheadControl = this.settings.formControl;
|
this.typeaheadControl = this.settings.formControl;
|
||||||
} else {
|
} else {
|
||||||
this.typeaheadControl = new UntypedFormControl('');
|
this.typeaheadControl = new FormControl('');
|
||||||
}
|
}
|
||||||
this.typeaheadForm = new UntypedFormGroup({
|
this.typeaheadForm = new FormGroup({
|
||||||
'typeahead': this.typeaheadControl
|
'typeahead': this.typeaheadControl
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user