Skip to content

Instantly share code, notes, and snippets.

@julianrubisch
Created March 18, 2021 13:58
Show Gist options
  • Save julianrubisch/103c937fdeb8065f3e9072b70cbbbea8 to your computer and use it in GitHub Desktop.
Save julianrubisch/103c937fdeb8065f3e9072b70cbbbea8 to your computer and use it in GitHub Desktop.
<!-- app/views/boards/_board.html.erb -->
<%= render partial: "embeds/embed", collection: embeds, locals: {board: board}, cached: true %>
<%= render partial: "embeds/embed", collection: embed_templates %>
<!-- app/views/boards/_board.html.erb -->
<ul class="grid grid-cols-1 gap-4 sm:grid-cols-3 md:grid-cols-4"
data-controller="board"
data-board-id-value="<%= board.id %>"
id="<%= dom_id(board) %>">
<%= render partial: "embeds/embed", collection: embeds, locals: {board: board}, cached: true %>
<!-- this is new -->
<li class="..." id="add-embed-button">
<div class="flex justify-center items-center">
<%= button_tag class: "...",
data: {reflex: "click->Template#insert", board_id: board.id} do %>
<i class="fas fa-plus fa-3x"></i>
<% end %>
</div>
</li>
</ul>
# app/channels/boards_channel.rb
class BoardsChannel < ApplicationCable::Channel
def subscribed
stream_from "board:#{current_user.id}"
end
end
# app/controllers/boards_controller.rb
class BoardsController < ApplicationController
# ...
def show
@embed_import = EmbedImport.new(board: @board)
@embeds = filter_for("Embed").apply!(@board.embeds)
@embed_templates = current_user.embed_templates
end
# ...
end
<!-- app/views/embeds/_embed.html.erb -->
<li class="..." id="<%= embed.persisted? ? dom_id(embed) : "embed-#{Time.now.to_i}" %>">
<div class="p-3 flex flex-col justify-between h-full w-full">
<% if embed.persisted? %>
<%= link_to [embed.board, embed], class: "space-y-3 flex-1" do %>
<h3 class="font-medium text-base truncate"><%= embed.title %></h3>
<%= embed.embed_code %>
<% end %>
<div class="flex items-center text-sm text-gray-500 space-x-1">
<div class="flex-shrink">
<span><%= embed.history_entries.size %></span>
<i class="fas fa-comments flex-shrink-0 h-5 w-5 text-gray-400"></i>
</div>
<%= render(ReactionComponent.new(reactable: embed, user: current_user)) %>
</div>
<% else %>
<%= render "embeds/form", embed: embed %>
<% end %>
</div>
</li>
<!-- app/views/embeds/_embed.html.erb -->
<li class="..." id="<%= dom_id(embed, embed.uuid) %>">
<div class="p-3 flex flex-col justify-between h-full w-full">
<% if embed.persisted? %>
<% else %>
<div class="flex justify-end mb-2">
<%= button_tag class:"...",
data: {reflex: "click->Template#remove", uuid: embed.uuid} do %>
<i class="fas fa-times"></i>
<% end %>
</div>
<div class="flex-1">
<%= render "embeds/form", embed: embed %>
</div>
<% end %>
</div>
</li>
# app/models/embed.rb
class Embed < ApplicationRecord
# ...
attribute :uuid, :string
# ...
end
<!-- app/views/embeds/_form.html.erb -->
<%= form_for([embed.board, embed], remote: true, data: {reflex: "submit->EmbedReflex#submit", resource: "Embed"}) do |form| %>
<%= form.hidden_field :uuid %>
<!-- ... -->
<% end %>
# app/reflexes/embed_reflex.rb
class EmbedReflex < ApplicationReflex
# ...
after_reflex do
StreamBoardJob.perform_now(board: @embed.board)
end
def submit
super do
morph :nothing
end
end
# ...
end
# app/reflexes/embed_reflex.rb
class EmbedReflex < ApplicationReflex
# ...
def submit
super do
current_user.remove_embed_template_for(uuid: submit_params[:uuid])
end
end
private
def submit_params
params.require(:embed).permit(:title, :input, :uuid)
end
end
# app/reflexes/embed_reflex.rb
class EmbedReflex < ApplicationReflex
# ...
after_reflex do
@embed.board.users.without(current_user).each do |user|
StreamBoardJob.perform_later(board: @embed.board, user: user)
end
end
# ...
end
# app/reflexes/template_reflex.rb
class TemplateReflex < ApplicationReflex
def insert
cable_ready.insert_adjacent_html(
selector: "#add-embed-button",
position: "beforebegin",
html: render(Embed.new(board: Board.find(element.dataset.board_id)))
).broadcast
morph :nothing
end
end
# app/reflexes/template_reflex.rb
class TemplateReflex < ApplicationReflex
def insert
current_user.add_embed_template_with(board: Board.find(element.dataset.board_id))
end
def remove
current_user.remove_embed_template_for(uuid: element.dataset.uuid)
end
end
# app/jobs/stream_board_job.rb
class StreamBoardJob < ApplicationJob
include CableReady::Broadcaster
queue_as :default
def perform(board:, user:)
cable_ready["board:#{user.id}"].morph(
selector: dom_id(board),
html: ApplicationController.render(board, locals: {embeds: board.embeds, embed_templates: user.embed_templates, user: user})
).broadcast
end
end
# app/models/user.rb
class User < ApplicationRecord
# ...
kredis_set :_embed_templates
def embed_templates
_embed_templates.members.map do |embed_template|
Embed.new.from_json(embed_template)
end
end
def remove_embed_template_for(uuid:)
template_to_remove = _embed_templates.members.find { |temp| JSON.parse(temp)["uuid"] == uuid }
_embed_templates.remove(template_to_remove)
end
def add_embed_template_with(**args)
_embed_templates << Embed.new(uuid: "U#{SecureRandom.urlsafe_base64}", **args).as_json
endend
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment