feat(anomalies): sort the feed (newest / top score / longest gap)

Adds a sort chip row to the anomaly feed — newest (default), highest score, or
longest suspension gap — replacing the fixed newest-first order. DetectedAt is the
tiebreak so order stays stable.

- AnomalySort enum + AnomalyFilter.Sort (default Newest, so existing constructions
  are unaffected); AnomalyBrowsingService applies it; feed sort chips +
  SetSort/SortLabel; en/ru resx.
- 2 tests: default newest-first + highest-score ordering.
This commit is contained in:
2026-05-29 11:55:46 +03:00
parent 67f2ae130c
commit 36178e6d1b
6 changed files with 93 additions and 7 deletions
@@ -64,9 +64,17 @@ public sealed class AnomalyBrowsingService : IAnomalyBrowsingService
filtered = filtered.Where(i => kinds.Contains(i.Kind));
}
return filtered
.OrderByDescending(static i => i.DetectedAt)
.ToList();
// DetectedAt is the tiebreak for the score/gap sorts so order stays stable.
var sorted = filter.Sort switch
{
AnomalySort.HighestScore =>
filtered.OrderByDescending(i => i.Score).ThenByDescending(i => i.DetectedAt),
AnomalySort.LongestGap =>
filtered.OrderByDescending(i => i.SuspensionGapSeconds).ThenByDescending(i => i.DetectedAt),
_ => filtered.OrderByDescending(i => i.DetectedAt),
};
return sorted.ToList();
}
public async Task<AnomalyDetailVm?> GetByIdAsync(Guid id, CancellationToken ct)