Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
428 changes: 428 additions & 0 deletions AnchorageFiller/.gitignore

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

</Project>
10 changes: 10 additions & 0 deletions AnchorageFiller/AnchorageFiller.Clients/FleetsClient.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using System.Net.Http.Json;
using AnchorageFiller.Clients.Responses;

namespace AnchorageFiller.Clients;

public class FleetsClient(HttpClient client) : IFleetsClient
{
public Task<GetFleetResponse?> GetRandomFleetAsync(CancellationToken cancellationToken = default) =>
client.GetFromJsonAsync<GetFleetResponse>("/api/fleets/random", cancellationToken);
}
8 changes: 8 additions & 0 deletions AnchorageFiller/AnchorageFiller.Clients/IFleetsClient.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using AnchorageFiller.Clients.Responses;

namespace AnchorageFiller.Clients;

public interface IFleetsClient
{
Task<GetFleetResponse?> GetRandomFleetAsync(CancellationToken cancellationToken = default);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
namespace AnchorageFiller.Clients.Responses;

public record FleetItem(Size SingleShipSize, string ShipDesignation, int ShipCount);
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
namespace AnchorageFiller.Clients.Responses;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You decide, but these are the DTOs used - and now you have 3 records in one class. They are lightweight, so that is ok'ish, but they could also each have their own file.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, refactored into separate files now. And I was contemplating whether to move these models to a separate core/dto's project or not. But maybe it's best to leave that up to the candidate. (We can see if they decide to create their own models and mapping)


public record GetFleetResponse(Size AnchorageSize, IReadOnlyList<FleetItem> Fleets);
3 changes: 3 additions & 0 deletions AnchorageFiller/AnchorageFiller.Clients/Responses/Size.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
namespace AnchorageFiller.Clients.Responses;

public record Size(int Width, int Height);
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<BlazorDisableThrowNavigationException>true</BlazorDisableThrowNavigationException>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\AnchorageFiller.Web\AnchorageFiller.Web.csproj" />
</ItemGroup>

</Project>
20 changes: 20 additions & 0 deletions AnchorageFiller/AnchorageFiller.Server/Components/App.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<base href="/" />
<ResourcePreloader />
<link rel="stylesheet" href="@Assets["app.css"]" />
<link rel="stylesheet" href="@Assets["AnchorageFiller.Server.styles.css"]" />
<ImportMap />
<HeadOutlet @rendermode="@(new InteractiveWebAssemblyRenderMode(prerender: false))" />
</head>

<body>
<Routes @rendermode="@(new InteractiveWebAssemblyRenderMode(prerender: false))" />
<script src="@Assets["_framework/blazor.web.js"]"></script>
</body>

</html>
Original file line number Diff line number Diff line change
@@ -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;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
@using System.Net.Http
@using System.Net.Http.Json
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using static Microsoft.AspNetCore.Components.Web.RenderMode
@using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.JSInterop
@using AnchorageFiller.Server
@using AnchorageFiller.Web
@using AnchorageFiller.Server.Components
48 changes: 48 additions & 0 deletions AnchorageFiller/AnchorageFiller.Server/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using AnchorageFiller.Clients;
using AnchorageFiller.Server.Components;
using Microsoft.AspNetCore.Mvc;
using System.Text.Json;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddRazorComponents()
.AddInteractiveWebAssemblyComponents();


builder.Services.AddHttpClient<IFleetsClient, FleetsClient>(client =>
{
client.BaseAddress = new(builder.Configuration.GetValue<string>("ApiUrl")!, UriKind.Absolute);
});
builder.Services.ConfigureHttpJsonOptions(options =>
{
options.SerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
});

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseWebAssemblyDebugging();
}
else
{
app.UseExceptionHandler("/Error", createScopeForErrors: true);
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseStatusCodePagesWithReExecute("/not-found", createScopeForStatusCodePages: true);
app.UseHttpsRedirection();

app.UseAntiforgery();

app.MapStaticAssets();
app.MapRazorComponents<App>()
.AddInteractiveWebAssemblyRenderMode()
.AddAdditionalAssemblies(typeof(AnchorageFiller.Web._Imports).Assembly);

// API Endpoints
app.MapGet("/api/fleets/random", ([FromServices] IFleetsClient client) => client.GetRandomFleetAsync());

await app.RunAsync();
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"$schema": "https://json.schemastore.org/launchsettings.json",
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
"applicationUrl": "http://localhost:5113",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
"applicationUrl": "https://localhost:7108;http://localhost:5113",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}
10 changes: 10 additions & 0 deletions AnchorageFiller/AnchorageFiller.Server/appsettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"ApiUrl": "https://esa.instech.no"
}
38 changes: 38 additions & 0 deletions AnchorageFiller/AnchorageFiller.Server/wwwroot/app.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
h1:focus {
outline: none;
}

