Skip to content

Commit f6a9f52

Browse files
committed
Refactor headers, health UI, and workflow type handling
- Refactored HeaderTitle to support optional icons and improved layout; updated all usages to provide relevant icons for visual distinction. - Enhanced Health page: added card layout, status chips with color/icons, refresh button, improved loading/empty states, and client-side filtering. - Changed Health nav icon to MonitorHeart for consistency. - Made "Add workflow" button more prominent in Workflows page. - Refactored SearchablePluginsList to use "Type:Version" string for OnItemClick and removed default LocalFileSystem entry. - Simplified WorkflowTask.Type to a string ("Plugin:Version") and updated WorkflowDesigner logic accordingly. - Performed minor code cleanups and consistency improvements. #91
1 parent f4cf0c9 commit f6a9f52

12 files changed

Lines changed: 232 additions & 114 deletions

File tree

src/Components/Layout/HeaderTitle.razor

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,43 @@
1-
<MudText Typo="Typo.h5" Color="Color.Default" Class="@CombineClass("mb-0")">
2-
@Title
3-
</MudText>
4-
<MudText Typo="Typo.subtitle2" Class="@CombineClass("mb-5 gray-subtitle")">
5-
@Description
6-
</MudText>
1+
@using MudBlazor
2+
3+
<MudStack Row="true"
4+
Spacing="2"
5+
AlignItems="AlignItems.Baseline"
6+
Class="@CombineClass("mb-6")">
7+
8+
@if (!string.IsNullOrWhiteSpace(Icon))
9+
{
10+
<MudAvatar Size="Size.Medium"
11+
Color="@IconColor"
12+
Variant="Variant.Filled">
13+
<MudIcon Icon="@Icon" />
14+
</MudAvatar>
15+
}
16+
17+
<MudStack Direction="Column" Spacing="1" AlignItems="AlignItems.Baseline">
18+
<MudText Typo="Typo.h5" Class="font-weight-medium">
19+
@Title
20+
</MudText>
21+
22+
@if (!string.IsNullOrWhiteSpace(Description))
23+
{
24+
<MudText Typo="Typo.body2" Class="gray-subtitle">
25+
@Description
26+
</MudText>
27+
}
28+
</MudStack>
29+
</MudStack>
730

