Merge pull request #1031 from basecamp/improve-workflows

Improve workflows
This commit is contained in:
Jason Zimdars
2025-09-08 10:32:50 -05:00
committed by GitHub
9 changed files with 69 additions and 25 deletions
+20
View File
@@ -12,4 +12,24 @@ module WorkflowsHelper
def stage_color(stage)
stage.color.presence || Card::DEFAULT_COLOR
end
def dependent_collections_sentence(workflow)
if workflow.collections.many?
"It will be removed from #{ workflow.collections.count } collections that are using it."
elsif workflow.collections.one?
"It will be removed from the only collection using it."
else
"It's not being used in any collections."
end
end
def workflow_switch_confirmation_message(workflow, collection)
if workflow == collection.workflow
"Stop using #{workflow.name}? Cards you're working on will lose their current stage."
elsif collection.workflow.present?
"Switch to #{workflow.name}? This will return all cards you're working on to the first stage."
else
nil
end
end
end
+2 -1
View File
@@ -4,7 +4,8 @@ class Workflow < ApplicationRecord
{ name: "In progress", color: "var(--color-card-3)" }
]
has_many :stages, dependent: :delete_all
has_many :stages, dependent: :destroy
has_many :collections, dependent: :nullify
after_create_commit :create_default_stages
+2
View File
@@ -1,6 +1,8 @@
class Workflow::Stage < ApplicationRecord
belongs_to :workflow, touch: true
has_many :cards, dependent: :nullify
before_validation :assign_random_color, on: :create
private
@@ -7,7 +7,10 @@
<div class="flex flex-wrap gap justify-center">
<% Workflow.all.each do |workflow| %>
<div class="workflow-preview txt-align-start border-radius <%= 'workflow-preview--selected' if workflow == collection.workflow %>">
<%= button_to collection_workflow_path(collection), method: :patch, aria: { label: workflow == collection.workflow ? "Stop using this workflow" : "Use this workflow" } do %>
<% confirmation_message = workflow_switch_confirmation_message(workflow, collection) %>
<%= button_to collection_workflow_path(collection), method: :patch,
aria: { label: workflow == collection.workflow ? "Stop using this workflow" : "Use this workflow" },
data: confirmation_message ? { turbo_confirm: confirmation_message } : {} do %>
<%= hidden_field_tag "collection[workflow_id]", workflow == collection.workflow ? "" : 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">
@@ -22,5 +25,6 @@
</div>
<% end %>
</div>
<%= link_to "Manage workflows", workflows_path, class: "btn btn--plain txt-link", data: { turbo_frame: "_top" } %>
<% end %>
+9 -2
View File
@@ -1,10 +1,17 @@
<%= turbo_frame_tag workflow do %>
<article class="panel" style="--panel-size: 40ch;">
<div class="flex gap-half align-center justify-starts">
<article class="panel" style="--panel-size: 40ch;" style="view-transition-name: <%= dom_id(workflow) %>">
<div class="flex gap-half align-center">
<%= turbo_frame_tag dom_id(workflow, :header) do %>
<%= link_to edit_workflow_path(workflow) do %>
<h3 class="txt-large txt-nowrap margin-none overflow-ellipsis"><%= workflow.name %></h3>
<% end %>
<%= button_to workflow_path(workflow), method: :delete, class: "btn txt-small borderless txt-subtle",
data: { turbo_frame: "_top", turbo_confirm: "Are you sure you want to delete this Workflow? #{ dependent_collections_sentence(workflow) }" },
form: { class: "flex-item-justify-end" } do %>
<%= icon_tag "trash" %>
<span class="for-screen-reader">Delete <%= workflow.name %></span>
<% end %>
<% end %>
</div>
+2 -6
View File
@@ -2,7 +2,8 @@
<div class="flex align-center gap-half">
<%= form_with model: @workflow, url: workflow_path(@workflow), id: dom_id(@workflow, :form), class: "full-width", data: { controller: "form" } do |form| %>
<h3 class="txt-large margin-none">
<%= form.text_field :name, required: true, autofocus: true, class: "input full-width", style: "--input-padding: 0.2em 0.5em;", data: { action: "keydown.esc@document->form#cancel" } %>
<%= form.text_field :name, required: true, autofocus: true, class: "input full-width",
style: "--input-padding: 0.2em 0.5em;", data: { action: "keydown.esc@document->form#cancel focus->form#select" } %>
</h3>
<%= link_to "Cancel", workflow_path(@workflow), data: { form_target: "cancel", turbo_frame: dom_id(@workflow) }, hidden: true %>
<% end %>
@@ -16,10 +17,5 @@
<%= icon_tag "remove-med" %>
<span class="for-screen-reader">Cancel</span>
<% end %>
<%= button_to workflow_path(@workflow), method: :delete, class: "btn txt-small btn--negative", data: { turbo_frame: :workflows, turbo_confirm: "Are you sure you want to delete this workflow?" } do %>
<%= icon_tag "minus" %>
<span class="for-screen-reader">Delete <%= @workflow.name %></span>
<% end %>
</div>
<% end %>
+16 -4
View File
@@ -11,8 +11,20 @@
</div>
<% end %>
<%= turbo_frame_tag :workflows do %>
<section class="center justify-center flex flex-wrap gap">
<section class="center justify-center flex flex-wrap gap">
<% if @workflows.any? %>
<%= render partial: "workflows/workflow", collection: @workflows %>
</section>
<% end %>
<% else %>
<div>
<p class="txt-medium txt-align-center">
Workflows are for organizing Cards you're working on into stages.
</p>
<p class="txt-medium txt-align-center">
<%= link_to new_workflow_path, class: "btn btn--link" do %>
<%= icon_tag "add" %>
<span>Create a new workflow</span>
<% end %>
</p>
</div>
<% end %>
</section>
+11 -10
View File
@@ -1,19 +1,20 @@
<% @page_title = "Create a new Workflow" %>
<% @page_title = "Workflows" %>
<% content_for :header do %>
<%= render "filters/menu", user_filtering: @user_filtering %>
<h1 class="header__title"><%= @page_title %></h1>
<% end %>
<%= turbo_frame_tag :workflows do %>
<article class="panel center margin-block-start flex flex-column gap" style="view-transition-name: <%= dom_id(@workflow) %>">
<article class="panel center" style="--panel-size: 40ch;" style="view-transition-name: <%= dom_id(@workflow) %>">
<div class="flex gap-half align-center justify-starts">
<%= form_with model: @workflow, url: workflows_path, data: { controller: "form" } do |form| %>
<%= form.text_field :name, required: true, autofocus: true, class: "input txt-large", placeholder: "Name your Workflow…", data: { action: "keydown.esc@document->form#cancel" } %>
<%= form.button type: :submit, class: "btn btn--reversed center margin-block-start txt-large" do %>
<%= icon_tag "check" %>
<span class="for-screen-reader">Create Workflow</span>
<h2 class="txt-large margin-none">
<%= form.text_field :name, required: true, autofocus: true, class: "input", placeholder: "Name your Workflow…", data: { action: "keydown.esc@document->form#cancel" } %>
</h2>
<%= form.button type: :submit, class: "btn btn--reversed center margin-block-start txt-medium" do %>
<span>Create Workflow</span>
<% end %>
<%= link_to "Go back", workflows_path, data: { form_target: "cancel", turbo_frame: "_top" }, hidden: true %>
<%= link_to "Go back", workflows_path, data: { form_target: "cancel" }, hidden: true %>
<% end %>
</article>
<% end %>
</div>
</article>
+2 -1
View File
@@ -1,6 +1,7 @@
<%= turbo_frame_tag @stage do %>
<%= form_with model: @stage, url: workflow_stage_path(@stage.workflow, @stage), id: dom_id(@stage, :form), class: "full-width", data: { controller: "form" } do |form| %>
<%= form.text_field :name, required: true, autofocus: true, class: "input full-width", data: { action: "keydown.esc@document->form#cancel" } %>
<%= form.text_field :name, required: true, autofocus: true, class: "input full-width",
data: { action: "keydown.esc@document->form#cancel focus->form#select" } %>
<%= link_to "Cancel", workflow_path(@workflow), data: { form_target: "cancel", turbo_frame: dom_id(@workflow) }, hidden: true %>
<% end %>