Merge branch 'main' into add-about-page
This commit is contained in:
@@ -23,7 +23,7 @@ jobs:
|
|||||||
id: builddeploy
|
id: builddeploy
|
||||||
uses: Azure/static-web-apps-deploy@v1
|
uses: Azure/static-web-apps-deploy@v1
|
||||||
with:
|
with:
|
||||||
azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_MANGO_PEBBLE_07630D403 }}
|
azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_VICTORIOUS_TREE_0B68B6103 }}
|
||||||
repo_token: ${{ secrets.GITHUB_TOKEN }} # Used for Github integrations (i.e. PR comments)
|
repo_token: ${{ secrets.GITHUB_TOKEN }} # Used for Github integrations (i.e. PR comments)
|
||||||
action: "upload"
|
action: "upload"
|
||||||
###### Repository/Build Configurations - These values can be configured to match your app requirements. ######
|
###### Repository/Build Configurations - These values can be configured to match your app requirements. ######
|
||||||
@@ -42,5 +42,5 @@ jobs:
|
|||||||
id: closepullrequest
|
id: closepullrequest
|
||||||
uses: Azure/static-web-apps-deploy@v1
|
uses: Azure/static-web-apps-deploy@v1
|
||||||
with:
|
with:
|
||||||
azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_MANGO_PEBBLE_07630D403 }}
|
azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_VICTORIOUS_TREE_0B68B6103 }}
|
||||||
action: "close"
|
action: "close"
|
||||||
@@ -7,9 +7,13 @@
|
|||||||
<i class="fa-brands fa-github fa-xl"></i>
|
<i class="fa-brands fa-github fa-xl"></i>
|
||||||
</a>
|
</a>
|
||||||
<a href="https://www.linkedin.com/in/beau-findlay/" class="text-slate-200 hover:text-slate-500">
|
<a href="https://www.linkedin.com/in/beau-findlay/" class="text-slate-200 hover:text-slate-500">
|
||||||
<span class="sr-only">YouTube</span>
|
<span class="sr-only">LinkedIn</span>
|
||||||
<i class="fa-brands fa-linkedin fa-xl"></i>
|
<i class="fa-brands fa-linkedin fa-xl"></i>
|
||||||
</a>
|
</a>
|
||||||
|
<a href="mailto:me@beaufindlay.com" class="text-slate-200 hover:text-slate-500">
|
||||||
|
<span class="sr-only">Email</span>
|
||||||
|
<i class="fa-regular fa-envelope fa-xl"></i>
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<p class="mt-8 text-xs leading-5 text-slate-100 md:order-1 md:mt-0">
|
<p class="mt-8 text-xs leading-5 text-slate-100 md:order-1 md:mt-0">
|
||||||
© @DateTime.UtcNow.Year Beau Findlay. All rights reserved.
|
© @DateTime.UtcNow.Year Beau Findlay. All rights reserved.
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<div class="flex flex-col min-h-screen fade-in">
|
<div class="flex flex-col min-h-screen fade-in">
|
||||||
<NavBar/>
|
<NavBar/>
|
||||||
|
|
||||||
<div class="px-4 md:px-12 py-4">
|
<div class="flex-1 px-4 md:px-12 py-4">
|
||||||
@Body
|
@Body
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -2,50 +2,63 @@
|
|||||||
|
|
||||||
@inject IJSRuntime JSRuntime
|
@inject IJSRuntime JSRuntime
|
||||||
|
|
||||||
@if (!hasPreviouslyRendered)
|
<PageTitle>About - Beau Findlay</PageTitle>
|
||||||
|
|
||||||
|
@if (comingSoon)
|
||||||
{
|
{
|
||||||
<h1 class="text-4xl">
|
<div class="text-center">
|
||||||
<Typewriter Text="This app"/>
|
<h1 class="text-4xl">Coming soon...</h1>
|
||||||
</h1>
|
</div>
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
<h1 class="text-4xl">This app<span class="blinking-cursor">|</span></h1>
|
@if (!hasPreviouslyRendered)
|
||||||
|
{
|
||||||
|
<h1 class="text-4xl">
|
||||||
|
<Typewriter Text="This app"/>
|
||||||
|
</h1>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<h1 class="text-4xl">This app<span class="blinking-cursor">|</span></h1>
|
||||||
|
}
|
||||||
|
|
||||||
|
<p class="py-4 text-xl">Below is a brief outline of how this app is made and what technologies are used. If you'd like to dive straight in then full project is available on my <Anchor Href="https://github.com/bdfin/my-portfolio">GitHub</Anchor>.</p>
|
||||||
|
|
||||||
|
<section class="py-6" id="@FrontEndSection">
|
||||||
|
<h2 class="text-2xl">Front-end</h2>
|
||||||
|
|
||||||
|
<p class="py-4">I wanted to create a decent, modern client-side experience for this app and given my <em class="text-xs">(very...)</em> limited front-end expertise I decided to choose <Anchor Href="https://dotnet.microsoft.com/en-us/apps/aspnet/web-apps/blazor">.NET Blazor Webassembly</Anchor>. Blazor is Microsoft's take on component-based SPAs (single page applications) and offers us back-end focussed devs a way of producing decent client experiences without needing to dive into another front-end specific technology.</p>
|
||||||
|
|
||||||
|
<p class="py-4">Blazor traditionally came in two flavours, server and webassembly with an additional third option (Blazor Web App) recently released with .NET 8 which is an amalgamation of both. <Anchor Href="https://learn.microsoft.com/en-us/aspnet/core/blazor/hosting-models?view=aspnetcore-8.0#blazor-server">Blazor Server</Anchor> initially generates content on the server and utilises web-sockets to communicate dynamic UI updates with the client without requiring a page load, whereas <Anchor Href="https://learn.microsoft.com/en-us/aspnet/core/blazor/hosting-models?view=aspnetcore-8.0#blazor-webassembly">Blazor Webassembly</Anchor> downloads the entire app to the client browser on first load alongside a light-weight .NET run-time to execute code directly on the browsers UI thread.</p>
|
||||||
|
|
||||||
|
<p class="py-4">As Blazor server requires a dedicated server to host the application, I chose Blazor webassembly to enable me to host this app for free using an <Anchor Href="https://azure.microsoft.com/en-gb/products/app-service/static">Azure Static Web App</Anchor>. You can read more about this in the <a @onclick="() => ScrollToElementAsync(HostingSection)" class="underline underline-offset-2 cursor-pointer">hosting</a> section.</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="py-6" id="@BackEndSection">
|
||||||
|
<h2 class="text-2xl pb-4">Back-end</h2>
|
||||||
|
<p class="my-4">As the </p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
|
||||||
|
<section class="py-6" id="@HostingSection">
|
||||||
|
<h2 class="text-2xl pb-4">Hosting</h2>
|
||||||
|
<p></p>
|
||||||
|
</section>
|
||||||
}
|
}
|
||||||
|
|
||||||
<p class="py-4 text-xl">Below is a brief outline of how this app is made and what technologies are used. If you'd like to dive straight in then full project is available on my <Anchor Href="https://github.com/bdfin/my-portfolio">GitHub</Anchor>.</p>
|
|
||||||
|
|
||||||
<section class="py-6" id="@FrontEndSection">
|
<AnchorNavigation/>
|
||||||
<h2 class="text-2xl">Front-end</h2>
|
|
||||||
|
|
||||||
<p class="py-4">I wanted to create a decent, modern client-side experience for this app and given my <em class="text-xs">(very...)</em> limited front-end expertise I decided to choose <Anchor Href="https://dotnet.microsoft.com/en-us/apps/aspnet/web-apps/blazor">.NET Blazor Webassembly</Anchor>. Blazor is Microsoft's take on component-based SPAs (single page applications) and offers us back-end focussed devs a way of producing decent client experiences without needing to dive into another front-end specific technology.</p>
|
|
||||||
|
|
||||||
<p class="py-4">Blazor traditionally came in two flavours, server and webassembly with an additional third option (Blazor Web App) recently released with .NET 8 which is an amalgamation of both. <Anchor Href="https://learn.microsoft.com/en-us/aspnet/core/blazor/hosting-models?view=aspnetcore-8.0#blazor-server">Blazor Server</Anchor> initially generates content on the server and utilises web-sockets to communicate dynamic UI updates with the client without requiring a page load, whereas <Anchor Href="https://learn.microsoft.com/en-us/aspnet/core/blazor/hosting-models?view=aspnetcore-8.0#blazor-webassembly">Blazor Webassembly</Anchor> downloads the entire app to the client browser on first load alongside a light-weight .NET run-time to execute code directly on the browsers UI thread.</p>
|
|
||||||
|
|
||||||
<p class="py-4">As Blazor server requires a dedicated server to host the application, I chose Blazor webassembly to enable me to host this app for free using an <Anchor Href="https://azure.microsoft.com/en-gb/products/app-service/static">Azure Static Web App</Anchor>. You can read more about this in the <a @onclick="() => ScrollToElementAsync(HostingSection)" class="underline underline-offset-2 cursor-pointer">hosting</a> section.</p>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section class="py-6" id="@BackEndSection">
|
|
||||||
<h2 class="text-2xl pb-4">Back-end</h2>
|
|
||||||
<p class="my-4">As the </p>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
|
|
||||||
<section class="py-6" id="@HostingSection">
|
|
||||||
<h2 class="text-2xl pb-4">Hosting</h2>
|
|
||||||
<p></p>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<AnchorNavigation />
|
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private const string ComponentKey = "ComponentRendered_About";
|
private const string ComponentKey = "ComponentRendered_About";
|
||||||
private const string FrontEndSection = "front-end";
|
private const string FrontEndSection = "front-end";
|
||||||
private const string BackEndSection = "back-end";
|
private const string BackEndSection = "back-end";
|
||||||
private const string HostingSection = "hosting";
|
private const string HostingSection = "hosting";
|
||||||
|
|
||||||
private bool hasPreviouslyRendered;
|
private bool hasPreviouslyRendered;
|
||||||
|
private bool comingSoon = true;
|
||||||
|
|
||||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||||
{
|
{
|
||||||
if (firstRender)
|
if (firstRender)
|
||||||
@@ -59,7 +72,7 @@ else
|
|||||||
{
|
{
|
||||||
await JSRuntime.InvokeVoidAsync("localStorage.setItem", ComponentKey, "true");
|
await JSRuntime.InvokeVoidAsync("localStorage.setItem", ComponentKey, "true");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (previousValue != hasPreviouslyRendered)
|
if (previousValue != hasPreviouslyRendered)
|
||||||
{
|
{
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
@@ -71,4 +84,5 @@ else
|
|||||||
{
|
{
|
||||||
await JSRuntime.InvokeVoidAsync("scrollToElement", elementId);
|
await JSRuntime.InvokeVoidAsync("scrollToElement", elementId);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -3,6 +3,8 @@
|
|||||||
@inject HttpClient HttpClient
|
@inject HttpClient HttpClient
|
||||||
@inject IJSRuntime JSRuntime
|
@inject IJSRuntime JSRuntime
|
||||||
|
|
||||||
|
<PageTitle>Contact - Beau Findlay</PageTitle>
|
||||||
|
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
<h1 class="text-4xl">Contact</h1>
|
<h1 class="text-4xl">Contact</h1>
|
||||||
|
|
||||||
@@ -19,14 +21,14 @@
|
|||||||
<div class="sm:col-span-2">
|
<div class="sm:col-span-2">
|
||||||
<label for="name" class="block font-semibold leading-6">Name</label>
|
<label for="name" class="block font-semibold leading-6">Name</label>
|
||||||
<div class="mt-2.5">
|
<div class="mt-2.5">
|
||||||
<InputText id="name" @bind-Value="contactInput.Name" class="block w-full text-lg border-0 px-3.5 py-2 bg-black shadow ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-gray-600"/>
|
<InputText id="name" @bind-Value="contactInput.Name" class="block w-full text-lg border-0 px-3.5 py-2 bg-black shadow ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-gray-600" autocomplete="given-name"/>
|
||||||
<ValidationMessage For="() => contactInput.Name" class="text-red-600"/>
|
<ValidationMessage For="() => contactInput.Name" class="text-red-600"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="sm:col-span-2">
|
<div class="sm:col-span-2">
|
||||||
<label for="email" class="block font-semibold leading-6">Email</label>
|
<label for="email" class="block font-semibold leading-6">Email</label>
|
||||||
<div class="mt-2.5">
|
<div class="mt-2.5">
|
||||||
<InputText id="email" @bind-Value="contactInput.Email" class="block w-full text-lg border-0 px-3.5 py-2 bg-black shadow ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-gray-600"/>
|
<InputText id="email" @bind-Value="contactInput.Email" class="block w-full text-lg border-0 px-3.5 py-2 bg-black shadow ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-gray-600" autocomplete="email"/>
|
||||||
<ValidationMessage For="() => contactInput.Email" class="text-red-600"/>
|
<ValidationMessage For="() => contactInput.Email" class="text-red-600"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -666,6 +666,10 @@ video {
|
|||||||
max-width: 36rem;
|
max-width: 36rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.flex-1 {
|
||||||
|
flex: 1 1 0%;
|
||||||
|
}
|
||||||
|
|
||||||
.flex-shrink-0 {
|
.flex-shrink-0 {
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 5.4 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 423 B |
Binary file not shown.
|
After Width: | Height: | Size: 862 B |
@@ -2,11 +2,24 @@
|
|||||||
<html lang="en">
|
<html lang="en">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
|
<script id="cookieyes"
|
||||||
|
type="text/javascript"
|
||||||
|
src="https://cdn-cookieyes.com/client_data/a05e8ecc917e725a2226b46a/script.js"></script>
|
||||||
<meta charset="utf-8"/>
|
<meta charset="utf-8"/>
|
||||||
<meta name="viewport"
|
<meta name="viewport"
|
||||||
content="width=device-width, initial-scale=1.0"/>
|
content="width=device-width, initial-scale=1.0"/>
|
||||||
|
<meta property="description" content="A Software Developer">
|
||||||
|
<meta property="og:title" content="Beau Findlay" />
|
||||||
|
<meta property="og:description" content="A Software Developer">
|
||||||
|
<meta property="og:type" content="website" />
|
||||||
|
<meta property="og:image" content="images/beaufindlay-logo.png" />
|
||||||
|
<meta property="og:url" content="https://beaufindlay.com" />
|
||||||
<title>Beau Findlay</title>
|
<title>Beau Findlay</title>
|
||||||
<base href="/"/>
|
<base href="/"/>
|
||||||
|
<link rel="apple-touch-icon" sizes="180x180" href="images/apple-touch-icon.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="32x32" href="images/favicon-32x32.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="16x16" href="images/favicon-16x16.png">
|
||||||
|
<link rel="manifest" href="/site.webmanifest">
|
||||||
<link rel="stylesheet"
|
<link rel="stylesheet"
|
||||||
href="css/app.min.css"/>
|
href="css/app.min.css"/>
|
||||||
<link rel="stylesheet"
|
<link rel="stylesheet"
|
||||||
@@ -17,16 +30,19 @@
|
|||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="bg-black font-mono text-slate-50 min-h-screen antialiased">
|
<body class="bg-black font-mono text-slate-50 min-h-screen antialiased">
|
||||||
<div id="app" class="h-full">
|
<div id="app"
|
||||||
|
class="h-full">
|
||||||
<div class="flex items-center justify-center text-2xl">
|
<div class="flex items-center justify-center text-2xl">
|
||||||
<p class="py-10">
|
<p class="py-10">
|
||||||
Loading beaufindlay.com<span class="blinking-cursor">|</span>
|
Loading
|
||||||
|
beaufindlay.com<span class="blinking-cursor">|</span>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script src="js/smoothScroll.js"></script>
|
<script src="js/smoothScroll.js"></script>
|
||||||
<script src="_framework/blazor.webassembly.js"></script>
|
<script src="_framework/blazor.webassembly.js"></script>
|
||||||
<script src="https://www.google.com/recaptcha/api.js?render=6LcvxZIpAAAAAOIP5L6kGngwDZRpwkTdMezPn06x" async
|
<script src="https://www.google.com/recaptcha/api.js?render=6LcvxZIpAAAAAOIP5L6kGngwDZRpwkTdMezPn06x"
|
||||||
|
async
|
||||||
defer></script>
|
defer></script>
|
||||||
<script src="js/recaptcha.js"></script>
|
<script src="js/recaptcha.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
19
BeauFindlay/src/BeauFindlay.Client/wwwroot/site.webmanifest
Normal file
19
BeauFindlay/src/BeauFindlay.Client/wwwroot/site.webmanifest
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"short_name": "",
|
||||||
|
"icons": [
|
||||||
|
{
|
||||||
|
"src": "images/android-chrome-192x192.png",
|
||||||
|
"sizes": "192x192",
|
||||||
|
"type": "image/png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "images/android-chrome-512x512.png",
|
||||||
|
"sizes": "512x512",
|
||||||
|
"type": "image/png"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"theme_color": "#ffffff",
|
||||||
|
"background_color": "#ffffff",
|
||||||
|
"display": "standalone"
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user