Skip to content

Commit

Permalink
Feature/refactor general info (#106)
Browse files Browse the repository at this point in the history
* move global transfer info to the side for larger displays

* misc updates

* update how data is rendered for transfer info, WIP

* endpoint to toggle alt rate limits

* UI to toggle alt rate limit

* show refresh interval in side-nav & other refactoring

* move global transfer info files, create modal for updating global limits

* endpoints for updating global limits

* set limit via UI

* more responsive styles & update sample data

* forgot to include endpoints in prod json...

* POST body should be empty instead of empty object

* also show rate limit if its globally set

* should use kibibits
  • Loading branch information
bill-ahmed authored Jan 10, 2021
1 parent 8dbaebc commit c8380a4
Show file tree
Hide file tree
Showing 23 changed files with 439 additions and 216 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ A material-themed interface to the original [qBittorrent Web UI](https://github.
## Demo!
A live demo is available here: https://qbit-material-webui-demo.herokuapp.com/.

## Installation -- Replacing your existing qBittorrent Web UI
-----

## Installation
This app is tested with **v4.1.5** and higher of qBittorrent, any lower version are not guaranteed to work.

1. Take a production-ready build from [releases](https://github.com/bill-ahmed/qbit-material-WebUI/releases), or [build it yourself](#build)
Expand Down
8 changes: 4 additions & 4 deletions mock_backend/sample_data.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,10 @@ function GetMainData(){
"alltime_ul": 169885275053,
"average_time_queue": 3787,
"connection_status": "connected",
"dht_nodes": 393,
"dht_nodes": GetRandomInt(0, 400),
"dl_info_data": GetRandomInt(MIN_FILE_SIZE, MAX_FILE_SIZE),
"dl_info_speed": GetRandomInt(MIN_SPEED, MAX_SPEED),
"dl_rate_limit": 0,
"dl_rate_limit": GetRandomInt(MIN_SPEED, 10000),
"free_space_on_disk": GetRandomInt(MIN_FILE_SIZE, MAX_FILE_SIZE * 100),
"global_ratio": "1.25",
"queued_io_jobs": 0,
Expand All @@ -55,8 +55,8 @@ function GetMainData(){
"total_wasted_session": 0,
"up_info_data": GetRandomInt(MIN_FILE_SIZE, MAX_FILE_SIZE),
"up_info_speed": GetRandomInt(MIN_SPEED, MAX_SPEED),
"up_rate_limit": 0,
"use_alt_speed_limits": false,
"up_rate_limit": GetRandomInt(MIN_SPEED, 10000),
"use_alt_speed_limits": GetRandomInt(1, 4) % 2 === 0,
"write_cache_overload": "0"
},
"torrents_removed": ["0daea5cece5"],
Expand Down
6 changes: 4 additions & 2 deletions src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import { DeleteTorrentDialogComponent } from './modals/delete-torrent-dialog/del
import { MatCheckboxModule } from '@angular/material/checkbox';
import { SearchTorrentsComponent } from './home/search-torrents/search-torrents.component';
import { MatCardModule } from '@angular/material/card';
import { GlobalTransferInfoComponent } from './torrents-table/global-transfer-info/global-transfer-info.component';
import { GlobalTransferInfoComponent } from './global-transfer-info/global-transfer-info.component';
import { MatSnackBarModule } from '@angular/material/snack-bar';
import { MatDividerModule } from '@angular/material/divider';
import { MatTabsModule } from '@angular/material/tabs';
Expand Down Expand Up @@ -64,6 +64,7 @@ import { WarnSnackbarComponent } from './services/notifications/snackbar/warn-sn
import { ErrorSnackbarComponent } from './services/notifications/snackbar/error-snackbar/error-snackbar.component';
import { InfoSnackbarComponent } from './services/notifications/snackbar/info-snackbar/info-snackbar.component';
import { DragAndDropFilesDirective } from './drag-and-drop-files.directive';
import { RateLimitsDialogComponent } from './modals/rate-limits-dialog/rate-limits-dialog.component';

var appRoutes: Routes;

Expand Down Expand Up @@ -104,7 +105,8 @@ if(!environment.production){
WarnSnackbarComponent,
ErrorSnackbarComponent,
InfoSnackbarComponent,
DragAndDropFilesDirective
DragAndDropFilesDirective,
RateLimitsDialogComponent
],
imports: [
CdkTableModule,
Expand Down
67 changes: 67 additions & 0 deletions src/app/global-transfer-info/global-transfer-info.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<div [ngClass]="{'dark-theme': isDarkTheme | async}" class="global-transfer-info-container mat-app-background">
<mat-card class="mat-elevation-z3 data-container">
<section id="disk_summary">
<mat-spinner diameter=30 *ngIf="isLoading()"></mat-spinner>

<div *ngIf="!isLoading()" id="summaryContent">
<mat-chip-list>
<mat-chip color="default" disableRipple selected>
<mat-icon color="primary">refresh</mat-icon>
<h4>Refresh Interval: {{refreshInterval / 1000}}s</h4>
</mat-chip>

<mat-chip color="default" disableRipple selected>
<mat-icon color="primary">storage</mat-icon>
<h4>Free space: {{getFreeSpaceOnDisk()}}</h4>
</mat-chip>
</mat-chip-list>
</div>
</section>

<br class="hide-small"/>
<mat-divider class="hide-small" [inset]="true"></mat-divider>
<br/>

<section id="global_transfer">
<mat-spinner diameter=30 *ngIf="isLoading()"></mat-spinner>
<div *ngIf="!isLoading()" id="summaryContent">
<mat-chip-list>
<mat-chip color="primary" (click)="handleDownloadLimitSelect()" disableRipple selected matTooltip="Click to set download limit" matTooltipPosition="above">
<mat-icon>arrow_downward</mat-icon>
<h4>{{getDownloadSpeedString()}} {{getDownLimitString()}}</h4>
</mat-chip>

<mat-chip disableRipple>
<mat-icon>vertical_align_bottom</mat-icon>
<h4>Downloaded: {{getDownloadedString()}}</h4>
</mat-chip>

<br/>
<mat-chip color="accent" (click)="handleUploadLimitSelect()" disableRipple selected matTooltip="Click to set upload limit" matTooltipPosition="below">
<mat-icon>arrow_upward</mat-icon>
<h4>{{getUploadSpeedString()}} {{getUpLimitString()}}</h4>
</mat-chip>

<mat-chip disableRipple>
<mat-icon>vertical_align_top</mat-icon>
<h4>Uploaded: {{getUploadedString()}}</h4>
</mat-chip>
</mat-chip-list>
</div>
</section>

<div class="hide-small">
<br/>
<mat-divider [inset]="true"></mat-divider>
<br/>
</div>

<section class="hide-small" id="bottom_actions">
<div class="row">
<mat-slide-toggle labelPosition="before" id="useAltLimits" (toggleChange)="toggleAltSpeedLimits()" [checked]="isAltSpeedEnabled" color="primary" matTooltip="Use alt speed limits" matTooltipPosition="above">
<mat-icon style="margin-top: 8px;">speed</mat-icon>
</mat-slide-toggle>
</div>
</section>
</mat-card>
</div>
69 changes: 69 additions & 0 deletions src/app/global-transfer-info/global-transfer-info.component.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
.global-transfer-info-container {
height: 100%;
padding-top: 56px;

.data-container {
height: 100%;

display: flex;
flex-direction: column;

section h2 {
font-weight: 400;
}

#disk_summary, #global_transfer {
display: flex;
flex-direction: column;

width: 100%;
}

#global_transfer {
flex-grow: 1;
}

#bottom_actions {
width: 100%;

#useAltLimits > label > span {
display: flex;
align-items: center;
}
}
}
}

.row {
display: flex;
flex-direction: row;

margin: 5px 0;
}

h3 {
font-size: 11pt;
margin: 0;
}

#summaryContent h4 {
font-size: 10pt;
margin: 0 5px 0 5px;
}

