mirror of
https://github.com/Cleanuparr/Cleanuparr.git
synced 2026-04-02 05:21:16 -04:00
Add hide unmonitored toggle for quality scores (#535)
This commit is contained in:
@@ -77,6 +77,24 @@ public class CustomFormatScoreControllerTests : IDisposable
|
||||
body.GetProperty("Items")[0].GetProperty("Title").GetString().ShouldBe("Below Cutoff");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetCustomFormatScores_WithHideUnmonitoredTrue_ExcludesUnmonitoredItems()
|
||||
{
|
||||
var radarr = SeekerTestDataFactory.AddRadarrInstance(_dataContext);
|
||||
AddScoreEntry(radarr.Id, 1, "Monitored Movie", currentScore: 100, cutoffScore: 500, isMonitored: true);
|
||||
AddScoreEntry(radarr.Id, 2, "Unmonitored Movie", currentScore: 200, cutoffScore: 500, isMonitored: false);
|
||||
AddScoreEntry(radarr.Id, 3, "Another Monitored", currentScore: 300, cutoffScore: 500, isMonitored: true);
|
||||
|
||||
var result = await _controller.GetCustomFormatScores(hideUnmonitored: true);
|
||||
var body = GetResponseBody(result);
|
||||
|
||||
body.GetProperty("TotalCount").GetInt32().ShouldBe(2);
|
||||
var items = body.GetProperty("Items");
|
||||
items.GetArrayLength().ShouldBe(2);
|
||||
items[0].GetProperty("Title").GetString().ShouldBe("Another Monitored");
|
||||
items[1].GetProperty("Title").GetString().ShouldBe("Monitored Movie");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetCustomFormatScores_WithSearchFilter_ReturnsMatchingTitlesOnly()
|
||||
{
|
||||
@@ -314,7 +332,8 @@ public class CustomFormatScoreControllerTests : IDisposable
|
||||
int currentScore,
|
||||
int cutoffScore,
|
||||
InstanceType itemType = InstanceType.Radarr,
|
||||
DateTime? lastSynced = null)
|
||||
DateTime? lastSynced = null,
|
||||
bool isMonitored = true)
|
||||
{
|
||||
_dataContext.CustomFormatScoreEntries.Add(new CustomFormatScoreEntry
|
||||
{
|
||||
@@ -327,6 +346,7 @@ public class CustomFormatScoreControllerTests : IDisposable
|
||||
CurrentScore = currentScore,
|
||||
CutoffScore = cutoffScore,
|
||||
QualityProfileName = "HD",
|
||||
IsMonitored = isMonitored,
|
||||
LastSyncedAt = lastSynced ?? DateTime.UtcNow
|
||||
});
|
||||
_dataContext.SaveChanges();
|
||||
|
||||
@@ -28,7 +28,8 @@ public sealed class CustomFormatScoreController : ControllerBase
|
||||
[FromQuery] Guid? instanceId = null,
|
||||
[FromQuery] string? search = null,
|
||||
[FromQuery] string sortBy = "title",
|
||||
[FromQuery] bool hideMet = false)
|
||||
[FromQuery] bool hideMet = false,
|
||||
[FromQuery] bool hideUnmonitored = false)
|
||||
{
|
||||
if (page < 1) page = 1;
|
||||
if (pageSize < 1) pageSize = 50;
|
||||
@@ -53,6 +54,11 @@ public sealed class CustomFormatScoreController : ControllerBase
|
||||
query = query.Where(e => e.CurrentScore < e.CutoffScore);
|
||||
}
|
||||
|
||||
if (hideUnmonitored)
|
||||
{
|
||||
query = query.Where(e => e.IsMonitored);
|
||||
}
|
||||
|
||||
int totalCount = await query.CountAsync();
|
||||
|
||||
var items = await (sortBy == "date"
|
||||
|
||||
@@ -99,12 +99,13 @@ export class CfScoreApi {
|
||||
return this.http.get<CfScoreUpgradesResponse>('/api/seeker/cf-scores/upgrades', { params });
|
||||
}
|
||||
|
||||
getScores(page = 1, pageSize = 50, search?: string, instanceId?: string, sortBy?: string, hideMet?: boolean): Observable<CfScoreEntriesResponse> {
|
||||
getScores(page = 1, pageSize = 50, search?: string, instanceId?: string, sortBy?: string, hideMet?: boolean, hideUnmonitored?: boolean): Observable<CfScoreEntriesResponse> {
|
||||
const params: Record<string, string | number | boolean> = { page, pageSize };
|
||||
if (search) params['search'] = search;
|
||||
if (instanceId) params['instanceId'] = instanceId;
|
||||
if (sortBy) params['sortBy'] = sortBy;
|
||||
if (hideMet) params['hideMet'] = true;
|
||||
if (hideUnmonitored) params['hideUnmonitored'] = true;
|
||||
return this.http.get<CfScoreEntriesResponse>('/api/seeker/cf-scores', { params });
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,11 @@
|
||||
[checked]="hideMet()"
|
||||
(checkedChange)="onHideMetChange($event)"
|
||||
/>
|
||||
<app-toggle
|
||||
label="Hide unmonitored"
|
||||
[checked]="hideUnmonitored()"
|
||||
(checkedChange)="onHideUnmonitoredChange($event)"
|
||||
/>
|
||||
</div>
|
||||
<div class="toolbar__actions">
|
||||
<app-button variant="ghost" size="sm" (clicked)="refresh()">
|
||||
|
||||
@@ -54,6 +54,7 @@ export class QualityTabComponent implements OnInit {
|
||||
|
||||
readonly sortBy = signal<string>('title');
|
||||
readonly hideMet = signal(false);
|
||||
readonly hideUnmonitored = signal(false);
|
||||
readonly sortOptions: SelectOption[] = [
|
||||
{ label: 'Title', value: 'title' },
|
||||
{ label: 'Last Synced', value: 'date' },
|
||||
@@ -93,7 +94,7 @@ export class QualityTabComponent implements OnInit {
|
||||
|
||||
loadScores(): void {
|
||||
this.loading.set(true);
|
||||
this.api.getScores(this.currentPage(), this.pageSize(), this.searchQuery() || undefined, this.selectedInstanceId() || undefined, this.sortBy(), this.hideMet()).subscribe({
|
||||
this.api.getScores(this.currentPage(), this.pageSize(), this.searchQuery() || undefined, this.selectedInstanceId() || undefined, this.sortBy(), this.hideMet(), this.hideUnmonitored()).subscribe({
|
||||
next: (result) => {
|
||||
this.items.set(result.items);
|
||||
this.totalRecords.set(result.totalCount);
|
||||
@@ -122,9 +123,7 @@ export class QualityTabComponent implements OnInit {
|
||||
}
|
||||
|
||||
onInstanceFilterChange(value: string): void {
|
||||
this.selectedInstanceId.set(value);
|
||||
this.currentPage.set(1);
|
||||
this.loadScores();
|
||||
this.applyFilterChange(this.selectedInstanceId, value);
|
||||
}
|
||||
|
||||
private loadStats(): void {
|
||||
@@ -140,13 +139,19 @@ export class QualityTabComponent implements OnInit {
|
||||
}
|
||||
|
||||
onSortChange(value: string): void {
|
||||
this.sortBy.set(value);
|
||||
this.currentPage.set(1);
|
||||
this.loadScores();
|
||||
this.applyFilterChange(this.sortBy, value);
|
||||
}
|
||||
|
||||
onHideMetChange(value: boolean): void {
|
||||
this.hideMet.set(value);
|
||||
this.applyFilterChange(this.hideMet, value);
|
||||
}
|
||||
|
||||
onHideUnmonitoredChange(value: boolean): void {
|
||||
this.applyFilterChange(this.hideUnmonitored, value);
|
||||
}
|
||||
|
||||
private applyFilterChange<T>(setter: { set: (v: T) => void }, value: T): void {
|
||||
setter.set(value);
|
||||
this.currentPage.set(1);
|
||||
this.loadScores();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user