Show different status matrices per tab

This commit is contained in:
Mir Bhatia
2026-03-17 15:52:01 +01:00
parent 72d54a8a57
commit cfafd01fb0
7 changed files with 114 additions and 8 deletions
@@ -0,0 +1,43 @@
<%#-- copyright
OpenProject is an open source project management software.
Copyright (C) the OpenProject GmbH
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License version 3.
OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
Copyright (C) 2006-2013 Jean-Philippe Lang
Copyright (C) 2010-2013 the ChiliProject Team
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
See COPYRIGHT and LICENSE files for more details.
++#%>
<%=
render(Primer::Beta::Blankslate.new(border: true)) do |blankslate|
blankslate.with_heading(tag: :h2).with_content(t("admin.workflows.blankslate.title"))
blankslate.with_description_content(t("admin.workflows.blankslate.description"))
blankslate.with_primary_action(
href: helpers.status_dialog_workflows_path(role_id: @role.id, type_id: @type.id, tab: @tab),
scheme: :secondary,
data: { controller: "async-dialog" }
) do |button|
button.with_leading_visual_icon(icon: :plus)
t("admin.workflows.status_button")
end
end
%>
@@ -0,0 +1,42 @@
# frozen_string_literal: true
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
#++
module Workflows
class BlankslateComponent < ApplicationComponent
include OpPrimer::ComponentHelpers
def initialize(role:, type:, tab:)
super
@role = role
@type = type
@tab = tab
end
end
end
+5 -1
View File
@@ -154,7 +154,11 @@ class WorkflowsController < ApplicationController
end
def role_type_statuses
@type.statuses(role: @role)
@type.statuses(role: @role, tab: current_tab)
end
def current_tab
params[:tab] || "always"
end
def workflows_for_form
+16 -4
View File
@@ -86,16 +86,28 @@ class Type < ApplicationRecord
name <=> other.name
end
def self.statuses(types, role: nil) # rubocop:disable Metrics/AbcSize
def self.statuses(types, role: nil, tab: nil) # rubocop:disable Metrics/AbcSize
workflow_table, status_table = [Workflow, Status].map(&:arel_table)
old_id_subselect, new_id_subselect = %i[old_status_id new_status_id].map do |foreign_key|
subquery = workflow_table.project(workflow_table[foreign_key]).where(workflow_table[:type_id].in(types))
subquery = subquery.where(workflow_table[:role_id].eq(role.id)) if role
subquery = apply_tab_condition(subquery, workflow_table, tab) if tab
subquery
end
Status.where(status_table[:id].in(old_id_subselect).or(status_table[:id].in(new_id_subselect)))
end
def self.apply_tab_condition(subquery, workflow_table, tab)
case tab
when "author"
subquery.where(workflow_table[:author].eq(true))
when "assignee"
subquery.where(workflow_table[:assignee].eq(true))
else
subquery.where(workflow_table[:author].eq(false).and(workflow_table[:assignee].eq(false)))
end
end
def self.standard_type
where(is_standard: true).first
end
@@ -104,13 +116,13 @@ class Type < ApplicationRecord
includes(:projects).where(projects: { id: project })
end
def statuses(include_default: false, role: nil)
def statuses(include_default: false, role: nil, tab: nil)
if new_record?
Status.none
elsif include_default
self.class.statuses([id], role:).or(Status.where_default)
self.class.statuses([id], role:, tab:).or(Status.where_default)
else
self.class.statuses([id], role:)
self.class.statuses([id], role:, tab:)
end
end
+3 -1
View File
@@ -55,6 +55,8 @@ See COPYRIGHT and LICENSE files for more details.
end
%>
<% end %>
<% end %>
<% else %>
<%= render Workflows::BlankslateComponent.new(role: @role, type: @type, tab: params[:tab]) %>
<% end %>
<% end %>
<% end %>
+3
View File
@@ -418,6 +418,9 @@ en:
role_selector:
label: "Role: %{role}"
no_role: "Select role"
blankslate:
title: "No status transitions configured"
description: "Add statuses to start configuring workflows for this role"
authentication:
login_and_registration: "Login and registration"
@@ -35,9 +35,9 @@
tbody
span.workflow-table--turned-header
white-space: nowrap
transform: rotate(270deg)
transform: rotate(270deg) translateX(-50%)
position: absolute
top: 235px
top: 50%
left: 0px
transform-origin: 0 0
text-transform: uppercase