Exam Area: Content Area 4 – Framework Components (15%)
Reference: https://docs.developers.optimizely.com/content-management-system/docs/user-interface
Gadgets are widgets that can be added to the Dashboard in the CMS.
// Gadget Controller
[EPiServer.Shell.Web.ScriptResource("ClientResources/Scripts/MyGadget.js")]
public class MyGadgetController : Controller
{
public ActionResult Index()
{
var model = new MyGadgetViewModel
{
Title = "My Gadget",
Count = GetItemCount()
};
return PartialView(model);
}
}
<!-- module.config -->
<module>
<guiPlugins>
<add name="MyGadget"
displayName="My Custom Gadget"
description="Shows something useful"
category="My Company"
plugInArea="Dashboard"
controlUrl="~/MyGadget/"
sortIndex="100" />
</guiPlugins>
</module>
// Use an attribute to register a gadget
[GadgetWidgetPlugin(
DisplayName = "Recent Changes",
Description = "Shows recent content changes",
WidgetUrl = "~/episerver/cms/gadgets/RecentChanges",
PlugInAreas = PlugInArea.Dashboard)]
public class RecentChangesGadget { }
// Add a menu item to CMS navigation
using EPiServer.Shell.Navigation;
[MenuItem("/global/cms/myitem",
Text = "My Feature",
TextResourceKey = "/mysite/menu/myfeature",
Url = "~/episerver/cms/myfeature/",
SortIndex = 200)]
public class MyMenuProvider { }
// Custom menu provider (CMS 12 approach)
[MenuProvider]
public class MyMenuProvider : IMenuProvider
{
public IEnumerable<MenuItem> GetMenuItems()
{
yield return new UrlMenuItem("My Feature",
"/global/cms/myfeature",
"~/episerver/cms/myfeature/")
{
IsAvailable = context => context.RequestContext
.HttpContext.User.IsInRole("WebAdmins"),
SortIndex = 200,
AuthorizationPolicy = "Authenticated"
};
}
}
// Create a custom view
[ViewConfiguration(
Name = "MyView",
ControllerType = typeof(MyViewController),
ViewType = typeof(MyViewType),
HideViewFromUI = false,
IconClass = "epi-icon__layout")]
public class MyViewConfiguration : ViewConfiguration<MyViewType>
{
public MyViewConfiguration()
{
Name = "MyView";
Description = "My custom view";
ContextualizationClass = "MyViewContextualizer";
}
}
// Available plug-in areas
PlugInArea.Dashboard // Dashboard gadgets
PlugInArea.Navigation // Navigation menu
PlugInArea.AssetsPanel // Assets panel
PlugInArea.EditPanel // Edit panel
// Configure TinyMCE
[InitializableModule]
public class TinyMceConfigModule : IInitializableModule
{
public void Initialize(InitializationEngine context)
{
context.InitComplete += InitComplete;
}
private void InitComplete(object sender, InitializationEventArgs e)
{
var options = ServiceLocator.Current.GetInstance<TinyMceConfiguration>();
// Add a custom plugin
options.ForAll().AddPlugin("myplugin", "~/ClientResources/tinymce/myplugin.js");
// Add a toolbar button
options.ForAll().AppendToolbarRow("myplugin");
// Style formats
options.ForAll().AddStyleFormat(new StyleFormat
{
Name = "Custom Quote",
Inline = "span",
Classes = "custom-quote"
});
}
public void Uninitialize(InitializationEngine context) { }
}
appsettings.json:{
"EPiServer": {
"TinyMce": {
"Default": {
"toolbar": "bold italic | link | code",
"plugins": "lists link code"
}
}
}
}
// Add CSS class options to TinyMCE
options.ForAll().AddStyleFormats(new[]
{
new StyleFormat { Name = "Callout", Inline = "span", Classes = "callout" },
new StyleFormat { Name = "Warning", Inline = "span", Classes = "warning" },
new StyleFormat { Name = "Success Block", Block = "div", Classes = "success" }
});
// A component displayed only in a specific context
[Component(
PlugInAreas = new[] { "ContextualInformation" },
SortIndex = 100)]
public class MyContextComponent : IComponent
{
public string Name => "MyContextInfo";
public string Categories => "cms";
}
// Add default gadgets to the dashboard
[InitializableModule]
public class DashboardConfig : IInitializableModule
{
public void Initialize(InitializationEngine context)
{
// Configure default dashboard gadgets
}
}
PlugInArea.Dashboard)[MenuItem] attribute or IMenuProvider)TinyMceConfiguration in an init module or appsettings.json)[MenuProvider] attribute used for? (Registers a custom menu provider)