Last active
September 12, 2020 00:14
-
-
Save jacobjones/ab73e3858bb11a97ae027b962ed71aee to your computer and use it in GitHub Desktop.
A plugin which allows editors to easily move categories within Episerver (https://jakejon.es/blog/a-plugin-to-move-categories-in-episerver)
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
<%@ Page Language="c#" CodeBehind="MoveCategories.aspx.cs" AutoEventWireup="False" Inherits="AlloyDemoKit.AddOns.MoveCategories.MoveCategories" Title="Move Categories" %> | |
<%@ Register TagPrefix="EPiServerUI" Namespace="EPiServer.UI.WebControls" Assembly="EPiServer.UI, Version=11.23.0.0, Culture=neutral, PublicKeyToken=8fe83dea738b45b7" %> | |
<asp:content contentplaceholderid="MainRegion" runat="server"> | |
<asp:Panel runat="server" CssClass="EP-systemMessage" ID="errorPanel" Visible="false"> | |
<asp:Literal runat="server" ID="errorText" /> | |
</asp:Panel> | |
<div class="epi-formArea epi-paddingVertical-small"> | |
<div class="epi-size15"> | |
<div> | |
<asp:Label AssociatedControlID="sourceList" Text="Category" runat="server" /> | |
<asp:DropDownList ID="sourceList" runat="server"/> | |
</div> | |
<div> | |
<asp:Label AssociatedControlID="destinationList" Text="Destination" runat="server" /> | |
<asp:DropDownList ID="destinationList" runat="server"/> | |
</div> | |
<div class="epi-buttonContainer"> | |
<EPiServerUI:ToolButton id="saveButton" DisablePageLeaveCheck="true" OnClick="Move_Click" runat="server" SkinID="Save" text="Move" ToolTip="Move the specified category" /> | |
</div> | |
</div> | |
</div> | |
</asp:content> |
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
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Net; | |
using System.Text; | |
using System.Web.UI.WebControls; | |
using EPiServer; | |
using EPiServer.DataAbstraction; | |
using EPiServer.PlugIn; | |
using EPiServer.Security; | |
using EPiServer.ServiceLocation; | |
using EPiServer.Shell.WebForms; | |
namespace AlloyDemoKit.AddOns.MoveCategories | |
{ | |
[GuiPlugIn( | |
DisplayName = "Move Categories", | |
Description = "Move Categories", | |
RequiredAccess = AccessLevel.Administer, | |
Area = PlugInArea.AdminMenu, | |
Url = "~/AddOns/MoveCategories/MoveCategories.aspx")] | |
public partial class MoveCategories : WebFormsBase | |
{ | |
private readonly Injected<CategoryRepository> _categoryRepository = default(Injected<CategoryRepository>); | |
protected override void OnPreInit(EventArgs e) | |
{ | |
base.OnPreInit(e); | |
MasterPageFile = UriSupport.ResolveUrlFromUIBySettings("MasterPages/EPiServerUI.master"); | |
SystemMessageContainer.Heading = "Move Categories"; | |
SystemMessageContainer.Description = "Move a category (and it's descendants) to anywhere within the category tree."; | |
} | |
protected override void OnLoad(EventArgs e) | |
{ | |
if (!PrincipalInfo.HasAdminAccess) | |
{ | |
Response.Clear(); | |
Response.StatusCode = (int)HttpStatusCode.Unauthorized; | |
return; | |
} | |
base.OnLoad(e); | |
if (!IsPostBack) { | |
Setup(); | |
} | |
} | |
private void Setup() | |
{ | |
// Hide any errors | |
errorPanel.Visible = false; | |
errorText.Text = null; | |
var root = _categoryRepository.Service.GetRoot(); | |
var items = new List<ListItem>(); | |
GetCategories(root, items, 0); | |
sourceList.DataSource = | |
items.Where(x => !x.Value.Equals(root.ID.ToString(), StringComparison.OrdinalIgnoreCase)); | |
sourceList.DataValueField = nameof(ListItem.Value); | |
sourceList.DataTextField = nameof(ListItem.Text); | |
sourceList.DataBind(); | |
destinationList.DataSource = items; | |
destinationList.DataValueField = nameof(ListItem.Value); | |
destinationList.DataTextField = nameof(ListItem.Text); | |
destinationList.DataBind(); | |
} | |
private static void GetCategories(Category category, ICollection<ListItem> items, int depth) | |
{ | |
items.Add(new ListItem | |
{ | |
Text = $"{new StringBuilder().Insert(0, "—", depth)}{category.Description ?? category.Name}", | |
Value = category.ID.ToString() | |
}); | |
if (category.Categories == null) | |
{ | |
return; | |
} | |
foreach (var child in category.Categories) | |
{ | |
GetCategories(child, items, depth + 1); | |
} | |
} | |
private void ShowError(string message) | |
{ | |
Setup(); | |
errorPanel.Visible = true; | |
errorText.Text = message; | |
} | |
protected void Move_Click(object sender, EventArgs e) | |
{ | |
var source = Request.Form[(string) sourceList.UniqueID]; | |
var destination = Request.Form[(string) destinationList.UniqueID]; | |
if (string.IsNullOrEmpty(source)) | |
{ | |
ShowError("No category selected."); | |
return; | |
} | |
if (string.IsNullOrEmpty(destination)) | |
{ | |
ShowError("No destination category selected."); | |
return; | |
} | |
int sourceId; | |
int destinationId; | |
if (!int.TryParse(source, out sourceId)) | |
{ | |
ShowError("Invalid category selected."); | |
return; | |
} | |
if (!int.TryParse(destination, out destinationId)) | |
{ | |
ShowError("Invalid destination category selected."); | |
return; | |
} | |
var category = _categoryRepository.Service.Get(sourceId); | |
if (category == null) | |
{ | |
ShowError("Could not retrieve the specified category."); | |
return; | |
} | |
if (category.Parent.ID == destinationId) | |
{ | |
ShowError("Category already lives under the specified destination."); | |
return; | |
} | |
category = category.CreateWritableClone(); | |
// Update the parent | |
category.Parent = _categoryRepository.Service.Get(destinationId); | |
_categoryRepository.Service.Save(category); | |
Setup(); | |
} | |
} | |
} |
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
//------------------------------------------------------------------------------ | |
// <auto-generated> | |
// This code was generated by a tool. | |
// | |
// Changes to this file may cause incorrect behavior and will be lost if | |
// the code is regenerated. | |
// </auto-generated> | |
//------------------------------------------------------------------------------ | |
namespace AlloyDemoKit.AddOns.MoveCategories { | |
public partial class MoveCategories { | |
/// <summary> | |
/// errorPanel control. | |
/// </summary> | |
/// <remarks> | |
/// Auto-generated field. | |
/// To modify move field declaration from designer file to code-behind file. | |
/// </remarks> | |
protected global::System.Web.UI.WebControls.Panel errorPanel; | |
/// <summary> | |
/// errorText control. | |
/// </summary> | |
/// <remarks> | |
/// Auto-generated field. | |
/// To modify move field declaration from designer file to code-behind file. | |
/// </remarks> | |
protected global::System.Web.UI.WebControls.Literal errorText; | |
/// <summary> | |
/// sourceList control. | |
/// </summary> | |
/// <remarks> | |
/// Auto-generated field. | |
/// To modify move field declaration from designer file to code-behind file. | |
/// </remarks> | |
protected global::System.Web.UI.WebControls.DropDownList sourceList; | |
/// <summary> | |
/// destinationList control. | |
/// </summary> | |
/// <remarks> | |
/// Auto-generated field. | |
/// To modify move field declaration from designer file to code-behind file. | |
/// </remarks> | |
protected global::System.Web.UI.WebControls.DropDownList destinationList; | |
/// <summary> | |
/// saveButton control. | |
/// </summary> | |
/// <remarks> | |
/// Auto-generated field. | |
/// To modify move field declaration from designer file to code-behind file. | |
/// </remarks> | |
protected global::EPiServer.UI.WebControls.ToolButton saveButton; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment