Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[59769] When adding new relations, auto-scroll to show the newly added relation #17355

66 changes: 46 additions & 20 deletions app/components/work_package_relations_tab/index_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,16 @@ class WorkPackageRelationsTab::IndexComponent < ApplicationComponent
include Turbo::FramesHelper
include OpTurbo::Streamable

attr_reader :work_package, :relations, :children, :directionally_aware_grouped_relations
attr_reader :work_package, :relations, :children, :directionally_aware_grouped_relations, :scroll_to_id

def initialize(work_package:, relations:, children:)
def initialize(work_package:, relations:, children:, scroll_to_id: nil)
super()

@work_package = work_package
@relations = relations
@children = children
@directionally_aware_grouped_relations = group_relations_by_directional_context
@scroll_to_id = scroll_to_id
end

def self.wrapper_key
Expand Down Expand Up @@ -47,23 +48,44 @@ def group_relations_by_directional_context
def any_relations? = relations.any? || children.any?

def render_relation_group(title:, relation_type:, items:, &_block)
render(border_box_container(padding: :condensed,
data: { test_selector: "op-relation-group-#{relation_type}" })) do |border_box|
border_box.with_header(py: 3) do
flex_layout(align_items: :center) do |flex|
flex.with_column(mr: 2) do
render(Primer::Beta::Text.new(font_size: :normal, font_weight: :bold)) { title }
end
flex.with_column do
render(Primer::Beta::Counter.new(count: items.size, round: true, scheme: :primary))
end
render(border_box_container(
padding: :condensed,
data: { test_selector: "op-relation-group-#{relation_type}" }
)) do |border_box|
render_header(border_box, title, items)
render_items(border_box, items, &_block)
end
end

def render_header(border_box, title, items)
border_box.with_header(py: 3) do
flex_layout(align_items: :center) do |flex|
flex.with_column(mr: 2) do
render(Primer::Beta::Text.new(font_size: :normal, font_weight: :bold)) { title }
end
flex.with_column do
render(Primer::Beta::Counter.new(count: items.size, round: true, scheme: :primary))
end
end
end
end

items.each do |item|
border_box.with_row(test_selector: row_test_selector(item)) do
yield(item)
end
def render_items(border_box, items)
items.each do |item|
related_work_package_id = find_related_work_package_id(item)
data_attribute = nil
if related_work_package_id.to_s == @scroll_to_id
data_attribute = {
controller: "work-packages--relations-tab--scroll",
application_target: "dynamic",
"work-packages--relations-tab--scroll-target": "scrollToRow"
}
end
border_box.with_row(
test_selector: row_test_selector(item),
data: data_attribute
) do
yield(item)
end
end
end
Expand All @@ -83,11 +105,15 @@ def new_button_test_selector(relation_type:)
end

def row_test_selector(item)
related_work_package_id = find_related_work_package_id(item)
"op-relation-row-#{related_work_package_id}"
end

def find_related_work_package_id(item)
if item.is_a?(Relation)
target = item.to == work_package ? item.from : item.to
"op-relation-row-#{target.id}"
else # Work Package object
"op-relation-row-#{item.id}"
item.from_id == work_package.id ? item.to_id : item.from_id
else
item.id
end
end
end
3 changes: 2 additions & 1 deletion app/controllers/work_package_children_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ def create
component = WorkPackageRelationsTab::IndexComponent.new(
work_package: @work_package,
relations: @relations,
children: @children
children: @children,
scroll_to_id: target_work_package_id
)
replace_via_turbo_stream(component:)
update_flash_message_via_turbo_stream(
Expand Down
4 changes: 3 additions & 1 deletion app/controllers/work_package_relations_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,12 @@ def create
.call(create_relation_params)

if service_result.success?
target_work_package_id = params[:relation][:to_id]
@work_package.reload
component = WorkPackageRelationsTab::IndexComponent.new(work_package: @work_package,
relations: @work_package.relations,
children: @work_package.children)
children: @work_package.children,
scroll_to_id: target_work_package_id)
replace_via_turbo_stream(component:)
respond_with_turbo_streams
else
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Controller } from '@hotwired/stimulus';

export default class ScrollController extends Controller {
static targets = ['scrollToRow'];

declare readonly scrollToRowTarget:HTMLElement;
declare readonly hasScrollToRowTarget:boolean;

scrollToRowTargetConnected() {
if (this.hasScrollToRowTarget) {
setTimeout(() => {
this.scrollToRowTarget.scrollIntoView({ behavior: 'smooth', block: 'center' });
});
}
}
}
2 changes: 1 addition & 1 deletion spec/controllers/work_package_relations_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@
new_relation = Relation.last

expect(WorkPackageRelationsTab::IndexComponent).to have_received(:new)
.with(work_package:, relations: [relation, new_relation], children:)
.with(work_package:, relations: [relation, new_relation], children:, scroll_to_id: unrelated_work_package.id)
expect(controller).to have_received(:replace_via_turbo_stream)
.with(component: an_instance_of(WorkPackageRelationsTab::IndexComponent))
end
Expand Down
Loading