@using Microsoft.AspNetCore.Components.Web
@using Microsoft.EntityFrameworkCore
@using OpenArchival.Blazor.AdminPages
@using OpenArchival.DataAccess
@using OpenArchival.Blazor.CustomComponents
@using MudExRichTextEditor
@using MudBlazor
@using System.Text
@page "/admin/blogedit"
@page "/admin/blogedit/{Id}"
@layout AdminPages.AdminControlPanelLayout;
Create a Blog Post
@((MarkupString)BlogPostModel.Content)
Publish
@inject IDbContextFactory ContextFactory;
@inject ISnackbar Snackbar;
@inject NavigationManager NavigationManager;
@*OnKeyDown="@(ev => HandleChipContainerEnter(ev, _tagsChipContainer, _tagsInputValue, () => _tagsInputValue = string.Empty))"*@
@code {
[Parameter]
public int Id { get; set; }
public List StringTags { get; set; } = [];
public BlogPost BlogPostModel { get; set; } = new();
private MudExRichTextEdit _contentEditor = default!;
private string _tagsInputValue = "";
private ChipContainer _tagsChipContainer = default!;
protected override void OnParametersSet()
{
if (Id != 0)
{
using var context = ContextFactory.CreateDbContext();
BlogPost? existingPost = context.BlogPosts.Include(p => p.Tags).Where(p => p.Id == Id).FirstOrDefault();
if (existingPost is null)
{
NavigationManager.NavigateTo($"blog-not-found/{System.Web.HttpUtility.UrlEncode($"No blog with id {Id} exists in the database!")}");
return;
}
BlogPostModel = existingPost;
}
base.OnParametersSet();
}
private async Task DeDuplicatePostTags(BlogPost post, ApplicationDbContext context)
{
List finalTags = [];
foreach (BlogPostTag tag in post.Tags)
{
var existing = await context.BlogPostTags.Where(t => t.Name == tag.Name).FirstOrDefaultAsync();
if (existing is not null)
{
finalTags.Add(existing);
}
else
{
context.BlogPostTags.Add(tag);
finalTags.Add(tag);
}
}
post.Tags = finalTags;
}
private void BuildBlogSearchIndex(BlogPost post)
{
var tagsSb = new StringBuilder();
var allSb = new StringBuilder();
allSb.Append($"{post.Title} ");
allSb.Append($"{post.Content} ");
foreach (BlogPostTag tag in post.Tags)
{
tagsSb.Append($"{tag.Name} ");
allSb.Append($"{tag.Name} ");
}
post.AllSearchString = allSb.ToString();
post.TagsSearchString = tagsSb.ToString();
}
private async Task OnPublishBlogPost(Microsoft.AspNetCore.Components.Web.MouseEventArgs args)
{
if (string.IsNullOrEmpty(BlogPostModel.Content))
{
Snackbar.Add("Content is required in the blog post, write something.", Severity.Warning);
return;
}
if (string.IsNullOrEmpty(BlogPostModel.Title))
{
Snackbar.Add("A post title is required", Severity.Warning);
return;
}
await using var context = await ContextFactory.CreateDbContextAsync();
BlogPostModel.ModifiedTime = DateTime.UtcNow;
// Blog post does not exist in database
if (BlogPostModel.Id == 0)
{
BlogPostModel.CreationTime = DateTime.UtcNow;
// Loop through the tags and de-duplicate any of them
await DeDuplicatePostTags(BlogPostModel, context);
BuildBlogSearchIndex(BlogPostModel);
context.BlogPosts.Add(BlogPostModel);
}
else
{
// Blog post exists in database
// Find the existing post so we can update it
BlogPost? existing = await context.BlogPosts.Include(p=>p.Tags).FirstOrDefaultAsync(p => p.Id == BlogPostModel.Id);
if (existing is null)
{
Snackbar.Add($"Unable to find a post with id {BlogPostModel.Id} in the database, cannot update post!", Severity.Error);
return;
}
// De-duplicate tags
await DeDuplicatePostTags(BlogPostModel, context);
// Copy over the values we want
existing.Title = BlogPostModel.Title;
existing.Content = BlogPostModel.Content;
existing.ModifiedTime = BlogPostModel.ModifiedTime;
existing.Tags.Clear();
foreach (var tag in BlogPostModel.Tags)
{
existing.Tags.Add(tag);
}
BuildBlogSearchIndex(existing);
}
await context.SaveChangesAsync();
Snackbar.Add("Changes saved!", Severity.Success);
// Reset the model
BlogPostModel = new();
StateHasChanged();
}
public void HandleTagsEnter(KeyboardEventArgs args)
{
if (args.Key == "Enter")
{
var newTag = new BlogPostTag() { Name = _tagsInputValue };
_tagsInputValue = "";
BlogPostModel.Tags.Add(newTag);
StateHasChanged();
}
}
}