Skip to content

Commit

Permalink
Merge pull request #9 from CMU-313/alex/feature/filter-topics-on-sear…
Browse files Browse the repository at this point in the history
…ch-query

Search: Filter topics based on a search query from templates/partials/topic-list-bar.tpl search bar. Hides topics that do not match and shows an info message for empty list.
  • Loading branch information
alx-zhu authored Sep 24, 2024
2 parents 16ac073 + ab4756e commit 5ca0ad0
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 1 deletion.
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -72,4 +72,7 @@ link-plugins.sh
test.sh

.docker/**
!**/.gitkeep
!**/.gitkeep

# Dump
dump.rdb
37 changes: 37 additions & 0 deletions public/src/client/category.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ define('forum/category', [
},
});

handleTopicSearch();

hooks.fire('action:topics.loaded', { topics: ajaxify.data.topics });
hooks.fire('action:category.loaded', { cid: ajaxify.data.cid });
};
Expand Down Expand Up @@ -112,6 +114,41 @@ define('forum/category', [
});
}

// Search for topics in the category based on the search term.
function handleTopicSearch() {
const searchEl = $('[component="topic-search"]');
const topicEls = $('[component="category/topic"]');

if (!searchEl.length) {
return;
}

searchEl.on('keyup', function () {
const searchTerm = searchEl.val().toLowerCase();
topicEls.each(function () {
const topicEl = $(this);
const titleEl = topicEl.find('[component="topic/header"] a');
const title = titleEl.text().toLowerCase();
const isMatch = title.indexOf(searchTerm) !== -1;
console.log(`Title: ${title}\n ${isMatch ? 'Hidden' : 'Visible'}\n`);

topicEl.toggleClass('hidden', !isMatch);
});

const visibleTopics = topicEls.filter(':not(.hidden)');
if (visibleTopics.length === 0) {
if ($('[component="category/topic/no-matches"]').length === 0) {
$(`<div component="category/topic/no-matches" class="alert alert-info">No topics match the search term ${searchTerm}.</div>`)
.insertAfter('[component="category/topic"]:last');
} else {
$('[component="category/topic/no-matches"]').removeClass('hidden');
}
} else {
$('[component="category/topic/no-matches"]').addClass('hidden');
}
});
}

Category.toTop = function () {
navigator.scrollTop(0);
};
Expand Down
62 changes: 62 additions & 0 deletions topic-list-bar.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<div class="{{{ if config.theme.stickyToolbar }}}sticky-tools{{{ end }}} mb-3">
<nav class="topic-list-header d-flex flex-nowrap my-2 p-0 border-0 rounded">
<div class="d-flex flex-row p-2 text-bg-light gap-1 border rounded w-100 align-items-center">
<div component="category/controls" class="d-flex me-auto mb-0 gap-2 flex-wrap">
{{{ if template.category }}}
<!-- IMPORT partials/category/watch.tpl -->
<!-- IMPORT partials/tags/filter-dropdown-left.tpl -->
<!-- IMPORT partials/category/sort.tpl -->
{{{ end }}}
{{{ if (template.popular || template.top)}}}
<!-- IMPORT partials/topic-terms.tpl -->
{{{ end }}}
{{{ if (template.unread || (template.recent || (template.popular || template.top))) }}}
<!-- IMPORT partials/topic-filters.tpl -->
<!-- IMPORT partials/category/filter-dropdown-left.tpl -->
<!-- IMPORT partials/tags/filter-dropdown-left.tpl -->
{{{ end }}}
{{{ if template.unread }}}
<div class="markread btn-group {{{ if !topics.length }}}hidden{{{ end }}}">
<!-- IMPORT partials/category/selector-dropdown-left.tpl -->
</div>
{{{ end }}}
{{{ if template.tag }}}
<!-- IMPORT partials/category/filter-dropdown-left.tpl -->
<!-- IMPORT partials/tags/watch.tpl -->
{{{ end }}}
<!-- IMPORT partials/category/tools.tpl -->

{{{ if (!feeds:disableRSS && rssFeedUrl) }}}
<a class="btn-ghost-sm d-none d-lg-flex align-self-stretch" target="_blank" href="{rssFeedUrl}" itemprop="item" title="[[global:rss-feed]]"><i class="fa fa-rss text-primary"></i></a>
{{{ end }}}

<a href="{{{ if template.category }}}{url}{{{ else }}}{config.relative_path}/{selectedFilter.url}{querystring}{{{ end }}}" class="btn btn-secondary fw-semibold position-absolute top-100 translate-middle-x start-50 mt-1 hide" style="--bs-btn-padding-y: .25rem; --bs-btn-padding-x: .5rem; --bs-btn-font-size: .75rem;" id="new-topics-alert">
<i class="fa fa-fw fa-arrow-up"></i> [[recent:load-new-posts]]
</a>
</div>

<div class="d-flex gap-1 align-items-center">
{{{ if template.category }}}
{{{ if privileges.topics:create }}}

<div class="input-group">
<input type="text" class="form-control form-control-sm" placeholder="Search" id="group-search">
<span class="input-group-text search-button"><i class="fa fa-search"></i></span>
</div>

<a href="{config.relative_path}/compose?cid={cid}" component="category/post" id="new_topic" class="btn btn-primary btn-sm text-nowrap" data-ajaxify="false" role="button">[[category:new-topic-button]]</a>

{{{ end }}}
{{{ else }}}
{{{ if canPost }}}
<!-- IMPORT partials/buttons/newTopic.tpl -->
{{{ end }}}
{{{ end }}}
<!-- only show login button if not logged in and doesn't have any posting privilege -->
{{{ if (!loggedIn && (!privileges.topics:create && !canPost))}}}
<a component="category/post/guest" href="{config.relative_path}/login" class="btn btn-sm btn-primary">[[category:guest-login-post]]</a>
{{{ end }}}
</div>
</div>
</nav>
</div>

0 comments on commit 5ca0ad0

Please sign in to comment.