831
@code {
932
[Parameter] public required string Title { get; set; }
1033
[Parameter] public string? Description { get; set; }
1134
[Parameter] public string? Class { get; set; }
1235

36+
// Optional icon parameters
37+
[Parameter] public string? Icon { get; set; }
38+
[Parameter] public Color IconColor { get; set; } = Color.Default;
39+
[Parameter] public Size IconSize { get; set; } = Size.Medium;
40+
1341
private string CombineClass(string defaultClass)
1442
{
1543
// If user provided a class, combine it with default class

src/Components/Layout/NavMenu.razor

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
<MudDivider />
1818
<MudNavLink Href="/health"
1919
Match="NavLinkMatch.Prefix"
20-
Icon="@Icons.Material.Filled.HealthAndSafety">Health</MudNavLink>
20+
Icon="@Icons.Material.Filled.MonitorHeart">Health</MudNavLink>
2121
<MudDivider />
2222
<MudNavLink Href="/version"
2323
Match="NavLinkMatch.Prefix"

src/Components/Pages/AllLogs/Logs.razor

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,12 @@
1111

1212
<PageTitle>FlowSynx Logs</PageTitle>
1313

14-
<HeaderTitle Title="Logs" Description="Search and browse execution logs with filtering options." />
14+
<HeaderTitle
15+
Title="Logs"
16+
Description="Search and browse execution logs with filtering options."
17+
Icon="@Icons.Material.Filled.ReceiptLong"
18+
IconColor="Color.Primary"
19+
IconSize="Size.Large" />
1520

1621
<MudPaper Class="px-4 pb-4 mb-4">
1722
<MudForm>

src/Components/Pages/Health/Health.razor

Lines changed: 134 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -10,36 +10,78 @@
1010

1111
<PageTitle>FlowSynx HealthCheck</PageTitle>
1212

13-
<HeaderTitle Title="Health Check" Description="Checking the Health of the FlowSynx System and Its Components" />
14-
15-
<MudTable
16-
T="IndividualHealthCheckResponse"
17-
ServerData="LoadData"
18-
Dense="true"
19-
Hover="true"
20-
Bordered="false"
21-
Striped="false"
22-
@ref="_table" LoadingProgressColor="Color.Primary">
23-
<HeaderContent>
24-
<MudTh>Component</MudTh>
25-
<MudTh>Description</MudTh>
26-
<MudTh>Status</MudTh>
27-
</HeaderContent>
28-
<RowTemplate>
29-
<MudTd DataLabel="Component"><b>@context.Component</b></MudTd>
30-
<MudTd DataLabel="Description">@context.Description</MudTd>
31-
<MudTd DataLabel="Status">@context.Status</MudTd>
32-
</RowTemplate>
33-
<NoRecordsContent>
34-
<MudText>No matching records found</MudText>
35-
</NoRecordsContent>
36-
<LoadingContent>
37-
<MudText>Loading...</MudText>
38-
</LoadingContent>
39-
</MudTable>
13+
<HeaderTitle
14+
Title="Health Check"
15+
Description="Checking the Health of the FlowSynx System and Its Components"
16+
Icon="@Icons.Material.Filled.MonitorHeart"
17+
IconColor="Color.Primary"
18+
IconSize="Size.Large" />
19+
20+
<MudContainer MaxWidth="MaxWidth.False" Class="pa-0">
21+
<MudCard Elevation="1">
22+
<MudTable
23+
T="IndividualHealthCheckResponse"
24+
ServerData="LoadData"
25+
Dense="true"
26+
Hover="true"
27+
Bordered="false"
28+
Striped="false"
29+
@ref="_table"
30+
LoadingProgressColor="Color.Primary"
31+
RowClassFunc="GetRowClass">
32+
<ToolBarContent>
33+
<MudButton Variant="Variant.Outlined"
34+
Color="Color.Default"
35+
OnClick="RefreshAsync"
36+
StartIcon="@Icons.Material.Filled.Refresh"
37+
Size="@Size.Small">Refresh</MudButton>
38+
</ToolBarContent>
39+
<HeaderContent>
40+
<MudTh>Component</MudTh>
41+
<MudTh>Description</MudTh>
42+
<MudTh>Status</MudTh>
43+
</HeaderContent>
44+
<RowTemplate>
45+
<MudTd DataLabel="Component">
46+
<MudStack Direction="Row" Spacing="1">
47+
<MudText Typo="Typo.body1"><b>@context.Component</b></MudText>
48+
</MudStack>
49+
</MudTd>
50+
<MudTd DataLabel="Description">
51+
<MudText Typo="Typo.body2">@context.Description</MudText>
52+
</MudTd>
53+
<MudTd DataLabel="Status">
54+
<MudChip T="string" Color="@GetStatusColor(context.Status)" Variant="Variant.Filled" Icon="@GetStatusIcon(context.Status)" Dense="true">
55+
@context.Status
56+
</MudChip>
57+
</MudTd>
58+
</RowTemplate>
59+
<NoRecordsContent>
60+
<MudEmptyState Icon="@Icons.Material.Outlined.SearchOff"
61+
Title="No matching records"
62+
Description="Try adjusting your search or refresh the data." />
63+
</NoRecordsContent>
64+
<LoadingContent>
65+
<MudStack Direction="Row" Spacing="2" Class="pa-4">
66+
<MudProgressCircular Color="Color.Primary" />
67+
<MudText>Loading…</MudText>
68+
</MudStack>
69+
</LoadingContent>
70+
</MudTable>
71+
</MudCard>
72+
</MudContainer>
4073

4174
@code {
4275
private MudTable<IndividualHealthCheckResponse>? _table;
76+
private string? _search;
77+
private int _healthyCount;
78+
private int _degradedCount;
79+
private int _unhealthyCount;
80+
81+
private async Task RefreshAsync()
82+
{
83+
await (_table?.ReloadServerData() ?? Task.CompletedTask);
84+
}
4385

4486
private async Task<TableData<IndividualHealthCheckResponse>> LoadData(
4587
TableState state,
@@ -55,22 +97,78 @@
5597
return new TableData<IndividualHealthCheckResponse> { Items = [], TotalItems = 0 };
5698
}
5799

58-
var plugins = result.Payload.HealthChecks;
100+
var plugins = result.Payload.HealthChecks?.ToList() ?? [];
101+
102+
// Apply search filter (client-side) using table state or local search box
103+
var searchTerm = !string.IsNullOrWhiteSpace(_search) ? _search : "";
104+
if (!string.IsNullOrWhiteSpace(searchTerm))
105+
{
106+
var s = searchTerm.Trim();
107+
plugins = plugins.Where(p =>
108+
(p.Component?.Contains(s, StringComparison.OrdinalIgnoreCase) ?? false) ||
109+
(p.Description?.Contains(s, StringComparison.OrdinalIgnoreCase) ?? false) ||
110+
(p.Status?.Contains(s, StringComparison.OrdinalIgnoreCase) ?? false)).ToList();
111+
}
112+
113+
// Compute summary counts
114+
_healthyCount = plugins.Count(p => EqualsIgnoreCase(p.Status, "Healthy") || EqualsIgnoreCase(p.Status, "Ok") || EqualsIgnoreCase(p.Status, "Pass"));
115+
_degradedCount = plugins.Count(p => EqualsIgnoreCase(p.Status, "Degraded") || EqualsIgnoreCase(p.Status, "Warn") || EqualsIgnoreCase(p.Status, "Warning"));
116+
_unhealthyCount = plugins.Count(p => EqualsIgnoreCase(p.Status, "Unhealthy") || EqualsIgnoreCase(p.Status, "Fail") || EqualsIgnoreCase(p.Status, "Error"));
59117

60118
return new TableData<IndividualHealthCheckResponse>
61-
{
62-
Items = plugins,
63-
TotalItems = plugins.Count()
64-
};
119+
{
120+
Items = plugins,
121+
TotalItems = plugins.Count
122+
};
65123
}
66124
catch (Exception ex)
67125
{
68126
SnackBar.Add($"Exception occurred: {ex.Message}", Severity.Error);
127+
_healthyCount = 0;
128+
_degradedCount = 0;
129+
_unhealthyCount = 0;
130+
69131
return new TableData<IndividualHealthCheckResponse>
70-
{
71-
Items = [],
72-
TotalItems = 0
73-
};
132+
{
133+
Items = [],
134+
TotalItems = 0
135+
};
74136
}
75137
}
138+
139+
private static Color GetStatusColor(string? status)
140+
{
141+
if (status is null) return Color.Default;
142+
return status.ToLowerInvariant() switch
143+
{
144+
"healthy" or "ok" or "pass" => Color.Success,
145+
"degraded" or "warn" or "warning" => Color.Warning,
146+
"unhealthy" or "fail" or "error" => Color.Error,
147+
_ => Color.Info
148+
};
149+
}
150+
151+
private static string GetStatusIcon(string? status)
152+
{
153+
if (status is null) return Icons.Material.Outlined.Info;
154+
return status.ToLowerInvariant() switch
155+
{
156+
"healthy" or "ok" or "pass" => Icons.Material.Filled.CheckCircle,
157+
"degraded" or "warn" or "warning" => Icons.Material.Filled.Warning,
158+
"unhealthy" or "fail" or "error" => Icons.Material.Filled.Error,
159+
_ => Icons.Material.Outlined.Info
160+
};
161+
}
162+
163+
private static string GetRowClass(IndividualHealthCheckResponse item, int rowNumber)
164+
=> GetStatusColor(item.Status) switch
165+
{
166+
Color.Success => "row-success",
167+
Color.Warning => "row-warning",
168+
Color.Error => "row-error",
169+
_ => string.Empty
170+
};
171+
172+
private static bool EqualsIgnoreCase(string? a, string b)
173+
=> string.Equals(a, b, StringComparison.OrdinalIgnoreCase);
76174
}

