Advanced search: WIP POC, integration with endpoint.

SVN:b1162[5400]
This commit is contained in:
Guillaume Lajarige
2018-03-09 11:10:03 +00:00
parent 37196b42ed
commit 0bf33ec7e9
5 changed files with 198 additions and 50 deletions

View File

@@ -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

View File

@@ -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)

View File

@@ -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);
},
});

View 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);
},
});
});

View File

@@ -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');
},