Skip to content

Commit

Permalink
Merge pull request #837 from EdiWang/feature/social-links-in-db
Browse files Browse the repository at this point in the history
Save and edit social links in admin portal
  • Loading branch information
EdiWang authored Oct 22, 2024
2 parents 356e165 + 8b97446 commit a15eeed
Show file tree
Hide file tree
Showing 14 changed files with 175 additions and 16 deletions.
4 changes: 4 additions & 0 deletions src/Moonglade.Configuration/BlogConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ public interface IBlogConfig
CustomStyleSheetSettings CustomStyleSheetSettings { get; set; }
CustomMenuSettings CustomMenuSettings { get; set; }
LocalAccountSettings LocalAccountSettings { get; set; }
SocialLinkSettings SocialLinkSettings { get; set; }
SystemManifestSettings SystemManifestSettings { get; set; }

IEnumerable<int> LoadFromConfig(IDictionary<string, string> config);
Expand All @@ -40,6 +41,8 @@ public class BlogConfig : IBlogConfig

public LocalAccountSettings LocalAccountSettings { get; set; }

public SocialLinkSettings SocialLinkSettings { get; set; }

public SystemManifestSettings SystemManifestSettings { get; set; }

public IEnumerable<int> LoadFromConfig(IDictionary<string, string> config)
Expand All @@ -53,6 +56,7 @@ public IEnumerable<int> LoadFromConfig(IDictionary<string, string> config)
CustomStyleSheetSettings = AssignValueForConfigItem(7, CustomStyleSheetSettings.DefaultValue, config);
CustomMenuSettings = AssignValueForConfigItem(10, CustomMenuSettings.DefaultValue, config);
LocalAccountSettings = AssignValueForConfigItem(11, LocalAccountSettings.DefaultValue, config);
SocialLinkSettings = AssignValueForConfigItem(12, SocialLinkSettings.DefaultValue, config);

// Special case
SystemManifestSettings = AssignValueForConfigItem(99, SystemManifestSettings.DefaultValue, config);
Expand Down
27 changes: 26 additions & 1 deletion src/Moonglade.Configuration/SocialLink.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,20 @@
namespace Moonglade.Configuration;
using System.ComponentModel.DataAnnotations;

namespace Moonglade.Configuration;

public class SocialLinkSettings : IBlogSettings
{
public bool IsEnabled { get; set; }

public SocialLink[] Links { get; set; } = [];

public static SocialLinkSettings DefaultValue =>
new()
{
IsEnabled = false,
Links = []
};
}

public class SocialLink
{
Expand All @@ -7,4 +23,13 @@ public class SocialLink
public string Icon { get; set; }

public string Url { get; set; }
}

public class SocialLinkSettingsJsonModel
{
[Display(Name = "Enable Social Links")]
public bool IsEnabled { get; set; }

[MaxLength(1024)]
public string JsonData { get; set; }
}
19 changes: 9 additions & 10 deletions src/Moonglade.Core/GetAllSocialLinksQuery.cs
Original file line number Diff line number Diff line change
@@ -1,22 +1,21 @@
using Microsoft.Extensions.Configuration;
using Moonglade.Configuration;
using Moonglade.Configuration;

namespace Moonglade.Core;

public record GetAllSocialLinksQuery : IRequest<List<SocialLink>>;
public record GetAllSocialLinksQuery : IRequest<SocialLink[]>;

