Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement basic talks filter based on language and kind #384

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 1 addition & 7 deletions app/controllers/events_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,7 @@ def index
def show
set_meta_tags(@event)

event_talks = @event.talks
if params[:q].present?
talks = event_talks.pagy_search(params[:q])
@pagy, @talks = pagy_meilisearch(talks, limit: 21)
else
@pagy, @talks = pagy(event_talks.with_essential_card_data.order(date: :desc), limit: 21)
end
@talks = @event.talks.with_essential_card_data.order(date: :desc)
end

# GET /events/1/edit
Expand Down
3 changes: 3 additions & 0 deletions app/javascript/controllers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ application.register("scroll-position", ScrollPositionController)
import SplideController from "./splide_controller"
application.register("splide", SplideController)

import TalksFilterController from "./talks_filter_controller"
application.register("talks-filter", TalksFilterController)

import TransitionController from "./transition_controller"
application.register("transition", TransitionController)

Expand Down
63 changes: 63 additions & 0 deletions app/javascript/controllers/talks_filter_controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { Controller } from '@hotwired/stimulus'

export default class extends Controller {
static targets = ['button', 'none']
static classes = ['active']
static values = {
kind: {
type: String,
default: 'all'
},
language: {
type: String,
default: 'all'
}
}

selectKind (event) {
const target = (event.target.dataset.kindValue) ? event.target : event.target.closest('[data-kind-value]')

if (!target) return

const value = target.dataset.kindValue
this.kindValue = (this.kindValue === value) ? 'all' : value
}

selectLanguage (event) {
const target = (event.target.dataset.languageValue) ? event.target : event.target.closest('[data-language-value]')

if (!target) return

const value = target.dataset.languageValue
this.languageValue = (this.languageValue === value) ? 'all' : value
}

kindValueChanged () {
this.updateFilterResult()
}

languageValueChanged () {
this.updateFilterResult()
}

updateFilterResult () {
this.buttonTargets.forEach(button => button.classList.remove(...this.activeClasses))
this.buttonTargets.find(button => button.dataset.languageValue === this.languageValue)?.classList.add(...this.activeClasses)
this.buttonTargets.find(button => button.dataset.kindValue === this.kindValue)?.classList.add(...this.activeClasses)

document.querySelectorAll('.talk-all').forEach(talk => talk.classList.add('hidden'))
this.element.querySelectorAll('.count').forEach(talk => talk.classList.add('hidden'))

this.element.querySelectorAll(`.count-kind.count-language-${this.languageValue}`).forEach(talk => talk.classList.remove('hidden'))
this.element.querySelectorAll(`.count-language.count-kind-${this.kindValue}`).forEach(talk => talk.classList.remove('hidden'))

const matchingTalks = document.querySelectorAll(`.talk-kind-${this.kindValue}.talk-language-${this.languageValue}`)
matchingTalks.forEach(talk => talk.classList.remove('hidden'))

if (matchingTalks.length === 0) {
this.noneTarget.classList.remove('hidden')
} else {
this.noneTarget.classList.add('hidden')
}
}
}
19 changes: 15 additions & 4 deletions app/models/talk.rb
Original file line number Diff line number Diff line change
Expand Up @@ -117,10 +117,21 @@ def analyze_talk_topics!
scope :without_topics, -> { where.missing(:talk_topics) }
scope :with_topics, -> { joins(:talk_topics) }

scope :with_essential_card_data, -> do
select(:id, :slug, :title, :date, :thumbnail_sm, :thumbnail_lg, :video_id, :video_provider, :event_id, :language)
.includes(:speakers, :event)
end
scope :with_essential_card_data, -> {
select(
:id,
:slug,
:kind,
:title,
:date,
:thumbnail_sm,
:thumbnail_lg,
:video_id,
:video_provider,
:event_id,
:language
).includes(:speakers, :event)
}

def managed_by?(visiting_user)
return false unless visiting_user.present?
Expand Down
5 changes: 2 additions & 3 deletions app/views/events/show.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<%= image_tag image_path(@event.banner_image_path), class: "w-full max-h- aspect-auto container" %>
</div>

