Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ charset = utf-8-bom
end_of_line = crlf
insert_final_newline = true

[*.{yml,json,csproj,props}]
indent_size = 2
indent_style = space
tab_width = 2

# Файлы C#

[*.{cs,razor,chtml,razor.cs,chtml.cs}]
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ jobs:
dotnet-quality: 'ga'

- name: Install EF CLI
run: dotnet tool install --global dotnet-ef
run: dotnet tool install --global dotnet-ef --version 8.*

- name: Restore backend dependencies
run: dotnet restore
Expand Down
2 changes: 1 addition & 1 deletion backend/Money.Api.Tests/Integration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Money.Api.BackgroundServices;
using Money.Data;
using System.Collections.Concurrent;

Expand All @@ -28,6 +27,7 @@ ApplicationDbContext CreateDbContext()
DbContextOptionsBuilder<ApplicationDbContext> optionsBuilder = new();
optionsBuilder.UseNpgsql(connectionString);
optionsBuilder.UseSnakeCaseNamingConvention();
optionsBuilder.EnableSensitiveDataLogging();
var context = new ApplicationDbContext(optionsBuilder.Options);
return context;
}
Expand Down
2 changes: 1 addition & 1 deletion backend/Money.Api.Tests/nlog.config
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@
<target name="custom" xsi:type="Console" />
</targets>
<rules>
<logger name="Money.Api.Middlewares.ExceptionMiddleware" minlevel="Warn" writeTo="custom" />
<logger name="Money.Api.Middlewares.ExceptionHandler" minlevel="Warn" writeTo="custom" />
</rules>
</nlog>
2 changes: 1 addition & 1 deletion backend/Money.Business/Services/DebtsService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ public async Task ForgiveAsync(int[] debtIds, int operationCategoryId, string? o
{
var entities = await context.Debts
.IsUserEntity(environment.UserId)
.Where(x => debtIds.Contains(x.Id) && x.StatusId == (int)DebtStatus.Actual)
.Where(x => debtIds.AsEnumerable().Contains(x.Id) && x.StatusId == (int)DebtStatus.Actual)
.ToListAsync(cancellationToken);

if (entities.Count == 0)
Expand Down
3 changes: 1 addition & 2 deletions frontend/Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="Blazored.LocalStorage" Version="4.5.0" />
<PackageVersion Include="ChartJs.Blazor.Fork" Version="2.0.2" />
<PackageVersion Include="CSharpFunctionalExtensions" Version="3.6.0" />
<PackageVersion Include="CSharpFunctionalExtensions.Analyzers" Version="1.4.1" />
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly" Version="9.0.10" />
Expand All @@ -19,4 +18,4 @@
<PackageVersion Include="NCalc.DependencyInjection" Version="5.8.0" />
<PackageVersion Include="SonarAnalyzer.CSharp" Version="10.4.0.108396" />
</ItemGroup>
</Project>
</Project>
34 changes: 17 additions & 17 deletions frontend/Money.Web/Common/AppSettings.cs
Original file line number Diff line number Diff line change
@@ -1,44 +1,44 @@
namespace Money.Web.Common;

public class AppSettings
public sealed class AppSettings
{
private bool _showDividers;
private bool _isDarkMode;
private bool _isDarkModeSystem;
private bool _isManualMode;
private bool _isSchedule;

public event EventHandler? OnChange;

public bool ShowDividers
{
get => _showDividers;
set => SetValue(ref _showDividers, value);
get;
set => SetValue(ref field, value);
}

public bool UseChartThemeColors
{
get;
set => SetValue(ref field, value);
} = true;

// TODO: Переделать на состояния
public bool IsDarkMode
{
get => _isDarkMode;
set => SetValue(ref _isDarkMode, value);
get;
set => SetValue(ref field, value);
}

public bool IsDarkModeSystem
{
get => _isDarkModeSystem;
set => SetValue(ref _isDarkModeSystem, value);
get;
set => SetValue(ref field, value);
}

public bool IsManualMode
{
get => _isManualMode;
set => SetValue(ref _isManualMode, value);
get;
set => SetValue(ref field, value);
}

public bool IsSchedule
{
get => _isSchedule;
set => SetValue(ref _isSchedule, value);
get;
set => SetValue(ref field, value);
}

private void SetValue(ref bool field, bool value)
Expand Down
31 changes: 31 additions & 0 deletions frontend/Money.Web/Common/ChartColors.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
namespace Money.Web.Common;

public static class ChartColors
{
public static readonly List<string> All =
[
Colors.Blue.Default,
Colors.Red.Default,
Colors.Green.Default,
Colors.Amber.Default,
Colors.Purple.Default,
Colors.Cyan.Default,
Colors.Teal.Default,
Colors.DeepOrange.Default,
Colors.Pink.Default,
Colors.Indigo.Default,
Colors.LightBlue.Default,
Colors.Lime.Default,
Colors.Yellow.Default,
Colors.Orange.Default,
Colors.DeepPurple.Default,
Colors.Brown.Default,
Colors.BlueGray.Default,
Colors.Gray.Default,
];

public static string GetColor(int index)
{
return All[index % All.Count];
}
}
1 change: 1 addition & 0 deletions frontend/Money.Web/Components/Charts/Chart.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<canvas id="@_id"></canvas>
43 changes: 43 additions & 0 deletions frontend/Money.Web/Components/Charts/Chart.razor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;
using Money.Web.Models.Charts.Config;

namespace Money.Web.Components.Charts;

public sealed partial class Chart(IJSRuntime jsRuntime) : IAsyncDisposable
{
private readonly string _id = "chart-" + Guid.NewGuid();
private bool _isRendered;

[Parameter]
public required ChartConfig Config { get; set; }

public ValueTask UpdateAsync()
{
if (_isRendered)
{
return jsRuntime.InvokeVoidAsync("moneyChart.update", _id, Config);
}

return ValueTask.CompletedTask;
}

public ValueTask DisposeAsync()
{
if (_isRendered)
{
return jsRuntime.InvokeVoidAsync("moneyChart.destroy", _id);
}

return ValueTask.CompletedTask;
}

protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
await jsRuntime.InvokeVoidAsync("moneyChart.create", _id, Config);
_isRendered = true;
}
}
}
142 changes: 110 additions & 32 deletions frontend/Money.Web/Models/Charts/BarChart.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
using ChartJs.Blazor.BarChart;
using ChartJs.Blazor.BarChart.Axes;
using ChartJs.Blazor.Common;
using Money.Web.Models.Charts.Config;

namespace Money.Web.Models.Charts;

public class BarChart : BaseChart<BarOptions>
public class BarChart : BaseChart
{
private static readonly Dictionary<TimeFrame.Mode, TimeFrame> TimeFrames = new()
{
Expand All @@ -22,44 +20,119 @@ public class BarChart : BaseChart<BarOptions>
private readonly int _daysBreakpoint = 31;
private readonly int _weekBreakpoint = 140;

public static BarChart Create(int operationTypeId)
public static BarChart Create(int operationTypeId, bool useThemeColors = true)
{
var scales = new Dictionary<string, ChartAxis>
{
["x"] = new()
{
Stacked = true,
},
["y"] = new()
{
Stacked = true,
BeginAtZero = true,
},
};

var legend = new ChartLegend
{
Display = true,
Position = "top",
Labels = new(),
};

if (useThemeColors)
{
scales["x"].Ticks = new()
{
Color = "var(--mud-palette-text-secondary)",
};

scales["x"].Grid = new()
{
Color = "var(--mud-palette-lines-default)",
};

scales["y"].Ticks = new()
{
Color = "var(--mud-palette-text-secondary)",
};

scales["y"].Grid = new()
{
Color = "var(--mud-palette-lines-default)",
};

legend.Labels.Color = "var(--mud-palette-text-primary)";
}

return new()
{
Chart = new(),
Config = new BarConfig
Chart = null,
Config = new()
{
Type = "bar",
Options = new()
{
Responsive = true,
Scales = new()
Scales = scales,
Plugins = new()
{
XAxes =
[
new BarCategoryAxis
{
Stacked = true,
},
],
YAxes =
[
new BarLinearCartesianAxis
{
Stacked = true,
Ticks = new()
{
BeginAtZero = true,
},
},
],
Legend = legend,
},
},
},
OperationTypeId = operationTypeId,
};
}

public Task UpdateAsync(List<Operation>? operations, List<Category> categories, DateRange range)
// TODO: Не работает + дублирование
public void UpdateTheme(bool useThemeColors)
{
var scales = Config.Options.Scales;
var legend = Config.Options.Plugins?.Legend;

if (scales == null || legend?.Labels == null)
{
return;
}

if (useThemeColors)
{
if (scales.TryGetValue("x", out var xAxis))
{
xAxis.Ticks?.Color = "var(--mud-palette-text-secondary)";
xAxis.Grid?.Color = "var(--mud-palette-lines-default)";
}

if (scales.TryGetValue("y", out var yAxis))
{
yAxis.Ticks?.Color = "var(--mud-palette-text-secondary)";
yAxis.Grid?.Color = "var(--mud-palette-lines-default)";
}

legend.Labels.Color = "var(--mud-palette-text-primary)";
}
else
{
if (scales.TryGetValue("x", out var xAxis))
{
xAxis.Ticks?.Color = null;
xAxis.Grid?.Color = null;
}

if (scales.TryGetValue("y", out var yAxis))
{
yAxis.Ticks?.Color = null;
yAxis.Grid?.Color = null;
}

legend.Labels.Color = null;
}
}

public ValueTask UpdateAsync(List<Operation>? operations, List<Category> categories, DateRange range)
{
Config.Data.Datasets.Clear();
Config.Data.Labels.Clear();
Expand All @@ -69,21 +142,26 @@ public Task UpdateAsync(List<Operation>? operations, List<Category> categories,
FillBarChart(Config.Data, operations, categories, range);
}

return Chart.Update();
if (Chart != null)
{
return Chart.UpdateAsync();
}

return ValueTask.CompletedTask;
}

private static BarDataset<decimal?>[] CreateDatasets(ChartData configData, List<Category> categories)
private static ChartDataset[] CreateDatasets(ChartData configData, List<Category> categories)
{
var datasets = new BarDataset<decimal?>[categories.Count];
var datasets = new ChartDataset[categories.Count];

for (var i = 0; i < categories.Count; i++)
{
var category = categories[i];

var dataset = new BarDataset<decimal?>
var dataset = new ChartDataset
{
Label = category.Name,
BackgroundColor = category.Color ?? Random.Shared.NextColor(),
BackgroundColor = category.Color ?? ChartColors.GetColor(i),
};

datasets[i] = dataset;
Expand Down
Loading
Loading