Have you ever felt tired of scrolling down the Asset Pane, looking for the item you’ve just created? I know someone would say, “Then just get a better structure for your content!”. Right, folder structure should be in a hierarchical order for best practice. However, in some cases (especially the Media), specific content must be in one place, causing a large amount of content located in one folder. It actually gave some frustrations to our client, since Optimizely did not support sorting by date out-of-the-box for Media Pane, editors have to scroll all the way down to find the images they’ve just uploaded seconds ago.
Solution
Nevertheless, with a little touch to Dojo customization, you would be able to achieve something like this:
Implementation
Setup a module initializer
First step is adding a module initializer. This will allows you to intercept to the UI events and create your own configures/customizations. Define your own module initializer:
define([ "dojo", "dojo/_base/declare", "epi/_Module", "epi-cms/plugin-area/assets-pane", "alloy/Command/SortBlocks", "dojo/topic", "epi-cms/asset/HierarchicalList" ], function (dojo, declare, _Module, assetPanePluginArea, SortBlocks, topic, HierarchicalList ) { return declare("alloy.moduleInitializer", [_Module], { initialize: function () { this.inherited(arguments); // Do any custom module initialization here } }); });
Then register your moduleInitializer in the module.config file. Something like this:
<?xml version="1.0" encoding="utf-8"?> <module> <assemblies> <add assembly="alloy-mvc" /> </assemblies> <clientResources debug="true"> </clientResources> <dojo> <paths> <add name="alloy" path="~/ClientResources/Scripts" /> </paths> </dojo> <clientModule initializer="alloy.moduleInitializer"> <moduleDependencies> <add dependency="CMS" type="RunAfter" /> </moduleDependencies> </clientModule> </module>
You can find more details about the module initializer in the Official Optimizely Developer Documentation
Extending the HierarchicalList module
Thanks to this brilliant post from Greg, now I have an idea on how to extend the original Episerver UI’s component. In order to modify the default behavior of the Asset Pane, we need to interact with the HierarchicalList component. I’m going to override its postCreate method by doing the following steps:
- Call the original postCreate function.
- Subscribe to my own custom events by using dojo/topic.
- When the events are called, change the sort order of the HierarchicalList and refresh the selected node.
define([ "dojo", "dojo/_base/declare", "epi/_Module", "epi-cms/plugin-area/assets-pane", "alloy/Command/SortBlocks", "dojo/topic", "epi-cms/asset/HierarchicalList" ], function (dojo, declare, _Module, assetPanePluginArea, SortBlocks, topic, HierarchicalList ) { return declare("alloy.moduleInitializer", [_Module], { initialize: function () { this.inherited(arguments); // Do any custom module initialization here // Extend postCreate method for HierarchicalList var original = HierarchicalList.prototype.postCreate; HierarchicalList.prototype.postCreate = function () { // call the original function original.apply(this, arguments); // subscribe to custom events this.own( topic.subscribe("/topic/alloy/sortByDate", function () { this.list.grid._sort = [{ attribute: "created", descending: true }]; // change sort order this.model._selectedTreeItemsSetter(this.model.selectedTreeItems); // refresh current node }.bind(this)), topic.subscribe("/topic/alloy/sortByName", function () { this.list.grid._sort = [{ attribute: "name", descending: false }]; // change sort order this.model._selectedTreeItemsSetter(this.model.selectedTreeItems); // refresh current node }.bind(this)) ); } } }); });
Creating the Sort button and adding it to the Asset Pane’s Plug-in area
Now we need a button to trigger the events that HierarchicalList subscribes to. The button’s jobs are just firing events and changing button text accordingly. Sample code for the button:
define([ "dojo/topic", "dojo/_base/declare", "epi/dependency", "epi/shell/command/_Command" ], function (topic, declare, dependency, _Command) { return declare([_Command], { label: "Sort By Created Date", iconClass: "epi-iconSort", sortByDate: true, constructor: function () { }, _execute: function () { if (this.sortByDate === true) { this.sortByDate = false; this.set("label", "Sort By Name"); topic.publish("/topic/alloy/sortByDate"); } else { this.sortByDate = true; this.set("label", "Sort By Created Date"); topic.publish("/topic/alloy/sortByName"); } }, _onModelChange: function () { this.set("canExecute", true); } }); });
Once we have the button, add this line of code to the initialize method of your moduleInitializer. This will bring your button to the Asset Pane’s Plug-in Area.
// Add Sort button to the Asset Pane assetPanePluginArea.add(SortBlocks);
For more information about Optimizely’s Plug-in Area, please refer to the Official Optimizely Developer Documentation.
Now you’re all set! Bonus point: since we modified the HierarchicalList, meaning we already had the Sorting option available for both Media and Blocks! The full working solution can be found in my Github.
Very nice post! And a helpful feature indeed.