Side Nav UX Changes (#3345)
Co-authored-by: Christopher <39032787+MrRobotjs@users.noreply.github.com> Co-authored-by: Robbie Davis <robbie@therobbiedavis.com>
This commit is contained in:
parent
aa939edf6d
commit
3a0c796c08
45 changed files with 1193 additions and 664 deletions
|
|
@ -1,4 +1,5 @@
|
|||
@import '../theme/variables';
|
||||
|
||||
.content-wrapper {
|
||||
padding: 0 0 0 10px;
|
||||
height: calc(var(--vh)* 100 - var(--nav-offset));
|
||||
|
|
@ -14,6 +15,7 @@
|
|||
scrollbar-width: thin;
|
||||
mask-image: linear-gradient(to bottom, transparent, black 0%, black 95%, transparent 100%);
|
||||
-webkit-mask-image: linear-gradient(to bottom, transparent, black 0%, black 95%, transparent 100%);
|
||||
//margin-top: 7px;
|
||||
|
||||
// For firefox
|
||||
@supports (-moz-appearance:none) {
|
||||
|
|
@ -55,7 +57,7 @@
|
|||
}
|
||||
|
||||
.companion-bar-content {
|
||||
margin-left: 190px;
|
||||
margin-left: var(--side-nav-width);
|
||||
}
|
||||
|
||||
@media (max-width: $grid-breakpoints-lg) {
|
||||
|
|
@ -82,7 +84,6 @@
|
|||
margin-left: 0;
|
||||
padding-left: 0;
|
||||
width: 100%;
|
||||
padding: 10px 0 0;
|
||||
height: calc(var(--vh) * 100 - var(--nav-mobile-offset));
|
||||
scrollbar-color: rgba(255,255,255,0.3) rgba(0, 0, 0, 0.1);
|
||||
scrollbar-width: thin;
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
<ng-container *transloco="let t; read: 'bulk-operations'">
|
||||
@if (bulkSelectionService.selections$ | async; as selectionCount) {
|
||||
@if (selectionCount > 0) {
|
||||
<div class="bulk-select-container">
|
||||
<div class="bulk-select mb-3 {{modalMode ? '' : 'fixed-top'}}" [ngStyle]="{'margin-top': topOffset + 'px'}">
|
||||
<div class="bulk-select-container" [ngStyle]="{'margin-left': marginLeft + 'px', 'margin-right': marginRight + 'px'}">
|
||||
<div class="bulk-select">
|
||||
<div class="d-flex justify-content-around align-items-center">
|
||||
|
||||
<span class="highlight">
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
.bulk-select-container {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
z-index: 1;
|
||||
top: 0;
|
||||
position: sticky;
|
||||
|
||||
.bulk-select {
|
||||
background-color: var(--bulk-selection-bg-color);
|
||||
|
|
|
|||
|
|
@ -37,7 +37,14 @@ export class BulkOperationsComponent implements OnInit {
|
|||
* Modal mode means don't fix to the top
|
||||
*/
|
||||
@Input() modalMode = false;
|
||||
@Input() topOffset: number = 75;
|
||||
/**
|
||||
* On Series Detail this should be 12
|
||||
*/
|
||||
@Input() marginLeft: number = 0;
|
||||
/**
|
||||
* On Series Detail this should be 12
|
||||
*/
|
||||
@Input() marginRight: number = 8;
|
||||
hasMarkAsRead: boolean = false;
|
||||
hasMarkAsUnread: boolean = false;
|
||||
actions: Array<ActionItem<any>> = [];
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@
|
|||
|
||||
@if (accountService.isAdmin$ | async) {
|
||||
<div class="col-auto ms-2">
|
||||
<button class="btn btn-secondary-outline" id="edit-btn--komf" (click)="openEditModal()" [ngbTooltip]="t('edit-series-alt')">
|
||||
<button class="btn btn-actions" id="edit-btn--komf" (click)="openEditModal()" [ngbTooltip]="t('edit-series-alt')">
|
||||
<span><i class="fa fa-pen" aria-hidden="true"></i></span>
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -73,7 +73,7 @@
|
|||
|
||||
<div class="col-auto ms-2 d-none d-md-block">
|
||||
<div class="card-actions" [ngbTooltip]="t('more-alt')">
|
||||
<app-card-actionables (actionHandler)="performAction($event)" [actions]="chapterActions" [labelBy]="series.name + ' ' + chapter.minNumber" iconClass="fa-ellipsis-h" btnClass="btn-secondary-outline btn"></app-card-actionables>
|
||||
<app-card-actionables (actionHandler)="performAction($event)" [actions]="chapterActions" [labelBy]="series.name + ' ' + chapter.minNumber" iconClass="fa-ellipsis-h" btnClass="btn-actions btn"></app-card-actionables>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -1 +1,5 @@
|
|||
@use '../../series-detail-common';
|
||||
|
||||
:host ::ng-deep .card-actions .btn.btn-actions {
|
||||
padding: 0.375rem 0.75rem;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -265,6 +265,14 @@ export class LibraryDetailComponent implements OnInit {
|
|||
case(Action.GenerateColorScape):
|
||||
await this.actionService.refreshLibraryMetadata(library, undefined, false);
|
||||
break;
|
||||
case (Action.Delete):
|
||||
await this.actionService.deleteLibrary(library, () => {
|
||||
this.loadPageSource.next(true);
|
||||
});
|
||||
break;
|
||||
case (Action.AnalyzeFiles):
|
||||
await this.actionService.analyzeFiles(library);
|
||||
break;
|
||||
case(Action.Edit):
|
||||
this.actionService.editLibrary(library);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
.widget-button--indicator {
|
||||
position: absolute;
|
||||
top: 30px;
|
||||
top: 24px;
|
||||
color: var(--event-widget-activity-bg-color);
|
||||
|
||||
&.error {
|
||||
|
|
@ -79,6 +79,7 @@
|
|||
.dark-menu-item {
|
||||
&.update-available {
|
||||
cursor: pointer;
|
||||
opacity: 1;
|
||||
|
||||
i.fa {
|
||||
color: var(--primary-color) !important;
|
||||
|
|
|
|||
|
|
@ -72,8 +72,6 @@ export class EventsWidgetComponent implements OnInit, OnDestroy {
|
|||
*/
|
||||
updateAvailable: boolean = false;
|
||||
|
||||
debugMode: boolean = false;
|
||||
|
||||
protected readonly EVENTS = EVENTS;
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,3 @@
|
|||
form {
|
||||
max-height: 38px;
|
||||
}
|
||||
|
||||
|
||||
.search-result img {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
|
@ -16,75 +11,89 @@ form {
|
|||
|
||||
|
||||
.typeahead-input {
|
||||
border: 1px solid transparent;
|
||||
border-radius: 4px;
|
||||
padding: 0px 6px;
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
box-sizing: border-box;
|
||||
box-shadow: none;
|
||||
cursor: text;
|
||||
background-color: var(--searchbar-bg-color);
|
||||
color: var(--body-text-color);
|
||||
min-height: 32px;
|
||||
transition-property: all;
|
||||
transition-duration: 0.3s;
|
||||
display: block;
|
||||
width: 50%;
|
||||
|
||||
.search {
|
||||
display: flex;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
box-sizing: border-box;
|
||||
box-shadow: none;
|
||||
cursor: text;
|
||||
background-color: var(--input-bg-color);
|
||||
color: var(--body-text-color);
|
||||
min-height: 38px;
|
||||
min-height: 32px;
|
||||
|
||||
.btn-close {
|
||||
position: unset;
|
||||
margin-top: unset;
|
||||
align-self: center;
|
||||
margin: 0 8px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
input {
|
||||
width: 100%;
|
||||
padding: 0px 6px;
|
||||
outline: 0 !important;
|
||||
border-radius: .28571429rem;
|
||||
margin: 0px !important;
|
||||
text-indent: 0 !important;
|
||||
line-height: inherit !important;
|
||||
box-shadow: none !important;
|
||||
transition-property: all;
|
||||
transition-duration: 0.3s;
|
||||
display: block;
|
||||
opacity: 1;
|
||||
position: relative;
|
||||
left: 4px;
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
|
||||
.search {
|
||||
display: flex;
|
||||
position: relative;
|
||||
&:focus-visible {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
&.focused {
|
||||
width: 100%;
|
||||
border-color: var(--primary-color);
|
||||
|
||||
input {
|
||||
outline: 0 !important;
|
||||
border-radius: .28571429rem;
|
||||
padding: 0px !important;
|
||||
min-height: 0px !important;
|
||||
max-width: 100% !important;
|
||||
margin: 0px !important;
|
||||
text-indent: 0 !important;
|
||||
line-height: inherit !important;
|
||||
box-shadow: none !important;
|
||||
width: 300px;
|
||||
transition-property: all;
|
||||
transition-duration: 0.3s;
|
||||
display: block;
|
||||
opacity: 1;
|
||||
position: relative;
|
||||
left: 4px;
|
||||
border: none;
|
||||
|
||||
&:focus-visible {
|
||||
width: calc(100vw - 180px);
|
||||
}
|
||||
|
||||
&:empty {
|
||||
padding-top: 6px !important;
|
||||
}
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
&.focused {
|
||||
width: 98.5%;
|
||||
border-color: var(--input-focused-border-color);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@media only screen and (max-width: 980px) {
|
||||
.typeahead-input {
|
||||
width: 65%;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* small devices (phones, 650px and down) */
|
||||
@media only screen and (max-width:650px) {
|
||||
input {
|
||||
width: 100%
|
||||
.typeahead-input {
|
||||
width: 75%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
|
||||
input:focus-visible {
|
||||
width: 100% !important;
|
||||
}
|
||||
@media only screen and (max-width: 500px) {
|
||||
.typeahead-input {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -160,10 +169,10 @@ ul ul {
|
|||
}
|
||||
|
||||
.overlay {
|
||||
position: absolute;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background: rgba(0,0,0,0.4);
|
||||
width: 100%;
|
||||
height: 100dvh;
|
||||
}
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,12 +9,14 @@
|
|||
}
|
||||
|
||||
<a class="navbar-brand dark-exempt" routerLink="/home" routerLinkActive="active">
|
||||
<app-image width="28px" height="28px" imageUrl="assets/images/logo-32.png" classes="logo" />
|
||||
<span class="d-none d-md-inline logo"> Kavita</span>
|
||||
<app-image width="24px" height="24px" imageUrl="assets/images/logo-32.png" classes="logo-icon" />
|
||||
<div class="d-none d-md-inline logo">
|
||||
<span>Kavita</span>
|
||||
</div>
|
||||
</a>
|
||||
<ul class="navbar-nav col me-auto">
|
||||
@if (accountService.currentUser$ | async; as user) {
|
||||
<div class="nav-item">
|
||||
<div class="nav-item search">
|
||||
<label for="nav-search" class="form-label visually-hidden">{{t('search-series-alt')}}</label>
|
||||
<div class="ng-autocomplete">
|
||||
<app-grouped-typeahead
|
||||
|
|
@ -161,8 +163,6 @@
|
|||
}
|
||||
</ul>
|
||||
|
||||
|
||||
@if (!searchFocused) {
|
||||
@if((breakpoint$ | async)! > Breakpoint.Tablet) {
|
||||
@if (backToTopNeeded) {
|
||||
<div class="back-to-top">
|
||||
|
|
@ -206,7 +206,7 @@
|
|||
</div>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
</div>
|
||||
</nav>
|
||||
|
|
|
|||
|
|
@ -1,91 +1,140 @@
|
|||
|
||||
.btn:focus, .btn:hover {
|
||||
.btn:focus {
|
||||
box-shadow: 0 0 0 0.1rem var(--navbar-btn-hover-outline-color);
|
||||
}
|
||||
|
||||
.navbar {
|
||||
background-color: var(--navbar-bg-color);
|
||||
background-color: var(--navbar-bg-color);
|
||||
|
||||
.side-nav-toggle {
|
||||
cursor: pointer;
|
||||
margin-left: 13px;
|
||||
font-size: 1.2rem;
|
||||
i {
|
||||
color: var(--navbar-fa-icon-color);
|
||||
}
|
||||
.navbar-nav {
|
||||
.nav-item {
|
||||
&.search {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.side-nav-toggle {
|
||||
cursor: pointer;
|
||||
margin-left: 0.8125rem;
|
||||
font-size: 1.2rem;
|
||||
|
||||
i {
|
||||
color: var(--navbar-fa-icon-color);
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
i {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.nav-item:not(.search) {
|
||||
display: unset;
|
||||
opacity: 0.8;
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// On Really small screens, hide the server settings wheel and show it in nav
|
||||
// TODO: Look into doing this with bootstrap 5 (and moving to _utilities.scss)
|
||||
.xs-only {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.not-xs-only {
|
||||
display: inherit;
|
||||
}
|
||||
|
||||
@media only screen and (max-width:300px) {
|
||||
.xs-only {
|
||||
display: inherit;
|
||||
}
|
||||
|
||||
.not-xs-only {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.nav-item.dropdown {
|
||||
position: unset;
|
||||
}
|
||||
|
||||
.navbar-brand {
|
||||
font-family: var(--brand-font-family);
|
||||
font-weight: bold;
|
||||
margin: 0 2rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
&:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.logo-icon {
|
||||
align-items: center;
|
||||
align-self: center;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 1.5rem;
|
||||
width: 1.5rem;
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
|
||||
.logo {
|
||||
vertical-align: text-top;
|
||||
max-height: 1.75rem;
|
||||
line-height: 2.0625rem;
|
||||
margin-left: 0.3125rem;
|
||||
}
|
||||
|
||||
.phone-hidden {
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
|
||||
.focus-visible:focus {
|
||||
visibility: visible;
|
||||
color: var(--nav-header-text-color);
|
||||
}
|
||||
|
||||
.ng-autocomplete {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
.primary-text {
|
||||
color: var(--nav-header-text-color);
|
||||
border: none;
|
||||
}
|
||||
|
||||
.search-result {
|
||||
width: 1.5rem;
|
||||
margin-top: 0.3125rem;
|
||||
}
|
||||
|
||||
.scroll-to-top:hover {
|
||||
animation: MoveUpDown 1s linear infinite;
|
||||
}
|
||||
|
||||
.text-light {
|
||||
color: var(--search-result-text-lite-color) !important;
|
||||
}
|
||||
|
||||
/* small devices (phones, 650px and down) */
|
||||
@media only screen and (max-width:650px) {
|
||||
.navbar-nav {
|
||||
width: 0;
|
||||
.navbar-nav {
|
||||
width: 0;
|
||||
}
|
||||
|
||||
.navbar-brand {
|
||||
margin: 0 1rem 0 1rem;
|
||||
|
||||
.logo-icon {
|
||||
margin: unset;
|
||||
}
|
||||
}
|
||||
|
||||
// On Really small screens, hide the server settings wheel and show it in nav
|
||||
// TODO: Look into doing this with bootstrap 5 (and moving to _utilities.scss)
|
||||
.xs-only {
|
||||
display: none;
|
||||
}
|
||||
.not-xs-only {
|
||||
display: inherit;
|
||||
}
|
||||
@media only screen and (max-width:300px) {
|
||||
.xs-only {
|
||||
display: inherit;
|
||||
}
|
||||
.not-xs-only {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.nav-item.dropdown {
|
||||
position: unset;
|
||||
}
|
||||
|
||||
.navbar-brand {
|
||||
font-family: var(--brand-font-family);
|
||||
font-weight: bold;
|
||||
margin: 0 1rem;
|
||||
|
||||
&:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.logo {
|
||||
max-height: 28px;
|
||||
vertical-align: text-top;
|
||||
}
|
||||
|
||||
.phone-hidden {
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
|
||||
.focus-visible:focus {
|
||||
visibility: visible;
|
||||
color: var(--nav-header-text-color);
|
||||
}
|
||||
|
||||
.ng-autocomplete {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
.primary-text {
|
||||
color: var(--nav-header-text-color);
|
||||
border: none;
|
||||
}
|
||||
|
||||
.search-result {
|
||||
width: 24px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.scroll-to-top:hover {
|
||||
animation: MoveUpDown 1s linear infinite;
|
||||
}
|
||||
|
||||
.text-light {
|
||||
color: var(--search-result-text-lite-color) !important;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<ng-container *transloco="let t; read: 'download-button'">
|
||||
@if (canDownload$ | async) {
|
||||
@if (download$ | async; as download) {
|
||||
<button class="btn btn-secondary-outline" (click)="downloadClicked()" [ngbTooltip]="t('download-tooltip')" [disabled]="download !== null">
|
||||
<button class="btn btn-actions" (click)="downloadClicked()" [ngbTooltip]="t('download-tooltip')" [disabled]="download !== null">
|
||||
@if (download) {
|
||||
<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>
|
||||
<span class="visually-hidden">{{t('downloading-status')}}</span>
|
||||
|
|
@ -10,7 +10,7 @@
|
|||
}
|
||||
</button>
|
||||
} @else {
|
||||
<button class="btn btn-secondary-outline" (click)="downloadClicked()" [ngbTooltip]="t('download-tooltip')">
|
||||
<button class="btn btn-actions" (click)="downloadClicked()" [ngbTooltip]="t('download-tooltip')">
|
||||
<i class="fa fa-arrow-alt-circle-down" aria-hidden="true"></i>
|
||||
</button>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<ng-container *transloco="let t; read: 'series-detail'">
|
||||
<app-bulk-operations [actionCallback]="bulkActionCallback" [topOffset]="56"></app-bulk-operations>
|
||||
<app-bulk-operations [actionCallback]="bulkActionCallback" [marginLeft]="12" [marginRight]="0"></app-bulk-operations>
|
||||
|
||||
@if (series && seriesMetadata && libraryType !== null) {
|
||||
<div [ngStyle]="{'height': ScrollingBlockHeight}" class="main-container container-fluid" #scrollingBlock>
|
||||
|
|
@ -48,7 +48,7 @@
|
|||
</div>
|
||||
|
||||
<div class="mt-3 mb-3">
|
||||
<div class="row g-0">
|
||||
<div class="row g-0" style="align-items: center;">
|
||||
<div class="col-auto">
|
||||
<div class="btn-group">
|
||||
<button type="button" class="btn btn-primary-outline" (click)="read()">
|
||||
|
|
@ -72,7 +72,7 @@
|
|||
</div>
|
||||
|
||||
<div class="col-auto ms-2">
|
||||
<button class="btn btn-secondary-outline" (click)="toggleWantToRead()" ngbTooltip="{{isWantToRead ? t('remove-from-want-to-read') : t('add-to-want-to-read')}}">
|
||||
<button class="btn btn-actions" (click)="toggleWantToRead()" ngbTooltip="{{isWantToRead ? t('remove-from-want-to-read') : t('add-to-want-to-read')}}">
|
||||
<span>
|
||||
<i class="{{isWantToRead ? 'fa-solid' : 'fa-regular'}} fa-star" aria-hidden="true"></i>
|
||||
</span>
|
||||
|
|
@ -81,7 +81,7 @@
|
|||
|
||||
@if (isAdmin) {
|
||||
<div class="col-auto ms-2">
|
||||
<button class="btn btn-secondary-outline" id="edit-btn--komf" (click)="openEditSeriesModal()" [ngbTooltip]="t('edit-series-alt')">
|
||||
<button class="btn btn-actions" id="edit-btn--komf" (click)="openEditSeriesModal()" [ngbTooltip]="t('edit-series-alt')">
|
||||
<span><i class="fa fa-pen" aria-hidden="true"></i></span>
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -89,19 +89,19 @@
|
|||
|
||||
@if ((accountService.hasValidLicense$ | async) && libraryAllowsScrobbling) {
|
||||
<div class="col-auto ms-2">
|
||||
<button class="btn btn-secondary-outline" (click)="toggleScrobbling($event)" [ngbTooltip]="t('scrobbling-tooltip')">
|
||||
<button class="btn btn-actions" (click)="toggleScrobbling($event)" [ngbTooltip]="t('scrobbling-tooltip')">
|
||||
<i class="fa-solid fa-tower-{{(isScrobbling) ? 'broadcast' : 'observation'}}" aria-hidden="true"></i>
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="col-auto ms-2 d-none d-md-block">
|
||||
<div class="card-actions mt-2" [ngbTooltip]="t('more-alt')">
|
||||
<app-card-actionables (actionHandler)="performAction($event)" [actions]="seriesActions" [labelBy]="series.name" iconClass="fa-ellipsis-h" btnClass="btn-secondary-outline btn"></app-card-actionables>
|
||||
<div class="card-actions btn-actions" [ngbTooltip]="t('more-alt')">
|
||||
<app-card-actionables (actionHandler)="performAction($event)" [actions]="seriesActions" [labelBy]="series.name" iconClass="fa-ellipsis-h" btnClass="btn"></app-card-actionables>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-auto ms-2 d-none d-md-block">
|
||||
<div class="col-auto ms-2 d-none d-md-block btn-actions">
|
||||
<app-download-button [download$]="download$" [entity]="series" entityType="series"></app-download-button>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -27,4 +27,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
:host ::ng-deep .card-actions.btn-actions .btn {
|
||||
padding: 0.375rem 0.75rem;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<ng-container *transloco="let t;">
|
||||
<div class="container-fluid">
|
||||
<div class="row g-0">
|
||||
<div class="col-10">
|
||||
<div class="settings-row g-0 row">
|
||||
<div class="col-10 setting-title">
|
||||
<h6 class="section-title">
|
||||
@if (labelId) {
|
||||
<label class="reset-label" [for]="labelId">{{title}}</label>
|
||||
|
|
@ -15,9 +15,9 @@
|
|||
</div>
|
||||
<div class="col-2 text-end align-self-end justify-content-end">
|
||||
@if (showEdit) {
|
||||
<button type="button" class="btn btn-text btn-sm" (click)="toggleEditMode()" [disabled]="!canEdit">
|
||||
{{isEditMode ? t('common.close') : (editLabel || t('common.edit'))}}
|
||||
</button>
|
||||
<button type="button" class="btn btn-text btn-sm" (click)="toggleEditMode()" [disabled]="!canEdit">
|
||||
{{isEditMode ? t('common.close') : (editLabel || t('common.edit'))}}
|
||||
</button>
|
||||
}
|
||||
@if (titleActionsRef) {
|
||||
<ng-container [ngTemplateOutlet]="titleActionsRef"></ng-container>
|
||||
|
|
@ -25,7 +25,6 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@if (isEditMode) {
|
||||
<ng-container [ngTemplateOutlet]="valueEditRef"></ng-container>
|
||||
} @else {
|
||||
|
|
@ -34,7 +33,6 @@
|
|||
</span>
|
||||
}
|
||||
|
||||
|
||||
@if (subtitle) {
|
||||
<div class="text-muted mt-2" [innerHTML]="subtitle | safeHtml"></div>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,21 +1,19 @@
|
|||
import {ChangeDetectionStrategy, ChangeDetectorRef, Component, DestroyRef, inject} from '@angular/core';
|
||||
import {CommonModule, NgOptimizedImage} from '@angular/common';
|
||||
import {NgOptimizedImage} from '@angular/common';
|
||||
import {FormControl, FormGroup, FormsModule, ReactiveFormsModule, Validators} from "@angular/forms";
|
||||
import {NgbCollapse, NgbTooltip} from "@ng-bootstrap/ng-bootstrap";
|
||||
import {translate, TranslocoDirective} from "@jsverse/transloco";
|
||||
import {AccountService} from "../../../_services/account.service";
|
||||
import {ToastrService} from "ngx-toastr";
|
||||
import {EditExternalSourceItemComponent} from "../edit-external-source-item/edit-external-source-item.component";
|
||||
import {ExternalSource} from "../../../_models/sidenav/external-source";
|
||||
import {ExternalSourceService} from "../../../_services/external-source.service";
|
||||
import {FilterPipe} from "../../../_pipes/filter.pipe";
|
||||
import {SmartFilter} from "../../../_models/metadata/v2/smart-filter";
|
||||
import {WikiLink} from "../../../_models/wiki";
|
||||
|
||||
@Component({
|
||||
selector: 'app-manage-external-sources',
|
||||
standalone: true,
|
||||
imports: [CommonModule, FormsModule, NgOptimizedImage, NgbTooltip, ReactiveFormsModule, TranslocoDirective, NgbCollapse, EditExternalSourceItemComponent, FilterPipe],
|
||||
imports: [FormsModule, NgOptimizedImage, NgbTooltip, ReactiveFormsModule, TranslocoDirective, NgbCollapse, EditExternalSourceItemComponent, FilterPipe],
|
||||
templateUrl: './manage-external-sources.component.html',
|
||||
styleUrls: ['./manage-external-sources.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<ng-container *transloco="let t; read: 'side-nav-companion-bar'">
|
||||
<div class="mt-0 ms-1 d-flex justify-content-between align-items-center">
|
||||
<div class="mt-0 d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<ng-content select="[title]"></ng-content>
|
||||
<ng-content select="[subtitle]"></ng-content>
|
||||
|
|
|
|||
|
|
@ -1,152 +1,33 @@
|
|||
@import '../../../../theme/variables';
|
||||
|
||||
::ng-deep .side-nav.closed {
|
||||
::ng-deep .side-nav app-side-nav-item:first-child {
|
||||
.active-highlight {
|
||||
border-top-left-radius: 3px;
|
||||
}
|
||||
}
|
||||
|
||||
::ng-deep .side-nav app-side-nav-item:first-child {
|
||||
.side-nav-item {
|
||||
.side-nav-text {
|
||||
opacity: 0 !important;
|
||||
}
|
||||
|
||||
.card-actions {
|
||||
opacity: 0 !important;
|
||||
}
|
||||
|
||||
&.active {
|
||||
color: var(--side-nav-item-active-color);
|
||||
background-color: unset !important;
|
||||
}
|
||||
border-top-left-radius: 3px;
|
||||
}
|
||||
}
|
||||
|
||||
.side-nav-item {
|
||||
position: relative;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 0 0 0 10px;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
min-height: 40px;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
font-size: 0.9rem;
|
||||
|
||||
.side-nav-text {
|
||||
opacity: 1;
|
||||
min-width: 100px;
|
||||
word-break: break-all;
|
||||
-webkit-line-clamp: 1;
|
||||
text-overflow: ellipsis;
|
||||
display: -webkit-box !important;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
|
||||
div {
|
||||
min-width: 102px;
|
||||
width: 100%
|
||||
@media (max-width: $grid-breakpoints-lg) {
|
||||
::ng-deep .side-nav app-side-nav-item:first-child {
|
||||
.side-nav-item {
|
||||
border-top-left-radius: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
span {
|
||||
display:flex;
|
||||
|
||||
&:last-child {
|
||||
flex-grow: 1;
|
||||
justify-content: end;
|
||||
}
|
||||
|
||||
div {
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
justify-content: inherit;
|
||||
min-width: 30px;
|
||||
width: 100%;
|
||||
padding-left: 5px;
|
||||
|
||||
i {
|
||||
font-size: 18px;
|
||||
}
|
||||
::ng-deep .side-nav app-side-nav-item:last-child {
|
||||
.side-nav-item {
|
||||
border-bottom-left-radius: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
&.closed {
|
||||
.side-nav-text {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.card-actions {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
&.active {
|
||||
color: var(--side-nav-item-active-color);
|
||||
background-color: unset;
|
||||
}
|
||||
|
||||
i {
|
||||
color: var(--side-nav-item-closed-color);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: var(--side-nav-hover-text-color);
|
||||
background-color: var(--side-nav-hover-bg-color);
|
||||
|
||||
i {
|
||||
color: var(--side-nav-item-closed-hover-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: var(--side-nav-hover-text-color);
|
||||
background-color: var(--side-nav-hover-bg-color);
|
||||
|
||||
.card-actions i.fa {
|
||||
// TODO: The override to white does not work, please fix for light themes
|
||||
color: var(--side-nav-hover-text-color) !important;
|
||||
}
|
||||
}
|
||||
|
||||
&.active {
|
||||
color: var(--side-nav-item-active-color);
|
||||
background-color: var(--side-nav-active-bg-color);
|
||||
|
||||
.active-highlight {
|
||||
background-color: var(--side-nav-item-active-color);
|
||||
width: 5px;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.side-nav-text, i {
|
||||
color: var(--side-nav-item-active-text-color) !important;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: var(--side-nav-hover-text-color);
|
||||
background-color: var(--side-nav-hover-bg-color);
|
||||
|
||||
.card-actions i.fa {
|
||||
// TODO: The override to white does not work, please fix for light themes
|
||||
color: var(--side-nav-hover-text-color) !important;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: var(--side-nav-text-color);
|
||||
}
|
||||
|
||||
@media (max-width: $grid-breakpoints-lg) {
|
||||
.side-nav-item {
|
||||
align-items: center;
|
||||
padding: 0 10px;
|
||||
height: 55px;
|
||||
font-size: 1rem;
|
||||
|
||||
.side-nav-text {
|
||||
width: 100%;
|
||||
|
|
@ -155,12 +36,5 @@ a {
|
|||
span:last-child {
|
||||
flex-grow: 0;
|
||||
}
|
||||
|
||||
|
||||
&.closed {
|
||||
.card-actions {
|
||||
font-size: inherit;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
@for(section of sections; track section.title + section.children.length; let idx = $index;) {
|
||||
@if (hasAnyChildren(user, section)) {
|
||||
<h5 class="side-nav-header mt-3 mb-2 ms-3" [ngClass]="{'mt-4': idx > 0}">{{t(section.title)}}</h5>
|
||||
<h5 class="side-nav-header mb-2 ms-3" [ngClass]="{'mt-4': idx > 0}">{{t(section.title)}}</h5>
|
||||
@for(item of section.children; track item.fragment) {
|
||||
@if (accountService.hasAnyRole(user, item.roles)) {
|
||||
<app-side-nav-item [id]="'nav-item-' + item.fragment" [noIcon]="true" link="/settings" [fragment]="item.fragment" [title]="item.fragment | settingFragment" [badgeCount]="item.badgeCount$ | async"></app-side-nav-item>
|
||||
|
|
|
|||
|
|
@ -1,84 +1,36 @@
|
|||
@import '../../../theme/variables';
|
||||
// TODO: Move this to a common file so it applies both ways
|
||||
.side-nav {
|
||||
padding-bottom: 10px;
|
||||
width: 190px;
|
||||
background-color: var(--side-nav-bg-color);
|
||||
height: calc((var(--vh)*100) - 75px);
|
||||
position: fixed;
|
||||
margin: 0;
|
||||
left: 10px;
|
||||
top: 73px;
|
||||
overflow-y: hidden;
|
||||
overflow-x: hidden;
|
||||
border-radius: var(--side-nav-border-radius);
|
||||
transition: width var(--side-nav-openclose-transition), background-color var(--side-nav-bg-color-transition), border-color var(--side-nav-border-transition);
|
||||
border: var(--side-nav-border);
|
||||
scrollbar-gutter: stable both-edges;
|
||||
scrollbar-width: thin;
|
||||
|
||||
// For firefox
|
||||
@supports (-moz-appearance:none) {
|
||||
scrollbar-color: transparent transparent;
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: transparent transparent;
|
||||
scrollbar-width: thin;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
background-color: transparent; /*make scrollbar space invisible */
|
||||
width: inherit;
|
||||
display: none;
|
||||
visibility: hidden;
|
||||
background: transparent;
|
||||
background-color: transparent; /*make scrollbar space invisible */
|
||||
width: inherit;
|
||||
display: none;
|
||||
visibility: hidden;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background: transparent; /*makes it invisible when not hovering*/
|
||||
background: transparent; /*makes it invisible when not hovering*/
|
||||
}
|
||||
|
||||
&:hover {
|
||||
scrollbar-width: thin;
|
||||
overflow-y: auto;
|
||||
|
||||
// For firefox
|
||||
@supports (-moz-appearance:none) {
|
||||
scrollbar-color: rgba(255,255,255,0.3) rgba(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
visibility: visible;
|
||||
background-color: rgba(255,255,255,0.3); /*On hover, it will turn grey*/
|
||||
}
|
||||
}
|
||||
|
||||
&.no-donate {
|
||||
height: calc((var(--vh)*100) - 82px);
|
||||
}
|
||||
|
||||
&.hidden {
|
||||
display: none;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
&.closed {
|
||||
width: 50px;
|
||||
overflow-x: hidden;
|
||||
scrollbar-width: thin;
|
||||
overflow-y: auto;
|
||||
background-color: var(--side-nav-closed-bg-color);
|
||||
border: var(--side-nav-border-closed);
|
||||
}
|
||||
// For firefox
|
||||
@supports (-moz-appearance:none) {
|
||||
scrollbar-color: rgba(255,255,255,0.3) rgba(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
.side-nav-item:first {
|
||||
border-top-left-radius: var(--side-nav-border-radius);
|
||||
border-top-right-radius: var(--side-nav-border-radius);
|
||||
}
|
||||
}
|
||||
|
||||
::ng-deep .side-nav-text {
|
||||
div {
|
||||
display: flex;
|
||||
}
|
||||
span {
|
||||
font-size: 0.6rem;
|
||||
&::-webkit-scrollbar-thumb {
|
||||
visibility: visible;
|
||||
background-color: rgba(255,255,255,0.3); /*On hover, it will turn grey*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -112,21 +64,6 @@
|
|||
height: calc((var(--vh)*100) - var(--nav-mobile-offset));
|
||||
}
|
||||
}
|
||||
|
||||
.side-nav-overlay {
|
||||
background-color: var(--side-nav-overlay-color);
|
||||
width: 100vw;
|
||||
height: calc((var(--vh)*100) - var(--nav-offset));
|
||||
position: absolute;
|
||||
left: 0;
|
||||
z-index: 998;
|
||||
|
||||
&.closed {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
.side-nav-header {
|
||||
|
|
@ -134,12 +71,3 @@
|
|||
font-weight: bold;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.side-nav-header:first-of-type {
|
||||
margin-top: 0.5rem !important;
|
||||
}
|
||||
|
||||
// Overrides for this component
|
||||
::ng-deep .side-nav-item {
|
||||
padding: 0 0 0 20px !important;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<ng-container *transloco="let t; read: 'series-detail'">
|
||||
|
||||
<app-bulk-operations [actionCallback]="bulkActionCallback" [topOffset]="55"></app-bulk-operations>
|
||||
<app-bulk-operations [actionCallback]="bulkActionCallback" [marginLeft]="12" [marginRight]="0"></app-bulk-operations>
|
||||
|
||||
<div [ngStyle]="{'height': ScrollingBlockHeight}" class="main-container container-fluid" #scrollingBlock>
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue