adding wasm client project, github actions, radzen
This commit is contained in:
parent
ff1a391599
commit
4c5fa9e0e6
52
.github/workflows/ci.yml
vendored
Normal file
52
.github/workflows/ci.yml
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
name: ci
|
||||
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
dotnet-version: [ '8.0.x' ]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Setup .NET Core SDK ${{ matrix.dotnet-version }}
|
||||
uses: actions/setup-dotnet@v3.0.3
|
||||
with:
|
||||
dotnet-version: ${{ matrix.dotnet-version }}
|
||||
- name: Install Dependencies
|
||||
run: dotnet restore Overflow.sln
|
||||
- name: Build
|
||||
run: dotnet build --configuration Debug --no-restore Overflow.sln
|
||||
- name: Test
|
||||
run: dotnet test --no-restore --verbosity normal Overflow.sln
|
||||
|
||||
build-Docker:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
needs: [build, build-Js] # for ignoring bad builds
|
||||
if: github.event_name == 'push' && (github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/'))
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
|
||||
- name: Login to DockerHub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Build Web Container
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
push: true
|
||||
tags: |
|
||||
sarsoo/overflow:latest
|
||||
sarsoo/overflow:${{ github.ref_name }}
|
||||
file: Dockerfile
|
@ -7,9 +7,9 @@ using Overflow.SouthernWater;
|
||||
|
||||
var driver = new MongoClient("mongodb://localhost");
|
||||
|
||||
var api = new SouthernWater(new HttpClient());
|
||||
var api = new SouthernWaterApi(new HttpClient());
|
||||
await api.LoadApiUrl();
|
||||
|
||||
var runner = new SouthernWaterApiJobRunnerPersisting(api, NullLogger<SouthernWaterApiJobRunner>.Instance, driver.GetDatabase("overflow"));
|
||||
|
||||
await runner.LoadSpills();
|
||||
await runner.LoadSpills(5);
|
@ -1,14 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.6" />
|
||||
<PackageReference Include="Npgsql" Version="8.0.3" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
@ -10,7 +10,7 @@ public class Tests
|
||||
[Test]
|
||||
public async Task Test1()
|
||||
{
|
||||
var southern = new SouthernWater.SouthernWater(new HttpClient());
|
||||
var southern = new SouthernWater.SouthernWaterApi(new HttpClient());
|
||||
await southern.LoadApiUrl();
|
||||
var spills = await southern.GetSpills();
|
||||
}
|
||||
|
43
Overflow.Web.Client/Components/SpillsTable.razor
Normal file
43
Overflow.Web.Client/Components/SpillsTable.razor
Normal file
@ -0,0 +1,43 @@
|
||||
@using Overflow.SouthernWater
|
||||
@rendermode RenderMode.InteractiveAuto
|
||||
|
||||
@if (Job == null)
|
||||
{
|
||||
<p>
|
||||
<em>Loading...</em>
|
||||
</p>
|
||||
}
|
||||
else
|
||||
{
|
||||
<RadzenDataGrid Data="@Job.Spills" TItem="Spill"
|
||||
AllowFiltering="true"
|
||||
AllowColumnResize="true"
|
||||
AllowSorting="true"
|
||||
PageSize="25"
|
||||
AllowPaging="true"
|
||||
ShowPagingSummary="true"
|
||||
>
|
||||
<Columns>
|
||||
@if (ShowIds)
|
||||
{
|
||||
<RadzenDataGridColumn TItem="Spill" Property="sw_id" Title="Id"/>
|
||||
<RadzenDataGridColumn TItem="Spill" Property="eventId" Title="Event Id"/>
|
||||
<RadzenDataGridColumn TItem="Spill" Property="siteUnitNumber" Title="Site Unit Number"/>
|
||||
<RadzenDataGridColumn TItem="Spill" Property="associatedSiteId" Title="Associated Site Id"/>
|
||||
<RadzenDataGridColumn TItem="Spill" Property="overFlowSiteId" Title="OverFlow Site Id"/>
|
||||
}
|
||||
<RadzenDataGridColumn TItem="Spill" Property="bathingSite" Title="Bathing Site"/>
|
||||
<RadzenDataGridColumn TItem="Spill" Property="outfallName" Title="Outfall"/>
|
||||
<RadzenDataGridColumn TItem="Spill" Property="eventStart" Title="Event Start"/>
|
||||
<RadzenDataGridColumn TItem="Spill" Property="eventStop" Title="Event End"/>
|
||||
<RadzenDataGridColumn TItem="Spill" Property="duration" Title="Duration"/>
|
||||
<RadzenDataGridColumn TItem="Spill" Property="status" Title="Status"/>
|
||||
<RadzenDataGridColumn TItem="Spill" Property="isImpacting" Title="Is Impacting"/>
|
||||
</Columns>
|
||||
</RadzenDataGrid>
|
||||
}
|
||||
|
||||
@code {
|
||||
[Parameter] public SouthernWaterApiJob? Job { get; set; }
|
||||
[Parameter] public bool ShowIds { get; set; }
|
||||
}
|
@ -5,6 +5,7 @@
|
||||
<meta charset="utf-8"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
<base href="/"/>
|
||||
<link rel="stylesheet" href="_content/Radzen.Blazor/css/material-base.css">
|
||||
<link rel="stylesheet" href="bootstrap/bootstrap.min.css"/>
|
||||
<link rel="stylesheet" href="app.css"/>
|
||||
<link rel="stylesheet" href="Overflow.Web.styles.css"/>
|
||||
@ -15,6 +16,7 @@
|
||||
<body>
|
||||
<Routes/>
|
||||
<script src="_framework/blazor.web.js"></script>
|
||||
<script src="_content/Radzen.Blazor/Radzen.Blazor.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
@ -1,6 +1,6 @@
|
||||
<div class="top-row ps-3 navbar navbar-dark">
|
||||
<div class="container-fluid">
|
||||
<a class="navbar-brand" href="">Overflow.Web</a>
|
||||
<a class="navbar-brand" href="">Overflow</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -21,8 +21,8 @@
|
||||
</div>
|
||||
|
||||
<div class="nav-item px-3">
|
||||
<NavLink class="nav-link" href="weather">
|
||||
<span class="bi bi-list-nested-nav-menu" aria-hidden="true"></span> Weather
|
||||
<NavLink class="nav-link" href="spills">
|
||||
<span class="bi bi-list-nested-nav-menu" aria-hidden="true"></span> Spills
|
||||
</NavLink>
|
||||
</div>
|
||||
</nav>
|
||||
|
@ -1,7 +1,5 @@
|
||||
@page "/"
|
||||
|
||||
<PageTitle>Home</PageTitle>
|
||||
<PageTitle>Overflow</PageTitle>
|
||||
|
||||
<h1>Hello, world!</h1>
|
||||
|
||||
Welcome to your new app.
|
||||
<h1>Overflow</h1>
|
||||
|
33
Overflow.Web/Components/Pages/Spills.razor
Normal file
33
Overflow.Web/Components/Pages/Spills.razor
Normal file
@ -0,0 +1,33 @@
|
||||
@page "/spills"
|
||||
@using MongoDB.Driver
|
||||
@using Overflow.SouthernWater
|
||||
@rendermode RenderMode.InteractiveServer
|
||||
|
||||
<PageTitle>Southern Water Spills</PageTitle>
|
||||
|
||||
<h1>Spills</h1>
|
||||
|
||||
<p>This component demonstrates showing data.</p>
|
||||
|
||||
<RadzenCard class="my-4">
|
||||
<RadzenStack Orientation="Orientation.Horizontal" AlignItems="AlignItems.Start" Wrap="FlexWrap.Wrap">
|
||||
<RadzenCheckBox @bind-Value=@showIds Name="ShowIds" />
|
||||
<RadzenLabel Text="Show IDs" Component="ShowIds" Style="margin-left: 8px; vertical-align: middle;" />
|
||||
</RadzenStack>
|
||||
</RadzenCard>
|
||||
|
||||
<SpillsTable Job=@job ShowIds=@showIds />
|
||||
|
||||
@code {
|
||||
private SouthernWaterApiJob? job;
|
||||
[Inject] private IMongoDatabase database { get; set; }
|
||||
private bool showIds;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
job = database.GetCollection<SouthernWaterApiJob>(Static.CollectionName)
|
||||
.AsQueryable()
|
||||
.OrderByDescending(j => j.EndTime)
|
||||
.FirstOrDefault();
|
||||
}
|
||||
}
|
@ -1,67 +0,0 @@
|
||||
@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>Temp. (C)</th>
|
||||
<th>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);
|
||||
}
|
||||
|
||||
}
|
@ -7,4 +7,8 @@
|
||||
@using Microsoft.AspNetCore.Components.Web.Virtualization
|
||||
@using Microsoft.JSInterop
|
||||
@using Overflow.Web
|
||||
@using Overflow.Web.Components
|
||||
@using Overflow.Web.Components
|
||||
@using Overflow.Web.Client.Pages
|
||||
@using Overflow.Web.Client.Components
|
||||
@using Radzen
|
||||
@using Radzen.Blazor
|
@ -7,11 +7,25 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="8.0.6" />
|
||||
<PackageReference Include="MongoDB.Driver" Version="2.25.0" />
|
||||
<PackageReference Include="Quartz" Version="3.9.0" />
|
||||
<PackageReference Include="Quartz.AspNetCore" Version="3.9.0" />
|
||||
<PackageReference Include="Quartz.Extensions.DependencyInjection" Version="3.9.0" />
|
||||
<PackageReference Include="Quartz.Extensions.Hosting" Version="3.9.0" />
|
||||
<PackageReference Include="Radzen.Blazor" Version="4.32.6" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Overflow.Web.Client\Overflow.Web.Client.csproj" />
|
||||
<ProjectReference Include="..\Overflow\Overflow.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<_ContentIncludedByDefault Remove="wwwroot\app.css" />
|
||||
<_ContentIncludedByDefault Remove="wwwroot\bootstrap\bootstrap.min.css" />
|
||||
<_ContentIncludedByDefault Remove="wwwroot\bootstrap\bootstrap.min.css.map" />
|
||||
<_ContentIncludedByDefault Remove="wwwroot\favicon.png" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
@ -1,13 +1,18 @@
|
||||
using Overflow.Web.Components;
|
||||
using Overflow;
|
||||
|
||||
|
||||
using MongoDB.Driver;
|
||||
using Overflow.SouthernWater;
|
||||
using Quartz;
|
||||
using Quartz.AspNetCore;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
// Add services to the container.
|
||||
builder.Services.AddRazorComponents()
|
||||
.AddInteractiveServerComponents();
|
||||
.AddInteractiveServerComponents()
|
||||
.AddInteractiveWebAssemblyComponents();
|
||||
|
||||
var driver = new MongoClient(builder.Configuration.GetConnectionString("Default"));
|
||||
builder.Services.AddSingleton(driver);
|
||||
@ -15,6 +20,32 @@ builder.Services.AddScoped<IMongoDatabase>(s => s.GetRequiredService<MongoClient
|
||||
|
||||
builder.Services.AddControllers();
|
||||
|
||||
// base configuration from appsettings.json
|
||||
builder.Services.Configure<QuartzOptions>(builder.Configuration.GetSection("Quartz"));
|
||||
|
||||
// if you are using persistent job store, you might want to alter some options
|
||||
builder.Services.Configure<QuartzOptions>(options =>
|
||||
{
|
||||
options.Scheduling.IgnoreDuplicates = true; // default: false
|
||||
options.Scheduling.OverWriteExistingData = true; // default: true
|
||||
});
|
||||
|
||||
builder.Services.AddQuartz(q =>
|
||||
{
|
||||
// base Quartz scheduler, job and trigger configuration
|
||||
});
|
||||
|
||||
// ASP.NET Core hosting
|
||||
builder.Services.AddQuartzServer(options =>
|
||||
{
|
||||
// when shutting down we want jobs to complete gracefully
|
||||
options.WaitForJobsToComplete = false;
|
||||
});
|
||||
|
||||
builder.Services.AddHttpClient();
|
||||
builder.Services.AddSingleton<SouthernWaterApi>();
|
||||
builder.Services.AddScoped<SouthernWaterApiJobRunner, SouthernWaterApiJobRunnerPersisting>();
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
// Configure the HTTP request pipeline.
|
||||
@ -32,6 +63,7 @@ app.UseAntiforgery();
|
||||
|
||||
app.MapControllers();
|
||||
app.MapRazorComponents<App>()
|
||||
.AddInteractiveServerRenderMode();
|
||||
.AddInteractiveServerRenderMode()
|
||||
.AddInteractiveWebAssemblyRenderMode();
|
||||
|
||||
app.Run();
|
@ -5,5 +5,8 @@
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
},
|
||||
"ConnectionStrings": {
|
||||
"Default": "mongodb://localhost"
|
||||
},
|
||||
"AllowedHosts": "*"
|
||||
}
|
||||
|
@ -8,6 +8,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Overflow.Web", "Overflow.We
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Overflow.CLI", "Overflow.CLI\Overflow.CLI.csproj", "{393EF268-E745-4550-9607-DBE6B4C456DA}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Overflow.Web.Client", "Overflow.Web.Client\Overflow.Web.Client.csproj", "{FDA03F0A-260B-4110-B5B6-19CCFFBB1618}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@ -30,5 +32,9 @@ Global
|
||||
{393EF268-E745-4550-9607-DBE6B4C456DA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{393EF268-E745-4550-9607-DBE6B4C456DA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{393EF268-E745-4550-9607-DBE6B4C456DA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{FDA03F0A-260B-4110-B5B6-19CCFFBB1618}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{FDA03F0A-260B-4110-B5B6-19CCFFBB1618}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{FDA03F0A-260B-4110-B5B6-19CCFFBB1618}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{FDA03F0A-260B-4110-B5B6-19CCFFBB1618}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
@ -4,7 +4,7 @@ using System.Text.RegularExpressions;
|
||||
|
||||
namespace Overflow.SouthernWater;
|
||||
|
||||
public partial class SouthernWater
|
||||
public partial class SouthernWaterApi
|
||||
{
|
||||
private readonly HttpClient _client;
|
||||
|
||||
@ -13,7 +13,7 @@ public partial class SouthernWater
|
||||
private string baseUrl;
|
||||
private string apiKey;
|
||||
|
||||
public SouthernWater(HttpClient client)
|
||||
public SouthernWaterApi(HttpClient client)
|
||||
{
|
||||
_client = client;
|
||||
}
|
@ -1,9 +1,11 @@
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Bson.Serialization.Attributes;
|
||||
|
||||
namespace Overflow.SouthernWater;
|
||||
|
||||
public class SouthernWaterApiJob
|
||||
{
|
||||
[BsonId]
|
||||
public ObjectId _id { get; set; }
|
||||
public DateTime StartTime { get; set; }
|
||||
public DateTime? EndTime { get; set; }
|
||||
|
@ -4,11 +4,11 @@ using MongoDB.Driver;
|
||||
|
||||
namespace Overflow.SouthernWater;
|
||||
|
||||
public class SouthernWaterApiJobRunner(SouthernWater client, ILogger<SouthernWaterApiJobRunner> logger)
|
||||
public class SouthernWaterApiJobRunner(SouthernWaterApi client, ILogger<SouthernWaterApiJobRunner> logger)
|
||||
{
|
||||
protected readonly ILogger<SouthernWaterApiJobRunner> _logger = logger;
|
||||
|
||||
public async Task<SouthernWaterApiJob> LoadSpills()
|
||||
public async Task<SouthernWaterApiJob> LoadSpills(int? pageLimit = null)
|
||||
{
|
||||
var interval = TimeSpan.FromSeconds(30);
|
||||
var job = new SouthernWaterApiJob
|
||||
@ -28,7 +28,7 @@ public class SouthernWaterApiJobRunner(SouthernWater client, ILogger<SouthernWat
|
||||
|
||||
await JobCreated(job);
|
||||
|
||||
var spills = client.GetAllSpills(interval);
|
||||
var spills = client.GetAllSpills(interval, pageLimit: pageLimit);
|
||||
|
||||
await foreach (var page in spills)
|
||||
{
|
||||
@ -81,12 +81,12 @@ public class SouthernWaterApiJobRunner(SouthernWater client, ILogger<SouthernWat
|
||||
}
|
||||
|
||||
public class SouthernWaterApiJobRunnerPersisting(
|
||||
SouthernWater client,
|
||||
SouthernWaterApi client,
|
||||
ILogger<SouthernWaterApiJobRunner> logger,
|
||||
IMongoDatabase mongo)
|
||||
: SouthernWaterApiJobRunner(client, logger)
|
||||
{
|
||||
private readonly IMongoCollection<SouthernWaterApiJob> _collection = mongo.GetCollection<SouthernWaterApiJob>("southern_water_api_job");
|
||||
private readonly IMongoCollection<SouthernWaterApiJob> _collection = mongo.GetCollection<SouthernWaterApiJob>(Static.CollectionName);
|
||||
|
||||
protected override async Task JobCreated(SouthernWaterApiJob job)
|
||||
{
|
||||
|
@ -6,9 +6,6 @@ namespace Overflow.SouthernWater;
|
||||
|
||||
public class Spill
|
||||
{
|
||||
[JsonIgnore]
|
||||
public ObjectId _id { get; set; }
|
||||
|
||||
[JsonPropertyName("id")]
|
||||
public int sw_id { get; set; }
|
||||
public int eventId { get; set; }
|
||||
|
7
Overflow/Static.cs
Normal file
7
Overflow/Static.cs
Normal file
@ -0,0 +1,7 @@
|
||||
namespace Overflow;
|
||||
|
||||
public static class Static
|
||||
{
|
||||
public static readonly string DatabaseName = "overflow";
|
||||
public static readonly string CollectionName = "southern_water_api_job";
|
||||
}
|
Loading…
Reference in New Issue
Block a user