From 5b16cda8ea92ca149cc42ae4fc16038e4c5f3e51 Mon Sep 17 00:00:00 2001 From: Leon Hoppe Date: Tue, 21 Jan 2025 14:39:30 +0100 Subject: [PATCH 1/3] Added client side repos --- src/Portfolio.Api/Program.cs | 1 - .../Components/CancellableComponent.cs | 11 ++++++++++ src/Portfolio.Web/Program.cs | 12 ++++++++++- src/Portfolio.Web/Services/AboutRepository.cs | 20 +++++++++++++++++++ .../Services/ProjectRepository.cs | 15 ++++++++++++++ .../Services/TechnologyRepository.cs | 15 ++++++++++++++ .../Services/TimelineRepository.cs | 15 ++++++++++++++ 7 files changed, 87 insertions(+), 2 deletions(-) create mode 100644 src/Portfolio.Web/Components/CancellableComponent.cs create mode 100644 src/Portfolio.Web/Services/AboutRepository.cs create mode 100644 src/Portfolio.Web/Services/ProjectRepository.cs create mode 100644 src/Portfolio.Web/Services/TechnologyRepository.cs create mode 100644 src/Portfolio.Web/Services/TimelineRepository.cs diff --git a/src/Portfolio.Api/Program.cs b/src/Portfolio.Api/Program.cs index e093629..cdef3e7 100644 --- a/src/Portfolio.Api/Program.cs +++ b/src/Portfolio.Api/Program.cs @@ -75,7 +75,6 @@ await using (var scope = app.Services.CreateAsyncScope()) { await db.Database.EnsureCreatedAsync(); } -app.UseHttpsRedirection(); app.MapDefaultEndpoints(); app.MapControllers(); diff --git a/src/Portfolio.Web/Components/CancellableComponent.cs b/src/Portfolio.Web/Components/CancellableComponent.cs new file mode 100644 index 0000000..a2aab92 --- /dev/null +++ b/src/Portfolio.Web/Components/CancellableComponent.cs @@ -0,0 +1,11 @@ +using Microsoft.AspNetCore.Components; + +namespace Portfolio.Web.Components; + +public class CancellableComponent : ComponentBase, IDisposable { + protected CancellationTokenSource TokenSource { get; } = new(); + + public void Dispose() { + TokenSource.Dispose(); + } +} \ No newline at end of file diff --git a/src/Portfolio.Web/Program.cs b/src/Portfolio.Web/Program.cs index d82cbbf..6ab644c 100644 --- a/src/Portfolio.Web/Program.cs +++ b/src/Portfolio.Web/Program.cs @@ -1,4 +1,6 @@ +using Portfolio.Shared.Services; using Portfolio.Web.Components; +using Portfolio.Web.Services; var builder = WebApplication.CreateBuilder(args); @@ -8,6 +10,15 @@ builder.Services.AddRazorComponents() builder.AddServiceDefaults(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); + +builder.Services.AddHttpClient("api", client => { + client.BaseAddress = new Uri("http://api"); +}); + var app = builder.Build(); // Configure the HTTP request pipeline. @@ -17,7 +28,6 @@ if (!app.Environment.IsDevelopment()) { app.UseHsts(); } -app.UseHttpsRedirection(); app.MapDefaultEndpoints(); app.UseAntiforgery(); diff --git a/src/Portfolio.Web/Services/AboutRepository.cs b/src/Portfolio.Web/Services/AboutRepository.cs new file mode 100644 index 0000000..e666782 --- /dev/null +++ b/src/Portfolio.Web/Services/AboutRepository.cs @@ -0,0 +1,20 @@ +using Portfolio.Shared.Models; +using Portfolio.Shared.Services; + +namespace Portfolio.Web.Services; + +internal sealed class AboutRepository(IHttpClientFactory factory) : IAboutRepository { + private About DefaultValue => new() { + AboutMe = string.Empty, + Future = string.Empty + }; + + public async Task GetAbout(CancellationToken ct) { + var client = factory.CreateClient("api"); + var response = await client.GetAsync("api/about", ct); + if (!response.IsSuccessStatusCode) return DefaultValue; + + var data = await response.Content.ReadFromJsonAsync(ct); + return data ?? DefaultValue; + } +} \ No newline at end of file diff --git a/src/Portfolio.Web/Services/ProjectRepository.cs b/src/Portfolio.Web/Services/ProjectRepository.cs new file mode 100644 index 0000000..eccefc4 --- /dev/null +++ b/src/Portfolio.Web/Services/ProjectRepository.cs @@ -0,0 +1,15 @@ +using Portfolio.Shared.Models; +using Portfolio.Shared.Services; + +namespace Portfolio.Web.Services; + +internal sealed class ProjectRepository(IHttpClientFactory factory) : IProjectRepository { + public async Task> GetProjects(CancellationToken ct) { + var client = factory.CreateClient("api"); + var response = await client.GetAsync("api/projects", ct); + if (!response.IsSuccessStatusCode) return []; + + var data = await response.Content.ReadFromJsonAsync>(ct); + return data ?? []; + } +} \ No newline at end of file diff --git a/src/Portfolio.Web/Services/TechnologyRepository.cs b/src/Portfolio.Web/Services/TechnologyRepository.cs new file mode 100644 index 0000000..d723a6d --- /dev/null +++ b/src/Portfolio.Web/Services/TechnologyRepository.cs @@ -0,0 +1,15 @@ +using Portfolio.Shared.Models; +using Portfolio.Shared.Services; + +namespace Portfolio.Web.Services; + +internal sealed class TechnologyRepository(IHttpClientFactory factory) : ITechnologyRepository { + public async Task> GetTechnologies(CancellationToken ct) { + var client = factory.CreateClient("api"); + var response = await client.GetAsync("api/technologies", ct); + if (!response.IsSuccessStatusCode) return []; + + var data = await response.Content.ReadFromJsonAsync>(ct); + return data ?? []; + } +} \ No newline at end of file diff --git a/src/Portfolio.Web/Services/TimelineRepository.cs b/src/Portfolio.Web/Services/TimelineRepository.cs new file mode 100644 index 0000000..0057e61 --- /dev/null +++ b/src/Portfolio.Web/Services/TimelineRepository.cs @@ -0,0 +1,15 @@ +using Portfolio.Shared.Models; +using Portfolio.Shared.Services; + +namespace Portfolio.Web.Services; + +internal sealed class TimelineRepository(IHttpClientFactory factory) : ITimelineRepository { + public async Task> GetTimeline(TimelineEntryType type, CancellationToken ct) { + var client = factory.CreateClient("api"); + var result = await client.GetAsync($"api/timeline/{type}", ct); + if (!result.IsSuccessStatusCode) return []; + + var data = await result.Content.ReadFromJsonAsync>(ct); + return data ?? []; + } +} \ No newline at end of file -- 2.49.1 From a2cab3c84c82e595d56ee40e1b59bbc3a873a9fa Mon Sep 17 00:00:00 2001 From: Leon Hoppe Date: Tue, 21 Jan 2025 15:43:49 +0100 Subject: [PATCH 2/3] Added navigation and base layout --- src/Portfolio.Web/Components/App.razor | 7 +- .../Components/Layout/MainLayout.razor | 28 ++-- .../Components/Layout/MainLayout.razor.css | 97 +------------ .../Components/Layout/NavMenu.razor | 50 +++---- .../Components/Layout/NavMenu.razor.css | 131 ++++++------------ .../Components/Pages/Counter.razor | 19 --- src/Portfolio.Web/Components/Pages/Home.razor | 2 +- .../Components/Pages/Weather.razor | 61 -------- src/Portfolio.Web/Components/Routes.razor | 1 - src/Portfolio.Web/wwwroot/app.css | 32 +++++ src/Portfolio.Web/wwwroot/favicon.ico | Bin 0 -> 10143 bytes src/Portfolio.Web/wwwroot/favicon.png | 3 - src/Portfolio.Web/wwwroot/socials/gitlab.png | 3 + .../wwwroot/socials/instagram.png | 3 + src/Portfolio.Web/wwwroot/socials/mail.png | 3 + 15 files changed, 121 insertions(+), 319 deletions(-) delete mode 100644 src/Portfolio.Web/Components/Pages/Counter.razor delete mode 100644 src/Portfolio.Web/Components/Pages/Weather.razor create mode 100644 src/Portfolio.Web/wwwroot/favicon.ico delete mode 100644 src/Portfolio.Web/wwwroot/favicon.png create mode 100644 src/Portfolio.Web/wwwroot/socials/gitlab.png create mode 100644 src/Portfolio.Web/wwwroot/socials/instagram.png create mode 100644 src/Portfolio.Web/wwwroot/socials/mail.png diff --git a/src/Portfolio.Web/Components/App.razor b/src/Portfolio.Web/Components/App.razor index 939e292..d0c615a 100644 --- a/src/Portfolio.Web/Components/App.razor +++ b/src/Portfolio.Web/Components/App.razor @@ -5,12 +5,15 @@ - - + + + + + diff --git a/src/Portfolio.Web/Components/Layout/MainLayout.razor b/src/Portfolio.Web/Components/Layout/MainLayout.razor index e3b2918..fb2f4a0 100644 --- a/src/Portfolio.Web/Components/Layout/MainLayout.razor +++ b/src/Portfolio.Web/Components/Layout/MainLayout.razor @@ -1,23 +1,11 @@ @inherits LayoutComponentBase -
- +
+ -
-
- About -
- -
- @Body -
-
-
- -
- An unhandled error has occurred. - Reload - 🗙 -
\ No newline at end of file +
+ @Body +
+ \ No newline at end of file diff --git a/src/Portfolio.Web/Components/Layout/MainLayout.razor.css b/src/Portfolio.Web/Components/Layout/MainLayout.razor.css index 38d1f25..84243ae 100644 --- a/src/Portfolio.Web/Components/Layout/MainLayout.razor.css +++ b/src/Portfolio.Web/Components/Layout/MainLayout.razor.css @@ -1,98 +1,9 @@ -.page { - position: relative; - display: flex; - flex-direction: column; -} - main { - flex: 1; + background-color: var(--background); + min-height: 100%; } -.sidebar { - background-image: linear-gradient(180deg, rgb(5, 39, 103) 0%, #3a0647 70%); -} - -.top-row { - background-color: #f7f7f7; - border-bottom: 1px solid #d6d5d5; - justify-content: flex-end; - height: 3.5rem; - display: flex; - align-items: center; -} - - .top-row ::deep a, .top-row ::deep .btn-link { - white-space: nowrap; - margin-left: 1.5rem; - text-decoration: none; - } - - .top-row ::deep a:hover, .top-row ::deep .btn-link:hover { - text-decoration: underline; - } - - .top-row ::deep a:first-child { - overflow: hidden; - text-overflow: ellipsis; - } - -@media (max-width: 640.98px) { - .top-row { - justify-content: space-between; - } - - .top-row ::deep a, .top-row ::deep .btn-link { - margin-left: 0; - } -} - -@media (min-width: 641px) { - .page { - flex-direction: row; - } - - .sidebar { - width: 250px; - height: 100vh; - position: sticky; - top: 0; - } - - .top-row { - position: sticky; - top: 0; - z-index: 1; - } - - .top-row.auth ::deep a:first-child { - flex: 1; - text-align: right; - width: 0; - } - - .top-row, article { - padding-left: 2rem !important; - padding-right: 1.5rem !important; - } -} - -#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; +.nav-box { width: 100%; - z-index: 1000; + position: sticky; } - - #blazor-error-ui .dismiss { - cursor: pointer; - position: absolute; - right: 0.75rem; - top: 0.5rem; - } diff --git a/src/Portfolio.Web/Components/Layout/NavMenu.razor b/src/Portfolio.Web/Components/Layout/NavMenu.razor index 0b37b9d..f739cd2 100644 --- a/src/Portfolio.Web/Components/Layout/NavMenu.razor +++ b/src/Portfolio.Web/Components/Layout/NavMenu.razor @@ -1,29 +1,25 @@ -