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');
$tag = param_variable('tag');
$offset = param_integer('offset', 0);
$sort = param_alpha('sort', 'name');
$limit = param_integer('limit', 10);
$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);
$data->tagdisplay = hsc($tag);
......
......@@ -88,7 +88,11 @@ $string['mytags'] = 'My Tags';
$string['Tag'] = 'Tag';
$string['itemstaggedwith'] = 'Items tagged with "%s"';
$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';
......
......@@ -2038,9 +2038,15 @@ function tag_weight($freq) {
// return log10($freq);
}
function get_my_tags($limit=null, $cloud=true) {
function get_my_tags($limit=null, $cloud=true, $sort='freq') {
global $USER;
$id = $USER->get('id');
if ($limit || $sort != 'alpha') {
$sort = 'COUNT(t.tag) DESC';
}
else {
$sort = 't.tag ASC';
}
$tagrecords = get_records_sql_array("
SELECT
t.tag, COUNT(t.tag)
......@@ -2054,10 +2060,13 @@ function get_my_tags($limit=null, $cloud=true) {
WHERE v.owner = ?)
) t
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)
);
if ($cloud && $tagrecords) {
if (!$tagrecords) {
return false;
}
if ($cloud) {
$minfreq = $tagrecords[count($tagrecords) - 1]->count;
$maxfreq = $tagrecords[0]->count;
......@@ -2072,9 +2081,8 @@ function get_my_tags($limit=null, $cloud=true) {
$t->size = sprintf("%0.1f", $minsize + ($maxsize - $minsize) * $weight);
}
usort($tagrecords, create_function('$a,$b', 'return strnatcasecmp($a->tag, $b->tag);'));
return $tagrecords;
}
return false;
return $tagrecords;
}
function mytags_sideblock() {
......@@ -2167,13 +2175,17 @@ function build_portfolio_search_html(&$data) {
$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->assign_by_ref('data', $data->data);
$data->tablerows = $smarty->fetch('portfoliosearchresults.tpl');
$pagination = build_pagination(array(
'id' => 'results_pagination',
'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',
'datatable' => 'results',
'count' => $data->count,
......
......@@ -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);
}
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
if (empty($owner->id) || empty($owner->type)) {
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
$plugin = 'internal';
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() {
......
......@@ -844,9 +844,10 @@ class PluginSearchInternal extends PluginSearch {
* @param object $owner: owner type (user,group,institution), and id
* @param integer $limit
* @param integer $offset
* @param string $sort
* @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 (
(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 = ?)
......@@ -864,13 +865,15 @@ class PluginSearchInternal extends PluginSearch {
'owner' => $owner,
'offset' => $offset,
'limit' => $limit,
'sort' => $sort,
'count' => 0,
'data' => array(),
);
if ($count = count_records_sql('SELECT COUNT(*) ' . $from, $values, $offset, $limit)) {
$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) {
$ids = array('view' => array(), 'artefact' => array());
foreach ($data as &$d) {
......
......@@ -30,21 +30,61 @@ require('init.php');
require('searchlib.php');
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);
$js = '';
$limit = param_integer('limit', 10);
$offset = param_integer('offset', 0);
$sort = param_alpha('sort', 'name');
$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);
$hidepagination = $tag ? '' : "addElementClass('results_pagination', 'hidden');";
$js = <<<EOF
var p = 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) {
disconnectAll(elem);
connect(elem, 'onclick', function(e) {
......@@ -53,38 +93,71 @@ function rewriteTagLink(elem) {
var params = parseQueryString(href.substring(href.indexOf('?')+1, href.length));
sendjsonrequest(config.wwwroot + 'json/tagsearch.php', params, 'POST', function(data) {
p.updateResults(data);
// Update tag links in the My Tags list:
forEach(getElementsByTagAndClassName('a', 'selected', mytags_container), function(selected) {
removeElementClass(selected, 'selected');
});
// Mark the selected tag in the My Tags list:
addElementClass('tag:' + params.tag, 'selected');
// Replace the tag in the Search Results heading
var heading_tag = getFirstElementByTagAndClassName('a', 'tag', 'results_heading');
if (heading_tag) {
heading_tag.href = href;
heading_tag.innerHTML = data.data.tagdisplay;
}
if (hasElementClass('results', 'hidden')) {
removeElementClass('results', 'hidden');
removeElementClass('results_heading', 'hidden');
removeElementClass('results_pagination', 'hidden');
}
removeElementClass('results_container', 'hidden');
// Rewrite tag links in the results list:
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;
});
};
}
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');
p = {$data->pagination_js}
forEach(getElementsByTagAndClassName('a', 'tag', mytags_container), rewriteTagLink);
forEach(getElementsByTagAndClassName('a', 'tag', 'sb-mytags'), rewriteTagLink);
forEach(getElementsByTagAndClassName('a', 'tag', 'results'), rewriteTagLink);
forEach(getElementsByTagAndClassName('a', null, 'results_sort'), rewriteTagLink);
{$hidepagination}
});
EOF;
$tagsortoptions = array();
foreach (array('alpha', 'freq') as $option) {
$tagsortoptions[$option] = $option == $tagsort;
}
$smarty = smarty(array('paginator'));
$smarty->assign('PAGEHEADING', hsc(TITLE));
$smarty->assign('tags', $tags);
$smarty->assign('tagsortoptions', $tagsortoptions);
$smarty->assign('tag', $tag);
$smarty->assign_by_ref('results', $data);
$smarty->assign('INLINEJAVASCRIPT', $js);
......
......@@ -839,7 +839,9 @@ div.sideblock #friendscontrol label {
padding: 0 5px;
vertical-align: middle;
}
.mytags .tag.selected {
/* .tag-sort.selected, */
.tag-results .selected,
.mytags .selected {
color: #444;
font-weight: bold;
}
......
{include file="header.tpl"}
{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}
<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}
</div>
</div>
{else}
<div>{str tag=youhavenottaggedanythingyet}</div>
{/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>
<table id="results" class="tablerenderer fullwidth{if !$tag} hidden{/if}">
<div id="results_container" class="tag-results{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>
<tr><th></th><th></th><th></th></tr>
</thead>
......@@ -22,5 +33,6 @@
</tbody>
</table>
{$results->pagination}
</div>
{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