-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
15 changed files
with
549 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base | ||
WORKDIR /app | ||
EXPOSE 80 | ||
|
||
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build | ||
WORKDIR /src/rpc | ||
COPY ./rpc ./ | ||
WORKDIR /src/common | ||
COPY ./common ./ | ||
WORKDIR /src/stats | ||
COPY ./stats/TimeKeep.Stats.csproj . | ||
RUN dotnet restore | ||
COPY ./stats . | ||
RUN dotnet build -c Release -o /app/build | ||
|
||
FROM build AS publish | ||
RUN dotnet publish -c Release -o /app/publish /p:UseAppHost=false | ||
|
||
FROM base AS final | ||
WORKDIR /app | ||
COPY ./stats/appsettings.json . | ||
COPY --from=publish /app/publish . | ||
ENTRYPOINT dotnet TimeKeep.Stats.dll |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
namespace TimeKeep.Stats.Options; | ||
|
||
public class TimeKeepOptions | ||
{ | ||
public required string Server { init; get; } | ||
public required string Token { init; get; } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
@model (int, Dictionary<DateOnly, Week>) | ||
@using System.Globalization | ||
@using Humanizer | ||
@using Humanizer.Localisation | ||
@using TimeKeep.Stats.Services | ||
|
||
@{ | ||
var (hue, weeks) = Model; | ||
if (weeks.Count is 0) | ||
{ | ||
return; | ||
} | ||
var maxTimeSpent = weeks.Max(p => p.Value.Max); | ||
} | ||
|
||
<table style="--table-color: hsl(@hue 64% 59%)"> | ||
<thead> | ||
<tr> | ||
<th></th> | ||
@{ | ||
int? prevMonth = null; | ||
} | ||
@foreach (var (date, _) in weeks) | ||
{ | ||
var weekEndDate = date.AddDays(6); | ||
var month = weekEndDate.Month; | ||
if (month != prevMonth) | ||
{ | ||
<th> | ||
@if (month == 1 || prevMonth is null) | ||
{ | ||
@(weekEndDate.ToString("yyyy")) | ||
} | ||
@(weekEndDate.ToString("MMM")) | ||
</th> | ||
} | ||
else | ||
{ | ||
<th></th> | ||
} | ||
|
||
prevMonth = month; | ||
} | ||
</tr> | ||
</thead> | ||
<tbody> | ||
<tr> | ||
<th>Mon</th> | ||
@foreach (var (_, week) in weeks) | ||
{ | ||
<td style="--time-spent: @((week.Monday / maxTimeSpent).ToString("0.00000", NumberFormatInfo.InvariantInfo))" title="@(week.Monday.Humanize(precision: 2, minUnit: TimeUnit.Minute))"></td> | ||
} | ||
</tr> | ||
<tr> | ||
<th>Tue</th> | ||
@foreach (var (_, week) in weeks) | ||
{ | ||
<td style="--time-spent: @((week.Tuesday / maxTimeSpent).ToString("0.00000", NumberFormatInfo.InvariantInfo))" title="@(week.Tuesday.Humanize(precision: 2, minUnit: TimeUnit.Minute))"></td> | ||
} | ||
</tr> | ||
<tr> | ||
<th>Wed</th> | ||
@foreach (var (_, week) in weeks) | ||
{ | ||
<td style="--time-spent: @((week.Wednesday / maxTimeSpent).ToString("0.00000", NumberFormatInfo.InvariantInfo))" title="@(week.Wednesday.Humanize(precision: 2, minUnit: TimeUnit.Minute))"></td> | ||
} | ||
</tr> | ||
<tr> | ||
<th>Thu</th> | ||
@foreach (var (_, week) in weeks) | ||
{ | ||
<td style="--time-spent: @((week.Thursday / maxTimeSpent).ToString("0.00000", NumberFormatInfo.InvariantInfo))" title="@(week.Thursday.Humanize(precision: 2, minUnit: TimeUnit.Minute))"></td> | ||
} | ||
</tr> | ||
<tr> | ||
<th>Fri</th> | ||
@foreach (var (_, week) in weeks) | ||
{ | ||
<td style="--time-spent: @((week.Friday / maxTimeSpent).ToString("0.00000", NumberFormatInfo.InvariantInfo))" title="@(week.Friday.Humanize(precision: 2, minUnit: TimeUnit.Minute))"></td> | ||
} | ||
</tr> | ||
<tr> | ||
<th>Sun</th> | ||
@foreach (var (_, week) in weeks) | ||
{ | ||
<td style="--time-spent: @((week.Saturday / maxTimeSpent).ToString("0.00000", NumberFormatInfo.InvariantInfo))" title="@(week.Saturday.Humanize(precision: 2, minUnit: TimeUnit.Minute))"></td> | ||
} | ||
</tr> | ||
<tr> | ||
<th>Sat</th> | ||
@foreach (var (_, week) in weeks) | ||
{ | ||
<td style="--time-spent: @((week.Sunday / maxTimeSpent).ToString("0.00000", NumberFormatInfo.InvariantInfo))" title="@(week.Sunday.Humanize(precision: 2, minUnit: TimeUnit.Minute))"></td> | ||
} | ||
</tr> | ||
</tbody> | ||
</table> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
@page "/weeks" | ||
@namespace TimeKeep.Stats.Pages | ||
@using Grpc.Core | ||
@using TimeKeep.RPC.Categories | ||
@inject CategoriesService.CategoriesServiceClient categoriesClient | ||
|
||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
<title>Weeks</title> | ||
<link href="./style.css" rel="stylesheet"> | ||
</head> | ||
<body> | ||
@if (Request.Query.TryGetValue("categories", out var categories)) | ||
{ | ||
@await Component.InvokeAsync("WeekView", new { categories = categories.ToArray(), cancellationToken = HttpContext.RequestAborted }) | ||
} | ||
<br /> | ||
<form> | ||
<input name="categories" type="search" list="validCategories" required placeholder="Categories" value="@(categories)"> | ||
<datalist id="validCategories"> | ||
@{ | ||
var response = categoriesClient.List(new(), cancellationToken: HttpContext.RequestAborted); | ||
var validCategories = await response.ResponseStream.ReadAllAsync().ToArrayAsync(); | ||
} | ||
@foreach (var category in validCategories) | ||
{ | ||
<option value="@(category.Name)"></option> | ||
} | ||
</datalist> | ||
<input type="submit" value="Show"> | ||
</form> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
using System; | ||
using Microsoft.AspNetCore.Builder; | ||
using Microsoft.Extensions.Configuration; | ||
using Microsoft.Extensions.DependencyInjection; | ||
using TimeKeep.Stats; | ||
using TimeKeep.Stats.Options; | ||
using TimeKeep.Stats.Services; | ||
|
||
var builder = WebApplication.CreateBuilder(args); | ||
|
||
var timeKeepOptions = | ||
builder.Configuration.GetSection("TimeKeep").Get<TimeKeepOptions>() | ||
?? throw new Exception("Missing \"TimeKeep\" options."); | ||
|
||
builder.Services.AddRpcClients(timeKeepOptions); | ||
|
||
builder.Services.AddTransient<WeekService>(); | ||
|
||
builder.Services.AddRazorPages(); | ||
|
||
var app = builder.Build(); | ||
|
||
app.UseStaticFiles(); | ||
app.UseRouting(); | ||
app.MapRazorPages(); | ||
|
||
app.Run(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
{ | ||
"$schema": "http://json.schemastore.org/launchsettings.json", | ||
"iisSettings": { | ||
"windowsAuthentication": false, | ||
"anonymousAuthentication": true, | ||
"iisExpress": { | ||
"applicationUrl": "http://localhost:11608", | ||
"sslPort": 0 | ||
} | ||
}, | ||
"profiles": { | ||
"http": { | ||
"commandName": "Project", | ||
"dotnetRunMessages": true, | ||
"launchBrowser": true, | ||
"applicationUrl": "http://localhost:5143", | ||
"environmentVariables": { | ||
"ASPNETCORE_ENVIRONMENT": "Development" | ||
} | ||
}, | ||
"IIS Express": { | ||
"commandName": "IISExpress", | ||
"launchBrowser": true, | ||
"environmentVariables": { | ||
"ASPNETCORE_ENVIRONMENT": "Development" | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
using System; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
using Grpc.Core; | ||
using Microsoft.Extensions.DependencyInjection; | ||
using TimeKeep.RPC.Categories; | ||
using TimeKeep.RPC.Entries; | ||
using TimeKeep.Stats.Options; | ||
|
||
namespace TimeKeep.Stats; | ||
|
||
public static class RpcServiceCollectionExtensions | ||
{ | ||
public static IServiceCollection AddRpcClients( | ||
this IServiceCollection services, | ||
TimeKeepOptions options | ||
) | ||
{ | ||
var base64Token = GetBase64Token(options.Token); | ||
var callCredentials = CallCredentials.FromInterceptor( | ||
(_, metadata) => | ||
{ | ||
metadata.Add("Authorization", $"Bearer {base64Token}"); | ||
return Task.CompletedTask; | ||
} | ||
); | ||
services | ||
.AddGrpcClient<EntriesService.EntriesServiceClient>( | ||
(sp, o) => o.Address = new(options.Server) | ||
) | ||
.AddCallCredentials(callCredentials); | ||
services | ||
.AddGrpcClient<CategoriesService.CategoriesServiceClient>( | ||
(sp, o) => o.Address = new(options.Server) | ||
) | ||
.AddCallCredentials(callCredentials); | ||
return services; | ||
} | ||
|
||
private static string GetBase64Token(string token) | ||
{ | ||
var utf8ValidatingEncoding = new UTF8Encoding(false, true); | ||
var tokenBytes = utf8ValidatingEncoding.GetBytes(token); | ||
return Convert.ToBase64String(tokenBytes); | ||
} | ||
} |
Oops, something went wrong.