This commit is contained in:
Flaminel
2025-05-31 00:54:25 +03:00
parent d078ea288c
commit b2bb48a260
2 changed files with 427 additions and 298 deletions

View File

@@ -1,242 +1,266 @@
<app-settings-card title="Queue Cleaner Configuration">
<form [formGroup]="queueCleanerForm" class="p-fluid">
<!-- Main Settings -->
<div class="field-row">
<label class="field-label">Enable Queue Cleaner</label>
<div class="field-input">
<p-checkbox formControlName="enabled" [binary]="true" inputId="qcEnabled"></p-checkbox>
<small class="form-helper-text">When enabled, the queue cleaner will run according to the schedule</small>
</div>
</div>
<div class="field-row" formGroupName="jobSchedule">
<label class="field-label">Run Schedule</label>
<div class="field-input schedule-input">
<span class="schedule-label">Every</span>
<p-inputNumber
formControlName="every"
[showButtons]="true"
[min]="1"
[max]="59"
buttonLayout="horizontal"
inputStyleClass="schedule-value">
</p-inputNumber>
<div class="settings-container">
<div class="flex align-items-center justify-content-between mb-4">
<h1>Queue Cleaner Settings</h1>
</div>
<div class="grid">
<div class="col-12">
<p-card styleClass="settings-card h-full">
<ng-template pTemplate="header">
<div class="flex align-items-center justify-content-between p-3 border-bottom-1 surface-border">
<div class="header-title-container">
<h2 class="card-title m-0">Queue Cleaner Configuration</h2>
<span class="card-subtitle">Configure automatic queue cleanup</span>
</div>
<div class="flex align-items-center gap-2">
<i class="pi pi-cog text-xl"></i>
</div>
</div>
</ng-template>
<p-selectButton
formControlName="type"
[options]="scheduleUnitOptions"
optionLabel="label"
optionValue="value">
</p-selectButton>
</div>
<small class="form-helper-text">How often the queue cleaner should run</small>
<div class="card-content">
<form [formGroup]="queueCleanerForm" class="p-fluid">
<!-- Main Settings -->
<div class="field-row">
<label class="field-label">Enable Queue Cleaner</label>
<div class="field-input">
<p-checkbox formControlName="enabled" [binary]="true" inputId="qcEnabled"></p-checkbox>
<small class="form-helper-text">When enabled, the queue cleaner will run according to the schedule</small>
</div>
</div>
<div class="field-row" formGroupName="jobSchedule">
<label class="field-label">Run Schedule</label>
<div class="field-input schedule-input">
<span class="schedule-label">Every</span>
<p-inputNumber
formControlName="every"
[showButtons]="true"
[min]="1"
[max]="59"
buttonLayout="horizontal"
inputStyleClass="schedule-value">
</p-inputNumber>
<p-selectButton
formControlName="type"
[options]="scheduleUnitOptions"
optionLabel="label"
optionValue="value">
</p-selectButton>
</div>
<small class="form-helper-text">How often the queue cleaner should run</small>
</div>
<div class="field-row">
<label class="field-label">Run Sequentially</label>
<div class="field-input">
<p-checkbox formControlName="runSequentially" [binary]="true" inputId="qcRunSequentially"></p-checkbox>
<small class="form-helper-text">When enabled, jobs will run one after another instead of in parallel</small>
</div>
</div>
<div class="field-row">
<label class="field-label">Ignored Downloads Path</label>
<div class="field-input">
<input pInputText formControlName="ignoredDownloadsPath" />
<small class="form-helper-text">Path to the file containing ignored downloads</small>
</div>
</div>
<!-- Detailed Settings in Accordion -->
<p-accordion [multiple]="true" styleClass="mt-3">
<!-- Failed Import Settings -->
<p-accordionTab header="Failed Import Settings" [disabled]="!queueCleanerForm.get('enabled')?.value">
<div class="field-row">
<label class="field-label">Max Strikes</label>
<div class="field-input">
<p-inputNumber
formControlName="failedImportMaxStrikes"
[showButtons]="true"
[min]="0"
[max]="10"
buttonLayout="horizontal">
</p-inputNumber>
<small class="form-helper-text">Number of strikes before action is taken (0 to disable, min 3 to enable)</small>
</div>
</div>
<div class="field-row">
<label class="field-label">Ignore Private</label>
<div class="field-input">
<p-checkbox formControlName="failedImportIgnorePrivate" [binary]="true"></p-checkbox>
<small class="form-helper-text">When enabled, private torrents will be ignored</small>
</div>
</div>
<div class="field-row">
<label class="field-label">Delete Private</label>
<div class="field-input">
<p-checkbox formControlName="failedImportDeletePrivate" [binary]="true"></p-checkbox>
<small class="form-helper-text">When enabled, private torrents will be deleted</small>
</div>
</div>
<div class="field-row">
<label class="field-label">Ignore Patterns</label>
<div class="field-input">
<p-chips formControlName="failedImportIgnorePatterns" placeholder="Add pattern and press Enter"></p-chips>
<small class="form-helper-text">Patterns to ignore (e.g., *sample*)</small>
</div>
</div>
</p-accordionTab>
<!-- Stalled Settings -->
<p-accordionTab header="Stalled Download Settings" [disabled]="!queueCleanerForm.get('enabled')?.value">
<div class="field-row">
<label class="field-label">Max Strikes</label>
<div class="field-input">
<p-inputNumber
formControlName="stalledMaxStrikes"
[showButtons]="true"
[min]="0"
[max]="10"
buttonLayout="horizontal">
</p-inputNumber>
<small class="form-helper-text">Number of strikes before action is taken (0 to disable, min 3 to enable)</small>
</div>
</div>
<div class="field-row">
<label class="field-label">Reset Strikes On Progress</label>
<div class="field-input">
<p-checkbox formControlName="stalledResetStrikesOnProgress" [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">
<label class="field-label">Ignore Private</label>
<div class="field-input">
<p-checkbox formControlName="stalledIgnorePrivate" [binary]="true"></p-checkbox>
<small class="form-helper-text">When enabled, private torrents will be ignored</small>
</div>
</div>
<div class="field-row">
<label class="field-label">Delete Private</label>
<div class="field-input">
<p-checkbox formControlName="stalledDeletePrivate" [binary]="true"></p-checkbox>
<small class="form-helper-text">When enabled, private torrents will be deleted</small>
</div>
</div>
</p-accordionTab>
<!-- 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-input">
<p-inputNumber
formControlName="downloadingMetadataMaxStrikes"
[showButtons]="true"
[min]="0"
[max]="10"
buttonLayout="horizontal">
</p-inputNumber>
<small class="form-helper-text">Number of strikes before action is taken (0 to disable, min 3 to enable)</small>
</div>
</div>
</p-accordionTab>
<!-- Slow Download Settings -->
<p-accordionTab header="Slow Download Settings" [disabled]="!queueCleanerForm.get('enabled')?.value">
<div class="field-row">
<label class="field-label">Max Strikes</label>
<div class="field-input">
<p-inputNumber
formControlName="slowMaxStrikes"
[showButtons]="true"
[min]="0"
[max]="10"
buttonLayout="horizontal">
</p-inputNumber>
<small class="form-helper-text">Number of strikes before action is taken (0 to disable, min 3 to enable)</small>
</div>
</div>
<div class="field-row">
<label class="field-label">Reset Strikes On Progress</label>
<div class="field-input">
<p-checkbox formControlName="slowResetStrikesOnProgress" [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">
<label class="field-label">Ignore Private</label>
<div class="field-input">
<p-checkbox formControlName="slowIgnorePrivate" [binary]="true"></p-checkbox>
<small class="form-helper-text">When enabled, private torrents will be ignored</small>
</div>
</div>
<div class="field-row">
<label class="field-label">Delete Private</label>
<div class="field-input">
<p-checkbox formControlName="slowDeletePrivate" [binary]="true"></p-checkbox>
<small class="form-helper-text">When enabled, private torrents will be deleted</small>
</div>
</div>
<div class="field-row">
<label class="field-label">Minimum Speed</label>
<div class="field-input">
<app-byte-size-input
formControlName="slowMinSpeed"
[min]="0"
placeholder="Enter minimum speed"
helpText="Minimum speed threshold for slow downloads (e.g., 100KB/s)">
</app-byte-size-input>
</div>
</div>
<div class="field-row">
<label class="field-label">Maximum Time (hours)</label>
<div class="field-input">
<p-inputNumber
formControlName="slowMaxTime"
[showButtons]="true"
[min]="0"
[max]="168"
buttonLayout="horizontal">
</p-inputNumber>
<small class="form-helper-text">Maximum time allowed for slow downloads (in hours)</small>
</div>
</div>
<div class="field-row">
<label class="field-label">Ignore Above Size</label>
<div class="field-input">
<app-byte-size-input
formControlName="slowIgnoreAboveSize"
[min]="0"
placeholder="Enter size threshold"
helpText="Size threshold above which slow downloads are ignored">
</app-byte-size-input>
</div>
</div>
</p-accordionTab>
</p-accordion>
<!-- Action buttons -->
<div class="card-footer mt-3">
<button pButton type="button" label="Save" icon="pi pi-save" class="p-button-success"
[disabled]="queueCleanerForm.pristine || queueCleanerSaving()"
[loading]="queueCleanerSaving()"
(click)="saveQueueCleanerConfig()"></button>
<button pButton type="button" label="Reset" icon="pi pi-refresh" class="p-button-secondary p-button-outlined ml-2"
(click)="resetQueueCleanerConfig()"></button>
</div>
</form>
</div>
</p-card>
</div>
<div class="field-row">
<label class="field-label">Run Sequentially</label>
<div class="field-input">
<p-checkbox formControlName="runSequentially" [binary]="true" inputId="qcRunSequentially"></p-checkbox>
<small class="form-helper-text">When enabled, jobs will run one after another instead of in parallel</small>
</div>
</div>
<div class="field-row">
<label class="field-label">Ignored Downloads Path</label>
<div class="field-input">
<input pInputText formControlName="ignoredDownloadsPath" />
<small class="form-helper-text">Path to the file containing ignored downloads</small>
</div>
</div>
<!-- Detailed Settings in Accordion -->
<p-accordion [multiple]="true" styleClass="mt-3">
<!-- Failed Import Settings -->
<p-accordionTab header="Failed Import Settings">
<div class="field-row">
<label class="field-label">Max Strikes</label>
<div class="field-input">
<p-inputNumber
formControlName="failedImportMaxStrikes"
[showButtons]="true"
[min]="0"
[max]="10"
buttonLayout="horizontal">
</p-inputNumber>
<small class="form-helper-text">Number of strikes before action is taken (0 to disable, min 3 to enable)</small>
</div>
</div>
<div class="field-row">
<label class="field-label">Ignore Private</label>
<div class="field-input">
<p-checkbox formControlName="failedImportIgnorePrivate" [binary]="true"></p-checkbox>
<small class="form-helper-text">When enabled, private torrents will be ignored</small>
</div>
</div>
<div class="field-row">
<label class="field-label">Delete Private</label>
<div class="field-input">
<p-checkbox formControlName="failedImportDeletePrivate" [binary]="true"></p-checkbox>
<small class="form-helper-text">When enabled, private torrents will be deleted</small>
</div>
</div>
<div class="field-row">
<label class="field-label">Ignore Patterns</label>
<div class="field-input">
<p-chips formControlName="failedImportIgnorePatterns" placeholder="Add pattern and press Enter"></p-chips>
<small class="form-helper-text">Patterns to ignore (e.g., *sample*)</small>
</div>
</div>
</p-accordionTab>
<!-- Stalled Settings -->
<p-accordionTab header="Stalled Download Settings">
<div class="field-row">
<label class="field-label">Max Strikes</label>
<div class="field-input">
<p-inputNumber
formControlName="stalledMaxStrikes"
[showButtons]="true"
[min]="0"
[max]="10"
buttonLayout="horizontal">
</p-inputNumber>
<small class="form-helper-text">Number of strikes before action is taken (0 to disable, min 3 to enable)</small>
</div>
</div>
<div class="field-row">
<label class="field-label">Reset Strikes On Progress</label>
<div class="field-input">
<p-checkbox formControlName="stalledResetStrikesOnProgress" [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">
<label class="field-label">Ignore Private</label>
<div class="field-input">
<p-checkbox formControlName="stalledIgnorePrivate" [binary]="true"></p-checkbox>
<small class="form-helper-text">When enabled, private torrents will be ignored</small>
</div>
</div>
<div class="field-row">
<label class="field-label">Delete Private</label>
<div class="field-input">
<p-checkbox formControlName="stalledDeletePrivate" [binary]="true"></p-checkbox>
<small class="form-helper-text">When enabled, private torrents will be deleted</small>
</div>
</div>
</p-accordionTab>
<!-- Downloading Metadata Settings -->
<p-accordionTab header="Downloading Metadata Settings">
<div class="field-row">
<label class="field-label">Max Strikes</label>
<div class="field-input">
<p-inputNumber
formControlName="downloadingMetadataMaxStrikes"
[showButtons]="true"
[min]="0"
[max]="10"
buttonLayout="horizontal">
</p-inputNumber>
<small class="form-helper-text">Number of strikes before action is taken (0 to disable, min 3 to enable)</small>
</div>
</div>
</p-accordionTab>
<!-- Slow Download Settings -->
<p-accordionTab header="Slow Download Settings">
<div class="field-row">
<label class="field-label">Max Strikes</label>
<div class="field-input">
<p-inputNumber
formControlName="slowMaxStrikes"
[showButtons]="true"
[min]="0"
[max]="10"
buttonLayout="horizontal">
</p-inputNumber>
<small class="form-helper-text">Number of strikes before action is taken (0 to disable, min 3 to enable)</small>
</div>
</div>
<div class="field-row">
<label class="field-label">Reset Strikes On Progress</label>
<div class="field-input">
<p-checkbox formControlName="slowResetStrikesOnProgress" [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">
<label class="field-label">Ignore Private</label>
<div class="field-input">
<p-checkbox formControlName="slowIgnorePrivate" [binary]="true"></p-checkbox>
<small class="form-helper-text">When enabled, private torrents will be ignored</small>
</div>
</div>
<div class="field-row">
<label class="field-label">Delete Private</label>
<div class="field-input">
<p-checkbox formControlName="slowDeletePrivate" [binary]="true"></p-checkbox>
<small class="form-helper-text">When enabled, private torrents will be deleted</small>
</div>
</div>
<div class="field-row">
<label class="field-label">Minimum Speed</label>
<div class="field-input">
<app-byte-size-input
formControlName="slowMinSpeed"
[min]="0"
placeholder="Enter minimum speed"
helpText="Minimum speed threshold for slow downloads (e.g., 100KB/s)">
</app-byte-size-input>
</div>
</div>
<div class="field-row">
<label class="field-label">Maximum Time (hours)</label>
<div class="field-input">
<p-inputNumber
formControlName="slowMaxTime"
[showButtons]="true"
[min]="0"
[max]="168"
buttonLayout="horizontal">
</p-inputNumber>
<small class="form-helper-text">Maximum time allowed for slow downloads (in hours)</small>
</div>
</div>
<div class="field-row">
<label class="field-label">Ignore Above Size</label>
<div class="field-input">
<app-byte-size-input
formControlName="slowIgnoreAboveSize"
[min]="0"
placeholder="Enter size threshold"
helpText="Size threshold above which slow downloads are ignored">
</app-byte-size-input>
</div>
</div>
</p-accordionTab>
</p-accordion>
<!-- Put action buttons in the card footer using content projection -->
<div actions>
<button pButton type="button" label="Save" icon="pi pi-save" class="p-button-success"
[disabled]="queueCleanerForm.pristine || queueCleanerSaving()"
[loading]="queueCleanerSaving()"
(click)="saveQueueCleanerConfig()"></button>
<button pButton type="button" label="Reset" icon="pi pi-refresh" class="p-button-secondary p-button-outlined ml-2"
(click)="resetQueueCleanerConfig()"></button>
</div>
</form>
</app-settings-card>
</div>
</div>

View File

@@ -1,71 +1,176 @@
/* Queue Cleaner Settings Styles */
/* Form layout and structure */
.field-row {
display: flex;
margin-bottom: 1.25rem;
align-items: flex-start;
.settings-container {
padding: 1.5rem;
&:last-child {
margin-bottom: 0;
}
}
.field-label {
flex: 0 0 200px;
padding-top: 0.5rem;
font-weight: 500;
}
.field-input {
flex: 1;
max-width: 600px;
}
.form-helper-text {
display: block;
margin-top: 0.25rem;
color: #666;
font-size: 0.85rem;
}
/* Schedule input specific styles */
.schedule-input {
display: flex;
align-items: center;
gap: 0.5rem;
.schedule-label {
font-weight: 500;
margin-right: 0.5rem;
h1 {
font-size: 1.5rem;
font-weight: 600;
color: var(--text-color);
margin-bottom: 0.5rem;
}
.schedule-value {
width: 70px;
text-align: center;
}
::ng-deep .p-selectbutton {
.p-button {
padding: 0.5rem 0.75rem;
/* Card styles matching dashboard */
::ng-deep {
.settings-card {
height: 100%;
transition: transform 0.3s, box-shadow 0.3s;
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06);
border: 1px solid var(--surface-border);
&:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}
.p-card-header {
padding: 0;
}
.card-title {
font-size: 1.25rem;
font-weight: 600;
margin-bottom: 0.25rem;
}
.card-subtitle {
color: var(--text-color-secondary);
font-size: 0.875rem;
}
.p-card-body {
height: 100%;
display: flex;
flex-direction: column;
padding: 0;
}
.p-card-content {
flex-grow: 1;
padding: 1.5rem;
height: 100%;
}
/* Accordion disabled state */
.p-accordion {
.p-accordion-tab.p-disabled {
opacity: 0.6;
.p-accordion-header .p-accordion-header-link {
cursor: not-allowed;
color: var(--text-color-secondary);
}
}
}
}
}
/* Form layout and structure */
.field-row {
display: flex;
margin-bottom: 1.25rem;
align-items: flex-start;
&:last-child {
margin-bottom: 0;
}
}
.field-label {
flex: 0 0 200px;
padding-top: 0.5rem;
font-weight: 500;
}
.field-input {
flex: 1;
max-width: 600px;
}
.form-helper-text {
display: block;
margin-top: 0.25rem;
color: var(--text-color-secondary);
font-size: 0.85rem;
}
/* Schedule input specific styles */
.schedule-input {
display: flex;
align-items: center;
gap: 0.5rem;
.schedule-label {
font-weight: 500;
margin-right: 0.5rem;
}
.schedule-value {
width: 70px;
text-align: center;
}
::ng-deep .p-selectbutton {
.p-button {
padding: 0.5rem 0.75rem;
}
}
}
/* Card footer styling */
.card-footer {
border-top: 1px solid var(--surface-border);
padding-top: 1rem;
display: flex;
gap: 0.5rem;
.p-button {
flex: 1;
&:last-child {
flex: 0 0 auto;
}
}
}
}
/* Header title container and status tag styles */
.header-title-container {
display: flex;
flex-direction: column;
h2 {
margin: 0;
line-height: 1.2;
}
.card-subtitle {
margin-top: 0.25rem;
}
}
/* Responsive adjustments */
@media (max-width: 768px) {
.field-row {
flex-direction: column;
}
.field-label {
flex: 0 0 auto;
margin-bottom: 0.5rem;
padding-top: 0;
}
.field-input {
width: 100%;
max-width: 100%;
.settings-container {
padding: 1rem;
.field-row {
flex-direction: column;
}
.field-label {
flex: 0 0 auto;
margin-bottom: 0.5rem;
padding-top: 0;
}
.field-input {
width: 100%;
max-width: 100%;
}
.card-footer {
flex-direction: column;
}
}
}