Compare commits
11 Commits
5558aecb5a
...
5283985026
Author | SHA1 | Date | |
---|---|---|---|
5283985026 | |||
a9c4b3a144 | |||
2ea52759b8 | |||
7cad3204df | |||
eb152aaa09 | |||
a75536d08b | |||
08eed3c71e | |||
1a20749809 | |||
eed1e3ad8d | |||
6ef492016c | |||
bb088e3107 |
@ -77,6 +77,7 @@ public sealed class BlogApiController : ControllerBase
|
|||||||
excerpt = _blogPostService.RenderExcerpt(post, out bool trimmed),
|
excerpt = _blogPostService.RenderExcerpt(post, out bool trimmed),
|
||||||
content = includeContent ? _blogPostService.RenderPost(post) : null,
|
content = includeContent ? _blogPostService.RenderPost(post) : null,
|
||||||
trimmed,
|
trimmed,
|
||||||
|
tags = post.Tags.Select(t => t.Replace(' ', '-')),
|
||||||
url = new
|
url = new
|
||||||
{
|
{
|
||||||
year = post.Published.ToString("yyyy"),
|
year = post.Published.ToString("yyyy"),
|
||||||
|
71
OliverBooth/Controllers/ContactController.cs
Normal file
71
OliverBooth/Controllers/ContactController.cs
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
using MailKitSimplified.Sender.Services;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.Extensions.Primitives;
|
||||||
|
|
||||||
|
namespace OliverBooth.Controllers;
|
||||||
|
|
||||||
|
[Controller]
|
||||||
|
[Route("contact/submit")]
|
||||||
|
public class ContactController : Controller
|
||||||
|
{
|
||||||
|
private readonly ILogger<ContactController> _logger;
|
||||||
|
private readonly IConfiguration _configuration;
|
||||||
|
private readonly IConfigurationSection _destination;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="ContactController" /> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="logger">The logger.</param>
|
||||||
|
/// <param name="configuration">The configuration.</param>
|
||||||
|
public ContactController(ILogger<ContactController> logger, IConfiguration configuration)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
_configuration = configuration;
|
||||||
|
_destination = configuration.GetSection("Mail").GetSection("Destination");
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("{_?}")]
|
||||||
|
public IActionResult OnGet(string _)
|
||||||
|
{
|
||||||
|
_logger.LogWarning("Method GET for endpoint {Path} is not supported!", Request.Path);
|
||||||
|
return RedirectToPage("/Contact/Index");
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("other")]
|
||||||
|
public async Task<IActionResult> HandleMiscellaneous()
|
||||||
|
{
|
||||||
|
if (!Request.HasFormContentType)
|
||||||
|
{
|
||||||
|
return RedirectToPage("/Contact/Other");
|
||||||
|
}
|
||||||
|
|
||||||
|
IFormCollection form = Request.Form;
|
||||||
|
StringValues name = form["name"];
|
||||||
|
StringValues email = form["email"];
|
||||||
|
StringValues subject = form["subject"];
|
||||||
|
StringValues message = form["message"];
|
||||||
|
|
||||||
|
await using SmtpSender sender = CreateSender();
|
||||||
|
await sender.WriteEmail
|
||||||
|
.To("Oliver Booth", _destination.GetValue<string>("Other"))
|
||||||
|
.From(name, email)
|
||||||
|
.Subject(subject)
|
||||||
|
.BodyHtml(message)
|
||||||
|
.SendAsync();
|
||||||
|
|
||||||
|
TempData["Success"] = true;
|
||||||
|
return RedirectToPage("/Contact/Result");
|
||||||
|
}
|
||||||
|
|
||||||
|
private SmtpSender CreateSender()
|
||||||
|
{
|
||||||
|
IConfigurationSection mailSection = _configuration.GetSection("Mail");
|
||||||
|
string? mailServer = mailSection.GetSection("Server").Value;
|
||||||
|
string? mailUsername = mailSection.GetSection("Username").Value;
|
||||||
|
string? mailPassword = mailSection.GetSection("Password").Value;
|
||||||
|
|
||||||
|
var sender = SmtpSender.Create(mailServer);
|
||||||
|
sender.SetCredential(mailUsername, mailPassword);
|
||||||
|
return sender;
|
||||||
|
}
|
||||||
|
}
|
@ -34,6 +34,9 @@ internal sealed class BlogPost : IBlogPost
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public string Slug { get; internal set; } = string.Empty;
|
public string Slug { get; internal set; } = string.Empty;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public IReadOnlyList<string> Tags { get; internal set; } = ArraySegment<string>.Empty;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public string Title { get; internal set; } = string.Empty;
|
public string Title { get; internal set; } = string.Empty;
|
||||||
|
|
||||||
|
@ -28,5 +28,10 @@ internal sealed class BlogPostConfiguration : IEntityTypeConfiguration<BlogPost>
|
|||||||
builder.Property(e => e.DisqusPath).IsRequired(false);
|
builder.Property(e => e.DisqusPath).IsRequired(false);
|
||||||
builder.Property(e => e.Visibility).HasConversion(new EnumToStringConverter<BlogPostVisibility>()).IsRequired();
|
builder.Property(e => e.Visibility).HasConversion(new EnumToStringConverter<BlogPostVisibility>()).IsRequired();
|
||||||
builder.Property(e => e.Password).HasMaxLength(255).IsRequired(false);
|
builder.Property(e => e.Password).HasMaxLength(255).IsRequired(false);
|
||||||
|
builder.Property(e => e.Tags).IsRequired()
|
||||||
|
.HasConversion(
|
||||||
|
tags => string.Join(' ', tags.Select(t => t.Replace(' ', '-'))),
|
||||||
|
tags => tags.Split(' ', StringSplitOptions.RemoveEmptyEntries)
|
||||||
|
.Select(t => t.Replace('-', ' ')).ToArray());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -63,6 +63,12 @@ public interface IBlogPost
|
|||||||
/// <value>The slug of the post.</value>
|
/// <value>The slug of the post.</value>
|
||||||
string Slug { get; }
|
string Slug { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the tags of the post.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The tags of the post.</value>
|
||||||
|
IReadOnlyList<string> Tags { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the title of the post.
|
/// Gets the title of the post.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -64,6 +64,13 @@
|
|||||||
<a href="#disqus_thread" data-disqus-identifier="@post.GetDisqusIdentifier()">0 Comments</a>
|
<a href="#disqus_thread" data-disqus-identifier="@post.GetDisqusIdentifier()">0 Comments</a>
|
||||||
}
|
}
|
||||||
</p>
|
</p>
|
||||||
|
<div>
|
||||||
|
@foreach (string tag in post.Tags)
|
||||||
|
{
|
||||||
|
<a asp-page="Index" asp-route-tag="@tag" class="badge bg-secondary">@tag</a>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
<hr>
|
||||||
|
|
||||||
<article data-blog-post="true" data-blog-id="@post.Id.ToString("D")">
|
<article data-blog-post="true" data-blog-id="@post.Id.ToString("D")">
|
||||||
<p class="text-center">Loading ...</p>
|
<p class="text-center">Loading ...</p>
|
||||||
|
@ -10,12 +10,8 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script id="blog-post-template" type="text/x-handlebars-template">
|
<script id="blog-post-template" type="text/x-handlebars-template">
|
||||||
<div class="card-body">
|
<div class="card-header">
|
||||||
<h2>
|
<span class="text-muted">
|
||||||
<a href="{{post.url}}"> {{post.title}}</a>
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
<p class="text-muted">
|
|
||||||
<img class="blog-author-icon" src="{{author.avatar}}" alt="{{author.name}}">
|
<img class="blog-author-icon" src="{{author.avatar}}" alt="{{author.name}}">
|
||||||
<span>{{author.name}}<span>
|
<span>{{author.name}}<span>
|
||||||
<span> • </span>
|
<span> • </span>
|
||||||
@ -26,7 +22,12 @@
|
|||||||
Loading comment count …
|
Loading comment count …
|
||||||
</a>
|
</a>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</p>
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<h2>
|
||||||
|
<a href="{{post.url}}"> {{post.title}}</a>
|
||||||
|
</h2>
|
||||||
|
|
||||||
<p>{{{post.excerpt}}}</p>
|
<p>{{{post.excerpt}}}</p>
|
||||||
|
|
||||||
@ -38,4 +39,9 @@
|
|||||||
</p>
|
</p>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
|
<div class="card-footer">
|
||||||
|
{{#each post.tags}}
|
||||||
|
<a href="?tag={{this}}" class="badge text-bg-dark">{{this}}</a>
|
||||||
|
{{/each}}
|
||||||
|
</div>
|
||||||
</script>
|
</script>
|
||||||
|
@ -23,13 +23,13 @@
|
|||||||
<input type="hidden" name="contact-type" value="job-opportunity">
|
<input type="hidden" name="contact-type" value="job-opportunity">
|
||||||
|
|
||||||
<div class="form-group" style="margin-top: 10px;">
|
<div class="form-group" style="margin-top: 10px;">
|
||||||
<label for="your-name">Your Name</label>
|
<label for="name">Your Name</label>
|
||||||
<input type="text" class="form-control" id="your-name" name="your-name" placeholder="Who are you?" required>
|
<input type="text" class="form-control" id="name" name="name" placeholder="Who are you?" required>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group" style="margin-top: 10px;">
|
<div class="form-group" style="margin-top: 10px;">
|
||||||
<label for="your-email">Your Email Address</label>
|
<label for="email">Your Email Address</label>
|
||||||
<input type="email" class="form-control" id="your-email" name="your-email" placeholder="How can I reach you?" required>
|
<input type="email" class="form-control" id="email" name="email" placeholder="How can I reach you?" required>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group" style="margin-top: 10px;">
|
<div class="form-group" style="margin-top: 10px;">
|
||||||
@ -49,7 +49,7 @@
|
|||||||
|
|
||||||
<div class="form-group" style="margin-top: 10px;">
|
<div class="form-group" style="margin-top: 10px;">
|
||||||
<label for="starting-salary">Starting Salary</label>
|
<label for="starting-salary">Starting Salary</label>
|
||||||
<input type="number" class="form-control" id="starting-salary" name="starting-salary" placeholder="e.g. £30,000" required>
|
<input type="text" class="form-control" id="starting-salary" name="starting-salary" placeholder="e.g. £30,000" required>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button type="submit" class="btn btn-primary" style="margin-top: 10px;">Submit</button>
|
<button type="submit" class="btn btn-primary" style="margin-top: 10px;">Submit</button>
|
||||||
|
@ -18,8 +18,8 @@
|
|||||||
will review it as soon as I can!
|
will review it as soon as I can!
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Below is a <strong>non-exhaustive</strong> list of the repositories that are currently active. This list is subject
|
Below is a <mark>non-exhaustive</mark> list of the repositories that are currently active. This list is subject
|
||||||
to change at any time, and may not be up to date. For a better gauge of what I am currently working on, please
|
to change at any time, but may not be up-to-date. For a better gauge of what I am currently working on, please
|
||||||
visit my <a href="https://github.com/oliverbooth">GitHub profile</a>. If you would like to contribute to a project
|
visit my <a href="https://github.com/oliverbooth">GitHub profile</a>. If you would like to contribute to a project
|
||||||
that is not in active development, I would recommend that you fork the repository and continue development on your
|
that is not in active development, I would recommend that you fork the repository and continue development on your
|
||||||
own as unfortunately I have no timeline as to when I will start such projects back up again.
|
own as unfortunately I have no timeline as to when I will start such projects back up again.
|
||||||
|
@ -18,17 +18,17 @@
|
|||||||
can.
|
can.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<form>
|
<form method="post" asp-controller="Contact" asp-action="HandleMiscellaneous">
|
||||||
<input type="hidden" name="contact-type" value="other">
|
<input type="hidden" name="contact-type" value="other">
|
||||||
|
|
||||||
<div class="form-group" style="margin-top: 10px;">
|
<div class="form-group" style="margin-top: 10px;">
|
||||||
<label for="your-name">Your Name</label>
|
<label for="name">Your Name</label>
|
||||||
<input type="text" class="form-control" id="your-name" name="your-name" placeholder="Who are you?" required>
|
<input type="text" class="form-control" id="name" name="name" placeholder="Who are you?" required>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group" style="margin-top: 10px;">
|
<div class="form-group" style="margin-top: 10px;">
|
||||||
<label for="your-email">Your Email Address</label>
|
<label for="email">Your Email Address</label>
|
||||||
<input type="email" class="form-control" id="your-email" name="your-email" placeholder="How can I reach you?" required>
|
<input type="email" class="form-control" id="email" name="email" placeholder="How can I reach you?" required>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group" style="margin-top: 10px;">
|
<div class="form-group" style="margin-top: 10px;">
|
||||||
|
@ -40,13 +40,13 @@
|
|||||||
<input type="hidden" name="contact-type" value="project-idea">
|
<input type="hidden" name="contact-type" value="project-idea">
|
||||||
|
|
||||||
<div class="form-group" style="margin-top: 10px;">
|
<div class="form-group" style="margin-top: 10px;">
|
||||||
<label for="project-title">Your Name</label>
|
<label for="name">Your Name</label>
|
||||||
<input type="text" class="form-control" id="name" name="project-title" placeholder="Who are you?">
|
<input type="text" class="form-control" id="name" name="name" placeholder="Who are you?">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group" style="margin-top: 10px;">
|
<div class="form-group" style="margin-top: 10px;">
|
||||||
<label for="project-title">Your Email Address</label>
|
<label for="email">Your Email Address</label>
|
||||||
<input type="email" class="form-control" id="email" name="project-title" placeholder="How can I reach you, if I need to?">
|
<input type="email" class="form-control" id="email" name="email" placeholder="How can I reach you, if I need to?">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group" style="margin-top: 10px;">
|
<div class="form-group" style="margin-top: 10px;">
|
||||||
|
25
OliverBooth/Pages/Contact/Result.cshtml
Normal file
25
OliverBooth/Pages/Contact/Result.cshtml
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
@page
|
||||||
|
@model OliverBooth.Pages.Contact.Result
|
||||||
|
|
||||||
|
@{
|
||||||
|
ViewData["Title"] = "Contact";
|
||||||
|
}
|
||||||
|
|
||||||
|
@if (Model.WasSuccessful)
|
||||||
|
{
|
||||||
|
<h1 class="display-4 text-success"><i class="fa-solid fa-circle-check"></i> Sent successfully!</h1>
|
||||||
|
<p>Thank you for getting in touch. I will get back to you as soon as possible.</p>
|
||||||
|
<p>
|
||||||
|
In the meantime, why not check out my <a asp-page="/Blog/Index">blog</a> or
|
||||||
|
<a asp-page="/Projects/Index">portfolio</a>?
|
||||||
|
</p>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<h1 class="display-4 text-danger"><i class="fa-solid fa-circle-xmark"></i> A problem occured</h1>
|
||||||
|
<p>Sorry, something went wrong. This has been logged and if I'll get to it soon.</p>
|
||||||
|
<p>
|
||||||
|
You can <a asp-page="Index">try again</a>, or check out my <a asp-page="/Blog/Index">blog</a> or
|
||||||
|
<a asp-page="/Projects/Index">portfolio</a>!
|
||||||
|
</p>
|
||||||
|
}
|
23
OliverBooth/Pages/Contact/Result.cshtml.cs
Normal file
23
OliverBooth/Pages/Contact/Result.cshtml.cs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||||
|
|
||||||
|
namespace OliverBooth.Pages.Contact;
|
||||||
|
|
||||||
|
public class Result : PageModel
|
||||||
|
{
|
||||||
|
public bool WasSuccessful { get; private set; }
|
||||||
|
|
||||||
|
public IActionResult OnGet()
|
||||||
|
{
|
||||||
|
if (!TempData.ContainsKey("Success"))
|
||||||
|
{
|
||||||
|
return RedirectToPage("/Contact/Index");
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma warning disable S1125
|
||||||
|
WasSuccessful = TempData["Success"] is true;
|
||||||
|
#pragma warning restore S1125
|
||||||
|
TempData.Remove("Success");
|
||||||
|
return Page();
|
||||||
|
}
|
||||||
|
}
|
@ -4,11 +4,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
<h1 class="display-4">Projects</h1>
|
<h1 class="display-4">Projects</h1>
|
||||||
<h2 class="lead" style="margin-top: 20px">Ongoing Development</h2>
|
|
||||||
<p>This is work that I am actively developing and/or maintaining.</p>
|
|
||||||
<div class="card-group row">
|
<div class="card-group row">
|
||||||
<div class="col-xs-1 col-md-6 col-lg-6 d-flex align-items-stretch">
|
<div class="col-xs-1 col-md-6 col-lg-6 d-flex align-items-stretch">
|
||||||
<div class="card">
|
<div class="card border-success project-card">
|
||||||
|
<div class="card-header text-bg-success">In Active Development</div>
|
||||||
<img src="~/img/projects/hero/x10d-1280x640.png" class="card-img-top" alt="X10D">
|
<img src="~/img/projects/hero/x10d-1280x640.png" class="card-img-top" alt="X10D">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h5 class="card-title">X10D</h5>
|
<h5 class="card-title">X10D</h5>
|
||||||
@ -18,11 +18,12 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-xs-1 col-md-6 col-lg-6 d-flex align-items-stretch">
|
<div class="col-xs-1 col-md-6 col-lg-6 d-flex align-items-stretch">
|
||||||
<div class="card">
|
<div class="card border-success project-card">
|
||||||
|
<div class="card-header text-bg-success">In Active Development</div>
|
||||||
<img src="~/img/projects/hero/brackeysbot-1280x640.png" class="card-img-top" alt="BrackeysBot">
|
<img src="~/img/projects/hero/brackeysbot-1280x640.png" class="card-img-top" alt="BrackeysBot">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h5 class="card-title">BrackeysBot</h5>
|
<h5 class="card-title">BrackeysBot</h5>
|
||||||
<p class="card-text">A collection of self-contained Discord bots that power the <a href="https://discord.gg/brackeys">Brackeys Community</a> Disccord server.</p>
|
<p class="card-text">A collection of self-contained Discord bots that power the <a href="https://discord.gg/brackeys">Brackeys Community</a> Discord server.</p>
|
||||||
<a href="https://github.com/BrackeysBot" class="btn btn-primary">View on GitHub</a>
|
<a href="https://github.com/BrackeysBot" class="btn btn-primary">View on GitHub</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -30,7 +31,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="card-group row" style="margin-top: 20px;">
|
<div class="card-group row" style="margin-top: 20px;">
|
||||||
<div class="col-xs-1 col-md-6 col-lg-6 d-flex align-items-stretch">
|
<div class="col-xs-1 col-md-6 col-lg-6 d-flex align-items-stretch">
|
||||||
<div class="card">
|
<div class="card border-success project-card">
|
||||||
|
<div class="card-header text-bg-success">In Active Development</div>
|
||||||
<img src="~/img/projects/hero/none-1280x640.png" class="card-img-top" alt="Project KW">
|
<img src="~/img/projects/hero/none-1280x640.png" class="card-img-top" alt="Project KW">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h5 class="card-title">Project KW</h5>
|
<h5 class="card-title">Project KW</h5>
|
||||||
@ -41,14 +43,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h2 class="lead" style="margin-top: 20px">Past Work</h2>
|
|
||||||
<p>
|
|
||||||
This is work that I have deemed either "ready for public consumption" or "no further work needs to be done". It
|
|
||||||
includes projects that are both retired and still in use.
|
|
||||||
</p>
|
|
||||||
<div class="card-group row" style="margin-top: 20px;">
|
<div class="card-group row" style="margin-top: 20px;">
|
||||||
<div class="col-xs-1 col-md-6 col-lg-6 d-flex align-items-stretch">
|
<div class="col-xs-1 col-md-6 col-lg-6 d-flex align-items-stretch">
|
||||||
<div class="card">
|
<div class="card border-info project-card">
|
||||||
|
<div class="card-header text-bg-info">Past Work</div>
|
||||||
<img src="~/img/projects/hero/fiveoclock-1280x640.png" class="card-img-top" alt="It's 5 O'Clock Somewhere">
|
<img src="~/img/projects/hero/fiveoclock-1280x640.png" class="card-img-top" alt="It's 5 O'Clock Somewhere">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h5 class="card-title">It's 5 O'Clock Somewhere</h5>
|
<h5 class="card-title">It's 5 O'Clock Somewhere</h5>
|
||||||
@ -58,7 +56,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-xs-1 col-md-6 col-lg-6 d-flex align-items-stretch">
|
<div class="col-xs-1 col-md-6 col-lg-6 d-flex align-items-stretch">
|
||||||
<div class="card">
|
<div class="card border-info project-card">
|
||||||
|
<div class="card-header text-bg-info">Past Work</div>
|
||||||
<img src="~/img/projects/hero/birthday-1280x640.png" class="card-img-top" alt="Is It My Birthday?">
|
<img src="~/img/projects/hero/birthday-1280x640.png" class="card-img-top" alt="Is It My Birthday?">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h5 class="card-title">Is It My Birthday?</h5>
|
<h5 class="card-title">Is It My Birthday?</h5>
|
||||||
@ -70,7 +69,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="card-group row" style="margin-top: 20px;">
|
<div class="card-group row" style="margin-top: 20px;">
|
||||||
<div class="col-xs-1 col-md-6 col-lg-6 d-flex align-items-stretch">
|
<div class="col-xs-1 col-md-6 col-lg-6 d-flex align-items-stretch">
|
||||||
<div class="card">
|
<div class="card border-info project-card">
|
||||||
|
<div class="card-header text-bg-info">Past Work</div>
|
||||||
<img src="~/img/projects/hero/candyjam-1280x640.png" class="card-img-top" alt="Scrolling Candy Apple Saga">
|
<img src="~/img/projects/hero/candyjam-1280x640.png" class="card-img-top" alt="Scrolling Candy Apple Saga">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h5 class="card-title">Scrolling Candy Apple Saga</h5>
|
<h5 class="card-title">Scrolling Candy Apple Saga</h5>
|
||||||
@ -80,8 +80,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-xs-1 col-md-6 col-lg-6 d-flex align-items-stretch">
|
<div class="col-xs-1 col-md-6 col-lg-6 d-flex align-items-stretch">
|
||||||
<div class="card">
|
<div class="card border-light project-card">
|
||||||
<img src="~/img/projects/hero/none-1280x640.png" class="card-img-top" alt="SAMP.NET">
|
<div class="card-header text-bg-light">Retired</div>
|
||||||
|
<img src="~/img/projects/hero/sampdotnet-1280x640.png" class="card-img-top" alt="SAMP.NET">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h5 class="card-title">SAMP.NET</h5>
|
<h5 class="card-title">SAMP.NET</h5>
|
||||||
<p class="card-text">A .NET wrapper for the Pawn SAMP API, made during my time in college.</p>
|
<p class="card-text">A .NET wrapper for the Pawn SAMP API, made during my time in college.</p>
|
||||||
@ -92,7 +93,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="card-group row" style="margin-top: 20px;">
|
<div class="card-group row" style="margin-top: 20px;">
|
||||||
<div class="col-xs-1 col-md-6 col-lg-6 d-flex align-items-stretch">
|
<div class="col-xs-1 col-md-6 col-lg-6 d-flex align-items-stretch">
|
||||||
<div class="card">
|
<div class="card border-light project-card">
|
||||||
|
<div class="card-header text-bg-light">Retired</div>
|
||||||
<img src="~/img/projects/hero/none-1280x640.png" class="card-img-top" alt="SAMP.NET">
|
<img src="~/img/projects/hero/none-1280x640.png" class="card-img-top" alt="SAMP.NET">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h5 class="card-title">HaloMCCForgePatcher</h5>
|
<h5 class="card-title">HaloMCCForgePatcher</h5>
|
||||||
@ -101,16 +103,23 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-xs-1 col-md-6 col-lg-6 d-flex align-items-stretch">
|
||||||
|
<div class="card border-light project-card">
|
||||||
|
<div class="card-header text-bg-light">Retired</div>
|
||||||
|
<img src="~/img/projects/hero/unitydocs-1280x640.png" class="card-img-top" alt="Unity API Docs">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title">Unity API Docs</h5>
|
||||||
|
<p class="card-text">A complete rewrite and redesign of the Unity API docs, inspired by the C# and .NET documentation on Microsoft Learn.</p>
|
||||||
|
<p>This project was cancelled following Unity's pricing change announcement.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h2 class="lead" style="margin-top: 20px">On Hiatus</h2>
|
|
||||||
<p>
|
|
||||||
This is work that I have put on indefinite hold; projects that I would like to revisit one day, but I have no
|
|
||||||
timeline for when or if that will happen.
|
|
||||||
</p>
|
|
||||||
<div class="card-group row" style="margin-top: 20px">
|
<div class="card-group row" style="margin-top: 20px">
|
||||||
<div class="col-xs-1 col-md-6 col-lg-6 d-flex align-items-stretch">
|
<div class="col-xs-1 col-md-6 col-lg-6 d-flex align-items-stretch">
|
||||||
<div class="card">
|
<div class="card border-dark project-card">
|
||||||
|
<div class="card-header text-bg-dark">On Hiatus</div>
|
||||||
<img src="~/img/projects/hero/olive-1280x640.png" class="card-img-top" alt="Olive">
|
<img src="~/img/projects/hero/olive-1280x640.png" class="card-img-top" alt="Olive">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h5 class="card-title">Olive</h5>
|
<h5 class="card-title">Olive</h5>
|
||||||
@ -120,7 +129,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-xs-1 col-md-6 col-lg-6 d-flex align-items-stretch">
|
<div class="col-xs-1 col-md-6 col-lg-6 d-flex align-items-stretch">
|
||||||
<div class="card">
|
<div class="card border-dark project-card">
|
||||||
|
<div class="card-header text-bg-dark">On Hiatus</div>
|
||||||
<img src="~/img/projects/hero/none-1280x640.png" class="card-img-top" alt="TCP.NET">
|
<img src="~/img/projects/hero/none-1280x640.png" class="card-img-top" alt="TCP.NET">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h5 class="card-title">TCP.NET</h5>
|
<h5 class="card-title">TCP.NET</h5>
|
||||||
@ -132,7 +142,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="card-group row" style="margin-top: 20px;">
|
<div class="card-group row" style="margin-top: 20px;">
|
||||||
<div class="col-xs-1 col-md-6 col-lg-6 d-flex align-items-stretch">
|
<div class="col-xs-1 col-md-6 col-lg-6 d-flex align-items-stretch">
|
||||||
<div class="card">
|
<div class="card border-dark project-card">
|
||||||
|
<div class="card-header text-bg-dark">On Hiatus</div>
|
||||||
<img src="~/img/projects/hero/none-1280x640.png" class="card-img-top" alt="MelonSharp">
|
<img src="~/img/projects/hero/none-1280x640.png" class="card-img-top" alt="MelonSharp">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h5 class="card-title">MelonSharp</h5>
|
<h5 class="card-title">MelonSharp</h5>
|
||||||
@ -142,7 +153,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-xs-1 col-md-6 col-lg-6 d-flex align-items-stretch">
|
<div class="col-xs-1 col-md-6 col-lg-6 d-flex align-items-stretch">
|
||||||
<div class="card">
|
<div class="card border-dark project-card">
|
||||||
|
<div class="card-header text-bg-dark">On Hiatus</div>
|
||||||
<img src="~/img/projects/hero/syntaxgen-1280x640.png" class="card-img-top" alt="SyntaxGen.NET">
|
<img src="~/img/projects/hero/syntaxgen-1280x640.png" class="card-img-top" alt="SyntaxGen.NET">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h5 class="card-title">SyntaxGen.NET</h5>
|
<h5 class="card-title">SyntaxGen.NET</h5>
|
||||||
@ -154,17 +166,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="card-group row" style="margin-top: 20px;">
|
<div class="card-group row" style="margin-top: 20px;">
|
||||||
<div class="col-xs-1 col-md-6 col-lg-6 d-flex align-items-stretch">
|
<div class="col-xs-1 col-md-6 col-lg-6 d-flex align-items-stretch">
|
||||||
<div class="card">
|
<div class="card border-dark project-card">
|
||||||
<img src="~/img/projects/hero/unitydocs-1280x640.png" class="card-img-top" alt="Unity API Docs">
|
<div class="card-header text-bg-dark">On Hiatus</div>
|
||||||
<div class="card-body">
|
|
||||||
<h5 class="card-title">Unity API Docs</h5>
|
|
||||||
<p class="card-text">A complete rewrite and redesign of the Unity API docs, inspired by the C# and .NET documentation on Microsoft Learn.</p>
|
|
||||||
<p>This project is currently closed source until a stable prototype is ready.</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-xs-1 col-md-6 col-lg-6 d-flex align-items-stretch">
|
|
||||||
<div class="card">
|
|
||||||
<img src="~/img/projects/hero/mutation-1280x640.png" class="card-img-top" alt="Mutation">
|
<img src="~/img/projects/hero/mutation-1280x640.png" class="card-img-top" alt="Mutation">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h5 class="card-title">Mutation</h5>
|
<h5 class="card-title">Mutation</h5>
|
||||||
@ -173,10 +176,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<div class="card-group row" style="margin-top: 20px">
|
|
||||||
<div class="col-xs-1 col-md-6 col-lg-6 d-flex align-items-stretch">
|
<div class="col-xs-1 col-md-6 col-lg-6 d-flex align-items-stretch">
|
||||||
<div class="card">
|
<div class="card border-dark project-card">
|
||||||
|
<div class="card-header text-bg-dark">On Hiatus</div>
|
||||||
<img src="~/img/projects/hero/none-1280x640.png" class="card-img-top" alt="Olive">
|
<img src="~/img/projects/hero/none-1280x640.png" class="card-img-top" alt="Olive">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h5 class="card-title">Astraeos</h5>
|
<h5 class="card-title">Astraeos</h5>
|
||||||
|
@ -14,6 +14,7 @@ class BlogPost {
|
|||||||
private readonly _identifier: string;
|
private readonly _identifier: string;
|
||||||
private readonly _humanizedTimestamp: string;
|
private readonly _humanizedTimestamp: string;
|
||||||
private readonly _formattedDate: string;
|
private readonly _formattedDate: string;
|
||||||
|
private readonly _tags: string[];
|
||||||
|
|
||||||
constructor(json: any) {
|
constructor(json: any) {
|
||||||
this._id = json.id;
|
this._id = json.id;
|
||||||
@ -29,6 +30,7 @@ class BlogPost {
|
|||||||
this._identifier = json.identifier;
|
this._identifier = json.identifier;
|
||||||
this._humanizedTimestamp = json.humanizedTimestamp;
|
this._humanizedTimestamp = json.humanizedTimestamp;
|
||||||
this._formattedDate = json.formattedDate;
|
this._formattedDate = json.formattedDate;
|
||||||
|
this._tags = json.tags;
|
||||||
}
|
}
|
||||||
|
|
||||||
get id(): string {
|
get id(): string {
|
||||||
@ -66,6 +68,10 @@ class BlogPost {
|
|||||||
get url(): BlogUrl {
|
get url(): BlogUrl {
|
||||||
return this._url;
|
return this._url;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get tags(): string[] {
|
||||||
|
return this._tags;
|
||||||
|
}
|
||||||
|
|
||||||
get trimmed(): boolean {
|
get trimmed(): boolean {
|
||||||
return this._trimmed;
|
return this._trimmed;
|
||||||
|
@ -55,6 +55,7 @@ class UI {
|
|||||||
enable_comments: post.commentsEnabled,
|
enable_comments: post.commentsEnabled,
|
||||||
disqus_identifier: post.identifier,
|
disqus_identifier: post.identifier,
|
||||||
trimmed: post.trimmed,
|
trimmed: post.trimmed,
|
||||||
|
tags: post.tags
|
||||||
},
|
},
|
||||||
author: {
|
author: {
|
||||||
name: author.name,
|
name: author.name,
|
||||||
|
Loading…
Reference in New Issue
Block a user