/*
* Copyright 2013 Anyware Services
*
* 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.
*/
/**
* Singleton class do action on workflow
* @private
*/
Ext.define('Ametys.plugins.cms.content.actions.WorkflowAction', {
singleton: true,
/**
* @property {Number} _count Counter for processed contents
* @private
*/
_count: 0,
/**
* @property {String[]} _cumulatedContentsIds Array of processed contents' ids
* @private
*/
_cumulatedContentsIds: [],
/**
* @property {Ametys.window.DialogBox} _commentBox The popup window embedding a simple form with textarea to allow the user to enter a comment on workflow action
* @private
*/
_commentBox: null,
/**
* Action function to be called by the controller, check if it has to be confirmed.
* Will execute the workflow action of controller on all contents stored by the controller in controller.contents properties
* @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
* @param {Function} [callback] The callback function to call instead of the _startAction method
*/
doAction: function (controller, callback)
{
var needConfirm = controller.getInitialConfig('confirm') == "true";
if (needConfirm)
{
var title = controller.getInitialConfig('confirm-title') || "{{i18n plugin.cms:PLUGINS_CMS_WORKFLOW_DO_ACTION_TITLE}}";
var confirmMsg = controller.getInitialConfig('confirm-msg') || "{{i18n plugin.cms:PLUGINS_CMS_WORKFLOW_DO_ACTION_CONFIRM_MSG}}";
Ametys.Msg.confirm(title,
confirmMsg,
function(answer)
{
if (answer == 'yes')
{
Ametys.plugins.cms.content.actions.WorkflowAction._doAction(controller, callback);
}
}
);
}
else
{
Ametys.plugins.cms.content.actions.WorkflowAction._doAction(controller, callback);
}
},
/**
* Action function to be called by the controller.
* Will execute the workflow action of controller on all contents stored by the controller in controller.contents properties
* @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
* @param {Function} [callback] The callback function to call instead of the _startAction method
* @private
*/
_doAction: function (controller, callback)
{
if (controller.getInitialConfig('comment') == "true")
{
this._showCommentBox (controller, callback);
}
else if (callback)
{
callback(controller, '');
}
else
{
this._startAction (controller, '');
}
},
/**
* Execute the workflow action of controller on all contents stored by the controller in controller.contents properties
* @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling the #doAction function
* @param {String} comment The comments writen by caller. Can be empty
* @private
*/
_startAction: function (controller, comment /*, args */)
{
// Controller can be a WorkflowMenu item or SmartContentController
var actionId = controller.getInitialConfig('workflow-action-id') || controller.getWorkflowActionId();
var contentIds = controller.contents || controller.getContentIds();
var longRequest = controller.getConfig("long-request") || controller.getInitialConfig('long-request');
if (!Ext.isBoolean(longRequest))
{
longRequest = longRequest === 'true';
}
var args = Array.prototype.slice.call(arguments, 2);
var me = this;
Ametys.cms.content.ContentDAO.getContents(contentIds, function(contents) {
Ext.create("Ametys.message.Message", {
type: controller.getInitialConfig('workflow-changing-message-type') || Ametys.message.Message.WORKFLOW_CHANGING,
targets: {
id: Ametys.message.MessageTarget.CONTENT,
parameters: { contents: contents }
}
});
for (var i=0; i < contents.length; i++)
{
var contentId = contents[i].getId();
Ametys.data.ServerComm.send({
plugin: controller.getInitialConfig('workflow-action-plugin') || 'cms',
url: (controller.getInitialConfig('workflow-action-url') || 'do-action') + '/' + actionId,
parameters: {contentId: contentId, id: contentId, comment: comment, args: args},
priority: longRequest ? Ametys.data.ServerComm.PRIORITY_LONG_REQUEST : Ametys.data.ServerComm.PRIORITY_MAJOR,
waitMessage: controller.getConfig("waitMessage") || controller.getInitialConfig('waitMessage') || false,
callback: {
handler: me._workflowActionCallback,
scope: me,
arguments: [contentId, contents.length, controller, contents]
}
});
}
});
},
/**
* Callback function called after #_startAction is processed.
* Fires Ametys.message.Message.WORKFLOW_CHANGED message for concerned contents
* @param {Object} response The XML response provided by the {@link Ametys.data.ServerComm}
* @param {Object} args The callback parameters passed to the {@link Ametys.data.ServerComm#send} method
* @private
*/
_workflowActionCallback: function (response, args)
{
this._cumulatedContentsIds = this._cumulatedContentsIds || [];
this._count = this._count > 0 ? this._count : 0;
this._cumulatedContentsIds.push(args[0]);
this._count++;
var controller = args[2];
if (Ametys.data.ServerComm.handleBadResponse("{{i18n PLUGINS_CMS_WORKFLOW_ERROR_DESC}}", response, "Ametys.plugins.cms.content.controller.WorkflowMenu.doAction"))
{
// Fail: send WORKFLOW_CHANGED for all initial contents to stop refreshing of controller that listened for WORKFLOW_CHANGING
Ext.create("Ametys.message.Message", {
type: controller.getInitialConfig('workflow-changed-message-type') || Ametys.message.Message.WORKFLOW_CHANGED,
targets: {
id: Ametys.message.MessageTarget.CONTENT,
parameters: { contents: args[3] }
}
});
return;
}
var notificationMode = controller.getConfig("end-process-notification") || controller.getInitialConfig('end-process-notification') || 'message-box';
var success = Ext.dom.Query.selectValue ('> ActionResult > success', response) == "true";
var workflowErrors = Ext.dom.Query.select ('> ActionResult > workflowValidation > error', response);
if (!success && workflowErrors.length > 0)
{
var errorMsg = "{{i18n PLUGINS_CMS_WORKFLOW_ERROR_DESC}}" + args[0];
errorMsg += '<ul>';
for (var i=0; i < workflowErrors.length; i++)
{
errorMsg += '<li>' + Ext.dom.Query.selectValue("", workflowErrors[i]) + '</li>';
}
errorMsg += '</ul>';
if (notificationMode == 'message-box')
{
Ametys.Msg.show({
title: "{{i18n PLUGINS_CMS_WORKFLOW_ERROR_TITLE}}",
msg: errorMsg,
buttons: Ext.Msg.OK,
icon: Ext.Msg.ERROR
});
}
else
{
Ametys.notify({
type: 'error',
iconGlyph: 'ametysicon-letter-x5',
title: "{{i18n PLUGINS_CMS_WORKFLOW_ERROR_TITLE}}",
description: errorMsg
});
}
return;
}
var workflowWarnings = Ext.dom.Query.select ('> ActionResult > workflowValidation > warning', response);
if (workflowWarnings.length > 0)
{
var warnMsg = "{{i18n PLUGINS_CMS_WORKFLOW_WARN_DESC}}";
warnMsg += '<ul>';
for (var i=0; i < workflowWarnings.length; i++)
{
warnMsg += '<li>' + Ext.dom.Query.selectValue("", workflowWarnings[i]) + '</li>';
}
warnMsg += '</ul>';
if (notificationMode == 'message-box')
{
Ametys.Msg.show({
title: "{{i18n PLUGINS_CMS_WORKFLOW_WARN_TITLE}}",
msg: warnMsg,
buttons: Ext.Msg.OK,
icon: Ext.Msg.WARNING
});
}
else
{
Ametys.notify({
type: 'warn',
iconGlyph: 'ametysicon-caution9',
title: "{{i18n PLUGINS_CMS_WORKFLOW_WARN_TITLE}}",
description: warnMsg
});
}
}
// FIXME Optimize "with-contents"
var max = args[1];
if (this._count == max)
{
Ametys.cms.content.ContentDAO.getContents(this._cumulatedContentsIds, function(contents) {
// FIXME Fire lock changed ?
Ext.create("Ametys.message.Message", {
type: controller.getInitialConfig('workflow-changed-message-type') || Ametys.message.Message.WORKFLOW_CHANGED,
targets: {
id: Ametys.message.MessageTarget.CONTENT,
parameters: { contents: contents }
}
});
var successMsg = controller.getConfig("successMsg") || controller.getInitialConfig('successMsg');
if (workflowWarnings.length == 0 && successMsg)
{
var contentTitles = [];
Ext.Array.each(contents, function(content){
contentTitles.push(content.getTitle());
});
Ametys.notify({
type: 'info',
iconGlyph: 'ametysicon-check34',
title: controller.getConfig("successTitle") || controller.getInitialConfig('successTitle') || "{{i18n PLUGINS_CMS_WORKFLOW_SUCCESS_TITLE}}",
description: Ext.String.format(successMsg, contentTitles)
});
}
});
this._count = 0;
this._cumulatedContentsIds = [];
}
},
/**
* This function show dialog to enter comment on workflow action
* @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling the #doAction function
* @param {Function} [callback] The callback function to call after validating comment
* @private
*/
_showCommentBox: function (controller, callback)
{
if (this._commentBox == null)
{
this._commentBox = Ext.create('Ametys.window.DialogBox', {
title: "{{i18n PLUGINS_CMS_WORKFLOW_COMMENTS_DIALOG_TITLE}}",
icon: Ametys.getPluginResourcesPrefix('cms') + '/img/content/content_16.png',
cls: 'text-dialog',
width: 450,
height: 250,
scrollable: false,
defaults: {
cls: 'ametys',
labelAlign: 'right',
labelSeparator: '',
labelWidth: 120
},
items: [{
xtype: 'component',
html: "{{i18n PLUGINS_CMS_WORKFLOW_COMMENTS_DIALOG_MESSAGE}}",
width: '100%'
},
{
xtype: 'textareafield',
name: 'comment',
itemId: 'workflow-comment',
ametysDescription: "{{i18n PLUGINS_CMS_WORKFLOW_COMMENTS_DIALOG_TEXTAREA_DESC}}",
width: '100%',
height: 140
}
],
defaultFocus: 'workflow-comment',
closeAction: 'hide',
buttons : [{
text :"{{i18n PLUGINS_CMS_WORKFLOW_COMMENTS_DIALOG_OK}}",
handler : Ext.bind(this._validateComment, this, [controller, callback])
}, {
text :"{{i18n PLUGINS_CMS_WORKFLOW_COMMENTS_DIALOG_CANCEL}}",
handler: Ext.bind(function() {this._commentBox.hide();}, this)
}]
});
}
else
{
this._commentBox.down('button').setHandler (Ext.bind(this._validateComment, this, [controller, callback]));
}
this._commentBox.down('#workflow-comment').setValue('');
this._commentBox.show();
},
/**
* Function handler called when the 'Ok' button of #_commentBox dialog box is pressed
* @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling the #doAction function
* @param {Function} [callback] The callback function
* @private
*/
_validateComment: function (controller, callback)
{
var comment = this._commentBox.down('#workflow-comment').getValue();
this._commentBox.hide();
if (callback)
{
callback(controller, comment);
}
else
{
this._startAction (controller, comment);
}
}
});