fixed queue cleaner UI settings

This commit is contained in:
Flaminel
2025-06-06 22:20:56 +03:00
parent bcf093148c
commit 12ab97825b
2 changed files with 173 additions and 49 deletions

View File

@@ -64,14 +64,14 @@
</div>
<!-- Detailed Settings in Accordion -->
<p-accordion [multiple]="true" styleClass="mt-3">
<p-accordion [multiple]="true" styleClass="mt-3" [(activeIndex)]="activeAccordionIndices">
<!-- Failed Import Settings -->
<p-accordionTab header="Failed Import Settings" [disabled]="!queueCleanerForm.get('enabled')?.value">
<div class="field-row">
<div class="field-row" formGroupName="failedImport">
<label class="field-label">Max Strikes</label>
<div class="field-input">
<p-inputNumber
formControlName="failedImportMaxStrikes"
formControlName="maxStrikes"
[showButtons]="true"
[min]="0"
[max]="10"
@@ -84,26 +84,26 @@
</div>
</div>
<div class="field-row">
<div class="field-row" formGroupName="failedImport">
<label class="field-label">Ignore Private</label>
<div class="field-input">
<p-checkbox formControlName="failedImportIgnorePrivate" [binary]="true"></p-checkbox>
<p-checkbox formControlName="ignorePrivate" [binary]="true"></p-checkbox>
<small class="form-helper-text">When enabled, private torrents will be ignored</small>
</div>
</div>
<div class="field-row">
<div class="field-row" formGroupName="failedImport">
<label class="field-label">Delete Private</label>
<div class="field-input">
<p-checkbox formControlName="failedImportDeletePrivate" [binary]="true"></p-checkbox>
<p-checkbox formControlName="deletePrivate" [binary]="true"></p-checkbox>
<small class="form-helper-text">When enabled, private torrents will be deleted</small>
</div>
</div>
<div class="field-row">
<div class="field-row" formGroupName="failedImport">
<label class="field-label">Ignore Patterns</label>
<div class="field-input">
<p-chips formControlName="failedImportIgnorePatterns" placeholder="Add pattern and press Enter"></p-chips>
<p-chips formControlName="ignorePatterns" placeholder="Add pattern and press Enter"></p-chips>
<small class="form-helper-text">Patterns to ignore (e.g., *sample*)</small>
</div>
</div>
@@ -111,11 +111,11 @@
<!-- Stalled Settings -->
<p-accordionTab header="Stalled Download Settings" [disabled]="!queueCleanerForm.get('enabled')?.value">
<div class="field-row">
<div class="field-row" formGroupName="stalled">
<label class="field-label">Max Strikes</label>
<div class="field-input">
<p-inputNumber
formControlName="stalledMaxStrikes"
formControlName="maxStrikes"
[showButtons]="true"
[min]="0"
[max]="10"
@@ -128,26 +128,26 @@
</div>
</div>
<div class="field-row">
<div class="field-row" formGroupName="stalled">
<label class="field-label">Reset Strikes On Progress</label>
<div class="field-input">
<p-checkbox formControlName="stalledResetStrikesOnProgress" [binary]="true"></p-checkbox>
<p-checkbox formControlName="resetStrikesOnProgress" [binary]="true"></p-checkbox>
<small class="form-helper-text">When enabled, strikes will be reset if download progress is made</small>
</div>
</div>
<div class="field-row">
<div class="field-row" formGroupName="stalled">
<label class="field-label">Ignore Private</label>
<div class="field-input">
<p-checkbox formControlName="stalledIgnorePrivate" [binary]="true"></p-checkbox>
<p-checkbox formControlName="ignorePrivate" [binary]="true"></p-checkbox>
<small class="form-helper-text">When enabled, private torrents will be ignored</small>
</div>
</div>
<div class="field-row">
<div class="field-row" formGroupName="stalled">
<label class="field-label">Delete Private</label>
<div class="field-input">
<p-checkbox formControlName="stalledDeletePrivate" [binary]="true"></p-checkbox>
<p-checkbox formControlName="deletePrivate" [binary]="true"></p-checkbox>
<small class="form-helper-text">When enabled, private torrents will be deleted</small>
</div>
</div>
@@ -155,8 +155,8 @@
<!-- Downloading Metadata Settings -->
<p-accordionTab header="Downloading Metadata Settings" [disabled]="!queueCleanerForm.get('enabled')?.value">
<div class="field-row">
<label class="field-label">Max Strikes</label>
<div class="field-row" formGroupName="stalled">
<label class="field-label">Max Strikes for Downloading Metadata</label>
<div class="field-input">
<p-inputNumber
formControlName="downloadingMetadataMaxStrikes"
@@ -175,11 +175,11 @@
<!-- Slow Download Settings -->
<p-accordionTab header="Slow Download Settings" [disabled]="!queueCleanerForm.get('enabled')?.value">
<div class="field-row">
<div class="field-row" formGroupName="slow">
<label class="field-label">Max Strikes</label>
<div class="field-input">
<p-inputNumber
formControlName="slowMaxStrikes"
formControlName="maxStrikes"
[showButtons]="true"
[min]="0"
[max]="10"
@@ -192,35 +192,35 @@
</div>
</div>
<div class="field-row">
<div class="field-row" formGroupName="slow">
<label class="field-label">Reset Strikes On Progress</label>
<div class="field-input">
<p-checkbox formControlName="slowResetStrikesOnProgress" [binary]="true"></p-checkbox>
<p-checkbox formControlName="resetStrikesOnProgress" [binary]="true"></p-checkbox>
<small class="form-helper-text">When enabled, strikes will be reset if download progress is made</small>
</div>
</div>
<div class="field-row">
<div class="field-row" formGroupName="slow">
<label class="field-label">Ignore Private</label>
<div class="field-input">
<p-checkbox formControlName="slowIgnorePrivate" [binary]="true"></p-checkbox>
<p-checkbox formControlName="ignorePrivate" [binary]="true"></p-checkbox>
<small class="form-helper-text">When enabled, private torrents will be ignored</small>
</div>
</div>
<div class="field-row">
<div class="field-row" formGroupName="slow">
<label class="field-label">Delete Private</label>
<div class="field-input">
<p-checkbox formControlName="slowDeletePrivate" [binary]="true"></p-checkbox>
<p-checkbox formControlName="deletePrivate" [binary]="true"></p-checkbox>
<small class="form-helper-text">When enabled, private torrents will be deleted</small>
</div>
</div>
<div class="field-row">
<div class="field-row" formGroupName="slow">
<label class="field-label">Minimum Speed</label>
<div class="field-input">
<app-byte-size-input
formControlName="slowMinSpeed"
formControlName="minSpeed"
[min]="0"
placeholder="Enter minimum speed"
helpText="Minimum speed threshold for slow downloads (e.g., 100KB/s)"
@@ -229,11 +229,11 @@
</div>
</div>
<div class="field-row">
<div class="field-row" formGroupName="slow">
<label class="field-label">Maximum Time (hours)</label>
<div class="field-input">
<p-inputNumber
formControlName="slowMaxTime"
formControlName="maxTime"
[showButtons]="true"
[min]="0"
[max]="168"
@@ -244,11 +244,11 @@
</div>
</div>
<div class="field-row">
<div class="field-row" formGroupName="slow">
<label class="field-label">Ignore Above Size</label>
<div class="field-input">
<app-byte-size-input
formControlName="slowIgnoreAboveSize"
formControlName="ignoreAboveSize"
[min]="0"
placeholder="Enter size threshold"
helpText="Size threshold above which slow downloads are ignored"
@@ -257,6 +257,107 @@
</div>
</div>
</p-accordionTab>
<!-- Content Blocker Settings -->
<p-accordionTab header="Content Blocker Settings" [disabled]="!queueCleanerForm.get('enabled')?.value">
<div class="field-row" formGroupName="contentBlocker">
<label class="field-label">Enable Content Blocker</label>
<div class="field-input">
<p-checkbox formControlName="enabled" [binary]="true"></p-checkbox>
<small class="form-helper-text">When enabled, content blocker will filter downloads based on blocklists</small>
</div>
</div>
<div class="field-row" formGroupName="contentBlocker">
<label class="field-label">Ignore Private</label>
<div class="field-input">
<p-checkbox formControlName="ignorePrivate" [binary]="true"></p-checkbox>
<small class="form-helper-text">When enabled, private torrents will be ignored</small>
</div>
</div>
<div class="field-row" formGroupName="contentBlocker">
<label class="field-label">Delete Private</label>
<div class="field-input">
<p-checkbox formControlName="deletePrivate" [binary]="true"></p-checkbox>
<small class="form-helper-text">When enabled, private torrents will be deleted</small>
</div>
</div>
<div formGroupName="contentBlocker">
<div formGroupName="sonarrBlocklist" class="mt-4">
<h4>Sonarr Blocklist</h4>
<div class="field-row">
<label class="field-label">Blocklist Path</label>
<div class="field-input">
<input pInputText formControlName="path" />
<small class="form-helper-text">Path to the blocklist file or URL</small>
</div>
</div>
<div class="field-row">
<label class="field-label">Blocklist Type</label>
<div class="field-input">
<p-dropdown
formControlName="type"
[options]="[{label: 'Blacklist', value: 'Blacklist'}, {label: 'Whitelist', value: 'Whitelist'}]"
optionLabel="label"
optionValue="value"
></p-dropdown>
<small class="form-helper-text">Type of blocklist: Blacklist (block matches) or Whitelist (only allow matches)</small>
</div>
</div>
</div>
<div formGroupName="radarrBlocklist" class="mt-4">
<h4>Radarr Blocklist</h4>
<div class="field-row">
<label class="field-label">Blocklist Path</label>
<div class="field-input">
<input pInputText formControlName="path" />
<small class="form-helper-text">Path to the blocklist file or URL</small>
</div>
</div>
<div class="field-row">
<label class="field-label">Blocklist Type</label>
<div class="field-input">
<p-dropdown
formControlName="type"
[options]="[{label: 'Blacklist', value: 'Blacklist'}, {label: 'Whitelist', value: 'Whitelist'}]"
optionLabel="label"
optionValue="value"
></p-dropdown>
<small class="form-helper-text">Type of blocklist: Blacklist (block matches) or Whitelist (only allow matches)</small>
</div>
</div>
</div>
<div formGroupName="lidarrBlocklist" class="mt-4">
<h4>Lidarr Blocklist</h4>
<div class="field-row">
<label class="field-label">Blocklist Path</label>
<div class="field-input">
<input pInputText formControlName="path" />
<small class="form-helper-text">Path to the blocklist file or URL</small>
</div>
</div>
<div class="field-row">
<label class="field-label">Blocklist Type</label>
<div class="field-input">
<p-dropdown
formControlName="type"
[options]="[{label: 'Blacklist', value: 'Blacklist'}, {label: 'Whitelist', value: 'Whitelist'}]"
optionLabel="label"
optionValue="value"
></p-dropdown>
<small class="form-helper-text">Type of blocklist: Blacklist (block matches) or Whitelist (only allow matches)</small>
</div>
</div>
</div>
</div>
</p-accordionTab>
</p-accordion>
<!-- Action buttons -->

