mirror of
https://github.com/claunia/marechai.git
synced 2025-12-16 19:14:25 +00:00
Add list of GPUs.
This commit is contained in:
@@ -14,6 +14,7 @@ using Uno.UI;
|
|||||||
using CompanyDetailViewModel = Marechai.App.Presentation.ViewModels.CompanyDetailViewModel;
|
using CompanyDetailViewModel = Marechai.App.Presentation.ViewModels.CompanyDetailViewModel;
|
||||||
using ComputersListViewModel = Marechai.App.Presentation.ViewModels.ComputersListViewModel;
|
using ComputersListViewModel = Marechai.App.Presentation.ViewModels.ComputersListViewModel;
|
||||||
using ComputersViewModel = Marechai.App.Presentation.ViewModels.ComputersViewModel;
|
using ComputersViewModel = Marechai.App.Presentation.ViewModels.ComputersViewModel;
|
||||||
|
using GpuListViewModel = Marechai.App.Presentation.ViewModels.GpusListViewModel;
|
||||||
using MachineViewViewModel = Marechai.App.Presentation.ViewModels.MachineViewViewModel;
|
using MachineViewViewModel = Marechai.App.Presentation.ViewModels.MachineViewViewModel;
|
||||||
using MainViewModel = Marechai.App.Presentation.ViewModels.MainViewModel;
|
using MainViewModel = Marechai.App.Presentation.ViewModels.MainViewModel;
|
||||||
using NewsViewModel = Marechai.App.Presentation.ViewModels.NewsViewModel;
|
using NewsViewModel = Marechai.App.Presentation.ViewModels.NewsViewModel;
|
||||||
@@ -122,6 +123,7 @@ public partial class App : Application
|
|||||||
services.AddSingleton<CompanyDetailService>();
|
services.AddSingleton<CompanyDetailService>();
|
||||||
services.AddSingleton<CompanyDetailViewModel>();
|
services.AddSingleton<CompanyDetailViewModel>();
|
||||||
services.AddSingleton<MachineViewViewModel>();
|
services.AddSingleton<MachineViewViewModel>();
|
||||||
|
services.AddSingleton<GpusService>();
|
||||||
services.AddTransient<PhotoDetailViewModel>();
|
services.AddTransient<PhotoDetailViewModel>();
|
||||||
|
|
||||||
services
|
services
|
||||||
@@ -134,6 +136,7 @@ public partial class App : Application
|
|||||||
|
|
||||||
services.AddTransient<ComputersListViewModel>();
|
services.AddTransient<ComputersListViewModel>();
|
||||||
services.AddTransient<ConsolesListViewModel>();
|
services.AddTransient<ConsolesListViewModel>();
|
||||||
|
services.AddTransient<GpuListViewModel>();
|
||||||
})
|
})
|
||||||
.UseNavigation(RegisterRoutes));
|
.UseNavigation(RegisterRoutes));
|
||||||
|
|
||||||
@@ -160,6 +163,7 @@ public partial class App : Application
|
|||||||
new ViewMap<CompanyDetailPage, CompanyDetailViewModel>(),
|
new ViewMap<CompanyDetailPage, CompanyDetailViewModel>(),
|
||||||
new ViewMap<MachineViewPage, MachineViewViewModel>(),
|
new ViewMap<MachineViewPage, MachineViewViewModel>(),
|
||||||
new ViewMap<PhotoDetailPage, PhotoDetailViewModel>(),
|
new ViewMap<PhotoDetailPage, PhotoDetailViewModel>(),
|
||||||
|
new ViewMap<GpuListPage, GpuListViewModel>(),
|
||||||
new DataViewMap<SecondPage, SecondViewModel, Entity>());
|
new DataViewMap<SecondPage, SecondViewModel, Entity>());
|
||||||
|
|
||||||
routes.Register(new RouteMap("",
|
routes.Register(new RouteMap("",
|
||||||
@@ -201,6 +205,15 @@ public partial class App : Application
|
|||||||
views.FindByViewModel<
|
views.FindByViewModel<
|
||||||
CompanyDetailViewModel>())
|
CompanyDetailViewModel>())
|
||||||
]),
|
]),
|
||||||
|
new RouteMap("gpus",
|
||||||
|
views.FindByViewModel<GpuListViewModel>(),
|
||||||
|
Nested:
|
||||||
|
[
|
||||||
|
new RouteMap("list-gpus",
|
||||||
|
views.FindByViewModel<
|
||||||
|
GpuListViewModel>(),
|
||||||
|
true)
|
||||||
|
]),
|
||||||
new RouteMap("Second",
|
new RouteMap("Second",
|
||||||
views.FindByViewModel<SecondViewModel>())
|
views.FindByViewModel<SecondViewModel>())
|
||||||
])
|
])
|
||||||
|
|||||||
204
Marechai.App/Presentation/ViewModels/GpusListViewModel.cs
Normal file
204
Marechai.App/Presentation/ViewModels/GpusListViewModel.cs
Normal file
@@ -0,0 +1,204 @@
|
|||||||
|
#nullable enable
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Marechai.App.Services;
|
||||||
|
using Uno.Extensions.Navigation;
|
||||||
|
|
||||||
|
namespace Marechai.App.Presentation.ViewModels;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ViewModel for displaying a list of GPUs
|
||||||
|
/// </summary>
|
||||||
|
public partial class GpusListViewModel : ObservableObject
|
||||||
|
{
|
||||||
|
private readonly GpusService _gpusService;
|
||||||
|
private readonly IStringLocalizer _localizer;
|
||||||
|
private readonly ILogger<GpusListViewModel> _logger;
|
||||||
|
private readonly INavigator _navigator;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private string _errorMessage = string.Empty;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private ObservableCollection<GpuListItem> _gpusList = [];
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private bool _hasError;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private bool _isDataLoaded;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private bool _isLoading;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private string _pageTitle = string.Empty;
|
||||||
|
|
||||||
|
public GpusListViewModel(GpusService gpusService, IStringLocalizer localizer, ILogger<GpusListViewModel> logger,
|
||||||
|
INavigator navigator)
|
||||||
|
{
|
||||||
|
_gpusService = gpusService;
|
||||||
|
_localizer = localizer;
|
||||||
|
_logger = logger;
|
||||||
|
_navigator = navigator;
|
||||||
|
LoadData = new AsyncRelayCommand(LoadDataAsync);
|
||||||
|
NavigateToGpuCommand = new AsyncRelayCommand<GpuListItem>(NavigateToGpuAsync);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IAsyncRelayCommand LoadData { get; }
|
||||||
|
public IAsyncRelayCommand<GpuListItem> NavigateToGpuCommand { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Loads all GPUs and sorts them with special handling for Framebuffer and Software
|
||||||
|
/// </summary>
|
||||||
|
private async Task LoadDataAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
IsLoading = true;
|
||||||
|
ErrorMessage = string.Empty;
|
||||||
|
HasError = false;
|
||||||
|
IsDataLoaded = false;
|
||||||
|
GpusList.Clear();
|
||||||
|
|
||||||
|
_logger.LogInformation("LoadDataAsync called for GPUs");
|
||||||
|
|
||||||
|
PageTitle = _localizer["GraphicalProcessingUnits"];
|
||||||
|
|
||||||
|
// Load GPUs from the API
|
||||||
|
await LoadGpusFromApiAsync();
|
||||||
|
|
||||||
|
_logger.LogInformation("LoadGpusFromApiAsync completed. GpusList.Count={Count}", GpusList.Count);
|
||||||
|
|
||||||
|
if(GpusList.Count == 0)
|
||||||
|
{
|
||||||
|
ErrorMessage = _localizer["No graphics processing units found"].Value;
|
||||||
|
HasError = true;
|
||||||
|
|
||||||
|
_logger.LogWarning("No GPUs found");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
IsDataLoaded = true;
|
||||||
|
}
|
||||||
|
catch(Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Error loading GPUs: {Exception}", ex.Message);
|
||||||
|
ErrorMessage = _localizer["Failed to load graphics processing units. Please try again later."].Value;
|
||||||
|
HasError = true;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
IsLoading = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Loads GPUs from the API and sorts them with special handling for Framebuffer and Software
|
||||||
|
/// </summary>
|
||||||
|
private async Task LoadGpusFromApiAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
List<GpuDto> gpus = await _gpusService.GetAllGpusAsync();
|
||||||
|
|
||||||
|
if(gpus == null || gpus.Count == 0)
|
||||||
|
{
|
||||||
|
_logger.LogInformation("No GPUs returned from API");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Separate special GPUs from regular ones
|
||||||
|
var specialGpus = new List<GpuListItem>();
|
||||||
|
var regularGpus = new List<GpuListItem>();
|
||||||
|
|
||||||
|
foreach(GpuDto gpu in gpus)
|
||||||
|
{
|
||||||
|
string displayName = gpu.Name ?? string.Empty;
|
||||||
|
|
||||||
|
// Replace special database names
|
||||||
|
if(displayName == "DB_FRAMEBUFFER")
|
||||||
|
displayName = "Framebuffer";
|
||||||
|
else if(displayName == "DB_SOFTWARE")
|
||||||
|
displayName = "Software";
|
||||||
|
else if(displayName == "DB_NONE") displayName = "None";
|
||||||
|
|
||||||
|
var gpuItem = new GpuListItem
|
||||||
|
{
|
||||||
|
Id = gpu.Id ?? 0,
|
||||||
|
Name = displayName,
|
||||||
|
Company = gpu.Company ?? string.Empty,
|
||||||
|
IsSpecial = gpu.Name is "DB_FRAMEBUFFER" or "DB_SOFTWARE" or "DB_NONE"
|
||||||
|
};
|
||||||
|
|
||||||
|
if(gpuItem.IsSpecial)
|
||||||
|
specialGpus.Add(gpuItem);
|
||||||
|
else
|
||||||
|
regularGpus.Add(gpuItem);
|
||||||
|
|
||||||
|
_logger.LogInformation("GPU: {Name}, Company: {Company}, ID: {Id}, IsSpecial: {IsSpecial}",
|
||||||
|
displayName,
|
||||||
|
gpu.Company,
|
||||||
|
gpu.Id,
|
||||||
|
gpuItem.IsSpecial);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort special GPUs: Framebuffer first, then Software, then None
|
||||||
|
specialGpus.Sort((a, b) =>
|
||||||
|
{
|
||||||
|
int orderA = a.Name == "Framebuffer"
|
||||||
|
? 0
|
||||||
|
: a.Name == "Software"
|
||||||
|
? 1
|
||||||
|
: 2;
|
||||||
|
|
||||||
|
int orderB = b.Name == "Framebuffer"
|
||||||
|
? 0
|
||||||
|
: b.Name == "Software"
|
||||||
|
? 1
|
||||||
|
: 2;
|
||||||
|
|
||||||
|
return orderA.CompareTo(orderB);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Sort regular GPUs alphabetically
|
||||||
|
regularGpus.Sort((a, b) => string.Compare(a.Name, b.Name, StringComparison.OrdinalIgnoreCase));
|
||||||
|
|
||||||
|
// Add special GPUs first, then regular GPUs
|
||||||
|
foreach(GpuListItem gpu in specialGpus) GpusList.Add(gpu);
|
||||||
|
|
||||||
|
foreach(GpuListItem gpu in regularGpus) GpusList.Add(gpu);
|
||||||
|
}
|
||||||
|
catch(Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Error loading GPUs from API");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Navigates to the GPU detail view
|
||||||
|
/// </summary>
|
||||||
|
private async Task NavigateToGpuAsync(GpuListItem? gpu)
|
||||||
|
{
|
||||||
|
if(gpu is null) return;
|
||||||
|
|
||||||
|
_logger.LogInformation("Navigating to GPU detail: {GpuName} (ID: {GpuId})", gpu.Name, gpu.Id);
|
||||||
|
|
||||||
|
// For now, we'll just log it. Implement detail page navigation when ready.
|
||||||
|
// await _navigator.NavigateViewModelAsync<GpuDetailViewModel>(this, data: gpu);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Data model for a GPU in the list
|
||||||
|
/// </summary>
|
||||||
|
public class GpuListItem
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string Name { get; set; } = string.Empty;
|
||||||
|
public string Company { get; set; } = string.Empty;
|
||||||
|
public bool IsSpecial { get; set; }
|
||||||
|
}
|
||||||
@@ -47,7 +47,7 @@ public partial class MainViewModel : ObservableObject
|
|||||||
NavigateToConsolesCommand = new AsyncRelayCommand(() => NavigateTo("consoles"));
|
NavigateToConsolesCommand = new AsyncRelayCommand(() => NavigateTo("consoles"));
|
||||||
NavigateToDocumentsCommand = new AsyncRelayCommand(() => NavigateTo("documents"));
|
NavigateToDocumentsCommand = new AsyncRelayCommand(() => NavigateTo("documents"));
|
||||||
NavigateToDumpsCommand = new AsyncRelayCommand(() => NavigateTo("dumps"));
|
NavigateToDumpsCommand = new AsyncRelayCommand(() => NavigateTo("dumps"));
|
||||||
NavigateToGraphicalProcessingUnitsCommand = new AsyncRelayCommand(() => NavigateTo("gpus"));
|
NavigateToGraphicalProcessingUnitsCommand = new AsyncRelayCommand(() => NavigateTo("gpus/list-gpus"));
|
||||||
NavigateToMagazinesCommand = new AsyncRelayCommand(() => NavigateTo("magazines"));
|
NavigateToMagazinesCommand = new AsyncRelayCommand(() => NavigateTo("magazines"));
|
||||||
NavigateToPeopleCommand = new AsyncRelayCommand(() => NavigateTo("people"));
|
NavigateToPeopleCommand = new AsyncRelayCommand(() => NavigateTo("people"));
|
||||||
NavigateToProcessorsCommand = new AsyncRelayCommand(() => NavigateTo("processors"));
|
NavigateToProcessorsCommand = new AsyncRelayCommand(() => NavigateTo("processors"));
|
||||||
|
|||||||
207
Marechai.App/Presentation/Views/GpuListPage.xaml
Normal file
207
Marechai.App/Presentation/Views/GpuListPage.xaml
Normal file
@@ -0,0 +1,207 @@
|
|||||||
|
<?xml version="1.0"
|
||||||
|
encoding="utf-8"?>
|
||||||
|
|
||||||
|
<Page x:Class="Marechai.App.Presentation.Views.GpuListPage"
|
||||||
|
x:Name="PageRoot"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:utu="using:Uno.Toolkit.UI"
|
||||||
|
NavigationCacheMode="Required"
|
||||||
|
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||||
|
|
||||||
|
<Grid utu:SafeArea.Insets="VisibleBounds">
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto" /> <RowDefinition Height="*" />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
|
<!-- Header -->
|
||||||
|
<utu:NavigationBar Grid.Row="0"
|
||||||
|
Content="Graphics Processing Units">
|
||||||
|
</utu:NavigationBar>
|
||||||
|
|
||||||
|
<!-- Main Content -->
|
||||||
|
<Grid Grid.Row="1">
|
||||||
|
|
||||||
|
<!-- Loading State -->
|
||||||
|
<StackPanel Visibility="{Binding IsLoading}"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
HorizontalAlignment="Center"
|
||||||
|
Padding="32"
|
||||||
|
Spacing="16">
|
||||||
|
<ProgressRing IsActive="True"
|
||||||
|
IsIndeterminate="True"
|
||||||
|
Height="64"
|
||||||
|
Width="64"
|
||||||
|
Foreground="{ThemeResource SystemAccentColor}" />
|
||||||
|
<TextBlock Text="Loading graphics processing units..."
|
||||||
|
FontSize="14"
|
||||||
|
TextAlignment="Center"
|
||||||
|
Foreground="{ThemeResource SystemBaseMediumColor}" />
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<!-- Error State -->
|
||||||
|
<StackPanel Visibility="{Binding HasError}"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
HorizontalAlignment="Center"
|
||||||
|
Padding="24"
|
||||||
|
Spacing="16"
|
||||||
|
MaxWidth="400">
|
||||||
|
<InfoBar IsOpen="True"
|
||||||
|
Severity="Error"
|
||||||
|
Title="Unable to Load Graphics Processing Units"
|
||||||
|
Message="{Binding ErrorMessage}"
|
||||||
|
IsClosable="False" />
|
||||||
|
<Button Content="Retry"
|
||||||
|
Command="{Binding LoadData}"
|
||||||
|
HorizontalAlignment="Center"
|
||||||
|
Style="{ThemeResource AccentButtonStyle}" />
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<!-- GPUs List -->
|
||||||
|
<Grid Visibility="{Binding IsDataLoaded}">
|
||||||
|
<ScrollViewer VerticalScrollBarVisibility="Auto"
|
||||||
|
HorizontalScrollBarVisibility="Disabled">
|
||||||
|
<Grid Padding="8">
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto" /> <RowDefinition Height="*" />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
|
<!-- Count Header -->
|
||||||
|
<StackPanel Grid.Row="0"
|
||||||
|
Padding="16,12"
|
||||||
|
Orientation="Horizontal"
|
||||||
|
Spacing="4">
|
||||||
|
<TextBlock FontSize="12"
|
||||||
|
FontWeight="SemiBold"
|
||||||
|
Foreground="{ThemeResource SystemBaseMediumColor}"
|
||||||
|
Text="RESULTS:" />
|
||||||
|
<TextBlock FontSize="12"
|
||||||
|
FontWeight="SemiBold"
|
||||||
|
Foreground="{ThemeResource SystemBaseMediumColor}"
|
||||||
|
Text="{Binding GpusList.Count}" />
|
||||||
|
<TextBlock FontSize="12"
|
||||||
|
FontWeight="SemiBold"
|
||||||
|
Foreground="{ThemeResource SystemBaseMediumColor}"
|
||||||
|
Text="graphics processing units" />
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<!-- GPUs List -->
|
||||||
|
<ItemsControl Grid.Row="1"
|
||||||
|
ItemsSource="{Binding GpusList}"
|
||||||
|
Padding="0"
|
||||||
|
Margin="0,8,0,0"
|
||||||
|
HorizontalAlignment="Stretch">
|
||||||
|
<ItemsControl.ItemsPanel>
|
||||||
|
<ItemsPanelTemplate>
|
||||||
|
<StackPanel Orientation="Vertical"
|
||||||
|
Spacing="0"
|
||||||
|
HorizontalAlignment="Stretch" />
|
||||||
|
</ItemsPanelTemplate>
|
||||||
|
</ItemsControl.ItemsPanel>
|
||||||
|
<ItemsControl.ItemTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<Button Padding="0"
|
||||||
|
Margin="0,0,0,8"
|
||||||
|
MinHeight="80"
|
||||||
|
HorizontalContentAlignment="Stretch"
|
||||||
|
VerticalContentAlignment="Stretch"
|
||||||
|
HorizontalAlignment="Stretch"
|
||||||
|
Command="{Binding DataContext.NavigateToGpuCommand, ElementName=PageRoot}"
|
||||||
|
CommandParameter="{Binding}"
|
||||||
|
Background="Transparent"
|
||||||
|
BorderThickness="0">
|
||||||
|
<Button.Template>
|
||||||
|
<ControlTemplate TargetType="Button">
|
||||||
|
<Grid MinHeight="80"
|
||||||
|
HorizontalAlignment="Stretch"
|
||||||
|
VerticalAlignment="Stretch">
|
||||||
|
<!-- Shadow effect -->
|
||||||
|
<Border x:Name="ShadowBorder"
|
||||||
|
Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
|
||||||
|
BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
|
||||||
|
BorderThickness="1"
|
||||||
|
CornerRadius="8"
|
||||||
|
Padding="16,12"
|
||||||
|
Translation="0, 0, 4"
|
||||||
|
VerticalAlignment="Stretch">
|
||||||
|
<Border.Shadow>
|
||||||
|
<ThemeShadow />
|
||||||
|
</Border.Shadow>
|
||||||
|
|
||||||
|
<Grid ColumnSpacing="16">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
|
<!-- GPU Info -->
|
||||||
|
<StackPanel Grid.Column="0"
|
||||||
|
Spacing="8"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
HorizontalAlignment="Stretch">
|
||||||
|
<TextBlock Text="{Binding Name}"
|
||||||
|
FontSize="16"
|
||||||
|
FontWeight="SemiBold"
|
||||||
|
Foreground="{ThemeResource TextControlForeground}"
|
||||||
|
TextTrimming="CharacterEllipsis" />
|
||||||
|
<StackPanel Orientation="Horizontal"
|
||||||
|
Spacing="6"
|
||||||
|
VerticalAlignment="Center">
|
||||||
|
<FontIcon Glyph=""
|
||||||
|
FontSize="14"
|
||||||
|
Foreground="{ThemeResource SystemAccentColor}" />
|
||||||
|
<TextBlock Text="{Binding Company}"
|
||||||
|
FontSize="13"
|
||||||
|
Foreground="{ThemeResource SystemBaseMediumColor}"
|
||||||
|
TextTrimming="CharacterEllipsis" />
|
||||||
|
</StackPanel>
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<!-- Navigation Arrow -->
|
||||||
|
<StackPanel Grid.Column="1"
|
||||||
|
VerticalAlignment="Center">
|
||||||
|
<FontIcon Glyph=""
|
||||||
|
FontSize="18"
|
||||||
|
Foreground="{ThemeResource SystemAccentColor}" />
|
||||||
|
</StackPanel>
|
||||||
|
</Grid>
|
||||||
|
</Border>
|
||||||
|
|
||||||
|
<VisualStateManager.VisualStateGroups>
|
||||||
|
<VisualStateGroup x:Name="CommonStates">
|
||||||
|
<VisualState x:Name="Normal" />
|
||||||
|
<VisualState x:Name="PointerOver">
|
||||||
|
<VisualState.Setters>
|
||||||
|
<Setter Target="ShadowBorder.Background"
|
||||||
|
Value="{ThemeResource CardBackgroundFillColorSecondaryBrush}" />
|
||||||
|
<Setter Target="ShadowBorder.Translation"
|
||||||
|
Value="0, -2, 8" />
|
||||||
|
</VisualState.Setters>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="Pressed">
|
||||||
|
<VisualState.Setters>
|
||||||
|
<Setter Target="ShadowBorder.Background"
|
||||||
|
Value="{ThemeResource CardBackgroundFillColorTertiaryBrush}" />
|
||||||
|
<Setter Target="ShadowBorder.Translation"
|
||||||
|
Value="0, 0, 2" />
|
||||||
|
</VisualState.Setters>
|
||||||
|
</VisualState>
|
||||||
|
</VisualStateGroup>
|
||||||
|
</VisualStateManager.VisualStateGroups>
|
||||||
|
</Grid>
|
||||||
|
</ControlTemplate>
|
||||||
|
</Button.Template>
|
||||||
|
</Button>
|
||||||
|
</DataTemplate>
|
||||||
|
</ItemsControl.ItemTemplate>
|
||||||
|
</ItemsControl>
|
||||||
|
|
||||||
|
</Grid>
|
||||||
|
</ScrollViewer>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
</Page>
|
||||||
37
Marechai.App/Presentation/Views/GpuListPage.xaml.cs
Normal file
37
Marechai.App/Presentation/Views/GpuListPage.xaml.cs
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
using Marechai.App.Presentation.ViewModels;
|
||||||
|
using Microsoft.UI.Xaml;
|
||||||
|
using Microsoft.UI.Xaml.Controls;
|
||||||
|
|
||||||
|
namespace Marechai.App.Presentation.Views;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Professional list view for displaying all graphics processing units.
|
||||||
|
/// Features responsive layout, modern styling, and special handling for Framebuffer and Software entries.
|
||||||
|
/// </summary>
|
||||||
|
public sealed partial class GpuListPage : Page
|
||||||
|
{
|
||||||
|
public GpuListPage()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
Loaded += GpuListPage_Loaded;
|
||||||
|
DataContextChanged += GpuListPage_DataContextChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GpuListPage_DataContextChanged(FrameworkElement sender, DataContextChangedEventArgs args)
|
||||||
|
{
|
||||||
|
if(DataContext is GpusListViewModel vm)
|
||||||
|
{
|
||||||
|
// Load data when DataContext is set
|
||||||
|
vm.LoadData.Execute(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GpuListPage_Loaded(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
if(DataContext is GpusListViewModel vm)
|
||||||
|
{
|
||||||
|
// Load data when page is loaded (fallback)
|
||||||
|
vm.LoadData.Execute(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
75
Marechai.App/Services/GpusService.cs
Normal file
75
Marechai.App/Services/GpusService.cs
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Marechai.App.Services;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Service for fetching and managing GPUs from the Marechai API
|
||||||
|
/// </summary>
|
||||||
|
public class GpusService
|
||||||
|
{
|
||||||
|
private readonly ApiClient _apiClient;
|
||||||
|
private readonly ILogger<GpusService> _logger;
|
||||||
|
|
||||||
|
public GpusService(ApiClient apiClient, ILogger<GpusService> logger)
|
||||||
|
{
|
||||||
|
_apiClient = apiClient;
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Fetches all GPUs from the API
|
||||||
|
/// </summary>
|
||||||
|
public async Task<List<GpuDto>> GetAllGpusAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Fetching all GPUs from API");
|
||||||
|
|
||||||
|
List<GpuDto> gpus = await _apiClient.Gpus.GetAsync();
|
||||||
|
|
||||||
|
if(gpus == null) return [];
|
||||||
|
|
||||||
|
_logger.LogInformation("Successfully fetched {Count} total GPUs", gpus.Count);
|
||||||
|
|
||||||
|
return gpus;
|
||||||
|
}
|
||||||
|
catch(Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Error fetching all GPUs from API");
|
||||||
|
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Fetches a single GPU by ID from the API
|
||||||
|
/// </summary>
|
||||||
|
public async Task<GpuDto?> GetGpuByIdAsync(int gpuId)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Fetching GPU {GpuId} from API", gpuId);
|
||||||
|
|
||||||
|
GpuDto? gpu = await _apiClient.Gpus[gpuId].GetAsync();
|
||||||
|
|
||||||
|
if(gpu == null)
|
||||||
|
{
|
||||||
|
_logger.LogWarning("GPU {GpuId} not found", gpuId);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
_logger.LogInformation("Successfully fetched GPU {GpuId}: {GpuName}", gpuId, gpu.Name);
|
||||||
|
|
||||||
|
return gpu;
|
||||||
|
}
|
||||||
|
catch(Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Error fetching GPU {GpuId} from API", gpuId);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user