public class GetAllSocialLinksQueryHandler(IConfiguration configuration) : IRequestHandler<GetAllSocialLinksQuery, List<SocialLink>>
public class GetAllSocialLinksQueryHandler(IBlogConfig blogConfig) : IRequestHandler<GetAllSocialLinksQuery, SocialLink[]>
{
public Task<List<SocialLink>> Handle(GetAllSocialLinksQuery request, CancellationToken ct)
public Task<SocialLink[]> Handle(GetAllSocialLinksQuery request, CancellationToken ct)
{
var section = configuration.GetSection("Experimental:SocialLinks");
var section = blogConfig.SocialLinkSettings;

if (!section.Exists())
if (!section.IsEnabled)
{
return Task.FromResult(new List<SocialLink>());
return Task.FromResult(Array.Empty<SocialLink>());
}

var links = section.Get<List<SocialLink>>();
return Task.FromResult(links ?? new List<SocialLink>());
var links = blogConfig.SocialLinkSettings.Links;
return Task.FromResult(links);
}
}
4 changes: 4 additions & 0 deletions src/Moonglade.Setup/BlogConfigInitializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ await mediator.Send(new AddDefaultConfigurationCommand(key, nameof(CustomMenuSet
await mediator.Send(new AddDefaultConfigurationCommand(key, nameof(LocalAccountSettings),
LocalAccountSettings.DefaultValue.ToJson()));
break;
case 12:
await mediator.Send(new AddDefaultConfigurationCommand(key, nameof(SocialLinkSettings),
SocialLinkSettings.DefaultValue.ToJson()));
break;
case 99:
await mediator.Send(new AddDefaultConfigurationCommand(key, nameof(SystemManifestSettings),
isNew ?
Expand Down
20 changes: 20 additions & 0 deletions src/Moonglade.Web/Controllers/SettingsController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,26 @@ public async Task<IActionResult> Advanced(AdvancedSettings model)
return NoContent();
}

[HttpPost("social-link")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
public async Task<IActionResult> SocialLink(SocialLinkSettingsJsonModel model)
{
if (model.IsEnabled && string.IsNullOrWhiteSpace(model.JsonData))
{
ModelState.AddModelError(nameof(SocialLinkSettingsJsonModel.JsonData), "JsonData is required");
return BadRequest(ModelState.CombineErrorMessages());
}

blogConfig.SocialLinkSettings = new()
{
IsEnabled = model.IsEnabled,
Links = model.JsonData.FromJson<SocialLink[]>()
};

await SaveConfigAsync(blogConfig.SocialLinkSettings);
return NoContent();
}

[HttpPost("reset")]
[ProducesResponseType(StatusCodes.Status202Accepted)]
public async Task<IActionResult> Reset(BlogDbContext context, IHostApplicationLifetime applicationLifetime)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
@using Moonglade.Utils
@model List<SocialLink>
@model SocialLink[]

@if (Model.Any())
{
Expand Down
83 changes: 83 additions & 0 deletions src/Moonglade.Web/Pages/Settings/SocialLinks.cshtml
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
@page "/admin/settings/social-links"
@Html.AntiForgeryToken()
@{
var bc = BlogConfig.SocialLinkSettings;
var settings = new SocialLinkSettingsJsonModel
{
IsEnabled = bc.IsEnabled,
JsonData = bc.Links.ToJson(true)
};
}

@section scripts {
<partial name="_MonacoLoaderScript" />
<script>
var jsonContentEditor = null;
require(['vs/editor/editor.main'], function () {
jsonContentEditor = initEditor('JsonContentEditor', "#settings_JsonData", 'json');
});
</script>
<script type="module">
import * as settings from '/js/app/admin.settings.module.js';
function handleSubmit(event) {
assignEditorValues(jsonContentEditor, "#settings_JsonData");
settings.handleSettingsSubmit(event);
}
const form = document.querySelector('#form-settings');
form.addEventListener('submit', handleSubmit);
</script>
}

@section head {
<style>
.monaco-target {
border: 1px solid var(--bs-border-color);
width: 100%;
min-height: calc(100vh - 440px);
}
</style>
}

@section admintoolbar {
<partial name="_SettingsHeader" />
}

<form id="form-settings" asp-controller="Settings" asp-action="SocialLink">
<div class="admin-settings-entry-container">

<div class="alert alert-warning">
<i class="bi-exclamation-triangle"></i> This feature is under development. It is currently in preview. A GUI editor will be available in the future.
</div>

<div class="settings-entry row align-items-center py-3 px-2 rounded-3 shadow-sm border mb-2">
<div class="col-auto">
<i class="bi-menu-app settings-entry-icon"></i>
</div>
<div class="col">
<label asp-for="@settings.IsEnabled" class="form-check-label"></label>
</div>
<div class="col-md-5 text-end">
<div class="form-check form-switch form-control-lg">
<input type="hidden" name="IsEnabled" value="false">
<input type="checkbox" name="IsEnabled" value="true" class="form-check-input" @(@settings.IsEnabled
? "checked"
: null)/>
</div>
</div>
</div>

<div id="JsonContentEditor" class="monaco-target p-3 rounded-3 shadow-sm border">
</div>
</div>

<textarea asp-for="@settings.JsonData" class="settings-jsoncontent-textarea d-none"></textarea>

<div class="admin-settings-action-container border-top pt-2 mt-2">
<button type="submit" class="btn btn-outline-accent" id="btn-save-settings">
@SharedLocalizer["Save"]
</button>
</div>
</form>
3 changes: 3 additions & 0 deletions src/Moonglade.Web/Pages/Settings/_SettingsHeader.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
<li role="presentation" class="nav-item nav-item-non-margin">
<a class="nav-link @(currentPage == "/Settings/Notification" ? "active" : null)" asp-page="./Notification">@SharedLocalizer["Notification"]</a>
</li>
<li role="presentation" class="nav-item nav-item-non-margin">
<a class="nav-link @(currentPage == "/Settings/SocialLinks" ? "active" : null)" asp-page="./SocialLinks">@SharedLocalizer["Social Links"]</a>
</li>
<li role="presentation" class="nav-item nav-item-non-margin">
<a class="nav-link @(currentPage == "/Settings/Advanced" ? "active" : null)" asp-page="./Advanced">@SharedLocalizer["Advanced"]</a>
</li>
Expand Down
2 changes: 1 addition & 1 deletion src/Moonglade.Web/Pages/Shared/_Aside.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
</section>
}

@if (Configuration.GetSection("Experimental:SocialLinks").Exists())
@if (BlogConfig.SocialLinkSettings.IsEnabled)
{
<section id="aside-sociallink" class="mb-4">
@await Component.InvokeAsync("SocialLink")
Expand Down
6 changes: 6 additions & 0 deletions src/Moonglade.Web/Resources/Program.de-DE.resx
Original file line number Diff line number Diff line change
Expand Up @@ -1038,4 +1038,10 @@
<data name="Confirm" xml:space="preserve">
<value>Bestätigen</value>
</data>
<data name="Enable Social Links" xml:space="preserve">
<value>Social Linking aktivieren</value>
</data>
<data name="Social Links" xml:space="preserve">
<value>Soziale Verknüpfungen</value>
</data>
</root>
6 changes: 6 additions & 0 deletions src/Moonglade.Web/Resources/Program.ja-JP.resx
Original file line number Diff line number Diff line change
Expand Up @@ -1038,4 +1038,10 @@
<data name="Confirm" xml:space="preserve">
<value>確認する</value>
</data>
<data name="Enable Social Links" xml:space="preserve">
<value>ソーシャルリンクを有効にする</value>
</data>
<data name="Social Links" xml:space="preserve">
<value>ソーシャルリンク</value>
</data>
</root>
6 changes: 6 additions & 0 deletions src/Moonglade.Web/Resources/Program.zh-Hans.resx
Original file line number Diff line number Diff line change
Expand Up @@ -1038,4 +1038,10 @@
<data name="Confirm" xml:space="preserve">
<value>确认</value>
</data>
<data name="Enable Social Links" xml:space="preserve">
<value>启用社交链接</value>
</data>
<data name="Social Links" xml:space="preserve">
<value>社交链接</value>
</data>
</root>
6 changes: 6 additions & 0 deletions src/Moonglade.Web/Resources/Program.zh-Hant.resx
Original file line number Diff line number Diff line change
Expand Up @@ -1041,4 +1041,10 @@
<data name="Confirm" xml:space="preserve">
<value>確認</value>
</data>
<data name="Enable Social Links" xml:space="preserve">
<value>啟用社交連結</value>
</data>
<data name="Social Links" xml:space="preserve">
<value>社交連結</value>
</data>
</root>
3 changes: 0 additions & 3 deletions src/Moonglade.Web/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,6 @@
"Enabled": true,
"HeaderName": "Sec-CH-Prefers-Color-Scheme"
},
"Experimental": {
"SocialLinks": []
},
"Logging": {
"LogLevel": {
"Default": "Warning",
Expand Down

0 comments on commit a15eeed

Please sign in to comment.