View File

@@ -67,6 +67,9 @@ export class QueueCleanerSettingsComponent implements OnDestroy {
readonly queueCleanerSaving = this.queueCleanerStore.saving;
readonly queueCleanerError = this.queueCleanerStore.error;
// Track active accordion tabs
activeAccordionIndices: number[] = [];
// Subject for unsubscribing from observables when component is destroyed
private destroy$ = new Subject<void>();
@@ -265,12 +268,17 @@ export class QueueCleanerSettingsComponent implements OnDestroy {
* Set up listeners for form control value changes to manage dependent control states
*/
private setupFormValueChangeListeners(): void {
// Listen for changes to the enabled control
this.queueCleanerForm.get('enabled')?.valueChanges.pipe(
takeUntil(this.destroy$)
).subscribe(enabled => {
this.updateMainControlsState(enabled);
});
// Listen to the 'enabled' control changes
this.queueCleanerForm.get('enabled')?.valueChanges
.pipe(takeUntil(this.destroy$))
.subscribe(enabled => {
this.updateMainControlsState(enabled);
// When disabled, close all accordions
if (!enabled) {
this.activeAccordionIndices = [];
}
});
// Failed import settings
this.queueCleanerForm.get('failedImport.maxStrikes')?.valueChanges.pipe(
@@ -350,19 +358,34 @@ export class QueueCleanerSettingsComponent implements OnDestroy {
* Update the state of main controls based on the 'enabled' control value
*/
private updateMainControlsState(enabled: boolean): void {
const options = { onlySelf: true };
// Common controls
const jobScheduleGroup = this.queueCleanerForm.get('jobSchedule') as FormGroup;
if (enabled) {
this.queueCleanerForm.get('jobSchedule')?.enable(options);
this.queueCleanerForm.get('runSequentially')?.enable(options);
this.queueCleanerForm.get('ignoredDownloadsPath')?.enable(options);
this.queueCleanerForm.get('contentBlocker')?.get('enabled')?.enable(options);
jobScheduleGroup.get('every')?.enable({emitEvent: false});
jobScheduleGroup.get('type')?.enable({emitEvent: false});
this.queueCleanerForm.get('runSequentially')?.enable({emitEvent: false});
this.queueCleanerForm.get('ignoredDownloadsPath')?.enable({emitEvent: false});
// Update individual config sections only if they are enabled
const failedImportMaxStrikes = this.queueCleanerForm.get('failedImport.maxStrikes')?.value;
const stalledMaxStrikes = this.queueCleanerForm.get('stalled.maxStrikes')?.value;
const slowMaxStrikes = this.queueCleanerForm.get('slow.maxStrikes')?.value;
const contentBlockerEnabled = this.queueCleanerForm.get('contentBlocker.enabled')?.value;
this.updateFailedImportDependentControls(failedImportMaxStrikes);
this.updateStalledDependentControls(stalledMaxStrikes);
this.updateSlowDependentControls(slowMaxStrikes);
this.updateContentBlockerDependentControls(contentBlockerEnabled);
} else {
this.queueCleanerForm.get('jobSchedule')?.disable(options);
this.queueCleanerForm.get('runSequentially')?.disable(options);
this.queueCleanerForm.get('ignoredDownloadsPath')?.disable(options);
this.queueCleanerForm.get('contentBlocker')?.get('enabled')?.disable(options);
this.updateContentBlockerDependentControls(false);
jobScheduleGroup.get('every')?.disable({emitEvent: false});
jobScheduleGroup.get('type')?.disable({emitEvent: false});
this.queueCleanerForm.get('runSequentially')?.disable({emitEvent: false});
this.queueCleanerForm.get('ignoredDownloadsPath')?.disable({emitEvent: false});
// Save current active accordion state before clearing it
// This will be empty when we collapse all accordions
this.activeAccordionIndices = [];
}
}