From 8b767a120b610a126949e634985156f0971e5f60 Mon Sep 17 00:00:00 2001 From: Daniel Rassiner Date: Mon, 31 Jul 2023 21:07:52 -0700 Subject: [PATCH] Standup meeting group refactor (#138) * wip * wip * Define @standup_meeting_group_user variable in joined_card_component.rb co-author: Roc Devenport rubykod@gmail.com * Add standup_meeting_groups::joins_controller.rb destroy action co-author: Roc Devenport rubykod@gmail.com * Defines @standup_meeting_group_user variable in joined_card_component.html.erb co-authored-by: Roc Devenport rubykod@gmail.com * . * Adds destroy.turbo_stream.erb file and updates controller to render turbo stream on destroy co-authored-by: RocDavenport rubykod@gmail.com * fixes linting error * breaks @joinable_standup_meeting_groups line the standup_meeting_groups_controller.rb * . * . * wip: adding joinable_item_component specs * removes join_button_component * removes leave_button_component * removed base_botton_component * Remove uneeded code from _standup_meeting_group_list_item.erb * adds styling changes to joined_card_component.html.erb * Refactores standup meeting group index to only display 3 cards per row. * clean code * Address pr comments * centered joined_card_components on small screen * deleted commented out code * wip: adding checkin_status feature to joined_cards * reverting to split up issues * adds icons and flash text for checkins messages * cleans code for pr * Adds test for joinableItemComponent * adds joined card component test * fixes rubocop errors * removes turbo from leave button and adds a redirect to joins destroy action * Changes joined card components container from grid to flexbox * refactor standup_meeting_groups turbo_stream to render JoinableItemComponent * remove _standup_meeting_group_list item partial --------- Co-authored-by: Gustavo Valenzuela --- app/components/flash_component.rb | 1 + .../base_button_component.rb | 25 ------------------- .../join_button_component.html.erb | 1 - .../join_button_component.rb | 2 -- .../joinable_item_component.html.erb | 7 ++++++ .../joinable_item_component.rb | 14 +++++++++++ .../joined_card_component.html.erb | 17 +++++++++++++ .../joined_card_component.rb | 13 ++++++++++ .../leave_button_component.html.erb | 1 - .../leave_button_component.rb | 9 ------- .../joins_controller.rb | 22 +++------------- .../standup_meeting_groups_controller.rb | 16 +++++++----- app/models/standup_meeting_group.rb | 4 +++ .../standup_meeting_groups/_form.html.erb | 13 ---------- .../_standup_meeting_group.html.erb | 2 +- .../_standup_meeting_group_list_item.erb | 17 ------------- .../create.turbo_stream.erb | 17 +++++++------ .../standup_meeting_groups/index.html.erb | 18 ++++++++----- .../joins/create.turbo_stream.erb | 4 +++ .../joins/destroy.turbo_stream.erb | 5 ++++ .../joinable_item_component_spec.rb | 16 ++++++++++++ .../joined_card_component_spec.rb | 14 +++++++++++ 22 files changed, 130 insertions(+), 108 deletions(-) delete mode 100644 app/components/standup_meeting_group/base_button_component.rb delete mode 100644 app/components/standup_meeting_group/join_button_component.html.erb delete mode 100644 app/components/standup_meeting_group/join_button_component.rb create mode 100644 app/components/standup_meeting_group/joinable_item_component.html.erb create mode 100644 app/components/standup_meeting_group/joinable_item_component.rb create mode 100644 app/components/standup_meeting_group/joined_card_component.html.erb create mode 100644 app/components/standup_meeting_group/joined_card_component.rb delete mode 100644 app/components/standup_meeting_group/leave_button_component.html.erb delete mode 100644 app/components/standup_meeting_group/leave_button_component.rb delete mode 100644 app/views/standup_meeting_groups/_standup_meeting_group_list_item.erb create mode 100644 app/views/standup_meeting_groups/joins/create.turbo_stream.erb create mode 100644 app/views/standup_meeting_groups/joins/destroy.turbo_stream.erb create mode 100644 spec/components/standup_meeting_group/joinable_item_component_spec.rb create mode 100644 spec/components/standup_meeting_group/joined_card_component_spec.rb diff --git a/app/components/flash_component.rb b/app/components/flash_component.rb index 9c06b927..c5c47686 100644 --- a/app/components/flash_component.rb +++ b/app/components/flash_component.rb @@ -2,6 +2,7 @@ class FlashComponent < ViewComponent::Base TYPE_THEMES = { + success: 'success', notice: 'success', alert: 'error', form_errors: 'error' diff --git a/app/components/standup_meeting_group/base_button_component.rb b/app/components/standup_meeting_group/base_button_component.rb deleted file mode 100644 index d248e850..00000000 --- a/app/components/standup_meeting_group/base_button_component.rb +++ /dev/null @@ -1,25 +0,0 @@ -# frozen_string_literal: true - -class StandupMeetingGroup::BaseButtonComponent < ViewComponent::Base - def self.for(standup_meeting_group:, current_user:) - standup_meeting_group_user = standup_meeting_group.standup_meeting_group_user(current_user.id) - - klass_name = standup_meeting_group_user.present? ? 'LeaveButtonComponent' : 'JoinButtonComponent' - - "StandupMeetingGroup::#{klass_name}".safe_constantize.new(standup_meeting_group:, current_user:, - standup_meeting_group_user:) - end - - protected - - attr_reader :standup_meeting_group, :user - - def initialize(standup_meeting_group:, current_user:, **args) - @standup_meeting_group = standup_meeting_group - @user = current_user - - after_initialize(**args) - end - - def after_initialize(**); end -end diff --git a/app/components/standup_meeting_group/join_button_component.html.erb b/app/components/standup_meeting_group/join_button_component.html.erb deleted file mode 100644 index 3fb60a2d..00000000 --- a/app/components/standup_meeting_group/join_button_component.html.erb +++ /dev/null @@ -1 +0,0 @@ -<%= button_to 'Join', standup_meeting_group_joins_path(@standup_meeting_group), class: 'btn btn-success' %> diff --git a/app/components/standup_meeting_group/join_button_component.rb b/app/components/standup_meeting_group/join_button_component.rb deleted file mode 100644 index a4b78cd0..00000000 --- a/app/components/standup_meeting_group/join_button_component.rb +++ /dev/null @@ -1,2 +0,0 @@ -class StandupMeetingGroup::JoinButtonComponent < StandupMeetingGroup::BaseButtonComponent -end diff --git a/app/components/standup_meeting_group/joinable_item_component.html.erb b/app/components/standup_meeting_group/joinable_item_component.html.erb new file mode 100644 index 00000000..4b06fd01 --- /dev/null +++ b/app/components/standup_meeting_group/joinable_item_component.html.erb @@ -0,0 +1,7 @@ +<%= tag.li(id: dom_id(standup_meeting_group), class: " justify-between flex flex-row p-4 mb-2 border-black border-2 items-center") do %> +

<%= standup_meeting_group.name %>

+ +
+ <%= button_to 'Join', standup_meeting_group_joins_path(@standup_meeting_group), class: 'btn btn-success' %> +
+<% end %> diff --git a/app/components/standup_meeting_group/joinable_item_component.rb b/app/components/standup_meeting_group/joinable_item_component.rb new file mode 100644 index 00000000..2be7bddf --- /dev/null +++ b/app/components/standup_meeting_group/joinable_item_component.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +class StandupMeetingGroup::JoinableItemComponent < ViewComponent::Base + include Turbo::FramesHelper + + with_collection_parameter :standup_meeting_group + + attr_reader :standup_meeting_group, :user + + def initialize(standup_meeting_group:, current_user:) + @standup_meeting_group = standup_meeting_group + @user = current_user + end +end diff --git a/app/components/standup_meeting_group/joined_card_component.html.erb b/app/components/standup_meeting_group/joined_card_component.html.erb new file mode 100644 index 00000000..e3a457db --- /dev/null +++ b/app/components/standup_meeting_group/joined_card_component.html.erb @@ -0,0 +1,17 @@ +<%= tag.div(id: dom_id(standup_meeting_group), class: "card card-bordered w-72") do %> +
+
+

<%= link_to standup_meeting_group %>

+
+

Checked in

+

Outstanding check in

+
+
+
+
+ + +
+
+
+<% end %> \ No newline at end of file diff --git a/app/components/standup_meeting_group/joined_card_component.rb b/app/components/standup_meeting_group/joined_card_component.rb new file mode 100644 index 00000000..be7ec5ee --- /dev/null +++ b/app/components/standup_meeting_group/joined_card_component.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +class StandupMeetingGroup::JoinedCardComponent < ViewComponent::Base + with_collection_parameter :standup_meeting_group + + attr_reader :standup_meeting_group, :user + + def initialize(standup_meeting_group:, current_user:) + @standup_meeting_group = standup_meeting_group + @user = current_user + @standup_meeting_group_user = standup_meeting_group.standup_meeting_groups_users.find_by(user:) + end +end diff --git a/app/components/standup_meeting_group/leave_button_component.html.erb b/app/components/standup_meeting_group/leave_button_component.html.erb deleted file mode 100644 index 5b659797..00000000 --- a/app/components/standup_meeting_group/leave_button_component.html.erb +++ /dev/null @@ -1 +0,0 @@ -<%= link_to 'Leave', standup_meeting_group_join_path(@standup_meeting_group, @standup_meeting_group_user), data: { turbo_method: :delete }, class: 'btn btn-danger' %> diff --git a/app/components/standup_meeting_group/leave_button_component.rb b/app/components/standup_meeting_group/leave_button_component.rb deleted file mode 100644 index 59003fe1..00000000 --- a/app/components/standup_meeting_group/leave_button_component.rb +++ /dev/null @@ -1,9 +0,0 @@ -class StandupMeetingGroup::LeaveButtonComponent < StandupMeetingGroup::BaseButtonComponent - def after_initialize(standup_meeting_group_user:) - @standup_meeting_group_user = standup_meeting_group_user - end - - private - - attr_reader :standup_meeting_group_user -end diff --git a/app/controllers/standup_meeting_groups/joins_controller.rb b/app/controllers/standup_meeting_groups/joins_controller.rb index a25fdeeb..6e230bbe 100644 --- a/app/controllers/standup_meeting_groups/joins_controller.rb +++ b/app/controllers/standup_meeting_groups/joins_controller.rb @@ -5,15 +5,11 @@ def create authorize @standup_meeting_group_user, policy_class: StandupMeetingGroup::JoinPolicy - @standup_meeting_group_user.save - # flash[:notice] = 'You have joined this standup meeting group.' - - component = ::StandupMeetingGroup::LeaveButtonComponent.new(standup_meeting_group: @standup_meeting_group, - current_user:, standup_meeting_group_user: @standup_meeting_group_user) + @standup_meeting_group_user.save! respond_to do |format| format.turbo_stream do - render turbo_stream: turbo_stream.update(helpers.dom_id(@standup_meeting_group, :join_or_leave), component) + flash.now[:notice] = "You have joined #{@standup_meeting_group.name}!" end end end @@ -25,20 +21,8 @@ def destroy authorize @standup_meeting_group_user, policy_class: StandupMeetingGroup::JoinPolicy @standup_meeting_group_user.destroy - - component = ::StandupMeetingGroup::JoinButtonComponent.new( - standup_meeting_group: @standup_meeting_group, current_user: - ) - respond_to do |format| - format.turbo_stream do - render turbo_stream: turbo_stream.update( - helpers.dom_id(@standup_meeting_group, :join_or_leave), component - ) - end - format.html do - redirect_to standup_meeting_groups_path - end + format.html { redirect_to standup_meeting_groups_path, notice: 'You have left the standup meeting group.' } end end end diff --git a/app/controllers/standup_meeting_groups_controller.rb b/app/controllers/standup_meeting_groups_controller.rb index fb4bc34c..da5cc153 100644 --- a/app/controllers/standup_meeting_groups_controller.rb +++ b/app/controllers/standup_meeting_groups_controller.rb @@ -2,7 +2,9 @@ class StandupMeetingGroupsController < ApplicationController before_action :set_standup_meeting_group, only: %i[edit update destroy] def index - @standup_meeting_groups = StandupMeetingGroup.includes(:standup_meeting_groups_users).all + @my_standup_meeting_groups = policy_scope(StandupMeetingGroup).includes(:standup_meeting_groups_users) + @joinable_standup_meeting_groups = StandupMeetingGroup.includes(:standup_meeting_groups_users) + .excluding(@my_standup_meeting_groups) end def show @@ -36,22 +38,24 @@ def edit; end def create @standup_meeting_group = StandupMeetingGroup.new(standup_meeting_group_params) - @new_standup_meeting_group = StandupMeetingGroup.new authorize(@standup_meeting_group) respond_to do |format| if @standup_meeting_group.save - format.turbo_stream + format.turbo_stream do + @new_standup_meeting_group = StandupMeetingGroup.new + + flash.now[:success] = "#{@standup_meeting_group.name} was successfully created." + end + format.html do redirect_to standup_meeting_group_url(@standup_meeting_group), notice: 'Standup meeting group was successfully created.' end else - # NOTE: figure out how to do errors format.turbo_stream do - render turbo_stream: turbo_stream.update(@standup_meeting_group, partial: 'form', - locals: { standup_meeting_group: @standup_meeting_group }) + flash.now[:form_errors] = @standup_meeting_group.errors.full_messages end format.html { render :new, status: :unprocessable_entity } end diff --git a/app/models/standup_meeting_group.rb b/app/models/standup_meeting_group.rb index c7673334..919c9f26 100644 --- a/app/models/standup_meeting_group.rb +++ b/app/models/standup_meeting_group.rb @@ -25,4 +25,8 @@ class StandupMeetingGroup < ApplicationRecord def standup_meeting_group_user(user_id) standup_meeting_groups_users.find_by(user_id:) end + + def to_s + name + end end diff --git a/app/views/standup_meeting_groups/_form.html.erb b/app/views/standup_meeting_groups/_form.html.erb index 457859de..d5e6dc8a 100644 --- a/app/views/standup_meeting_groups/_form.html.erb +++ b/app/views/standup_meeting_groups/_form.html.erb @@ -1,17 +1,4 @@ <%= form_with(model: standup_meeting_group) do |form| %> - <%# NOTE: can prob consolidate this into a shared partial %> - <% if standup_meeting_group.errors.any? %> -
-

<%= pluralize(standup_meeting_group.errors.count, "error") %> prohibited this standup_meeting_group from being saved:

- -
    - <% standup_meeting_group.errors.each do |error| %> -
  • <%= error.full_message %>
  • - <% end %> -
-
- <% end %> -
diff --git a/app/views/standup_meeting_groups/_standup_meeting_group.html.erb b/app/views/standup_meeting_groups/_standup_meeting_group.html.erb index b648af2f..35577cbc 100644 --- a/app/views/standup_meeting_groups/_standup_meeting_group.html.erb +++ b/app/views/standup_meeting_groups/_standup_meeting_group.html.erb @@ -7,7 +7,7 @@

<%= standup_meeting_group.name %>

- <%= button_to 'Leave', standup_meeting_group_join_path(standup_meeting_group, standup_meeting_group_user), method: :delete, data: { turbo: false }, class: 'link mt-4' %> + <%= button_to 'Leave', standup_meeting_group_join_path(standup_meeting_group, standup_meeting_group_user), method: :delete, class: 'link mt-4' %>
<%= render StandupMeeting::CheckInCtaComponent.new(standup_meeting_group: standup_meeting_group, standup_meeting: current_user_standup_meeting, current_user:) %>
diff --git a/app/views/standup_meeting_groups/_standup_meeting_group_list_item.erb b/app/views/standup_meeting_groups/_standup_meeting_group_list_item.erb deleted file mode 100644 index 115d4282..00000000 --- a/app/views/standup_meeting_groups/_standup_meeting_group_list_item.erb +++ /dev/null @@ -1,17 +0,0 @@ -<%= tag.li(id: dom_id(standup_meeting_group), class: "flex flex-row p-4 mb-2 border-black border-2 items-center") do %> -

<%= link_to standup_meeting_group.name, standup_meeting_group_path(standup_meeting_group) %>

- -
- <%= turbo_frame_tag dom_id(standup_meeting_group, :join_or_leave) do %> - <%= render StandupMeetingGroup::BaseButtonComponent.for(standup_meeting_group: standup_meeting_group, current_user: current_user) %> - <% end %> - - <% if policy(standup_meeting_group).edit? %> - <%= button_to "Edit", class: 'btn' %> - <% end %> - - <% if policy(standup_meeting_group).destroy? %> - <%= button_to "Delete", class: 'btn btn-danger' %> - <% end %> -
-<% end %> diff --git a/app/views/standup_meeting_groups/create.turbo_stream.erb b/app/views/standup_meeting_groups/create.turbo_stream.erb index 2aa02984..6501146d 100644 --- a/app/views/standup_meeting_groups/create.turbo_stream.erb +++ b/app/views/standup_meeting_groups/create.turbo_stream.erb @@ -1,11 +1,12 @@ -<%= turbo_stream.prepend( - "standup_meeting_group_list", - partial: 'standup_meeting_group_list_item', - locals: { standup_meeting_group: @standup_meeting_group } - ) -%> +<%= turbo_stream.update "flash", partial: "layouts/flash" %> -<%= turbo_stream.update "new_standup_meeting_group" do %> - <%= render "form", standup_meeting_group: @new_standup_meeting_group %> +<% if @standup_meeting_group.valid? %> + <%= turbo_stream.prepend "find-standup-meeting-groups" do %> + <%= render StandupMeetingGroup::JoinableItemComponent.new(standup_meeting_group: @standup_meeting_group, current_user: current_user) %> + <% end %> + + <%= turbo_stream.update "new_standup_meeting_group" do %> + <%= render "form", standup_meeting_group: @new_standup_meeting_group %> + <% end %> <% end %> diff --git a/app/views/standup_meeting_groups/index.html.erb b/app/views/standup_meeting_groups/index.html.erb index de53580b..e3266944 100644 --- a/app/views/standup_meeting_groups/index.html.erb +++ b/app/views/standup_meeting_groups/index.html.erb @@ -1,13 +1,19 @@ -

Standup Meeting Groups

- <% if policy(:standup_meeting_group).new? %>
<%= render 'form', standup_meeting_group: StandupMeetingGroup.new %>
<% end %> -
+
+

My Standups

+
+ <%= render StandupMeetingGroup::JoinedCardComponent.with_collection(@my_standup_meeting_groups, current_user:) %> +
+
-
    - <%= render partial: 'standup_meeting_group_list_item', collection: @standup_meeting_groups, as: :standup_meeting_group %> -
\ No newline at end of file +
+

Find a Standup

+
    + <%= render StandupMeetingGroup::JoinableItemComponent.with_collection(@joinable_standup_meeting_groups, current_user:) %> +
+
\ No newline at end of file diff --git a/app/views/standup_meeting_groups/joins/create.turbo_stream.erb b/app/views/standup_meeting_groups/joins/create.turbo_stream.erb new file mode 100644 index 00000000..bfb39792 --- /dev/null +++ b/app/views/standup_meeting_groups/joins/create.turbo_stream.erb @@ -0,0 +1,4 @@ +<%= turbo_stream.remove @standup_meeting_group %> +<%= turbo_stream.prepend 'my-standup-meeting-groups' do %> + <%= render StandupMeetingGroup::JoinedCardComponent.new(standup_meeting_group: @standup_meeting_group, current_user: current_user) %> +<% end %> diff --git a/app/views/standup_meeting_groups/joins/destroy.turbo_stream.erb b/app/views/standup_meeting_groups/joins/destroy.turbo_stream.erb new file mode 100644 index 00000000..7b0b48df --- /dev/null +++ b/app/views/standup_meeting_groups/joins/destroy.turbo_stream.erb @@ -0,0 +1,5 @@ +<%= turbo_stream.remove @standup_meeting_group %> + +<%= turbo_stream.prepend 'find-standup-meeting-groups' do %> + <%= render StandupMeetingGroup::JoinableItemComponent.new(standup_meeting_group: @standup_meeting_group, current_user: current_user ) %> +<% end %> diff --git a/spec/components/standup_meeting_group/joinable_item_component_spec.rb b/spec/components/standup_meeting_group/joinable_item_component_spec.rb new file mode 100644 index 00000000..4ee270a6 --- /dev/null +++ b/spec/components/standup_meeting_group/joinable_item_component_spec.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe StandupMeetingGroup::JoinableItemComponent, type: :component do + let(:standup_meeting_group) { create(:standup_meeting_group) } + let(:user) { create(:user) } + + context 'when standup meeting group is present and user is not a member' do + it 'renders the join button' do + render_inline(described_class.new(standup_meeting_group:, current_user: user)) + + expect(page).to have_button(text: 'Join') + end + end +end diff --git a/spec/components/standup_meeting_group/joined_card_component_spec.rb b/spec/components/standup_meeting_group/joined_card_component_spec.rb new file mode 100644 index 00000000..c9993dee --- /dev/null +++ b/spec/components/standup_meeting_group/joined_card_component_spec.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe StandupMeetingGroup::JoinedCardComponent, type: :component do + let(:standup_meeting_group) { create(:standup_meeting_group, name: 'Test Group') } + let(:user) { create(:user) } + + it 'renders the joined card with the right name' do + render_inline(described_class.new(standup_meeting_group:, current_user: user)) + + expect(page).to have_css('h4', text: 'Test Group') + end +end