mat-chip {
border-radius: 0;
width: 100%;
cursor: pointer;
}

/** For small screens */
@media only screen and (max-width: 1550px) {
.global-transfer-info-container {
padding-top: 0;

.hide-small {
display: none;
}
}
}
112 changes: 112 additions & 0 deletions src/app/global-transfer-info/global-transfer-info.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import { Component, OnInit } from '@angular/core';
import { MatDialogRef, MatDialog } from '@angular/material/dialog';
import { TorrentDataStoreService } from 'src/app/services/torrent-management/torrent-data-store.service';
import { GlobalTransferInfo, MainData } from 'src/utils/Interfaces';
import { UnitsHelperService } from 'src/app/services/units-helper.service';
import { ThemeService } from 'src/app/services/theme.service';
import { Observable } from 'rxjs';
import { NetworkConnectionInformationService } from 'src/app/services/network/network-connection-information.service';
import { RateLimitsDialogComponent } from '../modals/rate-limits-dialog/rate-limits-dialog.component';

@Component({
selector: 'app-global-transfer-info',
templateUrl: './global-transfer-info.component.html',
styleUrls: ['./global-transfer-info.component.scss']
})
export class GlobalTransferInfoComponent implements OnInit {

public data: GlobalTransferInfo = null;
public isAltSpeedEnabled: boolean;

public refreshInterval = -1;

public isDarkTheme: Observable<boolean>;

private rateLimitDiaglogRef: MatDialogRef<RateLimitsDialogComponent>;

constructor(private data_store: TorrentDataStoreService, private networkInfo: NetworkConnectionInformationService, private units_helper:
UnitsHelperService, private rateLimitDialog: MatDialog, private theme: ThemeService) { }

ngOnInit(): void {
this.isDarkTheme = this.theme.getThemeSubscription();
// Subscribe to any changes with data store
this.data_store.GetTorrentDataSubscription().subscribe((res: MainData) => {
if(res) {
this.handleDataChange(res.server_state);
}
});

// Store refresh interval & subscribe to any changes
this.refreshInterval = this.networkInfo.getRefreshInterval();
this.networkInfo.get_network_change_subscription()
.subscribe(newInterval => {
this.refreshInterval = this.networkInfo.getRefreshInterval();
})
}

handleDataChange(newData: GlobalTransferInfo): void {
this.data = newData;
this.isAltSpeedEnabled = this.data.use_alt_speed_limits;
}

handleDownloadLimitSelect() {
this.rateLimitDiaglogRef = this.rateLimitDialog.open(RateLimitsDialogComponent, {
autoFocus: false,
data: {
for: 'Download',
currentLimit: this.data.dl_rate_limit
},
panelClass: "generic-dialog"
});
}

handleUploadLimitSelect() {
this.rateLimitDiaglogRef = this.rateLimitDialog.open(RateLimitsDialogComponent, {
autoFocus: false,
data: {
for: 'Upload',
currentLimit: this.data.dl_rate_limit
},
panelClass: "generic-dialog"
});
}

async toggleAltSpeedLimits() {
console.log('toggled alt limits')
this.isAltSpeedEnabled = !this.isAltSpeedEnabled
await this.data_store.ToggleAltSpeedLimits();
}

getDownloadSpeedString() {
return `${this.units_helper.GetFileSizeString(this.data.dl_info_speed)}/s`;
}

getDownloadedString() {
return `${this.units_helper.GetFileSizeString(this.data.dl_info_data)}`;
}

getUploadSpeedString() {
return `${this.units_helper.GetFileSizeString(this.data.up_info_speed)}/s`;
}

getUploadedString() {
return `${this.units_helper.GetFileSizeString(this.data.up_info_data)}`;
}

getDownLimitString() {
return (this.isAltSpeedEnabled || this.data.dl_rate_limit > 0) ? `[${this.units_helper.GetFileSizeString(this.data.dl_rate_limit)}/s]` : '';
}

getUpLimitString() {
return (this.isAltSpeedEnabled || this.data.up_rate_limit > 0) ? `[${this.units_helper.GetFileSizeString(this.data.up_rate_limit)}/s]` : '';
}

getFreeSpaceOnDisk() {
return `${this.units_helper.GetFileSizeString(this.data.free_space_on_disk)}`;
}

isLoading(): boolean {
return !this.data;
}

}
34 changes: 30 additions & 4 deletions src/app/home/home.component.css
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,37 @@ app-search-torrents:focus-within {
min-height: 100%;
width: 100%;

flex-grow: 1;
flex-direction: column;
flex-direction: row;
justify-content: space-evenly;

padding-left: 2px;
padding-right: 2px;
}

