Workflow statuses editing

This commit is contained in:
2026-04-13 02:22:52 +03:00
parent 9766430e69
commit 450b7fb1d0
10 changed files with 130 additions and 20 deletions
@@ -0,0 +1,34 @@
# frozen_string_literal: true
module ProjectAdmin
module Workflows
class StatusesController < ApplicationController
before_action :fetch_workflow
def edit
@form = ProjectAdmin::Workflows::Statuses::BatchUpdate.from_model(@workflow)
end
def batch_update
form_params = params.expect(workflow: { task_statuses_attributes: [%i[id _destroy name color icon]] })
if form_params[:task_statuses_attributes].respond_to?(:keys)
form_params[:task_statuses_attributes] = form_params[:task_statuses_attributes].values
end
@form = ProjectAdmin::Workflows::Statuses::BatchUpdate.new(form_params)
if @form.perform(@workflow)
redirect_to project_admin_workflow_path(@project, @workflow)
else
render :edit
end
end
private
def fetch_workflow
@workflow = @project.workflows.find(params[:workflow_id])
end
end
end
end
@@ -0,0 +1,2 @@
module ProjectAdmin::Workflows::StatusesHelper
end
+8
View File
@@ -12,4 +12,12 @@ module TasksHelper
def task_status_selector(task, with_form: false)
render Tasks::Statuses::SelectorViewModel.new(task, with_form:)
end
# TODO: move into another helper?
def task_status_badge(status)
content_tag(
:span, mask_icon(Tasks::Statuses::SelectorViewModel.icon(status)) + status.name,
class: ['badge', 'task-status', status.color]
)
end
end
-1
View File
@@ -8,7 +8,6 @@ class TaskStatus < ApplicationRecord
enum :color, %w[blue gray yellow green purple pink].index_by(&:itself), default: 'gray', scopes: false
validates :name, presence: true, uniqueness: { scope: :workflow }
validates :category, presence: true
scope :default_order, -> { order(:position, :name) }
end
@@ -0,0 +1,55 @@
# frozen_string_literal: true
module ProjectAdmin
module Workflows
module Statuses
class BatchUpdate < ApplicationService
class TaskStatus
include ActiveModel::Model
include ActiveModel::Attributes
attribute :id, :string
attribute :_destroy, :boolean
attribute :name
attribute :color
attribute :icon
end
attr_accessor :task_statuses
attr_reader :workflow
def self.from_model(workflow)
new(task_statuses_attributes: workflow.task_statuses.map do |ts|
ts.attributes.slice(*TaskStatus.attribute_names)
end)
end
def task_statuses_attributes=(attributes)
@task_statuses = Array(attributes).map { |e| TaskStatus.new(e) }
end
def perform(workflow)
@workflow = workflow
task_status_models = @workflow.task_statuses.index_by(&:id)
@workflow.transaction(requires_new: true) do
task_statuses.each do |ts|
model = task_status_models.fetch(ts.id.to_i)
if ts._destroy
model.destroy!
else
model.update!(
name: ts.name,
icon: ts.icon,
color: ts.color
)
end
end
end
true
end
end
end
end
end
@@ -13,6 +13,12 @@ module Tasks
tool: 'tool_line'
}.freeze
def self.icon(status)
ICONS.fetch(status.icon.to_sym)
end
delegate :icon, to: :'self.class'
def initialize(task, with_form: false)
@task = task
@with_form = with_form
@@ -27,8 +33,7 @@ module Tasks
view_context.render(
partial: 'tasks/status_selector',
locals: { task: @task, id: dom_id, with_form: @with_form,
workflow_task_statuses:,
task_status_badge: ->(status) { task_status_badge(status, view_context) } }
workflow_task_statuses: }
)
end
@@ -37,17 +42,6 @@ module Tasks
def workflow_task_statuses
@task.workflow.task_statuses.sort_by { |e| [e.position, e.name] }
end
def task_status_badge(status, view_context)
view_context.content_tag(
:span, view_context.mask_icon(icon(status)) + status.name,
class: ['badge', 'task-status', status.color]
)
end
def icon(status)
ICONS.fetch(status.icon.to_sym)
end
end
end
end
@@ -5,4 +5,4 @@ h1
ul
- @workflow.task_statuses.each do |status|
li= status.name
li= task_status_badge(status)
@@ -0,0 +1,16 @@
= form_with model: @form, scope: 'workflow', url: project_admin_workflow_statuses_path(@project, @workflow), method: :put do |f|
= f.fields_for :task_statuses, include_id: false do |tsf|
fieldset
= tsf.hidden_field :id
= tsf.hidden_field :_destroy
.field
= tsf.label :name
= tsf.text_field :name
.field
= tsf.label :color
= tsf.select :color, TaskStatus.colors
.field
= tsf.label :icon
= tsf.select :icon, TaskStatus.icons
.submit
= f.submit
+2 -2
View File
@@ -1,9 +1,9 @@
details.dropdown.task-status-selector id=id data-controller="tasks--status-selector"
summary= task_status_badge[task.status]
summary= task_status_badge(task.status)
ul
- workflow_task_statuses.each do |status|
li
a href="#" data-status-id="#{status.id}" data-action="tasks--status-selector#changeStatus:prevent" = task_status_badge[status]
a href="#" data-status-id="#{status.id}" data-action="tasks--status-selector#changeStatus:prevent" = task_status_badge(status)
- if with_form
= form_with model: Tasks::ChangeStatus.new, url: change_status_task_path(task), method: :patch, data: {'tasks--status-selector-target': 'form', action: 'turbo:submit-end->tasks--status-selector#finalize'} do |f|
= f.hidden_field :status_id, data: {'tasks--status-selector-target': 'statusField'}
+5 -3
View File
@@ -21,9 +21,11 @@ Rails.application.routes.draw do
resources :projects do
namespace :project_admin, as: 'admin' do
resources :workflows do
namespace :statuses do
get '/', action: :index
patch '/', action: :batch_update
scope module: :workflows do
resources :statuses, only: %i[index] do
get :edit, on: :collection
put '/', action: :batch_update, on: :collection
end
end
end
end