/*
* Copyright 2015 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 class controls a ribbon query editor button.
* @private
*/
Ext.define('Ametys.plugins.externaldata.editor.QueryEditorButton', {
extend: 'Ametys.cms.editor.EditorButtonController',
statics: {
/**
* @private
* @property {Object} _queryData Query parameter cache. Avoids making a request each time a query is clicked in the editor.
*/
_queryData: {},
/**
* @private
* @property {Object} _listeners The listeners of the button.
*/
_listeners: {},
/**
* @private
* @property {Ext.form.Panel} _queryParamsPanel The params panel (on the right).
*/
/**
* @private
* @property {Ext.form.Panel} _queryDetailsPanel The params panel (on the left).
*/
/**
* @property {String} width. The width config.
*/
/**
* @property {String} disabled. The disabled config.
*/
/**
* Sets 'query-parameters' element to current node when the input loses the focus.
* @param {Ext.form.field.Text} input The input text
*/
setQueryParamsOnBlur: function(input)
{
this._setQueryParams(input.getName(), input.getValue());
},
/**
* Sets 'query-parameters' element to current node when pressing ENTER or ESC key.
* @param {Ext.form.field.Text} input The input text
* @param {Ext.event.Event} e The event object
*/
setQueryParamsOnSpecialKey: function(input, e)
{
if (e.getKey() == e.ENTER)
{
e.preventDefault();
e.stopPropagation();
this._setQueryParams(input.getName(), input.getValue());
}
else if (e.getKey() == e.ESC)
{
e.preventDefault();
e.stopPropagation();
input.setValue(this._currentNode.title || "");
}
},
/**
* Sets 'query-parameters' element to current node.
* @param {String} name The name of the field.
* @param {String} value The value to set.
* @private
*/
_setQueryParams: function(name, value)
{
var queryNode = this._currentNode;
if (queryNode != null && name != null)
{
// FIXME we do a defer to avoid an infinite loop with the event 'onblur'
Ext.defer(this._setQueryParams2, 0.1, this, [name, value, queryNode]);
}
},
/**
* Effectively sets 'query-parameters' element to current node. Called by {@link #_setQueryParams}.
* @param {String} name The name of the field.
* @param {String} value The value to set.
* @param {HTMLElement} queryNode The node to set.
* @private
*/
_setQueryParams2: function(name, value, queryNode)
{
// FIXME "tinyMCE.activeEditor" a better method is to use the field.getEditor()
tinyMCE.activeEditor.focus();
var paramName = name.substring(12, name.length);
var attributeName = 'param-' + paramName;
if (value == '')
{
if (queryNode.getAttribute(attributeName) != null)
{
queryNode.removeAttribute(attributeName);
tinyMCE.activeEditor.execCommand('mceAddUndoLevel');
}
}
else
{
if (queryNode.getAttribute(attributeName) != value)
{
queryNode.setAttribute(attributeName, value);
tinyMCE.activeEditor.execCommand('mceAddUndoLevel');
}
}
},
/**
* Enable/disable controller when a query is selected.
* @param {Ametys.ribbon.element.ui.ButtonController} controller The controller
* @param {Ametys.cms.form.widget.RichText} field The current field. Can be null
* @param {HTMLElement} node The current selected node. Can be null.
*/
queryEditorButtonListener: function(controller, field, node)
{
var imgTag = (field != null && node != null) ? field.getEditor().dom.getParent(field.getEditor().selection.getNode(), 'img[datainclusion=query]') : null;
if (imgTag)
{
if (imgTag.getAttribute('queryid') != null)
{
// Get the selected query Id and parameter values.
var queryId = imgTag.getAttribute('queryid');
var paramValues = {};
for (var i = 0; i < imgTag.attributes.length; i++)
{
var attribute = imgTag.attributes[i].name;
if (attribute.substr(0, 6) == 'param-')
{
var name = attribute.substring(6, attribute.length);
var value = imgTag.getAttribute(attribute);
paramValues[name] = value;
}
}
// Load the query panel.
this._loadQueryPanel(queryId, paramValues);
}
}
this._currentNode = imgTag;
},
/**
* Loads the query panel.
* @param {String} queryId The id of the query to load.
* @param {Object} paramValues The values to set to the parameters of the query.
* @private
*/
_loadQueryPanel: function(queryId, paramValues)
{
if (queryId)
{
// Remove all the elements in the panel.
this._clearPanels();
// Get the data for this query.
if (!this._queryData[queryId])
{
this._getQueryData(queryId, paramValues);
}
else
{
this._loadQueryPanelAfterQueryDataIsLoaded(queryId, paramValues);
}
}
},
/**
* Loads the query panel, after we are sure queryData is defined.
* @param {String} queryId The id of the query to load.
* @param {Object} paramValues The values to set to the parameters of the query.
* @private
*/
_loadQueryPanelAfterQueryDataIsLoaded: function(queryId, paramValues)
{
var queryData = this._queryData[queryId]
if (Ext.Object.isEmpty(queryData))
{
this._queryParamsPanel.add({
xtype: 'component',
html: "<b>{{i18n PLUGINS_EXTERNAL_DATA_CONTENT_EDITION_DELETED_QUERY_TITLE}}</b><br/>{{i18n PLUGINS_EXTERNAL_DATA_CONTENT_EDITION_DELETED_QUERY_MSG}}",
cls: "datainclusion-message-left"
});
}
else
{
// Name and description.
this._queryDetailsPanel.add({
xtype: 'component',
html: "<b>{{i18n PLUGINS_EXTERNAL_DATA_UI_HELPER_QUERY_NAME}}</b> : " + queryData['name'],
cls: "datainclusion-message-left",
anchor: '100%'
});
this._queryDetailsPanel.add({
xtype: 'component',
html: "<b>{{i18n PLUGINS_EXTERNAL_DATA_UI_HELPER_QUERY_DESCRIPTION}}</b> : " + queryData['description'],
cls: "datainclusion-message-left",
anchor: '100%'
});
// Parameters.
var parameters = queryData['parameters'];
if (Ext.Object.isEmpty(parameters))
{
this._queryParamsPanel.add({
xtype: 'component',
html: "{{i18n PLUGINS_EXTERNAL_DATA_QUERY_NO_PARAMETER}}",
cls: "datainclusion-message"
});
}
var columnCt;
// Add an input field for each parameter.
var index = 0;
for (var paramName in parameters)
{
if (index % 3 == 0)
{
columnCt = Ext.create('Ext.Container', { margin: '0 5 0 0', flex: 1, items: []});
this._queryParamsPanel.add(columnCt);
}
var paramLabel = parameters[paramName];
var field = this._addInputField(paramName, paramLabel);
field = columnCt.add(field);
if (paramValues != null && paramValues[paramName] != null)
{
var value = paramValues[paramName];
field.setValue(value);
}
else
{
field.setValue('');
}
index++;
}
}
},
/**
* Clears the panel of the old input fields.
* @private
*/
_clearPanels: function()
{
var item;
while (item = this._queryDetailsPanel.items.first())
{
this._queryDetailsPanel.remove(item, true);
}
while (item = this._queryParamsPanel.items.first())
{
this._queryParamsPanel.remove(item, true);
}
},
/**
* Gets a query parameter.
* Loads the parameters of a given query.
* @param {String} queryId The id of the query.
* @param {Object} paramValues The values to set to the parameters of the query.
* @return {Object} An object containing the data of the query.
* @private
*/
_getQueryData: function(queryId, paramValues)
{
Ametys.cms.externaldata.QueryDAO.getQueryProperties(
[queryId, Ametys.getAppParameter('siteName')],
this._getQueryDataCb,
{scope: this, arguments: [queryId, paramValues]}
);
},
/**
* Callback function after retrieving the query properties.
* Then resumes the loading of the query panel, since the query params are loaded.
* @param {Object} response The response of the server
* @param {Array} args The passed arguments
* @private
*/
_getQueryDataCb: function(response, args)
{
var queryId = args[0];
var paramValues = args[1];
this._queryData[queryId] = response;
this._loadQueryPanelAfterQueryDataIsLoaded(queryId, paramValues);
},
/**
* Adds an input field to the parameter panel.
* @param {String} name The name of the field.
* @param {String} label The label of the field.
* @return {Ext.form.field.Text} The textfield that was added.
* @private
*/
_addInputField: function(name, label)
{
var elementConf =
{
inputType: 'text',
xtype: 'textfield',
hideLabel: false,
fieldLabel: label,
name: 'query-param-' + name,
enableKeyEvents : true,
width: this.width != null ? this.width : 'auto',
disabled: this.disabled == "true",
listeners: this._listeners
};
return elementConf;
}
},
createUI: function(size, colspan)
{
for (var key in this.getInitialConfig())
{
if (/^on(.*)$/.test(key))
{
this.self._listeners[RegExp.$1] = Ext.bind(eval(this.getInitialConfig()[key]), this.self);
}
}
var tooltipImg;
if (this.getInitialConfig()['icon-large'] != null)
{
tooltipImg = Ametys.CONTEXT_PATH + this.getInitialConfig()['icon-large']
}
else if (this.getInitialConfig()['icon-medium'] != null)
{
tooltipImg = Ametys.CONTEXT_PATH + this.getInitialConfig()['icon-medium']
}
else if (this.getInitialConfig()['icon-small'] != null)
{
tooltipImg = Ametys.CONTEXT_PATH + this.getInitialConfig()['icon-small']
}
this.self.width = this.getInitialConfig()['width'];
this.self.disabled = this.getInitialConfig()['disabled'];
this.self._queryDetailsPanel = Ext.create('Ext.Container', {
itemId: 'query-details',
width: 270,
layout: 'anchor',
border: false,
items: []
});
this.self._queryParamsPanel = Ext.create('Ext.Container', {
itemId: 'query-parameters',
flex: 1,
layout: {
type: 'hbox',
align: 'stretch',
pack: 'start'
},
border: false,
defaultType: 'textfield',
labelWidth: this.getInitialConfig()['label-width'] != null ? Number(this.getInitialConfig()['label-width']) : 60
});
var element = Ext.create('Ext.Container', {
layout: {
type: 'hbox',
align: 'stretch'
},
border: false,
items: [this.self._queryDetailsPanel, this.self._queryParamsPanel]
});
return element;
},
setAdditionalDescription: function(additionalDescription)
{
// Does not need additional description, because it does not have elements when hidden and disabled.
}
});