/*
* 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.
*/
/**
* Helper to add or edit a SQL data source
* @private
*/
Ext.define('Ametys.plugins.admin.datasource.EditSQLDataSourceHelper', {
singleton: true,
/**
* @private
* @property {Boolean} _initialized True if the dialog box creation process is finished
*/
/**
* @private
* @property {String} _mode The current edition mode ('new' or 'edit')
*/
/**
* @private
* @property {Ametys.window.DialogBox} _box The dialog box
*/
/**
* @private
* @property {Ametys.form.ConfigurableFormPanel} _form The form panel
*/
/**
* @private
* @property {Object} _dbtypeTemplates the mapping of dbtype value with their associated template
*/
/**
* @private
* @property {Object} _databaseTypes All supported database types
*/
/**
* @private
* @property {String[]} _allowedDbTypes The allowed database types. Can be null to allowed all supported database types.
*/
/**
* @private
* @property {Function} _callback the callback function
*/
/**
* Open dialog box to create a new SQL data source
* @param {String[]} allowedDbTypes The allowed database type. Can be null to allowed all database types.
* @param {Function} [callback] a callback function to invoke after the data source was created.
*/
add: function (allowedDbTypes, callback)
{
this._allowedDbTypes = allowedDbTypes;
this._callback = callback;
this._mode = 'new';
this._open ();
},
/**
* Open dialog box to edit a SQL data source
* @param {String} id the id of the selected data source
* @param {Function} [callback] a callback function to invoke after the data source was edited.
*/
edit: function (id, callback)
{
this._allowedDbTypes = null;
this._callback = callback;
this._mode = 'edit';
this._open (id);
},
/**
* @private
* Show dialog box for SQL data source edition
* @param {String} id the id of the selected data source in 'edit' mode, null in 'new' mode
*/
_open: function (id)
{
var me = this;
function configureCallback (success)
{
if (success)
{
me._filterDBTypes();
me._initForm (id);
me._box.show();
}
}
// Create dialog box if needed
this._createDialogBox(configureCallback);
},
/**
* @private
* Filter the database list
*/
_filterDBTypes: function ()
{
var me = this;
var filteredDBTypes = [];
Ext.Array.each (this._databaseTypes, function (dbtype) {
if (me._allowedDbTypes == null || Ext.Array.contains (me._allowedDbTypes, dbtype.value))
{
filteredDBTypes.push([dbtype.value, dbtype.label]);
}
});
this._form.getForm().findField ('dbtype').getStore().removeAll();
this._form.getForm().findField ('dbtype').getStore().setData(filteredDBTypes);
},
/**
* @private
* Create the dialog box if it is not already the case
* @param {Function} callback function invoked when the dialog box's drawing is finished
*/
_createDialogBox: function (callback)
{
if (!this._initialized)
{
this._form = Ext.create('Ametys.form.ConfigurableFormPanel', {
testURL: Ametys.getPluginDirectPrefix('admin') + '/datasource/test'
});
this._box = Ext.create('Ametys.window.DialogBox', {
title: this._mode == 'new' ? "{{i18n PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_ADD_TITLE}}" : "{{i18n PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_EDIT_TITLE}}",
iconCls: "ametysicon-data110 " + (this._mode == 'new' ? "decorator-ametysicon-add64" : "decorator-ametysicon-edit45"),
layout: 'fit',
width: 700,
items: [this._form],
closeAction: 'hide',
defaultFocus: this._form,
referenceHolder: true,
defaultButton: 'okButton',
buttons : [{
reference: 'okButton',
text: "{{i18n PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_OK}}",
handler: Ext.bind(this._ok, this)
}, {
text: "{{i18n PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_CANCEL}}",
handler: Ext.bind(function() {this._box.hide();}, this)
}]
});
this._configureForm(callback);
}
else
{
this._box.setTitle(this._mode == 'new' ? "{{i18n PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_ADD_TITLE}}" : "{{i18n PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_EDIT_TITLE}}");
this._box.setIconCls("ametysicon-data110 " + (this._mode == 'new' ? "decorator-ametysicon-add64" : "decorator-ametysicon-edit45"));
callback(true);
}
},
/**
* @private
* Configure the {@link Ametys.form.ConfigurableFormPanel}
* @param {Function} callback function invoked when the form configuration is finished
*/
_configureForm: function(callback)
{
// Retrieve the handled database types
Ametys.data.ServerComm.callMethod({
role: "org.ametys.core.datasource.dbtype.SQLDatabaseTypeManager",
methodName: "getSQLDatabaseTypes",
parameters: [],
callback: {
handler: this._getSQLDatabaseTypesCb,
arguments: {
callback: callback
},
scope: this
},
errorMessage: {
category: this.self.getName(),
msg: "{{i18n PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_GET_DBTYPE_ERROR}}"
}
});
},
/**
* @private
* Callback for the form configuration process. Configures the {@link Ametys.form.ConfigurableFormPanel} of the dialog box
* @param {Object} response the server's response
* @param {Array} response.databaseTypes the array of database types
* @param {String} response.databaseTypes.label the label of the current database type
* @param {String} response.databaseTypes.value the value of the current database type
* @param {String} response.databaseTypes.template the template associated to the current database type
* @param {Object} args the callback arguments
* @param {Function} args.callback the callback function
*/
_getSQLDatabaseTypesCb: function(response, args)
{
var me = this;
var databaseTypes = response.databaseTypes;
this._databaseTypes = []; // The list of label-value pairs that will be displayed in the form
var templateMapping = {}; // The mapping of dbtype value and associated template
Ext.Array.each(databaseTypes, function(databaseType){
me._databaseTypes.push({label: databaseType.label, value: databaseType.value});
templateMapping[databaseType.value] = databaseType.template;
});
this._dbtypeTemplates = templateMapping;
var configuration = this._getFormConfiguration ();
this._form.configure(configuration);
args.callback(true);
},
/**
* @private
* Get the form configuration
* @param {Object[]} dbtypesEnumeration the dbtypes' enumeration
* @return {Object} the form configuration
*/
_getFormConfiguration: function ()
{
return {
// Data source id (for edition only)
'id': {
hidden: true,
type: 'string'
},
// Name
'name': {
type: 'string',
label: "{{i18n PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_FIELD_NAME}}",
description: "{{i18n PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_FIELD_NAME_DESCRIPTION}}",
validation: {
mandatory: true
}
},
// Description
'description': {
type: 'string',
widget: 'edition.textarea',
'widget-params': {
charCounter: false
},
label: "{{i18n PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_FIELD_DESCRIPTION}}",
description: "{{i18n PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_FIELD_DESCRIPTION_DESCRIPTION}}"
},
// Database type
'dbtype': {
type: 'string',
enumeration: this._databaseTypes,
label: "{{i18n PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_FIELD_DBTYPE}}",
description: "{{i18n PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_FIELD_DBTYPE_DESCRIPTION}}",
validation: {
mandatory: true
}
},
// Server url
'url': {
type: 'string',
label: "{{i18n PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_FIELD_URL}}",
description: "{{i18n PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_FIELD_URL_DESCRIPTION}}",
validation: {
mandatory: true
}
},
// Username
'user': {
type: 'string',
label: "{{i18n PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_FIELD_USER}}",
description: "{{i18n PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_FIELD_USER_DESCRIPTION}}"
},
// Password
'password': {
type: 'password',
widget: 'edition.password',
label: "{{i18n PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_FIELD_PASSWORD}}",
description: "{{i18n PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_FIELD_PASSWORD_DESCRIPTION}}"
},
// Is private ?
'private': {
type: 'boolean',
widget: 'edition.checkbox',
label: "{{i18n PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_FIELD_PRIVATE}}",
description: "{{i18n PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_FIELD_PRIVATE_DESCRIPTION}}",
},
// Global parameter checker
'field-checker': {
id: 'sql-connection-checker-datasource',
'icon-glyph': 'ametysicon-data110',
'linked-fields': ['id', 'dbtype', 'url', 'user', 'password'],
label: "{{i18n plugin.core-impl:PLUGINS_CORE_SQL_CONNECTION_CHECKER_LABEL}}",
description: "{{i18n plugin.core-impl:PLUGINS_CORE_SQL_CONNECTION_CHECKER_DESC}}"
}
}
},
/**
* @private
* Initialize the fields of the form
* @param {String} id the id of the data source if in 'edit' mode, null in 'new' mode
*/
_initForm: function (id)
{
var form = this._form.getForm();
if (!this._initialized)
{
form.findField('dbtype').on('change', Ext.bind(this._onDbtypeChange, this));
}
else
{
// Reset the parameter checker status to 'not tested' and reset the warnings
this._form.reset();
}
if (id == null)
{
// FIXME chrome automatically sets the user and password fields... see CMS-6913
this._form.setValues({});
form.reset();
}
else
{
var me = this;
Ametys.plugins.core.datasource.DataSourceDAO.getDataSource(["SQL", id], function (datasource) {
me._form.setValues({values: datasource});
});
}
this._initialized = true;
},
/**
* @private
* Handler when the "Ok" button is pressed
* Check if the data source is valid
*/
_ok: function()
{
if (!this._form.isValid())
{
return;
}
var fieldCheckersManager = this._form._fieldCheckersManager;
var sqlConnectionChecker = fieldCheckersManager._fieldCheckers[0];
if (sqlConnectionChecker.getStatus() == Ametys.form.ConfigurableFormPanel.FieldChecker.STATUS_SUCCESS)
{
this._okCb();
}
else if (sqlConnectionChecker.getStatus() == Ametys.form.ConfigurableFormPanel.FieldChecker.STATUS_FAILURE)
{
this._displayInvalidDataSourceDialog();
}
else
{
// Test the data source
Ext.getBody().mask("{{i18n plugin.core-ui:PLUGINS_CORE_UI_LOADMASK_DEFAULT_MESSAGE}}");
fieldCheckersManager.check(null,
true,
Ext.bind(function(success)
{
Ext.getBody().unmask();
if (success)
{
this._okCb();
}
else
{
this._displayInvalidDataSourceDialog();
}
}, this), false);
}
},
/**
* Display the warning dialog for the saving of invalid data sources
*/
_displayInvalidDataSourceDialog: function()
{
Ametys.Msg.show({
title: "{{i18n PLUGINS_ADMIN_UITOOL_DATASOURCE_INVALID_CREATION_TITLE}}",
message: "{{i18n PLUGINS_ADMIN_UITOOL_DATASOURCE_INVALID_CREATION_MSG}}",
icon: Ext.Msg.WARNING,
buttons: Ext.Msg.YESNO,
scope: this,
fn : function(btn) {
if (btn == 'yes') {
this._okCb();
}
}
});
},
/**
* @private
* Submit the form's values
*/
_okCb: function()
{
var values = this._form.getValues();
values['private'] = this._form.getForm().findField('private').getValue();
if (this._mode == 'new')
{
Ametys.plugins.core.datasource.DataSourceDAO.addDataSource(["SQL", values],
this._addOrEditDataSourceCb,
{scope: this, waitMessage: {target: this._box}}
);
}
else
{
Ametys.plugins.core.datasource.DataSourceDAO.editDataSource(["SQL", values], this._addOrEditDataSourceCb, {scope: this, waitMessage: {target: this._box}});
}
},
/**
* Callback function after adding or editing SQL data source
* @param {Object} datasource the datasource object
*/
_addOrEditDataSourceCb: function (datasource)
{
this._box.hide();
if (Ext.isFunction(this._callback))
{
this._callback(datasource);
}
},
/**
* @private
* Function invoked when the value of the dbtype field changes
* @param {Ametys.form.widget.ComboBox} combo the combobox
* @param {String} newValue the new value of the field
* @param {String} oldValue the previous value of the field
*/
_onDbtypeChange: function(combo, newValue, oldValue)
{
if (oldValue != newValue)
{
var form = this._form.getForm();
form.findField('url').setValue(this._dbtypeTemplates[newValue]);
}
}
});