feat(dotnet): migrate core formulas, deploy tools, and blazor admin web app to .NET 10
WBS-9.3 - NULL Policy CI Gate / NULL Policy Validation (push) Has been cancelled
Quant Engine CI/CD Pipeline / validate-core (pull_request) Has been cancelled
Quant Engine CI/CD Pipeline / validate-ui-and-storage (pull_request) Has been cancelled
WBS-9.3 - NULL Policy CI Gate / NULL Policy Validation (pull_request) Has been cancelled
WBS-9.3 - NULL Policy CI Gate / NULL Policy Validation (push) Has been cancelled
Quant Engine CI/CD Pipeline / validate-core (pull_request) Has been cancelled
Quant Engine CI/CD Pipeline / validate-ui-and-storage (pull_request) Has been cancelled
WBS-9.3 - NULL Policy CI Gate / NULL Policy Validation (pull_request) Has been cancelled
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
@page "/counter"
|
||||
@rendermode InteractiveServer
|
||||
|
||||
<PageTitle>Counter</PageTitle>
|
||||
|
||||
<h1>Counter</h1>
|
||||
|
||||
<p role="status">Current count: @currentCount</p>
|
||||
|
||||
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
|
||||
|
||||
@code {
|
||||
private int currentCount = 0;
|
||||
|
||||
private void IncrementCount()
|
||||
{
|
||||
currentCount++;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,227 @@
|
||||
@page "/"
|
||||
@using QuantEngine.Core.Models
|
||||
@using QuantEngine.Core.Interfaces
|
||||
@inject IWorkspaceRepository WorkspaceRepo
|
||||
@inject NavigationManager NavManager
|
||||
|
||||
<PageTitle>Quant Engine - Administration Dashboard</PageTitle>
|
||||
|
||||
<div class="dashboard-container">
|
||||
<!-- Header -->
|
||||
<header class="db-header">
|
||||
<div class="logo-area">
|
||||
<span class="icon">📈</span>
|
||||
<h1>Quant Engine</h1>
|
||||
<span class="badge">Active Workspace</span>
|
||||
</div>
|
||||
<div class="system-status">
|
||||
<span class="status-dot green"></span>
|
||||
<span>PostgreSQL: Connected</span>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- Main Content Grid -->
|
||||
<div class="db-grid">
|
||||
<!-- Sidebar Summary Cards -->
|
||||
<aside class="summary-panel">
|
||||
<!-- Locks Card -->
|
||||
<div class="card status-card">
|
||||
<h3>🔒 Active Locks</h3>
|
||||
@if (locks.Any())
|
||||
{
|
||||
<ul class="status-list">
|
||||
@foreach (var l in locks)
|
||||
{
|
||||
<li>
|
||||
<strong>@l.Domain</strong> / <span>@l.TargetRef</span>
|
||||
<span class="meta">by @l.LockedBy - @l.Reason (@l.LockedAt)</span>
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
}
|
||||
else
|
||||
{
|
||||
<p class="empty-state">No active locks in workspace.</p>
|
||||
}
|
||||
</div>
|
||||
|
||||
<!-- Approvals Card -->
|
||||
<div class="card status-card">
|
||||
<h3>✅ Approvals v2</h3>
|
||||
@if (approvals.Any())
|
||||
{
|
||||
<ul class="status-list">
|
||||
@foreach (var a in approvals)
|
||||
{
|
||||
<li class="approval-item">
|
||||
<div class="approval-meta">
|
||||
<strong>@a.Domain</strong> <span class="badge @(a.Status.ToLower())">@a.Status</span>
|
||||
</div>
|
||||
<span class="meta">by @a.ApprovedBy @@ @a.ApprovedAt</span>
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
}
|
||||
else
|
||||
{
|
||||
<p class="empty-state">No approvals pending.</p>
|
||||
}
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- Main Settings / Configuration Grid -->
|
||||
<main class="main-panel">
|
||||
<div class="card table-card">
|
||||
<div class="table-header">
|
||||
<h2>⚙️ System Config (Settings)</h2>
|
||||
<button class="btn btn-primary" @onclick="ShowAddSettingModal">Add Configuration</button>
|
||||
</div>
|
||||
|
||||
<div class="table-container">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Ordinal</th>
|
||||
<th>Key</th>
|
||||
<th>Value (JSON)</th>
|
||||
<th>Note</th>
|
||||
<th>Updated At</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@if (settings != null && settings.Any())
|
||||
{
|
||||
@foreach (var s in settings)
|
||||
{
|
||||
<tr>
|
||||
<td>@s.Ordinal</td>
|
||||
<td class="font-mono"><strong>@s.Key</strong></td>
|
||||
<td class="font-mono value-cell">@s.ValueJson</td>
|
||||
<td>@s.Note</td>
|
||||
<td class="meta">@s.UpdatedAt</td>
|
||||
<td>
|
||||
<div class="action-buttons">
|
||||
<button class="btn btn-sm btn-secondary" @onclick="() => EditSetting(s)">Edit</button>
|
||||
<button class="btn btn-sm btn-danger" @onclick="() => DeleteSetting(s.Key)">Delete</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
<tr>
|
||||
<td colspan="6" class="empty-row">No configuration settings found.</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<!-- Add/Edit Modal -->
|
||||
@if (showModal)
|
||||
{
|
||||
<div class="modal-backdrop" @onclick="CloseModal">
|
||||
<div class="modal-content" @onclick:stopPropagation="true">
|
||||
<div class="modal-header">
|
||||
<h3>@(isEditMode ? "Edit Setting" : "Add Setting")</h3>
|
||||
<button class="close-btn" @onclick="CloseModal">×</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label>Key</label>
|
||||
<input type="text" class="form-control" @bind="modalSetting.Key" disabled="@isEditMode" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Value (JSON)</label>
|
||||
<textarea class="form-control font-mono" rows="4" @bind="modalSetting.ValueJson"></textarea>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Note</label>
|
||||
<input type="text" class="form-control" @bind="modalSetting.Note" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Ordinal</label>
|
||||
<input type="number" class="form-control" @bind="modalSetting.Ordinal" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-secondary" @onclick="CloseModal">Cancel</button>
|
||||
<button class="btn btn-primary" @onclick="SaveSetting">Save Changes</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
@code {
|
||||
private List<Setting> settings = new();
|
||||
private List<WorkspaceLock> locks = new();
|
||||
private List<WorkspaceApproval> approvals = new();
|
||||
|
||||
private bool showModal = false;
|
||||
private bool isEditMode = false;
|
||||
private Setting modalSetting = new();
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await LoadData();
|
||||
}
|
||||
|
||||
private async Task LoadData()
|
||||
{
|
||||
settings = (await WorkspaceRepo.GetSettingsAsync()).ToList();
|
||||
locks = (await WorkspaceRepo.GetLocksAsync()).ToList();
|
||||
approvals = (await WorkspaceRepo.GetApprovalsAsync()).ToList();
|
||||
}
|
||||
|
||||
private void ShowAddSettingModal()
|
||||
{
|
||||
isEditMode = false;
|
||||
modalSetting = new Setting
|
||||
{
|
||||
Ordinal = settings.Count + 1,
|
||||
UpdatedAt = DateTime.UtcNow.AddHours(9).ToString("o")
|
||||
};
|
||||
showModal = true;
|
||||
}
|
||||
|
||||
private void EditSetting(Setting s)
|
||||
{
|
||||
isEditMode = true;
|
||||
modalSetting = new Setting
|
||||
{
|
||||
Ordinal = s.Ordinal,
|
||||
Key = s.Key,
|
||||
ValueJson = s.ValueJson,
|
||||
Note = s.Note,
|
||||
UpdatedAt = DateTime.UtcNow.AddHours(9).ToString("o")
|
||||
};
|
||||
showModal = true;
|
||||
}
|
||||
|
||||
private async Task SaveSetting()
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(modalSetting.Key)) return;
|
||||
|
||||
modalSetting.UpdatedAt = DateTime.UtcNow.AddHours(9).ToString("o");
|
||||
await WorkspaceRepo.UpsertSettingAsync(modalSetting);
|
||||
showModal = false;
|
||||
await LoadData();
|
||||
}
|
||||
|
||||
private async Task DeleteSetting(string key)
|
||||
{
|
||||
await WorkspaceRepo.DeleteSettingAsync(key);
|
||||
await LoadData();
|
||||
}
|
||||
|
||||
private void CloseModal()
|
||||
{
|
||||
showModal = false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
@page "/Error"
|
||||
@using System.Diagnostics
|
||||
|
||||
<PageTitle>Error</PageTitle>
|
||||
|
||||
<h1 class="text-danger">Error.</h1>
|
||||
<h2 class="text-danger">An error occurred while processing your request.</h2>
|
||||
|
||||
@if (ShowRequestId)
|
||||
{
|
||||
<p>
|
||||
<strong>Request ID:</strong> <code>@RequestId</code>
|
||||
</p>
|
||||
}
|
||||
|
||||
<h3>Development Mode</h3>
|
||||
<p>
|
||||
Swapping to <strong>Development</strong> environment will display more detailed information about the error that occurred.
|
||||
</p>
|
||||
<p>
|
||||
<strong>The Development environment shouldn't be enabled for deployed applications.</strong>
|
||||
It can result in displaying sensitive information from exceptions to end users.
|
||||
For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>
|
||||
and restarting the app.
|
||||
</p>
|
||||
|
||||
@code{
|
||||
[CascadingParameter]
|
||||
private HttpContext? HttpContext { get; set; }
|
||||
|
||||
private string? RequestId { get; set; }
|
||||
private bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
|
||||
|
||||
protected override void OnInitialized() =>
|
||||
RequestId = Activity.Current?.Id ?? HttpContext?.TraceIdentifier;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
@page "/"
|
||||
|
||||
<PageTitle>Home</PageTitle>
|
||||
|
||||
<h1>Hello, world!</h1>
|
||||
|
||||
Welcome to your new app.
|
||||
@@ -0,0 +1,5 @@
|
||||
@page "/not-found"
|
||||
@layout MainLayout
|
||||
|
||||
<h3>Not Found</h3>
|
||||
<p>Sorry, the content you are looking for does not exist.</p>
|
||||
@@ -0,0 +1,64 @@
|
||||
@page "/weather"
|
||||
@attribute [StreamRendering]
|
||||
|
||||
<PageTitle>Weather</PageTitle>
|
||||
|
||||
<h1>Weather</h1>
|
||||
|
||||
<p>This component demonstrates showing data.</p>
|
||||
|
||||
@if (forecasts == null)
|
||||
{
|
||||
<p><em>Loading...</em></p>
|
||||
}
|
||||
else
|
||||
{
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Date</th>
|
||||
<th aria-label="Temperature in Celsius">Temp. (C)</th>
|
||||
<th aria-label="Temperature in Fahrenheit">Temp. (F)</th>
|
||||
<th>Summary</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var forecast in forecasts)
|
||||
{
|
||||
<tr>
|
||||
<td>@forecast.Date.ToShortDateString()</td>
|
||||
<td>@forecast.TemperatureC</td>
|
||||
<td>@forecast.TemperatureF</td>
|
||||
<td>@forecast.Summary</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
}
|
||||
|
||||
@code {
|
||||
private WeatherForecast[]? forecasts;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
// Simulate asynchronous loading to demonstrate streaming rendering
|
||||
await Task.Delay(500);
|
||||
|
||||
var startDate = DateOnly.FromDateTime(DateTime.Now);
|
||||
var summaries = new[] { "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" };
|
||||
forecasts = Enumerable.Range(1, 5).Select(index => new WeatherForecast
|
||||
{
|
||||
Date = startDate.AddDays(index),
|
||||
TemperatureC = Random.Shared.Next(-20, 55),
|
||||
Summary = summaries[Random.Shared.Next(summaries.Length)]
|
||||
}).ToArray();
|
||||
}
|
||||
|
||||
private class WeatherForecast
|
||||
{
|
||||
public DateOnly Date { get; set; }
|
||||
public int TemperatureC { get; set; }
|
||||
public string? Summary { get; set; }
|
||||
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user