mirror of
https://github.com/Combodo/iTop.git
synced 2026-05-17 06:18:44 +02:00
Advanced search: WIP POC, UI/UX.
SVN:b1162[5430]
This commit is contained in:
@@ -63,6 +63,7 @@ class NiceWebPage extends WebPage
|
||||
$this->add_dict_entry('UI:Search:Criteria:Operator:String:EndsWith');
|
||||
$this->add_dict_entry('UI:Button:Apply');
|
||||
$this->add_dict_entry('UI:Button:Cancel');
|
||||
$this->add_dict_entry('UI:Button:Close');
|
||||
$this->add_dict_entry('UI:Button:More');
|
||||
$this->add_dict_entry('UI:Button:Less');
|
||||
$this->add_ready_script(
|
||||
|
||||
@@ -795,12 +795,20 @@ div.HRDrawer {
|
||||
display: inline-block;
|
||||
margin-right: 5px;
|
||||
margin-bottom: 5px;
|
||||
/* Non editable criteria */
|
||||
/* Draft criteria (modifications not applied) */
|
||||
/* Top left corner icons */
|
||||
/* Special criterion processing */
|
||||
}
|
||||
.search_form_handler .sf_criterion_area .search_form_criteria.locked {
|
||||
background-color: #f1f1f1;
|
||||
}
|
||||
.search_form_handler .sf_criterion_area .search_form_criteria.draft {
|
||||
border-style: dashed;
|
||||
}
|
||||
.search_form_handler .sf_criterion_area .search_form_criteria.draft .sfc_title {
|
||||
font-style: italic;
|
||||
}
|
||||
.search_form_handler .sf_criterion_area .search_form_criteria .sfc_close, .search_form_handler .sf_criterion_area .search_form_criteria .sfc_toggle {
|
||||
position: absolute;
|
||||
top: 7px;
|
||||
@@ -811,7 +819,7 @@ div.HRDrawer {
|
||||
}
|
||||
.search_form_handler .sf_criterion_area .search_form_criteria .sfc_toggle {
|
||||
display: inline-block;
|
||||
right: 20px;
|
||||
right: 23px;
|
||||
transition: all 0.4s ease-in-out;
|
||||
}
|
||||
.search_form_handler .sf_criterion_area .search_form_criteria .sfc_toggle.opened {
|
||||
@@ -905,6 +913,9 @@ div.HRDrawer {
|
||||
.search_form_handler .sf_criterion_area .search_form_criteria.search_form_criteria_raw .sfc_title {
|
||||
cursor: initial;
|
||||
}
|
||||
.search_form_handler .sf_criterion_area .search_form_criteria.search_form_criteria_raw .sfc_form_group {
|
||||
display: none;
|
||||
}
|
||||
.search_form_handler .sf_criterion_area .sf_more_criterion .sf_mc_list {
|
||||
position: absolute;
|
||||
max-height: 420px;
|
||||
|
||||
@@ -881,9 +881,18 @@ div.HRDrawer {
|
||||
margin-right: 5px;
|
||||
margin-bottom: 5px;
|
||||
|
||||
/* Non editable criteria */
|
||||
&.locked{
|
||||
background-color: $gray-extra-light;
|
||||
}
|
||||
/* Draft criteria (modifications not applied) */
|
||||
&.draft{
|
||||
border-style: dashed;
|
||||
|
||||
.sfc_title{
|
||||
font-style: italic;
|
||||
}
|
||||
}
|
||||
|
||||
/* Top left corner icons */
|
||||
.sfc_close,
|
||||
@@ -897,7 +906,7 @@ div.HRDrawer {
|
||||
}
|
||||
.sfc_toggle{
|
||||
display: inline-block;
|
||||
right: 20px;
|
||||
right: 23px;
|
||||
transition: all 0.4s ease-in-out;
|
||||
|
||||
&.opened{
|
||||
@@ -1022,6 +1031,9 @@ div.HRDrawer {
|
||||
.sfc_title{
|
||||
cursor: initial;
|
||||
}
|
||||
.sfc_form_group{
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -367,6 +367,7 @@ Dict::Add('EN US', 'English', 'English', array(
|
||||
'UI:Button:Ok' => 'Ok',
|
||||
'UI:Button:Save' => 'Save',
|
||||
'UI:Button:Cancel' => 'Cancel',
|
||||
'UI:Button:Close' => 'Close',
|
||||
'UI:Button:Apply' => 'Apply',
|
||||
'UI:Button:Back' => ' << Back ',
|
||||
'UI:Button:Restart' => ' |<< Restart ',
|
||||
|
||||
@@ -130,12 +130,12 @@ $(function()
|
||||
var me = this;
|
||||
|
||||
// Get criteria data
|
||||
this.element.bind('itop.search.criteria.get_data', function(oEvent, oData){
|
||||
this.element.on('itop.search.criteria.get_data', function(oEvent, oData){
|
||||
return me._onGetData(oData);
|
||||
});
|
||||
|
||||
// Get/SetCurrentValues callbacks handler
|
||||
this.element.bind('itop.search.criteria.get_current_values itop.search.criteria.set_current_values', function(oEvent, oData){
|
||||
this.element.on('itop.search.criteria.get_current_values itop.search.criteria.set_current_values', function(oEvent, oData){
|
||||
oEvent.stopPropagation();
|
||||
|
||||
var callback = me.options[oEvent.type+'_callback'];
|
||||
@@ -154,10 +154,47 @@ $(function()
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
// Close criteria
|
||||
this.element.on('itop.search.criteria.close', function(){
|
||||
return me._close();
|
||||
});
|
||||
},
|
||||
// - Cinematic
|
||||
// - Open / Close criteria
|
||||
_open: function()
|
||||
{
|
||||
this._resetOperators();
|
||||
this.element.find('.sfc_form_group, .sfc_toggle').addClass('opened');
|
||||
},
|
||||
_close: function()
|
||||
{
|
||||
this.element.find('.sfc_form_group, .sfc_toggle').removeClass('opened');
|
||||
this._unmarkAsDraft();
|
||||
},
|
||||
_closeAll: function()
|
||||
{
|
||||
this.element.closest('.search_form_handler').find('.search_form_criteria').each(function(){
|
||||
$(this).triggerHandler('itop.search.criteria.close');
|
||||
});
|
||||
},
|
||||
_remove: function()
|
||||
{
|
||||
this.element.remove();
|
||||
this.handler.triggerHandler('itop.search.criteria.removed');
|
||||
},
|
||||
// - Mark / Unmark criteria as draft (new value not applied)
|
||||
_markAsDraft: function()
|
||||
{
|
||||
this.element.addClass('draft');
|
||||
},
|
||||
_unmarkAsDraft: function()
|
||||
{
|
||||
this.element.removeClass('draft');
|
||||
},
|
||||
// - Apply / Cancel new value
|
||||
_apply: function()
|
||||
{
|
||||
this._trace('TODO: Apply button (call selected operator callback)');
|
||||
// Find active operator
|
||||
var oActiveOpElem = this.element.find('.sfc_op_radio:checked').closest('.sfc_fg_operator');
|
||||
if(oActiveOpElem.length === 0)
|
||||
@@ -179,14 +216,14 @@ $(function()
|
||||
this.options.operator = oActiveOpElem.find('.sfc_op_radio').val();
|
||||
this.options.values = aValues;
|
||||
this._setTitle();
|
||||
this._unmarkAsDraft();
|
||||
|
||||
// Trigger event to handler
|
||||
this.handler.triggerHandler('itop.search.criteria.value_changed');
|
||||
},
|
||||
_remove: function()
|
||||
_cancel: function()
|
||||
{
|
||||
this.element.remove();
|
||||
this.handler.triggerHandler('itop.search.criteria.removed');
|
||||
this._close();
|
||||
},
|
||||
|
||||
|
||||
@@ -198,7 +235,7 @@ $(function()
|
||||
},
|
||||
_onButtonCancel: function()
|
||||
{
|
||||
this._trace('TODO: Cancel button');
|
||||
this._cancel();
|
||||
},
|
||||
_onButtonMore: function()
|
||||
{
|
||||
@@ -246,11 +283,11 @@ $(function()
|
||||
// First memorize if current criteria is close
|
||||
var bOpen = !me.element.find('.sfc_toggle').hasClass('opened');
|
||||
// Then close every criterion
|
||||
me.handler.find('.sfc_form_group, .sfc_toggle').removeClass('opened');
|
||||
me._closeAll();
|
||||
// Finally open current criteria if necessary
|
||||
if(bOpen === true)
|
||||
{
|
||||
me.element.find('.sfc_form_group, .sfc_toggle').toggleClass('opened');
|
||||
me._open();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -332,6 +369,36 @@ $(function()
|
||||
me[sCallback]();
|
||||
});
|
||||
},
|
||||
// - Reset all operators but active one
|
||||
_resetOperators: function()
|
||||
{
|
||||
var me = this;
|
||||
|
||||
// Reset all operators
|
||||
this.element.find('.sfc_fg_operator').each(function(){
|
||||
var sCallback = '_reset' + me._toCamelCase($(this).attr('data-operator-code')) + 'Operator';
|
||||
if(me[sCallback] === undefined)
|
||||
{
|
||||
sCallback = '_resetOperator';
|
||||
}
|
||||
me[sCallback]($(this));
|
||||
});
|
||||
|
||||
// Set value on current operator
|
||||
var sCurrentOpCode = this.operators[this.options.operator].code;
|
||||
this.element.find('.sfc_fg_operator[data-operator-code="' + sCurrentOpCode + '"]').each(function(){
|
||||
// Check radio (we don't use .trigger('click'), otherwise the criteria will be seen as draft.
|
||||
$(this).find('.sfc_op_radio').prop('checked', true);
|
||||
|
||||
// Reset values
|
||||
var sCallback = '_set' + me._toCamelCase(sCurrentOpCode) + 'OperatorValues';
|
||||
if(me[sCallback] === undefined)
|
||||
{
|
||||
sCallback = '_setOperatorValues';
|
||||
}
|
||||
me[sCallback]($(this), me.options.values);
|
||||
});
|
||||
},
|
||||
// - Set the title element
|
||||
_setTitle: function(sTitle)
|
||||
{
|
||||
@@ -342,15 +409,18 @@ $(function()
|
||||
}
|
||||
this.element.find('.sfc_title').text(sTitle);
|
||||
},
|
||||
|
||||
// Operators helpers
|
||||
// - Return a HTML template for operators
|
||||
_getOperatorTemplate: function()
|
||||
{
|
||||
return '<div class="sfc_fg_operator"><label><input type="radio" class="sfc_op_radio" name="operator" /><span class="sfc_op_name"></span><span class="sfc_op_content"></span></label></div>';
|
||||
},
|
||||
|
||||
// Operators helpers
|
||||
// Prepare operator's DOM element
|
||||
// - Base preparation, always called
|
||||
_prepareOperator: function(oOpElem, sOpIdx, oOp)
|
||||
{
|
||||
var me = this;
|
||||
var sInputId = oOp.code + '_' + oOpElem.attr('id');
|
||||
|
||||
// Set radio
|
||||
@@ -366,11 +436,18 @@ $(function()
|
||||
.attr('data-operator-code', oOp.code);
|
||||
|
||||
// Bind events
|
||||
// - Check radio button on click
|
||||
// - Check radio button on click and mark criteria as draft
|
||||
oOpElem.on('click', function(){
|
||||
oOpElem.find('.sfc_op_radio').prop('checked', true);
|
||||
var bIsChecked = oOpElem.find('.sfc_op_radio').prop('checked');
|
||||
|
||||
if(bIsChecked === false)
|
||||
{
|
||||
oOpElem.find('.sfc_op_radio').prop('checked', true);
|
||||
me._markAsDraft();
|
||||
}
|
||||
});
|
||||
},
|
||||
// - Fallback for operator that has no dedicated callback
|
||||
_prepareDefaultOperator: function(oOpElem, sOpIdx, oOp)
|
||||
{
|
||||
var me = this;
|
||||
@@ -392,6 +469,8 @@ $(function()
|
||||
oOpElem.find('.sfc_op_radio').prop('checked', true)
|
||||
}
|
||||
|
||||
me._markAsDraft();
|
||||
|
||||
// Apply if enter key
|
||||
if(oEvent.key === 'Enter')
|
||||
{
|
||||
@@ -409,6 +488,13 @@ $(function()
|
||||
{
|
||||
// Do nothing as only the label is necessary
|
||||
},
|
||||
// Reset operator's state
|
||||
// - Fallback for operator that has no dedicated callback
|
||||
_resetOperator: function(oOpElem)
|
||||
{
|
||||
oOpElem.find('.sfc_op_content input').val('');
|
||||
},
|
||||
// Get operator's values
|
||||
// - Fallback for operators without a specific callback
|
||||
_getOperatorValues: function(oOpElem)
|
||||
{
|
||||
@@ -421,6 +507,21 @@ $(function()
|
||||
|
||||
return aValues;
|
||||
},
|
||||
// Set operator's values
|
||||
// - Fallback for operators without a specific callback
|
||||
_setOperatorValues: function(oOpElem, aValues)
|
||||
{
|
||||
if(aValues.length === 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
oOpElem.find('.sfc_op_content input').each(function(){
|
||||
$(this).val(aValues[0].value);
|
||||
});
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
|
||||
// Values helpers
|
||||
|
||||
@@ -11,6 +11,7 @@ $(function()
|
||||
{
|
||||
'criterion_outer_selector': null,
|
||||
'result_list_outer_selector': null,
|
||||
'data_config_list_selector': null,
|
||||
'submit_button_selector': null,
|
||||
'hide_initial_criterion': false, // TODO: What is that?
|
||||
'endpoint': null,
|
||||
@@ -133,10 +134,10 @@ $(function()
|
||||
});
|
||||
|
||||
// Criteria events
|
||||
this.element.bind('itop.search.criteria.value_changed', function(oEvent, oData){
|
||||
this.element.on('itop.search.criteria.value_changed', function(oEvent, oData){
|
||||
me._onCriteriaValueChanged(oData);
|
||||
});
|
||||
this.element.bind('itop.search.criteria.removed', function(oEvent, oData){
|
||||
this.element.on('itop.search.criteria.removed', function(oEvent, oData){
|
||||
me._onCriteriaRemoved(oData);
|
||||
});
|
||||
},
|
||||
@@ -268,6 +269,7 @@ $(function()
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: Change this so it appears after the search drawer.
|
||||
oResultAreaElem = $('<div></div>').appendTo(this.element);
|
||||
}
|
||||
oResultAreaElem.addClass('sf_results_area');
|
||||
@@ -404,13 +406,23 @@ $(function()
|
||||
_submit: function()
|
||||
{
|
||||
var me = this;
|
||||
|
||||
// Data
|
||||
// - Regular params
|
||||
var oData = {
|
||||
'params': JSON.stringify({
|
||||
'base_oql': this.options.search.base_oql,
|
||||
'criterion': this.options.search.criterion,
|
||||
}),
|
||||
'list_params': this.elements.results_area.data('sExtraParams'),
|
||||
};
|
||||
// - List params (pass through for the server), merge data_config with list_params if present.
|
||||
var oListParams = {};
|
||||
if(this.options.data_config_list_selector !== null)
|
||||
{
|
||||
// TODO: What ?
|
||||
}
|
||||
$.extend(oListParams, this.options.list_params);
|
||||
oData.list_params = JSON.stringify(oListParams);
|
||||
|
||||
// Show loader
|
||||
this._showLoader();
|
||||
|
||||
Reference in New Issue
Block a user