Merge pull request #696 from basecamp/flavorjones/collection-workflow-save

Collection edit page uses turbo frames to avoid resetting the user access form
This commit is contained in:
Mike Dalessio
2025-07-02 22:28:51 -04:00
committed by GitHub
10 changed files with 117 additions and 79 deletions
@@ -0,0 +1,14 @@
class Collections::EntropyConfigurationsController < ApplicationController
include CollectionScoped
def update
@collection.entropy_configuration.update!(entropy_configuration_params)
render turbo_stream: turbo_stream.replace([ @collection, :entropy_configuration ], partial: "collections/edit/auto_close", locals: { collection: @collection })
end
private
def entropy_configuration_params
params.expect(collection: [ :auto_close_period, :auto_reconsider_period ])
end
end
@@ -3,11 +3,12 @@ class Collections::PublicationsController < ApplicationController
def create
@collection.publish
redirect_to edit_collection_path(@collection)
render turbo_stream: turbo_stream.replace([ @collection, :publication ], partial: "collections/edit/publication", locals: { collection: @collection })
end
def destroy
@collection.unpublish
redirect_to edit_collection_path(@collection)
@collection.reload
render turbo_stream: turbo_stream.replace([ @collection, :publication ], partial: "collections/edit/publication", locals: { collection: @collection })
end
end
@@ -5,7 +5,7 @@ class Collections::WorkflowsController < ApplicationController
def update
@collection.update! workflow: @workflow
redirect_to cards_path(collection_ids: [ @collection ])
render turbo_stream: turbo_stream.replace([ @collection, :workflows ], partial: "collections/edit/workflows", locals: { collection: @collection })
end
private
@@ -1,4 +1,6 @@
<div class="margin-block-end">
<strong class="divider txt-large">Do or Die</strong>
<%= render "entropy/auto_close", model: collection %>
</div>
<%= turbo_frame_tag @collection, :entropy_configuration do %>
<div class="margin-block-end">
<strong class="divider txt-large">Do or Die</strong>
<%= render "entropy/auto_close", model: collection, url: collection_entropy_configuration_path(collection) %>
</div>
<% end %>
@@ -1,54 +1,55 @@
<div class="margin-block">
<strong class="divider txt-large">Public link</strong>
<p class="margin-none-block-start">Turn on the Public link to share this collection with anyone in the world. They wont need to log in and they wont be able to see anything else in Fizzy.</p>
<%= turbo_frame_tag @collection, :publication do %>
<div class="margin-block">
<strong class="divider txt-large">Public link</strong>
<p class="margin-none-block-start">Turn on the Public link to share this collection with anyone in the world. They wont need to log in and they wont be able to see anything else in Fizzy.</p>
<% if collection.published? %>
<div class="border-radius pad fill-selected">
<div class="flex-inline center justify-between gap">
<span class="txt-large"><%= icon_tag "lock" %></span>
<label class="switch flex align-center justify-between">
<%= form_with url: collection_publication_path(collection), method: :delete, data: { controller: "form" } do |form| %>
<%= form.check_box :published, class: "switch__input", checked: true, data: { action: "change->form#submit" } %>
<span class="switch__btn round"></span>
<span class="for-screen-reader">Turn off the public link</span>
<% end %>
</label>
<span class="txt-large"><%= icon_tag "world" %></span>
</div>
<% if collection.published? %>
<div class="border-radius pad fill-selected">
<div class="flex-inline center justify-between gap">
<span class="txt-large"><%= icon_tag "lock" %></span>
<label class="switch flex align-center justify-between">
<%= form_with url: collection_publication_path(collection), method: :delete, data: { controller: "form" } do |form| %>
<%= form.check_box :published, class: "switch__input", checked: true, data: { action: "change->form#submit" } %>
<span class="switch__btn round"></span>
<span class="for-screen-reader">Turn off the public link</span>
<% end %>
</label>
<span class="txt-large"><%= icon_tag "world" %></span>
</div>
<div class="flex align-center gap-half margin-block">
<%= text_field_tag :publication_url, published_collection_url(collection), disabled: true, class: "full-width input fill-white" %>
<div class="flex align-center justify-center gap-half">
<%= button_to_copy_to_clipboard(published_collection_url(collection)) do %>
<%= icon_tag "copy-paste" %>
<span class="for-screen-reader">Copy public link</span>
<div class="flex align-center gap-half margin-block">
<%= text_field_tag :publication_url, published_collection_url(collection), disabled: true, class: "full-width input fill-white" %>
<div class="flex align-center justify-center gap-half">
<%= button_to_copy_to_clipboard(published_collection_url(collection)) do %>
<%= icon_tag "copy-paste" %>
<span class="for-screen-reader">Copy public link</span>
<% end %>
</div>
</div>
<strong class="margin-block-end-half flex justify-center txt-small">Add an optional description to the public page</strong>
<div class="border-radius input fill-white">
<%= form_with model: collection, class: "txt-align-start", data: { controller: "form" } do |form| %>
<%= form.rich_textarea :public_description, class: "rich-text-content txt-small",
placeholder: "Add a public note about this collection…",
data: { action: "keydown.ctrl+enter->form#submit:prevent keydown.meta+enter->form#submit:prevent keydown.esc->form#cancel:stop" } %>
<%= form.button "Save changes", type: :submit, class: "btn txt-small" %>
<% end %>
</div>
</div>
<strong class="margin-block-end-half flex justify-center txt-small">Add an optional description to the public page</strong>
<div class="border-radius input fill-white">
<%= form_with model: collection, class: "txt-align-start", data: { controller: "form" } do |form| %>
<%= form.rich_textarea :public_description, class: "rich-text-content txt-small",
placeholder: "Add a public note about this collection…",
data: { action: "keydown.ctrl+enter->form#submit:prevent keydown.meta+enter->form#submit:prevent keydown.esc->form#cancel:stop" } %>
<%= form.button "Save changes", type: :submit, class: "btn txt-small" %>
<% end %>
<% else %>
<div class="border-radius pad fill-shade">
<div class="flex-inline center justify-between gap">
<span class="txt-large"><%= icon_tag "lock" %></span>
<label class="switch flex align-center justify-between">
<%= form_with url: collection_publication_path(collection), method: :post, data: { controller: "form" } do |form| %>
<%= form.check_box :published, class: "switch__input", checked: false, data: { action: "change->form#submit" } %>
<span class="switch__btn round"></span>
<span class="for-screen-reader">Turn on the public link</span>
<% end %>
</label>
<span class="txt-large"><%= icon_tag "world" %></span>
</div>
</div>
</div>
<% else %>
<div class="border-radius pad fill-shade">
<div class="flex-inline center justify-between gap">
<span class="txt-large"><%= icon_tag "lock" %></span>
<label class="switch flex align-center justify-between">
<%= form_with url: collection_publication_path(collection), method: :post, data: { controller: "form" } do |form| %>
<%= form.check_box :published, class: "switch__input", checked: false, data: { action: "change->form#submit" } %>
<span class="switch__btn round"></span>
<span class="for-screen-reader">Turn on the public link</span>
<% end %>
</label>
<span class="txt-large"><%= icon_tag "world" %></span>
</div>
</div>
<% end %>
</div>
<% end %>
</div>
<% end %>
+23 -21
View File
@@ -1,21 +1,23 @@
<strong class="txt-large">Workflows</strong>
<div class="flex justify-center margin-block-end">Use a Workflow to track progress in this Collection.</div>
<div class="flex flex-wrap gap justify-center">
<% Workflow.all.each do |workflow| %>
<div class="workflow-preview txt-align-start border border-radius <%= 'workflow-preview--selected' if workflow == collection.workflow %>">
<%= button_to collection_workflow_path(collection), method: :patch do %>
<%= hidden_field_tag "collection[workflow_id]", workflow.id %>
<strong class="txt-small overflow-ellipsis flex-item-no-shrink"><%= workflow.name %></strong>
<ul class="list-style-none txt-xx-small margin-none flex flex-column gap-half">
<% workflow.stages.each do |stage| %>
<li class="overflow-ellipsis flex align-center gap-half min-width">
<span class="workflow-preview__swatch btn btn--circle" style="--btn-background: <%= stage.color.present? ? stage.color : Card::Colored::DEFAULT_COLOR %>;"></span>
<span class="overflow-ellipsis"><%= stage.name %></span>
</li>
<% end %>
</ul>
<% end %>
</div>
<% end %>
</div>
<p class="margin-block-end-double"><%= link_to "Manage workflows", workflows_path, class: "btn btn--plain txt-link" %></p>
<%= turbo_frame_tag @collection, :workflows do %>
<strong class="txt-large">Workflows</strong>
<div class="flex justify-center margin-block-end">Use a Workflow to track progress in this Collection.</div>
<div class="flex flex-wrap gap justify-center">
<% Workflow.all.each do |workflow| %>
<div class="workflow-preview txt-align-start border border-radius <%= 'workflow-preview--selected' if workflow == collection.workflow %>">
<%= button_to collection_workflow_path(collection), method: :patch do %>
<%= hidden_field_tag "collection[workflow_id]", workflow.id %>
<strong class="txt-small overflow-ellipsis flex-item-no-shrink"><%= workflow.name %></strong>
<ul class="list-style-none txt-xx-small margin-none flex flex-column gap-half">
<% workflow.stages.each do |stage| %>
<li class="overflow-ellipsis flex align-center gap-half min-width">
<span class="workflow-preview__swatch btn btn--circle" style="--btn-background: <%= stage.color.present? ? stage.color : Card::Colored::DEFAULT_COLOR %>;"></span>
<span class="overflow-ellipsis"><%= stage.name %></span>
</li>
<% end %>
</ul>
<% end %>
</div>
<% end %>
</div>
<p class="margin-block-end-double"><%= link_to "Manage workflows", workflows_path, class: "btn btn--plain txt-link" %></p>
<% end %>
+1
View File
@@ -18,6 +18,7 @@ Rails.application.routes.draw do
resource :workflow, only: :update
resource :involvement
resource :publication
resource :entropy_configuration
end
resources :cards
@@ -0,0 +1,17 @@
require "test_helper"
class Collections::EntropyConfigurationsControllerTest < ActionDispatch::IntegrationTest
setup do
sign_in_as :kevin
@collection = collections(:writebook)
end
test "update" do
put collection_entropy_configuration_path(@collection), params: { collection: { auto_close_period: 1.day, auto_reconsider_period: 2.days } }
assert_equal 1.day, @collection.entropy_configuration.reload.auto_close_period
assert_equal 2.days, @collection.entropy_configuration.reload.auto_reconsider_period
assert_turbo_stream action: :replace, target: dom_id(@collection, :entropy_configuration)
end
end
@@ -13,7 +13,7 @@ class Collections::PublicationsControllerTest < ActionDispatch::IntegrationTest
post collection_publication_path(@collection)
end
assert_redirected_to edit_collection_path(@collection)
assert_turbo_stream action: :replace, target: dom_id(@collection, :publication)
end
test "unpublish a collection" do
@@ -24,6 +24,6 @@ class Collections::PublicationsControllerTest < ActionDispatch::IntegrationTest
delete collection_publication_path(@collection)
end
assert_redirected_to edit_collection_path(@collection)
assert_turbo_stream action: :replace, target: dom_id(@collection, :publication)
end
end
@@ -10,7 +10,7 @@ class Collections::WorkflowsControllerTest < ActionDispatch::IntegrationTest
patch collection_workflow_path(collection), params: { collection: { workflow_id: workflows(:on_call).id } }
assert_redirected_to cards_path(collection_ids: [ collection.id ])
assert_turbo_stream action: :replace, target: dom_id(collection, :workflows)
assert_equal workflows(:on_call), collection.reload.workflow
end
end