mirror of
https://github.com/Combodo/iTop.git
synced 2026-04-25 11:38:44 +02:00
Advanced search: WIP POC, integration with endpoint.
SVN:b1162[5400]
This commit is contained in:
@@ -53,6 +53,7 @@ class NiceWebPage extends WebPage
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/search/search_form_handler.js');
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/search/search_form_criteria.js');
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/search/search_form_criteria_raw.js');
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/search/search_form_criteria_string.js');
|
||||
$this->add_ready_script(
|
||||
<<< EOF
|
||||
//add new widget called TruncatedList to properly display truncated lists when they are sorted
|
||||
|
||||
@@ -9,17 +9,20 @@ $(function()
|
||||
// default options
|
||||
options:
|
||||
{
|
||||
get_current_values_callback: 'getCurrentValues',
|
||||
set_current_values_callback: function(me, oEvent, oData){ console.log('Search form criteria: set_current_values_callback must be overloaded, this is the default callback.'); },
|
||||
|
||||
ref: '',
|
||||
operator: '=',
|
||||
values: [],
|
||||
oql: '',
|
||||
is_removable: true,
|
||||
|
||||
field: {
|
||||
label: '',
|
||||
},
|
||||
is_modified: false, // TODO: change this on value change and remove oql property value
|
||||
},
|
||||
|
||||
handler: null,
|
||||
|
||||
// the constructor
|
||||
_create: function()
|
||||
{
|
||||
@@ -27,6 +30,9 @@ $(function()
|
||||
|
||||
this.element.addClass('search_form_criteria');
|
||||
|
||||
// Link search form handler
|
||||
this.handler = this.element.closest('.search_form_handler');
|
||||
|
||||
// GetData
|
||||
this.element.bind('itop.search.criteria.get_data', function(oEvent, oData){
|
||||
return me._onGetData(oData);
|
||||
@@ -78,25 +84,25 @@ $(function()
|
||||
},
|
||||
|
||||
|
||||
// Public methods
|
||||
getCurrentValues: function()
|
||||
// Protected methods
|
||||
_remove: function()
|
||||
{
|
||||
var aValues = this.options.values;
|
||||
return aValues;
|
||||
this.element.remove();
|
||||
this.handler.triggerHandler('itop.search.criteria.removed');
|
||||
},
|
||||
|
||||
|
||||
// Event callbacks
|
||||
_onGetData: function(oData)
|
||||
{
|
||||
var oData = {
|
||||
var oCriteriaData = {
|
||||
'ref': this.options.ref,
|
||||
'operator': this.options.operator,
|
||||
'values': this.options.values,
|
||||
'is_removable': this.options.is_removable,
|
||||
'oql': this.options.oql,
|
||||
};
|
||||
return oData;
|
||||
return oCriteriaData;
|
||||
},
|
||||
|
||||
|
||||
@@ -104,6 +110,8 @@ $(function()
|
||||
// - Prepare element DOM structure
|
||||
_prepareElement: function()
|
||||
{
|
||||
var me = this;
|
||||
|
||||
// Prepare base DOM structure
|
||||
//this.options.ref+' '+this.options.operator+' '+this.options.values
|
||||
this.element
|
||||
@@ -111,10 +119,19 @@ $(function()
|
||||
.append('<div class="sfc_form_group"></div>')
|
||||
.append('<div class="sfc_toggle"><a class="fa fa-caret-down" href="#"></a></div>');
|
||||
|
||||
// Bind events
|
||||
// - Toggler
|
||||
this.element.find('.sfc_toggle, .sfc_title').on('click', function(){
|
||||
me.element.find('.sfc_form_group').toggle();
|
||||
});
|
||||
|
||||
// Removable / locked decoration
|
||||
if(this.options.is_removable === true)
|
||||
{
|
||||
this.element.append('<div class="sfc_close"><a class="fa fa-times" href="#"></a></div>');
|
||||
this.element.find('.sfc_close').on('click', function(){
|
||||
me._remove();
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -134,6 +151,32 @@ $(function()
|
||||
},
|
||||
|
||||
|
||||
// Values helpers
|
||||
_getValuesAsText: function()
|
||||
{
|
||||
var aValues = [];
|
||||
for(var iValueIdx in this.options.values)
|
||||
{
|
||||
aValues.push(this.options.values[iValueIdx].value);
|
||||
}
|
||||
|
||||
return aValues.join(', ');
|
||||
},
|
||||
_makeOQLExpression: function()
|
||||
{
|
||||
var aValues = [];
|
||||
var sOQL = '';
|
||||
|
||||
for(var iValueIdx in this.options.values)
|
||||
{
|
||||
aValues.push( '\'' + this.options.values[iValueIdx].value + '\'' );
|
||||
}
|
||||
sOQL += '(`' + this.options.ref + '`) ' + this.options.operator + ' ' + aValues.join(', ') + ')';
|
||||
|
||||
return sOQL;
|
||||
},
|
||||
|
||||
|
||||
// Debug helpers
|
||||
// - Show a trace in the javascript console
|
||||
_trace: function(sMessage, oData)
|
||||
|
||||
@@ -43,12 +43,27 @@ $(function()
|
||||
this._super( key, value );
|
||||
},
|
||||
|
||||
// DOM element helpers
|
||||
_prepareElement: function()
|
||||
{
|
||||
this._super();
|
||||
|
||||
// Remove toggler as it's a non sense here
|
||||
this.element.find('.sfc_toggle').remove();
|
||||
},
|
||||
_setTitle: function(sTitle)
|
||||
{
|
||||
if(sTitle === undefined)
|
||||
{
|
||||
if(this.options.oql !== '')
|
||||
{
|
||||
sTitle = this.options.oql;
|
||||
}
|
||||
else
|
||||
{
|
||||
sTitle = this._makeOQLExpression();
|
||||
}
|
||||
}
|
||||
this._super(sTitle);
|
||||
},
|
||||
});
|
||||
|
||||
77
js/search/search_form_criteria_string.js
Normal file
77
js/search/search_form_criteria_string.js
Normal file
@@ -0,0 +1,77 @@
|
||||
//iTop Search form criteria string
|
||||
;
|
||||
$(function()
|
||||
{
|
||||
// the widget definition, where 'itop' is the namespace,
|
||||
// 'search_form_criteria_string' the widget name
|
||||
$.widget( 'itop.search_form_criteria_string', $.itop.search_form_criteria,
|
||||
{
|
||||
// default options
|
||||
options:
|
||||
{
|
||||
},
|
||||
|
||||
// the constructor
|
||||
_create: function()
|
||||
{
|
||||
var me = this;
|
||||
|
||||
this._super();
|
||||
this.element.addClass('search_form_criteria_string');
|
||||
},
|
||||
// called when created, and later when changing options
|
||||
_refresh: function()
|
||||
{
|
||||
|
||||
},
|
||||
// events bound via _bind are removed automatically
|
||||
// revert other modifications here
|
||||
_destroy: function()
|
||||
{
|
||||
this.element.removeClass('search_form_criteria_string');
|
||||
this._super();
|
||||
},
|
||||
// _setOptions is called with a hash of all options that are changing
|
||||
// always refresh when changing options
|
||||
_setOptions: function()
|
||||
{
|
||||
this._superApply(arguments);
|
||||
},
|
||||
// _setOption is called for each individual option that is changing
|
||||
_setOption: function( key, value )
|
||||
{
|
||||
this._super( key, value );
|
||||
},
|
||||
|
||||
// DOM element helpers
|
||||
_prepareElement: function()
|
||||
{
|
||||
var me = this;
|
||||
|
||||
this._super();
|
||||
|
||||
// TODO: Refactor this after UI mockups
|
||||
var oInputElem = $('<input type="text" />');
|
||||
oInputElem.on('change', function(){
|
||||
var sValue = $(this).val();
|
||||
|
||||
me.options.values = [{
|
||||
value: sValue,
|
||||
label: sValue,
|
||||
}];
|
||||
me._setTitle();
|
||||
|
||||
me.handler.triggerHandler('itop.search.criteria.value_changed');
|
||||
})
|
||||
.appendTo(this.element.find('.sfc_form_group'));
|
||||
},
|
||||
_setTitle: function(sTitle)
|
||||
{
|
||||
if(sTitle === undefined)
|
||||
{
|
||||
sTitle = this.options.field.label + ': ' + this._getValuesAsText();
|
||||
}
|
||||
this._super(sTitle);
|
||||
},
|
||||
});
|
||||
});
|
||||
@@ -51,7 +51,7 @@ $(function()
|
||||
// },
|
||||
],
|
||||
},
|
||||
'supported_criterion_types': ['raw'],
|
||||
'supported_criterion_types': ['raw', 'string'],
|
||||
'default_criteria_type': 'raw',
|
||||
},
|
||||
|
||||
@@ -60,6 +60,7 @@ $(function()
|
||||
{
|
||||
active_criterion: null,
|
||||
more_criterion: null,
|
||||
results_area: null,
|
||||
},
|
||||
|
||||
// the constructor
|
||||
@@ -113,16 +114,23 @@ $(function()
|
||||
{
|
||||
var me = this;
|
||||
|
||||
// Form events
|
||||
// - Prevent regular form submission (eg. hitting "Enter" in inputs)
|
||||
this.element.on('submit', function(oEvent){
|
||||
oEvent.preventDefault();
|
||||
});
|
||||
|
||||
// Criteria events
|
||||
this.element.bind('itop.search.criteria.value_changed', function(oEvent, oData){
|
||||
me._onCriteriaValueChanged(oData);
|
||||
});
|
||||
this.element.bind('itop.search.criteria.removed', function(oEvent, oData){
|
||||
me._onCriteriaRemoved(oData);
|
||||
});
|
||||
},
|
||||
// - Update search option of the widget
|
||||
_updateSearch: function()
|
||||
{
|
||||
var me = this;
|
||||
|
||||
// Criterion
|
||||
// - Note: As of today, only a "or" level with a "and" is supported, so the following part
|
||||
// will need some refactoring when introducing new stuff.
|
||||
@@ -170,10 +178,6 @@ $(function()
|
||||
// Prepare content
|
||||
this._prepareExistingCriterion();
|
||||
this._prepareMoreCriterionMenu();
|
||||
|
||||
// TODO: Delete this
|
||||
oCriterionAreaElem.append( $('<button type="button" value="submit" class="sf_submit_btn">Go!</button>') );
|
||||
this.options.submit_button_selector = '.sf_submit_btn';
|
||||
},
|
||||
// - Prepare existing criterion
|
||||
_prepareExistingCriterion: function()
|
||||
@@ -209,7 +213,7 @@ $(function()
|
||||
this.elements.more_criterion.find('> .sf_mc_list').append(oFieldElem);
|
||||
}
|
||||
|
||||
// Bind event
|
||||
// Bind events
|
||||
this.elements.more_criterion.find('.sf_mc_field').on('click', function(){
|
||||
// Prepare new criterion data
|
||||
var oData = {
|
||||
@@ -235,6 +239,8 @@ $(function()
|
||||
oResultAreaElem = $('<div></div>').appendTo(this.element);
|
||||
}
|
||||
oResultAreaElem.addClass('sf_results_area');
|
||||
|
||||
this.elements.results_area = oResultAreaElem;
|
||||
},
|
||||
|
||||
|
||||
@@ -242,15 +248,24 @@ $(function()
|
||||
// - Add a criteria to the form
|
||||
_addCriteria: function(oData)
|
||||
{
|
||||
var sRef = oData.ref
|
||||
var sRef = oData.ref;
|
||||
var sType = this._getCriteriaTypeFromFieldRef(sRef);
|
||||
|
||||
if(sType !== null)
|
||||
{
|
||||
var sWidgetClass = 'search_form_criteria' + '_' + sType;
|
||||
oCriteriaElem = $('<div></div>')
|
||||
|
||||
// Add some informations from the field
|
||||
oData.field = {
|
||||
label: this.options.search.fields[sRef].label,
|
||||
};
|
||||
|
||||
// Create DOM element
|
||||
var oCriteriaElem = $('<div></div>')
|
||||
.addClass('sf_criteria')
|
||||
.appendTo(this.elements.active_criterion);
|
||||
|
||||
// Instanciate widget
|
||||
$.itop[sWidgetClass](oData, oCriteriaElem);
|
||||
}
|
||||
else
|
||||
@@ -282,12 +297,16 @@ $(function()
|
||||
return sType;
|
||||
},
|
||||
// Criteria handlers
|
||||
// - Event value changed
|
||||
_onCriteriaValueChanged: function(oData)
|
||||
{
|
||||
this._updateSearch();
|
||||
this._submit();
|
||||
},
|
||||
_onCriteriaRemoved: function(oData)
|
||||
{
|
||||
this._updateSearch();
|
||||
this._submit();
|
||||
},
|
||||
|
||||
// Button handlers
|
||||
_onSubmitClick: function(oEvent)
|
||||
@@ -295,15 +314,12 @@ $(function()
|
||||
// Assertion: the search is already up to date
|
||||
this._submit();
|
||||
},
|
||||
_onCancelClick: function(oEvent)
|
||||
{
|
||||
// TODO
|
||||
},
|
||||
|
||||
|
||||
// Submit handlers
|
||||
_submit: function()
|
||||
{
|
||||
var me = this;
|
||||
var oData = {
|
||||
'params': JSON.stringify({
|
||||
'base_oql': this.options.search.base_oql,
|
||||
@@ -311,51 +327,47 @@ $(function()
|
||||
}),
|
||||
};
|
||||
|
||||
// Show loader
|
||||
this._showLoader();
|
||||
|
||||
// Do submit
|
||||
$.post(
|
||||
this.options.endpoint,
|
||||
oData,
|
||||
function(oResponse, sStatus, oXHR){
|
||||
console.log('POST success', oResponse, sStatus, oXHR);
|
||||
}
|
||||
oData
|
||||
)
|
||||
.done(function(a,b,c,d){ console.log('POST done', a,b,c,d);})
|
||||
.fail(function(a,b,c,d){ console.log('POST fail', a,b,c,d);})
|
||||
.always(function(a,b,c,d){ console.log('POST always', a,b,c,d);});
|
||||
.done(function(oResponse, sStatus, oXHR){ me._onSubmitSuccess(oResponse); })
|
||||
.fail(function(oResponse, sStatus, oXHR){ me._onSubmitFailure(oResponse); })
|
||||
.always(function(oResponse, sStatus, oXHR){ me._onSubmitAlways(oResponse); });
|
||||
},
|
||||
// - Called on form submit successes
|
||||
_onSubmitSuccess: function(oData, sFormPath)
|
||||
_onSubmitSuccess: function(oData)
|
||||
{
|
||||
// TODO
|
||||
// if(oData.form.updated_fields !== undefined)
|
||||
// {
|
||||
// this.element.find('[data-form-path="' + sFormPath + '"]').trigger('update_form', {updated_fields: oData.form.updated_fields});
|
||||
// }
|
||||
this.elements.results_area.html(oData);
|
||||
},
|
||||
// - Called on form submit failures
|
||||
_onSubmitFailure: function(oData, sFormPath)
|
||||
_onSubmitFailure: function(oData)
|
||||
{
|
||||
// TODO
|
||||
// TODO: onSubmitFailure callback
|
||||
},
|
||||
// - Called after form submits
|
||||
_onSubmitAlways: function(oData, sFormPath)
|
||||
_onSubmitAlways: function(oData)
|
||||
{
|
||||
// TODO
|
||||
// // Check all touched AFTER ajax is complete, otherwise the renderer will redraw the field in the mean time.
|
||||
// this.element.find('[data-form-path="' + sFormPath + '"]').trigger('validate');
|
||||
// this._enableFormAfterLoading();
|
||||
this._hideLoader();
|
||||
},
|
||||
|
||||
|
||||
// Global helpers
|
||||
// - Show loader
|
||||
_disableFormBeforeLoading: function()
|
||||
_showLoader: function()
|
||||
{
|
||||
// TODO
|
||||
// TODO: Show loader
|
||||
this._trace('Show loader');
|
||||
},
|
||||
// - Remove loader
|
||||
_enableFormAfterLoading: function()
|
||||
// - Hide loader
|
||||
_hideLoader: function()
|
||||
{
|
||||
// TODO
|
||||
// TODO: Hide loader
|
||||
this._trace('Hide loader');
|
||||
},
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user