From 4c28d9c34f5f3e5ccbbed6dbb0ba08bc5235b53b Mon Sep 17 00:00:00 2001
From: ftimme <ft@falkotimme.com>
Date: Thu, 10 May 2012 12:24:12 -0400
Subject: [PATCH] - Added global search (FS#2210, FS#2146).
---
interface/web/sites/form/ftp_user.tform.php | 8
interface/web/dns/form/dns_soa.tform.php | 14
interface/web/vm/form/openvz_ostemplate.tform.php | 14
interface/web/client/form/client.tform.php | 44 ++-
interface/web/mail/form/mail_domain.tform.php | 8
interface/web/themes/default/templates/main.tpl.htm | 7
interface/web/sites/ajax_get_json.php | 2
interface/web/vm/form/openvz_vm.tform.php | 14
interface/web/vm/form/openvz_template.tform.php | 11
interface/web/dns/form/dns_slave.tform.php | 11
interface/web/mail/form/mail_user.tform.php | 11
interface/web/vm/form/openvz_ip.tform.php | 8
interface/web/sites/form/database.tform.php | 14
interface/web/themes/default/css/screen/content_ispc.css | 130 +++++++++
interface/web/capp.php | 11
interface/web/themes/default/icons/x16/loading.gif | 0
interface/web/sites/form/shell_user.tform.php | 8
interface/lib/classes/functions.inc.php | 40 +++
interface/web/dashboard/ajax_get_json.php | 197 +++++++++++++++
interface/web/sites/form/web_domain.tform.php | 17 +
interface/web/js/jquery.ispconfigsearch.js | 156 ++++++++++++
interface/web/js/scrigo.js.php | 4
22 files changed, 685 insertions(+), 44 deletions(-)
diff --git a/interface/lib/classes/functions.inc.php b/interface/lib/classes/functions.inc.php
index b744e35..2fe7191 100644
--- a/interface/lib/classes/functions.inc.php
+++ b/interface/lib/classes/functions.inc.php
@@ -109,6 +109,46 @@
return $url;
}
+ function json_encode($data) {
+ if(!function_exists('json_encode')){
+ switch ($type = gettype($data)){
+ case 'NULL':
+ return 'null';
+ case 'boolean':
+ return ($data ? 'true' : 'false');
+ case 'integer':
+ case 'double':
+ case 'float':
+ return $data;
+ case 'string':
+ return '"' . addslashes($data) . '"';
+ case 'object':
+ $data = get_object_vars($data);
+ case 'array':
+ $output_index_count = 0;
+ $output_indexed = array();
+ $output_associative = array();
+ foreach($data as $key => $value){
+ $output_indexed[] = $this->json_encode($value);
+ $output_associative[] = $this->json_encode($key) . ':' . $this->json_encode($value);
+ if($output_index_count !== NULL && $output_index_count++ !== $key){
+ $output_index_count = NULL;
+ }
+ }
+ if($output_index_count !== NULL){
+ return '[' . implode(',', $output_indexed) . ']';
+ } else {
+ return '{' . implode(',', $output_associative) . '}';
+ }
+ default:
+ return ''; // Not supported
+ }
+ } else {
+ return json_encode($data);
+ }
+ }
+
+
}
diff --git a/interface/web/capp.php b/interface/web/capp.php
index 6317734..4512391 100644
--- a/interface/web/capp.php
+++ b/interface/web/capp.php
@@ -33,12 +33,16 @@
//* Import module variable
$mod = $_REQUEST["mod"];
+//* If we click on a search result, load that one instead of the module's start page
+$redirect = (isset($_REQUEST["redirect"]) ? $_REQUEST["redirect"] : '');
//* Check if user is logged in
if($_SESSION["s"]["user"]['active'] != 1) {
die("URL_REDIRECT: /index.php");
//die();
}
+
+if(!preg_match("/^[a-z]{2,20}$/i", $mod)) die('module name contains unallowed chars.');
//* Check if user may use the module.
$user_modules = explode(",",$_SESSION["s"]["user"]["modules"]);
@@ -50,7 +54,12 @@
include_once($mod."/lib/module.conf.php");
$_SESSION["s"]["module"] = $module;
session_write_close();
- echo "HEADER_REDIRECT:".$_SESSION["s"]["module"]["startpage"];
+ if($redirect == ''){
+ echo "HEADER_REDIRECT:".$_SESSION["s"]["module"]["startpage"];
+ } else {
+ //* If we click on a search result, load that one instead of the module's start page
+ echo "HEADER_REDIRECT:".$redirect;
+ }
} else {
$app->error($app->lng(302));
}
diff --git a/interface/web/client/form/client.tform.php b/interface/web/client/form/client.tform.php
index 85b8671..3fca605 100644
--- a/interface/web/client/form/client.tform.php
+++ b/interface/web/client/form/client.tform.php
@@ -29,6 +29,11 @@
Hint:
The ID field of the database table is not part of the datafield definition.
The ID field must be always auto incement (int or bigint).
+
+ Search:
+ - searchable = 1 or searchable = 2 include the field in the search
+ - searchable = 1: this field will be the title of the search result
+ - searchable = 2: this field will be included in the description of the search result
*/
@@ -90,7 +95,8 @@
'width' => '30',
'maxlength' => '255',
'rows' => '',
- 'cols' => ''
+ 'cols' => '',
+ 'searchable' => 2
),
'contact_name' => array (
'datatype' => 'VARCHAR',
@@ -104,7 +110,8 @@
'width' => '30',
'maxlength' => '255',
'rows' => '',
- 'cols' => ''
+ 'cols' => '',
+ 'searchable' => 1
),
'customer_no' => array (
'datatype' => 'VARCHAR',
@@ -115,7 +122,8 @@
'width' => '30',
'maxlength' => '255',
'rows' => '',
- 'cols' => ''
+ 'cols' => '',
+ 'searchable' => 2
),
'username' => array (
'datatype' => 'VARCHAR',
@@ -136,7 +144,8 @@
'width' => '30',
'maxlength' => '255',
'rows' => '',
- 'cols' => ''
+ 'cols' => '',
+ 'searchable' => 2
),
'password' => array (
'datatype' => 'VARCHAR',
@@ -181,7 +190,8 @@
'width' => '30',
'maxlength' => '255',
'rows' => '',
- 'cols' => ''
+ 'cols' => '',
+ 'searchable' => 2
),
'zip' => array (
'datatype' => 'VARCHAR',
@@ -192,7 +202,8 @@
'width' => '10',
'maxlength' => '255',
'rows' => '',
- 'cols' => ''
+ 'cols' => '',
+ 'searchable' => 2
),
'city' => array (
'datatype' => 'VARCHAR',
@@ -203,7 +214,8 @@
'width' => '30',
'maxlength' => '255',
'rows' => '',
- 'cols' => ''
+ 'cols' => '',
+ 'searchable' => 2
),
'state' => array (
'datatype' => 'VARCHAR',
@@ -214,7 +226,8 @@
'width' => '30',
'maxlength' => '255',
'rows' => '',
- 'cols' => ''
+ 'cols' => '',
+ 'searchable' => 2
),
'country' => array (
'datatype' => 'VARCHAR',
@@ -237,7 +250,8 @@
'width' => '30',
'maxlength' => '255',
'rows' => '',
- 'cols' => ''
+ 'cols' => '',
+ 'searchable' => 2
),
'mobile' => array (
'datatype' => 'VARCHAR',
@@ -248,7 +262,8 @@
'width' => '30',
'maxlength' => '255',
'rows' => '',
- 'cols' => ''
+ 'cols' => '',
+ 'searchable' => 2
),
'fax' => array (
'datatype' => 'VARCHAR',
@@ -259,7 +274,8 @@
'width' => '30',
'maxlength' => '255',
'rows' => '',
- 'cols' => ''
+ 'cols' => '',
+ 'searchable' => 2
),
'email' => array (
'datatype' => 'VARCHAR',
@@ -270,7 +286,8 @@
'width' => '30',
'maxlength' => '255',
'rows' => '',
- 'cols' => ''
+ 'cols' => '',
+ 'searchable' => 2
),
'internet' => array (
'datatype' => 'VARCHAR',
@@ -281,7 +298,8 @@
'width' => '30',
'maxlength' => '255',
'rows' => '',
- 'cols' => ''
+ 'cols' => '',
+ 'searchable' => 2
),
'icq' => array (
'datatype' => 'VARCHAR',
diff --git a/interface/web/dashboard/ajax_get_json.php b/interface/web/dashboard/ajax_get_json.php
new file mode 100644
index 0000000..18cd1e4
--- /dev/null
+++ b/interface/web/dashboard/ajax_get_json.php
@@ -0,0 +1,197 @@
+<?php
+
+/*
+Copyright (c) 2012, ISPConfig UG
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of ISPConfig nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+require_once('../../lib/config.inc.php');
+require_once('../../lib/app.inc.php');
+
+//* Check permissions for module
+$app->auth->check_module_permissions('dashboard');
+
+$app->uses('tform');
+
+$type = $_GET["type"];
+
+//if($_SESSION["s"]["user"]["typ"] == 'admin') {
+
+
+ if($type == 'globalsearch'){
+ $q = $app->db->quote($_GET["q"]);
+ $authsql = " AND ".$app->tform->getAuthSQL('r');
+ $modules = explode(',', $_SESSION['s']['user']['modules']);
+
+ // clients
+ $result_clients = _search('client', 'client');
+
+ // web sites
+ $result_webs = _search('sites', 'web_domain');
+
+ // FTP users
+ $result_ftp_users = _search('sites', 'ftp_user');
+
+ // shell users
+ $result_shell_users = _search('sites', 'shell_user');
+
+ // databases
+ /*
+ $result_databases = array('cheader' => array(), 'cdata' => array());
+ if(in_array('sites', $modules)){
+ $sql = "SELECT * FROM web_database WHERE database_name LIKE '%".$q."%' OR database_user LIKE '%".$q."%' OR remote_ips LIKE '%".$q."%'".$authsql." ORDER BY database_name";
+ $results = $app->db->queryAllRecords($sql);
+
+ if(is_array($results) && !empty($results)){
+ $result_databases['cheader'] = array('title' => 'Databases',
+ 'total' => count($results),
+ 'limit' => count($results)
+ );
+ foreach($results as $result){
+ $description = 'Database User: '.$result['database_user'].' - Remote IPs: '.$result['remote_ips'];
+ $result_databases['cdata'][] = array('title' => $result['database_name'],
+ 'description' => $description,
+ 'onclick' => 'capp(\'sites\',\'sites/database_edit.php?id='.$result['database_id'].'\');',
+ 'fill_text' => strtolower($result['database_name'])
+ );
+ }
+ }
+ }
+ */
+ $result_databases = _search('sites', 'database');
+
+ // email domains
+ $result_email_domains = _search('mail', 'mail_domain');
+
+ // email mailboxes
+ $result_email_mailboxes = _search('mail', 'mail_user');
+
+ // dns zones
+ $result_dns_zones = _search('dns', 'dns_soa');
+
+ // secondary dns zones
+ $result_secondary_dns_zones = _search('dns', 'dns_slave');
+
+ // virtual machines
+ $result_vms = _search('vm', 'openvz_vm');
+
+ // virtual machines os templates
+ $result_vm_ostemplates = _search('vm', 'openvz_ostemplate');
+
+ // virtual machines vm templates
+ $result_vm_vmtemplates = _search('vm', 'openvz_template');
+
+ // virtual machines ip addresses
+ $result_vm_ip_addresses = _search('vm', 'openvz_ip');
+
+ $json = $app->functions->json_encode(array($result_clients, $result_webs, $result_ftp_users, $result_shell_users, $result_databases, $result_email_domains, $result_email_mailboxes, $result_dns_zones, $result_secondary_dns_zones, $result_vms, $result_vm_ostemplates, $result_vm_vmtemplates, $result_vm_ip_addresses));
+ }
+
+//}
+
+function _search($module, $section){
+ global $app, $q, $authsql, $modules;
+ //$q = $app->db->quote($_GET["q"]);
+ //$authsql = " AND ".$app->tform->getAuthSQL('r');
+ //$user_modules = explode(',', $_SESSION['s']['user']['modules']);
+
+ $result_array = array('cheader' => array(), 'cdata' => array());
+ if(in_array($module, $modules)){
+ $search_fields = array();
+ $desc_fields = array();
+ if(is_file('../'.$module.'/form/'.$section.'.tform.php')){
+ include_once('../'.$module.'/form/'.$section.'.tform.php');
+
+ $category_title = $form["title"];
+ $form_file = $form["action"];
+ $db_table = $form["db_table"];
+ $db_table_idx = $form["db_table_idx"];
+ $order_by = $db_table_idx;
+
+ if(is_array($form["tabs"]) && !empty($form["tabs"])){
+ foreach($form["tabs"] as $tab){
+ if(is_array($tab['fields']) && !empty($tab['fields'])){
+ foreach($tab['fields'] as $key => $val){
+ if(isset($val['searchable']) && $val['searchable'] > 0){
+ $search_fields[] = $key." LIKE '%".$q."%'";
+ if($val['searchable'] == 1){
+ $order_by = $key;
+ $title_key = $key;
+ }
+ if($val['searchable'] == 2){
+ $desc_fields[] = $key;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ unset($form);
+
+ $where_clause = '';
+ if(!empty($search_fields)){
+ $where_clause = implode(' OR ', $search_fields);
+ } else {
+ // valid SQL query which returns an empty result set
+ $where_clause = '1 = 0';
+ }
+ $order_clause = '';
+ if($order_by != '') $order_clause = ' ORDER BY '.$order_by;
+
+ $results = $app->db->queryAllRecords("SELECT * FROM ".$db_table." WHERE ".$where_clause.$authsql.$order_clause);
+
+ if(is_array($results) && !empty($results)){
+ $lng_file = '../'.$module.'/lib/lang/'.$_SESSION['s']['language'].'_'.$section.'.lng';
+ if(is_file($lng_file)) include($lng_file);
+ $result_array['cheader'] = array('title' => $category_title,
+ 'total' => count($results),
+ 'limit' => count($results)
+ );
+ foreach($results as $result){
+ $description = '';
+ if(!empty($desc_fields)){
+ $desc_items = array();
+ foreach($desc_fields as $desc_field){
+ if($result[$desc_field] != '') $desc_items[] = $wb[$desc_field.'_txt'].': '.$result[$desc_field];
+ }
+ if(!empty($desc_items)) $description = implode(' - ', $desc_items);
+ }
+
+ $result_array['cdata'][] = array('title' => $wb[$title_key.'_txt'].': '.$result[$title_key],
+ 'description' => $description,
+ 'onclick' => "capp('".$module."','".$module."/".$form_file."?id=".$result[$db_table_idx]."');",
+ 'fill_text' => strtolower($result[$title_key])
+ );
+ }
+ }
+ }
+ return $result_array;
+}
+
+header('Content-type: application/json');
+echo $json;
+?>
\ No newline at end of file
diff --git a/interface/web/dns/form/dns_slave.tform.php b/interface/web/dns/form/dns_slave.tform.php
index 097602e..a1dea94 100644
--- a/interface/web/dns/form/dns_slave.tform.php
+++ b/interface/web/dns/form/dns_slave.tform.php
@@ -29,6 +29,11 @@
Hint:
The ID field of the database table is not part of the datafield definition.
The ID field must be always auto incement (int or bigint).
+
+ Search:
+ - searchable = 1 or searchable = 2 include the field in the search
+ - searchable = 1: this field will be the title of the search result
+ - searchable = 2: this field will be included in the description of the search result
*/
@@ -88,7 +93,8 @@
'default' => '',
'value' => '',
'width' => '30',
- 'maxlength' => '255'
+ 'maxlength' => '255',
+ 'searchable' => 1
),
'ns' => array (
'datatype' => 'VARCHAR',
@@ -100,7 +106,8 @@
'default' => '',
'value' => '',
'width' => '30',
- 'maxlength' => '255'
+ 'maxlength' => '255',
+ 'searchable' => 2
),
'xfer' => array (
'datatype' => 'VARCHAR',
diff --git a/interface/web/dns/form/dns_soa.tform.php b/interface/web/dns/form/dns_soa.tform.php
index 53b408e..c102e12 100644
--- a/interface/web/dns/form/dns_soa.tform.php
+++ b/interface/web/dns/form/dns_soa.tform.php
@@ -29,6 +29,11 @@
Hint:
The ID field of the database table is not part of the datafield definition.
The ID field must be always auto incement (int or bigint).
+
+ Search:
+ - searchable = 1 or searchable = 2 include the field in the search
+ - searchable = 1: this field will be the title of the search result
+ - searchable = 2: this field will be included in the description of the search result
*/
@@ -88,7 +93,8 @@
'default' => '',
'value' => '',
'width' => '30',
- 'maxlength' => '255'
+ 'maxlength' => '255',
+ 'searchable' => 1
),
'ns' => array (
'datatype' => 'VARCHAR',
@@ -100,7 +106,8 @@
'default' => '',
'value' => '',
'width' => '30',
- 'maxlength' => '255'
+ 'maxlength' => '255',
+ 'searchable' => 2
),
'mbox' => array (
'datatype' => 'VARCHAR',
@@ -114,7 +121,8 @@
'default' => '',
'value' => '',
'width' => '30',
- 'maxlength' => '255'
+ 'maxlength' => '255',
+ 'searchable' => 2
),
'serial' => array (
'datatype' => 'INTEGER',
diff --git a/interface/web/js/jquery.ispconfigsearch.js b/interface/web/js/jquery.ispconfigsearch.js
new file mode 100644
index 0000000..211dcd7
--- /dev/null
+++ b/interface/web/js/jquery.ispconfigsearch.js
@@ -0,0 +1,156 @@
+/*
+Copyright (c) 2012, ISPConfig UG
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of ISPConfig nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+(function($) {
+ $.fn.ispconfigSearch = function(settings){
+
+ var defaultSettings = {
+ dataSrc: '',
+ timeout: 500,
+ minChars: 2,
+ resultBox: '-resultbox',
+ cssPrefix: 'gs-',
+ fillSearchField: false,
+ fillSearchFieldWith: 'title',
+ resultsText: '$ of % results',
+ noResultsText: 'No results.',
+ displayEmptyCategories: false,
+ runJS: true
+ };
+
+ var previousQ = '';
+ var data;
+ var settings = $.extend(defaultSettings, settings);
+ settings.resultBox = $(this).attr('id')+settings.resultBox;
+
+ $(this).attr('autocomplete', 'off');
+ $(this).wrap('<div class="'+settings.cssPrefix+'container" />');
+ $(this).after('<ul id="'+settings.resultBox+'" class="'+settings.cssPrefix+'resultbox" style="display:none;"></ul>');
+ var searchField = $(this);
+ var resultBox = $('#'+settings.resultBox);
+
+ var timeout = null;
+ searchField.keyup(function(event) {
+ // 13 = enter, 9 = tab
+ if (event.keyCode != 13 && event.keyCode != 9){
+ // query value
+ var q = searchField.val();
+
+ if (settings.minChars > q.length || q == ''){
+ resultBox.fadeOut();
+ resetTimer(timeout);
+ } else {
+ if (timeout != null){
+ resetTimer(timeout);
+ }
+
+ timeout = setTimeout(function(){
+ searchField.addClass(settings.cssPrefix+'loading');
+
+ // we don't have to perform a new search if the query equals the previous query
+ previousQ = q;
+ var queryStringCombinator = '?';
+ if(settings.dataSrc.indexOf('?') != -1){
+ queryStringCombinator = '&';
+ }
+ $.getJSON(settings.dataSrc+queryStringCombinator+"q="+q, function(data, textStatus){
+ if (textStatus == 'success'){
+ var output = '';
+ var resultsFound = false;
+
+ if($.isEmptyObject(data) === false){
+ $.each(data, function(i, category){
+ if (category['cdata'].length > 0){
+ resultsFound = true;
+ }
+ });
+ }
+
+ if (!resultsFound){
+ output += '<li class="'+settings.cssPrefix+'cheader"><p class="'+settings.cssPrefix+'cheader-title">'+settings.noResultsText+'</p><p class="'+settings.cssPrefix+'cheader-limit">0 results</p></li>';
+ } else {
+
+ $.each(data, function(i, category){
+
+ if (settings.displayEmptyCategories || (!settings.displayEmptyCategories && category['cdata'].length != 0)){
+ var limit = category['cheader']['limit'];
+ var cnt = 0;
+
+ output += '<li class="'+settings.cssPrefix+'cheader"><p class="'+settings.cssPrefix+'cheader-title">'+category['cheader']['title']+'</p><p class="'+settings.cssPrefix+'cheader-limit">'+settings.resultsText.replace("%", category['cheader']['total']).replace("$", (category['cheader']['limit'] < category['cdata'].length ? category['cheader']['limit'] : category['cdata'].length))+'</p></li>';
+
+ var fillSearchFieldCode = (settings.fillSearchField) ? 'document.getElementById(\''+searchField.attr('id')+'\').value = \'%\';' : '';
+ //var fillSearchFieldCode = 'document.getElementById(\''+searchField.attr('id')+'\').value = \'%\';';
+
+ $.each(category['cdata'], function (j, item){
+ if (cnt < limit){
+ //var link = '<a href="'+((item['url'] != undefined) ? item['url'] : 'javascript:void(0);')+'" '+((item['onclick'] != undefined) ? ' onclick="'+fillSearchFieldCode.replace("%", ((settings.fillSearchField) ? item[settings.fillSearchFieldWith] : ''))+(settings.runJS ? item['onclick'] : '')+'"' : '')+((item['target'] != undefined) ? ' target="'+item['target']+'"' : '')+'>';
+ var link = '<a href="'+((item['url'] != undefined) ? item['url'] : 'javascript:void(0);')+'" '+((item['onclick'] != undefined) ? ' onclick="'+fillSearchFieldCode.replace("%", item[settings.fillSearchFieldWith])+(settings.runJS ? item['onclick'] : '')+'"' : '')+((item['target'] != undefined) ? ' target="'+item['target']+'"' : '')+'>';
+
+ output += '<li class="'+settings.cssPrefix+'cdata">'+link+"\n";
+ output += '<table border="0" cellspacing="0" cellpadding="0" width="100%"><tr><td>';
+ output += '<p>';
+ output += (item['title'] != undefined) ? '<span class="'+settings.cssPrefix+'cdata-title">'+item['title']+"</span><br />\n" : '';
+ output += (item['description'] != undefined) ? ''+item['description']+''+"\n" : '';
+ output += '</p>'+"\n";
+ output += '</td></tr></table>';
+ output += '</a></li>'+"\n";
+ }
+ cnt++;
+ });
+ }
+ });
+ }
+
+ resultBox.html(output).css({'position' : 'absolute', 'top' : searchField.position().top+searchField.outerHeight(), 'right' : '0'}).fadeIn();
+
+ searchField.removeClass(settings.cssPrefix+'loading');
+ }
+ });
+ }, settings.timeout);
+ }
+ }
+ });
+
+ searchField.blur(function(){
+ resultBox.fadeOut();
+ });
+
+ searchField.focus(function(){
+ if (searchField.val() == previousQ && searchField.val() != ''){
+ resultBox.fadeIn();
+ } else if (searchField.val() != ''){
+ searchField.trigger('keyup');
+ }
+ });
+
+ };
+
+ function resetTimer(timeout){
+ clearTimeout(timeout);
+ timeout = null;
+ };
+})(jQuery);
\ No newline at end of file
diff --git a/interface/web/js/scrigo.js.php b/interface/web/js/scrigo.js.php
index 25e2128..f8120e8 100644
--- a/interface/web/js/scrigo.js.php
+++ b/interface/web/js/scrigo.js.php
@@ -33,10 +33,10 @@
}
}
-function capp(module) {
+function capp(module, redirect) {
var submitFormObj = jQuery.ajax({ type: "GET",
url: "capp.php",
- data: "mod="+module,
+ data: "mod="+module+((redirect != undefined) ? '&redirect='+redirect : ''),
dataType: "html",
success: function(data, textStatus, jqXHR) {
if(jqXHR.responseText != '') {
diff --git a/interface/web/mail/form/mail_domain.tform.php b/interface/web/mail/form/mail_domain.tform.php
index 7bebe7e..fd0c287 100644
--- a/interface/web/mail/form/mail_domain.tform.php
+++ b/interface/web/mail/form/mail_domain.tform.php
@@ -29,6 +29,11 @@
Hint:
The ID field of the database table is not part of the datafield definition.
The ID field must be always auto incement (int or bigint).
+
+ Search:
+ - searchable = 1 or searchable = 2 include the field in the search
+ - searchable = 1: this field will be the title of the search result
+ - searchable = 2: this field will be included in the description of the search result
*/
@@ -83,7 +88,8 @@
'default' => '',
'value' => '',
'width' => '30',
- 'maxlength' => '255'
+ 'maxlength' => '255',
+ 'searchable' => 1
),
'active' => array (
'datatype' => 'VARCHAR',
diff --git a/interface/web/mail/form/mail_user.tform.php b/interface/web/mail/form/mail_user.tform.php
index b70d656..c9353ed 100644
--- a/interface/web/mail/form/mail_user.tform.php
+++ b/interface/web/mail/form/mail_user.tform.php
@@ -29,6 +29,11 @@
Hint:
The ID field of the database table is not part of the datafield definition.
The ID field must be always auto incement (int or bigint).
+
+ Search:
+ - searchable = 1 or searchable = 2 include the field in the search
+ - searchable = 1: this field will be the title of the search result
+ - searchable = 2: this field will be included in the description of the search result
*/
@@ -77,7 +82,8 @@
'default' => '',
'value' => '',
'width' => '30',
- 'maxlength' => '255'
+ 'maxlength' => '255',
+ 'searchable' => 1
),
'login' => array (
'datatype' => 'VARCHAR',
@@ -109,7 +115,8 @@
'default' => '',
'value' => '',
'width' => '30',
- 'maxlength' => '255'
+ 'maxlength' => '255',
+ 'searchable' => 2
),
'quota' => array (
'datatype' => 'INTEGER',
diff --git a/interface/web/sites/ajax_get_json.php b/interface/web/sites/ajax_get_json.php
index 8c7b738..887f5da 100644
--- a/interface/web/sites/ajax_get_json.php
+++ b/interface/web/sites/ajax_get_json.php
@@ -101,6 +101,6 @@
}
//}
-
+header('Content-type: application/json');
echo $json;
?>
\ No newline at end of file
diff --git a/interface/web/sites/form/database.tform.php b/interface/web/sites/form/database.tform.php
index 9bef109..b26a1e4 100644
--- a/interface/web/sites/form/database.tform.php
+++ b/interface/web/sites/form/database.tform.php
@@ -29,6 +29,11 @@
Hint:
The ID field of the database table is not part of the datafield definition.
The ID field must be always auto incement (int or bigint).
+
+ Search:
+ - searchable = 1 or searchable = 2 include the field in the search
+ - searchable = 1: this field will be the title of the search result
+ - searchable = 2: this field will be included in the description of the search result
*/
@@ -98,7 +103,8 @@
'default' => '',
'value' => '',
'width' => '30',
- 'maxlength' => '255'
+ 'maxlength' => '255',
+ 'searchable' => 1
),
'database_user' => array (
'datatype' => 'VARCHAR',
@@ -114,7 +120,8 @@
'default' => '',
'value' => '',
'width' => '30',
- 'maxlength' => '255'
+ 'maxlength' => '255',
+ 'searchable' => 2
),
'database_password' => array (
'datatype' => 'VARCHAR',
@@ -153,7 +160,8 @@
),
'default' => '',
'value' => '',
- 'width' => '60'
+ 'width' => '60',
+ 'searchable' => 2
),
##################################
# ENDE Datatable fields
diff --git a/interface/web/sites/form/ftp_user.tform.php b/interface/web/sites/form/ftp_user.tform.php
index 3450764..3f71828 100644
--- a/interface/web/sites/form/ftp_user.tform.php
+++ b/interface/web/sites/form/ftp_user.tform.php
@@ -29,6 +29,11 @@
Hint:
The ID field of the database table is not part of the datafield definition.
The ID field must be always auto incement (int or bigint).
+
+ Search:
+ - searchable = 1 or searchable = 2 include the field in the search
+ - searchable = 1: this field will be the title of the search result
+ - searchable = 2: this field will be included in the description of the search result
*/
@@ -92,7 +97,8 @@
'default' => '',
'value' => '',
'width' => '30',
- 'maxlength' => '255'
+ 'maxlength' => '255',
+ 'searchable' => 1
),
'password' => array (
'datatype' => 'VARCHAR',
diff --git a/interface/web/sites/form/shell_user.tform.php b/interface/web/sites/form/shell_user.tform.php
index ec7b612..061dd29 100644
--- a/interface/web/sites/form/shell_user.tform.php
+++ b/interface/web/sites/form/shell_user.tform.php
@@ -29,6 +29,11 @@
Hint:
The ID field of the database table is not part of the datafield definition.
The ID field must be always auto incement (int or bigint).
+
+ Search:
+ - searchable = 1 or searchable = 2 include the field in the search
+ - searchable = 1: this field will be the title of the search result
+ - searchable = 2: this field will be included in the description of the search result
*/
@@ -92,7 +97,8 @@
'default' => '',
'value' => '',
'width' => '30',
- 'maxlength' => '255'
+ 'maxlength' => '255',
+ 'searchable' => 1
),
'password' => array (
'datatype' => 'VARCHAR',
diff --git a/interface/web/sites/form/web_domain.tform.php b/interface/web/sites/form/web_domain.tform.php
index ce835a9..d97d78b 100644
--- a/interface/web/sites/form/web_domain.tform.php
+++ b/interface/web/sites/form/web_domain.tform.php
@@ -29,6 +29,11 @@
Hint:
The ID field of the database table is not part of the datafield definition.
The ID field must be always auto incement (int or bigint).
+
+ Search:
+ - searchable = 1 or searchable = 2 include the field in the search
+ - searchable = 1: this field will be the title of the search result
+ - searchable = 2: this field will be included in the description of the search result
*/
@@ -87,7 +92,8 @@
'keyfield'=> 'ip_address',
'valuefield'=> 'ip_address'
),*/
- 'value' => ''
+ 'value' => '',
+ 'searchable' => 2
),
'ipv6_address' => array (
'datatype' => 'VARCHAR',
@@ -98,7 +104,8 @@
'keyfield'=> 'ip_address',
'valuefield'=> 'ip_address'
),*/
- 'value' => ''
+ 'value' => '',
+ 'searchable' => 2
),
'domain' => array (
'datatype' => 'VARCHAR',
@@ -114,7 +121,8 @@
'default' => '',
'value' => '',
'width' => '30',
- 'maxlength' => '255'
+ 'maxlength' => '255',
+ 'searchable' => 1
),
'type' => array (
'datatype' => 'VARCHAR',
@@ -208,7 +216,8 @@
'formtype' => 'SELECT',
'default' => 'fast-cgi',
'valuelimit' => 'client:web_php_options',
- 'value' => array('no' => 'disabled_txt', 'fast-cgi' => 'Fast-CGI', 'cgi' => 'CGI', 'mod' => 'Mod-PHP', 'suphp' => 'SuPHP', 'php-fpm' => 'PHP-FPM')
+ 'value' => array('no' => 'disabled_txt', 'fast-cgi' => 'Fast-CGI', 'cgi' => 'CGI', 'mod' => 'Mod-PHP', 'suphp' => 'SuPHP', 'php-fpm' => 'PHP-FPM'),
+ 'searchable' => 2
),
'fastcgi_php_version' => array (
'datatype' => 'VARCHAR',
diff --git a/interface/web/themes/default/css/screen/content_ispc.css b/interface/web/themes/default/css/screen/content_ispc.css
index 796cd57..bb8b836 100644
--- a/interface/web/themes/default/css/screen/content_ispc.css
+++ b/interface/web/themes/default/css/screen/content_ispc.css
@@ -993,6 +993,134 @@
-ms-transform:rotate(90deg);
transform:rotate(90deg);
}
-
+
+ div.gs-container{
+ margin-top:10px;
+ }
+ div.gs-container *{
+ margin: 0;
+ padding: 0;
+ background-position: 0 0;
+ text-decoration: none;
+ font-size: 1em;
+ }
+ input.gs-loading{
+ background-image: url(../../icons/x16/loading.gif);
+ background-repeat: no-repeat;
+ background-position: center right;
+ }
+ ul.gs-resultbox{
+ margin: 0 !important;
+ padding: 0 !important;
+ width: 300px;
+ z-index: 999999;
+ border: 1px solid #aaa;
+ font-size: 11px;
+ background: #fff;
+ -moz-box-shadow: 2px 2px 5px 0 #c5c5c5;
+ -webkit-box-shadow: 2px 2px 5px 0 #c5c5c5;
+ -khtml-box-shadow: 2px 2px 5px 0 #c5c5c5;
+ -o-box-shadow: 2px 2px 5px 0 #c5c5c5;
+ -ms-box-shadow: 2px 2px 5px 0 #c5c5c5;
+ box-shadow: 2px 2px 5px 0 #c5c5c5;
+ list-style: none;
+ /*
+ -moz-border-radius-bottomleft:10px;
+ -webkit-border-bottom-left-radius:10px;
+ -khtml-border-bottom-left-radius:10px;
+ -o-border-bottom-left-radius:10px;
+ -ms-border-bottom-left-radius:10px;
+ border-bottom-left-radius:10px;
+ -moz-border-radius-bottomright:10px;
+ -webkit-border-bottom-right-radius:10px;
+ -khtml-border-bottom-right-radius:10px;
+ -o-border-bottom-right-radius:10px;
+ -ms-border-bottom-right-radius:10px;
+ border-bottom-right-radius:10px;
+ */
+ }
+ ul.gs-resultbox li{
+ float: left;
+ width: 100%;
+ clear: both;
+ cursor: pointer;
+ }
+ /*
+ ul.gs-resultbox li:last-child{
+ -moz-border-radius-bottomleft:10px;
+ -webkit-border-bottom-left-radius:10px;
+ -khtml-border-bottom-left-radius:10px;
+ -o-border-bottom-left-radius:10px;
+ -ms-border-bottom-left-radius:10px;
+ border-bottom-left-radius:10px;
+ -moz-border-radius-bottomright:10px;
+ -webkit-border-bottom-right-radius:10px;
+ -khtml-border-bottom-right-radius:10px;
+ -o-border-bottom-right-radius:10px;
+ -ms-border-bottom-right-radius:10px;
+ border-bottom-right-radius:10px;
+ }
+ */
+ ul.gs-resultbox li.gs-cheader{
+ height: 13px;
+ overflow: hidden;
+ padding: 5px 0;
+ color: #fff;
+ background: #6ea6d1;
+ cursor:default;
+ padding-bottom:10px;
+ }
+ ul.gs-resultbox li.gs-cheader p.gs-cheader-title{
+ margin: 0 !important;
+ padding: 0 0 0 10px !important;
+ float: left;
+ font-size: 12px;
+ font-weight: bold;
+ }
+ ul.gs-resultbox li.gs-cheader p.gs-cheader-limit{
+ margin: 0 !important;
+ padding: 0 10px 0 0 !important;
+ float: right;
+ font-size: 11px;
+ font-weight: normal;
+ }
+ ul.gs-resultbox li.gs-cdata{
+ margin: 0 !important;
+ padding: 0 !important;
+ border-bottom: 1px solid #c5c5c5;
+ }
+ ul.gs-resultbox li.gs-cdata:last-child{
+ border-bottom: none;
+ }
+ ul.gs-resultbox li.gs-cdata:hover{
+ background: #eaf4fd;
+ }
+ ul.gs-resultbox li.gs-cdata a{
+ display: block;
+ padding: 5px 10px;
+ text-decoration: none !important;
+ background: #fff;
+ }
+ ul.gs-resultbox li.gs-cdata a:hover{
+ background: #cde0ff;
+ }
+ ul.gs-resultbox li.gs-cdata img{
+ margin-right: 12px;
+ }
+ ul.gs-resultbox li.gs-cdata p{
+ margin: 0 !important;
+ padding: 0 !important;
+ color: #444;
+ font-size: 10px;
+ min-height:30px;
+ }
+ ul.gs-resultbox li.gs-cdata p span.gs-cdata-title{
+ display: inline !important;
+ margin: 0 !important;
+ padding: 0 !important;
+ font-size: 11px;
+ font-weight: bold;
+ color: #000;
+ }
}
diff --git a/interface/web/themes/default/icons/x16/loading.gif b/interface/web/themes/default/icons/x16/loading.gif
new file mode 100644
index 0000000..19afda1
--- /dev/null
+++ b/interface/web/themes/default/icons/x16/loading.gif
Binary files differ
diff --git a/interface/web/themes/default/templates/main.tpl.htm b/interface/web/themes/default/templates/main.tpl.htm
index 1854b50..b012c06 100644
--- a/interface/web/themes/default/templates/main.tpl.htm
+++ b/interface/web/themes/default/templates/main.tpl.htm
@@ -60,6 +60,7 @@
<script type="text/javascript" src="js/jquery-ui-1.8.16.custom.min.js"></script>
<script type="text/javascript" src="js/scrigo.js.php"></script>
<script type="text/javascript" src="js/uni-form/uni-form.jquery.js"></script>
+ <script type="text/javascript" src="js/jquery.ispconfigsearch.js"></script>
<script language="JavaScript" type="text/javascript">
var is_chrome = navigator.userAgent.toLowerCase().indexOf('chrome') > -1;
if(!is_chrome && getInternetExplorerVersion() > 8.0) {
@@ -81,6 +82,11 @@
jQuery('.subsectiontoggle').live("click", function(){
jQuery(this).children().toggleClass('showing').end().next().slideToggle();
});
+
+ jQuery('#globalsearch').ispconfigSearch({
+ dataSrc: '/dashboard/ajax_get_json.php?type=globalsearch'
+ });
+
});
@@ -109,6 +115,7 @@
<!-- end: skip link navigation -->
<tmpl_if name="cpuser">
<span><a href="#logout" onclick="loadContent('login/logout.php');"><tmpl_var name="logout_txt"> <tmpl_var format="strtoupper" name="cpuser"></a><!-- | <a href="#" onclick="capp('help')">Help</a> | <a href="#">Imprint</a>--></span>
+ <input type="text" id="globalsearch" size="30" value="" />
</tmpl_if>
</div>
<h1 id="ir-HeaderLogo" class="swap" style="background-image:url('{tmpl_var name='app_logo'}');"><span>ISPConfig 3</span></h1>
diff --git a/interface/web/vm/form/openvz_ip.tform.php b/interface/web/vm/form/openvz_ip.tform.php
index 78b9d94..ca958b3 100644
--- a/interface/web/vm/form/openvz_ip.tform.php
+++ b/interface/web/vm/form/openvz_ip.tform.php
@@ -29,6 +29,11 @@
Hint:
The ID field of the database table is not part of the datafield definition.
The ID field must be always auto incement (int or bigint).
+
+ Search:
+ - searchable = 1 or searchable = 2 include the field in the search
+ - searchable = 1: this field will be the title of the search result
+ - searchable = 2: this field will be included in the description of the search result
*/
@@ -83,7 +88,8 @@
'width' => '15',
'maxlength' => '15',
'rows' => '',
- 'cols' => ''
+ 'cols' => '',
+ 'searchable' => 1
),
'vm_id' => array (
'datatype' => 'INTEGER',
diff --git a/interface/web/vm/form/openvz_ostemplate.tform.php b/interface/web/vm/form/openvz_ostemplate.tform.php
index 6b9be3f..0224ffa 100644
--- a/interface/web/vm/form/openvz_ostemplate.tform.php
+++ b/interface/web/vm/form/openvz_ostemplate.tform.php
@@ -29,6 +29,11 @@
Hint:
The ID field of the database table is not part of the datafield definition.
The ID field must be always auto incement (int or bigint).
+
+ Search:
+ - searchable = 1 or searchable = 2 include the field in the search
+ - searchable = 1: this field will be the title of the search result
+ - searchable = 2: this field will be included in the description of the search result
*/
@@ -67,7 +72,8 @@
'default' => '',
'value' => '',
'width' => '30',
- 'maxlength' => '255'
+ 'maxlength' => '255',
+ 'searchable' => 1
),
'template_file' => array (
'datatype' => 'VARCHAR',
@@ -78,7 +84,8 @@
'default' => '',
'value' => '',
'width' => '30',
- 'maxlength' => '255'
+ 'maxlength' => '255',
+ 'searchable' => 2
),
'server_id' => array (
'datatype' => 'INTEGER',
@@ -112,7 +119,8 @@
'width' => '',
'maxlength' => '',
'rows' => '10',
- 'cols' => '30'
+ 'cols' => '30',
+ 'searchable' => 2
),
##################################
# ENDE Datatable fields
diff --git a/interface/web/vm/form/openvz_template.tform.php b/interface/web/vm/form/openvz_template.tform.php
index 845d2bc..39cd3ae 100644
--- a/interface/web/vm/form/openvz_template.tform.php
+++ b/interface/web/vm/form/openvz_template.tform.php
@@ -29,6 +29,11 @@
Hint:
The ID field of the database table is not part of the datafield definition.
The ID field must be always auto incement (int or bigint).
+
+ Search:
+ - searchable = 1 or searchable = 2 include the field in the search
+ - searchable = 1: this field will be the title of the search result
+ - searchable = 2: this field will be included in the description of the search result
*/
@@ -67,7 +72,8 @@
'default' => '',
'value' => '',
'width' => '30',
- 'maxlength' => '255'
+ 'maxlength' => '255',
+ 'searchable' => 1
),
'diskspace' => array (
'datatype' => 'INTEGER',
@@ -169,7 +175,8 @@
'default' => '8.8.8.8 8.8.4.4',
'value' => '',
'width' => '30',
- 'maxlength' => '255'
+ 'maxlength' => '255',
+ 'searchable' => 2
),
'active' => array (
'datatype' => 'VARCHAR',
diff --git a/interface/web/vm/form/openvz_vm.tform.php b/interface/web/vm/form/openvz_vm.tform.php
index 3d75e84..ac7e8ef 100644
--- a/interface/web/vm/form/openvz_vm.tform.php
+++ b/interface/web/vm/form/openvz_vm.tform.php
@@ -29,6 +29,11 @@
Hint:
The ID field of the database table is not part of the datafield definition.
The ID field must be always auto incement (int or bigint).
+
+ Search:
+ - searchable = 1 or searchable = 2 include the field in the search
+ - searchable = 1: this field will be the title of the search result
+ - searchable = 2: this field will be included in the description of the search result
*/
@@ -105,7 +110,8 @@
'keyfield'=> 'ip_address',
'valuefield'=> 'ip_address'
),
- 'value' => ''
+ 'value' => '',
+ 'searchable' => 2
),
'hostname' => array (
'datatype' => 'VARCHAR',
@@ -116,7 +122,8 @@
'default' => '',
'value' => '',
'width' => '30',
- 'maxlength' => '255'
+ 'maxlength' => '255',
+ 'searchable' => 1
),
'vm_password' => array (
'datatype' => 'VARCHAR',
@@ -158,7 +165,8 @@
'width' => '',
'maxlength' => '',
'rows' => '10',
- 'cols' => '30'
+ 'cols' => '30',
+ 'searchable' => 2
),
##################################
# ENDE Datatable fields
--
Gitblit v1.9.1