diff --git a/CHANGELOG.md b/CHANGELOG.md index 440e92fd4b..32983464c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,10 @@ and this project adheres to ### Fixed +- The breadcrumb project picker now shows the full ancestor path on the project + settings page (previously it collapsed to the sandbox's own name). + [#4769](https://github.com/OpenFn/lightning/issues/4769) + ## [2.16.4-pre] - 2026-05-18 ### Added diff --git a/lib/lightning_web/components/layout_components.ex b/lib/lightning_web/components/layout_components.ex index e4351604fe..fa2b1dde99 100644 --- a/lib/lightning_web/components/layout_components.ex +++ b/lib/lightning_web/components/layout_components.ex @@ -305,7 +305,7 @@ defmodule LightningWeb.LayoutComponents do ## Example <.breadcrumbs> - <.breadcrumb_project_picker project={@project} current_user={@current_user} access_root={@access_root} /> + <.breadcrumb_project_picker project={@project} label={@project_label} /> <.breadcrumb_items items={[{"History", "/projects/\#{@project}/history"}]} /> <.breadcrumb> <:label>{@page_title} @@ -356,32 +356,15 @@ defmodule LightningWeb.LayoutComponents do LiveView pages and the collaborative editor. """ attr :project, Lightning.Projects.Project, required: true - attr :current_user, Lightning.Accounts.User, default: nil - attr :access_root, Lightning.Projects.Project, default: nil + attr :label, :string, required: true def breadcrumb_project_picker(assigns) do - alias Lightning.Projects - alias Lightning.Projects.Project - - access_root = - case {assigns[:access_root], assigns[:current_user]} do - {%Project{} = ar, _} -> - ar - - {nil, %Lightning.Accounts.User{} = user} -> - Projects.access_root_for_user(assigns.project, user) - - _ -> - assigns.project - end - assigns = assigns |> assign( - :label, - Projects.display_name_within_access_root(assigns.project, access_root) + :is_sandbox, + to_string(Lightning.Projects.Project.sandbox?(assigns.project)) ) - |> assign(:is_sandbox, to_string(Project.sandbox?(assigns.project))) |> assign(:color, assigns.project.color) ~H""" diff --git a/lib/lightning_web/hooks.ex b/lib/lightning_web/hooks.ex index e83368163e..56813d3268 100644 --- a/lib/lightning_web/hooks.ex +++ b/lib/lightning_web/hooks.ex @@ -58,12 +58,19 @@ defmodule LightningWeb.Hooks do access_root = Lightning.Projects.access_root_for_user(project, current_user) + project_label = + Lightning.Projects.display_name_within_access_root( + project, + access_root + ) + {:cont, socket |> assign(:side_menu_theme, "primary-theme") |> assign(:project_user, project_user) |> assign(:project, project) |> assign(:access_root, access_root) + |> assign(:project_label, project_label) |> assign(:projects, projects)} true -> diff --git a/lib/lightning_web/live/channel_live/index.ex b/lib/lightning_web/live/channel_live/index.ex index 5c3a136fc0..230b180022 100644 --- a/lib/lightning_web/live/channel_live/index.ex +++ b/lib/lightning_web/live/channel_live/index.ex @@ -30,8 +30,7 @@ defmodule LightningWeb.ChannelLive.Index do <:label>{@page_title} diff --git a/lib/lightning_web/live/channel_request_live/show.ex b/lib/lightning_web/live/channel_request_live/show.ex index ec8de68109..cee507489b 100644 --- a/lib/lightning_web/live/channel_request_live/show.ex +++ b/lib/lightning_web/live/channel_request_live/show.ex @@ -57,8 +57,7 @@ defmodule LightningWeb.ChannelRequestLive.Show do <:label> diff --git a/lib/lightning_web/live/project_live/settings.html.heex b/lib/lightning_web/live/project_live/settings.html.heex index f7b4cee0a7..711dbdb27b 100644 --- a/lib/lightning_web/live/project_live/settings.html.heex +++ b/lib/lightning_web/live/project_live/settings.html.heex @@ -10,7 +10,10 @@ <:breadcrumbs> - + <:label>{@page_title} diff --git a/lib/lightning_web/live/run_live/index.html.heex b/lib/lightning_web/live/run_live/index.html.heex index 1325dec924..6a92211159 100644 --- a/lib/lightning_web/live/run_live/index.html.heex +++ b/lib/lightning_web/live/run_live/index.html.heex @@ -12,8 +12,7 @@ <:label>{@page_title} diff --git a/lib/lightning_web/live/run_live/show.ex b/lib/lightning_web/live/run_live/show.ex index b25d8623a5..56e8c62add 100644 --- a/lib/lightning_web/live/run_live/show.ex +++ b/lib/lightning_web/live/run_live/show.ex @@ -66,8 +66,7 @@ defmodule LightningWeb.RunLive.Show do <:label>Sandboxes diff --git a/lib/lightning_web/live/workflow_live/edit.ex b/lib/lightning_web/live/workflow_live/edit.ex index 2326f20bc2..cabfcf2c9b 100644 --- a/lib/lightning_web/live/workflow_live/edit.ex +++ b/lib/lightning_web/live/workflow_live/edit.ex @@ -97,8 +97,7 @@ defmodule LightningWeb.WorkflowLive.Edit do <:label>{@page_title} diff --git a/test/lightning_web/components/layout_components_test.exs b/test/lightning_web/components/layout_components_test.exs index b48db2d0c1..d738b090f6 100644 --- a/test/lightning_web/components/layout_components_test.exs +++ b/test/lightning_web/components/layout_components_test.exs @@ -62,21 +62,16 @@ defmodule LightningWeb.LayoutComponentsTest do end describe "breadcrumb_project_picker/1" do - test "renders ReactComponent mount point for a root project" do + test "renders the ReactComponent mount point for a root project" do project = %Lightning.Projects.Project{ id: Ecto.UUID.generate(), name: "my-project", - parent_id: nil, - parent: %Ecto.Association.NotLoaded{ - __field__: :parent, - __owner__: Lightning.Projects.Project, - __cardinality__: :one - } + parent_id: nil } html = (&LayoutComponents.breadcrumb_project_picker/1) - |> render_component(%{project: project}) + |> render_component(%{project: project, label: "my-project"}) assert html =~ "breadcrumb-project-picker-trigger" assert html =~ ~s(data-react-name="PickerButton") @@ -84,7 +79,7 @@ defmodule LightningWeb.LayoutComponentsTest do assert html =~ ~s(data-is-sandbox="false") end - test "renders ReactComponent mount point with sandbox data" do + test "renders the ReactComponent mount point for a sandbox" do parent = %Lightning.Projects.Project{ id: Ecto.UUID.generate(), name: "parent-project" @@ -100,45 +95,17 @@ defmodule LightningWeb.LayoutComponentsTest do html = (&LayoutComponents.breadcrumb_project_picker/1) - |> render_component(%{project: project}) + |> render_component(%{ + project: project, + label: "parent-project/my-sandbox" + }) assert html =~ "breadcrumb-project-picker-trigger" assert html =~ ~s(data-react-name="PickerButton") - assert html =~ ~s(data-label="my-sandbox") + assert html =~ ~s(data-label="parent-project/my-sandbox") assert html =~ ~s(data-is-sandbox="true") assert html =~ ~s(data-color="#E33D63") end - - test "uses the access_root attr to truncate the displayed ancestor chain" do - root = insert(:project, name: "acme-workspace") - sandbox = insert(:project, name: "acme-staging", parent: root) - - html = - (&LayoutComponents.breadcrumb_project_picker/1) - |> render_component(%{project: sandbox, access_root: sandbox}) - - assert html =~ ~s(data-label="acme-staging") - refute html =~ "acme-workspace/acme-staging" - end - - test "derives access_root from current_user when access_root is not passed" do - user = insert(:user) - root = insert(:project, name: "acme-workspace") - - sandbox = - insert(:project, - name: "acme-staging", - parent: root, - project_users: [%{user: user, role: :admin}] - ) - - html = - (&LayoutComponents.breadcrumb_project_picker/1) - |> render_component(%{project: sandbox, current_user: user}) - - assert html =~ ~s(data-label="acme-staging") - refute html =~ "acme-workspace/acme-staging" - end end describe "global_project_picker/1" do