28
Jun
2016

Referencing content gadget

A while ago I was talking to some content editors about how they worked with Episerver and what could make their work easier. One of the things they were struggling with is to find out where their content is being referenced. Which pages contain references to the page they are editing? Which pages are using the block they are editing?
Of course for a block this is very easy to check. Just click the link in the yellow bar to see where it is used.

ReferencingContent1

ReferencingContent2
However, I noticed some editors close the yellow bar, therefor losing the link.

For pages there is no easy way to see where they are referenced. There is the dirty way of deleting the page, see the warning and cancel the deletion. That is not the recommended way to work.

So I decided to create a simple gadget that will always display a list of referencing content.

ReferencingContent3

How it’s made

We start with defining a new component:

[Component(
    Title = "Referencing content",
    WidgetType = "alloy/Components/ReferencingContent",
    PlugInAreas = PlugInArea.Assets,
    Categories = "cms")]
public class ReferencingContentComponent {}

From our component we will use a ContentQuery to get a list of content items:

[ServiceConfiguration(typeof(IContentQuery))]
public class ReferencingContentQuery : ContentQueryBase
{
    private readonly IContentRepository _contentRepository;
    private readonly LanguageSelectorFactory _languageSelectorFactory;
        
    public ReferencingContentQuery(
        IContentQueryHelper queryHelper,
        IContentRepository contentRepository,
        LanguageSelectorFactory languageSelectorFactory) : base(contentRepository, queryHelper)
    {
        _contentRepository = contentRepository;
        _languageSelectorFactory = languageSelectorFactory;
    }

    protected override IEnumerable<IContent> GetContent(ContentQueryParameters parameters)
    {
        var sourceId = HttpUtility.HtmlDecode(parameters.AllParameters["contextId"]);
        var sourceRef = ContentReference.Parse(sourceId);

        var references = _contentRepository.GetReferencesToContent(sourceRef, false).Select(x => x.OwnerID);
        var items = _contentRepository.GetItems(references, _languageSelectorFactory.AutoDetect(parameters.AllLanguages));
        return items;
    }

    public override string Name
    {
        get { return "ReferrerQuery"; }
    }
}

The current content Id  (contextId) is passed as a parameter. The most important part of the query is _contentRepository.GetReferencesToContent, which gets the actual list of referencing content items.

The dojo part will use a ContentQueryGrid to call our ReferencingContentQuery and display it in a nice list:

define([
    "dojo/_base/declare",
    "dijit/_TemplatedMixin",
    "dijit/layout/_LayoutWidget",
    "dijit/_WidgetsInTemplateMixin",
    "epi/shell/_ContextMixin",
    "epi/cms/component/ContentQueryGrid",
    "epi/i18n!epi/cms/nls/referencingcontent",
    "dojo/text!./templates/ReferencingContent.html"],
    function (// Dojo        
        declare,
        // Dijit    
        _TemplatedMixin,
        _LayoutWidget,
        _WidgetsInTemplateMixin,
        // EPi CMS    
        _ContextMixin,
        ContentQueryGrid,
        resources,
        template) {
        return declare([
            _LayoutWidget,
            _TemplatedMixin,
            _WidgetsInTemplateMixin,
            _ContextMixin
        ],
        {
            templateString: template,

            resources: resources,

            startup: function () {
                this.inherited(arguments);
                var context = this.getCurrentContext();
                this.contentQuery.set("queryParameters", { contextId: context.id });
                this.contentQuery.set("queryName", "ReferrerQuery"); 
                this.subscribe("/epi/shell/context/changed", this._contextChanged);
            },            

            resize: function(newSize) {
                this.inherited(arguments);
                var gridSize = { w: newSize.w, h: newSize.h }
                this.contentQuery.resize(gridSize);
            },

            _contextChanged: function(newContext) {
                if (!newContext) {
                    return;
                }
                this.contentQuery.set("queryParameters", { contextId: newContext.id });
                this.contentQuery.set("queryName", "ReferrerQuery");
            }
        });
    });

using the template:

<div>
    <div class="epi-gadgetInnerToolbar">
        <span>${resources.header}</span>
    </div>
    <div data-dojo-type="epi-cms/component/ContentQueryGrid" data-dojo-attach-point="contentQuery"></div>
</div>

There is also some globalization in the gadget using: epi/i18n!epi/cms/nls/referencingcontent
so you can translate the header to your used languages

<?xml version="1.0" encoding="utf-8"?>
<languages>
  <language name="English" id="en">
    <referencingcontent>
      <header>The following content references the current item:</header>
    </referencingcontent>
  </language>
</languages>

Simple and effective. Happy content editors.

Share

You may also like...