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")]
|
||||
public async Task<ActionResult<string>> ConfirmForgotPassword(ConfirmPasswordResetDto dto)
|
||||
{
|
||||
var user = await _unitOfWork.UserRepository.GetUserByEmailAsync(dto.Email);
|
||||
if (user == null)
|
||||
try
|
||||
{
|
||||
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();
|
||||
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
|
||||
_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)
|
||||
{
|
||||
var user = await _unitOfWork.UserRepository.GetUserByUsernameAsync(username);
|
||||
if (user == null) return;
|
||||
var isAdmin = await _unitOfWork.UserRepository.IsUserAdminAsync(user);
|
||||
lock (OnlineUsers)
|
||||
{
|
||||
|
@ -185,8 +185,6 @@ namespace API
|
||||
var themeService = serviceProvider.GetRequiredService<IThemeService>();
|
||||
var dataContext = serviceProvider.GetRequiredService<DataContext>();
|
||||
|
||||
await MigrateBookmarks.Migrate(directoryService, unitOfWork,
|
||||
logger, cacheService);
|
||||
|
||||
// Only run this if we are upgrading
|
||||
await MigrateChangePasswordRoles.Migrate(unitOfWork, userManager);
|
||||
|
@ -165,7 +165,7 @@ export class AccountService implements OnDestroy {
|
||||
}
|
||||
|
||||
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) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
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 { ToastrService } from 'ngx-toastr';
|
||||
import { ConfirmService } from 'src/app/shared/confirm.service';
|
||||
@ -17,9 +17,9 @@ export class LibraryEditorModalComponent implements OnInit {
|
||||
|
||||
@Input() library: Library | undefined = undefined;
|
||||
|
||||
libraryForm: UntypedFormGroup = new UntypedFormGroup({
|
||||
name: new UntypedFormControl('', [Validators.required]),
|
||||
type: new UntypedFormControl(0, [Validators.required])
|
||||
libraryForm: FormGroup = new FormGroup({
|
||||
name: new FormControl('', [Validators.required]),
|
||||
type: new FormControl(0, [Validators.required])
|
||||
});
|
||||
|
||||
selectedFolders: string[] = [];
|
||||
|
@ -1,5 +1,5 @@
|
||||
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 { Library } from 'src/app/_models/library';
|
||||
import { Member } from 'src/app/_models/member';
|
||||
@ -19,7 +19,7 @@ export class EditUserComponent implements OnInit {
|
||||
selectedLibraries: Array<number> = [];
|
||||
isSaving: boolean = false;
|
||||
|
||||
userForm: UntypedFormGroup = new UntypedFormGroup({});
|
||||
userForm: FormGroup = new FormGroup({});
|
||||
|
||||
public get email() { return this.userForm.get('email'); }
|
||||
public get username() { return this.userForm.get('username'); }
|
||||
@ -28,8 +28,8 @@ export class EditUserComponent implements OnInit {
|
||||
constructor(public modal: NgbActiveModal, private accountService: AccountService) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
this.userForm.addControl('email', new UntypedFormControl(this.member.email, [Validators.required, Validators.email]));
|
||||
this.userForm.addControl('username', new UntypedFormControl(this.member.username, [Validators.required]));
|
||||
this.userForm.addControl('email', new FormControl(this.member.email, [Validators.required, Validators.email]));
|
||||
this.userForm.addControl('username', new FormControl(this.member.username, [Validators.required]));
|
||||
|
||||
this.userForm.get('email')?.disable();
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
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 { ToastrService } from 'ngx-toastr';
|
||||
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
|
||||
*/
|
||||
isSending: boolean = false;
|
||||
inviteForm: UntypedFormGroup = new UntypedFormGroup({});
|
||||
inviteForm: FormGroup = new FormGroup({});
|
||||
selectedRoles: Array<string> = [];
|
||||
selectedLibraries: Array<number> = [];
|
||||
emailLink: string = '';
|
||||
@ -32,7 +32,7 @@ export class InviteUserComponent implements OnInit {
|
||||
private confirmService: ConfirmService, private toastr: ToastrService) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
this.inviteForm.addControl('email', new UntypedFormControl('', [Validators.required]));
|
||||
this.inviteForm.addControl('email', new FormControl('', [Validators.required]));
|
||||
}
|
||||
|
||||
close() {
|
||||
|
@ -1,5 +1,5 @@
|
||||
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 { take } from 'rxjs';
|
||||
import { SettingsService, EmailTestResult } from '../settings.service';
|
||||
@ -13,14 +13,14 @@ import { ServerSettings } from '../_models/server-settings';
|
||||
export class ManageEmailSettingsComponent implements OnInit {
|
||||
|
||||
serverSettings!: ServerSettings;
|
||||
settingsForm: UntypedFormGroup = new UntypedFormGroup({});
|
||||
settingsForm: FormGroup = new FormGroup({});
|
||||
|
||||
constructor(private settingsService: SettingsService, private toastr: ToastrService) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
this.settingsService.getServerSettings().pipe(take(1)).subscribe((settings: ServerSettings) => {
|
||||
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 { UntypedFormGroup, UntypedFormControl, Validators } from '@angular/forms';
|
||||
import { FormGroup, FormControl, Validators } from '@angular/forms';
|
||||
import { ToastrService } from 'ngx-toastr';
|
||||
import { take } from 'rxjs';
|
||||
import { SettingsService } from '../settings.service';
|
||||
@ -13,14 +13,14 @@ import { ServerSettings } from '../_models/server-settings';
|
||||
export class ManageMediaSettingsComponent implements OnInit {
|
||||
|
||||
serverSettings!: ServerSettings;
|
||||
settingsForm: UntypedFormGroup = new UntypedFormGroup({});
|
||||
settingsForm: FormGroup = new FormGroup({});
|
||||
|
||||
constructor(private settingsService: SettingsService, private toastr: ToastrService) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
this.settingsService.getServerSettings().pipe(take(1)).subscribe((settings: ServerSettings) => {
|
||||
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 { UntypedFormControl, UntypedFormGroup, Validators } from '@angular/forms';
|
||||
import { FormControl, FormGroup, Validators } from '@angular/forms';
|
||||
import { ToastrService } from 'ngx-toastr';
|
||||
import { take } from 'rxjs/operators';
|
||||
import { ServerService } from 'src/app/_services/server.service';
|
||||
@ -14,7 +14,7 @@ import { ServerSettings } from '../_models/server-settings';
|
||||
})
|
||||
export class ManageSystemComponent implements OnInit {
|
||||
|
||||
settingsForm: UntypedFormGroup = new UntypedFormGroup({});
|
||||
settingsForm: FormGroup = new FormGroup({});
|
||||
serverSettings!: ServerSettings;
|
||||
serverInfo!: ServerInfo;
|
||||
|
||||
@ -30,12 +30,12 @@ export class ManageSystemComponent implements OnInit {
|
||||
|
||||
this.settingsService.getServerSettings().pipe(take(1)).subscribe((settings: ServerSettings) => {
|
||||
this.serverSettings = settings;
|
||||
this.settingsForm.addControl('cacheDirectory', new UntypedFormControl(this.serverSettings.cacheDirectory, [Validators.required]));
|
||||
this.settingsForm.addControl('taskScan', new UntypedFormControl(this.serverSettings.taskScan, [Validators.required]));
|
||||
this.settingsForm.addControl('taskBackup', new UntypedFormControl(this.serverSettings.taskBackup, [Validators.required]));
|
||||
this.settingsForm.addControl('port', new UntypedFormControl(this.serverSettings.port, [Validators.required]));
|
||||
this.settingsForm.addControl('loggingLevel', new UntypedFormControl(this.serverSettings.loggingLevel, [Validators.required]));
|
||||
this.settingsForm.addControl('allowStatCollection', new UntypedFormControl(this.serverSettings.allowStatCollection, [Validators.required]));
|
||||
this.settingsForm.addControl('cacheDirectory', new FormControl(this.serverSettings.cacheDirectory, [Validators.required]));
|
||||
this.settingsForm.addControl('taskScan', new FormControl(this.serverSettings.taskScan, [Validators.required]));
|
||||
this.settingsForm.addControl('taskBackup', new FormControl(this.serverSettings.taskBackup, [Validators.required]));
|
||||
this.settingsForm.addControl('port', new FormControl(this.serverSettings.port, [Validators.required]));
|
||||
this.settingsForm.addControl('loggingLevel', new FormControl(this.serverSettings.loggingLevel, [Validators.required]));
|
||||
this.settingsForm.addControl('allowStatCollection', new FormControl(this.serverSettings.allowStatCollection, [Validators.required]));
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
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 { ConfirmService } from 'src/app/shared/confirm.service';
|
||||
import { SettingsService } from '../settings.service';
|
||||
@ -28,7 +28,7 @@ interface AdhocTask {
|
||||
export class ManageTasksSettingsComponent implements OnInit {
|
||||
|
||||
serverSettings!: ServerSettings;
|
||||
settingsForm: UntypedFormGroup = new UntypedFormGroup({});
|
||||
settingsForm: FormGroup = new FormGroup({});
|
||||
taskFrequencies: Array<string> = [];
|
||||
logLevels: Array<string> = [];
|
||||
|
||||
@ -89,8 +89,8 @@ export class ManageTasksSettingsComponent implements OnInit {
|
||||
this.taskFrequencies = result.frequencies;
|
||||
this.logLevels = result.levels;
|
||||
this.serverSettings = result.settings;
|
||||
this.settingsForm.addControl('taskScan', new UntypedFormControl(this.serverSettings.taskScan, [Validators.required]));
|
||||
this.settingsForm.addControl('taskBackup', new UntypedFormControl(this.serverSettings.taskBackup, [Validators.required]));
|
||||
this.settingsForm.addControl('taskScan', new FormControl(this.serverSettings.taskScan, [Validators.required]));
|
||||
this.settingsForm.addControl('taskBackup', new FormControl(this.serverSettings.taskBackup, [Validators.required]));
|
||||
});
|
||||
|
||||
this.reoccuringTasks$ = this.serverService.getReoccuringJobs().pipe(shareReplay());
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { DOCUMENT } from '@angular/common';
|
||||
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 { BookPageLayoutMode } from 'src/app/_models/book-page-layout-mode';
|
||||
import { BookTheme } from 'src/app/_models/preferences/book-theme';
|
||||
@ -110,7 +110,7 @@ export class ReaderSettingsComponent implements OnInit, OnDestroy {
|
||||
|
||||
isFullscreen: boolean = false;
|
||||
|
||||
settingsForm: UntypedFormGroup = new UntypedFormGroup({});
|
||||
settingsForm: FormGroup = new FormGroup({});
|
||||
|
||||
/**
|
||||
* System provided themes
|
||||
@ -163,7 +163,7 @@ export class ReaderSettingsComponent implements OnInit, OnDestroy {
|
||||
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 => {
|
||||
const familyName = this.fontFamilies.filter(f => f.title === fontName)[0].family;
|
||||
if (familyName === 'default') {
|
||||
@ -175,36 +175,36 @@ export class ReaderSettingsComponent implements OnInit, OnDestroy {
|
||||
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.pageStyles['font-size'] = value + '%';
|
||||
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.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.pageStyles['line-height'] = value + '%';
|
||||
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.pageStyles['margin-left'] = value + '%';
|
||||
this.pageStyles['margin-right'] = value + '%';
|
||||
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.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) => {
|
||||
if (immersiveMode) {
|
||||
this.settingsForm.get('bookReaderTapToPaginate')?.setValue(true);
|
||||
|
@ -1,5 +1,5 @@
|
||||
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 { ToastrService } from 'ngx-toastr';
|
||||
import { CollectionTag } from 'src/app/_models/collection-tag';
|
||||
@ -26,7 +26,7 @@ export class BulkAddToCollectionComponent implements OnInit {
|
||||
*/
|
||||
lists: Array<CollectionTag> = [];
|
||||
loading: boolean = false;
|
||||
listForm: UntypedFormGroup = new UntypedFormGroup({});
|
||||
listForm: FormGroup = new FormGroup({});
|
||||
|
||||
collectionTitleTrackby = (index: number, item: CollectionTag) => `${item.title}`;
|
||||
|
||||
@ -38,8 +38,8 @@ export class BulkAddToCollectionComponent implements OnInit {
|
||||
|
||||
ngOnInit(): void {
|
||||
|
||||
this.listForm.addControl('title', new UntypedFormControl(this.title, []));
|
||||
this.listForm.addControl('filterQuery', new UntypedFormControl('', []));
|
||||
this.listForm.addControl('title', new FormControl(this.title, []));
|
||||
this.listForm.addControl('filterQuery', new FormControl('', []));
|
||||
|
||||
this.loading = true;
|
||||
this.cdRef.markForCheck();
|
||||
|
@ -1,5 +1,5 @@
|
||||
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 { ToastrService } from 'ngx-toastr';
|
||||
import { forkJoin } from 'rxjs';
|
||||
@ -37,7 +37,7 @@ export class EditCollectionTagsComponent implements OnInit {
|
||||
pagination!: Pagination;
|
||||
selectAll: boolean = true;
|
||||
libraryNames!: any;
|
||||
collectionTagForm!: UntypedFormGroup;
|
||||
collectionTagForm!: FormGroup;
|
||||
tabs = [{title: 'General', id: TabID.General}, {title: 'Cover Image', id: TabID.CoverImage}];
|
||||
active = TabID.General;
|
||||
imageUrls: Array<string> = [];
|
||||
@ -65,10 +65,10 @@ export class EditCollectionTagsComponent implements OnInit {
|
||||
if (this.pagination == undefined) {
|
||||
this.pagination = {totalPages: 1, totalItems: 200, itemsPerPage: 200, currentPage: 0};
|
||||
}
|
||||
this.collectionTagForm = new UntypedFormGroup({
|
||||
summary: new UntypedFormControl(this.tag.summary, []),
|
||||
coverImageLocked: new UntypedFormControl(this.tag.coverImageLocked, []),
|
||||
coverImageIndex: new UntypedFormControl(0, []),
|
||||
this.collectionTagForm = new FormGroup({
|
||||
summary: new FormControl(this.tag.summary, []),
|
||||
coverImageLocked: new FormControl(this.tag.coverImageLocked, []),
|
||||
coverImageIndex: new FormControl(0, []),
|
||||
|
||||
});
|
||||
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"
|
||||
></app-series-card>
|
||||
</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>
|
||||
</div>
|
@ -1,5 +1,5 @@
|
||||
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 { distinctUntilChanged, forkJoin, map, Observable, of, ReplaySubject, Subject, takeUntil } from 'rxjs';
|
||||
import { UtilityService } from '../shared/_services/utility.service';
|
||||
@ -66,9 +66,9 @@ export class MetadataFilterComponent implements OnInit, OnDestroy {
|
||||
libraries: Array<FilterItem<Library>> = [];
|
||||
|
||||
|
||||
readProgressGroup!: UntypedFormGroup;
|
||||
sortGroup!: UntypedFormGroup;
|
||||
seriesNameGroup!: UntypedFormGroup;
|
||||
readProgressGroup!: FormGroup;
|
||||
sortGroup!: FormGroup;
|
||||
seriesNameGroup!: FormGroup;
|
||||
isAscendingSort: boolean = true;
|
||||
|
||||
updateApplied: number = 0;
|
||||
@ -106,18 +106,18 @@ export class MetadataFilterComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
this.filter = this.seriesService.createSeriesFilter();
|
||||
this.readProgressGroup = new UntypedFormGroup({
|
||||
read: new UntypedFormControl({value: this.filter.readStatus.read, disabled: this.filterSettings.readProgressDisabled}, []),
|
||||
notRead: new UntypedFormControl({value: this.filter.readStatus.notRead, disabled: this.filterSettings.readProgressDisabled}, []),
|
||||
inProgress: new UntypedFormControl({value: this.filter.readStatus.inProgress, disabled: this.filterSettings.readProgressDisabled}, []),
|
||||
this.readProgressGroup = new FormGroup({
|
||||
read: new FormControl({value: this.filter.readStatus.read, disabled: this.filterSettings.readProgressDisabled}, []),
|
||||
notRead: new FormControl({value: this.filter.readStatus.notRead, disabled: this.filterSettings.readProgressDisabled}, []),
|
||||
inProgress: new FormControl({value: this.filter.readStatus.inProgress, disabled: this.filterSettings.readProgressDisabled}, []),
|
||||
});
|
||||
|
||||
this.sortGroup = new UntypedFormGroup({
|
||||
sortField: new UntypedFormControl({value: this.filter.sortOptions?.sortField || SortField.SortName, disabled: this.filterSettings.sortDisabled}, []),
|
||||
this.sortGroup = new FormGroup({
|
||||
sortField: new FormControl({value: this.filter.sortOptions?.sortField || SortField.SortName, disabled: this.filterSettings.sortDisabled}, []),
|
||||
});
|
||||
|
||||
this.seriesNameGroup = new UntypedFormGroup({
|
||||
seriesNameQuery: new UntypedFormControl({value: this.filter.seriesNameQuery || '', disabled: this.filterSettings.searchNameDisabled}, [])
|
||||
this.seriesNameGroup = new FormGroup({
|
||||
seriesNameQuery: new FormControl({value: this.filter.seriesNameQuery || '', disabled: this.filterSettings.searchNameDisabled}, [])
|
||||
});
|
||||
|
||||
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 { UntypedFormControl, UntypedFormGroup } from '@angular/forms';
|
||||
import { FormControl, FormGroup } from '@angular/forms';
|
||||
import { Subject } from 'rxjs';
|
||||
import { debounceTime, takeUntil } from 'rxjs/operators';
|
||||
import { KEY_CODES } from '../../shared/_services/utility.service';
|
||||
@ -66,7 +66,7 @@ export class GroupedTypeaheadComponent implements OnInit, OnDestroy {
|
||||
|
||||
hasFocus: boolean = false;
|
||||
isLoading: boolean = false;
|
||||
typeaheadForm: UntypedFormGroup = new UntypedFormGroup({});
|
||||
typeaheadForm: FormGroup = new FormGroup({});
|
||||
|
||||
prevSearchTerm: string = '';
|
||||
|
||||
@ -106,7 +106,7 @@ export class GroupedTypeaheadComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.typeaheadForm.addControl('typeahead', new UntypedFormControl(this.initialValue, []));
|
||||
this.typeaheadForm.addControl('typeahead', new FormControl(this.initialValue, []));
|
||||
this.cdRef.markForCheck();
|
||||
|
||||
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 { UntypedFormControl, UntypedFormGroup } from '@angular/forms';
|
||||
import { FormControl, FormGroup } from '@angular/forms';
|
||||
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { ToastrService } from 'ngx-toastr';
|
||||
import { ReadingList } from 'src/app/_models/reading-list';
|
||||
@ -56,7 +56,7 @@ export class AddToListModalComponent implements OnInit, AfterViewInit {
|
||||
*/
|
||||
lists: Array<any> = [];
|
||||
loading: boolean = false;
|
||||
listForm: UntypedFormGroup = new UntypedFormGroup({});
|
||||
listForm: FormGroup = new FormGroup({});
|
||||
|
||||
@ViewChild('title') inputElem!: ElementRef<HTMLInputElement>;
|
||||
|
||||
@ -65,8 +65,8 @@ export class AddToListModalComponent implements OnInit, AfterViewInit {
|
||||
|
||||
ngOnInit(): void {
|
||||
|
||||
this.listForm.addControl('title', new UntypedFormControl(this.title, []));
|
||||
this.listForm.addControl('filterQuery', new UntypedFormControl('', []));
|
||||
this.listForm.addControl('title', new FormControl(this.title, []));
|
||||
this.listForm.addControl('filterQuery', new FormControl('', []));
|
||||
|
||||
this.loading = true;
|
||||
this.readingListService.getReadingLists(false).subscribe(lists => {
|
||||
|
@ -1,5 +1,5 @@
|
||||
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 { ToastrService } from 'ngx-toastr';
|
||||
import { forkJoin } from 'rxjs';
|
||||
@ -18,7 +18,7 @@ import { UploadService } from 'src/app/_services/upload.service';
|
||||
export class EditReadingListModalComponent implements OnInit {
|
||||
|
||||
@Input() readingList!: ReadingList;
|
||||
reviewGroup!: UntypedFormGroup;
|
||||
reviewGroup!: FormGroup;
|
||||
|
||||
coverImageIndex: number = 0;
|
||||
/**
|
||||
@ -41,9 +41,9 @@ export class EditReadingListModalComponent implements OnInit {
|
||||
private imageService: ImageService) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
this.reviewGroup = new UntypedFormGroup({
|
||||
title: new UntypedFormControl(this.readingList.title, [Validators.required]),
|
||||
summary: new UntypedFormControl(this.readingList.summary, [])
|
||||
this.reviewGroup = new FormGroup({
|
||||
title: new FormControl(this.readingList.title, [Validators.required]),
|
||||
summary: new FormControl(this.readingList.summary, [])
|
||||
});
|
||||
|
||||
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 { UntypedFormControl, UntypedFormGroup, Validators } from '@angular/forms';
|
||||
import { FormControl, FormGroup, Validators } from '@angular/forms';
|
||||
import { SafeUrl } from '@angular/platform-browser';
|
||||
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { ToastrService } from 'ngx-toastr';
|
||||
@ -17,7 +17,7 @@ export class AddEmailToAccountMigrationModalComponent implements OnInit {
|
||||
@Input() password!: string;
|
||||
|
||||
isSaving: boolean = false;
|
||||
registerForm: UntypedFormGroup = new UntypedFormGroup({});
|
||||
registerForm: FormGroup = new FormGroup({});
|
||||
emailLink: string = '';
|
||||
emailLinkUrl: SafeUrl | undefined;
|
||||
error: string = '';
|
||||
@ -27,9 +27,9 @@ export class AddEmailToAccountMigrationModalComponent implements OnInit {
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.registerForm.addControl('username', new UntypedFormControl(this.username, [Validators.required]));
|
||||
this.registerForm.addControl('email', new UntypedFormControl('', [Validators.required, Validators.email]));
|
||||
this.registerForm.addControl('password', new UntypedFormControl(this.password, [Validators.required]));
|
||||
this.registerForm.addControl('username', new FormControl(this.username, [Validators.required]));
|
||||
this.registerForm.addControl('email', new FormControl('', [Validators.required, Validators.email]));
|
||||
this.registerForm.addControl('password', new FormControl(this.password, [Validators.required]));
|
||||
this.cdRef.markForCheck();
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
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 { ToastrService } from 'ngx-toastr';
|
||||
import { ThemeService } from 'src/app/_services/theme.service';
|
||||
@ -18,10 +18,10 @@ export class ConfirmEmailComponent {
|
||||
*/
|
||||
token: string = '';
|
||||
|
||||
registerForm: UntypedFormGroup = new UntypedFormGroup({
|
||||
email: new UntypedFormControl('', [Validators.required, Validators.email]),
|
||||
username: new UntypedFormControl('', [Validators.required]),
|
||||
password: new UntypedFormControl('', [Validators.required, Validators.maxLength(32), Validators.minLength(6)]),
|
||||
registerForm: FormGroup = new FormGroup({
|
||||
email: new FormControl('', [Validators.required, Validators.email]),
|
||||
username: new FormControl('', [Validators.required]),
|
||||
password: new FormControl('', [Validators.required, Validators.maxLength(32), Validators.minLength(6)]),
|
||||
});
|
||||
|
||||
/**
|
||||
|
@ -1,7 +1,7 @@
|
||||
<app-splash-container>
|
||||
<ng-container title><h2>Password Reset</h2></ng-container>
|
||||
<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()">
|
||||
<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>
|
||||
|
@ -0,0 +1,4 @@
|
||||
input {
|
||||
background-color: #fff !important;
|
||||
color: black !important;
|
||||
}
|
@ -1,8 +1,9 @@
|
||||
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 { ToastrService } from 'ngx-toastr';
|
||||
import { AccountService } from 'src/app/_services/account.service';
|
||||
import { NavService } from 'src/app/_services/nav.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-confirm-reset-password',
|
||||
@ -13,14 +14,18 @@ import { AccountService } from 'src/app/_services/account.service';
|
||||
export class ConfirmResetPasswordComponent {
|
||||
|
||||
token: string = '';
|
||||
registerForm: UntypedFormGroup = new UntypedFormGroup({
|
||||
email: new UntypedFormControl('', [Validators.required, Validators.email]),
|
||||
password: new UntypedFormControl('', [Validators.required, Validators.maxLength(32), Validators.minLength(6)]),
|
||||
registerForm: FormGroup = new FormGroup({
|
||||
email: new FormControl('', [Validators.required, Validators.email]),
|
||||
password: new FormControl('', [Validators.required, Validators.maxLength(32), Validators.minLength(6)]),
|
||||
});
|
||||
|
||||
constructor(private route: ActivatedRoute, private router: Router,
|
||||
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 email = this.route.snapshot.queryParamMap.get('email');
|
||||
|
@ -1,5 +1,5 @@
|
||||
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 { ToastrService } from 'ngx-toastr';
|
||||
import { take } from 'rxjs/operators';
|
||||
@ -17,10 +17,10 @@ import { MemberService } from 'src/app/_services/member.service';
|
||||
})
|
||||
export class RegisterComponent implements OnInit {
|
||||
|
||||
registerForm: UntypedFormGroup = new UntypedFormGroup({
|
||||
email: new UntypedFormControl('', [Validators.required, Validators.email]),
|
||||
username: new UntypedFormControl('', [Validators.required]),
|
||||
password: new UntypedFormControl('', [Validators.required, Validators.maxLength(32), Validators.minLength(6)]),
|
||||
registerForm: FormGroup = new FormGroup({
|
||||
email: new FormControl('', [Validators.required, Validators.email]),
|
||||
username: new FormControl('', [Validators.required]),
|
||||
password: new FormControl('', [Validators.required, Validators.maxLength(32), Validators.minLength(6)]),
|
||||
});
|
||||
|
||||
constructor(private router: Router, private accountService: AccountService,
|
||||
|
@ -1,5 +1,5 @@
|
||||
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 { NgbModal } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { ToastrService } from 'ngx-toastr';
|
||||
@ -20,9 +20,9 @@ import { NavService } from '../../_services/nav.service';
|
||||
export class UserLoginComponent implements OnInit {
|
||||
|
||||
//model: any = {username: '', password: ''};
|
||||
loginForm: UntypedFormGroup = new UntypedFormGroup({
|
||||
username: new UntypedFormControl('', [Validators.required]),
|
||||
password: new UntypedFormControl('', [Validators.required])
|
||||
loginForm: FormGroup = new FormGroup({
|
||||
username: new FormControl('', [Validators.required]),
|
||||
password: new FormControl('', [Validators.required])
|
||||
});
|
||||
|
||||
/**
|
||||
|
@ -1,5 +1,5 @@
|
||||
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 { Series } from 'src/app/_models/series';
|
||||
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 {
|
||||
|
||||
@Input() series!: Series;
|
||||
reviewGroup!: UntypedFormGroup;
|
||||
reviewGroup!: FormGroup;
|
||||
|
||||
constructor(public modal: NgbActiveModal, private seriesService: SeriesService, private readonly cdRef: ChangeDetectorRef) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.reviewGroup = new UntypedFormGroup({
|
||||
review: new UntypedFormControl(this.series.userReview, []),
|
||||
rating: new UntypedFormControl(this.series.userRating, [])
|
||||
this.reviewGroup = new FormGroup({
|
||||
review: new FormControl(this.series.userReview, []),
|
||||
rating: new FormControl(this.series.userRating, [])
|
||||
});
|
||||
this.cdRef.markForCheck();
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ import { NavService } from '../_services/nav.service';
|
||||
import { RelatedSeries } from '../_models/series-detail/related-series';
|
||||
import { RelationKind } from '../_models/series-detail/relation-kind';
|
||||
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 { DOCUMENT } from '@angular/common';
|
||||
import { User } from '../_models/user';
|
||||
@ -151,8 +151,8 @@ export class SeriesDetailComponent implements OnInit, OnDestroy, AfterContentChe
|
||||
renderMode: PageLayoutMode = PageLayoutMode.Cards;
|
||||
|
||||
pageExtrasGroup = new FormGroup({
|
||||
'sortingOption': new UntypedFormControl(this.sortingOptions[0].value, []),
|
||||
'renderMode': new UntypedFormControl(this.renderMode, []),
|
||||
'sortingOption': new FormControl(this.sortingOptions[0].value, []),
|
||||
'renderMode': new FormControl(this.renderMode, []),
|
||||
});
|
||||
|
||||
isAscendingSort: boolean = false; // TODO: Get this from User preferences
|
||||
@ -299,7 +299,8 @@ export class SeriesDetailComponent implements OnInit, OnDestroy, AfterContentChe
|
||||
this.changeDetectionRef.markForCheck();
|
||||
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.changeDetectionRef.markForCheck();
|
||||
});
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Observable } from 'rxjs';
|
||||
import { UntypedFormControl } from '@angular/forms';
|
||||
import { FormControl } from '@angular/forms';
|
||||
|
||||
export type SelectionCompareFn<T> = (a: T, b: T) => boolean;
|
||||
|
||||
@ -48,7 +48,7 @@ export class TypeaheadSettings<T> {
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { trigger, state, style, transition, animate } from '@angular/animations';
|
||||
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 { UntypedFormControl, UntypedFormGroup } from '@angular/forms';
|
||||
import { FormControl, FormGroup } from '@angular/forms';
|
||||
import { Observable, of, ReplaySubject, Subject } from 'rxjs';
|
||||
import { auditTime, distinctUntilChanged, filter, map, shareReplay, switchMap, take, takeUntil, tap } from 'rxjs/operators';
|
||||
import { KEY_CODES } from '../shared/_services/utility.service';
|
||||
@ -189,8 +189,8 @@ export class TypeaheadComponent implements OnInit, OnDestroy {
|
||||
showAddItem: boolean = false;
|
||||
filteredOptions!: Observable<string[]>;
|
||||
isLoadingOptions: boolean = false;
|
||||
typeaheadControl!: UntypedFormControl;
|
||||
typeaheadForm!: UntypedFormGroup;
|
||||
typeaheadControl!: FormControl;
|
||||
typeaheadForm!: FormGroup;
|
||||
|
||||
private readonly onDestroy = new Subject<void>();
|
||||
|
||||
@ -230,9 +230,9 @@ export class TypeaheadComponent implements OnInit, OnDestroy {
|
||||
if (this.settings.hasOwnProperty('formControl') && this.settings.formControl) {
|
||||
this.typeaheadControl = this.settings.formControl;
|
||||
} else {
|
||||
this.typeaheadControl = new UntypedFormControl('');
|
||||
this.typeaheadControl = new FormControl('');
|
||||
}
|
||||
this.typeaheadForm = new UntypedFormGroup({
|
||||
this.typeaheadForm = new FormGroup({
|
||||
'typeahead': this.typeaheadControl
|
||||
});
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user