Stats & More Polish on Metadata Matching (#3538)
This commit is contained in:
parent
6f3ba0948b
commit
5d6a5f0987
34 changed files with 178 additions and 124 deletions
|
@ -70,8 +70,10 @@ export class MatchSeriesModalComponent implements OnInit {
|
|||
const model: any = this.formGroup.value;
|
||||
model.seriesId = this.series.id;
|
||||
|
||||
const dontMatchChanged = this.series.dontMatch !== model.dontMatch;
|
||||
|
||||
// We need to update the dontMatch status
|
||||
if (model.dontMatch) {
|
||||
if (dontMatchChanged) {
|
||||
this.seriesService.updateDontMatch(this.series.id, model.dontMatch).subscribe(_ => {
|
||||
this.modalService.close(true);
|
||||
});
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
[limit]="pageInfo.size"
|
||||
>
|
||||
|
||||
<ngx-datatable-column name="lastModifiedUtc" [sortable]="true" [draggable]="false" [resizeable]="false">
|
||||
<ngx-datatable-column prop="lastModifiedUtc" [sortable]="true" [draggable]="false" [resizeable]="false">
|
||||
<ng-template let-column="column" ngx-datatable-header-template>
|
||||
{{t('last-modified-header')}}
|
||||
</ng-template>
|
||||
|
@ -46,7 +46,7 @@
|
|||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
|
||||
<ngx-datatable-column name="scrobbleEventType" [sortable]="true" [draggable]="false" [resizeable]="false">
|
||||
<ngx-datatable-column prop="scrobbleEventType" [sortable]="true" [draggable]="false" [resizeable]="false">
|
||||
<ng-template let-column="column" ngx-datatable-header-template>
|
||||
{{t('type-header')}}
|
||||
</ng-template>
|
||||
|
@ -55,7 +55,7 @@
|
|||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
|
||||
<ngx-datatable-column name="seriesName" [sortable]="true" [draggable]="false" [resizeable]="false">
|
||||
<ngx-datatable-column prop="seriesName" [sortable]="true" [draggable]="false" [resizeable]="false">
|
||||
<ng-template let-column="column" ngx-datatable-header-template>
|
||||
{{t('series-header')}}
|
||||
</ng-template>
|
||||
|
@ -64,7 +64,7 @@
|
|||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
|
||||
<ngx-datatable-column name="data" [sortable]="false" [draggable]="false" [resizeable]="false">
|
||||
<ngx-datatable-column prop="data" [sortable]="false" [draggable]="false" [resizeable]="false">
|
||||
<ng-template let-column="column" ngx-datatable-header-template>
|
||||
{{t('data-header')}}
|
||||
</ng-template>
|
||||
|
@ -98,7 +98,7 @@
|
|||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
|
||||
<ngx-datatable-column name="isPorcessed" [sortable]="true" [draggable]="false" [resizeable]="false">
|
||||
<ngx-datatable-column prop="isPorcessed" [sortable]="true" [draggable]="false" [resizeable]="false">
|
||||
<ng-template let-column="column" ngx-datatable-header-template>
|
||||
{{t('is-processed-header')}}
|
||||
</ng-template>
|
||||
|
|
|
@ -50,8 +50,12 @@
|
|||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
</div>
|
||||
}
|
||||
@if (isEmailInvalid$ | async) {
|
||||
<div class="invalid-feedback" style="display: block"><div>{{t('invalid-email-warning')}}</div></div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import {ChangeDetectionStrategy, ChangeDetectorRef, Component, inject, Input, OnInit} from '@angular/core';
|
||||
import {ChangeDetectionStrategy, ChangeDetectorRef, Component, DestroyRef, inject, Input, OnInit} from '@angular/core';
|
||||
import {FormControl, FormGroup, ReactiveFormsModule, Validators} from '@angular/forms';
|
||||
import {NgbActiveModal} from '@ng-bootstrap/ng-bootstrap';
|
||||
import {AgeRestriction} from 'src/app/_models/metadata/age-restriction';
|
||||
|
@ -9,23 +9,28 @@ import {SentenceCasePipe} from '../../_pipes/sentence-case.pipe';
|
|||
import {RestrictionSelectorComponent} from '../../user-settings/restriction-selector/restriction-selector.component';
|
||||
import {LibrarySelectorComponent} from '../library-selector/library-selector.component';
|
||||
import {RoleSelectorComponent} from '../role-selector/role-selector.component';
|
||||
import {NgIf} from '@angular/common';
|
||||
import {AsyncPipe, NgIf} from '@angular/common';
|
||||
import {TranslocoDirective} from "@jsverse/transloco";
|
||||
import {debounceTime, distinctUntilChanged, Observable, startWith, switchMap, tap} from "rxjs";
|
||||
import {map} from "rxjs/operators";
|
||||
import {takeUntilDestroyed} from "@angular/core/rxjs-interop";
|
||||
|
||||
const AllowedUsernameCharacters = /^[\sa-zA-Z0-9\-._@+/\s]*$/;
|
||||
const EmailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||
|
||||
@Component({
|
||||
selector: 'app-edit-user',
|
||||
templateUrl: './edit-user.component.html',
|
||||
styleUrls: ['./edit-user.component.scss'],
|
||||
standalone: true,
|
||||
imports: [ReactiveFormsModule, NgIf, RoleSelectorComponent, LibrarySelectorComponent, RestrictionSelectorComponent, SentenceCasePipe, TranslocoDirective],
|
||||
imports: [ReactiveFormsModule, RoleSelectorComponent, LibrarySelectorComponent, RestrictionSelectorComponent, SentenceCasePipe, TranslocoDirective, AsyncPipe],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class EditUserComponent implements OnInit {
|
||||
|
||||
private readonly accountService = inject(AccountService);
|
||||
private readonly cdRef = inject(ChangeDetectorRef);
|
||||
private readonly destroyRef = inject(DestroyRef);
|
||||
protected readonly modal = inject(NgbActiveModal);
|
||||
|
||||
@Input({required: true}) member!: Member;
|
||||
|
@ -36,6 +41,7 @@ export class EditUserComponent implements OnInit {
|
|||
isSaving: boolean = false;
|
||||
|
||||
userForm: FormGroup = new FormGroup({});
|
||||
isEmailInvalid$!: Observable<boolean>;
|
||||
|
||||
allowedCharacters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+/';
|
||||
|
||||
|
@ -47,9 +53,17 @@ export class EditUserComponent implements OnInit {
|
|||
|
||||
|
||||
ngOnInit(): void {
|
||||
this.userForm.addControl('email', new FormControl(this.member.email, [Validators.required, Validators.email]));
|
||||
this.userForm.addControl('email', new FormControl(this.member.email, [Validators.required]));
|
||||
this.userForm.addControl('username', new FormControl(this.member.username, [Validators.required, Validators.pattern(AllowedUsernameCharacters)]));
|
||||
|
||||
this.isEmailInvalid$ = this.userForm.get('email')!.valueChanges.pipe(
|
||||
startWith(this.member.email),
|
||||
distinctUntilChanged(),
|
||||
debounceTime(10),
|
||||
map(value => !EmailRegex.test(value)),
|
||||
takeUntilDestroyed(this.destroyRef)
|
||||
);
|
||||
|
||||
this.selectedRestriction = this.member.ageRestriction;
|
||||
this.cdRef.markForCheck();
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
[footerHeight]="50"
|
||||
>
|
||||
|
||||
<ngx-datatable-column name="emailTemplate" [sortable]="true" [draggable]="false" [resizeable]="false">
|
||||
<ngx-datatable-column prop="emailTemplate" [sortable]="true" [draggable]="false" [resizeable]="false">
|
||||
<ng-template let-column="column" ngx-datatable-header-template>
|
||||
{{t('template-header')}}
|
||||
</ng-template>
|
||||
|
@ -19,7 +19,7 @@
|
|||
</ngx-datatable-column>
|
||||
|
||||
|
||||
<ngx-datatable-column name="sendDate" [sortable]="true" [draggable]="false" [resizeable]="false">
|
||||
<ngx-datatable-column prop="sendDate" [sortable]="true" [draggable]="false" [resizeable]="false">
|
||||
<ng-template let-column="column" ngx-datatable-header-template>
|
||||
{{t('date-header')}}
|
||||
</ng-template>
|
||||
|
@ -28,7 +28,7 @@
|
|||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
|
||||
<ngx-datatable-column name="toUserName" [sortable]="true" [draggable]="false" [resizeable]="false">
|
||||
<ngx-datatable-column prop="toUserName" [sortable]="true" [draggable]="false" [resizeable]="false">
|
||||
<ng-template let-column="column" ngx-datatable-header-template>
|
||||
{{t('user-header')}}
|
||||
</ng-template>
|
||||
|
@ -37,7 +37,7 @@
|
|||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
|
||||
<ngx-datatable-column name="sent" [sortable]="true" [draggable]="false" [resizeable]="false">
|
||||
<ngx-datatable-column prop="sent" [sortable]="true" [draggable]="false" [resizeable]="false">
|
||||
<ng-template let-column="column" ngx-datatable-header-template>
|
||||
{{t('sent-header')}}
|
||||
</ng-template>
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
[footerHeight]="50"
|
||||
>
|
||||
|
||||
<ngx-datatable-column name="series.name" [sortable]="false" [draggable]="false" [resizeable]="false" [flexGrow]="3">
|
||||
<ngx-datatable-column prop="series.name" [sortable]="true" [draggable]="false" [resizeable]="false" [flexGrow]="3">
|
||||
<ng-template let-column="column" ngx-datatable-header-template>
|
||||
{{t('series-name-header')}}
|
||||
</ng-template>
|
||||
|
@ -34,7 +34,7 @@
|
|||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
|
||||
<ngx-datatable-column name="series.libraryId" [sortable]="false" [draggable]="false" [resizeable]="false" [flexGrow]="3">
|
||||
<ngx-datatable-column prop="series.libraryId" [sortable]="true" [draggable]="false" [resizeable]="false" [flexGrow]="2">
|
||||
<ng-template let-column="column" ngx-datatable-header-template>
|
||||
{{t('library-name-header')}}
|
||||
</ng-template>
|
||||
|
@ -43,8 +43,7 @@
|
|||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
|
||||
|
||||
<ngx-datatable-column name="status" [sortable]="false" [draggable]="false" [resizeable]="false" [flexGrow]="1">
|
||||
<ngx-datatable-column prop="status" [sortable]="false" [draggable]="false" [resizeable]="false" [flexGrow]="1">
|
||||
<ng-template let-column="column" ngx-datatable-header-template>
|
||||
{{t('status-header')}}
|
||||
</ng-template>
|
||||
|
@ -64,20 +63,22 @@
|
|||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
|
||||
<ngx-datatable-column name="validUntilUtc" [sortable]="false" [draggable]="false" [resizeable]="false" [flexGrow]="1">
|
||||
<ng-template let-column="column" ngx-datatable-header-template>
|
||||
{{t('valid-until-header')}}
|
||||
</ng-template>
|
||||
<ng-template let-item="row" ngx-datatable-cell-template>
|
||||
@if (item.series.isBlacklisted || item.series.dontMatch || !item.isMatched) {
|
||||
{{null | defaultValue}}
|
||||
} @else {
|
||||
{{item.validUntilUtc | utcToLocalTime}}
|
||||
}
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
@if (filterGroup.get('matchState')?.value === MatchStateOption.Matched) {
|
||||
<ngx-datatable-column prop="validUntilUtc" [sortable]="false" [draggable]="false" [resizeable]="false" [flexGrow]="1">
|
||||
<ng-template let-column="column" ngx-datatable-header-template>
|
||||
{{t('valid-until-header')}}
|
||||
</ng-template>
|
||||
<ng-template let-item="row" ngx-datatable-cell-template>
|
||||
@if (item.series.isBlacklisted || item.series.dontMatch || !item.isMatched) {
|
||||
{{null | defaultValue}}
|
||||
} @else {
|
||||
{{item.validUntilUtc | utcToLocalTime}}
|
||||
}
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
}
|
||||
|
||||
<ngx-datatable-column name="" [width]="20" [sortable]="false" [draggable]="false" [resizeable]="false" [flexGrow]="1">
|
||||
<ngx-datatable-column prop="" [width]="20" [sortable]="false" [draggable]="false" [resizeable]="false" [flexGrow]="1">
|
||||
<ng-template let-column="column" ngx-datatable-header-template>
|
||||
{{t('actions-header')}}
|
||||
</ng-template>
|
||||
|
|
|
@ -45,6 +45,7 @@ import {ScanSeriesEvent} from "../../_models/events/scan-series-event";
|
|||
})
|
||||
export class ManageMatchedMetadataComponent implements OnInit {
|
||||
protected readonly ColumnMode = ColumnMode;
|
||||
protected readonly MatchStateOption = MatchStateOption;
|
||||
protected readonly allMatchStates = allMatchStates.filter(m => m !== MatchStateOption.Matched); // Matched will have too many
|
||||
|
||||
private readonly licenseService = inject(LicenseService);
|
||||
|
@ -119,7 +120,8 @@ export class ManageMatchedMetadataComponent implements OnInit {
|
|||
fixMatch(series: Series) {
|
||||
this.actionService.matchSeries(series, result => {
|
||||
if (!result) return;
|
||||
this.loadData().subscribe();
|
||||
this.data = [...this.data.filter(s => s.series.id !== series.id)];
|
||||
this.cdRef.markForCheck();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
[limit]="15"
|
||||
>
|
||||
|
||||
<ngx-datatable-column name="filePath" [sortable]="true" [draggable]="false" [resizeable]="false" [flexGrow]="3">
|
||||
<ngx-datatable-column prop="filePath" [sortable]="true" [draggable]="false" [resizeable]="false" [flexGrow]="3">
|
||||
<ng-template let-column="column" ngx-datatable-header-template>
|
||||
{{t('file-header')}}
|
||||
</ng-template>
|
||||
|
@ -31,7 +31,7 @@
|
|||
</ngx-datatable-column>
|
||||
|
||||
|
||||
<ngx-datatable-column name="comment" [sortable]="true" [draggable]="false" [resizeable]="false" [flexGrow]="1">
|
||||
<ngx-datatable-column prop="comment" [sortable]="true" [draggable]="false" [resizeable]="false" [flexGrow]="1">
|
||||
<ng-template let-column="column" ngx-datatable-header-template>
|
||||
{{t('comment-header')}}
|
||||
</ng-template>
|
||||
|
@ -40,7 +40,7 @@
|
|||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
|
||||
<ngx-datatable-column name="createdUtc" [sortable]="true" [draggable]="false" [resizeable]="false" [flexGrow]="1">
|
||||
<ngx-datatable-column prop="createdUtc" [sortable]="true" [draggable]="false" [resizeable]="false" [flexGrow]="1">
|
||||
<ng-template let-column="column" ngx-datatable-header-template>
|
||||
{{t('created-header')}}
|
||||
</ng-template>
|
||||
|
|
|
@ -16,8 +16,7 @@ import {AgeRatingDto} from "../../_models/metadata/age-rating-dto";
|
|||
import {MetadataFieldMapping, MetadataFieldType} from "../_models/metadata-settings";
|
||||
import {PersonRole} from "../../_models/metadata/person";
|
||||
import {PersonRolePipe} from "../../_pipes/person-role.pipe";
|
||||
import {NgClass} from "@angular/common";
|
||||
import {allMetadataSettingField} from "../_models/metadata-setting-field";
|
||||
import {allMetadataSettingField, MetadataSettingField} from "../_models/metadata-setting-field";
|
||||
import {MetadataSettingFiledPipe} from "../../_pipes/metadata-setting-filed.pipe";
|
||||
|
||||
|
||||
|
@ -94,7 +93,7 @@ export class ManageMetadataSettingsComponent implements OnInit {
|
|||
|
||||
this.settingsForm.addControl('overrides', this.fb.group(
|
||||
Object.fromEntries(
|
||||
this.allMetadataSettingFields.map((role, index) => [
|
||||
this.allMetadataSettingFields.map((role: MetadataSettingField, index: number) => [
|
||||
`override_${index}`,
|
||||
this.fb.control((settings.overrides || []).includes(role)),
|
||||
])
|
||||
|
@ -182,8 +181,8 @@ export class ManageMetadataSettingsComponent implements OnInit {
|
|||
...model,
|
||||
ageRatingMappings,
|
||||
fieldMappings: withFieldMappings ? fieldMappings : [],
|
||||
blacklist: (model.blacklist || '').split(',').map((item: string) => item.trim()),
|
||||
whitelist: (model.whitelist || '').split(',').map((item: string) => item.trim()),
|
||||
blacklist: (model.blacklist || '').split(',').map((item: string) => item.trim()).filter((tag: string) => tag.length > 0),
|
||||
whitelist: (model.whitelist || '').split(',').map((item: string) => item.trim()).filter((tag: string) => tag.length > 0),
|
||||
personRoles: Object.entries(this.settingsForm.get('personRoles')!.value)
|
||||
.filter(([_, value]) => value)
|
||||
.map(([key, _]) => this.personRoles[parseInt(key.split('_')[1], 10)]),
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
[limit]="15"
|
||||
>
|
||||
|
||||
<ngx-datatable-column name="seriesId" [sortable]="true" [draggable]="false" [resizeable]="false" [flexGrow]="3">
|
||||
<ngx-datatable-column prop="seriesId" [sortable]="true" [draggable]="false" [resizeable]="false" [flexGrow]="3">
|
||||
<ng-template let-column="column" ngx-datatable-header-template>
|
||||
{{t('series-header')}}
|
||||
</ng-template>
|
||||
|
@ -34,7 +34,7 @@
|
|||
</ngx-datatable-column>
|
||||
|
||||
|
||||
<ngx-datatable-column name="created" [sortable]="true" [draggable]="false" [resizeable]="false" [flexGrow]="1">
|
||||
<ngx-datatable-column prop="createdUtc" [sortable]="true" [draggable]="false" [resizeable]="false" [flexGrow]="1">
|
||||
<ng-template let-column="column" ngx-datatable-header-template>
|
||||
{{t('created-header')}}
|
||||
</ng-template>
|
||||
|
@ -43,7 +43,7 @@
|
|||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
|
||||
<ngx-datatable-column name="comment" [sortable]="false" [draggable]="false" [resizeable]="false" [flexGrow]="1">
|
||||
<ngx-datatable-column prop="comment" [sortable]="false" [draggable]="false" [resizeable]="false" [flexGrow]="1">
|
||||
<ng-template let-column="column" ngx-datatable-header-template>
|
||||
{{t('comment-header')}}
|
||||
</ng-template>
|
||||
|
|
|
@ -160,7 +160,7 @@
|
|||
[limit]="15"
|
||||
>
|
||||
|
||||
<ngx-datatable-column name="title" [sortable]="true" [draggable]="false" [resizeable]="false" [flexGrow]="3">
|
||||
<ngx-datatable-column prop="title" [sortable]="true" [draggable]="false" [resizeable]="false" [flexGrow]="3">
|
||||
<ng-template let-column="column" ngx-datatable-header-template>
|
||||
{{t('job-title-header')}}
|
||||
</ng-template>
|
||||
|
@ -170,7 +170,7 @@
|
|||
</ngx-datatable-column>
|
||||
|
||||
|
||||
<ngx-datatable-column name="lastExecutionUtc" [sortable]="true" [draggable]="false" [resizeable]="false" [flexGrow]="1">
|
||||
<ngx-datatable-column prop="lastExecutionUtc" [sortable]="true" [draggable]="false" [resizeable]="false" [flexGrow]="1">
|
||||
<ng-template let-column="column" ngx-datatable-header-template>
|
||||
{{t('last-executed-header')}}
|
||||
</ng-template>
|
||||
|
@ -179,7 +179,7 @@
|
|||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
|
||||
<ngx-datatable-column name="cron" [sortable]="false" [draggable]="false" [resizeable]="false" [flexGrow]="1">
|
||||
<ngx-datatable-column prop="cron" [sortable]="false" [draggable]="false" [resizeable]="false" [flexGrow]="1">
|
||||
<ng-template let-column="column" ngx-datatable-header-template>
|
||||
{{t('cron-header')}}
|
||||
</ng-template>
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
[footerHeight]="50"
|
||||
>
|
||||
|
||||
<ngx-datatable-column name="username" [sortable]="true" [draggable]="false" [resizeable]="false">
|
||||
<ngx-datatable-column prop="username" [sortable]="true" [draggable]="false" [resizeable]="false">
|
||||
<ng-template let-column="column" ngx-datatable-header-template>
|
||||
{{t('username-header')}}
|
||||
</ng-template>
|
||||
|
@ -21,7 +21,7 @@
|
|||
</ngx-datatable-column>
|
||||
|
||||
|
||||
<ngx-datatable-column name="aniListValidUntilUtc" [sortable]="false" [draggable]="false" [resizeable]="false">
|
||||
<ngx-datatable-column prop="aniListValidUntilUtc" [sortable]="false" [draggable]="false" [resizeable]="false">
|
||||
<ng-template let-column="column" ngx-datatable-header-template>
|
||||
{{t('anilist-header')}}
|
||||
</ng-template>
|
||||
|
@ -34,7 +34,7 @@
|
|||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
|
||||
<ngx-datatable-column name="validUntilUtc" [sortable]="false" [draggable]="false" [resizeable]="false">
|
||||
<ngx-datatable-column prop="validUntilUtc" [sortable]="false" [draggable]="false" [resizeable]="false">
|
||||
<ng-template let-column="column" ngx-datatable-header-template>
|
||||
{{t('mal-header')}}
|
||||
</ng-template>
|
||||
|
|
|
@ -122,7 +122,7 @@
|
|||
[allowToggle]="false"
|
||||
(toggle)="switchTabsToDetail()">
|
||||
<ng-template #badgeExpanderItem let-item let-position="idx" let-last="last">
|
||||
<a routerLink="/person/{{item.name}}/" class="dark-exempt btn-icon">{{item.name}}</a>
|
||||
<a routerLink="/person/{{encodeURIComponent(item.name)}}/" class="dark-exempt btn-icon">{{item.name}}</a>
|
||||
</ng-template>
|
||||
</app-badge-expander>
|
||||
</div>
|
||||
|
|
|
@ -1173,4 +1173,6 @@ export class SeriesDetailComponent implements OnInit, AfterContentChecked {
|
|||
}
|
||||
}, 10);
|
||||
}
|
||||
|
||||
protected readonly encodeURIComponent = encodeURIComponent;
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
@if (person !== undefined) {
|
||||
<a class="btn btn-icon p-0" routerLink="/person/{{person.name}}">
|
||||
<a class="btn btn-icon p-0" routerLink="/person/{{encodeURIComponent(person.name)}}">
|
||||
<div class="tagbadge cursor clickable">
|
||||
<div class="d-flex flex-column align-items-center justify-content-center">
|
||||
<div class="image-container d-flex align-items-center justify-content-center">
|
||||
@if (HasCoverImage) {
|
||||
<app-image
|
||||
objectFit="cover"
|
||||
objectFit="cover"
|
||||
height="96px"
|
||||
width="96px"
|
||||
[imageUrl]="ImageUrl"
|
||||
|
|
|
@ -39,4 +39,6 @@ export class PersonBadgeComponent implements OnInit {
|
|||
this.staff = this.person as SeriesStaff;
|
||||
this.cdRef.markForCheck();
|
||||
}
|
||||
|
||||
protected readonly encodeURIComponent = encodeURIComponent;
|
||||
}
|
||||
|
|
|
@ -10,8 +10,8 @@
|
|||
|
||||
div {
|
||||
word-break: break-word;
|
||||
max-width: 75ch;
|
||||
|
||||
max-width: 120ch;
|
||||
|
||||
@media (max-width: $grid-breakpoints-sm) {
|
||||
max-width: 50ch;
|
||||
}
|
||||
|
|
|
@ -214,6 +214,8 @@ export class LibrarySettingsModalComponent implements OnInit {
|
|||
}
|
||||
|
||||
this.libraryForm.get('allowScrobbling')?.setValue(this.IsKavitaPlusEligible);
|
||||
this.libraryForm.get('allowMetadataMatching')?.setValue(this.IsKavitaPlusEligible);
|
||||
|
||||
if (!this.IsKavitaPlusEligible) {
|
||||
this.libraryForm.get('allowScrobbling')?.disable();
|
||||
this.libraryForm.get('allowMetadataMatching')?.disable();
|
||||
|
@ -238,10 +240,12 @@ export class LibrarySettingsModalComponent implements OnInit {
|
|||
this.libraryForm.get('manageCollections')?.setValue(this.library.manageCollections);
|
||||
this.libraryForm.get('manageReadingLists')?.setValue(this.library.manageReadingLists);
|
||||
this.libraryForm.get('collapseSeriesRelationships')?.setValue(this.library.collapseSeriesRelationships);
|
||||
this.libraryForm.get('allowScrobbling')?.setValue(this.library.allowScrobbling);
|
||||
this.libraryForm.get('allowMetadataMatching')?.setValue(this.library.allowMetadataMatching);
|
||||
this.libraryForm.get('allowScrobbling')?.setValue(this.IsKavitaPlusEligible ? this.library.allowScrobbling : false);
|
||||
this.libraryForm.get('allowMetadataMatching')?.setValue(this.IsKavitaPlusEligible ? this.library.allowMetadataMatching : false);
|
||||
this.selectedFolders = this.library.folders;
|
||||
|
||||
this.madeChanges = false;
|
||||
|
||||
for(let fileTypeGroup of allFileTypeGroup) {
|
||||
this.libraryForm.addControl(fileTypeGroup + '', new FormControl(this.library.libraryFileTypes.includes(fileTypeGroup), []));
|
||||
}
|
||||
|
|
|
@ -230,11 +230,13 @@ export class PreferenceNavComponent implements AfterViewInit {
|
|||
if (res) {
|
||||
const kavitaPlusSection = this.sections[4];
|
||||
if (kavitaPlusSection.children.length === 1) {
|
||||
kavitaPlusSection.children.push(new SideNavItem(SettingsTabId.ManageUserTokens, [Role.Admin]));
|
||||
kavitaPlusSection.children.push(new SideNavItem(SettingsTabId.Metadata, [Role.Admin]));
|
||||
|
||||
// Keep all setting type of screens above this line
|
||||
kavitaPlusSection.children.push(new SideNavItem(SettingsTabId.MatchedMetadata, [Role.Admin],
|
||||
this.matchedMetadataBadgeCount$
|
||||
));
|
||||
kavitaPlusSection.children.push(new SideNavItem(SettingsTabId.ManageUserTokens, [Role.Admin]));
|
||||
kavitaPlusSection.children.push(new SideNavItem(SettingsTabId.Metadata, [Role.Admin]));
|
||||
|
||||
// Scrobbling History needs to be per-user and allow admin to view all
|
||||
kavitaPlusSection.children.push(new SideNavItem(SettingsTabId.ScrobblingHolds, []));
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<ng-container *transloco="let t; read:'manage-devices'">
|
||||
|
||||
<div class="position-relative">
|
||||
<button class="btn btn-primary-outline position-absolute custom-position" [disabled]="isReadOnly$" (click)="addDevice()">
|
||||
<button class="btn btn-primary-outline position-absolute custom-position" [disabled]="isReadOnly$ | async" (click)="addDevice()">
|
||||
<i class="fa fa-plus" aria-hidden="true"></i><span class="phone-hidden ms-1">{{t('add')}}</span>
|
||||
</button>
|
||||
</div>
|
||||
|
@ -17,7 +17,7 @@
|
|||
[limit]="15"
|
||||
>
|
||||
|
||||
<ngx-datatable-column name="name" [sortable]="true" [draggable]="false" [resizeable]="false" [flexGrow]="3">
|
||||
<ngx-datatable-column prop="name" [sortable]="true" [draggable]="false" [resizeable]="false" [flexGrow]="3">
|
||||
<ng-template let-column="column" ngx-datatable-header-template>
|
||||
{{t('name-label')}}
|
||||
</ng-template>
|
||||
|
@ -27,7 +27,7 @@
|
|||
</ngx-datatable-column>
|
||||
|
||||
|
||||
<ngx-datatable-column name="email" [sortable]="true" [draggable]="false" [resizeable]="false" [flexGrow]="1">
|
||||
<ngx-datatable-column prop="emailAddress" [sortable]="true" [draggable]="false" [resizeable]="false" [flexGrow]="1">
|
||||
<ng-template let-column="column" ngx-datatable-header-template>
|
||||
{{t('email-label')}}
|
||||
</ng-template>
|
||||
|
@ -36,7 +36,7 @@
|
|||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
|
||||
<ngx-datatable-column name="platform" [sortable]="false" [draggable]="false" [resizeable]="false" [flexGrow]="1">
|
||||
<ngx-datatable-column prop="platform" [sortable]="false" [draggable]="false" [resizeable]="false" [flexGrow]="1">
|
||||
<ng-template let-column="column" ngx-datatable-header-template>
|
||||
{{t('platform-label')}}
|
||||
</ng-template>
|
||||
|
|
|
@ -8,16 +8,10 @@ import {
|
|||
import { Device } from 'src/app/_models/device/device';
|
||||
import { DeviceService } from 'src/app/_services/device.service';
|
||||
import { DevicePlatformPipe } from '../../_pipes/device-platform.pipe';
|
||||
import { SentenceCasePipe } from '../../_pipes/sentence-case.pipe';
|
||||
import {NgbCollapse, NgbModal} from '@ng-bootstrap/ng-bootstrap';
|
||||
import {NgbModal} from '@ng-bootstrap/ng-bootstrap';
|
||||
import {translate, TranslocoDirective} from "@jsverse/transloco";
|
||||
import {SettingsService} from "../../admin/settings.service";
|
||||
import {ConfirmService} from "../../shared/confirm.service";
|
||||
import {SettingItemComponent} from "../../settings/_components/setting-item/setting-item.component";
|
||||
import {DefaultValuePipe} from "../../_pipes/default-value.pipe";
|
||||
import {ScrobbleEventTypePipe} from "../../_pipes/scrobble-event-type.pipe";
|
||||
import {SortableHeader} from "../../_single-module/table/_directives/sortable-header.directive";
|
||||
import {UtcToLocalTimePipe} from "../../_pipes/utc-to-local-time.pipe";
|
||||
import {EditDeviceModalComponent} from "../_modals/edit-device-modal/edit-device-modal.component";
|
||||
import {DefaultModalOptions} from "../../_models/default-modal-options";
|
||||
import {takeUntilDestroyed} from "@angular/core/rxjs-interop";
|
||||
|
@ -25,7 +19,7 @@ import {map} from "rxjs";
|
|||
import {shareReplay} from "rxjs/operators";
|
||||
import {AccountService} from "../../_services/account.service";
|
||||
import {ColumnMode, NgxDatatableModule} from "@siemens/ngx-datatable";
|
||||
import {AsyncPipe, TitleCasePipe} from "@angular/common";
|
||||
import {AsyncPipe} from "@angular/common";
|
||||
|
||||
@Component({
|
||||
selector: 'app-manage-devices',
|
||||
|
@ -33,8 +27,7 @@ import {AsyncPipe, TitleCasePipe} from "@angular/common";
|
|||
styleUrls: ['./manage-devices.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
standalone: true,
|
||||
imports: [NgbCollapse, SentenceCasePipe, DevicePlatformPipe, TranslocoDirective, SettingItemComponent,
|
||||
DefaultValuePipe, ScrobbleEventTypePipe, SortableHeader, UtcToLocalTimePipe, AsyncPipe, NgxDatatableModule, TitleCasePipe]
|
||||
imports: [DevicePlatformPipe, TranslocoDirective, AsyncPipe, NgxDatatableModule]
|
||||
})
|
||||
export class ManageDevicesComponent implements OnInit {
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
[footerHeight]="50"
|
||||
>
|
||||
|
||||
<ngx-datatable-column name="seriesName" [sortable]="true" [draggable]="false" [resizeable]="false">
|
||||
<ngx-datatable-column prop="seriesName" [sortable]="true" [draggable]="false" [resizeable]="false">
|
||||
<ng-template let-column="column" ngx-datatable-header-template>
|
||||
{{t('series-name-header')}}
|
||||
</ng-template>
|
||||
|
@ -22,7 +22,7 @@
|
|||
</ngx-datatable-column>
|
||||
|
||||
|
||||
<ngx-datatable-column name="createdUtc" [sortable]="false" [draggable]="false" [resizeable]="false">
|
||||
<ngx-datatable-column prop="createdUtc" [sortable]="true" [draggable]="false" [resizeable]="false">
|
||||
<ng-template let-column="column" ngx-datatable-header-template>
|
||||
{{t('created-header')}}
|
||||
</ng-template>
|
||||
|
@ -31,7 +31,7 @@
|
|||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
|
||||
<ngx-datatable-column name="validUntilUtc" [sortable]="false" [draggable]="false" [resizeable]="false">
|
||||
<ngx-datatable-column prop="validUntilUtc" [sortable]="true" [draggable]="false" [resizeable]="false">
|
||||
<ng-template let-column="column" ngx-datatable-header-template>
|
||||
|
||||
</ng-template>
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
"username": "{{common.username}}",
|
||||
"required": "{{validation.required-field}}",
|
||||
"email": "{{common.email}}",
|
||||
"not-valid-email": "{{validation.valid-email}}",
|
||||
"invalid-email-warning": "A non-valid email will block some functionalities of Kavita",
|
||||
"cancel": "{{common.cancel}}",
|
||||
"saving": "Saving…",
|
||||
"update": "Update",
|
||||
|
@ -821,8 +821,7 @@
|
|||
"first-last-name-tooltip": "Ensure People's names are written First then Last",
|
||||
"person-roles-label": "Roles",
|
||||
"overrides-label": "Overrides",
|
||||
"overrides-description": "Allow Kavita to write over locked fields"
|
||||
|
||||
"overrides-description": "Allow Kavita to write over locked fields."
|
||||
},
|
||||
|
||||
"book-line-overlay": {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue