+
Aggregate Search
+
+
+
+ @if (!ModelState.IsValid)
+ {
+
+ @foreach (var modelState in ModelState.Values)
+ {
+ @foreach (var error in modelState.Errors)
+ {
+
@error.ErrorMessage
+ }
+ }
+
+ }
+
+ @if (Model.SearchResults != null)
+ {
+
+
Total: @Model.SearchResults.TotalCount | Page @Model.SearchResults.Page of @Math.Ceiling((double)Model.SearchResults.TotalCount / Model.SearchResults.PageSize)
+
+ @if (Model.SearchResults.Items.Count > 0)
+ {
+
+
+
+ | Aggregate Type |
+ Aggregate ID |
+ Version |
+ Last Updated |
+ Actions |
+
+
+
+ @foreach (var item in Model.SearchResults.Items)
+ {
+
+ | @item.AggregateType |
+ @item.AggregateId |
+ @item.CurrentVersion |
+ @item.LastUpdatedUtc.ToString("u") |
+
+ Events
+ Projection
+ |
+
+ }
+
+
+
+ @if (Model.PageNo > 1)
+ {
+
Previous
+ }
+
+ @if (Model.SearchResults.Page * Model.SearchResults.PageSize < Model.SearchResults.TotalCount)
+ {
+
Next
+ }
+ }
+ else
+ {
+
No aggregates found.
+ }
+
+ }
+
+ .admin-container {
+ max-width: 1200px;
+ margin: 0 auto;
+ padding: 20px;
+ }
+
+ .search-form {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
+ gap: 15px;
+ margin-bottom: 20px;
+ padding: 15px;
+ background-color: #f5f5f5;
+ border-radius: 4px;
+ }
+
+ .form-group {
+ display: flex;
+ flex-direction: column;
+ }
+
+ .form-group label {
+ font-weight: bold;
+ margin-bottom: 5px;
+ font-size: 14px;
+ }
+
+ .form-control {
+ padding: 8px;
+ border: 1px solid #ddd;
+ border-radius: 3px;
+ font-size: 14px;
+ }
+
+ .btn {
+ padding: 8px 12px;
+ border: none;
+ border-radius: 3px;
+ cursor: pointer;
+ font-size: 14px;
+ text-decoration: none;
+ display: inline-block;
+ }
+
+ .btn-primary {
+ background-color: #007bff;
+ color: white;
+ }
+
+ .btn-primary:hover {
+ background-color: #0056b3;
+ }
+
+ .btn-sm {
+ padding: 4px 8px;
+ font-size: 12px;
+ }
+
+ .btn-info {
+ background-color: #17a2b8;
+ color: white;
+ text-decoration: none;
+ }
+
+ .btn-success {
+ background-color: #28a745;
+ color: white;
+ text-decoration: none;
+ }
+
+ .table {
+ width: 100%;
+ border-collapse: collapse;
+ margin-bottom: 20px;
+ }
+
+ .table thead {
+ background-color: #f8f9fa;
+ }
+
+ .table th,
+ .table td {
+ padding: 12px;
+ text-align: left;
+ border-bottom: 1px solid #ddd;
+ }
+
+ .table tbody tr:hover {
+ background-color: #f5f5f5;
+ }
+
+ .table-striped tbody tr:nth-child(odd) {
+ background-color: #fafafa;
+ }
+
+ .search-results {
+ background-color: #fff;
+ padding: 15px;
+ border: 1px solid #ddd;
+ border-radius: 4px;
+ }
+
+ .alert {
+ padding: 12px;
+ margin-bottom: 20px;
+ border-radius: 4px;
+ }
+
+ .alert-danger {
+ background-color: #f8d7da;
+ color: #721c24;
+ border: 1px solid #f5c6cb;
+ }
+
+ code {
+ background-color: #f4f4f4;
+ padding: 2px 6px;
+ border-radius: 3px;
+ font-family: monospace;
+ font-size: 12px;
+ }
+
diff --git a/src/src/Admin.Site/Pages/AdminIndex.cshtml.cs b/src/src/Admin.Site/Pages/AdminIndex.cshtml.cs
new file mode 100644
index 00000000..fc52061d
--- /dev/null
+++ b/src/src/Admin.Site/Pages/AdminIndex.cshtml.cs
@@ -0,0 +1,58 @@
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Mvc.RazorPages;
+using Purview.EventSourcing.Admin.Abstractions.Models;
+using Purview.EventSourcing.Admin.Abstractions.Queries;
+using Purview.EventSourcing.Admin.Abstractions.Services;
+
+namespace Purview.EventSourcing.Admin.Site.Pages;
+
+public class AdminIndexModel(IAdminAggregateQueryService aggregateQueryService) : PageModel
+{
+ readonly IAdminAggregateQueryService _aggregateQueryService =
+ aggregateQueryService ?? throw new ArgumentNullException(nameof(aggregateQueryService));
+
+ [BindProperty(SupportsGet = true)]
+ public string? AggregateType { get; set; }
+
+ [BindProperty(SupportsGet = true)]
+ public string? AggregateId { get; set; }
+
+ [BindProperty(SupportsGet = true, Name = "page")]
+ public int PageNo { get; set; } = 1;
+
+ [BindProperty(SupportsGet = true)]
+ public int PageSize { get; set; } = 25;
+
+ public PagedResult