/**
* Copyright (C) 2005-2016 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* This is a customization of the [AlfCascadingMenu]{@link module:alfresco/menus/AlfCascadingMenu} to asynchronously
* load the available node creation templates from the Alfresco Repository. Currently this makes its own XHR call
* to retrieve the data (as this is quite a specific requirement) however it could potentially be decoupled via
* pub/sub to make more generic.
*
* @module alfresco/documentlibrary/AlfCreateTemplateContentMenu
* @extends module:alfresco/menus/AlfCascadingMenu
* @mixes module:alfresco/core/CoreXhr
* @author Dave Draper
*/
define(["dojo/_base/declare",
"alfresco/menus/AlfCascadingMenu",
"alfresco/documentlibrary/_AlfCreateContentMenuItemMixin",
"alfresco/documentlibrary/_AlfCreateContentPermissionsMixin",
"alfresco/documentlibrary/_AlfDocumentListTopicMixin",
"alfresco/core/CoreXhr",
"alfresco/menus/AlfMenuGroup",
"alfresco/menus/AlfMenuItem",
"dojo/_base/lang",
"dojo/_base/array",
"service/constants/Default"],
function(declare, AlfCascadingMenu, _AlfCreateContentMenuItemMixin, _AlfCreateContentPermissionsMixin,
_AlfDocumentListTopicMixin, AlfCoreXhr, AlfMenuGroup, AlfMenuItem, lang, array, AlfConstants) {
return declare([AlfCascadingMenu, _AlfCreateContentMenuItemMixin, _AlfCreateContentPermissionsMixin, _AlfDocumentListTopicMixin, AlfCoreXhr], {
/**
* An array of the i18n files to use with this widget.
*
* @instance
* @type {object[]}
* @default [{i18nFile: "./i18n/AlfCreateTemplateContentMenu.properties"}]
*/
i18nRequirements: [{i18nFile: "./i18n/AlfCreateTemplateContentMenu.properties"}],
/**
* This is the topic that is published by each menu item created within the cascade. It should not
* be reconfigured it as it is automatically generated to be a unique value so that only menu items
* added to this cascading menu will use it.
*
* @instance
* @type {String}
* @default
*/
_menuItemToParentTopic: null,
/**
* Indicates whether the templates have been loaded yet.
*
* @instance
* @type {boolean}
* @default
*/
_templatesAlreadyLoaded: false,
/**
* A URL to override the default. Primarily provided for the test harness.
* @instance
* @type {string}
* @default
*/
_templatesUrl: null,
/**
* The iconClass to use on each template content menu item
*
* @instance
* @type {string}
* @default
*/
templateIconClass: "alf-textdoc-icon",
/**
* The topic to publish on when requesting to create templated content
*
* @instance
* @type {string}
* @default
*/
templatePublishTopic: "ALF_CREATE_CONTENT",
/**
* The type of template to be created. Either "node" or "folder".
*
* @instance
* @type {string}
* @default
*/
templateType: "node",
/**
* This defines the default widgets to display in the menu which is initially just a loading
* message which should be replaced when the XHR request returns with some data.
*
* @instance
* @type {object[]}
*/
widgets: [
{
name: "alfresco/header/AlfMenuItem",
config: {
iconClass: "alf-loading-icon",
label: "loading.label"
}
}
],
/**
* Extends the [superclass function]{@link module:alfresco/menus/AlfCascadingMenu#postCreate} to subscribe to
* setup handlers to call [loadTemplates]{@link module:alfresco/documentlibrary/AlfCreateTemplateContentMenu#loadTemplates}
* when the cascading menu is opened.
*
* @instance
*/
postCreate: function alfresco_documentlibrary_AlfCreateTemplateContentMenu__postCreate() {
this.alfSubscribe(this.hashChangeTopic, lang.hitch(this, this.onFilterChange));
this.alfSubscribe(this.userAccessChangeTopic, lang.hitch(this, this.onUserAcess));
this.alfSubscribe(this.metadataChangeTopic, lang.hitch(this, this.onCurrentNodeChange));
// Create a unique topic for each menu item in the cascade to publish to in order for the
// current node to be added to the payload...
this._menuItemToParentTopic = this.generateUuid();
this.alfSubscribe(this._menuItemToParentTopic, lang.hitch(this, this.onCreateTemplatedContent), true);
this.inherited(arguments);
if (this.label)
{
this.set("label", this.message(this.label));
}
else
{
this.set("label", this.message("menu.label"));
}
if (this.popup)
{
// The "opOpen" function of the associated AlfMenuGroups widget is not defined by default so we're
// going to "link" it to the popupFocused function so that the first time the user clicks on the
// AlfSitesMenu in the menu bar we can asynchronously load the required data.
this.popup.onOpen = dojo.hitch(this, "loadTemplates");
}
else
{
this.alfLog("error", "No menu popup - something has gone wrong!");
}
},
/**
* This function is called when the user clicks on the "Templates" cascading menu item to asynchronously
* load the available content templates.
*
* @instance
*/
loadTemplates: function alfresco_documentlibrary_AlfCreateTemplateContentMenu__loadTemplates() {
if (this._templatesAlreadyLoaded)
{
this.alfLog("log", "Templates already loaded");
}
else
{
this.alfLog("log", "Loading templates");
var url = this._templatesUrl;
if (!url)
{
url = "slingshot/doclib/node-templates";
}
this.serviceXhr({url : AlfConstants.PROXY_URI + url,
method: "GET",
successCallback: this._templatesLoaded,
failureCallback: this._templatesLoadFailed,
callbackScope: this});
}
},
/**
* Handles the successful loading of template nodes.
*
* @instance _templatesLoaded
* @param {object} response The response from the request
* @param {object} originalRequestConfig The configuration passed on the original request
*/
_templatesLoaded: function alfresco_documentlibrary_AlfCreateTemplateContentMenu___templatesLoaded(response, /*jshint unused:false*/ originalRequestConfig) {
this.alfLog("log", "Templates data loaded successfully", response);
this._templatesAlreadyLoaded = true;
// Check for keyboard access by seeing if the first child is focused...
var focusFirstChild = this.popup && this.popup.getChildren().length > 0 && this.popup.getChildren()[0].focused;
// Remove the loading templates item...
var _this = this;
array.forEach(this.popup.getChildren(), function(widget) {
_this.popup.removeChild(widget);
});
// Add recent groups if there are some...
if (response.data)
{
if (response.data.length > 0)
{
var group = new AlfMenuGroup({});
this.popup.addChild(group);
array.forEach(response.data, dojo.hitch(this, "_addMenuItem", group));
}
else
{
// If there are no templates then we don't want to just display nothing, so we'll create
// a non-functional menu item (e.g. one that doesn't do anything) to indicate that there
// aren't any templates. A reference is kept so we can remove it when adding a new item.
this.addNoTemplatesMessageItem();
}
}
if (focusFirstChild)
{
// Focus the first template (or the no templates item)...
this.popup.focusFirstChild();
}
},
/**
* Handles failed attempts to load templates.
*
* @instance _templatesLoadFailed
* @param {object} response The response from the request
* @param {object} originalRequestConfig The configuration passed on the original request
*/
_templatesLoadFailed: function alfresco_documentlibrary_AlfCreateTemplateContentMenu___templatesLoadFailed(response, /*jshint unused:false*/ originalRequestConfig) {
this.alfLog("error", "Could not load templates menu items", response);
// Remove the loading templates item...
var _this = this;
array.forEach(this.popup.getChildren(), function(widget) {
_this.popup.removeChild(widget);
});
this.addTemplatesFailMessageItem();
},
/**
* Adds a non-functional message menu item to the templates menu. This is used when needing to
* indicate that the templates didn't load or that there are no templates.
*
* @instance
*/
addNoTemplatesMessageItem: function alfresco_documentlibrary_AlfCreateTemplateContentMenu__addNoTemplatesMessageItem() {
this._templatesMessageItem = new AlfMenuItem({
label: "no.templates.label"
});
this.popup.addChild(this._templatesMessageItem);
},
/**
* Adds a non-functional message menu item to the templates menu. This is used when needing to
* indicate that the templates could not be loaded. The most likely cause of this would be when
* connectivity has been lost, authentication timed out or the repository has gone down since
* loading the page.
*
* @instance
*/
addTemplatesFailMessageItem: function alfresco_documentlibrary_AlfCreateTemplateContentMenu__addTemplatesFailMessageItem() {
this._templatesMessageItem = new AlfMenuItem({
label: "templates.load.error"
});
this.popup.addChild(this._templatesMessageItem);
},
/**
* Adds an individual menu item.
*
* @instance
* @param {object} group The group to add the menu item to
* @param {object} widget The menu item to add
* @param {integer} index The index to add the menu item at.
*/
_addMenuItem: function alfresco_documentlibrary_AlfCreateTemplateContentMenu___addMenuItem(group, widget, /*jshint unused:false*/ index) {
var label = (widget.title !== "") ? widget.title : widget.name;
var item = new AlfMenuItem({
label: label,
iconClass: this.templateIconClass,
publishTopic: this._menuItemToParentTopic,
publishPayload: {
action: {
type: "template",
params: {
sourceNodeRef: widget.nodeRef,
targetNodeRef: null,
templateType: this.templateType,
name: widget.name,
title: widget.title,
description: widget.description
}
}
},
publishGlobal: true
});
group.addChild(item);
},
/**
* Adds the current node in which to create the templated content to the received payload and then publishes
* on to the [ActionService]{@link module:alfresco/services/ActionService} to create the templated content.
*
* @instance
* @param {object} payload The payload relating to the template to create.
*/
onCreateTemplatedContent: function alfresco_documentlibrary_AlfCreateTemplateContentMenu__onCreateTemplatedContent(payload) {
var targetNodeRef = lang.getObject("currentNode.parent.nodeRef", false, this);
if (targetNodeRef)
{
payload.action.params.targetNodeRef = this.currentNode.parent.nodeRef;
this.alfServicePublish(this.templatePublishTopic, payload);
}
else
{
this.alfLog("warn", "No current node has been provided in which to create templated content", payload, this);
}
}
});
});