.content app-torrents-table {
width: 83%;
}

.content app-global-transfer-info {
width: 15%;
margin-top: 30px;
}

/** For small screens */
@media only screen and (max-width: 1550px) {
.content {
flex-direction: column;
padding: 0 5%;
}

padding-left: 8%;
padding-right: 8%;
.content app-torrents-table {
width: 100%;
}

.content app-global-transfer-info {
width: 100%;
margin-top: 10px;
}
}

/** For phone screens */
Expand Down
14 changes: 7 additions & 7 deletions src/app/home/home.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,11 @@
<div class="toolbar">
<mat-toolbar>
<div>
<h1>
Manage Torrents
</h1>
<p class="hide_mobile" id="qbit_version_info" style="margin-bottom: 0; font-size: 11pt;">
Qbittorrent {{getAppVersion()}}, API v{{getAPIVersion()}}
</p>
<h1> qBittorrent </h1>

<h3 class="hide_mobile" style="font-size: 11pt;">
{{getAppVersion()}}, API v{{getAPIVersion()}}
</h3>
</div>

<app-search-torrents></app-search-torrents>
Expand Down Expand Up @@ -56,6 +55,7 @@ <h1>

<!-- Main Content -->
<div class="content" role="main">
<app-torrents-table></app-torrents-table>
<app-torrents-table></app-torrents-table>
<app-global-transfer-info></app-global-transfer-info>
</div>
</div>
Empty file.
Loading

0 comments on commit c8380a4

Please sign in to comment.