advanced search - merged commit (since sourceforge has lost our commit, this is a manual merge all all losts)

SVN:trunk[5638]
This commit is contained in:
Bruno Da Silva
2018-04-12 12:29:32 +00:00
parent 7309c046ae
commit 0b8f75f799
15 changed files with 205 additions and 65 deletions

View File

@@ -175,12 +175,6 @@ class DataTable
$sJSOptions = json_encode($aOptions);
$oPage->add_ready_script("$('#datatable_{$this->iListId}').datatable($sJSOptions);");
if (isset($aExtraParams['update_history']) && true == $aExtraParams['update_history'])
{
$sFilter = json_encode(array('filter' => $this->oSet->GetFilter()->serialize()));
$oPage->add_ready_script("$('body').trigger('update_history.itop', [$sFilter])");
}
return $sHtml;
}

View File

@@ -706,6 +706,20 @@ class DisplayBlock
}
}
}
if (isset($aExtraParams['update_history']) && true == $aExtraParams['update_history'])
{
$seventAttachedData = json_encode(array(
'filter' => $this->m_oSet->GetFilter()->serialize(),
'breadcrumb_id' => "ui-search-".$this->m_oSet->GetClass(),
'breadcrumb_label' => MetaModel::GetName($this->m_oSet->GetClass()),
'breadcrumb_max_count' => utils::GetConfig()->Get('breadcrumb.max_count'),
'breadcrumb_instance_id'=> MetaModel::GetConfig()->GetItopInstanceid(),
'breadcrumb_icon' => utils::GetAbsoluteUrlAppRoot().'images/breadcrumb-search.png'
));
$oPage->add_ready_script("$('body').trigger('update_history.itop', [$seventAttachedData])");
}
}
break;
@@ -1842,12 +1856,23 @@ class MenuBlock extends DisplayBlock
{
$sHtml .= "<div class=\"itop_popup actions_menu\"><ul>\n<li>".Dict::S('UI:Menu:Actions')."\n<ul>\n";
}
$sHtml .= $oPage->RenderPopupMenuItems($aActions, $aFavoriteActions);
if ($this->m_sStyle == 'details')
{
$sSearchAction = "window.location=\"{$sRootUrl}pages/UI.php?operation=search_form&class=$sClass{$sContext}\"";
$sHtml .= "<div class=\"actions_button icon_actions_button\" title=\"".htmlentities(Dict::Format('UI:SearchFor_Class', MetaModel::GetName($sClass)), ENT_QUOTES, 'UTF-8')."\"><span class=\"search-button fa fa-search\" onclick='$sSearchAction'></span></div>";
}
if (!$oPage->IsPrintableVersion() && ($sRefreshAction!=''))
{
$sHtml .= "<div class=\"actions_button\" title=\"".htmlentities(Dict::S('UI:Button:Refresh'), ENT_QUOTES, 'UTF-8')."\"><span class=\"refresh-button\" onclick=\"$sRefreshAction\"></span></div>";
$sHtml .= "<div class=\"actions_button icon_actions_button\" title=\"".htmlentities(Dict::S('UI:Button:Refresh'), ENT_QUOTES, 'UTF-8')."\"><span class=\"refresh-button fa fa-refresh\" onclick=\"$sRefreshAction\"></span></div>";
}
}
static $bPopupScript = false;

View File