src/Components/Pages/Plugins/Plugins.razor

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,12 @@
1111

1212
<PageTitle>FlowSynx Plugins</PageTitle>
1313

14-
<HeaderTitle Title="Installed plugins" Description="This section enumerates all plugins currently installed and available within the FlowSynx system. Each entry includes the plugin name, version, type, and a brief description of its functionality. " />
14+
<HeaderTitle
15+
Title="Managing plugins"
16+
Description="This section enumerates all plugins currently installed and available within the FlowSynx system. Each entry includes the plugin name, version, type, and a brief description of its functionality."
17+
Icon="@Icons.Material.Filled.GridView"
18+
IconColor="Color.Primary"
19+
IconSize="Size.Large" />
1520

1621
<MudTable T="PluginsListResponse"
1722
ServerData="LoadData"

src/Components/Pages/Version/Version.razor

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,12 @@
66

77
<PageTitle>FlowSynx Version</PageTitle>
88

9-
<HeaderTitle Title="Version" Description="Details about the currently deployed version of the FlowSynx system" />
9+
<HeaderTitle
10+
Title="Version"
11+
Description="Details about the currently deployed version of the FlowSynx system"
12+
Icon="@Icons.Material.Filled.Info"
13+
IconColor="Color.Primary"
14+
IconSize="Size.Large" />
1015

1116
<MudTable T="VersionResponse" ServerData="LoadData" Dense="true" Hover="true" Bordered="false" Striped="false" @ref="_table" LoadingProgressColor="Color.Primary">
1217
<HeaderContent>

src/Components/Pages/Workflows/AddWorkflow.razor

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,12 @@
1111
@inject NavigationManager Navigation
1212

1313
<PageTitle>FlowSynx add workflow</PageTitle>
14-
<HeaderTitle Title="Workflow designer" Description="A visual interface to create, edit, and manage workflow." />
14+
<HeaderTitle
15+
Title="Workflow designer"
16+
Description="A visual interface to create, edit, and manage workflow."
17+
Icon="@Icons.Material.Filled.DesignServices"
18+
IconColor="Color.Primary"
19+
IconSize="Size.Large" />
1520

1621
<MudTabs Outlined="true" Position="Position.Top" Rounded="true" Border="true"
1722
ApplyEffectsToContainer="true" Class="mb-4">

src/Components/Pages/Workflows/ManageWorkflow.razor

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,12 @@
1313
@inject NavigationManager Navigation
1414

1515
<PageTitle>FlowSynx manage workflow</PageTitle>
16-
<HeaderTitle Title="Workflow designer" Description="A visual interface to create, edit, and manage workflow." />
16+
17+
<HeaderTitle Title="Workflow designer"
18+
Description="A visual interface to create, edit, and manage workflow."
19+
Icon="@Icons.Material.Filled.DesignServices"
20+
IconColor="Color.Primary"
21+
IconSize="Size.Large" />
1722

1823
<MudTabs Outlined="true"
1924
Position="Position.Top"

src/Components/Pages/Workflows/SearchablePluginsList.razor

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,9 @@
4444
<MudList T="object" Dense="true">
4545
@foreach (var version in item.Versions)
4646
{
47+
var pluginType = $"{item.Type}:{version}";
4748
<MudListItem T="object"
48-
OnClick="@(() => OnItemClick.InvokeAsync((item.Type, version)))">
49+
OnClick="@(() => OnItemClick.InvokeAsync(pluginType))">
4950
<MudText Typo="Typo.body2">Version: @version</MudText>
5051
</MudListItem>
5152
}
@@ -57,15 +58,14 @@
5758
</MudExpansionPanels>
5859

5960
@code {
60-
[Parameter] public EventCallback<(string Type, string Version)> OnItemClick { get; set; }
61+
[Parameter] public EventCallback<string> OnItemClick { get; set; }
6162

6263
private List<PluginTypeInfo> Items { get; set; } = new();
6364
private string _search = string.Empty;
6465

6566
protected override async Task OnInitializedAsync()
6667
{
6768
Items = await LoadPluginTypes(CancellationToken.None);
68-
Items.Insert(0, new PluginTypeInfo { Type = "LocalFileSystem", Versions = new List<string>() });
6969
}
7070

7171
private List<PluginTypeInfo> FilteredItems =>
@@ -136,11 +136,12 @@
136136
if (plugin.Versions.Any())
137137
{
138138
var latest = plugin.Versions.First(); // versions are sorted descending
139-
OnItemClick.InvokeAsync((plugin.Type, latest));
139+
var pluginType = $"{plugin.Type}:{latest}";
140+
OnItemClick.InvokeAsync(pluginType);
140141
}
141142
else
142143
{
143-
OnItemClick.InvokeAsync((plugin.Type, string.Empty));
144+
OnItemClick.InvokeAsync($"{plugin.Type}:latest");
144145
}
145146
}
146147

0 commit comments

Comments
 (0)