216 lines
9.6 KiB
Plaintext
216 lines
9.6 KiB
Plaintext
@using RobotNet10.RobotApp.Client.Shared.Devices
|
|
@using Microsoft.AspNetCore.Components
|
|
@using MudBlazor
|
|
|
|
<MudCard Elevation="1" Class="mb-2">
|
|
<MudCardContent Class="pa-2">
|
|
@* Compact Header *@
|
|
<MudStack Row="true" AlignItems="@AlignItems.Center" Justify="Justify.SpaceBetween" Spacing="1" Class="mb-1">
|
|
<MudStack Row="true" AlignItems="@AlignItems.Center" Spacing="1">
|
|
<MudIcon Icon="@GetDeviceIcon()" Color="@GetStatusColor()" Size="Size.Small" />
|
|
<div>
|
|
<MudText Typo="Typo.body2" Style="font-weight: 600; line-height: 1.2;">@Device.DeviceName</MudText>
|
|
<MudText Typo="Typo.caption" Color="Color.Secondary" Style="line-height: 1;">@Device.DeviceId</MudText>
|
|
</div>
|
|
</MudStack>
|
|
<MudStack Row="true" AlignItems="@AlignItems.Center" Spacing="1">
|
|
<MudChip T="string" Size="Size.Small" Color="@GetStatusColor()" Variant="Variant.Filled" Style="font-size: 0.7rem;">
|
|
@Device.Status.ToString()
|
|
</MudChip>
|
|
<MudIconButton Icon="@Icons.Material.Filled.Settings"
|
|
Size="Size.Small"
|
|
Color="Color.Primary"
|
|
Variant="Variant.Text"
|
|
OnClick="NavigateToDeviceManagement"
|
|
title="Manage Device" />
|
|
</MudStack>
|
|
</MudStack>
|
|
|
|
@* Compact Info Grid - 2 columns *@
|
|
<MudGrid Spacing="1" Class="mt-1">
|
|
@* Device Type *@
|
|
<MudItem xs="6">
|
|
<MudStack Row="true" AlignItems="@AlignItems.Center" Spacing="1">
|
|
<MudText Typo="Typo.caption" Color="Color.Secondary" Style="min-width: 60px;">Type:</MudText>
|
|
<MudChip T="string" Size="Size.Small" Variant="Variant.Text" Style="font-size: 0.7rem; height: 20px;">@Device.DeviceType</MudChip>
|
|
</MudStack>
|
|
</MudItem>
|
|
|
|
@* Connection Status *@
|
|
<MudItem xs="6">
|
|
<MudStack Row="true" AlignItems="@AlignItems.Center" Spacing="1">
|
|
<MudText Typo="Typo.caption" Color="Color.Secondary" Style="min-width: 60px;">Status:</MudText>
|
|
<MudIcon Icon="@(Device.IsConnected ? Icons.Material.Filled.CheckCircle : Icons.Material.Filled.Cancel)"
|
|
Color="@(Device.IsConnected ? Color.Success : Color.Error)"
|
|
Size="Size.Small" Style="width: 16px; height: 16px;" />
|
|
<MudText Typo="Typo.caption">@(Device.IsConnected ? "Yes" : "No")</MudText>
|
|
</MudStack>
|
|
</MudItem>
|
|
|
|
@* Last Update - Compact format *@
|
|
<MudItem xs="12">
|
|
<MudStack Row="true" AlignItems="@AlignItems.Center" Spacing="1">
|
|
<MudText Typo="Typo.caption" Color="Color.Secondary" Style="min-width: 60px;">Updated:</MudText>
|
|
<MudText Typo="Typo.caption">@Device.LastUpdateTime.ToString("MM-dd HH:mm:ss")</MudText>
|
|
</MudStack>
|
|
</MudItem>
|
|
|
|
@* Reconnect Attempts - Only show if > 0 *@
|
|
@if (Device.ReconnectAttemptCount > 0)
|
|
{
|
|
<MudItem xs="12">
|
|
<MudStack Row="true" AlignItems="@AlignItems.Center" Spacing="1">
|
|
<MudText Typo="Typo.caption" Color="Color.Secondary" Style="min-width: 60px;">Retries:</MudText>
|
|
<MudChip T="int" Size="Size.Small" Color="Color.Warning" Style="font-size: 0.7rem; height: 20px;">@Device.ReconnectAttemptCount</MudChip>
|
|
</MudStack>
|
|
</MudItem>
|
|
}
|
|
</MudGrid>
|
|
|
|
@* Error Message - Compact *@
|
|
@if (!string.IsNullOrWhiteSpace(Device.LastError))
|
|
{
|
|
<MudAlert Severity="Severity.Error" Dense="true" Class="mt-1" Style="padding: 4px 8px;">
|
|
<MudText Typo="Typo.caption" Style="line-height: 1.2;">@Device.LastError</MudText>
|
|
</MudAlert>
|
|
}
|
|
|
|
@* Properties - Collapsed by default, only show count *@
|
|
@if (Device.Properties.Any())
|
|
{
|
|
<MudExpansionPanels Dense="true" Class="mt-1">
|
|
<MudExpansionPanel Text="@($"Properties ({Device.Properties.Count})")" Icon="@Icons.Material.Filled.Info" Style="font-size: 0.75rem;">
|
|
<MudSimpleTable Dense="true" Style="font-size: 0.7rem;">
|
|
<thead>
|
|
<tr>
|
|
<th style="padding: 4px;">Property</th>
|
|
<th style="padding: 4px;">Value</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@foreach (var prop in GetDisplayedProperties().Take(5))
|
|
{
|
|
<tr>
|
|
<td style="padding: 2px 4px;">
|
|
<MudText Typo="Typo.caption">@prop.DisplayName</MudText>
|
|
</td>
|
|
<td style="padding: 2px 4px;">
|
|
@if (Device.Properties.TryGetValue(prop.Key, out var value))
|
|
{
|
|
<MudText Typo="Typo.caption">
|
|
@FormatPropertyValue(value, prop)
|
|
</MudText>
|
|
}
|
|
</td>
|
|
</tr>
|
|
}
|
|
@if (Device.Properties.Count > 5)
|
|
{
|
|
<tr>
|
|
<td colspan="2" style="padding: 2px 4px; text-align: center;">
|
|
<MudText Typo="Typo.caption" Color="Color.Secondary">
|
|
... and @(Device.Properties.Count - 5) more
|
|
</MudText>
|
|
</td>
|
|
</tr>
|
|
}
|
|
</tbody>
|
|
</MudSimpleTable>
|
|
</MudExpansionPanel>
|
|
</MudExpansionPanels>
|
|
}
|
|
</MudCardContent>
|
|
</MudCard>
|
|
|
|
@code {
|
|
[Parameter, EditorRequired]
|
|
public DeviceDto Device { get; set; } = null!;
|
|
|
|
[Inject]
|
|
private NavigationManager NavigationManager { get; set; } = null!;
|
|
|
|
private void NavigateToDeviceManagement()
|
|
{
|
|
var deviceType = GetDeviceTypeRoute(Device.DeviceType);
|
|
var deviceId = Uri.EscapeDataString(Device.DeviceId);
|
|
NavigationManager.NavigateTo($"/devices/{deviceType}/{deviceId}");
|
|
}
|
|
|
|
private string GetDeviceTypeRoute(DeviceType deviceType)
|
|
{
|
|
return deviceType switch
|
|
{
|
|
DeviceType.Lidar => "lidar",
|
|
DeviceType.Imu => "imu",
|
|
DeviceType.Battery => "battery",
|
|
DeviceType.ModbusTcp => "modbustcp",
|
|
DeviceType.RfHandle => "rfhandle",
|
|
DeviceType.CameraQr => "cameraqr",
|
|
DeviceType.CiA402Servo => "cia402servo",
|
|
_ => deviceType.ToString().ToLowerInvariant()
|
|
};
|
|
}
|
|
|
|
private string GetDeviceIcon()
|
|
{
|
|
return Device.DeviceType switch
|
|
{
|
|
DeviceType.Lidar => Icons.Material.Filled.Radar,
|
|
DeviceType.Imu => Icons.Material.Filled.Explore,
|
|
DeviceType.Battery => Icons.Material.Filled.BatteryFull,
|
|
DeviceType.ModbusTcp => Icons.Material.Filled.Lan,
|
|
DeviceType.RfHandle => Icons.Material.Filled.RadioButtonChecked,
|
|
DeviceType.CameraQr => Icons.Material.Filled.QrCodeScanner,
|
|
DeviceType.CiA402Servo => Icons.Material.Filled.Settings,
|
|
_ => Icons.Material.Filled.Devices
|
|
};
|
|
}
|
|
|
|
private Color GetStatusColor()
|
|
{
|
|
return Device.Status switch
|
|
{
|
|
DeviceStatus.Connected => Color.Success,
|
|
DeviceStatus.Connecting => Color.Info,
|
|
DeviceStatus.Disconnecting => Color.Warning,
|
|
DeviceStatus.Disconnected => Color.Default,
|
|
DeviceStatus.Reconnecting => Color.Warning,
|
|
DeviceStatus.Error => Color.Error,
|
|
DeviceStatus.Initializing => Color.Info,
|
|
_ => Color.Default
|
|
};
|
|
}
|
|
|
|
private IEnumerable<PropertyDescription> GetDisplayedProperties()
|
|
{
|
|
return Device.PropertyDescriptions
|
|
.OrderBy(p => p.DisplayOrder)
|
|
.ThenBy(p => p.Category ?? "")
|
|
.ThenBy(p => p.DisplayName);
|
|
}
|
|
|
|
private string FormatPropertyValue(string value, PropertyDescription prop)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(value))
|
|
return "-";
|
|
|
|
if (prop.DataType == "number" && double.TryParse(value, out var numValue))
|
|
{
|
|
if (!string.IsNullOrWhiteSpace(prop.Format))
|
|
{
|
|
try
|
|
{
|
|
return string.Format(prop.Format, numValue) + (prop.Unit != null ? $" {prop.Unit}" : "");
|
|
}
|
|
catch
|
|
{
|
|
return value + (prop.Unit != null ? $" {prop.Unit}" : "");
|
|
}
|
|
}
|
|
return value + (prop.Unit != null ? $" {prop.Unit}" : "");
|
|
}
|
|
|
|
return value + (prop.Unit != null ? $" {prop.Unit}" : "");
|
|
}
|
|
}
|