@@ -922,6 +922,9 @@ input.dp-applied {
text-overflow: ellipsis;
cursor: pointer;
}
.search_form_handler .sf_criterion_area .search_form_criteria .sfc_title .values {
font-weight: bold;
}
.search_form_handler .sf_criterion_area .search_form_criteria .sfc_form_group {
/* Form group (operators) is displayed only when the criteria is toggled to opened state */
display: none;
@@ -2426,12 +2429,18 @@ h2.printable-tab-title {
select.multiselect {
max-width: 150px;
}
span.refresh-button {
span.search-button, span.refresh-button {
display: inline-block;
width: 21px;
height: 18px;
cursor: pointer;
background: transparent url(../images/refresh-fff.png?v=v2.5.0) left center no-repeat;
color: #fff;
text-align: center;
padding-top: 3px;
font-size: 10px;
}
.actions_button.icon_actions_button {
padding: 0 2px 0 2px;
}
.case-log-history-entry {
display: block;

View File

@@ -1038,6 +1038,11 @@ input.dp-applied {
overflow-x: hidden;
text-overflow: ellipsis;
cursor: pointer;
.values {
font-weight: bold;
}
}
.sfc_form_group{
/* Form group (operators) is displayed only when the criteria is toggled to opened state */
@@ -2751,12 +2756,25 @@ h2.printable-tab-title {
select.multiselect {
max-width: 150px;
}
span.refresh-button {
//span.refresh-button {
// display: inline-block;
// width: 21px;
// height: 18px;
// cursor: pointer;
// background: transparent url(../images/refresh-fff.png?v=#{$version}) left center no-repeat;
//}
span.search-button, span.refresh-button {
display: inline-block;
width: 21px;
height: 18px;
cursor: pointer;
background: transparent url(../images/refresh-fff.png?v=#{$version}) left center no-repeat;
color: #FFFFFF;
text-align: center;
padding-top: 3px;
font-size: 10px;
}
.actions_button.icon_actions_button {
padding: 0 2px 0 2px;
}
.case-log-history-entry {
display: block;

View File

@@ -537,7 +537,7 @@ $(function()
sDictEntry = 'UI:Search:Criteria:Title:Default:' + this._toCamelCase(sOperator);
}
sTitle = Dict.Format(sDictEntry, this.options.field.label, sValueAsText);
sTitle = Dict.Format(sDictEntry, this.options.field.label, '<span class="values">'+sValueAsText+'</span>');
// Last chande fallback
if(sTitle === sDictEntry)
@@ -551,9 +551,11 @@ $(function()
_setTitle: function(sTitle)
{
sTitle = this._computeTitle(sTitle);
this.element.find('.sfc_title')
.html(sTitle)
.attr('title', sTitle);
var titleElemnt = this.element.find('.sfc_title');
titleElemnt.html(sTitle);
titleElemnt.attr('title', titleElemnt.text());
},
// Operators helpers

View File

@@ -34,8 +34,14 @@ $(function()
// "onclose_show" : "until", => on x_picker close, should we open another one (on "from" close shall we show "until")
// "value_index": 0, => the widget communicate with an array of values, the index 0 is "from" the index 1 is "until"
// Date_time widget specifi settings :
// Date_time widget specific settings :
// > Beware : a lot of those parameters are unused (the intial dev. tested several different UI before the final choice)
// "x_picker" : 'datetimepicker', => the plugin used either datepicker or datetimepicker
// "picker_extra_params": { => extram init params for the datepicker, use by the datetime to force the time of the "until" at 23:59:59
// "hour": 23,
// "minute":59,
// "second":59
// },
// "default_time_add": false, => either false to disable it or number of second to add (used by the datetimepicker to choose the right time on synched datepicker change, its value change from 0 for "from" to +1d-1s for "until"
// "show_on_advanced": true, => is the input displaye on "more" or "less" mode advanced is an lais for "more" in the css
// "synced_with": "from_time", => from and until has both two input (datepicker and datetimepicker). each time one input change, the other one has to change
@@ -301,21 +307,54 @@ $(function()
if (sTitle === undefined)
{
var aValues = me._getValues();
// switch (true)
// {
// case (typeof aValues[0] == 'undefined' && typeof aValues[1] == 'undefined'):
// case (typeof aValues[0].label == 'undefined' && typeof aValues[1].label == 'undefined'):
// case (aValues[0].label.trim() == '' && aValues[1].label.trim() == ''):
// var sDictEntrySuffix = ':All';
// break;
// case (typeof aValues[0] == 'undefined' ):
// case (typeof aValues[0].label == 'undefined' ):
// case (aValues[0].label.trim() == '' ):
// var sDictEntrySuffix = ':Until';
// break;
// case (typeof aValues[1] == 'undefined'):
// case (typeof aValues[1].label == 'undefined' ):
// case (aValues[1].label.trim() == ''):
// var sDictEntrySuffix = ':From';
// break;
// default:
// var sDictEntrySuffix = '';
// break;
// }
switch (true)
{
case (typeof aValues[0] == 'undefined' && typeof aValues[1] == 'undefined'):
case (typeof aValues[0].label == 'undefined' && typeof aValues[1].label == 'undefined'):
case (aValues[0].label.trim() == '' && aValues[1].label.trim() == ''):
var sDictEntrySuffix = ':All';
break;
case (typeof aValues[0] == 'undefined' ):
case (typeof aValues[0].label == 'undefined' ):
case (aValues[0].label.trim() == '' ):
var sDictEntrySuffix = ':Until';
break;
case (typeof aValues[1] == 'undefined'):
var sDictEntrySuffix = ':From';
break;
case (typeof aValues[0].label == 'undefined' && typeof aValues[1].label == 'undefined'):
var sDictEntrySuffix = ':All';
break;
case (typeof aValues[0].label == 'undefined' ):
var sDictEntrySuffix = ':Until';
break;
case (typeof aValues[1].label == 'undefined' ):
case (aValues[1].label.trim() == ''):
var sDictEntrySuffix = ':From';
break;
case ((typeof aValues[0].label == 'string' && aValues[0].label.trim() == '') && (typeof aValues[1].label == 'string' && aValues[1].label.trim() == '')):
var sDictEntrySuffix = ':All';
break;
case (typeof aValues[0].label == 'string' && aValues[0].label.trim() == ''):
var sDictEntrySuffix = ':Until';
break;
case (typeof aValues[1].label == 'string' && aValues[1].label.trim() == ''):
var sDictEntrySuffix = ':From';
break;
default:
@@ -330,7 +369,7 @@ $(function()
sDictEntry = 'UI:Search:Criteria:Title:Default:' + this._toCamelCase(me.options.operator) + sDictEntrySuffix;
}
sTitle = Dict.Format(sDictEntry, this.options.field.label, this._getValuesAsText());
sTitle = Dict.Format(sDictEntry, this.options.field.label, '<span class="values">'+this._getValuesAsText()+'</span>');
return sTitle;
}
@@ -344,6 +383,8 @@ $(function()
{
var me = this;
var keepTime = true;
if (aRawValues == undefined)
{
aRawValues = me._getValues();
@@ -358,8 +399,17 @@ $(function()
}
else
{
// aRawValues[1].label = aRawValues[1].label.replace(/(\s\d{2}:\d{2}:\d{2})/, '');
aRawValues[1].label = aRawValues[1].label.replace('23:59:59', '');
if (
null == aRawValues[1].label.match('23:59:59')
||
(typeof aRawValues[0] != 'undefined' && typeof aRawValues[0].label != 'undefined' && aRawValues[0].label != '' && null == aRawValues[0].label.match('00:00:00'))
)
{
keepTime = false;
}
else {
aRawValues[1].label = aRawValues[1].label.replace('23:59:59', '');
}
}
if (typeof aRawValues[0] == 'undefined' || typeof aRawValues[0].label == 'undefined' || aRawValues[0].label == '')
{
@@ -367,8 +417,10 @@ $(function()
}
else
{
// aRawValues[0].label = aRawValues[0].label.replace(/(\s\d{2}:\d{2}:\d{2})/, '');
aRawValues[0].label = aRawValues[0].label.replace('00:00:00', '');
if (keepTime)
{
aRawValues[0].label = aRawValues[0].label.replace('00:00:00', '');
}
}
}
return me._super(aRawValues);

View File

@@ -439,7 +439,11 @@ $(function()
aFirstValues.push(this.options.values[i].label);
}
sTitle = Dict.Format('UI:Search:Criteria:Title:Enum:In:Many', this.options.field.label, aFirstValues.join(', '), (iValCount - iValLimit+1));
sTitle = Dict.Format(
'UI:Search:Criteria:Title:Enum:In:Many',
'<span class="values">'+this.options.field.label, aFirstValues.join(', ')+'</span>',
'<span class="values">'+(iValCount - iValLimit+1)+'</span>'
);
}
return this._super(sTitle);

View File

@@ -235,7 +235,7 @@ $(function()
sDictEntry = 'UI:Search:Criteria:Title:Default:' + this._toCamelCase(me.options.operator) + sDictEntrySuffix;
}
sTitle = Dict.Format(sDictEntry, this.options.field.label, this._getValuesAsText());
sTitle = Dict.Format(sDictEntry, this.options.field.label, '<span class="values">'+this._getValuesAsText()+'</span>');
return sTitle;
}

View File

@@ -28,12 +28,14 @@ $(function()
'code': 'ends_with',
'rank': 30,
},
'=': {
'rank': 40,//pre-existing, reordered
},
'REGEXP': {
'label': Dict.S('UI:Search:Criteria:Operator:String:RegExp'),
'code': 'reg_exp',
'rank': 40,
'rank': 50,
},
'=': null, // Remove this one from string widget.
},
},

View File

@@ -170,7 +170,7 @@ $(function()
me._onCriteriaErrorOccured(oData);
});
$('body').on('update_history.itop', function(event, filter) {
$('body').on('update_history.itop', function(event, eventData) {
if (! me.element.is(':visible'))
{
@@ -183,14 +183,31 @@ $(function()
return;
}
me._trace('history update', filter);
me._trace('history update', eventData);
var newUrl = GetAbsoluteUrlAppRoot()+'pages/UI.php?operation=search';
newUrl = newUrl + '&filter='+filter['filter'];
newUrl = newUrl + '&filter='+eventData['filter'];
newUrl = newUrl + '&c[menu]='+me._extractURLParameter(window.location.href, "c[menu]");
if ('' != me._extractURLParameter(window.location.href, "debug"))
{
newUrl = newUrl + '&debug='+me._extractURLParameter(window.location.href, "debug");
}
history.replaceState(null, null, newUrl);
$('#itop-breadcrumb').breadcrumb('RefreshLatestEntry', newUrl);
$('#itop-breadcrumb')
.breadcrumb('destroy')
.breadcrumb({
itop_instance_id: eventData['breadcrumb_instance_id'],
max_count: eventData['breadcrumb_max_count'],
new_entry: {
"id": eventData['breadcrumb_id'],
"label": eventData['breadcrumb_label'],
"url": newUrl,
'icon': eventData['breadcrumb_icon'],
'description': ''
}
});
});
},
@@ -214,7 +231,7 @@ $(function()
}
}
}
return null;
return '';
},
// - Update search option of the widget
_updateSearch: function()

View File

@@ -29,7 +29,7 @@ $(function()
{
"itop_root_class": null,
"preference_code": undefined, // if undefined, it is computed on _create
"history_max_length": 10, // if the history is longer, the older entries are removed
"history_max_length": 5, // if the history is longer, the older entries are removed
"history_backend_store_timeout": 5000, // wait for this time before storing the new history in the backend
},

View File

@@ -128,12 +128,15 @@ function ReloadAndDisplay($oPage, $oObj, $sMessageId = '', $sMessage = '', $sSev
function DisplayDetails($oP, $sClass, $oObj, $id)
{
$sClassLabel = MetaModel::GetName($sClass);
$oSearch = new DBObjectSearch($sClass);
$oBlock = new DisplayBlock($oSearch, 'search', false);
$oBlock->Display($oP, 0, array(
'table_id' => 'search-widget-results-outer',
'open' => false,
));
// 2018-04-11 : removal of the search block
// $oSearch = new DBObjectSearch($sClass);
// $oBlock = new DisplayBlock($oSearch, 'search', false);
// $oBlock->Display($oP, 0, array(
// 'table_id' => 'search-widget-results-outer',
// 'open' => false,
// 'update_history' => false,
// ));
// The object could be listed, check if it is actually allowed to view it
$oSet = CMDBObjectSet::FromObject($oObj);

View File

@@ -57,9 +57,10 @@ $sOperation = utils::ReadParam('operation', '');
$oP->SetBreadCrumbEntry('ui-tool-universalsearch', Dict::S('Menu:UniversalSearchMenu'), Dict::S('Menu:UniversalSearchMenu+'), '', utils::GetAbsoluteUrlAppRoot().'images/wrench.png');
// First part: select the class to search for
$oP->add("<form>");
$oP->add(Dict::S('UI:UniversalSearch:LabelSelectTheClass')."<select style=\"width: 150px;\" id=\"select_class\" name=\"baseClass\" onChange=\"this.form.submit();\">");
//$sSearchHeaderForceDropdown
$sSearchHeaderForceDropdown = '<select id="select_class" name="baseClass" onChange="this.form.submit();">';
$aClassLabels = array();
foreach(MetaModel::GetClasses('bizmodel') as $sCurrentClass)
{
@@ -70,11 +71,11 @@ foreach($aClassLabels as $sCurrentClass => $sLabel)
{
$sDescription = MetaModel::GetClassDescription($sCurrentClass);
$sSelected = ($sCurrentClass == $sBaseClass) ? " SELECTED" : "";
$oP->add("<option value=\"$sCurrentClass\" title=\"$sDescription\"$sSelected>$sLabel</option>");
$sSearchHeaderForceDropdown .= "<option value=\"$sCurrentClass\" title=\"$sDescription\"$sSelected>$sLabel</option>";
}
$oP->add("</select>\n");
$oP->add($oAppContext->GetForForm());
$oP->add("</form>\n");
$sSearchHeaderForceDropdown .= "</select>\n";
//end of $sSearchHeaderForceDropdown
try
{
@@ -111,6 +112,7 @@ if ($oFilter != null)
$aExtraParams['baseClass'] = $sBaseClass;
$aExtraParams['action'] = utils::GetAbsoluteUrlAppRoot().'pages/UniversalSearch.php';
$aExtraParams['table_id'] = '1';
$aExtraParams['search_header_force_dropdown'] = $sSearchHeaderForceDropdown;
//$aExtraParams['class'] = $sClassName;
$oBlock->Display($oP, 0, $aExtraParams);

View File

@@ -104,9 +104,14 @@ try
}
if (!isset($aExtraParams['update_history']))
{
$aExtraParams['update_history'] = true;
}
$aExtraParams['display_limit'] = true;
$aExtraParams['truncated'] = true;
$aExtraParams['update_history'] = true;
if (isset($sListId))
{
$oDisplayBlock->Display($oPage, $sListId, $aExtraParams);

View File

@@ -114,24 +114,31 @@ class SearchForm
}
}
$aSubClasses = MetaModel::GetSubclasses($sRootClass);
if (count($aSubClasses) > 0)
if (isset($aExtraParams['search_header_force_dropdown']))
{
$aOptions = array();
$aOptions[MetaModel::GetName($sRootClass)] = "<option value=\"$sRootClass\">".MetaModel::GetName($sRootClass)."</options>\n";
foreach($aSubClasses as $sSubclassName)
{
$aOptions[MetaModel::GetName($sSubclassName)] = "<option value=\"$sSubclassName\">".MetaModel::GetName($sSubclassName)."</options>\n";
}
$aOptions[MetaModel::GetName($sClassName)] = "<option selected value=\"$sClassName\">".MetaModel::GetName($sClassName)."</options>\n";
ksort($aOptions);
$sContext = $oAppContext->GetForLink();
$sClassesCombo = "<select name=\"class\" onChange=\"ReloadSearchForm('$sSearchFormId', this.value, '$sRootClass', '$sContext', '{$aExtraParams['result_list_outer_selector']}')\">\n".implode('',
$aOptions)."</select>\n";
$sClassesCombo = $aExtraParams['search_header_force_dropdown'];
}
else
{
$sClassesCombo = MetaModel::GetName($sClassName);
$aSubClasses = MetaModel::GetSubclasses($sRootClass);
if (count($aSubClasses) > 0)
{
$aOptions = array();
$aOptions[MetaModel::GetName($sRootClass)] = "<option value=\"$sRootClass\">".MetaModel::GetName($sRootClass)."</options>\n";
foreach($aSubClasses as $sSubclassName)
{
$aOptions[MetaModel::GetName($sSubclassName)] = "<option value=\"$sSubclassName\">".MetaModel::GetName($sSubclassName)."</options>\n";
}
$aOptions[MetaModel::GetName($sClassName)] = "<option selected value=\"$sClassName\">".MetaModel::GetName($sClassName)."</options>\n";
ksort($aOptions);
$sContext = $oAppContext->GetForLink();
$sClassesCombo = "<select name=\"class\" onChange=\"ReloadSearchForm('$sSearchFormId', this.value, '$sRootClass', '$sContext', '{$aExtraParams['result_list_outer_selector']}')\">\n".implode('',
$aOptions)."</select>\n";
}
else
{
$sClassesCombo = MetaModel::GetName($sClassName);
}
}
$bAutoSubmit = true;