Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| cfcf45cdf3 |
@@ -24,9 +24,6 @@ public class AnalyticsController : ApiControllerBase
|
|||||||
public async Task<IActionResult> Volume([FromQuery] int days = 90, CancellationToken ct = default)
|
public async Task<IActionResult> Volume([FromQuery] int days = 90, CancellationToken ct = default)
|
||||||
=> Ok(await _analytics.GetVolumeOverTimeAsync(UserId, Math.Clamp(days, 1, 3660), ct));
|
=> Ok(await _analytics.GetVolumeOverTimeAsync(UserId, Math.Clamp(days, 1, 3660), ct));
|
||||||
|
|
||||||
[HttpGet("heatmap")]
|
|
||||||
public async Task<IActionResult> Heatmap(CancellationToken ct) => Ok(await _analytics.GetHeatmapAsync(UserId, ct));
|
|
||||||
|
|
||||||
[HttpGet("category-heatmap")]
|
[HttpGet("category-heatmap")]
|
||||||
public async Task<IActionResult> CategoryHeatmap(CancellationToken ct) => Ok(await _analytics.GetCategoryHeatmapAsync(UserId, ct));
|
public async Task<IActionResult> CategoryHeatmap(CancellationToken ct) => Ok(await _analytics.GetCategoryHeatmapAsync(UserId, ct));
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ public interface IAnalyticsService
|
|||||||
Task<InboxHealthDto> GetInboxHealthAsync(Guid userId, CancellationToken ct = default);
|
Task<InboxHealthDto> GetInboxHealthAsync(Guid userId, CancellationToken ct = default);
|
||||||
Task<IReadOnlyList<SenderStatDto>> GetTopSendersAsync(Guid userId, int take = 20, CancellationToken ct = default);
|
Task<IReadOnlyList<SenderStatDto>> GetTopSendersAsync(Guid userId, int take = 20, CancellationToken ct = default);
|
||||||
Task<IReadOnlyList<TimeSeriesPointDto>> GetVolumeOverTimeAsync(Guid userId, int days = 90, CancellationToken ct = default);
|
Task<IReadOnlyList<TimeSeriesPointDto>> GetVolumeOverTimeAsync(Guid userId, int days = 90, CancellationToken ct = default);
|
||||||
Task<IReadOnlyList<HeatmapCellDto>> GetHeatmapAsync(Guid userId, CancellationToken ct = default);
|
|
||||||
Task<IReadOnlyList<CategoryHeatmapCellDto>> GetCategoryHeatmapAsync(Guid userId, CancellationToken ct = default);
|
Task<IReadOnlyList<CategoryHeatmapCellDto>> GetCategoryHeatmapAsync(Guid userId, CancellationToken ct = default);
|
||||||
Task<IReadOnlyList<AttachmentBreakdownDto>> GetAttachmentBreakdownAsync(Guid userId, CancellationToken ct = default);
|
Task<IReadOnlyList<AttachmentBreakdownDto>> GetAttachmentBreakdownAsync(Guid userId, CancellationToken ct = default);
|
||||||
Task<SidebarCountsDto> GetSidebarCountsAsync(Guid userId, CancellationToken ct = default);
|
Task<SidebarCountsDto> GetSidebarCountsAsync(Guid userId, CancellationToken ct = default);
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ public record InboxHealthDto(
|
|||||||
|
|
||||||
public record TimeSeriesPointDto(DateOnly Day, int Count);
|
public record TimeSeriesPointDto(DateOnly Day, int Count);
|
||||||
|
|
||||||
public record HeatmapCellDto(int DayOfWeek, int Hour, int Count);
|
|
||||||
|
|
||||||
/// <summary>Email counts per category per day-of-week, for the category heatmap.</summary>
|
/// <summary>Email counts per category per day-of-week, for the category heatmap.</summary>
|
||||||
public record CategoryHeatmapCellDto(string Category, int DayOfWeek, int Count);
|
public record CategoryHeatmapCellDto(string Category, int DayOfWeek, int Count);
|
||||||
@@ -39,6 +38,5 @@ public record DashboardSummaryDto(
|
|||||||
int UnreadEmails,
|
int UnreadEmails,
|
||||||
IReadOnlyList<SenderStatDto> TopSenders,
|
IReadOnlyList<SenderStatDto> TopSenders,
|
||||||
IReadOnlyList<TimeSeriesPointDto> VolumeOverTime,
|
IReadOnlyList<TimeSeriesPointDto> VolumeOverTime,
|
||||||
IReadOnlyList<HeatmapCellDto> Heatmap,
|
|
||||||
IReadOnlyList<AttachmentBreakdownDto> AttachmentBreakdown,
|
IReadOnlyList<AttachmentBreakdownDto> AttachmentBreakdown,
|
||||||
long StorageEstimateBytes);
|
long StorageEstimateBytes);
|
||||||
|
|||||||
@@ -16,11 +16,10 @@ public class AnalyticsService : IAnalyticsService
|
|||||||
var health = await GetInboxHealthAsync(userId, ct);
|
var health = await GetInboxHealthAsync(userId, ct);
|
||||||
var top = await GetTopSendersAsync(userId, 10, ct);
|
var top = await GetTopSendersAsync(userId, 10, ct);
|
||||||
var volume = await GetVolumeOverTimeAsync(userId, 90, ct);
|
var volume = await GetVolumeOverTimeAsync(userId, 90, ct);
|
||||||
var heatmap = await GetHeatmapAsync(userId, ct);
|
|
||||||
var attachments = await GetAttachmentBreakdownAsync(userId, ct);
|
var attachments = await GetAttachmentBreakdownAsync(userId, ct);
|
||||||
|
|
||||||
return new DashboardSummaryDto(
|
return new DashboardSummaryDto(
|
||||||
health, health.TotalEmails, health.UnreadEmails, top, volume, heatmap, attachments,
|
health, health.TotalEmails, health.UnreadEmails, top, volume, attachments,
|
||||||
health.EstimatedStorageBytes);
|
health.EstimatedStorageBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,19 +74,6 @@ public class AnalyticsService : IAnalyticsService
|
|||||||
.ToList();
|
.ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<IReadOnlyList<HeatmapCellDto>> GetHeatmapAsync(Guid userId, CancellationToken ct = default)
|
|
||||||
{
|
|
||||||
var raw = await _db.Emails
|
|
||||||
.Where(e => e.UserId == userId)
|
|
||||||
.Select(e => new { e.SentAtUtc })
|
|
||||||
.ToListAsync(ct);
|
|
||||||
|
|
||||||
return raw
|
|
||||||
.GroupBy(x => new { Dow = (int)x.SentAtUtc.DayOfWeek, Hour = x.SentAtUtc.Hour })
|
|
||||||
.Select(g => new HeatmapCellDto(g.Key.Dow, g.Key.Hour, g.Count()))
|
|
||||||
.ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<IReadOnlyList<CategoryHeatmapCellDto>> GetCategoryHeatmapAsync(Guid userId, CancellationToken ct = default)
|
public async Task<IReadOnlyList<CategoryHeatmapCellDto>> GetCategoryHeatmapAsync(Guid userId, CancellationToken ct = default)
|
||||||
{
|
{
|
||||||
var raw = await _db.Emails
|
var raw = await _db.Emails
|
||||||
|
|||||||
Reference in New Issue
Block a user