/**
* Project : AMDA-NG
* Name : SearchUI.js
* @class amdaUI.SearchUI
* @extends Ext.container.Container
* @brief Search Module UI definition (View)
* @author CDA
* @version $Id: SearchUI.js 2467 2014-07-10 16:06:26Z myriam $
*/
Ext.define('amdaUI.SearchUI',
{
extend: 'Ext.container.Container',
alias: 'widget.panelSearch',
requires: [
'amdaUI.CalculatorUI',
'amdaUI.TimeSelectorUI',
'extensions.SelectableTextArea',
'amdaUI.ParamArgumentsPlug',
'amdaModel.RequestParamObject'
],
constructor: function (config) {
this.init(config);
this.callParent(arguments);
// load object into view
this.loadObject();
var searchArgsPlug = this.getPlugin('search-param-components-plugin');
if (searchArgsPlug)
searchArgsPlug.onApply = this.onApplyParameterArgs;
},
addTT: function (newTTName, newTTid) {
this.timeSelector.addTT(newTTName, newTTid);
},
addTTs: function (TTarray) {
// set TTTab
this.timeSelector.setTTTab(TTarray);
},
addParam: function (newParamName, isLeaf, needArgs, components) {
if (needArgs || components)
this.editParameterArgs(newParamName, components);
else
this.addParamInEditor(newParamName);
},
addParamInEditor: function (param) {
var selection = this.constructionField.getSelection();
this.constructionField.setValue(selection.beforeText + param + selection.afterText);
this.constructionField.focus();
this.constructionField.setCaretPosition(this.constructionField.getValue().length);
},
onApplyParameterArgs: function (uiScope, paramRequestObject) {
var fullParam = paramRequestObject.getParamFullName();
uiScope.addParamInEditor(fullParam);
},
editParameterArgs: function (name, components) {
var paramObj = amdaModel.RequestParamObject.getEmptyObj();
paramObj.paramid = name;
if (components) {
if (components['index1']) {
paramObj['dim1-index'] = components['index1'];
++paramObj['type'];
}
if (components['index2']) {
paramObj['dim2-index'] = components['index2'];
++paramObj['type'];
}
}
var paramArgsPlug = this.getPlugin('search-param-components-plugin');
if (paramArgsPlug) {
var workinRequestParamObject = Ext.create('amdaModel.RequestParamObject', paramObj);
paramArgsPlug.show('search-param-components-plugin', workinRequestParamObject);
}
},
/**
* Set Start-Stop from parameter info (Local & MyData)
*/
setTimeFromData: function (obj) {
if (!obj.start || !obj.stop)
return;
var dateStart = new Date(obj.start.replace(/[T|Z]/g, ' ').replace(/\-/g, '\/'));
var dateStop = new Date(obj.stop.replace(/[T|Z]/g, ' ').replace(/\-/g, '\/'));
this.down('form').getForm().setValues({ startDate: dateStart, stopDate: dateStop });
},
setObject: function (obj) {
this.object = obj;
this.loadObject();
},
/**
* update this.object from form
*/
updateObject: function () {
// get the basic form
var basicForm = this.formPanel.getForm();
// get the timeSource selected
var timeSource = this.timeSelector.getActiveTimeSource();
var updateStatus = true;
var fieldsWithoutName = basicForm.getFields().items;
Ext.Array.each(fieldsWithoutName, function (item, index, allItems) {
if (item !== this.fieldName) {
if (!item.isValid()) {
if ((timeSource === amdaModel.AmdaTimeObject.inputTimeSrc[0]) &&
((item.name == 'startDate') || (item.name == 'stopDate') || (item.name == 'duration'))) {
updateStatus = true;
}
else {
// set update isn't allowed
updateStatus = false;
return false;
}
}
}
}, this);
if (timeSource === amdaModel.AmdaTimeObject.inputTimeSrc[0] // timeSource 'TimeTable'
&& this.timeSelector.TTGrid.getStore().count() == 0) {
Ext.Msg.show({
title: 'Warning', msg: 'You chose Time Selection `by TimeTable` but no timeTable was added!'
+ '
You must add one or choose Time Selection `by Interval`',
icon: Ext.MessageBox.WARNING, buttons: Ext.Msg.OK
});
updateStatus = false;
}
// if the update is allowed
if (updateStatus) {
/// real object update
// update TimeTable object with the content of form
basicForm.updateRecord(this.object);
this.object.set('timesrc', timeSource);
// set valid intervals into TimeTable object
if (timeSource === amdaModel.AmdaTimeObject.inputTimeSrc[0]) {
this.object.set('timeTables', this.timeSelector.TTGrid.getStore().data.items);
}
}
// return the update status
return updateStatus;
},
/**
* load this.object into form
*/
loadObject: function () {
// load object into form
this.formPanel.getForm().loadRecord(this.object);
// set object's TTs into the timeselector
this.addTTs(this.object.get('timeTables'));
},
/**
* save method called by Save button to launch the save process
*/
saveProcess: function (toRename) {
// if the TimeTable object has been modified
if (this.object.dirty) {
// Search module
var searchModule = myDesktopApp.getLoadedModule(myDesktopApp.dynamicModules.search.id);//('search-win');
// if the name has been modified this is a creation
if (this.object.isModified('name')) {
// if object already has an id : it's a 'rename' of an existing Condition
if (this.object.get('id')) {
// the context Node is the parent node of current edited one
var contextNode = searchModule.linkedNode.parentNode;
// link a new node to the TimeTableModule
searchModule.createLinkedNode();
// set the contextNode
searchModule.linkedNode.set('contextNode', contextNode);
// create a new object linked
searchModule.createObject(this.object.getJsonValues());
var searchObj = searchModule.linkedNode.get('object');
// synchronisation of objects
this.object = searchObj;
if (toRename) searchModule.linkedNode.toRename = true;
}
searchModule.linkedNode.create();
} else {
searchModule.linkedNode.set('contextNode', searchModule.contextNode);
// this.object.fireEvent('modify');
searchModule.linkedNode.update();
}
}
},
/**
* overwrite metod called by Save button
*/
overwriteProcess: function (btn) {
if (btn == 'cancel') return;
this.fieldName.clearInvalid();
this.saveProcess(true);
},
/**
* search method called by 'Do Search' button to launch the search process
*/
doSearch: function () {
var searchModule = myDesktopApp.getLoadedModule(myDesktopApp.dynamicModules.search.id);
searchModule.linkedNode.execute();
// fire execution
// this.object.fireEvent('execute',this.object.dirty);
},
/**
* Check if brackets are balanced
*/
isBalanced: function (str) {
str = ("" + str).replace(/[^()\[\]{}]/g, "");
var bracket = {
"]": "[",
"}": "{",
")": "("
},
openBrackets = [],
isClean = true,
i = 0,
len = str.length;
for (; isClean && i < len; i++) {
if (bracket[str[i]]) {
isClean = (openBrackets.pop() === bracket[str[i]]);
} else {
openBrackets.push(str[i]);
}
}
if (!(isClean && !openBrackets.length)) return 'Brackets are not balanced';
return true;
},
/**
* Update constructionField (Search Condition) in window search
*/
updateConstruct: function (oldval, newval) {
var expression = this.constructionField.value;
oldval = oldval.replace(/[(]/g, "\\(");
oldval = oldval.replace(/[)]/g, "\\)");
var reg = new RegExp(oldval, "g");
expression = expression.replace(reg, newval);
this.constructionField.setValue(expression);
},
/**
* Check if changes were made before closing window
* @return true if changes
*/
fclose: function () {
var form = this.formPanel.getForm();
var isDirty = form.isDirty();
return isDirty;
},
/**
* Component configiration / init
*/
init: function (config) {
this.timeSelector = new amdaUI.TimeSelectorUI({ id: 'SearchTimeSelector', flex: 2 });
this.fieldName = new Ext.form.field.Text({
labelAlign: 'top', itemId: 'formParamName',
fieldLabel: 'Request Name',
labelPad: 0,
name: 'name',
width: 165,
allowBlank: false,
stripCharsRe: /(^\s+|\s+$)/g,
validateOnChange: false,
validateOnBlur: false,
validFlag: false,
validator: function () {
return this.validFlag;
}
});
this.constructionField = new extensions.SelectableTextArea(
{
labelAlign: 'top',
labelPad: 0,
itemId: 'formSearchCondition',
fieldLabel: ' Data Mining Condition',
allowBlank: false, blankText: 'Condition expression is required',
name: 'expression',
validateOnChange: false,
validateOnBlur: false,
validator: this.isBalanced,
flex: 2,
listeners:
{
render: function (o, op) {
var me = this;
var el = me.bodyEl;
var dropTarget = Ext.create('Ext.dd.DropTarget', el,
{
ddGroup: 'explorerTree',
notifyEnter: function (ddSource, e, data) { },
notifyOver: function (ddSource, e, data) {
if (data.records[0].get('nodeType') == 'localParam' && data.records[0].get('notyet')) {
this.valid = false;
return this.dropNotAllowed;
}
if (((data.records[0].get('nodeType') == 'localParam') ||
(data.records[0].get('nodeType') == 'remoteParam') ||
(data.records[0].get('nodeType') == 'remoteSimuParam') ||
(data.records[0].get('nodeType') == 'derivedParam') ||
(data.records[0].get('nodeType') == 'specialParam') ||
(data.records[0].get('nodeType') == 'myDataParam') ||
(data.records[0].get('nodeType') == 'alias')) &&
(data.records[0].isLeaf() || data.records[0].get('isParameter')) &&
!data.records[0].data.disable) {
this.valid = true;
return this.dropAllowed;
}
this.valid = false;
return this.dropNotAllowed;
},
notifyDrop: function (ddSource, e, data) {
if (!this.valid) return false;
var nameToSent;
var components = null;
switch (data.records[0].get('nodeType')) {
case 'localParam':
case 'remoteParam':
case 'remoteSimuParam':
nameToSent = data.records[0].get('id');
if (data.records[0].get('alias') != "")
nameToSent = "#" + data.records[0].get('alias');
var component_info = data.records[0].get('component_info');
if (component_info && component_info.parentId) {
if (component_info.index1 && component_info.index2) {
nameToSent = component_info.parentId;
components = [];
if (component_info.index1)
components['index1'] = component_info.index1;
if (component_info.index2)
components['index2'] = component_info.index2;
}
if (data.records[0].get('needsArgs')) {
nameToSent = component_info.parentId;
if (component_info.index1) {
components = [];
components['index1'] = component_info.index1;
}
}
}
break;
case 'alias':
nameToSent = "#" + data.records[0].get('text');
break;
case 'derivedParam':
nameToSent = "ws_" + data.records[0].get('text');
break;
case 'specialParam':
nameToSent = data.records[0].get('id');
break;
case 'myDataParam':
var name = data.records[0].get('text');
nameToSent = "wsd_" + name;
var size = data.records[0].get('size');
if (size && size > 1) {
nameToSent += "(0)";
myDesktopApp.warningMsg("parameter " + name + " is array of size: " + size + "
Please put index");
}
break;
default:
return false;
}
var searchModule = myDesktopApp.getLoadedModule(myDesktopApp.dynamicModules.search.id);
if (searchModule) {
if (data.records[0].get('predefinedArgs')) {
searchModule.parseTemplatedParam(nameToSent, function (param_info) {
searchModule.addParam(param_info.paramid, data.records[0].get('leaf'), true, components, param_info.template_args);
});
}
else {
searchModule.addParam(nameToSent, data.records[0].get('leaf'), data.records[0].get('needsArgs'), components);
}
}
return true;
}
});
}
}
});
var samplingmode_store = new Ext.data.ArrayStore({
fields: ['id', 'name'],
data: [
['timestep', 'Time Step'],
['refparam', 'Ref. Parameter']
]
});
this.timeStepField = new Ext.form.NumberField({
fieldLabel: ' Time Step (sec)',
labelAlign: 'top',
labelPad: 0,
blankText: 'Time Step is required',
name: 'sampling',
minValue: 0.001,
decimalPrecision: 10,
hideTrigger: true,
width: 165,
validateOnBlur: false,
allowBlank: false,
isValid: function () {
var me = this,
disabled = me.disabled,
validate = me.forceValidation || !disabled;
if (!me.isVisible()) {
return true;
}
return validate ? me.validateValue(me.processRawValue(me.getRawValue())) : disabled;
}
});
this.refParamField = new Ext.form.TextField({
fieldLabel: ' Reference Param.',
labelAlign: 'top',
labelPad: 0,
name: 'reference_param',
width: 165,
hidden: true,
allowBlank: false,
listeners: {
afterrender: function (field, eOpts) {
var paramTarget = new Ext.dd.DropTarget(field.el.dom,
{
ddGroup: 'explorerTree',
notifyEnter: function (ddSource, e, data) {
},
notifyDrop: function (ddSource, e, data) {
var selectedRecord = ddSource.dragData.records[0];
switch (selectedRecord.$className) {
case 'amdaModel.LocalParamNode':
case 'amdaModel.RemoteParamNode':
case 'amdaModel.RemoteSimuParamNode':
if (!selectedRecord.get('isParameter') || selectedRecord.get('disable'))
return false;
if (selectedRecord.get('alias') != "")
field.setValue("#" + selectedRecord.get('alias'));
else
field.setValue(selectedRecord.get('id'));
return true;
case 'amdaModel.AliasNode':
if (!selectedRecord.isLeaf())
return false;
field.setValue("#" + selectedRecord.get('text'));
return true;
case 'amdaModel.DerivedParamNode':
if (!selectedRecord.isLeaf())
return false;
field.setValue("ws_" + selectedRecord.get('text'));
return true;
case 'amdaModel.MyDataParamNode':
if (!selectedRecord.isLeaf())
return false;
field.setValue("wsd_" + selectedRecord.get('text'));
return true;
default:
return false;
}
return true;
}
}
);
},
scope: this
},
isValid: function () {
var me = this,
disabled = me.disabled,
validate = me.forceValidation || !disabled;
if (!me.isVisible()) {
return true;
}
return validate ? me.validateValue(me.processRawValue(me.getRawValue())) : disabled;
}
});
this.samplingDefContainer = new Ext.container.Container({
border: false,
items: [
this.timeStepField,
this.refParamField
],
width: 165
});
this.formPanel = new Ext.form.Panel(
{
region: 'center',
bodyStyle: { background: '#dfe8f6' },
border: false, buttonAlign: 'left',
trackResetOnLoad: true, //reset to the last loaded record
layout: {
type: 'vbox',
align: 'stretch',
defaultMargins: { top: 5, left: 5, bottom: 10, right: 10 }
},
id: 'formSearch',
defaults: {
border: false
},
items: [
{
xtype: 'container',
flex: 2.5,
layout: {
type: 'hbox',
align: 'stretch'
},
items: [
{
flex: 3,
xtype: 'container',
border: false,
layout: {
type: 'table',
columns: 3
},
defaultType: 'textfield',
defaults: {
labelAlign: 'top',
labelPad: 0
},
items: [
this.fieldName,
{ xtype: 'component', width: 45 },
{
fieldLabel: 'Last modification',
xtype: 'displayfield',
name: 'last_update',
width: 165,
renderer: function (value, field) {
var tpl = new Ext.XTemplate('
{date}>');
var mod_date = 'Not saved';
if (value > 0)
mod_date = Ext.Date.format(new Date(value * 1000), "Y-m-d\\TH:i:s");
return tpl.apply({ date: mod_date });
},
},
{
xtype: 'combo',
fieldLabel: 'Sampling mode',
name: 'sampling_mode',
queryMode: 'local',
editable: false,
valueField: 'id',
displayField: 'name',
store: samplingmode_store,
value: samplingmode_store.first(),
width: 165,
listeners: {
change: function (field, value) {
this.timeStepField.setVisible(value != 'refparam');
this.refParamField.setVisible(value == 'refparam');
},
scope: this
}
},
{
xtype: 'component', width: 45
},
this.samplingDefContainer,
{
xtype: 'displayfield', width: 165,
hideLabel: true,
fieldStyle: 'display:inline-block;text-align:right',
value: 'Data Gap '
},
{
xtype: 'component', width: 45
},
{
xtype: 'numberfield', name: 'gap',
fieldLabel: 'if no data for interval', minValue: 1,
labelAlign: 'top', hideTrigger: true, width: 165
},
{
xtype: 'textarea',
name: 'description',
fieldLabel: 'Description',
width: 375, height: 70,
colspan: 3
}
]
},
this.timeSelector
]
},
this.constructionField
],
fbar: [
{
text: 'Do Search',
scope: this,
handler: function (button) {
// update object with user's values
// if the return is true (object had been updated)
if (this.updateObject()) {
// launch the search process
this.doSearch();
}
}
},
{
text: 'Save Request',
scope: this,
handler: function () {
// update object with user's values
// if the return is true (object had been updated)
if (this.updateObject()) {
var searchModule = myDesktopApp.getLoadedModule(myDesktopApp.dynamicModules.search.id);
if (!searchModule)
return;
var me = this;
searchModule.linkedNode.isValidName(this.fieldName.getValue(), function (res) {
if (!res) {
me.fieldName.validFlag = 'Error during object validation';
myDesktopApp.errorMsg(me.fieldName.validFlag);
me.fieldName.validate();
return;
}
if (!res.valid) {
if (res.error) {
if (res.error.search('subtree') != -1) {
Ext.MessageBox.show({
title: 'Warning',
msg: res.error + '
Do you want to overwrite it?',
width: 300,
buttons: Ext.MessageBox.OKCANCEL,
fn: me.overwriteProcess,
icon: Ext.MessageBox.WARNING,
scope: me
});
me.fieldName.validFlag = true;
}
else
me.fieldName.validFlag = res.error;
}
else {
me.fieldName.validFlag = 'Invalid object name';
myDesktopApp.errorMsg(me.fieldName.validFlag);
}
me.fieldName.validate();
return;
}
me.fieldName.validFlag = true;
me.fieldName.validate();
me.saveProcess(false);
});
}
}
},
{
text: 'Reset',
scope: this,
handler: function () {
var searchModule = myDesktopApp.getLoadedModule(myDesktopApp.dynamicModules.search.id);
searchModule.createLinkedNode();
searchModule.createObject();
this.setObject(searchModule.getLinkedNode().get('object'));
}
}
]
});
var myConf = {
layout: 'border',
defaults: { layout: 'fit', border: false },
items:
[
this.formPanel,
{
xtype: 'panel', region: 'south',
title: 'Information',
collapsible: true,
collapseMode: 'header',
height: 100,
autoHide: false,
iconCls: 'icon-information',
bodyStyle: 'padding:5px',
loader:
{
autoLoad: true,
url: helpDir + 'dataMiningHOWTO'
}
}
],
plugins: [
{ ptype: 'calculator', myBtns: [], context: 'Condition' },
{ ptype: 'paramArgumentsPlugin', pluginId: 'search-param-components-plugin' }
],
listeners: {
click: {
element: 'el',
fn: function (e, t) {
var me = t,
text = me.getAttribute('amda_clicktip');
if (text) {
e.preventDefault();
AmdaAction.getInfo({ name: text }, function (res, e) {
if (res.success) myDesktopApp.infoMsg(res.result);
});
}
}
}
}
};
Ext.apply(this, Ext.apply(arguments, myConf));
}
});