You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 4 Next »

projectdoc Toolbox

Renders a menu with tools to inspect information from a projectdoc document, shown in the browser.

Identifier
de.smartics.userscripts.confluence.projectdoc-inspect-menu
Type
Repository
Since
1.0

The userscript renders a menu on a Confluence page with tools to inspect the projectdoc document shown in the browser.

It implements the following actions:

  1. Display Document Properties
  2. Display Space Properties
  3. Display Transcluding Documents

Code

The code of the script for reference.

projectdoc-inspect-menu.js
/*
 * Copyright 2019-2020 Kronseder & Reiner GmbH, smartics
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

"use strict";

AJS.toInit(function () {
  const logToConsole = false;

  const $propertiesMarker = AJS.$(".projectdoc-document-element.properties");
  if (!$propertiesMarker.length) {
    if (logToConsole) AJS.log("[projectdoc-inspect-menu] Not a projectdoc document. Quitting.");
    return;
  }

  const showDocumentProperties = function () {
    if(logToConsole) AJS.log("[projectdoc-inspect-menu] Fetching document properties ...");
    const pageId = AJS.params.pageId;
    const locale = AJS.params.userLocale;
    const baseURL = AJS.params.baseUrl;

    const htmlTitle = "Page Properties";
    let html = "<html lang='" + locale + "'><head><title>" + htmlTitle + "</title><style>" +
      " .table-sm td, .table-sm th {padding: .1rem !important;}" +
      " .table td, .table th { font-size: 10px !important;}" +
      "</style>" +
      "<link rel=\"stylesheet\"" +
      " href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css\"" +
      " integrity=\"sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T\"" +
      " crossorigin=\"anonymous\">" +
      "</head><body><h6>" + htmlTitle + "</h6>";
    if(logToConsole) AJS.log("[projectdoc-inspect-menu] Making call ...");
    AJS.$.ajax({
      url: baseURL + "/rest/projectdoc/1/document/" + pageId + ".json?expand=property&resource-mode=html",
      async: true,
      contentType: 'application/json'
    }).success(function (data) {
      if(logToConsole) AJS.log("[projectdoc-inspect-menu] Document Properties Data: " + JSON.stringify(data));

      html += "<table class=\"table table-sm table-bordered table-striped\">";
      AJS.$.each(data["property"],
        function (index, obj) {
          html = html + "<tr><th>" + obj.name + "</th><td>" + obj.value + "</td></tr>"
        }
      );
      html += "</table></body></html>";
      const showDialog = window.open('', '', 'width=600,height=800,location=no,toolbar=0');
      showDialog.document.body.innerHTML = html;
    }).error(function (jqXHR, textStatus) {
      AJS.log("[projectdoc-inspect-menu] Error fetching document properties: " + jqXHR.status + " (" + textStatus + ")");
      alert("Failed to fetch document properties: "  + jqXHR.status + " (" + textStatus + ")");
    });
  };

  const showSpaceProperties = function () {
    const spaceKey = AJS.params.spaceKey;
    const locale = AJS.params.userLocale;
    const baseUrl = AJS.params.baseUrl;

    const htmlTitle = "Space Properties for " + spaceKey;
    let html = "<html lang='" + locale + "'><head><title>" + htmlTitle + "</title><style>" +
      " .table-sm td, .table-sm th {padding: .1rem !important;}" +
      " .table td, .table th { font-size: 10px !important;}" +
      "</style>" +
      "<link rel=\"stylesheet\"" +
      " href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css\"" +
      " integrity=\"sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T\"" +
      " crossorigin=\"anonymous\">" +
      "</head><body><h6>" + htmlTitle + "</h6>";

    if(logToConsole) AJS.log("[projectdoc-inspect-menu] Querying Properties Data for Space '" + spaceKey + "' ...");
    AJS.$.ajax({
      url: baseUrl + "/rest/projectdoc/1/space/" + spaceKey,
      async: true,
      dataType: 'json'
      //contentType: 'application/json'
    }).success(function (data) {
      if(logToConsole) AJS.log("[projectdoc-inspect-menu] Space Properties Data: " + JSON.stringify(data));

      html += "<table class=\"table table-sm table-bordered table-striped\">";
      AJS.$.each(data["property"],
        function (index, obj) {
          html = html + "<tr><td>" + obj.source + "</td><th>" + obj.name + "</th><td>" + obj.value + "</td></tr>"
        }
      );
      html += "</table></body></html>";

      const showDialog = window.open('', '', 'width=600,height=800,location=no,toolbar=0');
      showDialog.document.body.innerHTML = html;
    }).error(function (jqXHR, textStatus) {
      AJS.log("[projectdoc-inspect-menu] Error fetching space properties: " + jqXHR.status + " (" + textStatus + ")");
      alert("Failed to fetch space properties: "  + jqXHR.status + " (" + textStatus + ")");
    });
  };

  const listTranscludingDocument = function () {
    const pageId = AJS.params.pageId;
    const locale = AJS.params.userLocale;
    const baseUrl = AJS.params.baseUrl;

    function createPage(i18n, currentDocument, documents) {
      const htmlTitle = "Transcluding Documents for " + currentDocument[i18n.name];
      let html = "<html lang='" + locale + "'><head><title>" + htmlTitle + "</title><style>" +
        " body {margin: 1rem !important;}" +
        " .table-sm td, .table-sm th {padding: .1rem !important;}" +
        " .table td, .table th { font-size: .8rem !important;}" +
        "</style>" +
        "<link rel=\"stylesheet\"" +
        " href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css\"" +
        " integrity=\"sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T\"" +
        " crossorigin=\"anonymous\">" +
        "</head><body><h3>" + htmlTitle + "</h3>";
      html += "<table class=\"table table-sm table-bordered table-striped\">";

      const hitCount = documents.document.length;
      const tinyUrlNamePlain = i18n["tinyUrl"]+ '\u00a7';
      html += "<p>Content of document '<a href='" + currentDocument[tinyUrlNamePlain] + "'>" + currentDocument[i18n.name] + "</a>' is transcluded by ";
      if (hitCount === 0) {
        html += "no document.</p>";
      } else if (hitCount === 1) {
        html += "one document.</p>";
      } else {
        html += hitCount + " documents.</p>";
      }

      $.each(documents.document, function (index, doc) {
          const current = {};
          $.each(doc.property, function (i, property) {
            current[property.name] = property.value;
          });
          const name = current[i18n.name];
          const shortDescription = current[i18n.shortDescription];
          const url = current[tinyUrlNamePlain];
          html = html + "<tr><th><a href='" + url + "'>" + name + "</a></th><td>" + shortDescription + "</td></tr>";
        }
      );

      html += "</table></body></html>";
      return html;
    }

    if(PDBMLS) {
      const i18n = PDBMLS.fetchI18n(baseUrl, ["title", "spaceKey", "name", "shortDescription", "tinyUrl"]);
      const tinyUrlNamePlain = i18n["tinyUrl"]+ '\u00a7';

      const currentDocument = PDBMLS.fetchDocument(baseUrl, pageId, [i18n.spaceKey, i18n.title, i18n.name, tinyUrlNamePlain]);

      if (currentDocument) {
        const spaceKey = currentDocument[i18n.spaceKey];
        const title = currentDocument[i18n.title];
        const pageReference = spaceKey + "." + title;
        const where = "$<TranscludedDocumentTitles>=[" + pageReference + "]";

        const documents = PDBMLS.fetchDocuments(baseUrl, [i18n.name, i18n.shortDescription, tinyUrlNamePlain], where);
        let html = createPage(i18n, currentDocument, documents);

        const container = window.open('', '', 'width=600,height=800,location=no,toolbar=0');
        container.document.body.innerHTML = html;
      }
    } else {
      AJS.log("[projectdoc-inspect-menu] Error transcluding documents. PDBMLS service of Bookmarklets Extension not found.");
      alert("Failed to transcluding documents: PDBMLS service of Bookmarklets Extension not found.");
    }
  };

  if (logToConsole) AJS.log("[projectdoc-inspect-menu] Adding menu ...");
  const createMenu = function () {
    const $rootEntry = AJS.$("<div id='projectdoc-menu-inspect'></div>");
    $rootEntry.addClass("aui-buttons");

    const $menu = AJS.$("<button id='projectdoc-menu-inspect-button'></button>");
    $menu.addClass("aui-button aui-dropdown2-trigger");
    $menu.attr("aria-controls", "projectdoc-menu-inspect-dropdown");
    $rootEntry.append($menu);
    $menu.text("Inspect");
    const $dropdown = AJS.$("<aui-dropdown-menu id=\"projectdoc-menu-inspect-dropdown\">");
    $menu.append($dropdown);

    const $propertiesSection = AJS.$("<aui-section label=\"Properties\">");
    $dropdown.append($propertiesSection);

    const $menuItemDocumentProperties = AJS.$("<aui-item-link id='projectdoc-menu-inspect-item-document-properties' href=\"#document-properties\"></aui-item-link>");
    $menuItemDocumentProperties.text("Show document properties");
    $menuItemDocumentProperties.on("click", function (event) {
      event.preventDefault();
      showDocumentProperties();
    });
    $propertiesSection.append($menuItemDocumentProperties);

    const $menuItemSpaceProperties = AJS.$("<aui-item-link id='projectdoc-menu-inspect-item-space-properties' href=\"#space-properties\"></aui-item-link>");
    $menuItemSpaceProperties.text("Show space properties");
    $menuItemSpaceProperties.on("click", function (event) {
      event.preventDefault();
      showSpaceProperties();
    });
    $propertiesSection.append($menuItemSpaceProperties);

    const $menuItemTransclusions = AJS.$("<aui-item-link id='projectdoc-menu-inspect-item-transclusions' href=\"#transclusions\"></aui-item-link>");
    $menuItemTransclusions.text("Show transclusions");
    $menuItemTransclusions.on("click", function (event) {
      event.preventDefault();
      listTranscludingDocument();
    });
    $propertiesSection.append($menuItemTransclusions);

    return $rootEntry;
  }

  const getParentWith = function ($rootElement, tagName) {
    let $parent = $rootElement.parent();
    while ($parent !== undefined) {
      if (logToConsole) AJS.log("[projectdoc-inspect-menu] Found parent '" + $parent.prop('tagName') + "'.");
      if ($parent.prop('tagName') === tagName) {
        if (logToConsole) AJS.log("[projectdoc-inspect-menu] Parent is matching.");
        return $parent;
      }
      $parent = $parent.parent();
    }
  };

  const $createButton = AJS.$('#create-page-button');
  if ($createButton.length) {
    if (logToConsole) AJS.log("[projectdoc-inspect-menu] Found create button on page.");
    const $navContainer = getParentWith($createButton, "UL");
    if ($navContainer) {
      if (logToConsole) AJS.log("[projectdoc-inspect-menu] Found navigation container on page.");
      const $projectdocMenu = createMenu();
      $navContainer.append($projectdocMenu);
    } else {
      AJS.log("[projectdoc-inspect-menu] No navigation container found on page to add menu. No menu is added.");
    }
  }
});

Details

More information on using this userscript.

Rendering

The inspect menu is rendered next to the create button in the Confluence toolbar.

Screenshot showing the menu with its menu items.

Requirements

The script requires the following apps to be installed on Confluence.

The projectdoc Toolbox for Atlassian Confluence
The projectdoc Toolbox supports agile teams in writing project documentation collaboratively. This is an introduction to use cases for and features of the projectdoc Toolbox.
Web API Extension
Add-on to extend projectdoc with an API to access on the web.
Bookmarklets Extension
Add-on to extend the Toolkit with Bookmarklets. Allows to execute tools via the browser.

Limitations

There is an issue with the calculation of the URLs to transcluding pages.

Resources

More information on this topic is available by the following resources.

Display Document Properties
Displays the document properties of the projectdoc document currently shown in the browser.
Display Space Properties
Displays the space properties of the projectdoc document's space currently shown in the browser.
List Transcluding Documents
Shows the list of documents that transclude content from the current document.



  • No labels