When creating page shortcut, Editor has to open setting tab, then click Manage link on shortcut property and then find a destination page in tree. So when he found a target page in Navigation Pane, then to create a shortcut he has to find it once again in the dialog. I prepared a functionality of creating shortcuts using D&D directly from Navigation Pane.
The final effect should look like:
To add D&D feature to shortcut property I extended default ShortcutEditor widget and added _DndStateMixin mixin. Next I implemented methods from mixin (canAccept, _onDndStart, _onDndCancel, _onDndDrop and onDropData). The acceptedTypes are not hardcoded but they came from metadata of the contentShortcutLink property (this.metadata.properties[3].settings.allowedTypes).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
define([ "dojo/_base/declare", "dojo/_base/connect", "dojo/dom-class", "dojo/dom-style", "dojo/dom-construct", "epi/shell/dnd/Target", "epi-cms/widget/_DndStateMixin", "epi-cms/contentediting/editors/ShortcutEditor", "epi/i18n!epi/cms/nls/episerver.cms.widget.shortcutblockeditor" ], function ( declare, connect, domClass, domStyle, domConstruct, Target, _DndStateMixin, ShortcutEditor, resources ) { return declare([ShortcutEditor, _DndStateMixin], { dropTarget: null, postCreate: function () { this.inherited(arguments); this.dndOverlay = domConstruct.create("div", { style: "border: 2px dashed rgba(180,198,0,1); position: absolute; left: -2px; top: -1px; right: -2px; bottom: -1px; display: none;" }, this.domNode); domStyle.set(this.domNode, "position", "relative"); this.own(this.dropTarget = new Target(this.dndOverlay, { accept: this.metadata.properties[3].settings.allowedTypes, createItemOnDrop: false, readOnly: this.readOnly })); this.connect(this.dropTarget, "onDropData", "onDropData"); }, canAccept: function () { return !domClass.contains(this.dndOverlay, "dojoDndTargetDisabled"); }, _onDndStart: function () { domStyle.set(this.dndOverlay, "display", "block"); this.inherited(arguments); }, _onDndCancel: function () { domStyle.set(this.dndOverlay, "display", "none"); this.inherited(arguments); }, _onDndDrop: function () { domStyle.set(this.dndOverlay, "display", "none"); this.inherited(arguments); }, onDropData: function (dndData, source, nodes, copy) { if (dndData.length === 0 || !dndData[0].data) { return; } var value = { contentShortcutLink: dndData[0].data.contentLink, pageShortcutType: 1, pageShortcutTypeName: resources.shortcuttype1, pageTargetFrame: null }; this.set("value", value); this.onChange(value); } }); }); |
When moving content over property, the drag item is highlighted.
In onDropData method, the shortcut property value is set to “Shortcut to another content item” (pageShortcutType = 1) and contentShortcutLink property is set to target URL.
After clicking “Manage” link, the Type and Internal Shortcusts are preselected:
The new property editor (DroppableShortcutBlockEditorDescriptor) has to be registered on the server. It’s done using InitializationModule.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
using System; using System.Collections.Generic; using System.Linq; using EPiServer.Cms.Shell.UI; using EPiServer.Framework; using EPiServer.Framework.Initialization; using EPiServer.ServiceLocation; using EPiServer.Shell.ObjectEditing; using EPiServer.Shell.ObjectEditing.EditorDescriptors; namespace AlloyTemplates.Business.Initialization { [InitializableModule] [ModuleDependency(typeof(EPiServer.Web.InitializationModule))] [ModuleDependency(typeof(EPiServer.Shell.UI.InitializationModule))] public class ProviderInitializationModule : IInitializableModule { public void Initialize(InitializationEngine context) { // find the ShortcutBlock type var shortcutBlock = typeof(GroupedMetaDataPropertyInfo).Assembly.GetType("EPiServer.Cms.Shell.UI.ObjectEditing.InternalMetadata.ShortcutBlock"); var metadataHandlerRegistry = ServiceLocator.Current.GetInstance<MetadataHandlerRegistry>(); var defaultHandler = metadataHandlerRegistry.GetMetadataHandlers(shortcutBlock).OfType<EditorDescriptor>().FirstOrDefault(); metadataHandlerRegistry.RegisterMetadataHandler(shortcutBlock, new DroppableShortcutBlockEditorDescriptor(defaultHandler), null, EditorDescriptorBehavior.OverrideDefault); } public void Uninitialize(InitializationEngine context) { } } public class DroppableShortcutBlockEditorDescriptor : EditorDescriptor { private readonly EditorDescriptor _original; public DroppableShortcutBlockEditorDescriptor(EditorDescriptor original) { _original = original; } public override void ModifyMetadata(ExtendedMetadata metadata, IEnumerable<Attribute> attributes) { this._original.ModifyMetadata(metadata, attributes); metadata.ClientEditingClass = "alloy/editors/DroppableShortcutEditor"; } } } |