Page tree
Skip to end of metadata
Go to start of metadata


The Linchpin Sidebar on the right hand side offers a variety of dynamic contents for a user's everyday work. With this API, you can register your own, individual panels for the sidebar.

Setup (Backend)

To connect a sidebar panel you need to use Atlassian's ModuleDescriptor mechanism.

An corresponding entry in the atlassian-plugin.xml looks like this:


<linchpin-sidebar-panel key="saved-for-later" class="net.seibertmedia.confluence.linchpinsidebar.panels.savedforlater.SavedForLaterPanel" />


key: a unique key for the descriptor within the implementing app
class: a class that implements the interface LinchpinSidebarPanel and thus further configures the panel (see JavaDocs of the interface).


Obsolete attributes since version 1.3 of the Linchpin Sidebar app

section-name: the section within which the panel is supposed to appear. Available sections: "linchpin", "confluence-features", "jira"
weight: Weight of the panel, determining the order of the panels within the section. 

Since version 1.3 of the Linchpin Sidebar app (which comes bundled with new versions of Linchpin Theme, Suite and Essentials) segmenting and ordering items in the sidebar is configurable.

  • Panels that have neither weight nor section will be placed at the end initially, until an admin changes this configuration.
  • Pre-existing panels that have section and weight will be sorted by section and weight until the configuration is saved for the first time. 
  • New panels with section and weight that are added might appear in a random place, but once the configuration is saved, they keep their configured place. 


Necessary Java classes are being exported by the app. The implementing app needs appropriate imports (pom.xml):

<dependency>
    <groupId>net.seibertmedia.confluence</groupId>
    <artifactId>linchpin-sidebar</artifactId>
    <version>1.2.3</version>
    <scope>provided</scope>
</dependency>

You need to download and install this dependency to your local Maven repository: linchpin-sidebar-1.2.3.obr (This version should be sufficient for development, but you can also use linchpin-sidebar-1.3.0.obr)

mvn install:install-file
  -Dfile=./linchpin-sidebar-1.2.3.obr
  -DgroupId=net.seibertmedia.confluence
  -DartifactId=linchpin-sidebar
  -Dversion=1.2.3
  -Dpackaging=obr
  -DgeneratePom=true

