From 32ed65d3493807525e74f8e015656da8489eec00 Mon Sep 17 00:00:00 2001 From: Peter Rotich <peter@osticket.com> Date: Mon, 9 Apr 2012 11:07:27 -0400 Subject: [PATCH] Advanced search initial changes --- include/ajax.config.php | 2 +- include/ajax.tickets.php | 51 +++++++++++- include/staff/tickets.inc.php | 112 +++++++++++++++++++++++-- scp/ajax.php | 7 +- scp/css/scp.css | 153 ++++++++++++++++++++++++++++++++++ scp/images/ajax-loader.gif | Bin 0 -> 1849 bytes scp/js/scp.js | 84 ++++++++++++++++++- 7 files changed, 395 insertions(+), 14 deletions(-) create mode 100644 scp/images/ajax-loader.gif diff --git a/include/ajax.config.php b/include/ajax.config.php index 7dcfd9972..fc9fb2c3f 100644 --- a/include/ajax.config.php +++ b/include/ajax.config.php @@ -19,7 +19,7 @@ if(!defined('INCLUDE_DIR')) die('!'); class ConfigAjaxAPI extends AjaxController { //config info UI might need. - function ui() { + function scp_ui() { global $thisstaff, $cfg; $config=array('ticket_lock_time'=>($cfg->getLockTime()*3600), diff --git a/include/ajax.tickets.php b/include/ajax.tickets.php index 458e430ea..648edc825 100644 --- a/include/ajax.tickets.php +++ b/include/ajax.tickets.php @@ -20,11 +20,11 @@ include_once(INCLUDE_DIR.'class.ticket.php'); class TicketsAjaxAPI extends AjaxController { - function search() { + function lookup() { global $thisstaff; if(!is_numeric($_REQUEST['q'])) - return self::searchByEmail(); + return self::lookupByEmail(); $limit = isset($_REQUEST['limit']) ? (int) $_REQUEST['limit']:25; @@ -53,7 +53,7 @@ class TicketsAjaxAPI extends AjaxController { return $this->json_encode($tickets); } - function searchByEmail() { + function lookupByEmail() { global $thisstaff; @@ -84,6 +84,51 @@ class TicketsAjaxAPI extends AjaxController { return $this->json_encode($tickets); } + function search() { + global $thisstaff; + + $result=array(); + $sql='SELECT count(ticket_id) as tickets ' + .' FROM '.TICKET_TABLE + .' WHERE 1 '; + + //Access control. + $sql.=' AND ( staff_id='.db_input($thisstaff->getId()); + + if(($teams=$thisstaff->getTeams()) && count(array_filter($teams))) + $sql.=' OR team_id IN('.implode(',', array_filter($teams)).')'; + + if(!$thisstaff->showAssignedOnly() && ($depts=$thisstaff->getDepts())) + $sql.=' OR dept_id IN ('.implode(',', $depts).')'; + + $sql.=' ) '; + + //Department + if($_REQUEST['deptId']) + $sql.=' AND dept_id='.db_input($_REQUEST['deptId']); + + //Status + switch(strtolower($_REQUEST['status'])) { + case 'open'; + $sql.=' AND status="open" '; + break; + case 'overdue': + $sql.=' AND status="open" and isoverdue=1 '; + break; + case 'closed': + $sql.=' AND status="closed" '; + break; + } + + if(($tickets=db_result(db_query($sql)))) { + $result['success'] ="Search criteria matched $tickets tickets - view"; + } else { + $result['fail']='No tickets found matching your search criteria.'.$tickets; + } + + return $this->json_encode($result); + } + function acquireLock($tid) { global $cfg,$thisstaff; diff --git a/include/staff/tickets.inc.php b/include/staff/tickets.inc.php index 67d270c3f..c60bdc750 100644 --- a/include/staff/tickets.inc.php +++ b/include/staff/tickets.inc.php @@ -97,9 +97,6 @@ $deep_search=false; if($search): $qstr.='&a='.urlencode($_REQUEST['a']); $qstr.='&t='.urlencode($_REQUEST['t']); - if(isset($_REQUEST['advance_search'])){ //advance search box! - $qstr.='&advance_search=Search'; - } //query if($searchTerm){ @@ -250,12 +247,10 @@ if(!$results_type) { } $negorder=$order=='DESC'?'ASC':'DESC'; //Negate the sorting.. -$basic_display=!isset($_REQUEST['advance_search'])?true:false; - //YOU BREAK IT YOU FIX IT. ?> <!-- SEARCH FORM START --> -<div id='basic' style="display:<?php echo $basic_display?'block':'none'; ?>"> +<div id='basic_search'> <form action="tickets.php" method="get"> <input type="hidden" name="a" value="search"> <table> @@ -263,6 +258,7 @@ $basic_display=!isset($_REQUEST['advance_search'])?true:false; <td><input type="text" id="basic-ticket-search" name="query" size=30 value="<?php echo Format::htmlchars($_REQUEST['query']); ?>" autocomplete="off" autocorrect="off" autocapitalize="off"></td> <td><input type="submit" name="basic_search" class="button" value="Search"></td> + <td> <a href="" id="go-advanced">[advanced]</a></td> </tr> </table> </form> @@ -449,3 +445,107 @@ $basic_display=!isset($_REQUEST['advance_search'])?true:false; } ?> </form> </div> +<div id="overlay"></div> +<div style="display:none;" id="advanced-search"> + <h3>Advanced Ticket Search</h3> + <a class="close" href="">×</a> + <form action="tickets.php" method="post" id="search" name="search"> + <input type="hidden" name="a" value="search"> + <fieldset class="query"> + <label for="query">Keyword:</label> + <input type="input" id="query" name="query" size="20"> <em>Optional</em> + </fieldset> + <fieldset> + <label for="status">Status:</label> + <select id="status" name="status"> + <option value="">— Any Status —</option> + <option value="open">Open</option> + <option value="overdue">Overdue</option> + <option value="closed">Closed</option> + </select> + <label for="deptId">Dept:</label> + <select id="deptId" name="deptId"> + <option value="">— All Departments —</option> + <?php + if(($mydepts = $thisstaff->getDepts()) && ($depts=Dept::getDepartments())) { + foreach($depts as $id =>$name) { + if(!in_array($id, $mydepts)) continue; + echo sprintf('<option value="%d">%s</option>', $id, $name); + } + } + ?> + </select> + </fieldset> + <fieldset class="owner"> + <label for="assigneeId">Assigned To:</label> + <select id="assigneeId" name="assigneeId"> + <option value="0">— Anyone —</option> + <?php + if(($users=Staff::getStaffMembers())) { + echo '<OPTGROUP label="Staff Members ('.count($users).')">'; + foreach($users as $id => $name) { + $k="s$id"; + echo sprintf('<option value="%s">%s</option>', $k, $name); + } + echo '</OPTGROUP>'; + } + + if(($teams=Team::getTeams())) { + echo '<OPTGROUP label="Teams ('.count($teams).')">'; + foreach($teams as $id => $name) { + $k="t$id"; + echo sprintf('<option value="%s">%s</option>', $k, $name); + } + echo '</OPTGROUP>'; + } + ?> + </select> + <label for="staffId">Closed By:</label> + <select id="staffId" name="staffId"> + <option value="0">— Anyone —</option> + <?php + if(($users=Staff::getStaffMembers())) { + foreach($users as $id => $name) { + $k="s$id"; + echo sprintf('<option value="%s">%s</option>', $k, $name); + } + } + ?> + </select> + </fieldset> + <fieldset class="date_range"> + <label>Date Range:</label> + <input class="dp" type="input" size="20" name="startDate"><i></i> + <span>TO</span> + <input class="dp" type="input" size="20" name="endDate"><i></i> + </fieldset> + <fieldset class="sorting"> + <label>Sorting:</label> + <select name="sort"> + <option value="date">Create Date</option> + </select> + <select name="order"> + <option value="desc">Descending</option> + <option value="asc">Ascending</option> + </select> + <select name="limit"> + <option value="25">25 records/page</option> + <option value="50" selected="selected">50 records/page</option> + <option value="75">75 records/page</option> + <option value="100">100 records/page</option> + </select> + </fieldset> + <p> + <span class="buttons"> + <input type="submit" value="Search"> + <input type="reset" value="Reset"> + <input type="button" value="Cancel" class="close"> + </span> + <span class="spinner"> + <img src="./images/ajax-loader.gif" width="16" height="16"> + </span> + </p> + </form> + <div id="result-count"> + </div> +</div> diff --git a/scp/ajax.php b/scp/ajax.php index 471e9c710..2b08168ad 100644 --- a/scp/ajax.php +++ b/scp/ajax.php @@ -43,10 +43,13 @@ $dispatcher = patterns('', url_get('^ticket_variables', 'ticket_variables') )), url('^/config/', patterns('ajax.config.php:ConfigAjaxAPI', - url_get('^ui', 'ui') + url_get('^ui', 'scp_ui') )), url_get('^/users$', array('ajax.users.php:UsersAjaxAPI', 'search')), - url_get('^/tickets$', array('ajax.tickets.php:TicketsAjaxAPI', 'search')), + url('^/tickets', patterns('ajax.tickets.php:TicketsAjaxAPI', + url_get('^/lookup', 'lookup'), + url_get('^$', 'search') + )), url('^/ticket/', patterns('ajax.tickets.php:TicketsAjaxAPI', url_get('^(?P<tid>\d+)/preview', 'previewTicket'), url_get('^(?P<tid>\d+)/lock', 'acquireLock'), diff --git a/scp/css/scp.css b/scp/css/scp.css index 5ccdbe543..de333413a 100644 --- a/scp/css/scp.css +++ b/scp/css/scp.css @@ -1060,3 +1060,156 @@ h2 .reload { padding-left: 24px; background: url('../images/icons/page.png') 0 50% no-repeat; } + + +/* Advanced Ticket Search */ + +#overlay { + background:#000; + position:absolute; + display:none; + z-index:1000; +} + +#advanced-search, #advanced-search * { + box-sizing: border-box; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; +} + +#advanced-search { + position:absolute; + padding:1em; + width:640px; + height:400px; + background:#fff; + border:1px solid #2a67ac; + display:none; + z-index:1200; +} + +#advanced-search h3 { + color:#2a67ac; + font-size:20px; + margin:0; + padding:0; + display:inline-block; +} + +#advanced-search a.close { + display:inline-block; + float:right; + font-size:16px; + color:#777; +} + +#advanced-search form { + clear:both; + padding:2em 0 1em 0; + width:100%; +} + +#advanced-search div.closed_by, #advanced-search span.spinner { + display:none; +} + +#advanced-search fieldset { + margin:0; + padding:0.25em 0; + border:none; + overflow:hidden; +} + +#advanced-search label { + width:100px; + display:inline-block; + text-align:right; + padding:10px; +} + +#advanced-search fieldset input { + border:1px solid #ccc; + background:#fff; +} + +#advanced-search fieldset select { + width:170px; + display:inline-block; +} + +#advanced-search fieldset span { + width:50px; + display:inline-block; + text-align:center; + color:#777; + font-size:0.75em; +} + +#advanced-search .query input { + width:350px; +} + +#advanced-search .date_range input { + width:175px; +} + +#advanced-search .date_range i { + display:inline-block; + margin-left:3px; + position:relative; + top:5px; + width:16px; + height:16px; + background:url(../images/cal.png) bottom left no-repeat; +} + +#advanced-search fieldset.sorting select { + width:130px; +} + +#advanced-search p { + text-align:center; +} + +#advanced-search input[type="submit"], +#advanced-search input[type="reset"], +#advanced-search input[type="button"] +{ + display:inline-block; + margin:0; + height:24px; + line-height:24px; + font-weight:bold; + border:1px solid #666666; + padding:0 10px; + background: url('../images/grey_btn_bg.png?1312910883') top left repeat-x; + color: #333; +} + +#advanced-search input[type="reset"], #advanced-search input[type="button"] { + opacity:0.7; +} + +#advanced-search input[type=submit]:hover, #advanced-search input[type=submit]:active, +#advanced-search input[type=reset]:hover, #advanced-search input[type=reset]:active { + background-position:bottom left; +} + +#result-count div { + padding:5px 10px; + text-align:left; + font-weight:bold; + width:100%; + margin:0 auto; +} + +#result-count .success { + background:#e3ffd8; + border:1px solid #0a0; +} + +#result-count .fail { + background:#ffd8d8; + border:1px solid #a00; +} + diff --git a/scp/images/ajax-loader.gif b/scp/images/ajax-loader.gif new file mode 100644 index 0000000000000000000000000000000000000000..d42f72c723644bbf8cf8d6e1b7ff0bea7ddd305a GIT binary patch literal 1849 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 literal 0 HcmV?d00001 diff --git a/scp/js/scp.js b/scp/js/scp.js index 7a9e0e218..37389d34b 100644 --- a/scp/js/scp.js +++ b/scp/js/scp.js @@ -198,11 +198,11 @@ $(document).ready(function(){ } } - /* Typeahead init */ + /* Typeahead tickets lookup */ $('#basic-ticket-search').typeahead({ source: function (typeahead, query) { $.ajax({ - url: "ajax.php/tickets?q="+query, + url: "ajax.php/tickets/lookup?q="+query, dataType: 'json', success: function (data) { typeahead.process(data); @@ -215,6 +215,7 @@ $(document).ready(function(){ property: "value" }); + /* Typeahead user lookup */ $('#email.typeahead').typeahead({ source: function (typeahead, query) { if(query.length > 2) { @@ -235,5 +236,84 @@ $(document).ready(function(){ property: "email" }); + /* advanced search */ + $("#overlay").css({ + opacity : 0.3, + top : 0, + left : 0, + width : $(window).width(), + height : $(window).height() + }); + + $("#advanced-search").css({ + top : ($(window).height() / 6), + left : ($(window).width() / 2 - 300) + }); + + $('#go-advanced').click(function(e) { + e.preventDefault(); + $('#result-count').html(''); + $('#overlay').show(); + $('#advanced-search').show(); + }); + + $('#advanced-search').delegate('a.close, input.close', 'click', function(e) { + e.preventDefault(); + $('#advanced-search').hide() + $('#overlay').hide(); + }).delegate('#status', 'change', function() { + switch($(this).val()) { + case 'closed': + $('select#assigneeId').find('option:first').attr('selected', 'selected').parent('select'); + $('select#assigneeId').attr('disabled','disabled'); + $('select#staffId').removeAttr('disabled'); + break; + case 'open': + case 'overdue': + $('select#staffId').find('option:first').attr('selected', 'selected').parent('select'); + $('select#staffId').attr('disabled','disabled'); + $('select#assigneeId').removeAttr('disabled'); + break; + default: + $('select#staffId').removeAttr('disabled'); + $('select#assigneeId').removeAttr('disabled'); + } + }); + + $('#advanced-search form#search').submit(function(e) { + e.preventDefault(); + var fObj = $(this); + var elem = $('#advanced-search'); + $('#result-count').html(''); + $.ajax({ + url: "ajax.php/tickets", + data: fObj.serialize(), + dataType: 'json', + beforeSend: function ( xhr ) { + $('.buttons', elem).hide(); + $('.spinner', elem).show(); + return true; + }, + success: function (resp) { + + if(resp.success) { + $('#result-count').html('<div class="success">' + resp.success +'</div>'); + } else if (resp.fail) { + $('#result-count').html('<div class="fail">' + resp.fail +'</div>'); + } else { + $('#result-count').html('<div class="fail">Unknown error</div>'); + } + } + }) + .done( function () { + }) + .fail( function () { + $('#result-count').html('<div class="fail">Advanced search failed - try again!</div>'); + }) + .always( function () { + $('.spinner', elem).hide(); + $('.buttons', elem).show(); + }); + }); }); -- GitLab