refactor(web): MudBlazor → Fluent UI Blazor v5 마이그레이션 완료
Quant Engine CI/CD Pipeline / validate-core (push) Failing after 10s
WBS-9.3 - NULL Policy CI Gate / NULL Policy Validation (push) Failing after 8s
Quant Engine CI/CD Pipeline / validate-ui-and-storage (push) Has been skipped
Snapshot Admin Deployment / build-and-deploy (push) Failing after 1m0s
Deploy to Production / Build & Deploy to Production (push) Successful in 1m21s

**주요 변경사항:**
- NuGet: MudBlazor 6.10.0 → Microsoft.FluentUI.AspNetCore.Components 5.0.0-rc.4-26177.1 변경
- Program.cs: MudBlazor DI → Fluent UI DI 등록
- App.razor: CSS/JS 라이브러리 및 프로바이더 변경
- MainLayout.razor: MudLayout → FluentStack 기반 재구성
  - FluentHeader 헤더 적용
  - 네비게이션 사이드바 토글 기능
  - Flexbox 레이아웃
- NavMenu.razor: MudNavMenu/MudNavLink → FluentNavMenu/FluentNavLink
- Dashboard.razor: MudBlazor 모든 컴포넌트 → Fluent UI v5로 변환
  - MudCard → FluentCard
  - MudGrid → FluentStack (Wrap)
  - MudText → HTML (h1, p, span)
  - MudChip → FluentBadge
  - MudTable → FluentDataGrid
  - MudAlert → div (커스텀 스타일)
- Operations.razor: 동일 패턴 적용
- _Imports.razor: Fluent UI 네임스페이스 추가

**빌드 결과:**  SUCCESS (0 errors, 5 warnings)

