A bunch of bug fixes and some enhancements (#3871)
Co-authored-by: Joseph Milazzo <josephmajora@gmail.com>
This commit is contained in:
parent
62231d3c4e
commit
6fa1cf994e
24 changed files with 1464 additions and 91 deletions
|
@ -9,6 +9,24 @@ import {AccountService} from "./account.service";
|
|||
import {map} from "rxjs/operators";
|
||||
import {NavigationEnd, Router} from "@angular/router";
|
||||
import {takeUntilDestroyed} from "@angular/core/rxjs-interop";
|
||||
import {SettingsTabId} from "../sidenav/preference-nav/preference-nav.component";
|
||||
import {WikiLink} from "../_models/wiki";
|
||||
|
||||
/**
|
||||
* NavItem used to construct the dropdown or NavLinkModal on mobile
|
||||
* Priority construction
|
||||
* @param routerLink A link to a page on the web app, takes priority
|
||||
* @param fragment Optional fragment for routerLink
|
||||
* @param href A link to an external page, must set noopener noreferrer
|
||||
* @param click Callback, lowest priority. Should only be used if routerLink and href or not set
|
||||
*/
|
||||
interface NavItem {
|
||||
transLocoKey: string;
|
||||
href?: string;
|
||||
fragment?: string;
|
||||
routerLink?: string;
|
||||
click?: () => void;
|
||||
}
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
|
@ -21,6 +39,33 @@ export class NavService {
|
|||
|
||||
public localStorageSideNavKey = 'kavita--sidenav--expanded';
|
||||
|
||||
public navItems: NavItem[] = [
|
||||
{
|
||||
transLocoKey: 'all-filters',
|
||||
routerLink: '/all-filters/',
|
||||
},
|
||||
{
|
||||
transLocoKey: 'browse-genres',
|
||||
routerLink: '/browse/genres',
|
||||
},
|
||||
{
|
||||
transLocoKey: 'browse-tags',
|
||||
routerLink: '/browse/tags',
|
||||
},
|
||||
{
|
||||
transLocoKey: 'announcements',
|
||||
routerLink: '/announcements/',
|
||||
},
|
||||
{
|
||||
transLocoKey: 'help',
|
||||
href: WikiLink.Guides,
|
||||
},
|
||||
{
|
||||
transLocoKey: 'logout',
|
||||
click: () => this.logout(),
|
||||
}
|
||||
]
|
||||
|
||||
private navbarVisibleSource = new ReplaySubject<boolean>(1);
|
||||
/**
|
||||
* If the top Nav bar is rendered or not
|
||||
|
@ -127,6 +172,13 @@ export class NavService {
|
|||
}, 10);
|
||||
}
|
||||
|
||||
logout() {
|
||||
this.accountService.logout();
|
||||
this.hideNavBar();
|
||||
this.hideSideNav();
|
||||
this.router.navigateByUrl('/login');
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the side nav. When being visible, the side nav will automatically return to previous collapsed state.
|
||||
*/
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
[sorts]="[{prop: 'createdUtc', dir: 'desc'}]"
|
||||
>
|
||||
|
||||
<ngx-datatable-column prop="select" [sortable]="false" [draggable]="false" [resizeable]="false" [width]="50">
|
||||
<ngx-datatable-column prop="select" [sortable]="false" [draggable]="false" [resizeable]="false">
|
||||
<ng-template let-column="column" ngx-datatable-header-template>
|
||||
<div class="form-check">
|
||||
<input id="select-all" type="checkbox" class="form-check-input"
|
||||
|
|
|
@ -190,7 +190,7 @@ export class ManageMetadataSettingsComponent implements OnInit {
|
|||
destinationValue: value.destinationValue,
|
||||
excludeFromSource: value.excludeFromSource
|
||||
}
|
||||
}).filter(m => m.sourceValue.length > 0);
|
||||
}).filter(m => m.sourceValue.length > 0 && m.destinationValue.length > 0);
|
||||
|
||||
// Translate blacklist string -> Array<string>
|
||||
return {
|
||||
|
@ -231,15 +231,6 @@ export class ManageMetadataSettingsComponent implements OnInit {
|
|||
excludeFromSource: [mapping?.excludeFromSource || false]
|
||||
});
|
||||
|
||||
// Autofill destination value if empty when source value loses focus
|
||||
mappingGroup.get('sourceValue')?.valueChanges
|
||||
.pipe(
|
||||
filter(() => !mappingGroup.get('destinationValue')?.value)
|
||||
)
|
||||
.subscribe(sourceValue => {
|
||||
mappingGroup.get('destinationValue')?.setValue(sourceValue);
|
||||
});
|
||||
|
||||
//@ts-ignore
|
||||
this.fieldMappings.push(mappingGroup);
|
||||
}
|
||||
|
|
|
@ -205,12 +205,15 @@
|
|||
<span class="d-none d-xs-none d-sm-none d-md-inline-block fw-bold">{{user.username | sentenceCase}}</span>
|
||||
</button>
|
||||
<div ngbDropdownMenu>
|
||||
<a ngbDropdownItem routerLink="/all-filters/">{{t('all-filters')}}</a>
|
||||
<a ngbDropdownItem routerLink="/browse/genres">{{t('browse-genres')}}</a>
|
||||
<a ngbDropdownItem routerLink="/browse/tags">{{t('browse-tags')}}</a>
|
||||
<a ngbDropdownItem routerLink="/announcements/">{{t('announcements')}}</a>
|
||||
<a ngbDropdownItem [href]="WikiLink.Guides" rel="noopener noreferrer" target="_blank">{{t('help')}}</a>
|
||||
<a ngbDropdownItem (click)="logout()">{{t('logout')}}</a>
|
||||
@for (navItem of navService.navItems; track $index) {
|
||||
@if (navItem.routerLink) {
|
||||
<a ngbDropdownItem [routerLink]="navItem.routerLink" [fragment]="navItem.fragment">{{t(navItem.transLocoKey)}}</a>
|
||||
} @else if (navItem.href) {
|
||||
<a ngbDropdownItem [href]="navItem.href" rel="noopener noreferrer" target="_blank">{{t(navItem.transLocoKey)}}</a>
|
||||
} @else if (navItem.click) {
|
||||
<a ngbDropdownItem (click)="navItem.click()">{{t(navItem.transLocoKey)}}</a>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
|
|
@ -134,13 +134,6 @@ export class NavHeaderComponent implements OnInit {
|
|||
this.cdRef.markForCheck();
|
||||
}
|
||||
|
||||
logout() {
|
||||
this.accountService.logout();
|
||||
this.navService.hideNavBar();
|
||||
this.navService.hideSideNav();
|
||||
this.router.navigateByUrl('/login');
|
||||
}
|
||||
|
||||
moveFocus() {
|
||||
this.document.getElementById('content')?.focus();
|
||||
}
|
||||
|
@ -253,7 +246,6 @@ export class NavHeaderComponent implements OnInit {
|
|||
|
||||
openLinkSelectionMenu() {
|
||||
const ref = this.modalService.open(NavLinkModalComponent, {fullscreen: 'sm'});
|
||||
ref.componentInstance.logoutFn = this.logout.bind(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -6,21 +6,22 @@
|
|||
<button type="button" class="btn-close" [attr.aria-label]="t('close')" (click)="close()"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
|
||||
<div class="mb-3">
|
||||
<a routerLink="/settings" [fragment]="SettingsTabId.Preferences" (click)="closeIfOnSettings()" [title]="t('settings')">{{t('settings')}}</a>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<a routerLink="/all-filters/">{{t('all-filters')}}</a>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<a routerLink="/announcements/">{{t('announcements')}}</a>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<a [href]="WikiLink.Guides" rel="noopener noreferrer" target="_blank">{{t('help')}}</a>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<a href="javascript:void(0);" (click)="logout()">{{t('logout')}}</a>
|
||||
</div>
|
||||
|
||||
@for (navItem of navService.navItems; track $index) {
|
||||
<div class="mb-3">
|
||||
@if (navItem.routerLink) {
|
||||
<a [routerLink]="navItem.routerLink" [fragment]="navItem.fragment">{{t(navItem.transLocoKey)}}</a>
|
||||
} @else if (navItem.href) {
|
||||
<a [href]="navItem.href" rel="noopener noreferrer" target="_blank">{{t(navItem.transLocoKey)}}</a>
|
||||
} @else if (navItem.click) {
|
||||
<a href="javascript:void(0);" (click)="navItem.click()">{{t(navItem.transLocoKey)}}</a>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-primary" (click)="close()">{{t('close')}}</button>
|
||||
|
|
|
@ -5,6 +5,7 @@ import {Router, RouterLink} from "@angular/router";
|
|||
import {ReactiveFormsModule} from "@angular/forms";
|
||||
import {TranslocoDirective} from "@jsverse/transloco";
|
||||
import {SettingsTabId} from "../../../sidenav/preference-nav/preference-nav.component";
|
||||
import {NavService} from "../../../_services/nav.service";
|
||||
|
||||
@Component({
|
||||
selector: 'app-nav-link-modal',
|
||||
|
@ -25,17 +26,12 @@ export class NavLinkModalComponent {
|
|||
private readonly cdRef = inject(ChangeDetectorRef);
|
||||
private readonly modal = inject(NgbActiveModal);
|
||||
private readonly router = inject(Router);
|
||||
|
||||
@Input({required: true}) logoutFn!: () => void;
|
||||
protected readonly navService = inject(NavService);
|
||||
|
||||
close() {
|
||||
this.modal.close();
|
||||
}
|
||||
|
||||
logout() {
|
||||
this.logoutFn();
|
||||
}
|
||||
|
||||
closeIfOnSettings() {
|
||||
setTimeout(() => {
|
||||
const currentUrl = this.router.url;
|
||||
|
|
|
@ -187,9 +187,8 @@ export class PersonDetailComponent implements OnInit {
|
|||
filter.combination = FilterCombination.Or;
|
||||
filter.limitTo = 20;
|
||||
|
||||
// I might want to use roles$ to do all this
|
||||
allPeople.forEach(f => {
|
||||
filter.statements.push({comparison: FilterComparison.Contains, value: this.person!.id + '', field: f});
|
||||
roles.forEach(pr => {
|
||||
filter.statements.push({comparison: FilterComparison.Contains, value: this.person!.id + '', field: personRoleForFilterField(pr)});
|
||||
});
|
||||
|
||||
return filter;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue