diff --git a/front/assets/js/memory_cookie.js b/front/assets/js/memory_cookie.js index 7f0a572de..26ea0a34e 100644 --- a/front/assets/js/memory_cookie.js +++ b/front/assets/js/memory_cookie.js @@ -31,7 +31,8 @@ export class MemoryCookie { rootSidebar: false, rootRequester: true, projectType: "", - projectRequester: false, + projectListing: "all_pipelines", + projectRequester: "false", logDark: false, logWrap: true, logLive: true, diff --git a/front/assets/js/project/components/choose_select.js b/front/assets/js/project/components/choose_select.js index b08aafba3..aabff8e6c 100644 --- a/front/assets/js/project/components/choose_select.js +++ b/front/assets/js/project/components/choose_select.js @@ -19,6 +19,11 @@ export class ChooseSelect { let value = e.target.value; let key = e.target.getAttribute("data-key") + if (key === "listing_requester") { + this.updateListingRequester(value) + return + } + MemoryCookie.set('project' + key.charAt(0).toUpperCase() + key.slice(1), value) var u = new Url; @@ -27,4 +32,30 @@ export class ChooseSelect { window.location.href = u.toString() }) } + + updateListingRequester(value) { + const selection = this.selectionFor(value) + + MemoryCookie.set('projectListing', selection.listing) + MemoryCookie.set('projectRequester', selection.requester) + + const url = new Url + url.query['listing'] = selection.listing + url.query['requester'] = selection.requester + delete url.query['page_token'] + delete url.query['direction'] + + window.location.href = url.toString() + } + + selectionFor(value) { + switch (value) { + case 'all_by_me': + return { listing: 'all_pipelines', requester: 'true' } + case 'latest_per_branch': + return { listing: 'latest', requester: 'false' } + default: + return { listing: 'all_pipelines', requester: 'false' } + } + } } diff --git a/front/assets/js/workflow_list.js b/front/assets/js/workflow_list.js index cc0ae5135..e420c170e 100644 --- a/front/assets/js/workflow_list.js +++ b/front/assets/js/workflow_list.js @@ -7,7 +7,7 @@ export var WorkflowList = { pagination: null, pollmanList: null, container: null, - queryParams: ['page_token', 'direction', 'date_from', 'date_to', 'author'], + queryParams: ['page_token', 'direction', 'date_from', 'date_to', 'author', 'listing', 'requester'], init: function() { if(this.initiated === true) { return; } diff --git a/front/lib/front/memory_cookie.ex b/front/lib/front/memory_cookie.ex index 5c377bc39..bf88448f6 100644 --- a/front/lib/front/memory_cookie.ex +++ b/front/lib/front/memory_cookie.ex @@ -18,6 +18,7 @@ defmodule Front.MemoryCookie do "rootSidebar" => false, "rootRequester" => true, "projectType" => "", + "projectListing" => "all_pipelines", "projectRequester" => "false", "logDark" => false, "logWrap" => true, diff --git a/front/lib/front/project_page/model.ex b/front/lib/front/project_page/model.ex index bad986dcb..a8bad0c3c 100644 --- a/front/lib/front/project_page/model.ex +++ b/front/lib/front/project_page/model.ex @@ -1,12 +1,14 @@ defmodule Front.ProjectPage.Model do use TypedStruct alias Front.{Async, Decorators, Models} + alias InternalApi.PlumberWF.ListKeysetRequest.Direction, as: KeysetDirection require Logger typedstruct do field(:project, Front.Model.Project.t()) field(:page_token, String.t()) field(:direction, String.t()) + field(:list_mode, String.t()) field(:user_page?, boolean()) field(:ref_types, String.t()) field(:workflows, [Front.Model.Workflow.t()], enforce: true) @@ -35,6 +37,7 @@ defmodule Front.ProjectPage.Model do field(:user_id, String.t()) field(:page_token, String.t(), default: "") field(:direction, String.t()) + field(:list_mode, String.t(), default: "latest") field(:user_page?, boolean()) field(:ref_types, [String.t()]) end @@ -51,7 +54,8 @@ defmodule Front.ProjectPage.Model do @spec get(LoadParams.t()) :: {:ok, __MODULE__.t()} | {:error, String.t()} def get(params, opts \\ []) do with true <- first_page?(params), - true <- everyones_page?(params) do + true <- everyones_page?(params), + true <- cacheable_mode?(params) do fetch_from_cache(params, opts[:force_cold_boot]) else false -> @@ -79,7 +83,7 @@ defmodule Front.ProjectPage.Model do end def cache_key(params) do - "#{cache_prefix()}/#{cache_version()}/project_id=#{params.project_id}/ref_types=#{params.ref_types}/" + "#{cache_prefix()}/#{cache_version()}/project_id=#{params.project_id}/ref_types=#{params.ref_types}/list_mode=#{params.list_mode}/" end @spec refresh(LoadParams.t()) :: {:ok, t(), atom()} | {:error, String.t()} @@ -167,6 +171,7 @@ defmodule Front.ProjectPage.Model do project: project, page_token: params.page_token, direction: params.direction, + list_mode: params.list_mode, user_page?: params.user_page?, ref_types: params.ref_types, workflows: workflows, @@ -186,8 +191,16 @@ defmodule Front.ProjectPage.Model do defp first_page?(params), do: params.page_token == "" defp everyones_page?(params), do: params.user_page? == false + defp cacheable_mode?(params), do: (params.list_mode || "latest") == "latest" defp list_workflows(params) do + case params.list_mode do + "all_pipelines" -> list_workflows_keyset(params) + _ -> list_workflows_latest(params) + end + end + + defp list_workflows_latest(params) do list_params = [ page_size: 10, page_token: params.page_token, @@ -196,12 +209,7 @@ defmodule Front.ProjectPage.Model do git_ref_types: params.ref_types ] - list_params = - if params.user_page? do - list_params |> Keyword.merge(requester_id: params.user_id) - else - list_params - end + list_params = maybe_put_requester(list_params, params.user_page?, params.user_id) workflow_api_metric_name = if params.user_page? do @@ -222,4 +230,47 @@ defmodule Front.ProjectPage.Model do {workflows, next_page_token, previous_page_token} end + + defp list_workflows_keyset(params) do + direction = keyset_direction(params.direction) + + list_params = + [ + page_size: 10, + page_token: params.page_token, + direction: direction, + project_id: params.project_id, + git_ref_types: params.ref_types + ] + |> maybe_put_requester(params.user_page?, params.user_id) + |> Enum.reject(fn {_, value} -> is_nil(value) or value == "" end) + + workflow_api_metric_name = + if params.user_page? do + "project_page_model_list_keyset_by_me" + else + "project_page_model_list_keyset" + end + + {wfs, next_page_token, previous_page_token} = + Watchman.benchmark(workflow_api_metric_name, fn -> + Models.Workflow.list_keyset(list_params) + end) + + workflows = + Watchman.benchmark("project_page_model_decorate_workflows", fn -> + Decorators.Workflow.decorate_many(wfs) + end) + + {workflows, next_page_token, previous_page_token} + end + + defp maybe_put_requester(list_params, true, requester_id), + do: Keyword.merge(list_params, requester_id: requester_id) + + defp maybe_put_requester(list_params, _requester?, _requester_id), do: list_params + + defp keyset_direction("next"), do: KeysetDirection.value(:NEXT) + defp keyset_direction("previous"), do: KeysetDirection.value(:PREVIOUS) + defp keyset_direction(_), do: nil end diff --git a/front/lib/front_web/controllers/project_controller.ex b/front/lib/front_web/controllers/project_controller.ex index 40a349a74..e19f398d9 100644 --- a/front/lib/front_web/controllers/project_controller.ex +++ b/front/lib/front_web/controllers/project_controller.ex @@ -107,6 +107,7 @@ defmodule FrontWeb.ProjectController do user_id: user_id, page_token: params["page_token"] || "", direction: params["direction"] || "", + list_mode: workflow_list_mode_setting(conn), user_page?: user_page?(conn), ref_types: ref_types(conn) ) @@ -819,6 +820,7 @@ defmodule FrontWeb.ProjectController do user_id: user_id, page_token: params["page_token"] || "", direction: params["direction"] || "", + list_mode: workflow_list_mode_setting(conn), user_page?: user_page?(conn), ref_types: ref_types(conn) ) @@ -841,6 +843,9 @@ defmodule FrontWeb.ProjectController do branches: model.branches, type: workflow_list_type_setting(conn), requester: model.user_page?, + listing: model.list_mode, + listing_requester: combined_listing_requester(model.list_mode, model.user_page?), + all_pipelines_enabled: show_all_pipelines?(conn), notice: conn |> get_flash(:notice), social_metatags: true, workflows: model.workflows @@ -887,6 +892,7 @@ defmodule FrontWeb.ProjectController do user_id: user_id, page_token: params["page_token"] || "", direction: params["direction"] || "", + list_mode: workflow_list_mode_setting(conn), user_page?: false, ref_types: ref_types(conn) ) @@ -897,8 +903,10 @@ defmodule FrontWeb.ProjectController do state: "poll", href: "/projects/#{project.id}/workflows", params: [ + requester: data.user_page?, page_token: params.page_token, - direction: params.direction + direction: params.direction, + listing: data.list_mode || workflow_list_mode_setting(conn) ] } @@ -915,6 +923,9 @@ defmodule FrontWeb.ProjectController do pollman: pollman, title: "#{project.name}・#{data.organization.name}", requester: data.user_page?, + listing: data.list_mode, + listing_requester: combined_listing_requester(data.list_mode, data.user_page?), + all_pipelines_enabled: show_all_pipelines?(conn), type: workflow_list_type_setting(conn), notice: conn |> get_flash(:notice), social_metatags: true @@ -938,7 +949,8 @@ defmodule FrontWeb.ProjectController do requester: user_page?(conn), page_token: conn.params["page_token"] || "", direction: conn.params["direction"] || "", - type: conn.params["type"] || memory["projectType"] + type: conn.params["type"] || memory["projectType"], + listing: model.list_mode || workflow_list_mode_setting(conn) ] } end @@ -949,13 +961,43 @@ defmodule FrontWeb.ProjectController do conn.params["type"] || memory["projectType"] end + defp workflow_list_mode_setting(conn) do + memory = conn.req_cookies["memory"] |> MemoryCookie.values() + + requested_mode = conn.params["listing"] || memory["projectListing"] || "all_pipelines" + + if show_all_pipelines?(conn) do + normalize_list_mode(requested_mode) + else + "latest" + end + end + + defp normalize_list_mode("all_pipelines"), do: "all_pipelines" + defp normalize_list_mode(_), do: "latest" + + defp show_all_pipelines?(conn) do + FeatureProvider.feature_enabled?(:project_page_all_pipelines, + param: conn.assigns.organization_id + ) + end + defp filters(conn) do + list_mode = workflow_list_mode_setting(conn) + requester? = user_page?(conn) + %{ type: workflow_list_type_setting(conn), - requester: user_page?(conn) + requester: requester?, + listing: list_mode, + listing_requester: combined_listing_requester(list_mode, requester?) } end + defp combined_listing_requester(_, true), do: "all_by_me" + defp combined_listing_requester("all_pipelines", _), do: "all_pipelines" + defp combined_listing_requester(_, _), do: "latest_per_branch" + defp ref_types(conn) do conn |> workflow_list_type_setting() |> String.split(",", trim: true) end diff --git a/front/lib/front_web/templates/project/_tabs.html.eex b/front/lib/front_web/templates/project/_tabs.html.eex index 45ccb5db0..d1ecfbca2 100644 --- a/front/lib/front_web/templates/project/_tabs.html.eex +++ b/front/lib/front_web/templates/project/_tabs.html.eex @@ -1,4 +1,15 @@