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

Feature/display rich text reaction selector #471

Open
wants to merge 16 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 13 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
13 changes: 13 additions & 0 deletions app/assets/images/smiley_face.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions app/assets/stylesheets/application.tailwind.css
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
@import "tailwindcss/components";
@import "tailwindcss/utilities";
@import 'direct_uploads';
@import 'emoji_selector';

.field_with_errors {
@apply flex [&>input]:input-error [&>input]:w-full;
Expand Down
7 changes: 7 additions & 0 deletions app/assets/stylesheets/emoji_selector.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
details > summary {
list-style: none;
}

details > summary::-webkit-details-marker {
display: none;
}
7 changes: 7 additions & 0 deletions app/components/rich_text_component.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<span class="flex flex-col justify_center font-bold">
<%= user_full_name %>
</span>

<div class="divider my-1 "></div>

<%= tag.span(@rich_text, class: "grow whitespace-pre-line") %>
19 changes: 19 additions & 0 deletions app/components/rich_text_component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# frozen_string_literal: true

class RichTextComponent < ViewComponent::Base
def initialize(rich_text:, user:)
@rich_text = rich_text
@user = user
end

private

def user_full_name
@user.full_name
end

# Check to see if the body does not have blank text.
def render?
@rich_text.present?
end
end
9 changes: 0 additions & 9 deletions app/components/standup_meetings/update_component.html.erb

This file was deleted.

25 changes: 0 additions & 25 deletions app/components/standup_meetings/update_component.rb

This file was deleted.

5 changes: 5 additions & 0 deletions app/helpers/emojis_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module EmojisHelper
def all_emojis
Emoji.captions.map { |caption| Emoji.new(caption) }
end
end
1 change: 1 addition & 0 deletions app/javascript/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import 'trix';
import '@rails/actiontext';
import './src/direct_uploads';
import './src/inline_code';
import './src/emoji_selector';

import * as ActiveStorage from '@rails/activestorage';

Expand Down
13 changes: 13 additions & 0 deletions app/javascript/src/emoji_selector.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
document.addEventListener('click', (event) => {
wwrk22 marked this conversation as resolved.
Show resolved Hide resolved
const emojiSelections = document.querySelectorAll('details[open].emoji-selection');

if (emojiSelections.length > 0) {
const selectionClicked = [...emojiSelections].some(
(selection) => selection.contains(event.target),
);

if (selectionClicked === false) {
emojiSelections.forEach((selection) => selection.removeAttribute('open'));
}
}
});
32 changes: 32 additions & 0 deletions app/views/rich_text_reactions/_emoji_selector.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<%#
Locals required:
- rich_text_id: Id of the ActionText::RichText that the new RichTextReaction belongs to

Helpers used:
- app/helpers/emojis_helper
%>

<div class="relative">
<details class="emoji-selection inline-block align-middle">
<summary class="list-marker-none cursor-pointer">
<%= render inline: Rails.root.join('app/assets/images/smiley_face.svg').read %>
wwrk22 marked this conversation as resolved.
Show resolved Hide resolved
</summary>

<div class="absolute bottom-6 z-100
bg-gray-100 border border-gray-300 rounded-lg p-1">
<%= form_with model: RichTextReaction.new do |form| %>
<%= form.hidden_field :rich_text_id, value: rich_text_id %>

<% all_emojis.each do |emoji| %>
<%= form.button :emoji_caption,
value: emoji.caption,
class: "p-1 border-transparent border-2
hover:bg-gray-300 hover:rounded-lg
active:border active:border-2 active:border-green-400" do %>
<%= emoji.emoji %>
<% end %>
<% end %>
<% end %>
</div>
</details>
</div>
3 changes: 2 additions & 1 deletion app/views/rich_text_reactions/create.turbo_stream.erb
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
<%= "PLACEHOLDER" %>
<%# placeholder %>
<%= "" %>
10 changes: 10 additions & 0 deletions app/views/standup_meetings/_update.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<%#
wwrk22 marked this conversation as resolved.
Show resolved Hide resolved
Locals required:
- rich_text: an ActionText::RichText object,
- user: the owner User of rich_text
%>

<div class="border p-4 flex flex-col justify-between mt-4">
<%= render RichTextComponent.new(rich_text:, user:) %>
<%= render partial: "rich_text_reactions/emoji_selector", locals: { rich_text_id: rich_text.id } %>
</div>
33 changes: 21 additions & 12 deletions app/views/standup_meetings/index.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -48,24 +48,33 @@

<div class="flex flex-col lg:flex-row justify-evenly" data-tabs-target="panel">
<%= render StandupMeetings::ColumnComponent.new(title: "Previous Work Day") do%>
<%= render StandupMeetings::UpdateComponent.with_collection(
@completed_meetings,
content_type: :yesterday_work_description
) %>
<% @completed_meetings.each do |completed_meeting| %>
<%= render partial: "update",
locals: {
rich_text: completed_meeting.yesterday_work_description,
user: completed_meeting.user
} %>
<% end %>
<% end %>

<%= render StandupMeetings::ColumnComponent.new(title: "Today's Work Day") do %>
<%= render StandupMeetings::UpdateComponent.with_collection(
@completed_meetings,
content_type: :today_work_description
) %>
<% @completed_meetings.each do |completed_meeting| %>
<%= render partial: "update",
locals: {
rich_text: completed_meeting.today_work_description,
user: completed_meeting.user
} %>
<% end %>
<% end %>

<%= render StandupMeetings::ColumnComponent.new(title: "Blockers") do %>
<%= render StandupMeetings::UpdateComponent.with_collection(
@completed_meetings,
content_type: :blockers_description
) %>
<% @completed_meetings.each do |completed_meeting| %>
<%= render partial: "update",
locals: {
rich_text: completed_meeting.blockers_description,
user: completed_meeting.user
} %>
<% end %>
<% end %>
</div>

Expand Down
23 changes: 23 additions & 0 deletions spec/components/rich_text_component_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# frozen_string_literal: true

require 'rails_helper'

RSpec.describe RichTextComponent, type: :component do
let!(:rich_text) { build(:action_text_rich_text) }
let!(:user) { rich_text.record }

it "renders the rich text content along with the user's full name" do
render_inline described_class.new(rich_text:, user:)

expect(page).to have_content(rich_text.to_plain_text)
.and have_content(user.full_name)
end

it 'renders nothing with no rich text content' do
rich_text.body = ActionText::Content.new('')

render_inline described_class.new(rich_text:, user:)

expect(page).not_to have_content('body')
end
end
43 changes: 0 additions & 43 deletions spec/components/standup_meetings/update_component_spec.rb

This file was deleted.

15 changes: 2 additions & 13 deletions spec/factories/action_text_rich_texts.rb
Original file line number Diff line number Diff line change
@@ -1,19 +1,8 @@
FactoryBot.define do
factory :action_text_rich_text, class: 'ActionText::RichText' do
# +rich_text_owner+ must be given by the user of this factory, and it may
# be any persisted ActiveRecord model record.
transient do
rich_text_owner { nil }
end

name { Faker::Lorem.word }
body { ActionText::Content.new "<div>#{Faker::Lorem.sentence}</div>" }

after(:build) do |action_text_rich_text, evaluator|
if evaluator.rich_text_owner
action_text_rich_text.record_type = evaluator.rich_text_owner.class.name
action_text_rich_text.record_id = evaluator.rich_text_owner.id
end
end
record_type { User.name }
record_id { create(:user).id }
end
end
9 changes: 1 addition & 8 deletions spec/factories/rich_text_reactions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,8 @@
#
FactoryBot.define do
factory :rich_text_reaction do
# +rich_text_owner+ can be given by the user of this factory, and it may
# be any persisted ActiveRecord model record. By default, a User record is
# used.
transient do
rich_text_owner { user }
end

user
emoji_caption { Emoji.captions.sample }
rich_text { association(:action_text_rich_text, rich_text_owner:) }
rich_text { association(:action_text_rich_text, record: user) }
end
end
26 changes: 26 additions & 0 deletions spec/views/rich_text_reactions/_emoji_selector.html.erb_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# frozen_string_literal: true

require 'rails_helper'

RSpec.describe 'rich_text_reactions/_emoji_selector.html.erb' do
it 'renders a form to create a new rich text reaction' do
rich_text_id = create(:rich_text_reaction).rich_text_id

emojis = Emoji.captions.map { |caption| Emoji.new(caption) }

render partial: 'rich_text_reactions/emoji_selector',
locals: { rich_text_id:, emojis: }

expect(rendered)
.to have_selector("form[action='#{rich_text_reactions_path}']",
visible: :hidden)
.and have_selector("input[value='#{rich_text_id}']",
visible: :hidden)

emojis.each do |emoji|
expect(rendered).to have_button('rich_text_reaction[emoji_caption]',
text: emoji.emoji,
visible: :hidden)
end
end
end
Loading