Commit 5b654041 authored by Richard Mansfield's avatar Richard Mansfield
Browse files

Add sort options for both tag list and search results

parent 19472fa5
...@@ -32,10 +32,11 @@ require('searchlib.php'); ...@@ -32,10 +32,11 @@ require('searchlib.php');
$tag = param_variable('tag'); $tag = param_variable('tag');
$offset = param_integer('offset', 0); $offset = param_integer('offset', 0);
$sort = param_alpha('sort', 'name');
$limit = param_integer('limit', 10); $limit = param_integer('limit', 10);
$owner = (object) array('type' => 'user', 'id' => $USER->get('id')); $owner = (object) array('type' => 'user', 'id' => $USER->get('id'));
$data = get_portfolio_items_by_tag($tag, $owner, $limit, $offset); $data = get_portfolio_items_by_tag($tag, $owner, $limit, $offset, $sort);
build_portfolio_search_html($data); build_portfolio_search_html($data);
$data->tagdisplay = hsc($tag); $data->tagdisplay = hsc($tag);
......
...@@ -88,7 +88,11 @@ $string['mytags'] = 'My Tags'; ...@@ -88,7 +88,11 @@ $string['mytags'] = 'My Tags';
$string['Tag'] = 'Tag'; $string['Tag'] = 'Tag';
$string['itemstaggedwith'] = 'Items tagged with "%s"'; $string['itemstaggedwith'] = 'Items tagged with "%s"';
$string['numitems'] = '%s items'; $string['numitems'] = '%s items';
$string['searchresultsfor'] = 'Search results for'; $string['searchresultsfor'] = 'Search results for:';
$string['sortalpha'] = 'Sort tags alphabetically';
$string['sortfreq'] = 'Sort tags by frequency';
$string['sortresultsby'] = 'Sort results by:';
$string['date'] = 'Date';
$string['selfsearch'] = 'Search My Portfolio'; $string['selfsearch'] = 'Search My Portfolio';
......
...@@ -2038,9 +2038,15 @@ function tag_weight($freq) { ...@@ -2038,9 +2038,15 @@ function tag_weight($freq) {
// return log10($freq); // return log10($freq);
} }
function get_my_tags($limit=null, $cloud=true) { function get_my_tags($limit=null, $cloud=true, $sort='freq') {
global $USER; global $USER;
$id = $USER->get('id'); $id = $USER->get('id');
if ($limit || $sort != 'alpha') {
$sort = 'COUNT(t.tag) DESC';
}
else {
$sort = 't.tag ASC';
}
$tagrecords = get_records_sql_array(" $tagrecords = get_records_sql_array("
SELECT SELECT
t.tag, COUNT(t.tag) t.tag, COUNT(t.tag)
...@@ -2054,10 +2060,13 @@ function get_my_tags($limit=null, $cloud=true) { ...@@ -2054,10 +2060,13 @@ function get_my_tags($limit=null, $cloud=true) {
WHERE v.owner = ?) WHERE v.owner = ?)
) t ) t
GROUP BY t.tag GROUP BY t.tag
ORDER BY COUNT(t.tag) DESC" . (is_null($limit) ? '' : " LIMIT $limit"), ORDER BY " . $sort . (is_null($limit) ? '' : " LIMIT $limit"),
array($id, $id) array($id, $id)
); );
if ($cloud && $tagrecords) { if (!$tagrecords) {
return false;
}
if ($cloud) {
$minfreq = $tagrecords[count($tagrecords) - 1]->count; $minfreq = $tagrecords[count($tagrecords) - 1]->count;
$maxfreq = $tagrecords[0]->count; $maxfreq = $tagrecords[0]->count;
...@@ -2072,9 +2081,8 @@ function get_my_tags($limit=null, $cloud=true) { ...@@ -2072,9 +2081,8 @@ function get_my_tags($limit=null, $cloud=true) {
$t->size = sprintf("%0.1f", $minsize + ($maxsize - $minsize) * $weight); $t->size = sprintf("%0.1f", $minsize + ($maxsize - $minsize) * $weight);
} }
usort($tagrecords, create_function('$a,$b', 'return strnatcasecmp($a->tag, $b->tag);')); usort($tagrecords, create_function('$a,$b', 'return strnatcasecmp($a->tag, $b->tag);'));
return $tagrecords;
} }
return false; return $tagrecords;
} }
function mytags_sideblock() { function mytags_sideblock() {
...@@ -2167,13 +2175,17 @@ function build_portfolio_search_html(&$data) { ...@@ -2167,13 +2175,17 @@ function build_portfolio_search_html(&$data) {
$item->typestr = get_string($item->artefacttype, 'artefact.' . $artefacttypes[$item->artefacttype]->plugin); $item->typestr = get_string($item->artefacttype, 'artefact.' . $artefacttypes[$item->artefacttype]->plugin);
} }
} }
$data->baseurl = get_config('wwwroot') . 'tags.php?tag=' . urlencode($data->tag);
$data->sortcols = array('name', 'date');
$smarty = smarty_core(); $smarty = smarty_core();
$smarty->assign_by_ref('data', $data->data); $smarty->assign_by_ref('data', $data->data);
$data->tablerows = $smarty->fetch('portfoliosearchresults.tpl'); $data->tablerows = $smarty->fetch('portfoliosearchresults.tpl');
$pagination = build_pagination(array( $pagination = build_pagination(array(
'id' => 'results_pagination', 'id' => 'results_pagination',
'class' => 'center', 'class' => 'center',
'url' => get_config('wwwroot') . 'tags.php?tag=' . urlencode($data->tag), 'url' => $data->baseurl . ($data->sort == 'name' ? '' : '&sort=' . $data->sort),
'jsonscript' => 'json/tagsearch.php', 'jsonscript' => 'json/tagsearch.php',
'datatable' => 'results', 'datatable' => 'results',
'count' => $data->count, 'count' => $data->count,
......
...@@ -441,7 +441,7 @@ function search_selfsearch($query_string, $limit, $offset, $type = 'all') { ...@@ -441,7 +441,7 @@ function search_selfsearch($query_string, $limit, $offset, $type = 'all') {
return call_static_method(generate_class_name('search', $plugin), 'self_search', $query_string, $limit, $offset, $type); return call_static_method(generate_class_name('search', $plugin), 'self_search', $query_string, $limit, $offset, $type);
} }
function get_portfolio_items_by_tag($tag, $owner, $limit, $offset, $returntags=true) { function get_portfolio_items_by_tag($tag, $owner, $limit, $offset, $sort='name', $returntags=true) {
// For now, can only be used to search a user's portfolio // For now, can only be used to search a user's portfolio
if (empty($owner->id) || empty($owner->type)) { if (empty($owner->id) || empty($owner->type)) {
throw new SystemException('get_views_and_artefacts_by_tag: invalid owner'); throw new SystemException('get_views_and_artefacts_by_tag: invalid owner');
...@@ -453,7 +453,7 @@ function get_portfolio_items_by_tag($tag, $owner, $limit, $offset, $returntags=t ...@@ -453,7 +453,7 @@ function get_portfolio_items_by_tag($tag, $owner, $limit, $offset, $returntags=t
$plugin = 'internal'; $plugin = 'internal';
safe_require('search', $plugin); safe_require('search', $plugin);
return call_static_method(generate_class_name('search', $plugin), 'portfolio_search_by_tag', $tag, $owner, $limit, $offset, $returntags); return call_static_method(generate_class_name('search', $plugin), 'portfolio_search_by_tag', $tag, $owner, $limit, $offset, $sort, $returntags);
} }
function get_search_plugins() { function get_search_plugins() {
......
...@@ -844,9 +844,10 @@ class PluginSearchInternal extends PluginSearch { ...@@ -844,9 +844,10 @@ class PluginSearchInternal extends PluginSearch {
* @param object $owner: owner type (user,group,institution), and id * @param object $owner: owner type (user,group,institution), and id
* @param integer $limit * @param integer $limit
* @param integer $offset * @param integer $offset
* @param string $sort
* @param boolean $returntags Return all the tags that have been attached to each result * @param boolean $returntags Return all the tags that have been attached to each result
*/ */
public static function portfolio_search_by_tag($tag, $owner, $limit, $offset, $returntags) { public static function portfolio_search_by_tag($tag, $owner, $limit, $offset, $sort, $returntags) {
$from = "FROM ( $from = "FROM (
(SELECT a.id, a.title, a.description, 'artefact' AS type, a.artefacttype, " . db_format_tsfield('a.ctime', 'ctime') . " (SELECT a.id, a.title, a.description, 'artefact' AS type, a.artefacttype, " . db_format_tsfield('a.ctime', 'ctime') . "
FROM {artefact} a JOIN {artefact_tag} at ON (a.id = at.artefact AND at.tag = ?) FROM {artefact} a JOIN {artefact_tag} at ON (a.id = at.artefact AND at.tag = ?)
...@@ -864,13 +865,15 @@ class PluginSearchInternal extends PluginSearch { ...@@ -864,13 +865,15 @@ class PluginSearchInternal extends PluginSearch {
'owner' => $owner, 'owner' => $owner,
'offset' => $offset, 'offset' => $offset,
'limit' => $limit, 'limit' => $limit,
'sort' => $sort,
'count' => 0, 'count' => 0,
'data' => array(), 'data' => array(),
); );
if ($count = count_records_sql('SELECT COUNT(*) ' . $from, $values, $offset, $limit)) { if ($count = count_records_sql('SELECT COUNT(*) ' . $from, $values, $offset, $limit)) {
$result->count = $count; $result->count = $count;
if ($data = get_records_sql_assoc("SELECT type || ':' || id AS tid, * " . $from . ' ORDER BY p.title ASC', $values, $offset, $limit)) { $sort = $sort == 'date' ? 'ctime DESC' : 'title ASC';
if ($data = get_records_sql_assoc("SELECT type || ':' || id AS tid, * " . $from . ' ORDER BY ' . $sort, $values, $offset, $limit)) {
if ($returntags) { if ($returntags) {
$ids = array('view' => array(), 'artefact' => array()); $ids = array('view' => array(), 'artefact' => array());
foreach ($data as &$d) { foreach ($data as &$d) {
......
...@@ -30,21 +30,61 @@ require('init.php'); ...@@ -30,21 +30,61 @@ require('init.php');
require('searchlib.php'); require('searchlib.php');
define('TITLE', get_string('mytags')); define('TITLE', get_string('mytags'));
$tags = get_my_tags();
$tagsort = param_alpha('ts', null) != 'freq' ? 'alpha' : 'freq';
$tags = get_my_tags(null, false, $tagsort);
$tagsstr = json_encode($tags);
$tag = param_variable('tag', null); $tag = param_variable('tag', null);
$js = ''; $js = '';
$limit = param_integer('limit', 10); $limit = param_integer('limit', 10);
$offset = param_integer('offset', 0); $offset = param_integer('offset', 0);
$sort = param_alpha('sort', 'name');
$owner = (object) array('type' => 'user', 'id' => $USER->get('id')); $owner = (object) array('type' => 'user', 'id' => $USER->get('id'));
$data = get_portfolio_items_by_tag($tag, $owner, $limit, $offset); $data = get_portfolio_items_by_tag($tag, $owner, $limit, $offset, $sort);
build_portfolio_search_html($data); build_portfolio_search_html($data);
$hidepagination = $tag ? '' : "addElementClass('results_pagination', 'hidden');"; $hidepagination = $tag ? '' : "addElementClass('results_pagination', 'hidden');";
$js = <<<EOF $js = <<<EOF
var p = null; var p = null;
var mytags_container = null; var mytags_container = null;
var inittags = {$tagsstr};
var mytags = {};
function sortTagAlpha(a, b) {
var aid = getNodeAttribute(a, 'id');
var bid = getNodeAttribute(b, 'id');
return aid < bid ? -1 : (aid > bid ? 1 : 0);
}
function sortTagFreq(a, b) {
var aid = getNodeAttribute(a, 'id');
var bid = getNodeAttribute(b, 'id');
return mytags[bid] - mytags[aid];
}
var sort_functions = {'alpha': sortTagAlpha, 'freq': sortTagFreq};
function rewriteTagSortLink(elem) {
connect(elem, 'onclick', function(e) {
e.stop();
var href = getNodeAttribute(this, 'href');
var params = parseQueryString(href.substring(href.indexOf('?')+1, href.length));
var elems = getElementsByTagAndClassName('a', 'tag', mytags_container);
elems.sort(sort_functions[params.ts]);
replaceChildNodes(mytags_container, elems);
forEach(getElementsByTagAndClassName('a', 'current-tab'), function(selected) {
removeElementClass(selected, 'current-tab');
});
addElementClass(this, 'current-tab');
return false;
});
}
function rewriteTagLink(elem) { function rewriteTagLink(elem) {
disconnectAll(elem); disconnectAll(elem);
connect(elem, 'onclick', function(e) { connect(elem, 'onclick', function(e) {
...@@ -53,38 +93,71 @@ function rewriteTagLink(elem) { ...@@ -53,38 +93,71 @@ function rewriteTagLink(elem) {
var params = parseQueryString(href.substring(href.indexOf('?')+1, href.length)); var params = parseQueryString(href.substring(href.indexOf('?')+1, href.length));
sendjsonrequest(config.wwwroot + 'json/tagsearch.php', params, 'POST', function(data) { sendjsonrequest(config.wwwroot + 'json/tagsearch.php', params, 'POST', function(data) {
p.updateResults(data); p.updateResults(data);
// Update tag links in the My Tags list:
forEach(getElementsByTagAndClassName('a', 'selected', mytags_container), function(selected) { forEach(getElementsByTagAndClassName('a', 'selected', mytags_container), function(selected) {
removeElementClass(selected, 'selected'); removeElementClass(selected, 'selected');
}); });
// Mark the selected tag in the My Tags list:
addElementClass('tag:' + params.tag, 'selected'); addElementClass('tag:' + params.tag, 'selected');
// Replace the tag in the Search Results heading
var heading_tag = getFirstElementByTagAndClassName('a', 'tag', 'results_heading'); var heading_tag = getFirstElementByTagAndClassName('a', 'tag', 'results_heading');
if (heading_tag) { if (heading_tag) {
heading_tag.href = href; heading_tag.href = href;
heading_tag.innerHTML = data.data.tagdisplay; heading_tag.innerHTML = data.data.tagdisplay;
} }
if (hasElementClass('results', 'hidden')) {
removeElementClass('results', 'hidden'); removeElementClass('results_container', 'hidden');
removeElementClass('results_heading', 'hidden');
removeElementClass('results_pagination', 'hidden'); // Rewrite tag links in the results list:
}
forEach(getElementsByTagAndClassName('a', 'tag', 'results'), rewriteTagLink); forEach(getElementsByTagAndClassName('a', 'tag', 'results'), rewriteTagLink);
// Rewrite Sort By links above the Search results:
forEach(getElementsByTagAndClassName('a', null, 'results_sort'), function (a) {
var href = getNodeAttribute(a, 'href');
var params = parseQueryString(href.substring(href.indexOf('?')+1, href.length));
params.tag = data.data.tag;
setNodeAttribute(a, 'href', config.wwwroot + 'tags.php?' + queryString(params));
if (hasElementClass(a, 'selected') && data.data.sort != params.sort) {
removeElementClass(a, 'selected');
}
else if (!hasElementClass(a, 'selected') && data.data.sort == params.sort) {
addElementClass(a, 'selected');
}
rewriteTagLink(a);
});
}); });
return false; return false;
}); });
}; }
addLoadEvent(function() { addLoadEvent(function() {
forEach(inittags, function(t) {
mytags['tag:' + t.tag] = t.count;
});
forEach(getElementsByTagAndClassName('a', 'tag-sort'), rewriteTagSortLink);
mytags_container = getFirstElementByTagAndClassName(null, 'mytags', 'main-column-container'); mytags_container = getFirstElementByTagAndClassName(null, 'mytags', 'main-column-container');
p = {$data->pagination_js} p = {$data->pagination_js}
forEach(getElementsByTagAndClassName('a', 'tag', mytags_container), rewriteTagLink); forEach(getElementsByTagAndClassName('a', 'tag', mytags_container), rewriteTagLink);
forEach(getElementsByTagAndClassName('a', 'tag', 'sb-mytags'), rewriteTagLink); forEach(getElementsByTagAndClassName('a', 'tag', 'sb-mytags'), rewriteTagLink);
forEach(getElementsByTagAndClassName('a', 'tag', 'results'), rewriteTagLink); forEach(getElementsByTagAndClassName('a', 'tag', 'results'), rewriteTagLink);
forEach(getElementsByTagAndClassName('a', null, 'results_sort'), rewriteTagLink);
{$hidepagination} {$hidepagination}
}); });
EOF; EOF;
$tagsortoptions = array();
foreach (array('alpha', 'freq') as $option) {
$tagsortoptions[$option] = $option == $tagsort;
}
$smarty = smarty(array('paginator')); $smarty = smarty(array('paginator'));
$smarty->assign('PAGEHEADING', hsc(TITLE)); $smarty->assign('PAGEHEADING', hsc(TITLE));
$smarty->assign('tags', $tags); $smarty->assign('tags', $tags);
$smarty->assign('tagsortoptions', $tagsortoptions);
$smarty->assign('tag', $tag); $smarty->assign('tag', $tag);
$smarty->assign_by_ref('results', $data); $smarty->assign_by_ref('results', $data);
$smarty->assign('INLINEJAVASCRIPT', $js); $smarty->assign('INLINEJAVASCRIPT', $js);
......
...@@ -839,7 +839,9 @@ div.sideblock #friendscontrol label { ...@@ -839,7 +839,9 @@ div.sideblock #friendscontrol label {
padding: 0 5px; padding: 0 5px;
vertical-align: middle; vertical-align: middle;
} }
.mytags .tag.selected { /* .tag-sort.selected, */
.tag-results .selected,
.mytags .selected {
color: #444; color: #444;
font-weight: bold; font-weight: bold;
} }
......
{include file="header.tpl"} {include file="header.tpl"}
{if $tags} {if $tags}
<div class="mytags"> <ul class="in-page-tabs">
{foreach from=$tagsortoptions key=tagsortfield item=selectedsort name=tagsortoptions}
<li><a href="{$WWWROOT}tags.php?ts={$tagsortfield}" class="tag-sort{if $selectedsort} current-tab{/if}">{str tag=sort$tagsortfield}</a></li>
{/foreach}
</ul>
<div class="subpage mytags">
{foreach from=$tags item=t} {foreach from=$tags item=t}
<a id="tag:{$t->tag}" class="tag{if $t->tag == $tag} selected{/if}" href="{$WWWROOT}tags.php?tag={$t->tag|urlencode}">{$t->tag|escape}&nbsp;<span class="tagfreq">({$t->count})</span></a> <a id="tag:{$t->tag}" class="tag{if $t->tag == $tag} selected{/if}" href="{$WWWROOT}tags.php?tag={$t->tag|urlencode}">{$t->tag|escape}&nbsp;<span class="tagfreq">({$t->count})</span></a>
{/foreach} {/foreach}
</div> </div>
{else} {else}
<div>{str tag=youhavenottaggedanythingyet}</div> <div>{str tag=youhavenottaggedanythingyet}</div>
{/if} {/if}
<h6 id="results_heading"{if !$tag} class="hidden"{/if}>{str tag=searchresultsfor}: <a class="tag" href="{$WWWROOT}tags.php?tag={$tag|urlencode}">{$tag|escape}</a></h4> <div id="results_container" class="tag-results{if !$tag} hidden{/if}">
<table id="results" class="tablerenderer fullwidth{if !$tag} hidden{/if}"> <h2 id="results_heading">{str tag=searchresultsfor} <a class="tag" href="{$WWWROOT}tags.php?tag={$tag|urlencode}">{$tag|escape}</a></h4>
<div id="results_sort">{str tag=sortresultsby}
{foreach from=$results->sortcols item=sortfield name=sortcols}
<a href="{$results->baseurl}&sort={$sortfield}"{if $results->sort == $sortfield} class="selected"{/if}>{str tag=$sortfield}</a>{if !$smarty.foreach.sortcols.last} | {/if}
{/foreach}
</div>
<table id="results" class="tablerenderer fullwidth">
<thead> <thead>
<tr><th></th><th></th><th></th></tr> <tr><th></th><th></th><th></th></tr>
</thead> </thead>
...@@ -22,5 +33,6 @@ ...@@ -22,5 +33,6 @@
</tbody> </tbody>
</table> </table>
{$results->pagination} {$results->pagination}
</div>
{include file="footer.tpl"} {include file="footer.tpl"}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment