feat(home): sort podcasts by recent activity + add dropdown menu to choose between sorting options

fixes #164
This commit is contained in:
Yassine Doghri 2022-02-05 16:57:20 +00:00
parent 91128fad7a
commit 7b89da6106
6 changed files with 90 additions and 3 deletions

View File

@ -27,7 +27,12 @@ class HomeController extends BaseController
return redirect()->to(rtrim(host_url(), '/') . $route);
}
$allPodcasts = (new PodcastModel())->findAll();
$sortOptions = ['activity', 'created_desc', 'created_asc'];
$sortBy = in_array($this->request->getGet('sort'), $sortOptions, true) ? $this->request->getGet(
'sort'
) : 'activity';
$allPodcasts = (new PodcastModel())->getAllPodcasts($sortBy);
// check if there's only one podcast to redirect user to it
if (count($allPodcasts) === 1) {
@ -38,6 +43,7 @@ class HomeController extends BaseController
$data = [
'metatags' => get_home_metatags(),
'podcasts' => $allPodcasts,
'sortBy' => $sortBy,
];
return view('home', $data);

View File

@ -10,5 +10,11 @@ declare(strict_types=1);
return [
'all_podcasts' => 'All podcasts',
'sort_by' => 'Sort by',
'sort_options' => [
'activity' => 'Recent activity',
'created_desc' => 'Newest first',
'created_asc' => 'Oldest first',
],
'no_podcast' => 'No podcast found',
];

View File

@ -10,5 +10,11 @@ declare(strict_types=1);
return [
'all_podcasts' => 'Tous les podcasts',
'sort_by' => 'Trier par',
'sort_options' => [
'activity' => 'Activité récente',
'created_desc' => 'Le plus récent dabord',
'created_asc' => 'Le plus ancien dabord',
],
'no_podcast' => 'Aucun podcast trouvé',
];

View File

@ -166,6 +166,42 @@ class PodcastModel extends Model
return $found;
}
/**
* @param 'activity'|'created_asc'|'created_desc' $orderBy
*
* @return Podcast[]
*/
public function getAllPodcasts(string $orderBy = null): array
{
if ($orderBy === 'activity') {
$prefix = $this->db->getPrefix();
$fediverseTablePrefix = config('Fediverse')
->tablesPrefix;
$this->select(
'podcasts.*, MAX(' . $prefix . $fediverseTablePrefix . 'posts.published_at' . ') as max_published_at'
)
->join(
$fediverseTablePrefix . 'posts',
$fediverseTablePrefix . 'posts.actor_id = podcasts.actor_id',
'left'
)
->where(
'`' . $prefix . $fediverseTablePrefix . 'posts`.`published_at` <= NOW()',
null,
false
)->orWhere($fediverseTablePrefix . 'posts.published_at', null)
->groupBy('cp_podcasts.actor_id')
->orderBy('max_published_at', 'DESC');
} elseif ($orderBy === 'created_desc') {
$this->orderBy('created_at', 'DESC');
} elseif ($orderBy === 'created_asc') {
$this->orderBy('created_at', 'ASC');
}
return $this->findAll();
}
/**
* Gets all the podcasts a given user is contributing to
*
@ -378,6 +414,10 @@ class PodcastModel extends Model
{
$podcast = (new self())->getPodcastById(is_array($data['id']) ? $data['id'][0] : $data['id']);
// delete cache for users' podcasts
cache()
->deleteMatching('user*podcasts');
if ($podcast !== null) {
// delete cache all podcast pages
cache()

View File

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<g>
<path d="M0 0H24V24H0Z" fill="none"/>
<path d="M3 18H7V16H3ZM3 6V8H21V6Zm0 7H15V11H3Z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 178 B

View File

@ -47,10 +47,33 @@
</h1>
</header>
<main class="container flex-1 px-4 py-10 mx-auto">
<Heading tagName="h2" class="inline-block mb-2"><?= lang('Home.all_podcasts') ?> (<?= count(
<div class="flex flex-wrap items-center justify-between py-2 border-b border-subtle gap-x-4">
<Heading tagName="h2" class="inline-block"><?= lang('Home.all_podcasts') ?> (<?= count(
$podcasts,
) ?>)</Heading>
<div class="grid gap-4 grid-cols-cards">
<button class="inline-flex items-center px-2 py-1 text-sm font-semibold focus:ring-accent" id="sortby-dropdown" data-dropdown="button" data-dropdown-target="sortby-dropdown-menu" aria-haspopup="true" aria-expanded="false"><?= icon('sort', 'mr-1 text-xl opacity-50') . lang('Home.sort_by') ?></button>
<DropdownMenu id="sortby-dropdown-menu" labelledby="sortby-dropdown" items="<?= esc(json_encode([
[
'type' => 'link',
'title' => ($sortBy === 'activity' ? '✓ ' : '') . lang('Home.sort_options.activity'),
'uri' => route_to('home') . '?sort=activity',
'class' => $sortBy === 'activity' ? 'font-semibold' : '',
],
[
'type' => 'link',
'title' => ($sortBy === 'created_desc' ? '✓ ' : '') . lang('Home.sort_options.created_desc'),
'uri' => route_to('home') . '?sort=created_desc',
'class' => $sortBy === 'created_desc' ? 'font-semibold' : '',
],
[
'type' => 'link',
'title' => ($sortBy === 'created_asc' ? '✓ ' : '') . lang('Home.sort_options.created_asc'),
'uri' => route_to('home') . '?sort=created_asc',
'class' => $sortBy === 'created_asc' ? 'font-semibold' : '',
],
])) ?>" />
</div>
<div class="grid gap-4 mt-4 grid-cols-cards">
<?php if ($podcasts): ?>
<?php foreach ($podcasts as $podcast): ?>
<a href="<?= $podcast->link ?>" class="relative w-full h-full overflow-hidden transition shadow focus:ring-accent rounded-xl border-subtle hover:shadow-xl focus:shadow-xl group border-3">