-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
OSOE-652: Better favicon inclusion in Lombiq.BaseTheme
- Loading branch information
Showing
23 changed files
with
459 additions
and
32 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
Binary file not shown.
33 changes: 33 additions & 0 deletions
33
Lombiq.BaseTheme.Samples/Migrations/Lombiq.BaseTheme.Samples.UpdateFrom0.recipe.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
{ | ||
"steps": [ | ||
// You can add an icon as a regular media file and then pick it from the editor, or just have media and settings | ||
// steps in your recipe like below. | ||
{ | ||
"name": "media", | ||
"Files": [ | ||
{ | ||
"SourcePath": "Icons/favicon.ico", | ||
"TargetPath": "Icons/favicon.ico" | ||
}, | ||
{ | ||
"SourcePath": "Icons/oc-favicon.ico", | ||
"TargetPath": "Icons/oc-favicon.ico" | ||
} | ||
] | ||
}, | ||
{ | ||
"name": "settings", | ||
"BaseThemeSettings": { | ||
// The HideMenu can be used if you don't want to use the Boostrap main menu widget injected by the base theme. | ||
"HideMenu": false, | ||
// You can set a single icon using a media path, so the same as the TargetPath in the recipe's media step. | ||
"Icon": "Icons/favicon.ico", | ||
// The time stamp is a UTC DateTime.Ticks value, you can make it any random long number in the recipe because | ||
// the chance that the next save will have the exact same ticks is vanishingly low. | ||
"TimeStamp": 638240128517358149 | ||
} | ||
} | ||
] | ||
} | ||
|
||
// END OF TRAINING SECTION: Set up favicon using recipe migrations |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
using Lombiq.HelpfulLibraries.OrchardCore.Data; | ||
using OrchardCore.Recipes.Services; | ||
|
||
namespace Lombiq.BaseTheme.Samples.Migrations; | ||
|
||
// Migrations based on the RecipeMigrationsBase class have a default CreateAsync method that invokes the recipe in the | ||
// same directory called "{module-or-theme-id}.UpdateFrom0.recipe.json". For any subsequent update migrations, you can | ||
// create an UpdateFrom1Async, UpdateFrom2Async, etc as usual, but all you have to put in it is ExecuteAsync(N) to | ||
// invoke the corresponding "{module-or-theme-id}.UpdateFromN.recipe.json" recipe and return the incremented version | ||
// number. | ||
// If you just want a static default icon, check out the DerivedTheme.Favicon in Manifest.cs! | ||
public class RecipeMigrations : RecipeMigrationsBase | ||
{ | ||
public RecipeMigrations(IRecipeMigrator recipeMigrator) | ||
: base(recipeMigrator) | ||
{ | ||
} | ||
} | ||
|
||
// NEXT STATION: Migrations/Lombiq.BaseTheme.Samples.UpdateFrom0.recipe.json |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
using Lombiq.BaseTheme.Constants; | ||
using OrchardCore.DisplayManagement.Manifest; | ||
using OrchardCore.ResourceManagement; | ||
using System; | ||
using System.Collections.Generic; | ||
|
||
namespace Lombiq.BaseTheme.Attributes; | ||
|
||
/// <summary> | ||
/// Indicates a theme derived from <c>Lombiq.BaseTheme</c>. | ||
/// </summary> | ||
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true, Inherited = false)] | ||
public sealed class DerivedThemeAttribute : ThemeAttribute | ||
{ | ||
public IEnumerable<LinkEntry> Links { get; set; } | ||
public string Favicon { get; set; } | ||
|
||
public DerivedThemeAttribute() => | ||
BaseTheme = FeatureIds.BaseTheme; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
using Lombiq.BaseTheme.Models; | ||
using Lombiq.BaseTheme.ViewModels; | ||
using Lombiq.HelpfulExtensions.Extensions.ContentTypes; | ||
using Microsoft.AspNetCore.Mvc; | ||
using Microsoft.AspNetCore.Mvc.Localization; | ||
using Newtonsoft.Json; | ||
using Newtonsoft.Json.Linq; | ||
using OrchardCore.ContentManagement; | ||
using OrchardCore.ContentManagement.Metadata.Models; | ||
using OrchardCore.DisplayManagement; | ||
using OrchardCore.DisplayManagement.Notify; | ||
using OrchardCore.Entities; | ||
using OrchardCore.Media.Fields; | ||
using OrchardCore.Media.Settings; | ||
using OrchardCore.Media.ViewModels; | ||
using OrchardCore.Modules; | ||
using OrchardCore.Settings; | ||
using System.Collections.Generic; | ||
using System.Threading.Tasks; | ||
|
||
namespace Lombiq.BaseTheme.Controllers; | ||
|
||
// This controller is there for editing the BaseThemeSettings. We can't use a site settings driver for this, because you | ||
// can't declare admin-accessible shapes in a site theme. | ||
public class AdminController : Controller | ||
{ | ||
private readonly IClock _clock; | ||
private readonly INotifier _notifier; | ||
private readonly ISiteService _siteService; | ||
private readonly IShapeFactory _shapeFactory; | ||
private readonly IHtmlLocalizer<AdminController> H; | ||
|
||
public AdminController( | ||
IClock clock, | ||
INotifier notifier, | ||
ISiteService siteService, | ||
IShapeFactory shapeFactory, | ||
IHtmlLocalizer<AdminController> htmlLocalizer) | ||
{ | ||
_clock = clock; | ||
_notifier = notifier; | ||
_siteService = siteService; | ||
_shapeFactory = shapeFactory; | ||
|
||
H = htmlLocalizer; | ||
} | ||
|
||
public async Task<IActionResult> Index() | ||
{ | ||
var section = (await _siteService.LoadSiteSettingsAsync()).As<BaseThemeSettings>(); | ||
|
||
var model = new BaseThemeSettingsViewModel | ||
{ | ||
HideMenu = section.HideMenu, | ||
Icon = section.Icon, | ||
Editor = await _shapeFactory.CreateAsync<EditMediaFieldViewModel>("MediaField_Edit", editor => | ||
{ | ||
var part = CreatePart(section); | ||
|
||
editor.Paths = string.IsNullOrWhiteSpace(section.Icon) | ||
? "[]" | ||
: JsonConvert.SerializeObject(new[] { new { path = section.Icon } }); | ||
editor.Field = part.Icon; | ||
editor.Part = part; | ||
editor.PartFieldDefinition = new ContentPartFieldDefinition( | ||
new ContentFieldDefinition(nameof(BaseThemeSettingsPart.Icon)), | ||
nameof(BaseThemeSettingsPart.Icon), | ||
JObject.FromObject(new Dictionary<string, object> | ||
{ | ||
[nameof(MediaFieldSettings)] = new MediaFieldSettings { Multiple = false }, | ||
})) | ||
{ | ||
PartDefinition = new ContentPartDefinition(nameof(BaseThemeSettingsPart)), | ||
}; | ||
}), | ||
}; | ||
|
||
model.Editor.Metadata.OnDisplaying(context => context.DisplayContext.HtmlFieldPrefix = nameof(model.Editor)); | ||
|
||
return View(model); | ||
} | ||
|
||
[HttpPost] | ||
[ValidateAntiForgeryToken] | ||
public async Task<IActionResult> Update([FromForm] BaseThemeSettingsViewModel viewModel) | ||
{ | ||
var siteSettings = await _siteService.LoadSiteSettingsAsync(); | ||
siteSettings.Alter<BaseThemeSettings>(nameof(BaseThemeSettings), settings => | ||
{ | ||
settings.TimeStamp = _clock.UtcNow.Ticks; | ||
settings.Icon = viewModel.Icon; | ||
settings.HideMenu = viewModel.HideMenu; | ||
}); | ||
|
||
await _siteService.UpdateSiteSettingsAsync(siteSettings); | ||
await _notifier.SuccessAsync(H["Site settings updated successfully."]); | ||
|
||
return RedirectToAction(nameof(Index)); | ||
} | ||
|
||
private static BaseThemeSettingsPart CreatePart(BaseThemeSettings section) | ||
{ | ||
var content = new ContentItem { ContentType = ContentTypes.Empty }; | ||
|
||
content.Weld(new BaseThemeSettingsPart | ||
{ | ||
ContentItem = content, | ||
Icon = new MediaField | ||
{ | ||
ContentItem = content, | ||
MediaTexts = new[] { section.Icon }, | ||
Paths = new[] { section.Icon }, | ||
}, | ||
}); | ||
|
||
return content.As<BaseThemeSettingsPart>(); | ||
} | ||
|
||
public class BaseThemeSettingsPart : ContentPart | ||
{ | ||
public MediaField Icon { get; set; } = new(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
namespace Lombiq.BaseTheme.Models; | ||
|
||
public class BaseThemeSettings | ||
{ | ||
public long TimeStamp { get; set; } | ||
public string Icon { get; set; } | ||
public bool HideMenu { get; set; } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
using Lombiq.BaseTheme.Controllers; | ||
using Lombiq.BaseTheme.Permissions; | ||
using Lombiq.HelpfulLibraries.OrchardCore.Navigation; | ||
using Microsoft.AspNetCore.Http; | ||
using Microsoft.Extensions.Localization; | ||
using OrchardCore.Navigation; | ||
|
||
namespace Lombiq.BaseTheme.Navigation; | ||
|
||
public class BaseThemeSettingsAdminMenu : AdminMenuNavigationProviderBase | ||
{ | ||
public BaseThemeSettingsAdminMenu( | ||
IHttpContextAccessor hca, | ||
IStringLocalizer<BaseThemeSettingsAdminMenu> stringLocalizer) | ||
: base(hca, stringLocalizer) | ||
{ | ||
} | ||
|
||
protected override void Build(NavigationBuilder builder) => | ||
builder.Add(T["Configuration"], configuration => configuration | ||
.Add(T["Settings"], settings => settings | ||
.Add(T["Base Theme"], T["Base Theme"], baseTheme => baseTheme | ||
.ActionTask<AdminController>(_hca.HttpContext, controller => controller.Index()) | ||
.Permission(BaseThemeSettingsPermissions.ManageBaseThemeSettings) | ||
.LocalNav() | ||
))); | ||
} |
13 changes: 13 additions & 0 deletions
13
Lombiq.BaseTheme/Permissions/BaseThemeSettingsPermissions.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
using Lombiq.HelpfulLibraries.OrchardCore.Users; | ||
using OrchardCore.Security.Permissions; | ||
using System.Collections.Generic; | ||
|
||
namespace Lombiq.BaseTheme.Permissions; | ||
|
||
public class BaseThemeSettingsPermissions : AdminPermissionBase | ||
{ | ||
public static readonly Permission ManageBaseThemeSettings = | ||
new(nameof(ManageBaseThemeSettings), "Manage Lombiq.BaseTheme Settings."); | ||
|
||
protected override IEnumerable<Permission> AdminPermissions => new[] { ManageBaseThemeSettings }; | ||
} |
Oops, something went wrong.