<div class="container py-8">
<div class="container pt-8">
<div class="block lg:flex gap-8 align-center justify-between">
<div class="flex flex-col lg:flex-row gap-8 items-center lg:justify-right text-center lg:text-left mb-6 lg:mb-0">
<%= image_tag image_path(@event.avatar_image_path),
Expand Down Expand Up @@ -42,6 +42,7 @@
</div>

<div class="container py-8">
<%= render partial: "talks/talk_filter", locals: {talks: @talks} %>

<div class="flex items-start flex-wrap gap-8 sm:flex-nowrap w-full">
<div class="w-full">
Expand Down Expand Up @@ -71,8 +72,6 @@
</div>
</div>
<% end %>

<%== pagy_nav(@pagy) if @pagy.pages > 1 %>
</div>
</div>
</div>
2 changes: 2 additions & 0 deletions app/views/speakers/show.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
</div>

<div class="w-full">
<%= render partial: "talks/talk_filter", locals: {talks: @talks} %>

<div id="talks" class="min-w-full grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-8 h-full sm:p-4">
<%= render partial: "talks/card",
collection: @talks,
Expand Down
2 changes: 1 addition & 1 deletion app/views/talks/_card.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<% language = Language.by_code(talk.language) %>

<div class="card card-compact bg-white shadow-xl w-full" id="<%= dom_id talk %>">
<div class="card card-compact bg-white shadow-xl w-full <%= "talk-all talk-kind-all talk-kind-#{talk.kind} talk-language-all talk-language-#{talk.language}" %>" id="<%= dom_id talk %>">
<%= link_to talk_path(talk, back_to: back_to, back_to_title: back_to_title), class: "flex aspect-video overflow-hidden relative" do %>
<% if language && language != "English" %>
<div class="absolute top-0 left-0 z-10 m-3 p-1 px-2 bg-black/15 backdrop-blur-md rounded-full group">
Expand Down
47 changes: 47 additions & 0 deletions app/views/talks/_talk_filter.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<% classes = "bg-white hover:bg-gray-100 cursor-pointer px-4 py-2 text-sm text-gray-500 rounded-full border font-bold select-none" %>
<% active_classes = "bg-red-500 hover:bg-red-600 text-white border-red-500" %>

<% talks_by_language = talks.group_by(&:language) %>
<% talks_by_kind = talks.group_by(&:kind) %>

<% if talks_by_language.length >= 2 || talks_by_kind.length >= 2 %>
<div class="mb-6" data-controller="talks-filter" data-talks-filter-active-class="<%= active_classes %>">
<div class="flex divide-x">
<% if talks_by_kind.length >= 2 %>
<div class="flex gap-2 mb-3 pr-6 justify-center">
<% talks_by_kind.each do |kind, talks| %>
<div data-action="click->talks-filter#selectKind" data-talks-filter-target="button" class="<%= classes %>" data-kind-value="<%= kind %>">
<%= kind.humanize.pluralize %>
<span class="count count-kind count-language-all">(<%= talks.length %>)</span>

<% talks_by_language.each do |language, talks| %>
<span class="hidden count count-kind count-language-<%= language %>">(<%= talks.select { |talk| talk.kind == kind }.count %>)</span>
<% end %>
</div>
<% end %>
</div>
<% end %>

<% if talks_by_language.length >= 2 %>
<div class="flex gap-2 mb-3 px-6 justiy-center">
<% talks_by_language.each do |language, talks| %>
<div data-action="click->talks-filter#selectLanguage" data-talks-filter-target="button" class="<%= classes %>" data-language-value="<%= language %>">
<%= Language.by_code(language) %>
<span class="count count-language count-kind-all">(<%= talks.length %>)</span>

<% talks_by_kind.each do |kind, talks| %>
<span class="hidden count count-language count-kind-<%= kind %>">(<%= talks.select { |talk| talk.language == language }.count %>)</span>
<% end %>
</div>
<% end %>
</div>
<% end %>
</div>

<div class="hidden" data-talks-filter-target="none">
<div class="w-full border bg-white text-gray-500 flex justify-center content-center font-medium text-lg rounded-lg py-10 mt-6">
No videos matched your filters.
</div>
</div>
</div>
<% end %>