Tweaks (#1890)
* Updated number inputs with a more mobile friendly control * Started writing lots of unit tests on PersonHelper to try and hammer out foreign constraint * Fixes side-nav actionable alignment * Added some unit tests * Buffed out the unit tests * Applied input modes throughout the app * Fixed a small bug in refresh token validation to make it work correctly * Try out a new way to block multithreading from interacting with people during series metadata update. * Fixed the lock code to properly lock, which should help with any constraint issues. * Locking notes * Tweaked locking on people to prevent a constraint issue. This slows down the scanner a bit, but not much. Will tweak after validating on a user's server. * Replaced all DBFactory.Series with SeriesBuilder. * Replaced all DBFactory.Volume() with VolumeBuilder * Replaced SeriesMetadata with Builder * Replaced DBFactory.CollectionTag * Lots of refactoring to streamline entity creation * Fixed one of the unit tests * Refactored all of new Library() * Removed tag and genre * Removed new SeriesMetadata * Refactored new Volume() * MangaFile() * ReadingList() * Refactored all of Chapter and ReadingList * Add title to all event widget flows * Updated Base Url to inform user it doesn't work for docker users with non-root user. * Added unit test coverage to FormatChapterTitle and FormatChapterName. * Started on Unit test for scanner, but need to finish it later. --------- Co-authored-by: Robbie Davis <robbie@therobbiedavis.com>
This commit is contained in:
parent
eec03d7e96
commit
385f61f9f0
105 changed files with 2257 additions and 2660 deletions
|
@ -285,9 +285,9 @@ export class AccountService implements OnDestroy {
|
|||
}
|
||||
|
||||
const jwtToken = JSON.parse(atob(this.currentUser.token.split('.')[1]));
|
||||
// set a timeout to refresh the token a minute before it expires
|
||||
// set a timeout to refresh the token 10 mins before it expires
|
||||
const expires = new Date(jwtToken.exp * 1000);
|
||||
const timeout = expires.getTime() - Date.now() - (60 * 1000);
|
||||
const timeout = expires.getTime() - Date.now() - (60 * 10000);
|
||||
this.refreshTokenTimeout = setTimeout(() => this.refreshToken().subscribe(() => {}), timeout);
|
||||
}
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
<div class="col-md-6 col-sm-12">
|
||||
<div class="mb-3" style="width:100%">
|
||||
<label for="email" class="form-label">Email</label>
|
||||
<input class="form-control" type="email" id="email" formControlName="email">
|
||||
<input class="form-control" inputmode="email" type="email" id="email" formControlName="email">
|
||||
<div id="inviteForm-validations" class="invalid-feedback" *ngIf="userForm.dirty || userForm.touched" [class.is-invalid]="userForm.get('email')?.invalid && userForm.get('email')?.touched">
|
||||
<div *ngIf="userForm.get('email')?.errors?.required">
|
||||
This field is required
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
<div class="row g-0">
|
||||
<div class="mb-3" style="width:100%">
|
||||
<label for="email" class="form-label">Email</label>
|
||||
<input class="form-control" type="email" id="email" formControlName="email" required [class.is-invalid]="inviteForm.get('email')?.invalid && inviteForm.get('email')?.touched">
|
||||
<input class="form-control" type="email" inputmode="email" id="email" formControlName="email" required [class.is-invalid]="inviteForm.get('email')?.invalid && inviteForm.get('email')?.touched">
|
||||
<div id="inviteForm-validations" class="invalid-feedback" *ngIf="inviteForm.dirty || inviteForm.touched">
|
||||
<div *ngIf="email?.errors?.required">
|
||||
This field is required
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
<ng-template #emailServiceTooltip>Use fully qualified URL of the email service. Do not include ending slash.</ng-template>
|
||||
<span class="visually-hidden" id="settings-emailservice-help"><ng-container [ngTemplateOutlet]="emailServiceTooltip"></ng-container></span>
|
||||
<div class="input-group">
|
||||
<input id="settings-emailservice" aria-describedby="settings-emailservice-help" class="form-control" formControlName="emailServiceUrl" type="text" aria-describedby="change-bookmarks-dir">
|
||||
<input id="settings-emailservice" aria-describedby="settings-emailservice-help" class="form-control" formControlName="emailServiceUrl" type="url" autocapitalize="off" inputmode="url" aria-describedby="change-bookmarks-dir">
|
||||
<button class="btn btn-outline-secondary" (click)="resetEmailServiceUrl()">
|
||||
Reset
|
||||
</button>
|
||||
|
|
|
@ -35,8 +35,8 @@
|
|||
|
||||
<div class="mb-3">
|
||||
<label for="settings-baseurl" class="form-label">Base Url</label> <i class="fa fa-info-circle" placement="right" [ngbTooltip]="baseUrlTooltip" role="button" tabindex="0"></i>
|
||||
<ng-template #baseUrlTooltip>Use this if you want to host Kavita on a base url ie) yourdomain.com/kavita</ng-template>
|
||||
<span class="visually-hidden" id="settings-cachedir-help">Use this if you want to host Kavita on a base url ie) yourdomain.com/kavita</span>
|
||||
<ng-template #baseUrlTooltip>Use this if you want to host Kavita on a base url ie) yourdomain.com/kavita. Not supported on Docker using non-root user.</ng-template>
|
||||
<span class="visually-hidden" id="settings-cachedir-help">Use this if you want to host Kavita on a base url ie) yourdomain.com/kavita. Not supported on Docker using non-root user.</span>
|
||||
<input id="settings-baseurl" aria-describedby="settings-baseurl-help" class="form-control" formControlName="baseUrl" type="text"
|
||||
[class.is-invalid]="settingsForm.get('baseUrl')?.invalid && settingsForm.get('baseUrl')?.touched">
|
||||
<div id="baseurl-validations" class="invalid-feedback" *ngIf="settingsForm.dirty || settingsForm.touched">
|
||||
|
@ -77,7 +77,7 @@
|
|||
<ng-template #backupTasksTooltip>The number of backups to maintain. Default is 30, minumum is 1, maximum is 30.</ng-template>
|
||||
<span class="visually-hidden" id="backup-tasks-help">The number of backups to maintain. Default is 30, minumum is 1, maximum is 30.</span>
|
||||
<input id="backup-tasks" aria-describedby="backup-tasks-help" class="form-control" formControlName="totalBackups"
|
||||
type="number" step="1" min="1" max="30" onkeypress="return event.charCode >= 48 && event.charCode <= 57"
|
||||
type="number" inputmode="numeric" step="1" min="1" max="30" onkeypress="return event.charCode >= 48 && event.charCode <= 57"
|
||||
[class.is-invalid]="settingsForm.get('totalBackups')?.invalid && settingsForm.get('totalBackups')?.touched">
|
||||
<ng-container *ngIf="settingsForm.get('totalBackups')?.errors as errors">
|
||||
<p class="invalid-feedback" *ngIf="errors.min">
|
||||
|
@ -97,7 +97,7 @@
|
|||
<ng-template #logTasksTooltip>The number of logs to maintain. Default is 30, minumum is 1, maximum is 30.</ng-template>
|
||||
<span class="visually-hidden" id="log-tasks-help">The number of backups to maintain. Default is 30, minumum is 1, maximum is 30.</span>
|
||||
<input id="log-tasks" aria-describedby="log-tasks-help" class="form-control" formControlName="totalLogs"
|
||||
type="number" step="1" min="1" max="30" onkeypress="return event.charCode >= 48 && event.charCode <= 57"
|
||||
type="number" inputmode="numeric" step="1" min="1" max="30" onkeypress="return event.charCode >= 48 && event.charCode <= 57"
|
||||
[class.is-invalid]="settingsForm.get('totalLogs')?.invalid && settingsForm.get('totalLogs')?.touched">
|
||||
<ng-container *ngIf="settingsForm.get('totalLogs')?.errors as errors">
|
||||
<p class="invalid-feedback" *ngIf="errors.min">
|
||||
|
|
|
@ -88,7 +88,7 @@
|
|||
<label for="release-year" class="form-label">Release Year</label>
|
||||
<div class="input-group {{metadata.releaseYearLocked ? 'lock-active' : ''}}">
|
||||
<ng-container [ngTemplateOutlet]="lock" [ngTemplateOutletContext]="{ item: metadata, field: 'releaseYearLocked' }"></ng-container>
|
||||
<input type="number" class="form-control" id="release-year" formControlName="releaseYear" maxlength="4" minlength="4" [class.is-invalid]="editSeriesForm.get('releaseYear')?.invalid && editSeriesForm.get('releaseYear')?.touched">
|
||||
<input type="number" inputmode="numeric" class="form-control" id="release-year" formControlName="releaseYear" maxlength="4" minlength="4" [class.is-invalid]="editSeriesForm.get('releaseYear')?.invalid && editSeriesForm.get('releaseYear')?.touched">
|
||||
<ng-container *ngIf="editSeriesForm.get('releaseYear')?.errors as errors">
|
||||
<p class="invalid-feedback" *ngIf="errors.pattern">
|
||||
This must be a valid year greater than 1000 and 4 characters long
|
||||
|
|
|
@ -92,7 +92,7 @@
|
|||
<ng-template #progressEvent>
|
||||
<li class="list-group-item dark-menu-item">
|
||||
<div class="h6 mb-1">{{message.title}}</div>
|
||||
<div class="accent-text mb-1" *ngIf="message.subTitle !== ''">{{message.subTitle}}</div>
|
||||
<div class="accent-text mb-1" *ngIf="message.subTitle !== ''" [title]="message.subTitle">{{message.subTitle}}</div>
|
||||
<div class="progress-container row g-0 align-items-center">
|
||||
<div class="col-2">{{prettyPrintProgress(message.body.progress) + '%'}}</div>
|
||||
<div class="col-10 progress" style="height: 5px;">
|
||||
|
@ -122,7 +122,7 @@
|
|||
<ng-container *ngFor="let download of activeDownloads">
|
||||
<li class="list-group-item dark-menu-item">
|
||||
<div class="h6 mb-1">Downloading {{download.entityType | sentenceCase}}</div>
|
||||
<div class="accent-text mb-1" *ngIf="download.subTitle !== ''">{{download.subTitle}}</div>
|
||||
<div class="accent-text mb-1" *ngIf="download.subTitle !== ''" [title]="download.subTitle">{{download.subTitle}}</div>
|
||||
<div class="progress-container row g-0 align-items-center">
|
||||
<div class="col-2">{{download.progress}}%</div>
|
||||
<div class="col-10 progress" style="height: 5px;">
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<form [formGroup]="typeaheadForm" class="grouped-typeahead">
|
||||
<div class="typeahead-input" [ngClass]="{'focused': hasFocus}" (click)="onInputFocus($event)">
|
||||
<div class="search">
|
||||
<input #input [id]="id" type="text" autocomplete="off" formControlName="typeahead" [placeholder]="placeholder"
|
||||
<input #input [id]="id" type="text" inputmode="search" autocomplete="off" formControlName="typeahead" [placeholder]="placeholder"
|
||||
aria-haspopup="listbox" aria-owns="dropdown" aria-expanded="hasFocus && (grouppedData.persons.length || grouppedData.collections.length || grouppedData.series.length || grouppedData.persons.length || grouppedData.tags.length || grouppedData.genres.length)"
|
||||
aria-autocomplete="list" (focusout)="close($event)" (focus)="open($event)" role="search"
|
||||
>
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
<div class="me-3 align-middle">
|
||||
<div style="padding-top: 40px">
|
||||
<label for="reorder-{{i}}" class="form-label visually-hidden">Reorder</label>
|
||||
<input *ngIf="accessibilityMode" id="reorder-{{i}}" class="form-control" type="number" min="0" [max]="items.length - 1" [value]="i" style="width: 60px"
|
||||
<input *ngIf="accessibilityMode" id="reorder-{{i}}" class="form-control" type="number" inputmode="numeric" min="0" [max]="items.length - 1" [value]="i" style="width: 60px"
|
||||
(focusout)="updateIndex(i, item)" (keydown.enter)="updateIndex(i, item)" aria-describedby="instructions">
|
||||
</div>
|
||||
</div>
|
||||
|
@ -31,7 +31,7 @@
|
|||
<div class="me-3 align-middle">
|
||||
<div class="align-middle" style="padding-top: 40px" *ngIf="accessibilityMode">
|
||||
<label for="reorder-{{i}}" class="form-label visually-hidden">Reorder</label>
|
||||
<input id="reorder-{{i}}" class="form-control" type="number" min="0" [max]="items.length - 1" [value]="i" style="width: 60px"
|
||||
<input id="reorder-{{i}}" class="form-control" type="number" inputmode="numeric" min="0" [max]="items.length - 1" [value]="i" style="width: 60px"
|
||||
(focusout)="updateIndex(i, item)" (keydown.enter)="updateIndex(i, item)" aria-describedby="instructions">
|
||||
</div>
|
||||
<i *ngIf="!accessibilityMode" class="fa fa-grip-vertical drag-handle" aria-hidden="true" cdkDragHandle></i>
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
<div class="col-md-6 col-sm-12" *ngIf="reviewGroup.get('startingMonth') as formControl" style="width: 90%">
|
||||
<label for="start-month" class="form-label">Month</label>
|
||||
<input id="start-month" class="form-control" formControlName="startingMonth"
|
||||
type="number" [class.is-invalid]="formControl?.invalid && formControl?.touched"
|
||||
type="number" inputmode="numeric" [class.is-invalid]="formControl?.invalid && formControl?.touched"
|
||||
aria-describedby="starting-year-header">
|
||||
<div id="inviteForm-validations" class="invalid-feedback" *ngIf="reviewGroup.dirty || reviewGroup.touched">
|
||||
<div *ngIf="formControl.errors?.min || formControl.errors?.max">
|
||||
|
@ -53,7 +53,7 @@
|
|||
</div>
|
||||
<div class="col-md-6 col-sm-12" *ngIf="reviewGroup.get('startingYear') as formControl" style="width: 90%">
|
||||
<label for="start-year" class="form-label">Year</label>
|
||||
<input id="start-year" class="form-control" formControlName="startingYear" type="number"
|
||||
<input id="start-year" class="form-control" formControlName="startingYear" type="number" inputmode="numeric"
|
||||
[class.is-invalid]="formControl.invalid && formControl.touched"
|
||||
aria-describedby="starting-year-header">
|
||||
<div id="inviteForm-validations" class="invalid-feedback" *ngIf="reviewGroup.dirty || reviewGroup.touched">
|
||||
|
@ -68,7 +68,7 @@
|
|||
<h6 id="ending-year-heading">Ending</h6>
|
||||
<div class="col-md-6 col-sm-12" *ngIf="reviewGroup.get('endingMonth') as formControl" style="width: 90%">
|
||||
<label for="library-name" class="form-label">Month</label>
|
||||
<input id="library-name" class="form-control" formControlName="endingMonth" type="number"
|
||||
<input id="library-name" class="form-control" formControlName="endingMonth" type="number" inputmode="numeric"
|
||||
[class.is-invalid]="formControl?.invalid && formControl?.touched"
|
||||
aria-describedby="ending-year-header">
|
||||
<div id="inviteForm-validations" class="invalid-feedback" *ngIf="reviewGroup.dirty || reviewGroup.touched">
|
||||
|
@ -79,7 +79,7 @@
|
|||
</div>
|
||||
<div class="col-md-6 col-sm-12" *ngIf="reviewGroup.get('endingYear') as formControl" style="width: 90%">
|
||||
<label for="library-name" class="form-label">Year</label>
|
||||
<input id="library-name" class="form-control" formControlName="endingYear" type="number"
|
||||
<input id="library-name" class="form-control" formControlName="endingYear" type="number" inputmode="numeric"
|
||||
[class.is-invalid]="formControl?.invalid && formControl?.touched"
|
||||
aria-describedby="ending-year-header">
|
||||
<div id="inviteForm-validations" class="invalid-feedback" *ngIf="reviewGroup.dirty || reviewGroup.touched">
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
<div class="mb-3" style="width:100%">
|
||||
<label for="email" class="form-label">Email</label>
|
||||
<input class="form-control" type="email" id="email" formControlName="email" required readonly
|
||||
<input class="form-control" type="email" inputmode="email" id="email" formControlName="email" required readonly
|
||||
[class.is-invalid]="registerForm.get('email')?.invalid && registerForm.get('email')?.touched">
|
||||
<div id="inviteForm-validations" class="invalid-feedback" *ngIf="registerForm.dirty || registerForm.touched">
|
||||
<div *ngIf="registerForm.get('email')?.errors?.required">
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
<span class="visually-hidden" id="email-help">
|
||||
<ng-container [ngTemplateOutlet]="emailTooltip"></ng-container>
|
||||
</span>
|
||||
<input class="form-control" type="email" id="email" formControlName="email" required aria-describedby="email-help"
|
||||
<input class="form-control" type="email" inputmode="email" id="email" formControlName="email" required aria-describedby="email-help"
|
||||
[class.is-invalid]="registerForm.get('email')?.invalid && registerForm.get('email')?.touched">
|
||||
<div id="inviteForm-validations" class="invalid-feedback" *ngIf="registerForm.dirty || registerForm.touched">
|
||||
<div *ngIf="registerForm.get('email')?.errors?.required">
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<form [formGroup]="registerForm" (ngSubmit)="submit()">
|
||||
<div class="mb-3" style="width:100%">
|
||||
<label for="email" class="form-label">Email</label>
|
||||
<input class="form-control custom-input" type="email" id="email" formControlName="email" [class.is-invalid]="registerForm.get('email')?.invalid && registerForm.get('email')?.touched">
|
||||
<input class="form-control custom-input" type="email" inputmode="email" id="email" formControlName="email" [class.is-invalid]="registerForm.get('email')?.invalid && registerForm.get('email')?.touched">
|
||||
<div id="inviteForm-validations" class="invalid-feedback" *ngIf="registerForm.dirty || registerForm.touched">
|
||||
<div *ngIf="registerForm.get('email')?.errors?.required">
|
||||
This field is required
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
<div class="mb-3" style="width:100%">
|
||||
<label for="email" class="form-label">Email</label>
|
||||
<input class="form-control" type="email" id="email" formControlName="email" [class.is-invalid]="registerForm.get('email')?.invalid && registerForm.get('email')?.touched">
|
||||
<input class="form-control" type="email" inputmode="email" id="email" formControlName="email" [class.is-invalid]="registerForm.get('email')?.invalid && registerForm.get('email')?.touched">
|
||||
<div id="inviteForm-validations" class="invalid-feedback" *ngIf="registerForm.dirty || registerForm.touched">
|
||||
<div *ngIf="registerForm.get('email')?.errors?.required">
|
||||
This field is required
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
|
||||
|
||||
span {
|
||||
display:flex;
|
||||
|
||||
&:last-child {
|
||||
flex-grow: 1;
|
||||
justify-content: end;
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
<span class="visually-hidden" id="email-help">The number of backups to maintain. Default is 30, minumum is 1, maximum is 30.</span>
|
||||
|
||||
<input id="email" aria-describedby="email-help"
|
||||
class="form-control" formControlName="email" type="email"
|
||||
class="form-control" formControlName="email" type="email" inputmode="email"
|
||||
placeholder="id@kindle.com" [class.is-invalid]="settingsForm.get('email')?.invalid && settingsForm.get('email')?.touched">
|
||||
<ng-container *ngIf="settingsForm.get('email')?.errors as errors">
|
||||
<p class="invalid-feedback" *ngIf="errors.email">
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue