WIP: CornHusker/add-db #6

Draft
CornHusker wants to merge 2 commits from CornHusker/add-db into cswimr/add-src
7 changed files with 250 additions and 24 deletions

View file

@ -0,0 +1,104 @@
@page "/turrets/create"
@using System.Runtime.InteropServices.JavaScript
@using Microsoft.EntityFrameworkCore
@using ZenithInfo.Models
@inject IDbContextFactory<ZenithInfo.Data.ZenithInfoContext> DbFactory
@inject NavigationManager NavigationManager
<PageTitle>Create</PageTitle>
<h1>Create</h1>
<h2>Turret</h2>
<hr />
<div class="row">
<div class="col-md-4">
<EditForm method="post" Model="Turret" OnValidSubmit="AddTurret" FormName="create" Enhance>
<DataAnnotationsValidator />
<ValidationSummary class="text-danger" role="alert"/>
<div class="mb-3">
<label for="name" class="form-label">Name:</label>
<InputText id="name" @bind-Value="Turret.Name" class="form-control" />
<ValidationMessage For="() => Turret.Name" class="text-danger" />
</div>
<div class="mb-3">
<label for="description" class="form-label">Description:</label>
<InputText id="description" @bind-Value="Turret.Description" class="form-control" />
<ValidationMessage For="() => Turret.Description" class="text-danger" />
</div>
<div class="mb-3">
<label for="damage" class="form-label">Damage:</label>
<InputNumber id="damage" @bind-Value="Turret.Damage" class="form-control" />
<ValidationMessage For="() => Turret.Damage" class="text-danger" />
</div>
<div class="mb-3">
<label for="reload" class="form-label">Reload:</label>
<InputNumber id="reload" @bind-Value="Turret.Reload" class="form-control" />
<ValidationMessage For="() => Turret.Reload" class="text-danger" />
</div>
<div class="mb-3">
<label for="range" class="form-label">Range:</label>
<InputNumber id="range" @bind-Value="Turret.Range" class="form-control" />
<ValidationMessage For="() => Turret.Range" class="text-danger" />
</div>
<div class="mb-3">
<label for="optimal range" class="form-label">Optimal Range:</label>
<InputNumber id="optimal range" @bind-Value="Turret.OptimalRange" class="form-control" />
<ValidationMessage For="() => Turret.OptimalRange" class="text-danger" />
</div>
<div class="mb-3">
<label for="accuracy falloff range" class="form-label">Accuracy Falloff Range:</label>
<InputNumber id="accuracy falloff range" @bind-Value="Turret.AccuracyFalloffRange" class="form-control" />
<ValidationMessage For="() => Turret.AccuracyFalloffRange" class="text-danger" />
</div>
<div class="mb-3">
<label for="size" class="form-label">Size:</label>
<InputSelect id="size" @bind-Value="Turret.Size" class="form-control" />
<ValidationMessage For="() => Turret.Size" class="text-danger" />
</div>
<div class="mb-3">
<label for="rating" class="form-label">Type:</label>
<InputSelect id="rating" @bind-Value="Turret.Type" class="form-control" />
<ValidationMessage For="() => Turret.Type" class="text-danger" />
</div>
<div class="mb-3">
<label for="icon" class="form-label">Icon:</label>
<InputNumber id="icon" @bind-Value="Turret.Icon" class="form-control" />
<ValidationMessage For="() => Turret.Icon" class="text-danger" />
</div>
<div class="mb-3">
<label for="beam size" class="form-label">Beam Size:</label>
<InputNumber id="beam size" @bind-Value="Turret.BeamSize" class="form-control" />
<ValidationMessage For="() => Turret.BeamSize" class="text-danger" />
</div>
<div class="mb-3">
<label for="base cost" class="form-label">Base Cost:</label>
<InputNumber id="base cost" @bind-Value="Turret.BaseCost" class="form-control" />
<ValidationMessage For="() => Turret.BaseCost" class="text-danger" />
</div>
<div class="mb-3">
<label for="rarity" class="form-label">Rarity:</label>
<InputSelect id="rarity" @bind-Value="Turret.Rarity" class="form-control" />
<ValidationMessage For="() => Turret.Rarity" class="text-danger" />
</div>
<button type="submit" class="btn btn-primary">Create</button>
</EditForm>
</div>
</div>
<div>
<a href="/turrets">Back to List</a>
</div>
@code {
[SupplyParameterFromForm]
private Turret Turret { get; set; } = new();
private async Task AddTurret()
{
using var context = DbFactory.CreateDbContext();
context.Turret.Add(Turret);
await context.SaveChangesAsync();
NavigationManager.NavigateTo("/turrets");
}
}

View file

@ -0,0 +1,64 @@
@page "/turrets"
@rendermode InteractiveServer
@using Microsoft.EntityFrameworkCore
@using Microsoft.AspNetCore.Components.QuickGrid
@using Microsoft.AspNetCore.Components.QuickGrid.EntityFrameworkAdapter
@using ZenithInfo.Models
@using ZenithInfo.Data
@implements IAsyncDisposable
@inject IDbContextFactory<ZenithInfoContext> DbFactory
<PageTitle>Index</PageTitle>
<h1>Index</h1>
<div>
<input type="search" @bind="nameFilter" @bind:event="oninput" />
</div>
<p>
<a href="turrets/create">Create New</a>
</p>
<div>
<QuickGrid Class="table" Items="FilteredTurrets" Pagination="pagination">
<PropertyColumn Property="turret => turret.Name" Sortable="true" />
<PropertyColumn Property="turret => turret.Description" />
<PropertyColumn Property="turret => turret.Damage" />
<PropertyColumn Property="turret => turret.Reload" />
<PropertyColumn Property="turret => turret.Range" />
<PropertyColumn Property="turret => turret.OptimalRange" Title="Optimal Range" />
<PropertyColumn Property="turret => turret.AccuracyFalloffRange" Title="Accuracy Falloff Range" />
<PropertyColumn Property="turret => turret.Accuracy" />
<PropertyColumn Property="turret => turret.Size" />
<PropertyColumn Property="turret => turret.Type" />
<PropertyColumn Property="turret => turret.Icon" />
<PropertyColumn Property="turret => turret.BeamSize" />
<PropertyColumn Property="turret => turret.BaseCost" />
<PropertyColumn Property="turret => turret.Rarity" />
<TemplateColumn Context="turret">
<a href="@($"turrets/edit?id={turret.Id}")">Edit</a> |
<a href="@($"turrets/details?id={turret.Id}")">Details</a> |
<a href="@($"turrets/delete?id={turret.Id}")">Delete</a>
</TemplateColumn>
</QuickGrid>
</div>
<Paginator State="pagination" />
@code {
private ZenithInfoContext context = default!;
private PaginationState pagination = new PaginationState { ItemsPerPage = 5 };
private string nameFilter = string.Empty;
private IQueryable<Turret> FilteredTurrets =>
context.Turret.Where(m => m.Name!.Contains(nameFilter));
protected override void OnInitialized()
{
context = DbFactory.CreateDbContext();
}
public async ValueTask DisposeAsync() => await context.DisposeAsync();
}

View file

@ -0,0 +1,7 @@
::deep tr {
height: 3em;
}
::deep tr > td {
vertical-align: middle;
}

19
Data/ZenithInfoContext.cs Normal file
View file

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using ZenithInfo.Models;
namespace ZenithInfo.Data
{
public class ZenithInfoContext : DbContext
{
public ZenithInfoContext (DbContextOptions<ZenithInfoContext> options)
: base(options)
{
}
public DbSet<ZenithInfo.Models.Turret> Turret { get; set; } = default!;
}
}

View file

@ -4,8 +4,11 @@ namespace ZenithInfo.Models
{ {
public class Turret public class Turret
{ {
public required string Name { get; set; } // required by EF Core. see https://learn.microsoft.com/en-us/aspnet/core/blazor/tutorials/movie-database-app/part-2?view=aspnetcore-9.0&pivots=vs#add-a-data-model
public required string Description { get; set; } public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public double Damage { get; set; } public double Damage { get; set; }
public double Reload { get; set; } public double Reload { get; set; }
public double Range { get; set; } public double Range { get; set; }

View file

@ -1,6 +1,10 @@
using System.Reflection; using System.Reflection;
using Microsoft.AspNetCore.Components.QuickGrid.EntityFrameworkAdapter;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Models;
using ZenithInfo.Components; using ZenithInfo.Components;
using ZenithInfo.Data;
using ZenithInfo.Models; using ZenithInfo.Models;
using ZenithInfo.Util.SwaggerTheme; using ZenithInfo.Util.SwaggerTheme;
@ -17,6 +21,12 @@ if (config?.GlobalToken == "CHANGE-ME")
); );
} }
// Initialize Database
builder.Services.AddQuickGridEntityFrameworkAdapter();
builder.Services.AddDbContextFactory<ZenithInfoContext>(options =>
options.UseNpgsql(builder.Configuration.GetConnectionString("ZenithInfoContext"))
);
// Sentry // Sentry
if (config?.UseSentry == true) if (config?.UseSentry == true)
{ {

View file

@ -1,22 +1,41 @@
<Project Sdk="Microsoft.NET.Sdk.Web"> <Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS> <DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
<GenerateDocumentationFile>true</GenerateDocumentationFile> <GenerateDocumentationFile>true</GenerateDocumentationFile>
<NoWarn>$(NoWarn);1591</NoWarn> <NoWarn>$(NoWarn);1591</NoWarn>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="AspNetCore.SwaggerUI.Themes" Version="2.0.0" /> <PackageReference Include="AspNetCore.SwaggerUI.Themes" Version="2.0.0" />
<PackageReference Include="Sentry.AspNetCore" Version="5.0.0" /> <PackageReference Include="Sentry.AspNetCore" Version="5.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="7.2.0" /> <PackageReference Include="Swashbuckle.AspNetCore" Version="7.2.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<EmbeddedResource Include="Util\SwaggerTheme\modern.custom.css" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="9.0.0" />
</ItemGroup> <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.11" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="9.0.0">
</Project> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="9.0.0" />
<PackageReference Include="Npgsql" Version="9.0.2" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.2" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL.Design" Version="1.1.0" />
<PackageReference Include="Microsoft.AspNetCore.Components.QuickGrid.EntityFrameworkAdapter" Version="8.0.0" />
</ItemGroup>
<ItemGroup>
<Folder Include="Data\" />
<Folder Include="Migrations\" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Util\SwaggerTheme\modern.custom.css" />
</ItemGroup>
</Project>