.valid.modified:not([type=checkbox]) {
outline: 1px solid #26b050;
}

.invalid {
outline: 1px solid #e50000;
}

.validation-message {
color: #e50000;
}

.blazor-error-boundary {
background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
padding: 1rem 1rem 1rem 3.7rem;
color: white;
}

.blazor-error-boundary::after {
content: "An error has occurred."
}

.darker-border-checkbox.form-check-input {
border-color: #929292;
}

.form-floating > .form-control-plaintext::placeholder, .form-floating > .form-control::placeholder {
color: var(--bs-secondary-color);
text-align: end;
}

.form-floating > .form-control-plaintext:focus::placeholder, .form-floating > .form-control:focus::placeholder {
text-align: start;
}
21 changes: 21 additions & 0 deletions AnchorageFiller/AnchorageFiller.Web/AnchorageFiller.Web.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">

<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<NoDefaultLaunchSettingsFile>true</NoDefaultLaunchSettingsFile>
<StaticWebAssetProjectMode>Default</StaticWebAssetProjectMode>
<BlazorDisableThrowNavigationException>true</BlazorDisableThrowNavigationException>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" />
<PackageReference Include="Microsoft.Extensions.Http" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\AnchorageFiller.Clients\AnchorageFiller.Clients.csproj" />
</ItemGroup>

</Project>
9 changes: 9 additions & 0 deletions AnchorageFiller/AnchorageFiller.Web/Layout/MainLayout.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
@inherits LayoutComponentBase

@Body

<div id="blazor-error-ui" data-nosnippet>
An unhandled error has occurred.
<a href="." class="reload">Reload</a>
<span class="dismiss">🗙</span>
</div>
20 changes: 20 additions & 0 deletions AnchorageFiller/AnchorageFiller.Web/Layout/MainLayout.razor.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#blazor-error-ui {
color-scheme: light only;
background: lightyellow;
bottom: 0;
box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
box-sizing: border-box;
display: none;
left: 0;
padding: 0.6rem 1.25rem 0.7rem 1.25rem;
position: fixed;
width: 100%;
z-index: 1000;
}

#blazor-error-ui .dismiss {
cursor: pointer;
position: absolute;
right: 0.75rem;
top: 0.5rem;
}
17 changes: 17 additions & 0 deletions AnchorageFiller/AnchorageFiller.Web/Pages/Home.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
@page "/"
@using AnchorageFiller.Clients

<PageTitle>Home</PageTitle>

<h1>Hello, world!</h1>

Welcome to your new app.

@code {
[Inject] public required IFleetsClient FleetsClient { get; set; }

protected override async Task OnInitializedAsync()
{
var fleets = await FleetsClient.GetRandomFleetAsync();
}
}
5 changes: 5 additions & 0 deletions AnchorageFiller/AnchorageFiller.Web/Pages/NotFound.razor
Original file line number Diff line number Diff line change
@@ -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>
13 changes: 13 additions & 0 deletions AnchorageFiller/AnchorageFiller.Web/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using AnchorageFiller.Clients;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;

var builder = WebAssemblyHostBuilder.CreateDefault(args);


builder.Services
.AddHttpClient<IFleetsClient, FleetsClient>(client =>
{
client.BaseAddress = new(builder.HostEnvironment.BaseAddress, UriKind.Absolute);
});

await builder.Build().RunAsync();
6 changes: 6 additions & 0 deletions AnchorageFiller/AnchorageFiller.Web/Routes.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<Router AppAssembly="typeof(Program).Assembly" NotFoundPage="typeof(Pages.NotFound)">
<Found Context="routeData">
<RouteView RouteData="routeData" DefaultLayout="typeof(Layout.MainLayout)" />
<FocusOnNavigate RouteData="routeData" Selector="h1" />
</Found>
</Router>
10 changes: 10 additions & 0 deletions AnchorageFiller/AnchorageFiller.Web/_Imports.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
@using System.Net.Http
@using System.Net.Http.Json
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using static Microsoft.AspNetCore.Components.Web.RenderMode
@using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.JSInterop
@using AnchorageFiller.Web
@using AnchorageFiller.Web.Layout
10 changes: 10 additions & 0 deletions AnchorageFiller/AnchorageFiller.slnx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<Solution>
<Configurations>
<Platform Name="Any CPU" />
<Platform Name="x64" />
<Platform Name="x86" />
</Configurations>
<Project Path="AnchorageFiller.Web/AnchorageFiller.Web.csproj" />
<Project Path="AnchorageFiller.Clients/AnchorageFiller.Clients.csproj" Id="f463c6d2-1bcd-43f5-bb98-58cd169258f4" />
<Project Path="AnchorageFiller.Server/AnchorageFiller.Server.csproj" />
</Solution>
Loading