diff --git a/include/ajax.search.php b/include/ajax.search.php index 931da5b9291b167987dc1ec18e60776209d54656..bd39a2e0eeabfe1764e7575d3e694385384dbc3c 100644 --- a/include/ajax.search.php +++ b/include/ajax.search.php @@ -143,26 +143,38 @@ class SearchAjaxAPI extends AjaxController { -$size); } - function _tryAgain($search, $form, $errors=array()) { + function _tryAgain($search, $form, $errors=array(), $info=array()) { $matches = $search->getSupportedMatches(); include STAFFINC_DIR . 'templates/advanced-search.tmpl.php'; } - function saveSearch($id) { + function saveSearch($id=0) { global $thisstaff; - $search = SavedSearch::lookup($id); if (!$thisstaff) Http::response(403, 'Agent login is required'); - elseif (!$search || !$search->checkAccess($thisstaff)) + + if ($id) { // update + $search = SavedSearch::lookup($id); + } else { // new search + $search = SavedSearch::create(array('root' => 'T')); + $search->staff_id = $thisstaff->getId(); + } + + if (!$search || !$search->checkAccess($thisstaff)) Http::response(404, 'No such saved search'); if (false === $this->_saveSearch($search)) return; - Http::response(200, $this->encode(array( - 'redirect' => 'tickets.php?queue='.Format::htmlchars($search->id), - ))); + $info = array( + 'msg' => sprintf('%s %s %s', + __('Search'), + $id ? __('updated') : __('created'), + __('successfully')), + ); + + $this->_tryAgain($search, $search->getForm(), null, $info); } function _saveSearch(SavedSearch $search) { @@ -182,22 +194,6 @@ class SearchAjaxAPI extends AjaxController { return true; } - function createSearch() { - global $thisstaff; - - if (!$thisstaff) - Http::response(403, 'Agent login is required'); - - $search = SavedSearch::create(array('root' => 'T')); - $search->staff_id = $thisstaff->getId(); - if (false === $this->_saveSearch($search)) - return; - - Http::response(200, $this->encode(array( - 'redirect' => 'tickets.php?queue='.Format::htmlchars($search->id), - ))); - } - function editColumn($column_id) { global $thisstaff; @@ -243,6 +239,21 @@ class SearchAjaxAPI extends AjaxController { include STAFFINC_DIR . 'templates/queue-sorting-edit.tmpl.php'; } + function getQueue($id) { + global $thisstaff; + + $queue = SavedSearch::lookup($id); + if (!$thisstaff) + Http::response(403, 'Agent login is required'); + elseif (!$queue || !$queue->checkAccess($thisstaff)) + Http::response(404, 'No such queue'); + + Http::response(200, $this->encode(array( + 'name' => $queue->getName(), + 'criteria' => nl2br(Format::htmlchars($queue->describeCriteria())), + ))); + } + function deleteQueue($id) { global $thisstaff; diff --git a/include/class.queue.php b/include/class.queue.php index 740673590b3a7531b9d284985d916021e41d43b6..502e3fbb3e4266136dbc6922b87fef365270f724 100644 --- a/include/class.queue.php +++ b/include/class.queue.php @@ -998,6 +998,11 @@ class CustomQueue extends VerySimpleModel { // Set basic search information if (!$vars['name']) $errors['name'] = __('A title is required'); + elseif (($q=CustomQueue::lookup(array( + 'title' => $vars['name'], + 'parent_id' => $vars['parent_id'] ?: 0, + 'staff_id' => $this->staff_id)))) + $errors['name'] = __('Saved queue with same name exists'); $this->title = $vars['name']; $this->parent_id = @$vars['parent_id'] ?: 0; diff --git a/include/staff/templates/advanced-search-criteria.tmpl.php b/include/staff/templates/advanced-search-criteria.tmpl.php index 4390cbc001061cc129676da900cebd3080913e77..136c7d139bb7a35d382757fe2e534230f79d997a 100644 --- a/include/staff/templates/advanced-search-criteria.tmpl.php +++ b/include/staff/templates/advanced-search-criteria.tmpl.php @@ -88,24 +88,6 @@ foreach ($matches as $path => $F) { <?php } } ?> </select> - -<div class="row"> -</br> - <label class="checkbox inline"><input id="save-search" type="checkbox" name="save-search" - - onclick="javascript: - var form = $(this).closest('form'); - form.attr('action', form.attr('action') + '/' + <?php echo - $search->id ?: "'create'"; ?>);"> - <?php echo __('Save Search'); ?></label> - </br> - <input name="name" type="text" size="40" style="margin-top: 5px;" - value="<?php echo Format::htmlchars($search->getName()); ?>" - placeholder="<?php - echo __('Search Title'); ?>"/> - <div class="error"><?php echo Format::htmlchars($errors['name']); ?></div> -</div> - <script> $(function() { $('#search-add-new-field').on('change', function() { diff --git a/include/staff/templates/advanced-search.tmpl.php b/include/staff/templates/advanced-search.tmpl.php index e904b971f280a0126d2f13d6473c4f0ce44bb3f9..71d2deedcb0314a1dd4355bad643fb42a68d363d 100644 --- a/include/staff/templates/advanced-search.tmpl.php +++ b/include/staff/templates/advanced-search.tmpl.php @@ -18,12 +18,21 @@ $qname = $search->getName() ?: __('Advanced Ticket Search'); <h3 class="drag-handle"><?php echo Format::htmlchars($qname); ?></h3> <a class="close" href=""><i class="icon-remove-circle"></i></a> <hr/> - -<form action="#tickets/search" method="post" name="search"> - +<?php +$info['error'] = $info['error'] ?: $errors['err']; +if ($info['error']) { + echo sprintf('<p id="msg_error">%s</p>', $info['error']); +} elseif ($info['warn']) { + echo sprintf('<p id="msg_warning">%s</p>', $info['warn']); +} elseif ($info['msg']) { + echo sprintf('<p id="msg_notice">%s</p>', $info['msg']); +} ?> +<form action="#tickets/search" method="post" name="search" id="advsearch" + class="<?php echo ($search->isSaved() || $parent) ? 'savedsearch' : 'adhocsearch'; ?>"> + <input type="hidden" name="id" value="<?php echo $search->getId(); ?>"> <div class="flex row"> <div class="span12"> - <select name="parent_id"> + <select id="parent" name="parent_id" > <?php foreach ($queues as $id => $name) { ?> @@ -42,17 +51,22 @@ foreach ($queues as $id => $name) { <div class="tab_content" id="criteria"> <div class="flex row"> - <div class="span12" style="overflow-y: scroll; height:100%;"> -<?php if ($parent) { ?> - <div class="faded" style="margin-bottom: 1em"> + <div class="span12" style="overflow-y: auto; height:auto;"> + <div class="error"><?php echo Format::htmlchars($errors['criteria']); ?></div> + <div class="faded <?php echo $parent ? ' ': 'hidden'; ?>" + id="inherited-parent" style="margin-bottom: 1em"> + <div> - <strong><?php echo __('Inherited Criteria'); ?></strong> + <strong><a href="#" id="parent-info"><i class="icon-caret-right"></i> <?php + echo sprintf('%s (<span id="parent-name">%s</span>)', + __('Inherited Criteria'), + $parent ? $parent->getName() : ''); + ?></a></strong> </div> - <div> - <?php echo nl2br(Format::htmlchars($parent->describeCriteria())); ?> + <div id="parent-criteria" class="hidden"> + <?php echo $parent ? nl2br(Format::htmlchars($parent->describeCriteria())) : ''; ?> </div> </div> -<?php } ?> <input type="hidden" name="a" value="search"> <?php include STAFFINC_DIR . 'templates/advanced-search-criteria.tmpl.php'; ?> </div> @@ -60,26 +74,48 @@ foreach ($queues as $id => $name) { </div> -<div class="tab_content hidden" id="columns" style="overflow-y: scroll; -height:100%;"> +<div class="tab_content hidden" id="columns" style="overflow-y: auto; +height:auto;"> <?php include STAFFINC_DIR . "templates/queue-columns.tmpl.php"; ?> </div> -<div class="tab_content hidden" id="fields" style="overflow-y: scroll; -height:auto;"> +<div class="tab_content hidden" id="fields"> <?php include STAFFINC_DIR . "templates/queue-fields.tmpl.php"; ?> </div> + <?php + $save = (($parent && !$search->isSaved()) || $errors); ?> + <div style="margin-top:10px;"><a href="#" + id="save"><i class="icon-caret-<?php echo $save ? 'down' : 'right'; + ?>"></i> <span><?php echo __('Save Search'); ?></span></a></div> + <div id="save-changes" class="<?php echo $save ? '' : 'hidden'; ?>" style="padding:5px; border-top: 1px dotted #777;"> + <div><input name="name" type="text" size="40" + value="<?php echo $search->isSaved() ? Format::htmlchars($search->getName()) : ''; ?>" + placeholder="<?php echo __('Search Title'); ?>"> + <span class="buttons"> + <button class="button" type="button" name="save" + value="save"><i class="icon-save"></i> <?php echo $search->id + ? __('Save Changes') : __('Save'); ?></button> + </span> + </div> + <div class="error" id="name-error"><?php echo Format::htmlchars($errors['name']); ?></div> + </div> <hr/> - <div> - <div class="buttons pull-right"> + <div> + <p class="full-width"> + <span class="buttons pull-left"> + <input type="reset" id="reset" value="<?php echo __('Reset'); ?>"> + <input type="button" name="cancel" class="close" + value="<?php echo __('Cancel'); ?>"> + </span> + <span class="buttons pull-right"> <button class="button" type="submit" name="submit" value="search" id="do_search"><i class="icon-search"></i> <?php echo __('Search'); ?></button> - </div> - </div> - + </span> + </p> + </div> </form> <script> @@ -103,6 +139,78 @@ height:auto;"> $(el).val(i + 1 + offset); }); } - }); + }); + + $('a#parent-info').click(function() { + var $this = $(this); + $('#parent-criteria').slideToggle('fast', function(){ + if ($(this).is(":hidden")) + $this.find('i').removeClass('icon-caret-down').addClass('icon-caret-right'); + else + $this.find('i').removeClass('icon-caret-right').addClass('icon-caret-down'); + }); + return false; + }); + + $('form select#parent').change(function() { + var form = $(this).closest('form'); + var qid = parseInt($(this).val(), 10) || 0; + + if (qid > 0) { + $.ajax({ + type: "GET", + url: 'ajax.php/queue/'+qid, + dataType: 'json', + success: function(queue) { + $('#parent-name', form).html(queue.name); + $('#parent-criteria', form).html(queue.criteria); + $('#inherited-parent', form).fadeIn(); + } + }) + .done(function() { }) + .fail(function() { }); + } else { + $('#inherited-parent', form).fadeOut(); + } + }); + + $('a#save').click(function() { + var $this = $(this); + $('#save-changes').slideToggle('fast', function(){ + if ($(this).is(":hidden")) + $this.find('i').removeClass('icon-caret-down').addClass('icon-caret-right'); + else + $this.find('i').removeClass('icon-caret-right').addClass('icon-caret-down'); + }); + return false; + }); + + $('form.savedsearch').on('keyup change paste', 'input, select, textarea', function() { + var form = $(this).closest('form'); + $this = $('#save-changes', form); + if ($this.is(":hidden")) + $this.fadeIn(); + $('a#save').find('i').removeClass('icon-caret-right').addClass('icon-caret-down'); + $('button[name=save]', form).addClass('save pending'); + $('div.error', form).html(''); + }); + + $(document).on('click', 'form#advsearch input#reset', function(e) { + var f = $(this).closest('form'); + $('button[name=save]', f).removeClass('save pending'); + $('div#save-changes', f).hide(); + }); + + $('button[name=save]').click(function() { + var $form = $(this).closest('form'); + var id = parseInt($('input[name=id]', $form).val(), 10) || 0; + var action = '#tickets/search'; + if (id > 0) + action = action + '/'+id; + + $form.prop('action', action+'/save'); + $form.submit(); + }); + }(); </script> diff --git a/include/staff/templates/queue-fields.tmpl.php b/include/staff/templates/queue-fields.tmpl.php index fffaa7a4e176bdb2805029902de418ef51f789d4..4ad7106870bd45278ee3b19661017a7c8dfb438b 100644 --- a/include/staff/templates/queue-fields.tmpl.php +++ b/include/staff/templates/queue-fields.tmpl.php @@ -1,3 +1,4 @@ +<div style="overflow-y: auto; height:auto; max-height: 350px;"> <table class="table"> <?php if ($queue->parent) { ?> @@ -38,7 +39,8 @@ $hidden_cols = $queue->inheritExport(); <td><small> </small></td> </tr> </tbody> - <tbody class="sortable-rows if-not-inherited <?php if ($hidden_cols) echo 'hidden'; ?>"> + <tbody class="sortable-rows if-not-inherited <?php if ($hidden_cols) echo + 'hidden'; ?>" style="overflow-y: auto;"> <tr id="field-template" class="hidden field-entry"> <td nowrap> <i class="faded-more icon-sort"></i> @@ -78,6 +80,7 @@ $hidden_cols = $queue->inheritExport(); </td></tr> </tbody> </table> +</div> <script> +function() { var Q = setInterval(function() { diff --git a/scp/ajax.php b/scp/ajax.php index bc23cb1ebca158bc75d7386a72b51496374dcbb1..039af6b3e48d838eeabd2506dffbfc67c3055ed7 100644 --- a/scp/ajax.php +++ b/scp/ajax.php @@ -177,9 +177,9 @@ $dispatcher = patterns('', url_post('^$', 'doSearch'), url_get('^/(?P<id>\d+)$', 'editSearch'), url_get('^/adhoc,(?P<key>[\w=/+]+)$', 'getAdvancedSearchDialog'), - url_post('^/(?P<id>\d+)$', 'saveSearch'), + url_post('^/(?P<id>\d+)/save$', 'saveSearch'), + url_post('^/save$', 'saveSearch'), url_delete('^/(?P<id>\d+)$', 'deleteSearch'), - url_post('^/create$', 'createSearch'), url_get('^/field/(?P<id>[\w_!:]+)$', 'addField'), url('^/column/edit/(?P<id>\d+)$', 'editColumn'), url('^/sort/edit/(?P<id>\d+)$', 'editSort'), @@ -269,6 +269,7 @@ $dispatcher = patterns('', )), url('^/queue/', patterns('ajax.search.php:SearchAjaxAPI', url('^(?P<id>\d+/)?preview$', 'previewQueue'), + url_get('^(?P<id>\d+)$', 'getQueue'), url_get('^addColumn$', 'addColumn'), url_get('^condition/add$', 'addCondition'), url_get('^condition/addProperty$', 'addConditionProperty'),