mirror of
https://github.com/Combodo/iTop.git
synced 2026-05-19 15:22:17 +02:00
Advanced search: UI/UX WIP.
SVN:b1162[5559]
This commit is contained in:
@@ -852,19 +852,24 @@ input.dp-applied {
|
||||
background-color: #eee;
|
||||
color: #2d2d2d;
|
||||
}
|
||||
.search_form_handler .sf_criterion_area .search_form_criteria .sfc_close, .search_form_handler .sf_criterion_area .search_form_criteria .sfc_toggle {
|
||||
.search_form_handler .sf_criterion_area .search_form_criteria .sfc_toggle, .search_form_handler .sf_criterion_area .search_form_criteria .sfc_close {
|
||||
position: absolute;
|
||||
top: 7px;
|
||||
color: #e87c1e;
|
||||
}
|
||||
.search_form_handler .sf_criterion_area .search_form_criteria .sfc_close {
|
||||
right: 7px;
|
||||
.search_form_handler .sf_criterion_area .search_form_criteria .sfc_locked {
|
||||
position: absolute;
|
||||
top: 9px;
|
||||
color: #808080;
|
||||
}
|
||||
.search_form_handler .sf_criterion_area .search_form_criteria .sfc_toggle {
|
||||
display: inline-block;
|
||||
right: 23px;
|
||||
transition: all 0.3s ease-in-out;
|
||||
}
|
||||
.search_form_handler .sf_criterion_area .search_form_criteria .sfc_close, .search_form_handler .sf_criterion_area .search_form_criteria .sfc_locked {
|
||||
right: 7px;
|
||||
}
|
||||
.search_form_handler .sf_criterion_area .search_form_criteria .sfc_title {
|
||||
max-width: 240px;
|
||||
padding-right: 30px;
|
||||
@@ -997,6 +1002,8 @@ input.dp-applied {
|
||||
}
|
||||
.search_form_handler .sf_criterion_area .search_form_criteria.search_form_criteria_raw .sfc_title {
|
||||
cursor: initial;
|
||||
padding-right: 20px;
|
||||
/* Less than regular as there is no toggle icon */
|
||||
}
|
||||
.search_form_handler .sf_criterion_area .search_form_criteria.search_form_criteria_raw .sfc_form_group {
|
||||
display: none;
|
||||
@@ -1139,19 +1146,47 @@ input.dp-applied {
|
||||
margin-top: 8px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.search_form_handler .sf_filter input, .search_form_handler .sf_filter button, .search_form_handler .sf_filter .sff_picto {
|
||||
vertical-align: middle;
|
||||
height: 22px;
|
||||
}
|
||||
.search_form_handler .sf_filter input, .search_form_handler .sf_filter button {
|
||||
border: 1px solid #ababab;
|
||||
}
|
||||
.search_form_handler .sf_filter input {
|
||||
width: 100%;
|
||||
}
|
||||
.search_form_handler .sf_filter .sff_picto {
|
||||
.search_form_handler .sf_filter button {
|
||||
width: 23px;
|
||||
/* Must be equals to .sf_filter > *:height */
|
||||
background-color: #fff;
|
||||
color: #ea7d1e;
|
||||
font-size: 10px;
|
||||
}
|
||||
.search_form_handler .sf_filter button:first-of-type {
|
||||
margin-left: 5px;
|
||||
}
|
||||
.search_form_handler .sf_filter button:not(:first-of-type) {
|
||||
border-left: transparent;
|
||||
}
|
||||
.search_form_handler .sf_filter .sff_input_wrapper {
|
||||
position: relative;
|
||||
}
|
||||
.search_form_handler .sf_filter .sff_input_wrapper .sff_picto {
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
top: 5px;
|
||||
top: 2px;
|
||||
opacity: 0.6;
|
||||
user-select: none;
|
||||
}
|
||||
.search_form_handler .sf_filter .sff_reset {
|
||||
.search_form_handler .sf_filter .sff_input_wrapper .sff_reset {
|
||||
display: none;
|
||||
}
|
||||
.search_form_handler .sf_filter.sf_with_buttons input {
|
||||
width: initial;
|
||||
/* Reset the 100% */
|
||||
min-width: 120px;
|
||||
}
|
||||
.sf_results_area .sf_results_placeholder {
|
||||
margin-top: 100px;
|
||||
text-align: center;
|
||||
|
||||
@@ -953,20 +953,26 @@ input.dp-applied {
|
||||
}
|
||||
|
||||
/* Top left corner icons */
|
||||
.sfc_close,
|
||||
.sfc_toggle{
|
||||
.sfc_toggle,
|
||||
.sfc_close{
|
||||
position: absolute;
|
||||
top: 7px;
|
||||
color: $search-criteria-box-picto-color;
|
||||
}
|
||||
.sfc_close{
|
||||
right: 7px;
|
||||
.sfc_locked{
|
||||
position: absolute;
|
||||
top: 9px;
|
||||
color: $gray-light;
|
||||
}
|
||||
.sfc_toggle{
|
||||
display: inline-block;
|
||||
right: 23px;
|
||||
transition: all 0.3s ease-in-out;
|
||||
}
|
||||
.sfc_close,
|
||||
.sfc_locked{
|
||||
right: 7px;
|
||||
}
|
||||
|
||||
.sfc_title{
|
||||
max-width: 240px;
|
||||
@@ -1142,6 +1148,7 @@ input.dp-applied {
|
||||
}
|
||||
.sfc_title{
|
||||
cursor: initial;
|
||||
padding-right: 20px; /* Less than regular as there is no toggle icon */
|
||||
}
|
||||
.sfc_form_group{
|
||||
display: none;
|
||||
@@ -1204,7 +1211,8 @@ input.dp-applied {
|
||||
}
|
||||
}
|
||||
|
||||
&.search_form_criteria_date_time, &.search_form_criteria_date {
|
||||
&.search_form_criteria_date_time,
|
||||
&.search_form_criteria_date {
|
||||
.sfc_form_group.advanced {
|
||||
.sfc_fg_operator_between {
|
||||
margin-bottom: 5px;
|
||||
@@ -1353,18 +1361,53 @@ input.dp-applied {
|
||||
margin-top: 8px;
|
||||
margin-bottom: 8px;
|
||||
|
||||
input,
|
||||
button,
|
||||
.sff_picto{
|
||||
vertical-align: middle;
|
||||
height: 22px;
|
||||
}
|
||||
|
||||
input,
|
||||
button{
|
||||
border: 1px solid #ABABAB;
|
||||
}
|
||||
input{
|
||||
width: 100%;
|
||||
}
|
||||
.sff_picto{
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
top: 5px;
|
||||
opacity: 0.6;
|
||||
user-select: none;
|
||||
button{
|
||||
width: 23px; /* Must be equals to .sf_filter > *:height */
|
||||
background-color: $white;
|
||||
color: $combodo-orange;
|
||||
font-size: 10px;
|
||||
|
||||
&:first-of-type{
|
||||
margin-left: 5px;
|
||||
}
|
||||
&:not(:first-of-type){
|
||||
border-left: transparent;
|
||||
}
|
||||
}
|
||||
.sff_reset{
|
||||
display: none;
|
||||
.sff_input_wrapper{
|
||||
position: relative;
|
||||
|
||||
.sff_picto{
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
top: 2px;
|
||||
opacity: 0.6;
|
||||
user-select: none;
|
||||
}
|
||||
.sff_reset{
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
&.sf_with_buttons{
|
||||
input{
|
||||
width: initial; /* Reset the 100% */
|
||||
min-width: 120px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1453,6 +1453,7 @@ When associated with a trigger, each action is given an "order" number, specifyi
|
||||
|
||||
// - Other translations
|
||||
'UI:Search:Value:Filter:Placeholder' => 'Filter...',
|
||||
'UI:Search:Value:Search:Placeholder' => 'Search...',
|
||||
'UI:Search:Value:Toggler:CheckAllNone' => 'Check all / none',
|
||||
|
||||
// - Widget other translations
|
||||
|
||||
@@ -595,7 +595,7 @@ $(function()
|
||||
|
||||
|
||||
// Values helpers
|
||||
// - Check if criteria has allowed values
|
||||
// - Check if criteria has allowed values either preloaded or through autocomplete
|
||||
_hasAllowedValues: function()
|
||||
{
|
||||
return ( (this.options.field.allowed_values !== undefined) && (this.options.field.allowed_values !== null) );
|
||||
@@ -615,6 +615,21 @@ $(function()
|
||||
{
|
||||
return (this._hasPreloadedAllowedValues()) ? this.options.field.allowed_values.values : {};
|
||||
},
|
||||
// - Check if criteria has allowed values that should be loaded through autocomplete
|
||||
_hasAutocompleteAllowedValues: function()
|
||||
{
|
||||
if(this._hasAllowedValues() && (this.options.field.allowed_values.autocomplete === true) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
// - Return the allowed values from the autocomplete
|
||||
_getAutocompleteAllowedValues: function()
|
||||
{
|
||||
console.log('TODO: Retrieve allowed values through autocomplete (get needle in the input)');
|
||||
},
|
||||
// - Return current values
|
||||
_getValues: function()
|
||||
{
|
||||
|
||||
@@ -95,12 +95,20 @@ $(function()
|
||||
|
||||
// - Filter
|
||||
var sFilterId = 'filter_' + sOpId;
|
||||
var sFilterPlaceholder = (this._hasAutocompleteAllowedValues()) ? Dict.S('UI:Search:Value:Search:Placeholder') : Dict.S('UI:Search:Value:Filter:Placeholder');
|
||||
var oFilterElem = $('<div class="sf_filter"></div>')
|
||||
.append('<input type="text" id="' + sFilterId + '" placeholder="' + Dict.S('UI:Search:Value:Filter:Placeholder') + '" /><span class="sff_picto sff_filter fa fa-filter"></span><span class="sff_picto sff_reset fa fa-times"></span>')
|
||||
.append('<span class="sff_input_wrapper"><input type="text" id="' + sFilterId + '" placeholder="' + sFilterPlaceholder + '" /><span class="sff_picto sff_filter fa fa-filter"></span><span class="sff_picto sff_reset fa fa-times"></span></span>')
|
||||
.appendTo(oOpContentElem);
|
||||
|
||||
// - Allowed values
|
||||
var oAllowedValuesElem = $('<div class="sfc_opc_mc_items"></div>');
|
||||
var oAllowedValuesElem = $('<div class="sfc_opc_mc_items"></div>')
|
||||
.appendTo(oOpContentElem);
|
||||
// - Static values: Always there no matter the field constraints
|
||||
var oStaticValuesElem = $('<div class="sfc_opc_mc_items_list sfc_opc_mc_items_static"></div>')
|
||||
.appendTo(oAllowedValuesElem);
|
||||
// - Dynamic values: Depends on the field constraints
|
||||
var oDynamicValuesElem = $('<div class="sfc_opc_mc_items_list sfc_opc_mc_items_dynamic"></div>')
|
||||
.appendTo(oAllowedValuesElem);
|
||||
|
||||
// - Null value if allowed
|
||||
// Note: null values is NOT put among the allowed values for two reasons:
|
||||
@@ -114,7 +122,7 @@ $(function()
|
||||
.addClass('sfc_opc_mc_item')
|
||||
.attr('data-value-code', sValCode)
|
||||
.append('<label><input type="checkbox" value="' + sValCode + '"/>' + sValLabel + '</label>')
|
||||
.appendTo(oAllowedValuesElem);
|
||||
.appendTo(oStaticValuesElem);
|
||||
}
|
||||
|
||||
// - Regular allowed values
|
||||
@@ -129,7 +137,7 @@ $(function()
|
||||
.addClass('sfc_opc_mc_item')
|
||||
.attr('data-value-code', sValCode)
|
||||
.append('<label><input type="checkbox" value="'+sValCode+'"/>'+sValLabel+'</label>')
|
||||
.appendTo(oAllowedValuesElem);
|
||||
.appendTo(oDynamicValuesElem);
|
||||
|
||||
if (this._isSelectedValues(sValCode))
|
||||
{
|
||||
@@ -137,7 +145,20 @@ $(function()
|
||||
}
|
||||
}
|
||||
}
|
||||
oAllowedValuesElem.appendTo(oOpContentElem);
|
||||
|
||||
// - Specific to autocomplete mode
|
||||
if(this._hasAutocompleteAllowedValues())
|
||||
{
|
||||
// Remove filter picto from input
|
||||
oFilterElem.find('.sff_filter').remove();
|
||||
|
||||
// Add search dialog button
|
||||
oFilterElem
|
||||
.append('<button type="button" class="sff_search_dialog"><span class=" fa fa-search"></span></button>')
|
||||
.addClass('sf_with_buttons');
|
||||
|
||||
// Prepare "selected" values area
|
||||
}
|
||||
|
||||
// Events
|
||||
// - Check / Uncheck all toggler
|
||||
@@ -151,7 +172,7 @@ $(function()
|
||||
});
|
||||
|
||||
// - Filter
|
||||
// Note: "keyup" event is use instead of "keydown", otherwise, the inpu value would not be set yet.
|
||||
// Note: "keyup" event is use instead of "keydown", otherwise, the input value would not be set yet.
|
||||
oFilterElem.find('input').on('keyup focus', function(oEvent){
|
||||
// TODO: Move on values with up and down arrow keys; select with space or enter.
|
||||
|
||||
@@ -204,6 +225,56 @@ $(function()
|
||||
me._apply();
|
||||
});
|
||||
|
||||
// - Specific to autocomplete mode
|
||||
// TODO: We NEED to refactor all of this for a better integration. Most might be in the main widget as any widget could use XHR helpers.
|
||||
if(this._hasAutocompleteAllowedValues())
|
||||
{
|
||||
// // Autocomplete
|
||||
// var oACXHR = null;
|
||||
// var oACTimeout = null;
|
||||
// oFilterElem.find('input').off('keyup focus').on('keyup focus', function(oEvent){
|
||||
// // TODO: Move on values with up and down arrow keys; select with space or enter.
|
||||
//
|
||||
// var sFilter = $(this).val();
|
||||
//
|
||||
// if(sFilter === '')
|
||||
// {
|
||||
// oOpContentElem.find('.sfc_opc_mc_item').html('');
|
||||
// oFilterElem.find('.sff_reset').hide();
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// oOpContentElem.find('.sfc_opc_mc_item').html('TOTR: Wait');
|
||||
// if(oACXHR !== null)
|
||||
// {
|
||||
// oACXHR.abort();
|
||||
// }
|
||||
// oACXHR = $.post(
|
||||
// AddAppContext(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php'),
|
||||
// {
|
||||
// sTargetClass: me.options.field.class,
|
||||
// //iInputId: me.id,
|
||||
// //iObjectId: iObjectId,
|
||||
// sAttCode: me.options.field.code,
|
||||
// bSearchMode: true,
|
||||
// operation: 'getObjectName'
|
||||
// }
|
||||
// )
|
||||
// .done(function(oResponse, sStatus, oXHR){ console.log('ok', oResponse); })
|
||||
// .fail(function(oResponse, sStatus, oXHR){ console.log('fail', oResponse); })
|
||||
// .always(function(oResponse, sStatus, oXHR){ console.log('always', oResponse); });
|
||||
//
|
||||
// oFilterElem.find('.sff_reset').show();
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// // Open search dialog
|
||||
// oFilterElem.find('.sff_search_dialog').on('click', function(){
|
||||
// // TODO: Open search dialog with right params
|
||||
// alert('Not implemented yet');
|
||||
// });
|
||||
}
|
||||
|
||||
oOpElem.find('.sfc_op_content').append(oOpContentElem);
|
||||
},
|
||||
_setTitle: function(sTitle)
|
||||
|
||||
@@ -9,11 +9,13 @@ $(function()
|
||||
// default options
|
||||
options:
|
||||
{
|
||||
'endpoint': AddAppContext(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php'),
|
||||
|
||||
// Null value
|
||||
'null_value': {
|
||||
'code': 0,
|
||||
'label': Dict.S('UI:UndefinedObject'),
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
@@ -52,6 +54,5 @@ $(function()
|
||||
//------------------
|
||||
// Inherited methods
|
||||
//------------------
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
@@ -48,5 +48,25 @@ $(function()
|
||||
// Inherited methods
|
||||
//------------------
|
||||
|
||||
// DOM element helpers
|
||||
prepareInOperator: function(oOpElem, sOpIdx, oOp)
|
||||
{
|
||||
var me = this;
|
||||
|
||||
this._super();
|
||||
|
||||
// DOM elements
|
||||
// - Add search dialog button
|
||||
this.element.find('.sf_filter')
|
||||
.append('<button type="button" class="sff_hierarchy_dialog"><span class=" fa fa-sitemap"></span></button>')
|
||||
.addClass('sf_with_buttons');
|
||||
|
||||
// Events
|
||||
// - Open hierarchy dialog
|
||||
this.element.find('.sff_hierarchy_dialog').on('click', function(){
|
||||
// TODO: Open hierarchy dialog with right params
|
||||
alert('Not implemented yet');
|
||||
});
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
@@ -319,7 +319,7 @@ $(function()
|
||||
var oFilterElem = $('<div></div>')
|
||||
.addClass('sf_filter')
|
||||
.addClass('sfm_filter')
|
||||
.append('<input type="text" placeholder="' + Dict.S('UI:Search:Value:Filter:Placeholder') + '" /><span class="sff_picto sff_filter fa fa-filter"></span><span class="sff_picto sff_reset fa fa-times"></span>')
|
||||
.append('<span class="sff_input_wrapper"><input type="text" placeholder="' + Dict.S('UI:Search:Value:Filter:Placeholder') + '" /><span class="sff_picto sff_filter fa fa-filter"></span><span class="sff_picto sff_reset fa fa-times"></span></span>')
|
||||
.appendTo(oContentElem);
|
||||
|
||||
// - Lists container
|
||||
@@ -618,46 +618,54 @@ $(function()
|
||||
_addCriteria: function(oData)
|
||||
{
|
||||
var sRef = oData.ref;
|
||||
var sType = (oData.widget !== undefined) ? oData.widget : this._getCriteriaTypeFromFieldRef(sRef);
|
||||
var sType = sType = (oData.widget !== undefined) ? oData.widget : this._getCriteriaTypeFromFieldRef(sRef);
|
||||
|
||||
if(sType !== null)
|
||||
// Force to raw for non removable criteria
|
||||
if( (oData.is_removable !== undefined) && (oData.is_removable === false) )
|
||||
{
|
||||
// Retrieve widget class
|
||||
var sWidgetName = this._getCriteriaWidgetNameFromType(sType);
|
||||
|
||||
// Add some informations from the field
|
||||
if(this._hasFieldDefinition(sRef))
|
||||
{
|
||||
var oFieldDef = this._getFieldDefinition(sRef);
|
||||
oData.field = {
|
||||
label: oFieldDef.label,
|
||||
class: oFieldDef.class,
|
||||
class_alias: oFieldDef.class_alias,
|
||||
code: oFieldDef.code,
|
||||
widget: oFieldDef.widget,
|
||||
allowed_values: oFieldDef.allowed_values,
|
||||
is_null_allowed: oFieldDef.is_null_allowed,
|
||||
};
|
||||
}
|
||||
|
||||
if ('date' == sType || 'date_time' == sType)
|
||||
{
|
||||
oData.datepicker = this.options.datepicker;
|
||||
}
|
||||
|
||||
// Create DOM element
|
||||
var oCriteriaElem = $('<div></div>')
|
||||
.addClass('sf_criteria')
|
||||
//.insertBefore(this.elements.more_criterion);
|
||||
.appendTo(this.elements.criterion_area);
|
||||
|
||||
// Instanciate widget
|
||||
$.itop[sWidgetName](oData, oCriteriaElem);
|
||||
sType = 'raw';
|
||||
}
|
||||
else
|
||||
|
||||
// Protection against bad initialization data
|
||||
if(sType === null)
|
||||
{
|
||||
this._trace('Could not add criteria as we could not retrieve type for ref "' + sRef + '".');
|
||||
this._trace('Could not add criteria as we could not retrieve type for ref "'+sRef+'".');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Retrieve widget class
|
||||
var sWidgetName = this._getCriteriaWidgetNameFromType(sType);
|
||||
|
||||
// Add some informations from the field
|
||||
if(this._hasFieldDefinition(sRef))
|
||||
{
|
||||
var oFieldDef = this._getFieldDefinition(sRef);
|
||||
oData.field = {
|
||||
label: oFieldDef.label,
|
||||
class: oFieldDef.class,
|
||||
class_alias: oFieldDef.class_alias,
|
||||
code: oFieldDef.code,
|
||||
widget: oFieldDef.widget,
|
||||
allowed_values: oFieldDef.allowed_values,
|
||||
is_null_allowed: oFieldDef.is_null_allowed,
|
||||
};
|
||||
}
|
||||
|
||||
if ('date' == sType || 'date_time' == sType)
|
||||
{
|
||||
oData.datepicker = this.options.datepicker;
|
||||
}
|
||||
|
||||
// Create DOM element
|
||||
var oCriteriaElem = $('<div></div>')
|
||||
.addClass('sf_criteria')
|
||||
//.insertBefore(this.elements.more_criterion);
|
||||
.appendTo(this.elements.criterion_area);
|
||||
|
||||
// Instanciate widget
|
||||
$.itop[sWidgetName](oData, oCriteriaElem);
|
||||
|
||||
return true;
|
||||
},
|
||||
// - Find a criteria's type from a field's ref (usually <CLASS_ALIAS>.<ATT_CODE>)
|
||||
_getCriteriaTypeFromFieldRef: function(sRef)
|
||||
|
||||
Reference in New Issue
Block a user