Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -72,46 +72,36 @@ See COPYRIGHT and LICENSE files for more details.
end

flex.with_row do
render(border_box_container(mb: 3, data: drop_target_config)) do |component|
component.with_header(font_weight: :bold) do
flex_layout(justify_content: :space_between, align_items: :center) do |header_container|
header_container.with_column do
render(Primer::Beta::Text.new(font_weight: :bold)) do
I18n.t("settings.project_phase_definitions.section_header")
end
end
end
end
if definitions.empty?
component.with_row do
render(Primer::Beta::Text.new(color: :subtle)) do
t("settings.project_phase_definitions.non_defined")
end
end
else
definitions.each do |definition|
component.with_row(
data: {
"projects--settings--border-box-filter-target": "searchItem",
test_selector: "project-phase-definition",
**draggable_item_config(definition)
}
) do
render(
Settings::ProjectPhaseDefinitions::RowComponent.new(
definition,
first?: definition == definitions.first,
last?: definition == definitions.last
)
render(
OpenProject::Common::BorderBoxListComponent.new(
container: "project-phase-definitions",
position: :relative,
mb: 3,
empty_state_behavior: :dynamic,
data: drop_target_config
)
) do |list|
list.with_header(title: I18n.t("settings.project_phase_definitions.section_header"))

definitions.each do |definition|
list.with_item(
test_selector: "project-phase-definition",
data: {
"projects--settings--border-box-filter-target": "searchItem",
**draggable_item_config(definition)
}
) do
render(
Settings::ProjectPhaseDefinitions::RowComponent.new(
definition,
first?: definition == definitions.first,
last?: definition == definitions.last
)
end
)
end
end
end
end
flex.with_row(display: :none, data: { "projects--settings--border-box-filter-target": "noResultsText" }) do
render Primer::Beta::Text.new do
I18n.t("js.autocompleter.notFoundText")

list.with_empty_state(title: t("settings.project_phase_definitions.non_defined"))
end
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,16 @@ def wrapper_data_attributes
def drop_target_config
{
generic_drag_and_drop_target: "container",
"target-container-accessor": ":scope > ul",
"target-allowed-drag-type": "life-cycle-step-definition"
target_container_accessor: ":scope > ul",
target_allowed_drag_type: "life-cycle-step-definition"
}
end

def draggable_item_config(definition)
{
"draggable-type": "life-cycle-step-definition",
"drop-url": drop_admin_settings_project_phase_definition_path(definition)
draggable_id: definition.id,
draggable_type: "life-cycle-step-definition",
drop_url: drop_admin_settings_project_phase_definition_path(definition)
}
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,54 +29,50 @@ See COPYRIGHT and LICENSE files for more details.

<%=
component_wrapper(data: wrapper_data_attributes) do
render(border_box_container(mb: 3, data: (readonly? ? {} : drag_and_drop_target_config))) do |component|
component.with_header(font_weight: :bold, py: 2) do
flex_layout(justify_content: :space_between, align_items: :center) do |section_header_container|
section_header_container.with_column(py: 2) do
render(Primer::Beta::Text.new(font_weight: :bold)) do
I18n.t("types.edit.export_configuration.pdf_export_templates.label")
end
render(
OpenProject::Common::BorderBoxListComponent.new(
container: "pdf-export-templates",
position: :relative,
mb: 3,
data: (readonly? ? {} : drag_and_drop_target_config)
)
) do |list|
list.with_header(title: I18n.t("types.edit.export_configuration.pdf_export_templates.label")) do |header|
unless readonly?
header.with_action_button(
tag: :a,
href: enable_all_type_pdf_export_template_index_path(type_id: @type.id),
scheme: :invisible,
font_weight: :bold,
color: :subtle,
aria: { label: t("projects.settings.actions.label_enable_all") },
test_selector: "enable-all-pdf-export-templates",
data: { turbo_method: :put, turbo_stream: true }
) do |button|
button.with_leading_visual_icon(icon: "check-circle", color: :subtle)
I18n.t("types.edit.export_configuration.pdf_export_templates.actions.label_enable_all")
end
unless readonly?
section_header_container.with_column(flex_layout: true, justify_content: :flex_end) do |actions_container|
actions_container.with_column do
render(
Primer::Beta::Button.new(
tag: :a,
href: enable_all_type_pdf_export_template_index_path(type_id: @type.id),
scheme: :invisible,
font_weight: :bold,
color: :subtle,
"aria-label": t("projects.settings.actions.label_enable_all"),
data: { "turbo-method": :put, "turbo-stream": true, test_selector: "enable-all-pdf-export-templates" }
)
) do |button|
button.with_leading_visual_icon(icon: "check-circle", color: :subtle)
I18n.t("types.edit.export_configuration.pdf_export_templates.actions.label_enable_all")
end
end
actions_container.with_column do
render(
Primer::Beta::Button.new(
tag: :a,
href: disable_all_type_pdf_export_template_index_path(type_id: @type.id),
scheme: :invisible,
font_weight: :bold,
color: :subtle,
"aria-label": t("projects.settings.actions.label_disable_all"),
data: { "turbo-method": :put, "turbo-stream": true, test_selector: "disable-all-pdf-export-templates" }
)
) do |button|
button.with_leading_visual_icon(icon: "x-circle", color: :subtle)
I18n.t("types.edit.export_configuration.pdf_export_templates.actions.label_disable_all")
end
end
end
header.with_action_button(
tag: :a,
href: disable_all_type_pdf_export_template_index_path(type_id: @type.id),
scheme: :invisible,
font_weight: :bold,
color: :subtle,
aria: { label: t("projects.settings.actions.label_disable_all") },
test_selector: "disable-all-pdf-export-templates",
data: { turbo_method: :put, turbo_stream: true }
) do |button|
button.with_leading_visual_icon(icon: "x-circle", color: :subtle)
I18n.t("types.edit.export_configuration.pdf_export_templates.actions.label_disable_all")
end
end
end

@type.pdf_export_templates.list.each do |template|
component.with_row(data: (readonly? ? {} : draggable_item_config(template))) do
list.with_item(
test_selector: "pdf-export-template-row-#{template.id}",
data: (readonly? ? {} : draggable_item_config(template))
) do
render(
WorkPackageTypes::ExportTemplateRowComponent.new(
type: @type,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,18 +54,16 @@ def wrapper_data_attributes
def drag_and_drop_target_config
{
generic_drag_and_drop_target: "container",
"target-container-accessor": ":scope > ul",
"target-allowed-drag-type": "template",
test_selector: "pdf-export-template-rows"
target_container_accessor: ":scope > ul",
target_allowed_drag_type: "template"
}
end

def draggable_item_config(template)
{
"draggable-id": template.id,
"draggable-type": "template",
"drop-url": drop_type_pdf_export_template_path(type_id: @type.id, id: template.id),
test_selector: "pdf-export-template-row-#{template.id}"
draggable_id: template.id,
draggable_type: "template",
drop_url: drop_type_pdf_export_template_path(type_id: @type.id, id: template.id)
}
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,15 @@ See COPYRIGHT and LICENSE files for more details.
enabled: !readonly?,
size: :small,
status_label_position: :start,
aria: { label: toggle_label },
test_selector: "toggle-pdf-export-template-row-#{@template.id}"
}
# A read-only toggle is disabled, so it never posts; omit the mutation wiring entirely.
unless readonly?
toggle_options.merge!(
src: toggle_type_pdf_export_template_path(type_id: @type.id, id: @template.id),
csrf_token: form_authenticity_token,
data: { "turbo-method": :post, "turbo-stream": true },
data: { turbo_method: :post, turbo_stream: true },
classes: "op-primer-adjustments__toggle-switch--hidden-loading-indicator"
)
end
Expand Down
13 changes: 13 additions & 0 deletions app/components/work_package_types/export_template_row_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,18 @@ def initialize(type:, template:, readonly: false)
end

def readonly? = @readonly

def wrapper_uniq_by
@template.id
end

private

def toggle_label
I18n.t(
"types.edit.export_configuration.pdf_export_templates.actions.label_toggle_template",
template: @template.label
)
end
end
end
1 change: 1 addition & 0 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6217,6 +6217,7 @@ en:
actions:
label_disable_all: "Disable all"
label_enable_all: "Enable all"
label_toggle_template: "Toggle %{template}"
label: "PDF Export templates"
tab: "Generate PDF"
templates:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# 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.
#++

require "rails_helper"

RSpec.describe Settings::ProjectPhaseDefinitions::IndexComponent, type: :component do
include Rails.application.routes.url_helpers

subject(:rendered_component) { render_inline(described_class.new(definitions:)) }

# The row component reads the +project_count+ column added by the
# +with_project_count+ scope, so definitions are loaded through it.
let(:definitions) { Project::PhaseDefinition.with_project_count }

def drop_url_for(definition)
drop_admin_settings_project_phase_definition_path(definition)
end

context "with definitions" do
let!(:draggable_records) { create_list(:project_phase_definition, 2) }

it_behaves_like "rendering Box", row_count: 2
it_behaves_like "a reorderable Border Box List", drag_type: "life-cycle-step-definition"
end

context "without definitions" do
it_behaves_like "rendering an empty Border Box List",
heading: I18n.t("settings.project_phase_definitions.non_defined")
end
end
Loading
Loading