Compare commits
11 changed files with 6 additions and 190 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -48,4 +48,3 @@ DataDir/
|
||||||
|
|
||||||
# Exclude test reports (local test report, not for the repo)
|
# Exclude test reports (local test report, not for the repo)
|
||||||
/test-reports
|
/test-reports
|
||||||
/doc/**/.*.md
|
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,6 @@ public static class ServiceCollectionHelpers
|
||||||
var billingClient = new BillingApiClient(api, () => settings.ApiUrl);
|
var billingClient = new BillingApiClient(api, () => settings.ApiUrl);
|
||||||
var estimateClient = new EstimateApiClient(api, () => settings.ApiUrl);
|
var estimateClient = new EstimateApiClient(api, () => settings.ApiUrl);
|
||||||
var frontClient = new FrontOfficeApiClient(api, () => settings.ApiUrl);
|
var frontClient = new FrontOfficeApiClient(api, () => settings.ApiUrl);
|
||||||
var resourceUsageClient = new ResourceUsageApiClient(api, () => settings.ApiUrl);
|
|
||||||
var userDirectory = new UserDirectory(userSearchClient);
|
var userDirectory = new UserDirectory(userSearchClient);
|
||||||
var reverseGeocoding = new NominatimReverseGeocodingService();
|
var reverseGeocoding = new NominatimReverseGeocodingService();
|
||||||
|
|
||||||
|
|
@ -76,7 +75,6 @@ public static class ServiceCollectionHelpers
|
||||||
services.AddTransient<EstimateListPage>();
|
services.AddTransient<EstimateListPage>();
|
||||||
services.AddTransient<EstimateValidationPage>();
|
services.AddTransient<EstimateValidationPage>();
|
||||||
services.AddTransient<MyFilesPage>();
|
services.AddTransient<MyFilesPage>();
|
||||||
services.AddTransient<ResourceUsagePage>();
|
|
||||||
|
|
||||||
// ViewModels
|
// ViewModels
|
||||||
services.AddSingleton(settings);
|
services.AddSingleton(settings);
|
||||||
|
|
@ -89,7 +87,6 @@ public static class ServiceCollectionHelpers
|
||||||
services.AddSingleton(billingClient);
|
services.AddSingleton(billingClient);
|
||||||
services.AddSingleton(estimateClient);
|
services.AddSingleton(estimateClient);
|
||||||
services.AddSingleton(frontClient);
|
services.AddSingleton(frontClient);
|
||||||
services.AddSingleton(resourceUsageClient);
|
|
||||||
services.AddSingleton(userFilesClient);
|
services.AddSingleton(userFilesClient);
|
||||||
services.AddSingleton<IReverseGeocodingService>(reverseGeocoding);
|
services.AddSingleton<IReverseGeocodingService>(reverseGeocoding);
|
||||||
services.AddSingleton<IUserDirectory>(userDirectory);
|
services.AddSingleton<IUserDirectory>(userDirectory);
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,6 @@ public class ViewLocator : IDataTemplate
|
||||||
EstimateListPageViewModel => services.GetRequiredService<EstimateListPage>(),
|
EstimateListPageViewModel => services.GetRequiredService<EstimateListPage>(),
|
||||||
EstimateValidationPageViewModel => services.GetRequiredService<EstimateValidationPage>(),
|
EstimateValidationPageViewModel => services.GetRequiredService<EstimateValidationPage>(),
|
||||||
MyFilesViewModel => services.GetRequiredService<MyFilesPage>(),
|
MyFilesViewModel => services.GetRequiredService<MyFilesPage>(),
|
||||||
ResourceUsagePageViewModel => services.GetRequiredService<ResourceUsagePage>(),
|
|
||||||
ChatViewModel => services.GetRequiredService<ChatPage>(),
|
ChatViewModel => services.GetRequiredService<ChatPage>(),
|
||||||
null => new TextBlock { Text = "No view for <null>" },
|
null => new TextBlock { Text = "No view for <null>" },
|
||||||
_ => new TextBlock { Text = $"No view for {data.GetType().Name}" }
|
_ => new TextBlock { Text = $"No view for {data.GetType().Name}" }
|
||||||
|
|
|
||||||
|
|
@ -36,14 +36,12 @@ public class HomePageViewModel : ViewModelBase
|
||||||
OpenProviderEstimates = new AsyncRelayCommand(() => OpenEstimateListAsync(EstimateListPerspective.Provider));
|
OpenProviderEstimates = new AsyncRelayCommand(() => OpenEstimateListAsync(EstimateListPerspective.Provider));
|
||||||
OpenBlogs = new AsyncRelayCommand(App.PushBlogsPageAsync);
|
OpenBlogs = new AsyncRelayCommand(App.PushBlogsPageAsync);
|
||||||
OpenMyFiles = new AsyncRelayCommand(OpenMyFilesAsync);
|
OpenMyFiles = new AsyncRelayCommand(OpenMyFilesAsync);
|
||||||
OpenResourceUsage = new AsyncRelayCommand(OpenResourceUsageAsync);
|
|
||||||
OpenChat = new AsyncRelayCommand(OpenChatAsync);
|
OpenChat = new AsyncRelayCommand(OpenChatAsync);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public IAsyncRelayCommand OpenChat { get; }
|
public IAsyncRelayCommand OpenChat { get; }
|
||||||
public IAsyncRelayCommand OpenBlogs { get; }
|
public IAsyncRelayCommand OpenBlogs { get; }
|
||||||
public IAsyncRelayCommand OpenResourceUsage { get; }
|
|
||||||
public IAsyncRelayCommand OpenActivities { get; }
|
public IAsyncRelayCommand OpenActivities { get; }
|
||||||
public IAsyncRelayCommand OpenProviderRequests { get; }
|
public IAsyncRelayCommand OpenProviderRequests { get; }
|
||||||
public IAsyncRelayCommand OpenClientEstimates { get; }
|
public IAsyncRelayCommand OpenClientEstimates { get; }
|
||||||
|
|
@ -140,25 +138,6 @@ public class HomePageViewModel : ViewModelBase
|
||||||
await app.PushPageAsync(vm);
|
await app.PushPageAsync(vm);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task OpenResourceUsageAsync()
|
|
||||||
{
|
|
||||||
var app = (App?)Application.Current;
|
|
||||||
if (app is null)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException("Application PostIt indisponible.");
|
|
||||||
}
|
|
||||||
|
|
||||||
var resourceUsageClient = app.ServiceProvider?.GetRequiredService<ResourceUsageApiClient>();
|
|
||||||
if (resourceUsageClient is null)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException("Client usage indisponible.");
|
|
||||||
}
|
|
||||||
|
|
||||||
var vm = new ResourceUsagePageViewModel(resourceUsageClient);
|
|
||||||
await vm.InitializeAsync();
|
|
||||||
await app.PushPageAsync(vm);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Avalonia designer constructor. Builds a self-contained VM
|
/// Avalonia designer constructor. Builds a self-contained VM
|
||||||
/// with a freshly-constructed Settings so the XAML preview can
|
/// with a freshly-constructed Settings so the XAML preview can
|
||||||
|
|
|
||||||
|
|
@ -1,90 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.ObjectModel;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
|
||||||
using CommunityToolkit.Mvvm.Input;
|
|
||||||
using Yavsc.Abstract.Resources;
|
|
||||||
using Yavsc.Api.Client;
|
|
||||||
|
|
||||||
namespace PostIt.ViewModels;
|
|
||||||
|
|
||||||
public partial class ResourceUsagePageViewModel : ViewModelBase
|
|
||||||
{
|
|
||||||
private readonly ResourceUsageApiClient _client;
|
|
||||||
|
|
||||||
[ObservableProperty]
|
|
||||||
public partial bool IsBusy { get; set; }
|
|
||||||
|
|
||||||
[ObservableProperty]
|
|
||||||
public partial bool IsAdminView { get; set; }
|
|
||||||
|
|
||||||
[ObservableProperty]
|
|
||||||
public partial ResourceUsageSummary? CurrentSummary { get; set; }
|
|
||||||
|
|
||||||
[ObservableProperty]
|
|
||||||
public partial ObservableCollection<ResourceUsageSummary> Overview { get; set; } = new();
|
|
||||||
|
|
||||||
public string Heading => IsAdminView ? "Vue d'administration des usages" : "Mon usage des ressources";
|
|
||||||
|
|
||||||
public override bool CanNavigateNext { get => false; protected set { _ = value; } }
|
|
||||||
public override bool CanNavigatePrevious { get => true; protected set { _ = value; } }
|
|
||||||
|
|
||||||
public ResourceUsagePageViewModel(ResourceUsageApiClient client)
|
|
||||||
{
|
|
||||||
_client = client ?? throw new ArgumentNullException(nameof(client));
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task InitializeAsync() => RefreshAsync();
|
|
||||||
|
|
||||||
[RelayCommand]
|
|
||||||
public async Task RefreshAsync()
|
|
||||||
{
|
|
||||||
IsBusy = true;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Overview.Clear();
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var adminOverview = await _client.GetAdminOverviewAsync().ConfigureAwait(true);
|
|
||||||
if (adminOverview is { Count: > 0 })
|
|
||||||
{
|
|
||||||
foreach (var item in adminOverview)
|
|
||||||
{
|
|
||||||
Overview.Add(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
CurrentSummary = adminOverview[0];
|
|
||||||
IsAdminView = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
// Non-admin users are not allowed on the admin route; fall back
|
|
||||||
// to the current-user summary below.
|
|
||||||
}
|
|
||||||
|
|
||||||
var current = await _client.GetCurrentAsync().ConfigureAwait(true);
|
|
||||||
CurrentSummary = current;
|
|
||||||
if (current is not null)
|
|
||||||
{
|
|
||||||
Overview.Clear();
|
|
||||||
Overview.Add(current);
|
|
||||||
}
|
|
||||||
|
|
||||||
IsAdminView = false;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
CurrentSummary = null;
|
|
||||||
Overview.Clear();
|
|
||||||
IsAdminView = false;
|
|
||||||
throw new InvalidOperationException($"Impossible de charger l'usage des ressources : {ex.Message}", ex);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
IsBusy = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -44,9 +44,5 @@
|
||||||
Command="{Binding OpenMyFiles}"
|
Command="{Binding OpenMyFiles}"
|
||||||
HorizontalAlignment="Center"
|
HorizontalAlignment="Center"
|
||||||
IsEnabled="{Binding SessionStatus.IsLoggedIn}"/>
|
IsEnabled="{Binding SessionStatus.IsLoggedIn}"/>
|
||||||
<Button Content="Mon usage / administration"
|
|
||||||
Command="{Binding OpenResourceUsage}"
|
|
||||||
HorizontalAlignment="Center"
|
|
||||||
IsEnabled="{Binding SessionStatus.IsLoggedIn}"/>
|
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</ContentPage>
|
</ContentPage>
|
||||||
|
|
|
||||||
|
|
@ -1,57 +0,0 @@
|
||||||
<ContentPage xmlns="https://github.com/avaloniaui"
|
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
|
||||||
xmlns:vm="using:PostIt.ViewModels"
|
|
||||||
xmlns:resources="using:Yavsc.Abstract.Resources"
|
|
||||||
x:Class="PostIt.Views.ResourceUsagePage"
|
|
||||||
x:DataType="vm:ResourceUsagePageViewModel"
|
|
||||||
Header="Usage des ressources">
|
|
||||||
|
|
||||||
<StackPanel Margin="16" Spacing="12">
|
|
||||||
<TextBlock Text="{Binding Heading}"
|
|
||||||
FontSize="22"
|
|
||||||
FontWeight="SemiBold"/>
|
|
||||||
|
|
||||||
<Button Content="Actualiser"
|
|
||||||
Command="{Binding RefreshCommand}"
|
|
||||||
IsEnabled="{Binding !IsBusy}"/>
|
|
||||||
|
|
||||||
<ProgressBar IsVisible="{Binding IsBusy}"
|
|
||||||
IsIndeterminate="True"
|
|
||||||
Height="8"/>
|
|
||||||
|
|
||||||
<StackPanel IsVisible="{Binding !IsAdminView}">
|
|
||||||
<TextBlock Text="Résumé personnel" FontWeight="Bold"/>
|
|
||||||
<StackPanel DataContext="{Binding CurrentSummary}" Spacing="4">
|
|
||||||
<TextBlock Text="{Binding UserName, StringFormat='Utilisateur : {0}'}"/>
|
|
||||||
<TextBlock Text="{Binding ApiCalls, StringFormat='Appels API : {0:F0}'}"/>
|
|
||||||
<TextBlock Text="{Binding CpuSeconds, StringFormat='CPU : {0:F3} s'}"/>
|
|
||||||
<TextBlock Text="{Binding BandwidthMb, StringFormat='Bande passante : {0:F3} Mo'}"/>
|
|
||||||
<TextBlock Text="{Binding StorageMb, StringFormat='Stockage : {0:F3} Mo'}"/>
|
|
||||||
<TextBlock Text="{Binding EstimatedCompensation, StringFormat='Estimation : {0:F2}'}"/>
|
|
||||||
</StackPanel>
|
|
||||||
</StackPanel>
|
|
||||||
|
|
||||||
<ItemsControl ItemsSource="{Binding Overview}"
|
|
||||||
IsVisible="{Binding IsAdminView}">
|
|
||||||
<ItemsControl.ItemTemplate>
|
|
||||||
<DataTemplate x:DataType="resources:ResourceUsageSummary">
|
|
||||||
<Border Margin="0,0,0,8"
|
|
||||||
Padding="12"
|
|
||||||
CornerRadius="8"
|
|
||||||
BorderBrush="#D0D7DE"
|
|
||||||
BorderThickness="1">
|
|
||||||
<StackPanel Spacing="4">
|
|
||||||
<TextBlock Text="{Binding UserName}"
|
|
||||||
FontWeight="Bold"/>
|
|
||||||
<TextBlock Text="{Binding ApiCalls, StringFormat='Appels API : {0:F0}'}"/>
|
|
||||||
<TextBlock Text="{Binding CpuSeconds, StringFormat='CPU : {0:F3} s'}"/>
|
|
||||||
<TextBlock Text="{Binding BandwidthMb, StringFormat='Bande passante : {0:F3} Mo'}"/>
|
|
||||||
<TextBlock Text="{Binding StorageMb, StringFormat='Stockage : {0:F3} Mo'}"/>
|
|
||||||
<TextBlock Text="{Binding EstimatedCompensation, StringFormat='Estimation : {0:F2}'}"/>
|
|
||||||
</StackPanel>
|
|
||||||
</Border>
|
|
||||||
</DataTemplate>
|
|
||||||
</ItemsControl.ItemTemplate>
|
|
||||||
</ItemsControl>
|
|
||||||
</StackPanel>
|
|
||||||
</ContentPage>
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
using Avalonia.Controls;
|
|
||||||
|
|
||||||
namespace PostIt.Views;
|
|
||||||
|
|
||||||
public partial class ResourceUsagePage : ContentPage
|
|
||||||
{
|
|
||||||
public ResourceUsagePage()
|
|
||||||
{
|
|
||||||
InitializeComponent();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
background-position: 0%;
|
background-position: 0%;
|
||||||
background-attachment: fixed;">
|
background-attachment: fixed;">
|
||||||
<a class="navbar-brand logo" href="/">
|
<a class="navbar-brand logo" href="/">
|
||||||
<img src="~/images/yavsc-logo.svg" alt="Yavsc" style="height:32px; margin-left:8px; display:inline-block; vertical-align:middle;" />
|
<img src="~/images/yavsc-logo.svg" alt="Yavsc" style="height:32px; margin-right:8px; display:inline-block; vertical-align:middle;" />
|
||||||
@SiteSettings.Value.Title
|
@SiteSettings.Value.Title
|
||||||
</a>
|
</a>
|
||||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse"
|
<button class="navbar-toggler" type="button" data-bs-toggle="collapse"
|
||||||
|
|
|
||||||
|
|
@ -14229,6 +14229,10 @@ body {
|
||||||
--bs-secondary-rgb: transparent
|
--bs-secondary-rgb: transparent
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.card a {
|
||||||
|
color: #fff
|
||||||
|
}
|
||||||
|
|
||||||
.card .text-muted {
|
.card .text-muted {
|
||||||
color: rgba(255, 255, 255, .7) !important
|
color: rgba(255, 255, 255, .7) !important
|
||||||
}
|
}
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue