Add bulk change settings modal.
This commit is contained in:
parent
ba243d3e83
commit
d01cb71866
5 changed files with 274 additions and 4 deletions
|
|
@ -74,6 +74,15 @@
|
||||||
>
|
>
|
||||||
Retry Selected
|
Retry Selected
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
<button
|
||||||
|
class="button is-primary"
|
||||||
|
(click)="changeSettingsModal()"
|
||||||
|
[disabled]="selectedTorrents.length === 0"
|
||||||
|
*ngIf="torrents.length > 0"
|
||||||
|
>
|
||||||
|
Change Settings
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -150,11 +159,144 @@
|
||||||
class="button is-success"
|
class="button is-success"
|
||||||
(click)="retryOk()"
|
(click)="retryOk()"
|
||||||
[disabled]="retrying"
|
[disabled]="retrying"
|
||||||
[ngClass]="{ 'is-loading': deleting }"
|
[ngClass]="{ 'is-loading': retrying }"
|
||||||
>
|
>
|
||||||
Retry selected
|
Retry selected
|
||||||
</button>
|
</button>
|
||||||
<button class="button" (click)="retryCancel()" [disabled]="retrying" [ngClass]="{ 'is-loading': deleting }">
|
<button class="button" (click)="retryCancel()" [disabled]="retrying" [ngClass]="{ 'is-loading': retrying }">
|
||||||
|
Cancel
|
||||||
|
</button>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="modal" [class.is-active]="isChangeSettingsModalActive">
|
||||||
|
<div class="modal-background"></div>
|
||||||
|
<div class="modal-card">
|
||||||
|
<header class="modal-card-head">
|
||||||
|
<p class="modal-card-title">Change settings for selected torrents</p>
|
||||||
|
<button class="delete" aria-label="close" (click)="changeSettingsCancel()"></button>
|
||||||
|
</header>
|
||||||
|
<section class="modal-card-body">
|
||||||
|
<div class="field">
|
||||||
|
<label class="label">Downloader</label>
|
||||||
|
<div class="control select is-fullwidth">
|
||||||
|
<select [(ngModel)]="updateSettingsDownloadClient">
|
||||||
|
<option [ngValue]="null"></option>
|
||||||
|
<option [ngValue]="0">Internal Downloader</option>
|
||||||
|
<option [ngValue]="1">Aria2c</option>
|
||||||
|
<option [ngValue]="2">Symlink Downloader</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<p class="help">
|
||||||
|
Select which downloader is used to download this torrent from the debrid provider to your host.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="field">
|
||||||
|
<label class="label">Post Download Action</label>
|
||||||
|
<div class="control select is-fullwidth">
|
||||||
|
<select [(ngModel)]="updateSettingsHostDownloadAction">
|
||||||
|
<option [ngValue]="0">Download all files to host</option>
|
||||||
|
<option [ngValue]="1">Don't download any files to host</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<p class="help">
|
||||||
|
When a torrent is finished downloading on the provider, perform this action. Use this setting if you only want
|
||||||
|
to add files to Real-Debrid but not download them to the host.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="field">
|
||||||
|
<label class="label">Category</label>
|
||||||
|
<div class="control">
|
||||||
|
<input class="input" type="text" maxlength="100" [(ngModel)]="updateSettingsCategory" />
|
||||||
|
</div>
|
||||||
|
<p class="help">The category becomes a sub-folder in your main download path.</p>
|
||||||
|
</div>
|
||||||
|
<div class="field">
|
||||||
|
<label class="label">Priority</label>
|
||||||
|
<div class="control">
|
||||||
|
<input class="input" type="number" step="1" [(ngModel)]="updateSettingsPriority" />
|
||||||
|
</div>
|
||||||
|
<p class="help">
|
||||||
|
Set the priority for this torrent where 1 is the highest. When empty it will be assigned the lowest priority.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="field">
|
||||||
|
<label class="label">Automatic retry downloads</label>
|
||||||
|
<div class="control">
|
||||||
|
<input
|
||||||
|
class="input"
|
||||||
|
type="number"
|
||||||
|
max="1000"
|
||||||
|
min="0"
|
||||||
|
step="1"
|
||||||
|
[(ngModel)]="updateSettingsDownloadRetryAttempts"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<p class="help">When a single download fails it will retry it this many times before marking it as failed.</p>
|
||||||
|
</div>
|
||||||
|
<div class="field">
|
||||||
|
<label class="label">Automatic retry torrent</label>
|
||||||
|
<div class="control">
|
||||||
|
<input
|
||||||
|
class="input"
|
||||||
|
type="number"
|
||||||
|
max="1000"
|
||||||
|
min="0"
|
||||||
|
step="1"
|
||||||
|
[(ngModel)]="updateSettingsTorrentRetryAttempts"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<p class="help">
|
||||||
|
When a single download has failed multiple times (see setting above) or when the torrent itself received an
|
||||||
|
error it will retry the full torrent this many times before marking it failed.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="field">
|
||||||
|
<label class="label">Delete download when in error</label>
|
||||||
|
<div class="control">
|
||||||
|
<input class="input" type="number" max="1000" min="0" step="1" [(ngModel)]="updateSettingsDeleteOnError" />
|
||||||
|
</div>
|
||||||
|
<p class="help">
|
||||||
|
When a download has been in error for this many minutes, delete it from the provider and the client. 0 to
|
||||||
|
disable.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="field">
|
||||||
|
<label class="label">Torrent maximum lifetime</label>
|
||||||
|
<div class="control">
|
||||||
|
<input
|
||||||
|
class="input"
|
||||||
|
type="number"
|
||||||
|
max="100000"
|
||||||
|
min="0"
|
||||||
|
step="1"
|
||||||
|
[(ngModel)]="updateSettingsTorrentLifetime"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<p class="help">
|
||||||
|
The maximum lifetime of a torrent in minutes. When this time has passed, mark the torrent as error. If the
|
||||||
|
torrent is completed and has downloads, the lifetime setting will not apply. 0 to disable.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="notification is-danger is-light" *ngIf="changeSettingsError?.length > 0">
|
||||||
|
Error changing settings: {{ changeSettingsError }}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<footer class="modal-card-foot">
|
||||||
|
<button
|
||||||
|
class="button is-success"
|
||||||
|
(click)="changeSettingsOk()"
|
||||||
|
[disabled]="changingSettings"
|
||||||
|
[ngClass]="{ 'is-loading': changingSettings }"
|
||||||
|
>
|
||||||
|
Save
|
||||||
|
</button>
|
||||||
|
<button class="button" (click)="changeSettingsCancel()" [disabled]="changingSettings" [ngClass]="{ 'is-loading': changingSettings }">
|
||||||
Cancel
|
Cancel
|
||||||
</button>
|
</button>
|
||||||
</footer>
|
</footer>
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,23 @@ export class TorrentTableComponent implements OnInit {
|
||||||
public retryError: string;
|
public retryError: string;
|
||||||
public retrying: boolean;
|
public retrying: boolean;
|
||||||
|
|
||||||
constructor(private router: Router, private torrentService: TorrentService) {}
|
public isChangeSettingsModalActive: boolean;
|
||||||
|
public changeSettingsError: string;
|
||||||
|
public changingSettings: boolean;
|
||||||
|
|
||||||
|
public updateSettingsDownloadClient: number;
|
||||||
|
public updateSettingsHostDownloadAction: number;
|
||||||
|
public updateSettingsCategory: string;
|
||||||
|
public updateSettingsPriority: number;
|
||||||
|
public updateSettingsDownloadRetryAttempts: number;
|
||||||
|
public updateSettingsTorrentRetryAttempts: number;
|
||||||
|
public updateSettingsDeleteOnError: number;
|
||||||
|
public updateSettingsTorrentLifetime: number;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private router: Router,
|
||||||
|
private torrentService: TorrentService,
|
||||||
|
) {}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.torrentService.getList().subscribe(
|
this.torrentService.getList().subscribe(
|
||||||
|
|
@ -38,7 +54,7 @@ export class TorrentTableComponent implements OnInit {
|
||||||
},
|
},
|
||||||
(err) => {
|
(err) => {
|
||||||
this.error = err.error;
|
this.error = err.error;
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -138,4 +154,89 @@ export class TorrentTableComponent implements OnInit {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public changeSettingsModal(): void {
|
||||||
|
this.changeSettingsError = null;
|
||||||
|
|
||||||
|
const selectedTorrents = this.torrents.where((m) => this.selectedTorrents.indexOf(m.torrentId) > -1);
|
||||||
|
|
||||||
|
this.updateSettingsDownloadClient =
|
||||||
|
selectedTorrents.distinctBy((m) => m.downloadClient).count() == 1 ? selectedTorrents[0].downloadClient : null;
|
||||||
|
this.updateSettingsHostDownloadAction =
|
||||||
|
selectedTorrents.distinctBy((m) => m.hostDownloadAction).count() == 1
|
||||||
|
? selectedTorrents[0].hostDownloadAction
|
||||||
|
: null;
|
||||||
|
this.updateSettingsCategory =
|
||||||
|
selectedTorrents.distinctBy((m) => m.category).count() == 1 ? selectedTorrents[0].category : null;
|
||||||
|
this.updateSettingsPriority =
|
||||||
|
selectedTorrents.distinctBy((m) => m.priority).count() == 1 ? selectedTorrents[0].priority : null;
|
||||||
|
this.updateSettingsDownloadRetryAttempts =
|
||||||
|
selectedTorrents.distinctBy((m) => m.downloadRetryAttempts).count() == 1
|
||||||
|
? selectedTorrents[0].downloadRetryAttempts
|
||||||
|
: null;
|
||||||
|
this.updateSettingsTorrentRetryAttempts =
|
||||||
|
selectedTorrents.distinctBy((m) => m.torrentRetryAttempts).count() == 1
|
||||||
|
? selectedTorrents[0].torrentRetryAttempts
|
||||||
|
: null;
|
||||||
|
this.updateSettingsDeleteOnError =
|
||||||
|
selectedTorrents.distinctBy((m) => m.deleteOnError).count() == 1 ? selectedTorrents[0].deleteOnError : null;
|
||||||
|
this.updateSettingsTorrentLifetime =
|
||||||
|
selectedTorrents.distinctBy((m) => m.lifetime).count() == 1 ? selectedTorrents[0].lifetime : null;
|
||||||
|
|
||||||
|
this.isChangeSettingsModalActive = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public changeSettingsCancel(): void {
|
||||||
|
this.isChangeSettingsModalActive = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public changeSettingsOk(): void {
|
||||||
|
this.changingSettings = true;
|
||||||
|
|
||||||
|
let calls: Observable<void>[] = [];
|
||||||
|
|
||||||
|
const selectedTorrents = this.torrents.where((m) => this.selectedTorrents.indexOf(m.torrentId) > -1);
|
||||||
|
|
||||||
|
selectedTorrents.forEach((torrent) => {
|
||||||
|
if (this.updateSettingsDownloadClient != null) {
|
||||||
|
torrent.downloadClient = this.updateSettingsDownloadClient;
|
||||||
|
}
|
||||||
|
if (this.updateSettingsHostDownloadAction != null) {
|
||||||
|
torrent.hostDownloadAction = this.updateSettingsHostDownloadAction;
|
||||||
|
}
|
||||||
|
if (this.updateSettingsCategory != null) {
|
||||||
|
torrent.category = this.updateSettingsCategory;
|
||||||
|
}
|
||||||
|
if (this.updateSettingsPriority != null) {
|
||||||
|
torrent.priority = this.updateSettingsPriority;
|
||||||
|
}
|
||||||
|
if (this.updateSettingsDownloadRetryAttempts != null) {
|
||||||
|
torrent.retryCount = this.updateSettingsDownloadRetryAttempts;
|
||||||
|
}
|
||||||
|
if (this.updateSettingsTorrentRetryAttempts != null) {
|
||||||
|
torrent.torrentRetryAttempts = this.updateSettingsTorrentRetryAttempts;
|
||||||
|
}
|
||||||
|
if (this.updateSettingsDeleteOnError != null) {
|
||||||
|
torrent.deleteOnError = this.updateSettingsDeleteOnError;
|
||||||
|
}
|
||||||
|
if (this.updateSettingsTorrentLifetime != null) {
|
||||||
|
torrent.lifetime = this.updateSettingsTorrentLifetime;
|
||||||
|
}
|
||||||
|
|
||||||
|
calls.push(this.torrentService.update(torrent));
|
||||||
|
});
|
||||||
|
|
||||||
|
forkJoin(calls).subscribe({
|
||||||
|
complete: () => {
|
||||||
|
this.isChangeSettingsModalActive = false;
|
||||||
|
this.changingSettings = false;
|
||||||
|
|
||||||
|
this.selectedTorrents = [];
|
||||||
|
},
|
||||||
|
error: (err) => {
|
||||||
|
this.changeSettingsError = err.error;
|
||||||
|
this.changingSettings = false;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,14 @@
|
||||||
<label class="label">Category</label>
|
<label class="label">Category</label>
|
||||||
{{ torrent.category || "(no category set)" }}
|
{{ torrent.category || "(no category set)" }}
|
||||||
</div>
|
</div>
|
||||||
|
<div class="field">
|
||||||
|
<label class="label">Downloader</label>
|
||||||
|
<ng-container [ngSwitch]="torrent.downloadClient">
|
||||||
|
<ng-container *ngSwitchCase="0">Internal Downloader</ng-container>
|
||||||
|
<ng-container *ngSwitchCase="1">Aria2c</ng-container>
|
||||||
|
<ng-container *ngSwitchCase="2">Symlink Downloader</ng-container>
|
||||||
|
</ng-container>
|
||||||
|
</div>
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label class="label">Post Download Action</label>
|
<label class="label">Post Download Action</label>
|
||||||
<ng-container [ngSwitch]="torrent.hostDownloadAction">
|
<ng-container [ngSwitch]="torrent.hostDownloadAction">
|
||||||
|
|
@ -469,10 +477,25 @@
|
||||||
<button class="delete" aria-label="close" (click)="updateSettingsCancel()"></button>
|
<button class="delete" aria-label="close" (click)="updateSettingsCancel()"></button>
|
||||||
</header>
|
</header>
|
||||||
<section class="modal-card-body">
|
<section class="modal-card-body">
|
||||||
|
<p>Settings that are blank do not have the same values for each torrent. Updating a setting with a blank value will not update it.</p>
|
||||||
|
<div class="field">
|
||||||
|
<label class="label">Downloader</label>
|
||||||
|
<div class="control select is-fullwidth">
|
||||||
|
<select [(ngModel)]="updateSettingsDownloadClient">
|
||||||
|
<option [ngValue]="0">Internal Downloader</option>
|
||||||
|
<option [ngValue]="1">Aria2c</option>
|
||||||
|
<option [ngValue]="2">Symlink Downloader</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<p class="help">
|
||||||
|
Select which downloader is used to download this torrent from the debrid provider to your host.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label class="label">Post Download Action</label>
|
<label class="label">Post Download Action</label>
|
||||||
<div class="control select is-fullwidth">
|
<div class="control select is-fullwidth">
|
||||||
<select [(ngModel)]="updateSettingsHostDownloadAction">
|
<select [(ngModel)]="updateSettingsHostDownloadAction">
|
||||||
|
<option [ngValue]="null"></option>
|
||||||
<option [ngValue]="0">Download all files to host</option>
|
<option [ngValue]="0">Download all files to host</option>
|
||||||
<option [ngValue]="1">Don't download any files to host</option>
|
<option [ngValue]="1">Don't download any files to host</option>
|
||||||
</select>
|
</select>
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ export class TorrentComponent implements OnInit {
|
||||||
|
|
||||||
public isUpdateSettingsModalActive: boolean;
|
public isUpdateSettingsModalActive: boolean;
|
||||||
|
|
||||||
|
public updateSettingsDownloadClient: number;
|
||||||
public updateSettingsHostDownloadAction: number;
|
public updateSettingsHostDownloadAction: number;
|
||||||
public updateSettingsCategory: string;
|
public updateSettingsCategory: string;
|
||||||
public updateSettingsPriority: number;
|
public updateSettingsPriority: number;
|
||||||
|
|
@ -177,6 +178,7 @@ export class TorrentComponent implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
public showUpdateSettingsModal(): void {
|
public showUpdateSettingsModal(): void {
|
||||||
|
this.updateSettingsDownloadClient = this.torrent.downloadClient;
|
||||||
this.updateSettingsHostDownloadAction = this.torrent.hostDownloadAction;
|
this.updateSettingsHostDownloadAction = this.torrent.hostDownloadAction;
|
||||||
this.updateSettingsCategory = this.torrent.category;
|
this.updateSettingsCategory = this.torrent.category;
|
||||||
this.updateSettingsPriority = this.torrent.priority;
|
this.updateSettingsPriority = this.torrent.priority;
|
||||||
|
|
@ -195,6 +197,7 @@ export class TorrentComponent implements OnInit {
|
||||||
public updateSettingsOk(): void {
|
public updateSettingsOk(): void {
|
||||||
this.updating = true;
|
this.updating = true;
|
||||||
|
|
||||||
|
this.torrent.downloadClient = this.updateSettingsDownloadClient;
|
||||||
this.torrent.hostDownloadAction = this.updateSettingsHostDownloadAction;
|
this.torrent.hostDownloadAction = this.updateSettingsHostDownloadAction;
|
||||||
this.torrent.category = this.updateSettingsCategory;
|
this.torrent.category = this.updateSettingsCategory;
|
||||||
this.torrent.priority = this.updateSettingsPriority;
|
this.torrent.priority = this.updateSettingsPriority;
|
||||||
|
|
|
||||||
|
|
@ -150,6 +150,7 @@ public class TorrentData
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dbTorrent.DownloadClient = torrent.DownloadClient;
|
||||||
dbTorrent.HostDownloadAction = torrent.HostDownloadAction;
|
dbTorrent.HostDownloadAction = torrent.HostDownloadAction;
|
||||||
dbTorrent.Category = torrent.Category;
|
dbTorrent.Category = torrent.Category;
|
||||||
dbTorrent.Priority = torrent.Priority;
|
dbTorrent.Priority = torrent.Priority;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue