Skip to content

Commit 37a141d

Browse files
authored
Merge pull request #224 from topcoder-platform/issues-133
Issues-95
2 parents d562c67 + 973fb0f commit 37a141d

File tree

7 files changed

+279
-3
lines changed

7 files changed

+279
-3
lines changed

config/vanilla/bootstrap.before.php

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,3 +399,185 @@ function updateRolePermissions($roleType, $roles) {
399399
}
400400
}
401401
}
402+
403+
if (!function_exists('sortsDropDown')) {
404+
/**
405+
* Returns a sorting drop-down menu.
406+
*
407+
* @param string $baseUrl Target URL with no query string applied.
408+
* @param array $filters A multidimensional array of rows with the following properties:
409+
* ** 'name': Friendly name for the filter.
410+
* ** 'param': URL parameter associated with the filter.
411+
* ** 'value': A value for the URL parameter.
412+
* @param string $extraClasses any extra classes you add to the drop down
413+
* @param string|null $default The default label for when no filter is active. If `null`, the default label is "All".
414+
* @param string|null $defaultURL URL override to return to the default, unfiltered state.
415+
* @param string $label Text for the label to attach to the cont
416+
* @return string
417+
*/
418+
function sortsDropDown($baseUrl, array $filters = [], $extraClasses = '', $default = null, $defaultUrl = null, $label = 'Sort') {
419+
if ($default === null) {
420+
$default = t('All');
421+
}
422+
423+
$links = [];
424+
$active = paramPreference(
425+
'sort',
426+
'CategorySort',
427+
null,//'Vanilla.SaveCategorySortPreference',
428+
null,
429+
false
430+
);
431+
// Translate filters into links.
432+
foreach ($filters as $filter) {
433+
// Make sure we have the bare minimum: a label and a URL parameter.
434+
if (!array_key_exists('name', $filter)) {
435+
throw new InvalidArgumentException('Sort does not have a name field.');
436+
}
437+
if (!array_key_exists('param', $filter)) {
438+
throw new InvalidArgumentException('Sort does not have a param field.');
439+
}
440+
441+
// Prepare for consumption by linkDropDown.
442+
$query = [$filter['param'] => $filter['value']];
443+
if (array_key_exists('extra', $filter) && is_array($filter['extra'])) {
444+
$query += $filter['extra'];
445+
}
446+
$url = url($baseUrl . '?' . http_build_query($query));
447+
$link = [
448+
'name' => $filter['name'],
449+
'url' => $url
450+
];
451+
452+
// If we don't already have an active link, and this parameter and value match, this is the active link.
453+
if ($active === null && Gdn::request()->get($filter['param']) == $filter['value']) {
454+
$active = $filter['value'];
455+
$link['active'] = true;
456+
} else if ($active == $filter['value']){
457+
$link['active'] = true;
458+
$active = $filter['value'];
459+
}
460+
461+
// Queue up another filter link.
462+
$links[] = $link;
463+
}
464+
465+
// Add the default link to the top of the list.
466+
array_unshift($links, [
467+
'active' => $active === null,
468+
'name' => $default,
469+
'url' => $defaultUrl ?: $baseUrl
470+
]);
471+
472+
// Generate the markup for the drop down menu.
473+
$output = linkDropDown($links, 'selectBox-following ' . trim($extraClasses), t($label) . ': ');
474+
return $output;
475+
}
476+
}
477+
478+
if (!function_exists('categorySorts')) {
479+
/**
480+
* Returns category sorting.
481+
*
482+
* @param string $extraClasses any extra classes you add to the drop down
483+
* @return string
484+
*/
485+
function categorySorts($extraClasses = '') {
486+
if (!Gdn::session()->isValid()) {
487+
return;
488+
}
489+
490+
$baseUrl = Gdn::request()->path();
491+
$transientKey = Gdn::session()->transientKey();
492+
$filters = [
493+
[
494+
'name' => t('New'),
495+
'param' => 'sort',
496+
'value' => 'new',
497+
'extra' => ['TransientKey' => $transientKey, 'save' => 1]
498+
],
499+
500+
[
501+
'name' => t('Old'),
502+
'param' => 'sort',
503+
'value' => 'old',
504+
'extra' => ['TransientKey' => $transientKey, 'save' => 1]
505+
]
506+
];
507+
508+
$defaultParams = ['TransientKey' => $transientKey];
509+
if (Gdn::request()->get('sort')) {
510+
$defaultParams['sort'] = Gdn::request()->get('sort');
511+
}
512+
513+
if (!empty($defaultParams)) {
514+
$defaultUrl = $baseUrl.'?'.http_build_query($defaultParams);
515+
} else {
516+
$defaultUrl = $baseUrl;
517+
}
518+
519+
return sortsDropDown(
520+
$baseUrl,
521+
$filters,
522+
$extraClasses,
523+
t('All'),
524+
$defaultUrl,
525+
'Sort'
526+
);
527+
}
528+
}
529+
530+
if (!function_exists('discussionSorts')) {
531+
/**
532+
* Returns discussions sorting.
533+
*
534+
* @param string $extraClasses any extra classes you add to the drop down
535+
* @return string
536+
*/
537+
function discussionSorts($extraClasses = '') {
538+
if (!Gdn::session()->isValid()) {
539+
return;
540+
}
541+
542+
$baseUrl = Gdn::request()->path();
543+
$transientKey = Gdn::session()->transientKey();
544+
545+
$filters = [
546+
[
547+
'name' => t('New'),
548+
'param' => 'sort',
549+
'value' => 'new',
550+
'extra' => ['TransientKey' => $transientKey, 'save' => 1]
551+
],
552+
[
553+
'name' => t('Old'),
554+
'param' => 'sort',
555+
'value' => 'old',
556+
'extra' => ['TransientKey' => $transientKey, 'save' => 1]
557+
]
558+
];
559+
560+
561+
$defaultParams = ['save' => 1, 'TransientKey' => $transientKey];
562+
if (Gdn::request()->get('sort')) {
563+
$defaultParams['sort'] = Gdn::request()->get('sort');
564+
}
565+
566+
if (!empty($defaultParams)) {
567+
$defaultUrl = $baseUrl.'?'.http_build_query($defaultParams);
568+
} else {
569+
$defaultUrl = $baseUrl;
570+
}
571+
572+
return sortsDropDown(
573+
$baseUrl,
574+
$filters,
575+
$extraClasses,
576+
t('All'),
577+
$defaultUrl,
578+
'Sort'
579+
);
580+
}
581+
}
582+
583+

vanilla/applications/vanilla/controllers/class.categoriescontroller.php

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ class CategoriesController extends VanillaController {
3131
/** @var bool Value indicating if the category-following filter should be displayed when rendering a view */
3232
public $enableFollowingFilter = true;//false;
3333

34+
const SORT_LAST_POST = 'new';
35+
const SORT_OLDEST_POST = 'old';
3436

3537
/**
3638
* @var \Closure $categoriesCompatibilityCallback A backwards-compatible callback to get `$this->data('Categories')`.
@@ -273,6 +275,7 @@ public function index($categoryIdentifier = '', $page = '0') {
273275
]);
274276

275277
$saveFollowing = Gdn::request()->get('save') && Gdn::session()->validateTransientKey(Gdn::request()->get('TransientKey', ''));
278+
276279
$followed = paramPreference(
277280
'followed',
278281
'FollowedCategories',
@@ -283,9 +286,23 @@ public function index($categoryIdentifier = '', $page = '0') {
283286
} else {
284287
$this->enableFollowingFilter = $followed = false;
285288
}
289+
286290
$this->setData('EnableFollowingFilter', $this->enableFollowingFilter);
287291
$this->setData('Followed', $followed);
288292

293+
$saveSorting =Gdn::request()->get('sort') && Gdn::request()->get('save') && Gdn::session()->validateTransientKey(Gdn::request()->get('TransientKey', ''));
294+
295+
$sort = paramPreference(
296+
'sort',
297+
'CategorySort',
298+
null,//'Vanilla.SaveCategorySortPreference',
299+
null,
300+
$saveSorting
301+
);
302+
303+
$this->log('index: sorts: after', ['$sort' => $sort, '$saveSorting'=>$saveSorting]);
304+
$this->setData('CategorySort', $sort);
305+
289306
if ($categoryIdentifier == '') {
290307
switch ($layout) {
291308
case 'mixed':
@@ -585,6 +602,24 @@ public function all($Category = '', $displayAs = '') {
585602
);
586603
}
587604

605+
if($this->data('CategorySort')) {
606+
if( $this->data('CategorySort') == self::SORT_OLDEST_POST) {
607+
usort($categoryTree, function ($a, $b) {
608+
return Gdn_Format::toTimestamp($a['LastDateInserted']) - Gdn_Format::toTimestamp($b['LastDateInserted']);
609+
});
610+
611+
} else if( $this->data('CategorySort') == self::SORT_LAST_POST) {
612+
usort($categoryTree, function ($a, $b) {
613+
return Gdn_Format::toTimestamp($b['LastDateInserted']) - Gdn_Format::toTimestamp($a['LastDateInserted']);
614+
615+
});
616+
}
617+
} else {
618+
usort($categoryTree, function ($a, $b) { // desc
619+
return Gdn_Format::toTimestamp($b['LastDateInserted']) - Gdn_Format::toTimestamp($a['LastDateInserted']);
620+
});
621+
}
622+
588623
$this->setData('CategoryTree', $categoryTree);
589624

590625
// Add modules

vanilla/applications/vanilla/models/class.discussionmodel.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,8 @@ class DiscussionModel extends Gdn_Model {
6464
protected static $allowedSorts = [
6565
'hot' => ['key' => 'hot', 'name' => 'Hot', 'orderBy' => ['DateLastComment' => 'desc']],
6666
'top' => ['key' => 'top', 'name' => 'Top', 'orderBy' => ['Score' => 'desc', 'DateInserted' => 'desc']],
67-
'new' => ['key' => 'new', 'name' => 'New', 'orderBy' => ['DateInserted' => 'desc']]
67+
'new' => ['key' => 'new', 'name' => 'New', 'orderBy' => ['DateInserted' => 'desc']],
68+
'old' => ['key' => 'old', 'name' => 'Old', 'orderBy' => ['DateInserted' => 'asc']]
6869
];
6970

7071
/**

vanilla/applications/vanilla/views/categories/all.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,11 @@
1010
echo wrap($description, 'div', ['class' => 'P PageDescription']);
1111
}
1212
$this->fireEvent('AfterPageTitle');
13+
echo '<div class="PageControls Top">';
1314
if ($this->data('EnableFollowingFilter')) {
14-
echo '<div class="PageControls Top">'.categoryFilters().'</div>';
15+
echo categoryFilters();
1516
}
17+
echo categorySorts();
18+
echo '</div>';
1619
$categories = $this->data('CategoryTree');
1720
writeCategoryList($categories, 1);
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php if (!defined('APPLICATION')) exit();
2+
echo '<h1 class="H HomepageTitle">'.$this->data('Title').'</h1>';
3+
echo '<div class="PageControls Top">';
4+
if ($this->data('EnableFollowingFilter')) {
5+
echo categoryFilters();
6+
}
7+
echo categorySorts();
8+
echo '</div>';
9+
10+
$ViewLocation = $this->fetchViewLocation('discussions', 'discussions');
11+
?>
12+
<div class="Categories">
13+
<?php if ($this->CategoryData->numRows() > 0): ?>
14+
<?php foreach ($this->CategoryData->result() as $Category) :
15+
if ($Category->CategoryID <= 0)
16+
continue;
17+
18+
$this->Category = $Category;
19+
$this->DiscussionData = $this->CategoryDiscussionData[$Category->CategoryID];
20+
21+
if ($this->DiscussionData->numRows() > 0) : ?>
22+
23+
<div class="CategoryBox Category-<?php echo $Category->UrlCode; ?>">
24+
<?php echo getOptions($Category); ?>
25+
<h2 class="H"><?php
26+
echo anchor(htmlspecialchars($Category->Name), categoryUrl($Category));
27+
Gdn::controller()->EventArguments['Category'] = $Category;
28+
Gdn::controller()->fireEvent('AfterCategoryTitle');
29+
?></h2>
30+
31+
<ul class="DataList Discussions">
32+
<?php include($this->fetchViewLocation('discussions', 'discussions')); ?>
33+
</ul>
34+
35+
<?php if ($this->DiscussionData->numRows() == $this->DiscussionsPerCategory) : ?>
36+
<div class="MorePager">
37+
<?php echo anchor(t('More Discussions'), '/categories/'.$Category->UrlCode); ?>
38+
</div>
39+
<?php endif; ?>
40+
41+
</div>
42+
43+
<?php endif; ?>
44+
45+
<?php endforeach; ?>
46+
<?php else: ?>
47+
<div class="Empty"><?php echo t('No categories were found.'); ?></div>
48+
<?php endif; ?>
49+
</div>

vanilla/applications/vanilla/views/categories/table.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,12 @@
77
<?php
88
$this->fireEvent('AfterDescription');
99
$this->fireEvent('AfterPageTitle');
10+
echo '<div class="PageControls Top">';
1011
if ($this->data('EnableFollowingFilter')) {
11-
echo '<div class="PageControls Top">'.categoryFilters().'</div>';
12+
echo categoryFilters();
1213
}
14+
echo categorySorts();
15+
echo '</div>';
1316
$categories = $this->data('CategoryTree');
1417
writeCategoryTable($categories);
1518
?>

vanilla/applications/vanilla/views/discussions/index.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@
4545
if ($this->data('EnableFollowingFilter')) {
4646
echo discussionFilters();
4747
}
48+
if($this instanceof CategoriesController) {
49+
echo discussionSorts();
50+
}
4851
$this->fireEvent('PageControls');
4952
echo '</div>';
5053

0 commit comments

Comments
 (0)