Skip to content

Commit 0034c17

Browse files
authored
Merge pull request opf#17604 from opf/58427-indicate-that-there-are-work-package-relations-which-the-user-has-no-permission-to-see
[58427] Indicate that there are work package relations which the user has no permission to see
2 parents ddffcd9 + 116bea2 commit 0034c17

File tree

14 files changed

+284
-171
lines changed

14 files changed

+284
-171
lines changed

app/components/work_package_relations_tab/index_component.html.erb

+24-11
Original file line numberDiff line numberDiff line change
@@ -47,34 +47,47 @@
4747
key_namespace = "#{I18N_NAMESPACE}.relations"
4848

4949
# Relations
50-
directionally_aware_grouped_relations.each do |relation_type, relations_of_type|
51-
base_key = "#{key_namespace}.label_#{relation_type}"
50+
directionally_aware_grouped_relations.each do |relation_group|
51+
base_key = "#{I18N_NAMESPACE}.relations.label_#{relation_group.type}"
52+
53+
# Combine visible and invisible relations into a single list
54+
all_relations = relation_group.visible_relations.map { |r| [r, :visible] } +
55+
relation_group.ghost_relations.map { |r| [r, :ghost] }
5256

5357
flex.with_row(mb: 4) do
5458
render_relation_group(
5559
title: t("#{base_key}_plural").upcase_first,
56-
relation_type:,
57-
items: relations_of_type
58-
) do |relation|
59-
render(WorkPackageRelationsTab::RelationComponent.new(work_package:,
60-
relation:))
60+
relation_type: relation_group.type,
61+
items: all_relations
62+
) do |relation, visibility|
63+
# Render each relation with its visibility
64+
render(WorkPackageRelationsTab::RelationComponent.new(
65+
work_package: work_package,
66+
relation: relation,
67+
visibility: visibility
68+
))
6169
end
6270
end
6371
end
6472

6573
# Children
66-
if children.any?
74+
if any_children?
6775
base_key = "#{key_namespace}.label_child"
6876

77+
# Combine visible and invisible children into a single list
78+
all_children = visible_children.map { |r| [r, :visible] } +
79+
ghost_children.map { |r| [r, :ghost] }
80+
6981
flex.with_row do
7082
render_relation_group(
7183
title: t("#{base_key}_plural").upcase_first,
7284
relation_type: :children,
73-
items: children
74-
) do |child|
85+
items: all_children
86+
) do |child, visibility|
7587
render(WorkPackageRelationsTab::RelationComponent.new(work_package:,
7688
relation: nil,
77-
child:))
89+
child:,
90+
visibility: visibility))
7891
end
7992
end
8093
end

app/components/work_package_relations_tab/index_component.rb

+14-15
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,15 @@ class WorkPackageRelationsTab::IndexComponent < ApplicationComponent
1616
include Turbo::FramesHelper
1717
include OpTurbo::Streamable
1818

19-
attr_reader :relations_mediator, :directionally_aware_grouped_relations, :relation_to_scroll_to
19+
attr_reader :relations_mediator, :relation_to_scroll_to
2020

21-
delegate :work_package, :relations, :children, :any_relations?, to: :relations_mediator
21+
delegate :work_package,
22+
:visible_children,
23+
:ghost_children,
24+
:directionally_aware_grouped_relations,
25+
:any_relations?,
26+
:any_children?,
27+
to: :relations_mediator
2228

2329
# Initialize the component with required data
2430
#
@@ -28,7 +34,6 @@ def initialize(work_package: nil, relation_to_scroll_to: nil)
2834
super()
2935

3036
@relations_mediator = WorkPackageRelationsTab::RelationsMediator.new(work_package:)
31-
@directionally_aware_grouped_relations = group_relations_by_directional_context
3237
@relation_to_scroll_to = relation_to_scroll_to
3338
end
3439

@@ -52,12 +57,6 @@ def should_render_create_button?
5257
should_render_add_child? || should_render_add_relations?
5358
end
5459

55-
def group_relations_by_directional_context
56-
relations.group_by do |relation|
57-
relation.relation_type_for(work_package)
58-
end
59-
end
60-
6160
def render_relation_group(title:, relation_type:, items:, &_block)
6261
render(border_box_container(
6362
padding: :condensed,
@@ -129,12 +128,12 @@ def render_child_menu_items(menu) # rubocop:disable Metrics/AbcSize
129128
end
130129

131130
def render_items(border_box, items)
132-
items.each do |item|
131+
items.each do |relation, visibility|
133132
border_box.with_row(
134-
test_selector: row_test_selector(item),
135-
data: data_attribute(item)
133+
test_selector: row_test_selector(relation, visibility),
134+
data: data_attribute(relation)
136135
) do
137-
yield(item)
136+
yield(relation, visibility)
138137
end
139138
end
140139
end
@@ -169,9 +168,9 @@ def new_button_test_selector(relation_type:)
169168
"op-new-relation-button-#{relation_type}"
170169
end
171170

172-
def row_test_selector(item)
171+
def row_test_selector(item, visibility)
173172
related_work_package_id = find_related_work_package_id(item)
174-
"op-relation-row-#{related_work_package_id}"
173+
"op-relation-row-#{visibility}-#{related_work_package_id}"
175174
end
176175

177176
def find_related_work_package_id(item)
Original file line numberDiff line numberDiff line change
@@ -1,104 +1,97 @@
11
<%=
2-
flex_layout do |flex|
3-
flex.with_row(flex_layout: true, justify_content: :space_between, align_items: :center) do |row|
4-
row.with_column do
5-
render(WorkPackages::InfoLineComponent.new(work_package: related_work_package))
6-
end
2+
flex_layout do |flex|
3+
if visible?
4+
flex.with_row(flex_layout: true, justify_content: :space_between, align_items: :center) do |row|
5+
row.with_column do
6+
render(WorkPackages::InfoLineComponent.new(work_package: related_work_package))
7+
end
78

8-
if should_render_action_menu?
9-
row.with_column do
10-
render(Primer::Alpha::ActionMenu.new(test_selector: action_menu_test_selector)) do |menu|
11-
menu.with_show_button(icon: "kebab-horizontal",
12-
"aria-label": I18n.t(:label_relation_actions),
13-
scheme: :invisible,
14-
ml: 2)
9+
if should_render_action_menu?
10+
row.with_column do
11+
render(Primer::Alpha::ActionMenu.new(test_selector: action_menu_test_selector)) do |menu|
12+
menu.with_show_button(icon: "kebab-horizontal",
13+
"aria-label": I18n.t(:label_relation_actions),
14+
scheme: :invisible,
15+
ml: 2)
1516

16-
if should_render_edit_option?
17-
menu.with_item(label: I18n.t(:label_relation_edit),
18-
href: edit_path,
19-
test_selector: edit_button_test_selector,
20-
content_arguments: {
21-
data: { turbo_stream: true }
22-
}) do |item|
23-
item.with_leading_visual_icon(icon: :pencil)
24-
end
25-
end
17+
if should_render_edit_option?
18+
menu.with_item(label: I18n.t(:label_relation_edit),
19+
href: edit_path,
20+
test_selector: edit_button_test_selector,
21+
content_arguments: {
22+
data: { turbo_stream: true }
23+
}) do |item|
24+
item.with_leading_visual_icon(icon: :pencil)
25+
end
26+
end
2627

27-
menu.with_item(label: I18n.t(:label_relation_delete),
28-
scheme: :danger,
29-
href: destroy_path,
30-
form_arguments: {
31-
method: :delete,
32-
data: {
33-
confirm: t("text_are_you_sure"),
34-
turbo_stream: true,
35-
update_work_package: true
36-
}
37-
},
38-
test_selector: delete_button_test_selector) do |item|
39-
item.with_leading_visual_icon(icon: :trash)
28+
menu.with_item(label: I18n.t(:label_relation_delete),
29+
scheme: :danger,
30+
href: destroy_path,
31+
form_arguments: {
32+
method: :delete,
33+
data: {
34+
confirm: t("text_are_you_sure"),
35+
turbo_stream: true,
36+
update_work_package: true
37+
}
38+
},
39+
test_selector: delete_button_test_selector) do |item|
40+
item.with_leading_visual_icon(icon: :trash)
41+
end
42+
end
4043
end
4144
end
4245
end
43-
end
44-
end
4546

46-
flex.with_row(mb: 2) do
47-
render(Primer::Beta::Link.new(href: work_package_path(related_work_package),
48-
color: :default,
49-
underline: false,
50-
font_size: :normal,
51-
font_weight: :bold,
52-
target: "_blank")) { related_work_package.subject }
53-
end
54-
55-
if should_display_description?
56-
flex.with_row(mb: 2) do
57-
render(Primer::Beta::Text.new(font_size: :small, color: :muted)) { format_text(relation, :description) }
58-
end
59-
end
47+
flex.with_row(mb: 2) do
48+
render(Primer::Beta::Link.new(href: work_package_path(related_work_package),
49+
color: :default,
50+
underline: false,
51+
font_size: :normal,
52+
font_weight: :bold,
53+
target: "_blank")) { related_work_package.subject }
54+
end
6055

61-
if should_display_dates_row?
62-
flex.with_row(flex_layout: true, align_items: :center, color: :muted, mb: 2) do |dates_row|
63-
if precedes? && lag_present?
64-
dates_row.with_column(mr: 1) do
65-
render(Primer::Beta::Octicon.new(icon: "arrow-both"))
56+
if should_display_description?
57+
flex.with_row(mb: 2) do
58+
render(Primer::Beta::Text.new(font_size: :small, color: :muted)) { format_text(relation, :description) }
6659
end
67-
dates_row.with_column(mr: 3) do
68-
render(Primer::Beta::Text.new) do
69-
lag_as_text(relation.lag)
70-
end
60+
end
61+
else
62+
flex.with_row(mb: 2) do
63+
render(Primer::Beta::Text.new(font_weight: :bold, color: :muted)) { I18n.t("work_package_relations_tab.relations.ghost_relation_title") }
64+
end
65+
flex.with_row(flex_layout: true, align_items: :center, color: :muted, mb: 2) do |ghost_description_row|
66+
ghost_description_row.with_column(mr: 1) do
67+
render(Primer::Beta::Octicon.new(icon: "alert"))
68+
end
69+
ghost_description_row.with_column do
70+
render(Primer::Beta::Text.new) { I18n.t("work_package_relations_tab.relations.ghost_relation_description") }
7171
end
7272
end
73+
end
7374

74-
if related_work_package.start_date.present? || related_work_package.due_date.present?
75-
dates_row.with_column(mr: 1) do
76-
icon = if follows?
77-
:calendar
78-
elsif precedes?
79-
:pin
80-
end
75+
# Show dates for both visible and ghost relation
76+
if should_display_dates_row?
77+
flex.with_row(flex_layout: true, align_items: :center, color: :muted, mb: 2) do |dates_row|
78+
if precedes? && lag_present?
79+
dates_row.with_column(mr: 1) { render(Primer::Beta::Octicon.new(icon: "arrow-both")) }
80+
dates_row.with_column(mr: 2) { render(Primer::Beta::Text.new) { lag_as_text(relation.lag) } }
81+
end
8182

82-
render(Primer::Beta::Octicon.new(icon:))
83+
dates_row.with_column(mr: 1) do
84+
render(Primer::Beta::Octicon.new(icon: helpers.work_package_dates_icon(related_work_package)))
8385
end
8486
dates_row.with_column do
85-
render(Primer::Beta::Text.new) do
86-
"#{format_date(related_work_package.start_date)} - #{format_date(related_work_package.due_date)}"
87-
end
87+
render(Primer::Beta::Text.new) { helpers.work_package_formatted_dates(related_work_package) }
8888
end
89-
end
9089

91-
if follows? && lag_present?
92-
dates_row.with_column(ml: 3, mr: 1) do
93-
render(Primer::Beta::Octicon.new(icon: "arrow-both"))
94-
end
95-
dates_row.with_column(mr: 1) do
96-
render(Primer::Beta::Text.new) do
97-
lag_as_text(relation.lag)
98-
end
90+
if follows? && lag_present?
91+
dates_row.with_column(ml: 2, mr: 1) { render(Primer::Beta::Octicon.new(icon: "arrow-both")) }
92+
dates_row.with_column(mr: 1) { render(Primer::Beta::Text.new) { lag_as_text(relation.lag) } }
9993
end
10094
end
10195
end
10296
end
103-
end
10497
%>

app/components/work_package_relations_tab/relation_component.rb

+12-4
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,17 @@ class WorkPackageRelationsTab::RelationComponent < ApplicationComponent
22
include ApplicationHelper
33
include OpPrimer::ComponentHelpers
44

5-
attr_reader :work_package, :relation, :child
5+
attr_reader :work_package, :relation, :child, :visibility
66

77
def initialize(work_package:,
88
relation:,
9+
visibility:,
910
child: nil)
1011
super()
1112

1213
@work_package = work_package
1314
@relation = relation
15+
@visibility = visibility
1416
@child = child
1517
end
1618

@@ -47,6 +49,10 @@ def allowed_to_manage_relations?
4749
helpers.current_user.allowed_in_project?(:manage_work_package_relations, @work_package.project)
4850
end
4951

52+
def visible?
53+
@visibility == :visible
54+
end
55+
5056
def underlying_resource_id
5157
@underlying_resource_id ||= if parent_child_relationship?
5258
@child.id
@@ -66,16 +72,18 @@ def lag_present?
6672
end
6773

6874
def should_display_dates_row?
69-
return false if parent_child_relationship?
70-
71-
relation.follows? || relation.precedes?
75+
parent_child_relationship? || relation.follows? || relation.precedes?
7276
end
7377

7478
def follows?
79+
return false if parent_child_relationship?
80+
7581
relation.relation_type_for(work_package) == Relation::TYPE_FOLLOWS
7682
end
7783

7884
def precedes?
85+
return false if parent_child_relationship?
86+
7987
relation.relation_type_for(work_package) == Relation::TYPE_PRECEDES
8088
end
8189

0 commit comments

Comments
 (0)