/*
* Copyright 2019 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.
*/
/**
* This tool displays the description of the extraction and the list of all available extraction files
* @private
*/
Ext.define('Ametys.plugins.extraction.execution.ExtractionExecutionTool', {
extend: "Ametys.tool.Tool",
/**
* @readonly
* @property {Boolean} extractionTabCompatible Specify this tool is compatible with the 'extraction tab'.
*/
extractionTabCompatible: true,
/**
* @private
* @property {String} _definitionFilePath Definition file path.
*/
/**
* @private
* @property {String} _definitionFileName Definition file name.
*/
/**
* @private
* @property {String} _descriptionId Identifier of the description.
*/
/**
* @private
* @property {Object} _author the extraction definition author
* @property {String} _author.login the author's login
* @property {String} _author.populationId the author's population identifier
*/
/**
* @private
* @property {String} _canRead true if the current user can read the extraction definition
*/
/**
* @private
* @property {String} _canWrite true if the current user can write the extraction definition
*/
/**
* @private
* @property {String} _canDelete true if the current user can delete the extraction definition
*/
/**
* @private
* @property {String} _canAssignRights true if the current user can edit rights of the extraction definition
*/
/**
* @private
* @property {Boolean} _isConcernedByCurrentModification <code>true</code> if this tool is concerned by the las MODIFYNG sent message, <code>false</code> otherwise.
*/
/**
* @private
* @property {String} _oldFilePath the extraction definition old file path
*/
/**
* @private
* @property {Ext.ux.IFrame} _descriptionIFrame The iframe object containing the description
*/
/**
* @private
* @property {Ametys.form.ConfigurableFormPanel} _executionForm The form for execution parameters
*/
/**
* @private
* @property {String} _baseUrl The url that the description iframe should stay on
*/
constructor: function(config)
{
this.callParent(arguments);
// Bus messages listeners
Ametys.message.MessageBus.on(Ametys.message.Message.MODIFYING, this._onDefinitionFileModifying, this);
Ametys.message.MessageBus.on(Ametys.message.Message.MODIFIED, this._onModified, this);
Ametys.message.MessageBus.on(Ametys.message.Message.DELETED, this._onDefinitionFileDeleted, this);
},
createPanel: function()
{
var descriptionIFrame = this._createDescriptionIFrame();
var executionFormPanel = this._createExecutionFormPanel();
return Ext.create("Ext.Panel", {
layout: {
type: 'vbox',
align: 'stretch'
},
items: [descriptionIFrame, executionFormPanel]
});
},
/**
* @private
* Create the panel with the description
* @return {Ext.Panel} The description panel
*/
_createDescriptionIFrame: function()
{
this._descriptionIFrame = Ext.create("Ext.ux.IFrame", {
flex:2,
split: true,
minHeight: 200
});
this._descriptionIFrame.on ('load', this._onIframeLoad, this);
return this._descriptionIFrame;
},
/**
* @private
* Create the panel with the execution form
* @return {Ext.Panel} The form panel
*/
_createExecutionFormPanel: function()
{
var executeButton = {
text: "{{i18n PLUGINS_EXTRACTION_EXECUTION_TOOL_BUTTON_LABEL}}",
handler: this._onExecute,
scope: this,
iconCls: 'ametysicon-play124'
};
this._executionForm = Ext.create('Ametys.form.ConfigurableFormPanel', {
flex: 1,
labelAlign: 'top'
});
return Ext.create("Ext.Panel", {
layout: {
type: 'vbox',
align: 'stretch'
},
flex:1,
split: true,
minHeight: 100,
items: [{
xtype: 'component',
html: "{{i18n PLUGINS_EXTRACTION_EXECUTE_EXTRACTION_DIALOG_DESCRIPTION}}"
},
this._executionForm
],
bbar : [executeButton]
});
},
getMBSelectionInteraction: function()
{
return Ametys.tool.Tool.MB_TYPE_ACTIVE;
},
/**
* Listener when definition files are beeing modifying
* @param {Ametys.message.Message} message The edition message.
* @private
*/
_onDefinitionFileModifying: function(message)
{
var target = message.getTarget(Ametys.message.MessageTarget.EXTRACTION_DEFINITION_FILE) || message.getTarget(Ametys.message.MessageTarget.EXTRACTION_DEFINITION_FOLDER);
if (target != null)
{
this._isConcernedByCurrentModification = Ext.String.startsWith(this._definitionFilePath, target.getParameters().path);
this._oldFilePath = target.getParameters().path;
}
},
/**
* Listener when definition files have been edited
* Will refresh the tool
* @param {Ametys.message.Message} message The edition message.
* @private
*/
_onModified: function(message)
{
if (!this._isConcernedByCurrentModification)
{
return;
}
var hasToRefreshTool = false;
// Check if the folder of the current extraction has been modified
var folderTarget = message.getTarget(Ametys.message.MessageTarget.EXTRACTION_DEFINITION_FOLDER);
if (folderTarget != null)
{
this._definitionFilePath = this._definitionFilePath.replace(this._oldFilePath, folderTarget.getParameters().path);
hasToRefreshTool = true;
}
// Check if the definition of the current extraction has been modified
var definitionFileTarget = message.getTarget(Ametys.message.MessageTarget.EXTRACTION_DEFINITION_FILE);
if (definitionFileTarget != null)
{
this._definitionFilePath = definitionFileTarget.getParameters().path;
this._definitionFileName = definitionFileTarget.getParameters().name;
// Get the description id from the target
var descriptionTarget = definitionFileTarget.getSubtarget(Ametys.message.MessageTarget.CONTENT);
var description = descriptionTarget ? descriptionTarget.getParameters().content : undefined;
this._descriptionId = description ? description.getId() : undefined
this._definitionAuthor = definitionFileTarget.getParameters().author;
this._definitionCanRead = definitionFileTarget.getParameters().canRead;
this._definitionCanWrite = definitionFileTarget.getParameters().canWrite;
this._definitionCanDelete = definitionFileTarget.getParameters().canDelete;
hasToRefreshTool = true;
}
// Check if the description of the current extraction has been modified
var contentTarget = message.getTarget(Ametys.message.MessageTarget.CONTENT, 1);
if (contentTarget != null)
{
var content = contentTarget.getParameters().content;
var contentId = content ? content.getId() : undefined
if (contentId == this._descriptionId)
{
hasToRefreshTool = true;
}
}
if (hasToRefreshTool)
{
this.refresh();
}
},
/**
* Listener when definition files have been deleted
* @param {Ametys.message.Message} message The deletion message.
* @private
*/
_onDefinitionFileDeleted: function(message)
{
var target = message.getTarget(Ametys.message.MessageTarget.EXTRACTION_DEFINITION_FILE) || message.getTarget(Ametys.message.MessageTarget.EXTRACTION_DEFINITION_FOLDER);
if (target != null)
{
if (Ext.String.startsWith(this._definitionFilePath, target.getParameters().path))
{
Ametys.tool.ToolsManager.removeTool(this);
}
}
},
sendCurrentSelection: function()
{
var targetParameters = {
path: this._definitionFilePath,
name: this._definitionFileName,
descriptionId: this._descriptionId,
author: this._author,
canRead: this._canRead,
canWrite: this._canWrite,
canDelete: this._canDelete,
canAssignRights: this._canAssignRights
}
Ext.create('Ametys.message.Message', {
type: Ametys.message.Message.SELECTION_CHANGED,
targets: {
id: Ametys.message.MessageTarget.EXTRACTION_DEFINITION_FILE,
parameters: targetParameters
}
});
},
setParams: function(params)
{
this.callParent(arguments);
this._definitionFilePath = params['id'];
this._definitionFileName = params['name'];
this._descriptionId = params['descriptionId'];
this._author = params['author'];
this._canRead = params['canRead'];
this._canWrite = params['canWrite'];
this._canDelete = params['canDelete'];
this._canAssignRights = params['canAssignRights'];
this.refresh();
},
refresh: function()
{
this.showRefreshing();
// Change the title of the tool to have the extraction name
this.setTitle(this._definitionFilePath);
// Refresh the description panel
if (this._descriptionId)
{
this._descriptionIFrame.show();
var wrappedUrl = this.getWrappedContentUrl ();
this._descriptionIFrame.load(Ametys.CONTEXT_PATH + wrappedUrl)
this._baseUrl = Ametys.CONTEXT_PATH + wrappedUrl;
}
else
{
this._descriptionIFrame.hide();
}
// Refresh the execution form
var encodedDefinitionFilePath = encodeURIComponent(this._definitionFilePath);
this.serverCall('getExecutionParameters', [encodedDefinitionFilePath], Ext.bind(this._refreshCb, this));
},
/**
* Get the wrapped url for content
* @returns {String} The wrapped url
*/
getWrappedContentUrl: function()
{
var additionParams = '';
additionParams += '&viewName=main'
additionParams += '&lang=' + Ametys.cms.language.LanguageDAO.getCurrentLanguage(); // default rendering language for multilingual content
// FIXME CMS-2316
var appParameters = Ametys.getAppParameters();
Ext.Object.each(appParameters, function(key, value) {
additionParams += '&' + key + '=' + encodeURIComponent(value);
});
return '/_wrapped-content.html?contentId=' + this._descriptionId + additionParams;
},
/**
* @private
* Listener called when the iframe is loaded.
* Protects the iframe by handling links of the internal frame by setting a onclick on every one
* @param {Ext.ux.IFrame} iframe The iframe
*/
_onIframeLoad: function(iframe)
{
if (window.event && window.event.srcElement.readyState && !/loaded|complete/.test(window.event.srcElement.readyState))
{
return;
}
Ametys.plugins.cms.content.tool.ContentTool.__URL_REGEXP.test(window.location.href);
var win = this._descriptionIFrame.getWin();
var outside = false;
try
{
win.location.href
}
catch (e)
{
outside = true;
}
if (outside || (win.location.href != 'about:blank' && win.location.href.indexOf(RegExp.$1 + this._baseUrl) != 0))
{
var outsideUrl = win.location.href;
// Back to iframe base url
win.location.href = this._baseUrl;
// Open ouside url in a new window
window.open(outsideUrl);
}
else
{
var links = win.document.getElementsByTagName("a");
for (var a = 0; a < links.length; a++)
{
if (links[a].getAttribute("internal") == null && !links[a].onclick)
{
links[a].onclick = Ext.bind(this._handleLink, this, [links[a]], false);
}
}
this._descriptionIFrame.getWin().onfocus = Ext.bind(this._onIframeFocus, this);
}
},
/**
* @private
* Lazy handling of links. Each times a link is clicked, check if we should open it in a window, open another tool...
* @param {HTMLElement} link The clicked link
*/
_handleLink: function(link)
{
var currentURI = this._descriptionIFrame.getWin().location.href;
var absHref = link.href;
var relHref = null;
if (/^(https?:\/\/[^\/]+)(\/.*)?/.test(absHref) && absHref.indexOf(RegExp.$1 + Ametys.CONTEXT_PATH) == 0)
{
relHref = absHref.substring(absHref.indexOf(RegExp.$1 + Ametys.CONTEXT_PATH) + (RegExp.$1 + Ametys.CONTEXT_PATH).length);
}
// Internal link
if (absHref.indexOf(currentURI) == 0) return true;
// JS Link
if (absHref.indexOf("javascript:") == 0) return true;
// Download link
if (relHref != null && relHref.indexOf("/plugins/explorer/download/") == 0) return true;
// Unknown link : open in a new window
window.open(absHref);
return false;
},
/**
* @private
* Listener when iframe takes the focus.<br/>
* Force the focus on tool.
*/
_onIframeFocus: function()
{
// Force focus on tool
this.focus();
},
/**
* @private
* Callback called when the execution for parameters are retrieved
* @param {Object} formConfiguration configuration of the execution form
*/
_refreshCb: function(formConfiguration)
{
this._executionForm.destroyComponents();
this._executionForm.configure(formConfiguration);
this._executionForm.setValues({});
this.showRefreshed();
},
/**
* @private
* Launch the extraction execution if the form is valid
*/
_onExecute: function()
{
if (this._executionForm && !this._executionForm.isValid())
{
return;
}
var values = this._executionForm.getJsonValues();
var variablesValues = {};
var recipient;
var pipelineId;
Ext.Object.each(values, function(key, value) {
switch (key)
{
case 'recipient':
recipient = value;
break;
case 'pipeline':
pipelineId = value;
break;
default:
variablesValues[key] = value;
break;
}
});
this.getContentPanel().mask();
this.serverCall('executeExtraction', [this._definitionFilePath, variablesValues, recipient, pipelineId], Ext.bind(this._executionLaunchedCb, this), { ignoreCallbackOnError: false });
},
/**
* @private
* Callback called when the extraction has been launched
* @param {Object} response Server response
*/
_executionLaunchedCb: function(response)
{
this.getContentPanel().unmask();
if (response && response['error'])
{
Ametys.Msg.show({
title: "{{i18n plugin.core:PLUGINS_CORE_SCHEDULER_ERROR_SCHEDULER_TITLE}}",
msg: "{{i18n plugin.core:PLUGINS_CORE_SCHEDULER_ERROR_SCHEDULER}}",
buttons: Ext.Msg.OK,
icon: Ext.MessageBox.ERROR
});
}
else
{
Ametys.notify({
title: "{{i18n PLUGINS_EXTRACTION_EXECUTE_EXTRACTION_LAUNCHED_NOTIF_TITLE}}",
description: "{{i18n PLUGINS_EXTRACTION_EXECUTE_EXTRACTION_LAUNCHED_NOTIF_DESCRIPTION}}"
});
}
}
});