(see also http://maven.apache.org/general.html#importing-jars)


Necessary instructions for the maven-confluence-plugin in your pom.xml:

<DynamicImport-Package>
    net.seibertmedia.confluence.linchpinsidebar.connect.external,
    net.seibertmedia.confluence.linchpinsidebar.render.translate.external
</DynamicImport-Package>


Setup (Content)

Currently the API only offers one method of integrating new sidebar content (see DisplayStrategy). While implementing the panel, a link to an action is transferred via the interface LinchpinSidebarPanel. The content of the panel is an iframe that renders this action. 


Definition of an action in the atlassian-plugin.xml:

<xwork name="Linchpin Sidebar Actions" key="linchpin-sidebar-actions">
    <package name="linchpin-sidebar-actions" extends="default" namespace="/linchpin/sidebar">
        <default-interceptor-ref name="defaultStack"/>
        <action name="saved-for-later" class="net.seibertmedia.confluence.linchpinsidebar.panels.savedforlater.SavedForLaterAction" method="doDefault">
            <result name="success" type="velocity">/sidebar/saved-for-later.vm</result>
        </action>
    </package>
</xwork>

Definition of a sidebar icons resource in the atlassian-plugin.xml:

<web-resource key="linchpin-sidebar-panel-icons">
    <resource name="recent.svg" type="download" location="sidebar/recent.svg" />
	<resource name="new-star.svg" type="download" location="sidebar/new-star.svg" />
</web-resource>

Minimum content of a velocity-template in the resource folder:

#requireResourcesForContext("linchpin-sidebar-iframe-utils")
<html>
<head>
    <title>Sidebar iFrame</title>
    <meta name="decorator" content="atl.popup" />
</head>
<body>
<div>
    <p>Some content...</p>
</div>
</body>
</html>


Stylings depending on a space scheme can be made with this lines within the iframe:

#set ($spaceKey = $req.getParameter("spaceKey"))
#set( $ltpCtx = {"spaceKey" : "$spaceKey"})
#if($spaceKey && $linchpinTheme)
    $linchpinTheme.includeExtensionResources($ltpCtx)
#end

#* alternativ *#
#parse ("/sidebar/space-scheme-aware-iframe.util.vm")


Integrating the resources under the context "linchpin-sidebar-iframe-utils" is necessary if:

  • the content of the action varies in size and might become larger than the sidebar itself. The loaded JavaScript ensures that the iframe of the action will be responsive within the sidebar. 
  • it's necessary to use one of the following util methods.

Within the action you can import two methods via requireJS (or almond), that make communication with the window outside the iframe easier.

  • getParentBody() returns a jQuery object of the surrounding body.
  • executeInParent(fn) executes a function in the surrounding window.

With this it's possible for example to open an aui dialog outside of the action. 


Example:

AJS.toInit(function () {

    var iframeUtils = require("linchpin/sidebar/iframe-utils");

    // move dialog to parent
    iframeUtils.getParentBody().append($('#demo-dialog'));
    $('#demo-dialog').remove();

    // Shows the dialog button within frame is clicked
    AJS.$("#dialog-show-button").click(function (e) {
        e.preventDefault();
        iframeUtils.executeInParent(function () {
            AJS.dialog2("#demo-dialog").show();
        });
    });

    // register close handler in parent
    iframeUtils.executeInParent(function () {
        // Hides the dialog
        AJS.$("#dialog-submit-button").click(function (e) {
            e.preventDefault();
            AJS.dialog2("#demo-dialog").hide();
        });
    });
})


By implementing the LinchpinSidebarPanel you define the URL to the action, how menu entries and their icons are shown etc.

Example:

public class SavedForLaterPanel implements LinchpinSidebarPanel {

    private final static I18nKey headline = I18nKey.of("starred.title");
    private final static I18nKey link = I18nKey.of("some.i18n.key");

    /* wird später u.U. für Migrationspfade nötig. aktuelle Version: 1 */
    @Override
    public int getApiVersion() {return 1; }

    /* aktuell einzige Art und Weise der Darstellung */
    @Override
    public DisplayStrategy getDisplayStrategy() {
        return DisplayStrategy.ACTION;
    }

    /* Angabe, wo das Icon des Eintrags zu sehen ist (überall oder nur im ausgeklappten Modus der Sidebar, vgl. JavaDocs am Enum) */
    @Override
    public MenuViewStrategy getMenuViewStrategy() {
        return MenuViewStrategy.DEFAULT;
    }

    /* Link zur Action */
    @Override
    public String getActionUrl() {
        return "/linchpin/sidebar/saved-for-later.action";
    }

    /* Identifier für das SVG-Icon (Format ist wichtig!) des Menüeintrages  */
    @Override
    public FrontendResourceIdentifier getIcon() {
        return new FrontendResourceIdentifier("net.seibertmedia.confluence.linchpin-sidebar:linchpin-sidebar-panel-icons", "new-star.svg");
    }

    /* Identifier für das svg (Format ist wichtig!) Icon des Menüeintrages im ausgeklappten Zustand.  Falls null wird das obere Icon verwendet. */
    @Nullable
    @Override
    public FrontendResourceIdentifier getNavigationIcon() {
        return null;
    }

    /* i18n Objekt für die Headline. Nicht im getter erzeugen. Objekt wird zur Laufzeit übersetzt. */
    @Override
    public I18nKey getHeadline() {
        return headline;
    }

    /* Link, der neben der Headline angezeigt wird. Optional. */
    @Override
    public AnchorLink getAnchor() {
        return new AnchorLink(link, "http://google.com");
    }
}