**다음 단계:** Stage 2 - Python → .NET 마이그레이션

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-06-29 23:11:18 +09:00
parent aad4788e84
commit 459edf5940
243 changed files with 2857 additions and 544 deletions
@@ -6,10 +6,9 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<base href="/quant/" />
<ResourcePreloader />
<!-- MudBlazor CSS -->
<!-- Fluent UI CSS -->
<link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" rel="stylesheet" />
<link href="_content/MudBlazor/MudBlazor.min.css" rel="stylesheet" />
<link rel="stylesheet" href="@Assets["lib/bootstrap/dist/css/bootstrap.min.css"]" />
<link href="_content/Microsoft.FluentUI.AspNetCore.Components/css/fluent-components.css" rel="stylesheet" />
<link rel="stylesheet" href="@Assets["app.css"]" />
<link rel="stylesheet" href="@Assets["QuantEngine.Web.styles.css"]" />
<ImportMap />
@@ -18,15 +17,13 @@
</head>
<body>
<MudThemeProvider />
<MudDialogProvider />
<MudSnackbarProvider />
<FluentDesignSystemProvider>
<Routes />
<ReconnectModal />
</FluentDesignSystemProvider>
<Routes />
<ReconnectModal />
<!-- MudBlazor JS -->
<script src="_content/MudBlazor/MudBlazor.min.js"></script>
<!-- Fluent UI JS -->
<script src="_content/Microsoft.FluentUI.AspNetCore.Components/js/fluent-components.js"></script>
<script src="@Assets["_framework/blazor.web.js"]"></script>
</body>
@@ -2,37 +2,42 @@
@inject Microsoft.AspNetCore.Hosting.IWebHostEnvironment WebHostEnvironment
@using System.IO
@using System.Text.Json
@using Microsoft.FluentUI.AspNetCore.Components
<MudLayout>
<MudAppBar Elevation="1">
<MudIconButton Icon="@Icons.Material.Filled.Menu" Color="Color.Inherit" Edge="Edge.Start" OnClick="@((e) => DrawerToggle())" />
<MudSpacer />
<MudText Typo="Typo.h5" Class="ml-3">Quant Engine</MudText>
<MudSpacer />
<MudIconButton Icon="@Icons.Material.Filled.Settings" Color="Color.Inherit" />
</MudAppBar>
<FluentStack Orientation="Orientation.Vertical" Class="h-100 w-100">
<!-- Header -->
<FluentHeader>
<FluentStack Orientation="Orientation.Horizontal" VerticalAlignment="VerticalAlignment.Center"
Style="width: 100%; padding: 8px 16px; gap: 16px;">
<FluentButton OnClick="@(() => navOpen = !navOpen)"
Title="Toggle Navigation"
Style="background: transparent; border: none; cursor: pointer;">
</FluentButton>
<h1 style="margin: 0; font-size: 20px; font-weight: 600;">QuantEngine v@appVersion</h1>
</FluentStack>
</FluentHeader>
<MudDrawer @bind-Open="@drawerOpen" Elevation="1" Class="d-flex flex-column h-100">
<MudDrawerHeader>
<MudText Typo="Typo.h6">Menu</MudText>
</MudDrawerHeader>
<NavMenu />
<MudSpacer />
<div class="px-4 py-3 mt-auto" style="border-top: 1px solid rgba(0,0,0,0.08); font-size: 11px; color: var(--mud-palette-text-secondary); line-height: 1.5; background-color: rgba(0,0,0,0.01);">
<div style="font-weight: 500; margin-bottom: 2px;">QuantEngine v@appVersion</div>
<div style="font-size: 10px; opacity: 0.85;">배포: @buildTime</div>
</div>
</MudDrawer>
<!-- Main Content Area -->
<FluentStack Orientation="Orientation.Horizontal" Class="flex-1" Style="overflow: hidden;">
<!-- Navigation Sidebar -->
@if (navOpen)
{
<nav style="width: 240px; background: var(--neutral-layer-1); border-right: 1px solid var(--neutral-stroke-1); padding: 12px; overflow-y: auto;">
<NavMenu />
<div style="margin-top: auto; padding-top: 12px; border-top: 1px solid var(--neutral-stroke-1); margin-top: 12px; font-size: 11px; color: var(--neutral-foreground-3); line-height: 1.5;">
<div style="font-weight: 500; margin-bottom: 2px;">QuantEngine v@appVersion</div>
<div style="font-size: 10px; opacity: 0.85;">배포: @buildTime</div>
</div>
</nav>
}
<MudMainContent>
<MudContainer MaxWidth="MaxWidth.Large" Class="my-4">
<!-- Page Content -->
<FluentStack Orientation="Orientation.Vertical" Class="flex-1" Style="overflow-y: auto; padding: 24px;">
@Body
</MudContainer>
</MudMainContent>
</MudLayout>
</FluentStack>
</FluentStack>
</FluentStack>
<div id="blazor-error-ui" data-nosnippet>
<div class="alert alert-danger" role="alert">
@@ -41,16 +46,24 @@
</div>
</div>
<style>
.h-100 {
height: 100%;
}
.w-100 {
width: 100%;
}
.flex-1 {
flex: 1;
display: flex;
}
</style>
@code {
private bool drawerOpen = true;
private bool navOpen = true;
private string appVersion = "Local Debug";
private string buildTime = "N/A";
private void DrawerToggle()
{
drawerOpen = !drawerOpen;
}
protected override void OnInitialized()
{
try
@@ -61,7 +74,7 @@
var jsonContent = File.ReadAllText(versionFilePath);
using var doc = System.Text.Json.JsonDocument.Parse(jsonContent);
var root = doc.RootElement;
if (root.TryGetProperty("version", out var versionProp))
{
appVersion = versionProp.GetString() ?? "Local Debug";
@@ -1,8 +1,10 @@
<MudNavMenu>
<MudNavLink Href="/" Match="NavLinkMatch.All" Icon="@Icons.Material.Filled.Dashboard">
@using Microsoft.FluentUI.AspNetCore.Components
<FluentNavMenu>
<FluentNavLink Href="/" Match="NavLinkMatch.All">
Dashboard
</MudNavLink>
<MudNavLink Href="/operations" Match="NavLinkMatch.Prefix" Icon="@Icons.Material.Filled.Assessment">
</FluentNavLink>
<FluentNavLink Href="/operations" Match="NavLinkMatch.Prefix">
Operations
</MudNavLink>
</MudNavMenu>
</FluentNavLink>
</FluentNavMenu>
@@ -4,117 +4,90 @@
<PageTitle>Quant Engine - Dashboard</PageTitle>
<MudText Typo="Typo.h4" Class="mb-2">Quant Engine</MudText>
<MudText Typo="Typo.body2" Color="Color.Secondary" Class="mb-4">
<h1 style="margin: 0 0 8px 0; font-size: 28px; font-weight: 600;">Quant Engine</h1>
<p style="margin: 0 0 16px 0; color: var(--neutral-foreground-2); font-size: 14px;">
루트 화면은 운영 진입점입니다. 가짜 성과 수치 없이 현재 스냅샷 상태와 리포트 경로만 보여줍니다.
</MudText>
</p>
<MudGrid Class="mb-4">
<MudItem xs="12" sm="6" md="4">
<MudCard Class="h-100">
<MudCardContent>
<MudText Typo="Typo.body2" Color="Color.Secondary">Operational Report</MudText>
<MudText Typo="Typo.h6" Class="mt-2">@ReportStateLabel</MudText>
<MudText Typo="Typo.caption">@ReportPath</MudText>
</MudCardContent>
</MudCard>
</MudItem>
<MudItem xs="12" sm="6" md="4">
<MudCard Class="h-100">
<MudCardContent>
<MudText Typo="Typo.body2" Color="Color.Secondary">Sections</MudText>
<MudText Typo="Typo.h6" Class="mt-2">@SectionCountLabel</MudText>
<MudText Typo="Typo.caption">Temp/operational_report.json</MudText>
</MudCardContent>
</MudCard>
</MudItem>
<MudItem xs="12" sm="6" md="4">
<MudCard Class="h-100">
<MudCardContent>
<MudText Typo="Typo.body2" Color="Color.Secondary">Primary Route</MudText>
<MudButton Variant="Variant.Filled" Color="Color.Primary" Href="/operations" Class="mt-2">
Open Operations
</MudButton>
</MudCardContent>
</MudCard>
</MudItem>
</MudGrid>
<!-- Top 3 Cards -->
<FluentStack Orientation="Orientation.Horizontal" HorizontalGap="16" Wrap="true" Style="margin-bottom: 16px;">
<FluentCard Style="flex: 1; min-width: 200px;">
<div style="padding: 16px;">
<p style="margin: 0 0 8px 0; color: var(--neutral-foreground-2); font-size: 12px; font-weight: 500;">Operational Report</p>
<h3 style="margin: 0; font-size: 20px; font-weight: 600;">@ReportStateLabel</h3>
<p style="margin: 8px 0 0 0; color: var(--neutral-foreground-3); font-size: 12px;">@ReportPath</p>
</div>
</FluentCard>
<FluentCard Style="flex: 1; min-width: 200px;">
<div style="padding: 16px;">
<p style="margin: 0 0 8px 0; color: var(--neutral-foreground-2); font-size: 12px; font-weight: 500;">Sections</p>
<h3 style="margin: 0; font-size: 20px; font-weight: 600;">@SectionCountLabel</h3>
<p style="margin: 8px 0 0 0; color: var(--neutral-foreground-3); font-size: 12px;">Temp/operational_report.json</p>
</div>
</FluentCard>
<FluentCard Style="flex: 1; min-width: 200px;">
<div style="padding: 16px;">
<p style="margin: 0 0 8px 0; color: var(--neutral-foreground-2); font-size: 12px; font-weight: 500;">Primary Route</p>
<FluentButton Appearance="ButtonAppearance.Primary" Href="/operations" Style="margin-top: 8px;">
Open Operations
</FluentButton>
</div>
</FluentCard>
</FluentStack>
<MudGrid Class="mb-4">
<MudItem xs="12" md="7">
<MudCard Class="h-100">
<MudCardHeader>
<CardHeaderContent>
<MudText Typo="Typo.h6">Current State</MudText>
</CardHeaderContent>
</MudCardHeader>
<MudCardContent>
<MudStack Spacing="2">
<MudText Typo="Typo.body2"><strong>Status:</strong> <MudChip Size="Size.Small" Color="@ReportChipColor">@ReportChipLabel</MudChip></MudText>
<MudText Typo="Typo.body2"><strong>Generated:</strong> @GeneratedAtLabel</MudText>
<MudText Typo="Typo.body2"><strong>Source:</strong> @SourceLabel</MudText>
<MudText Typo="Typo.body2"><strong>Decision feed:</strong> @DecisionFeedLabel</MudText>
<MudText Typo="Typo.body2"><strong>Factor feed:</strong> @FactorFeedLabel</MudText>
<MudText Typo="Typo.body2"><strong>Raw feed:</strong> @RawFeedLabel</MudText>
</MudStack>
</MudCardContent>
</MudCard>
</MudItem>
<!-- Current State & Routing Notes -->
<FluentStack Orientation="Orientation.Horizontal" HorizontalGap="16" Wrap="true" Style="margin-bottom: 16px;">
<FluentCard Style="flex: 2; min-width: 300px;">
<div style="padding: 16px;">
<h3 style="margin: 0 0 12px 0; font-size: 16px; font-weight: 600;">Current State</h3>
<FluentStack Orientation="Orientation.Vertical" VerticalGap="8">
<p style="margin: 0; font-size: 14px;"><strong>Status:</strong> <FluentBadge Appearance="BadgeAppearance.Filled">@ReportChipLabel</FluentBadge></p>
<p style="margin: 0; font-size: 14px;"><strong>Generated:</strong> @GeneratedAtLabel</p>
<p style="margin: 0; font-size: 14px;"><strong>Source:</strong> @SourceLabel</p>
<p style="margin: 0; font-size: 14px;"><strong>Decision feed:</strong> @DecisionFeedLabel</p>
<p style="margin: 0; font-size: 14px;"><strong>Factor feed:</strong> @FactorFeedLabel</p>
<p style="margin: 0; font-size: 14px;"><strong>Raw feed:</strong> @RawFeedLabel</p>
</FluentStack>
</div>
</FluentCard>
<MudItem xs="12" md="5">
<MudCard Class="h-100">
<MudCardHeader>
<CardHeaderContent>
<MudText Typo="Typo.h6">Routing Notes</MudText>
</CardHeaderContent>
</MudCardHeader>
<MudCardContent>
<MudStack Spacing="2">
<MudText Typo="Typo.body2">- 운영 데이터는 snapshot 우선입니다.</MudText>
<MudText Typo="Typo.body2">- Excel/GAS 의존 문구는 운영 경로에서 제거 대상입니다.</MudText>
<MudText Typo="Typo.body2">- 숫자는 provenance 없으면 표시하지 않습니다.</MudText>
</MudStack>
</MudCardContent>
</MudCard>
</MudItem>
</MudGrid>
<FluentCard Style="flex: 1; min-width: 250px;">
<div style="padding: 16px;">
<h3 style="margin: 0 0 12px 0; font-size: 16px; font-weight: 600;">Routing Notes</h3>
<ul style="margin: 0; padding-left: 16px; font-size: 14px;">
<li>운영 데이터는 snapshot 우선입니다.</li>
<li>Excel/GAS 의존 문구는 운영 경로에서 제거 대상입니다.</li>
<li>숫자는 provenance 없으면 표시하지 않습니다.</li>
</ul>
</div>
</FluentCard>
</FluentStack>
<MudCard>
<MudCardHeader>
<CardHeaderContent>
<MudText Typo="Typo.h6">Coverage Summary</MudText>
</CardHeaderContent>
</MudCardHeader>
<MudCardContent>
<!-- Coverage Summary -->
<FluentCard>
<div style="padding: 16px;">
<h3 style="margin: 0 0 12px 0; font-size: 16px; font-weight: 600;">Coverage Summary</h3>
@if (Sections.Count == 0)
{
<MudAlert Severity="Severity.Warning" Variant="Variant.Outlined">
<div style="padding: 12px; background: var(--warning-background-1); border: 1px solid var(--warning-stroke-1); border-radius: 4px; color: var(--warning-foreground-1); font-size: 14px;">
DATA_MISSING: operational_report.json이 비어 있거나 아직 생성되지 않았습니다.
</MudAlert>
</div>
}
else
{
<MudTable Items="Sections" Hover="true" Striped="true" Dense="true">
<HeaderContent>
<MudTh>Name</MudTh>
<MudTh>Title</MudTh>
<MudTh>Preview</MudTh>
</HeaderContent>
<RowTemplate>
<MudTd>@context.Name</MudTd>
<MudTd>@context.Title</MudTd>
<MudTd>@context.Preview</MudTd>
</RowTemplate>
</MudTable>
<FluentDataGrid Items="@Sections.AsQueryable()">
<PropertyColumn Property="@(x => x.Name)" Title="Name" />
<PropertyColumn Property="@(x => x.Title)" Title="Title" />
<PropertyColumn Property="@(x => x.Preview)" Title="Preview" />
</FluentDataGrid>
}
</MudCardContent>
</MudCard>
</div>
</FluentCard>
@code {
private readonly List<OperationalReportSection> Sections = new();
private string ReportStateLabel = "DATA_MISSING";
private string ReportChipLabel = "DATA_MISSING";
private Color ReportChipColor = Color.Warning;
private string SectionCountLabel = "0";
private string GeneratedAtLabel = "n/a";
private string SourceLabel = "n/a";
@@ -133,6 +106,5 @@
SourceLabel = report.SourceJson;
ReportStateLabel = Sections.Count > 0 ? "READY" : "DATA_MISSING";
ReportChipLabel = Sections.Count > 0 ? "READY" : "DATA_MISSING";
ReportChipColor = Sections.Count > 0 ? Color.Success : Color.Warning;
}
}
@@ -4,106 +4,85 @@
<PageTitle>Quant Engine - Operations</PageTitle>
<MudText Typo="Typo.h4" Class="mb-2">Operational Report</MudText>
<MudText Typo="Typo.body2" Color="Color.Secondary" Class="mb-4">
<h1 style="margin: 0 0 8px 0; font-size: 28px; font-weight: 600;">Operational Report</h1>
<p style="margin: 0 0 16px 0; color: var(--neutral-foreground-2); font-size: 14px;">
이 페이지는 `Temp/operational_report.json`만 읽습니다. DB 연결과 무관하게 동일한 결과를 보여주는 운영 고정 화면입니다.
</MudText>
</p>
<MudGrid Class="mb-4">
<MudItem xs="12" sm="6" md="3">
<MudCard Class="h-100">
<MudCardContent>
<MudText Typo="Typo.body2" Color="Color.Secondary">Schema</MudText>
<MudText Typo="Typo.h6" Class="mt-2">@SchemaVersion</MudText>
</MudCardContent>
</MudCard>
</MudItem>
<MudItem xs="12" sm="6" md="3">
<MudCard Class="h-100">
<MudCardContent>
<MudText Typo="Typo.body2" Color="Color.Secondary">Sections</MudText>
<MudText Typo="Typo.h6" Class="mt-2">@SectionCountLabel</MudText>
</MudCardContent>
</MudCard>
</MudItem>
<MudItem xs="12" sm="6" md="3">
<MudCard Class="h-100">
<MudCardContent>
<MudText Typo="Typo.body2" Color="Color.Secondary">Source</MudText>
<MudText Typo="Typo.h6" Class="mt-2">@SourceJson</MudText>
</MudCardContent>
</MudCard>
</MudItem>
<MudItem xs="12" sm="6" md="3">
<MudCard Class="h-100">
<MudCardContent>
<MudText Typo="Typo.body2" Color="Color.Secondary">Generated</MudText>
<MudText Typo="Typo.h6" Class="mt-2">@GeneratedAt</MudText>
</MudCardContent>
</MudCard>
</MudItem>
</MudGrid>
<!-- Metadata Cards -->
<FluentStack Orientation="Orientation.Horizontal" HorizontalGap="16" Wrap="true" Style="margin-bottom: 16px;">
<FluentCard Style="flex: 1; min-width: 150px;">
<div style="padding: 16px;">
<p style="margin: 0 0 8px 0; color: var(--neutral-foreground-2); font-size: 12px; font-weight: 500;">Schema</p>
<h3 style="margin: 0; font-size: 18px; font-weight: 600;">@SchemaVersion</h3>
</div>
</FluentCard>
<FluentCard Style="flex: 1; min-width: 150px;">
<div style="padding: 16px;">
<p style="margin: 0 0 8px 0; color: var(--neutral-foreground-2); font-size: 12px; font-weight: 500;">Sections</p>
<h3 style="margin: 0; font-size: 18px; font-weight: 600;">@SectionCountLabel</h3>
</div>
</FluentCard>
<FluentCard Style="flex: 1; min-width: 150px;">
<div style="padding: 16px;">
<p style="margin: 0 0 8px 0; color: var(--neutral-foreground-2); font-size: 12px; font-weight: 500;">Source</p>
<h3 style="margin: 0; font-size: 18px; font-weight: 600;">@SourceJson</h3>
</div>
</FluentCard>
<FluentCard Style="flex: 1; min-width: 150px;">
<div style="padding: 16px;">
<p style="margin: 0 0 8px 0; color: var(--neutral-foreground-2); font-size: 12px; font-weight: 500;">Generated</p>
<h3 style="margin: 0; font-size: 18px; font-weight: 600;">@GeneratedAt</h3>
</div>
</FluentCard>
</FluentStack>
<MudGrid Class="mb-4">
<!-- Highlight Sections Grid -->
<FluentStack Orientation="Orientation.Horizontal" HorizontalGap="16" Wrap="true" Style="margin-bottom: 16px;">
@foreach (var section in HighlightSections)
{
<MudItem xs="12" sm="6" lg="3">
<MudCard Class="h-100">
<MudCardContent>
<MudText Typo="Typo.body2" Color="Color.Secondary">@(section.Name)</MudText>
<MudText Typo="Typo.subtitle1" Class="mt-1">@(section.Title)</MudText>
<MudText Typo="Typo.caption" Color="Color.Secondary">@(section.Preview)</MudText>
</MudCardContent>
</MudCard>
</MudItem>
<FluentCard Style="flex: 1; min-width: 200px;">
<div style="padding: 16px;">
<p style="margin: 0 0 4px 0; color: var(--neutral-foreground-2); font-size: 12px;">@(section.Name)</p>
<h3 style="margin: 4px 0; font-size: 16px; font-weight: 600;">@(section.Title)</h3>
<p style="margin: 8px 0 0 0; color: var(--neutral-foreground-3); font-size: 12px;">@(section.Preview)</p>
</div>
</FluentCard>
}
</MudGrid>
</FluentStack>
<MudCard Class="mb-4">
<MudCardHeader>
<CardHeaderContent>
<MudText Typo="Typo.h6">Report Health</MudText>
</CardHeaderContent>
</MudCardHeader>
<MudCardContent>
<MudStack Spacing="2">
<MudText Typo="Typo.body2"><strong>Status:</strong> <MudChip Size="Size.Small" Color="@HealthColor">@HealthLabel</MudChip></MudText>
<MudText Typo="Typo.body2"><strong>Path:</strong> @ReportPath</MudText>
<MudText Typo="Typo.body2"><strong>Sections rendered:</strong> @RenderedSectionCountLabel</MudText>
</MudStack>
</MudCardContent>
</MudCard>
<!-- Report Health -->
<FluentCard Style="margin-bottom: 16px;">
<div style="padding: 16px;">
<h3 style="margin: 0 0 12px 0; font-size: 16px; font-weight: 600;">Report Health</h3>
<FluentStack Orientation="Orientation.Vertical" VerticalGap="8">
<p style="margin: 0; font-size: 14px;"><strong>Status:</strong> <FluentBadge Appearance="BadgeAppearance.Filled">@HealthLabel</FluentBadge></p>
<p style="margin: 0; font-size: 14px;"><strong>Path:</strong> @ReportPath</p>
<p style="margin: 0; font-size: 14px;"><strong>Sections rendered:</strong> @RenderedSectionCountLabel</p>
</FluentStack>
</div>
</FluentCard>
<MudCard>
<MudCardHeader>
<CardHeaderContent>
<MudText Typo="Typo.h6">Sections</MudText>
</CardHeaderContent>
</MudCardHeader>
<MudCardContent>
<!-- Sections Table -->
<FluentCard>
<div style="padding: 16px;">
<h3 style="margin: 0 0 12px 0; font-size: 16px; font-weight: 600;">Sections</h3>
@if (Sections.Count == 0)
{
<MudAlert Severity="Severity.Warning" Variant="Variant.Outlined">
<div style="padding: 12px; background: var(--warning-background-1); border: 1px solid var(--warning-stroke-1); border-radius: 4px; color: var(--warning-foreground-1); font-size: 14px;">
DATA_MISSING: operational_report.json에 표시할 섹션이 없습니다.
</MudAlert>
</div>
}
else
{
<MudTable Items="Sections" Hover="true" Striped="true" Dense="true">
<HeaderContent>
<MudTh>Name</MudTh>
<MudTh>Title</MudTh>
<MudTh>Preview</MudTh>
</HeaderContent>
<RowTemplate>
<MudTd>@context.Name</MudTd>
<MudTd>@context.Title</MudTd>
<MudTd>@context.Preview</MudTd>
</RowTemplate>
</MudTable>
<FluentDataGrid Items="@Sections.AsQueryable()">
<PropertyColumn Property="@(x => x.Name)" Title="Name" />
<PropertyColumn Property="@(x => x.Title)" Title="Title" />
<PropertyColumn Property="@(x => x.Preview)" Title="Preview" />
</FluentDataGrid>
}
</MudCardContent>
</MudCard>
</div>
</FluentCard>
@code {
private readonly List<OperationalReportSection> Sections = new();
@@ -114,7 +93,6 @@
private string SectionCountLabel = "0";
private string RenderedSectionCountLabel = "0";
private string HealthLabel = "DATA_MISSING";
private Color HealthColor = Color.Warning;
private string ReportPath = "n/a";
protected override async Task OnInitializedAsync()
@@ -133,6 +111,5 @@
SectionCountLabel = report.SectionCount.ToString();
RenderedSectionCountLabel = Sections.Count.ToString();
HealthLabel = Sections.Count > 0 ? "PASS" : "DATA_MISSING";
HealthColor = Sections.Count > 0 ? Color.Success : Color.Warning;
}
}
@@ -6,7 +6,8 @@
@using static Microsoft.AspNetCore.Components.Web.RenderMode
@using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.JSInterop
@using MudBlazor
@using Microsoft.FluentUI.AspNetCore.Components
@using Microsoft.FluentUI.AspNetCore.Components.Icons
@using QuantEngine.Web
@using QuantEngine.Web.Components
@using QuantEngine.Web.Components.Layout