diff --git a/app/controllers/cards/previews_controller.rb b/app/controllers/cards/previews_controller.rb new file mode 100644 index 000000000..f8893266f --- /dev/null +++ b/app/controllers/cards/previews_controller.rb @@ -0,0 +1,8 @@ +class Cards::PreviewsController < ApplicationController + include FilterScoped + before_action :set_filter, only: :index + + def index + set_page_and_extract_portion_from @filter.cards, per_page: CardsController::PAGE_SIZE + end +end diff --git a/app/controllers/cards_controller.rb b/app/controllers/cards_controller.rb index 83debddca..d0b751613 100644 --- a/app/controllers/cards_controller.rb +++ b/app/controllers/cards_controller.rb @@ -1,17 +1,17 @@ +require "ostruct" + class CardsController < ApplicationController - include CollectionScoped + include CollectionScoped, FilterScoped skip_before_action :set_collection, only: :index - - before_action :set_filter, only: :index before_action :set_card, only: %i[ show edit update destroy ] - RECENTLY_CLOSED_LIMIT = 100 + PAGE_SIZE = 50 def index - @considering_cards = @filter.cards.considering.load_async - @doing_cards = @filter.cards.doing.load_async - @closed_cards = @filter.with(indexed_by: "closed").cards.recently_closed_first.limit(RECENTLY_CLOSED_LIMIT).load_async + @considering = page_and_filter_for @filter.with(engagement_status: "considering"), per_page: PAGE_SIZE + @doing = page_and_filter_for @filter.with(engagement_status: "doing"), per_page: PAGE_SIZE + @closed = page_and_filter_for @filter.with(indexed_by: "closed"), per_page: PAGE_SIZE end def create @@ -35,16 +35,16 @@ class CardsController < ApplicationController end private - DEFAULT_PARAMS = { indexed_by: "newest" } - - def set_filter - @filter = Current.user.filters.from_params params.reverse_merge(**DEFAULT_PARAMS).permit(*Filter::PERMITTED_PARAMS) - end - def set_card @card = @collection.cards.find params[:id] end + def page_and_filter_for(filter, per_page: nil) + OpenStruct.new \ + page: GearedPagination::Recordset.new(filter.cards, per_page:).page(1), + filter: filter + end + def card_params params.expect(card: [ :status, :title, :color, :due_on, :image, :draft_comment, tag_ids: [] ]) end diff --git a/app/controllers/concerns/filter_scoped.rb b/app/controllers/concerns/filter_scoped.rb new file mode 100644 index 000000000..f3d5df02c --- /dev/null +++ b/app/controllers/concerns/filter_scoped.rb @@ -0,0 +1,14 @@ +module FilterScoped + extend ActiveSupport::Concern + + included do + before_action :set_filter, only: :index + end + + private + DEFAULT_PARAMS = { indexed_by: "newest" } + + def set_filter + @filter = Current.user.filters.from_params params.reverse_merge(**DEFAULT_PARAMS).permit(*Filter::PERMITTED_PARAMS) + end +end diff --git a/app/helpers/cards_helper.rb b/app/helpers/cards_helper.rb index d52545b93..ba75a6d4a 100644 --- a/app/helpers/cards_helper.rb +++ b/app/helpers/cards_helper.rb @@ -10,4 +10,20 @@ module CardsHelper "--card-rotate: #{value}deg;" end + + def cards_next_page_link(target, page:, filter:, fetch_on_visible: false, data: {}, **options) + url = cards_previews_path(target: target, page: page.next_param, **filter.as_params) + + if fetch_on_visible + data[:controller] = "#{data[:controller]} fetch-on-visible" + data[:fetch_on_visible_url_value] = url + end + + link_to "Load more", + url, + id: "#{target}-load-page-#{page.next_param}", + data: { turbo_stream: true, **data }, + class: "btn txt-small", + **options + end end diff --git a/app/models/card.rb b/app/models/card.rb index 50f2f541b..c58507125 100644 --- a/app/models/card.rb +++ b/app/models/card.rb @@ -29,6 +29,13 @@ class Card < ApplicationRecord end end + scope :by_engagement_status, ->(status) do + case status.to_s + when "considering" then considering + when "doing" then doing + end + end + def cache_key [ super, collection&.name ].compact.join("/") end diff --git a/app/models/concerns/filter/params.rb b/app/models/concerns/filter/params.rb deleted file mode 100644 index 26dc1f437..000000000 --- a/app/models/concerns/filter/params.rb +++ /dev/null @@ -1,21 +0,0 @@ -module Filter::Params - extend ActiveSupport::Concern - - PERMITTED_PARAMS = %i[ - indexed_by assignment_status collection_ids creator_ids - assignee_ids stage_ids tag_ids terms - ].freeze - - def as_params - self.class.normalize_params( - indexed_by: indexed_by, - assignment_status: assignment_status, - collection_ids: collections.ids, - creator_ids: creators.ids, - assignee_ids: assignees.ids, - stage_ids: stages.ids, - tag_ids: tags.ids, - terms: terms - ) - end -end diff --git a/app/models/filter.rb b/app/models/filter.rb index 62f89015c..1ec1a5e6c 100644 --- a/app/models/filter.rb +++ b/app/models/filter.rb @@ -20,6 +20,7 @@ class Filter < ApplicationRecord @cards ||= begin result = creator.accessible_cards.indexed_by(indexed_by) result = result.active unless indexed_by.closed? + result = result.by_engagement_status(engagement_status) if engagement_status.present? result = result.unassigned if assignment_status.unassigned? result = result.assigned_to(assignees.ids) if assignees.present? result = result.where(creator_id: creators.ids) if creators.present? diff --git a/app/models/filter/fields.rb b/app/models/filter/fields.rb index 56fca6ac7..ce284b398 100644 --- a/app/models/filter/fields.rb +++ b/app/models/filter/fields.rb @@ -16,7 +16,7 @@ module Filter::Fields end included do - store_accessor :fields, :assignment_status, :indexed_by, :terms + store_accessor :fields, :assignment_status, :indexed_by, :terms, :engagement_status def assignment_status super.to_s.inquiry @@ -26,6 +26,10 @@ module Filter::Fields (super || default_indexed_by).inquiry end + def engagement_status + super&.inquiry + end + def terms Array(super) end diff --git a/app/models/filter/params.rb b/app/models/filter/params.rb index dd519ec84..7a4b85d60 100644 --- a/app/models/filter/params.rb +++ b/app/models/filter/params.rb @@ -4,6 +4,7 @@ module Filter::Params PERMITTED_PARAMS = [ :assignment_status, :indexed_by, + :engagement_status, assignee_ids: [], creator_ids: [], collection_ids: [], @@ -35,6 +36,7 @@ module Filter::Params def as_params {}.tap do |params| params[:indexed_by] = indexed_by + params[:engagement_status] = engagement_status params[:assignment_status] = assignment_status params[:terms] = terms params[:tag_ids] = tags.ids diff --git a/app/views/cards/index.html.erb b/app/views/cards/index.html.erb index b8c80ab1d..c57284da5 100644 --- a/app/views/cards/index.html.erb +++ b/app/views/cards/index.html.erb @@ -7,8 +7,8 @@ <% end %>
Nothing here
<% end %> diff --git a/app/views/cards/index/engagement/_considering.html.erb b/app/views/cards/index/engagement/_considering.html.erb index 58f02a7f3..f2ff7475f 100644 --- a/app/views/cards/index/engagement/_considering.html.erb +++ b/app/views/cards/index/engagement/_considering.html.erb @@ -1,10 +1,14 @@ -Nothing here
<% end %> diff --git a/app/views/cards/index/engagement/_doing.html.erb b/app/views/cards/index/engagement/_doing.html.erb index 57fc1aff9..a612d5647 100644 --- a/app/views/cards/index/engagement/_doing.html.erb +++ b/app/views/cards/index/engagement/_doing.html.erb @@ -1,4 +1,4 @@ -Nothing here
<% end %> diff --git a/app/views/cards/previews/index.turbo_stream.erb b/app/views/cards/previews/index.turbo_stream.erb new file mode 100644 index 000000000..a97924606 --- /dev/null +++ b/app/views/cards/previews/index.turbo_stream.erb @@ -0,0 +1,10 @@ +<%= turbo_stream.remove "#{params[:target]}-load-page-#{@page.number}" %> + +<%= turbo_stream.append params[:target] do %> + <%= render partial: @filter.engagement_status&.considering? ? "cards/display/mini" : "cards/display/preview", + collection: @page.records, as: :card, cached: true %> + + <% unless @page.last? %> + <%= cards_next_page_link params[:target], page: @page, filter: @filter, fetch_on_visible: @filter.indexed_by.closed? %> + <% end %> +<% end %> diff --git a/config/routes.rb b/config/routes.rb index cc179969a..cf2b5fe76 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -8,6 +8,10 @@ Rails.application.routes.draw do end end + namespace :cards do + resources :previews + end + resources :cards do scope module: :cards do resource :engagement diff --git a/script/populate/cards_for_pagination.rb b/script/populate/cards_for_pagination.rb new file mode 100644 index 000000000..381d5e05b --- /dev/null +++ b/script/populate/cards_for_pagination.rb @@ -0,0 +1,30 @@ +require_relative "../../config/environment" + +CARDS_COUNT = 200 + +ApplicationRecord.current_tenant = "development-tenant" +account = Account.first +user = account.users.first +Current.session = user.sessions.last +collection = account.collections.first + +# Doing + +CARDS_COUNT.times do |index| + card = collection.cards.create!(title: "Doing card #{index}", creator: user, status: :published) + card.engage +end + +# Considering + +CARDS_COUNT.times do |index| + card = collection.cards.create!(title: "Considering card #{index}", creator: user, status: :published) + card.reconsider +end + +# Completed + +CARDS_COUNT.times do |index| + card = collection.cards.create!(title: "Popped card #{index}", creator: user, status: :published) + card.close +end diff --git a/script/renaming/content.rb b/script/renaming/content.rb index d63591e5c..ee95ec350 100644 --- a/script/renaming/content.rb +++ b/script/renaming/content.rb @@ -5,7 +5,7 @@ require "active_support/core_ext/string" # for camelize RENAME_RULES = { "bubble" => "card", - "popped" => "closed", + "closed" => "closed", "poppable" => "closeable", "pop" => "closure", "bucket" => "collection" diff --git a/script/renaming/files.rb b/script/renaming/files.rb index c75fddd84..86b7d3421 100644 --- a/script/renaming/files.rb +++ b/script/renaming/files.rb @@ -9,7 +9,7 @@ EXCLUDED_DIRS = [ "db", ".git", "script/renaming" ].freeze RENAMES = { "bubble" => "card", "poppable" => "closeable", - "popped" => "closed", + "closed" => "closed", "pop" => "closure", "bucket" => "collection" }.freeze diff --git a/test/controllers/cards/previews_controller_test.rb b/test/controllers/cards/previews_controller_test.rb new file mode 100644 index 000000000..ff6541831 --- /dev/null +++ b/test/controllers/cards/previews_controller_test.rb @@ -0,0 +1,13 @@ +require "test_helper" + +class Cards::PreviewsControllerTest < ActionDispatch::IntegrationTest + setup do + sign_in_as :kevin + end + + test "index" do + get cards_previews_url(format: :turbo_stream) + + assert_response :success + end +end