mirror of
https://github.com/Kareadita/Kavita.git
synced 2025-07-09 03:04:19 -04:00
Fixed a bug where when no devices, the submenu item would still render. (#1558)
This commit is contained in:
parent
56622ce800
commit
97642cf742
@ -6,6 +6,7 @@ using API.Data.Repositories;
|
|||||||
using API.DTOs.Device;
|
using API.DTOs.Device;
|
||||||
using API.Extensions;
|
using API.Extensions;
|
||||||
using API.Services;
|
using API.Services;
|
||||||
|
using Kavita.Common;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
@ -81,7 +82,15 @@ public class DeviceController : BaseApiController
|
|||||||
if (await _emailService.IsDefaultEmailService())
|
if (await _emailService.IsDefaultEmailService())
|
||||||
return BadRequest("Send to device cannot be used with Kavita's email service. Please configure your own.");
|
return BadRequest("Send to device cannot be used with Kavita's email service. Please configure your own.");
|
||||||
|
|
||||||
if (await _deviceService.SendTo(dto.ChapterId, dto.DeviceId)) return Ok();
|
try
|
||||||
|
{
|
||||||
|
var success = await _deviceService.SendTo(dto.ChapterId, dto.DeviceId);
|
||||||
|
if (success) return Ok();
|
||||||
|
}
|
||||||
|
catch (KavitaException ex)
|
||||||
|
{
|
||||||
|
return BadRequest(ex.Message);
|
||||||
|
}
|
||||||
|
|
||||||
return BadRequest("There was an error sending the file to the device");
|
return BadRequest("There was an error sending the file to the device");
|
||||||
}
|
}
|
||||||
|
@ -93,13 +93,14 @@ export interface ActionItem<T> {
|
|||||||
requiresAdmin: boolean;
|
requiresAdmin: boolean;
|
||||||
children: Array<ActionItem<T>>;
|
children: Array<ActionItem<T>>;
|
||||||
/**
|
/**
|
||||||
* Indicates that there exists a separate list will be loaded from an API
|
* Indicates that there exists a separate list will be loaded from an API.
|
||||||
|
* Rule: If using this, only one child should exist in children with the Action for dynamicList.
|
||||||
*/
|
*/
|
||||||
dynamicList?: Observable<{title: string, data: any}[]> | undefined;
|
dynamicList?: Observable<{title: string, data: any}[]> | undefined;
|
||||||
/**
|
/**
|
||||||
* Extra data that needs to be sent back from the card item. Used mainly for dynamicList. This will be the item from dyanamicList return
|
* Extra data that needs to be sent back from the card item. Used mainly for dynamicList. This will be the item from dyanamicList return
|
||||||
*/
|
*/
|
||||||
_extra?: any;
|
_extra?: {title: string, data: any};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
@ -416,13 +417,16 @@ export class ActionFactoryService {
|
|||||||
title: 'Send To',
|
title: 'Send To',
|
||||||
callback: this.dummyCallback,
|
callback: this.dummyCallback,
|
||||||
requiresAdmin: false,
|
requiresAdmin: false,
|
||||||
|
// dynamicList: this.deviceService.devices$.pipe(map((devices: Array<Device>) => devices.map(d => {
|
||||||
|
// return {'title': d.name, 'data': d};
|
||||||
|
// }), shareReplay())),
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
action: Action.SendTo,
|
action: Action.SendTo,
|
||||||
title: '',
|
title: '',
|
||||||
callback: this.dummyCallback,
|
callback: this.dummyCallback,
|
||||||
requiresAdmin: false,
|
requiresAdmin: false,
|
||||||
dynamicList: this.deviceService.devices$.pipe(map(devices => devices.map(d => {
|
dynamicList: this.deviceService.devices$.pipe(map((devices: Array<Device>) => devices.map(d => {
|
||||||
return {'title': d.name, 'data': d};
|
return {'title': d.name, 'data': d};
|
||||||
}), shareReplay())),
|
}), shareReplay())),
|
||||||
children: []
|
children: []
|
||||||
|
@ -221,7 +221,7 @@ export class CardDetailDrawerComponent implements OnInit, OnDestroy {
|
|||||||
break;
|
break;
|
||||||
case (Action.SendTo):
|
case (Action.SendTo):
|
||||||
{
|
{
|
||||||
const device = (action._extra.data as Device);
|
const device = (action._extra!.data as Device);
|
||||||
this.deviceSerivce.sendTo(chapter.id, device.id).subscribe(() => {
|
this.deviceSerivce.sendTo(chapter.id, device.id).subscribe(() => {
|
||||||
this.toastr.success('File emailed to ' + device.name);
|
this.toastr.success('File emailed to ' + device.name);
|
||||||
});
|
});
|
||||||
|
@ -7,23 +7,29 @@
|
|||||||
</div>
|
</div>
|
||||||
<ng-template #submenu let-list="list">
|
<ng-template #submenu let-list="list">
|
||||||
<ng-container *ngFor="let action of list">
|
<ng-container *ngFor="let action of list">
|
||||||
<ng-container *ngIf="action.children === undefined || action?.children?.length === 0 else submenuDropdown">
|
<!-- Non Submenu items -->
|
||||||
<ng-container *ngIf="action.dynamicList != undefined; else justItem">
|
<ng-container *ngIf="action.children === undefined || action?.children?.length === 0 || action.dynamicList != undefined; else submenuDropdown">
|
||||||
<ng-container *ngFor="let dynamicItem of (action.dynamicList | async)">
|
|
||||||
|
<ng-container *ngIf="action.dynamicList != undefined && toDList(action.dynamicList | async) as dList; else justItem">
|
||||||
|
<ng-container *ngFor="let dynamicItem of dList">
|
||||||
<button ngbDropdownItem (click)="performDynamicClick($event, action, dynamicItem)">{{dynamicItem.title}}</button>
|
<button ngbDropdownItem (click)="performDynamicClick($event, action, dynamicItem)">{{dynamicItem.title}}</button>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-template #justItem>
|
<ng-template #justItem>
|
||||||
<button ngbDropdownItem *ngIf="willRenderAction(action)" (click)="performAction($event, action)">{{action.title}}</button>
|
<button ngbDropdownItem *ngIf="willRenderAction(action)" (click)="performAction($event, action)">{{action.title}}</button>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<ng-template #submenuDropdown>
|
<ng-template #submenuDropdown>
|
||||||
|
<!-- Submenu items -->
|
||||||
|
<ng-container *ngIf="shouldRenderSubMenu(action, action.children[0].dynamicList | async)">
|
||||||
<div ngbDropdown #subMenuHover="ngbDropdown" placement="right" (mouseover)="preventEvent($event); openSubmenu(action.title, subMenuHover)" (mouseleave)="preventEvent($event)">
|
<div ngbDropdown #subMenuHover="ngbDropdown" placement="right" (mouseover)="preventEvent($event); openSubmenu(action.title, subMenuHover)" (mouseleave)="preventEvent($event)">
|
||||||
<button id="actions-{{action.title}}" class="submenu-toggle" ngbDropdownToggle>{{action.title}} <i class="fa-solid fa-angle-right submenu-icon"></i></button>
|
<button id="actions-{{action.title}}" class="submenu-toggle" ngbDropdownToggle>{{action.title}} <i class="fa-solid fa-angle-right submenu-icon"></i></button>
|
||||||
<div ngbDropdownMenu attr.aria-labelledby="actions-{{action.title}}">
|
<div ngbDropdownMenu attr.aria-labelledby="actions-{{action.title}}">
|
||||||
<ng-container *ngTemplateOutlet="submenu; context: { list: action.children }"></ng-container>
|
<ng-container *ngTemplateOutlet="submenu; context: { list: action.children }"></ng-container>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</ng-container>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
@ -47,10 +47,14 @@ export class CardActionablesComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
willRenderAction(action: ActionItem<any>): boolean {
|
willRenderAction(action: ActionItem<any>) {
|
||||||
return (action.requiresAdmin && this.isAdmin)
|
return (action.requiresAdmin && this.isAdmin)
|
||||||
|| (action.action === Action.Download && (this.canDownload || this.isAdmin))
|
|| (action.action === Action.Download && (this.canDownload || this.isAdmin))
|
||||||
|| (!action.requiresAdmin && action.action !== Action.Download)
|
|| (!action.requiresAdmin && action.action !== Action.Download);
|
||||||
|
}
|
||||||
|
|
||||||
|
shouldRenderSubMenu(action: ActionItem<any>, dynamicList: null | Array<any>) {
|
||||||
|
return (action.children[0].dynamicList === undefined || action.children[0].dynamicList === null) || (dynamicList !== null && dynamicList.length > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
openSubmenu(actionTitle: string, subMenu: NgbDropdown) {
|
openSubmenu(actionTitle: string, subMenu: NgbDropdown) {
|
||||||
@ -71,4 +75,9 @@ export class CardActionablesComponent implements OnInit {
|
|||||||
this.performAction(event, action);
|
this.performAction(event, action);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toDList(d: any) {
|
||||||
|
console.log('d: ', d);
|
||||||
|
if (d === undefined || d === null) return [];
|
||||||
|
return d as {title: string, data: any}[];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -446,7 +446,7 @@ export class SeriesDetailComponent implements OnInit, OnDestroy, AfterContentChe
|
|||||||
break;
|
break;
|
||||||
case (Action.SendTo):
|
case (Action.SendTo):
|
||||||
{
|
{
|
||||||
const device = (action._extra.data as Device);
|
const device = (action._extra!.data as Device);
|
||||||
this.deviceSerivce.sendTo(chapter.id, device.id).subscribe(() => {
|
this.deviceSerivce.sendTo(chapter.id, device.id).subscribe(() => {
|
||||||
this.toastr.success('File emailed to ' + device.name);
|
this.toastr.success('File emailed to ' + device.name);
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user