From 55c54ab591c5a896ca9013d17562531170f1131b Mon Sep 17 00:00:00 2001
From: Nelson Kopliku <nelson.kopliku@suse.com>
Date: Thu, 8 Aug 2024 15:34:38 +0200
Subject: [PATCH] Expose info about existence of prev/next page

---
 .../openapi/v1/schema/activity_log.ex         | 54 +++++++++++++++++--
 lib/trento_web/views/v1/activity_log_view.ex  |  6 ++-
 test/trento/activity_log_test.exs             | 31 +++++++++++
 3 files changed, 87 insertions(+), 4 deletions(-)

diff --git a/lib/trento_web/openapi/v1/schema/activity_log.ex b/lib/trento_web/openapi/v1/schema/activity_log.ex
index ca9a087556..58b52e6b26 100644
--- a/lib/trento_web/openapi/v1/schema/activity_log.ex
+++ b/lib/trento_web/openapi/v1/schema/activity_log.ex
@@ -39,6 +39,56 @@ defmodule TrentoWeb.OpenApi.V1.Schema.ActivityLog do
     })
   end
 
+  defmodule Pagination do
+    @moduledoc false
+    OpenApiSpex.schema(%{
+      additionalProperties: false,
+      type: :object,
+      properties: %{
+        start_cursor: %Schema{
+          type: :string,
+          description: "Cursor pointing to the start of the list.",
+          nullable: true
+        },
+        end_cursor: %Schema{
+          type: :string,
+          description: "Cursor pointing to the end of the list.",
+          nullable: true
+        },
+        has_next_page: %Schema{
+          type: :boolean,
+          description: "Flag indicating if there are more pages after the current one.",
+          nullable: false
+        },
+        has_previous_page: %Schema{
+          type: :boolean,
+          description: "Flag indicating if there are more pages before the current one.",
+          nullable: false
+        },
+        first: %Schema{
+          type: :integer,
+          description:
+            "Number of elements requested from the beginning of the list (forward navigation).",
+          nullable: true
+        },
+        last: %Schema{
+          type: :integer,
+          description:
+            "Number of elements requested from the end of the list (backward navigation).",
+          nullable: true
+        }
+      },
+      required: [
+        :start_cursor,
+        :end_cursor,
+        :has_next_page,
+        :has_previous_page,
+        :first,
+        :last
+      ]
+    })
+  end
+
   defmodule ActivityLog do
     @moduledoc false
 
@@ -49,9 +99,7 @@ defmodule TrentoWeb.OpenApi.V1.Schema.ActivityLog do
         type: :object,
         properties: %{
           data: ActivityLogEntries,
-          pagination: %Schema{
-            type: :object
-          }
+          pagination: Pagination
         },
         required: [:data, :pagination]
       },
diff --git a/lib/trento_web/views/v1/activity_log_view.ex b/lib/trento_web/views/v1/activity_log_view.ex
index 1e6f31548a..cb93537855 100644
--- a/lib/trento_web/views/v1/activity_log_view.ex
+++ b/lib/trento_web/views/v1/activity_log_view.ex
@@ -23,6 +23,8 @@ defmodule TrentoWeb.V1.ActivityLogView do
     %{
       end_cursor: end_cursor,
       start_cursor: start_cursor,
+      has_next_page?: has_next_page,
+      has_previous_page?: has_previous_page,
       flop: %{
         first: first,
         last: last
@@ -34,7 +36,9 @@ defmodule TrentoWeb.V1.ActivityLogView do
       start_cursor: start_cursor,
       end_cursor: end_cursor,
       first: first,
-      last: last
+      last: last,
+      has_next_page: has_next_page,
+      has_previous_page: has_previous_page
     }
   end
 end
diff --git a/test/trento/activity_log_test.exs b/test/trento/activity_log_test.exs
index 539bab1c9c..9a13100f56 100644
--- a/test/trento/activity_log_test.exs
+++ b/test/trento/activity_log_test.exs
@@ -295,5 +295,36 @@ defmodule Trento.ActivityLogTest do
       assert length(next_logs_alt) == length(next_logs)
       assert next_logs_alt == next_logs
     end
+
+    test "should expose information about the existence of previous or next page to navigate to" do
+      insert_list(100, :activity_log_entry)
+
+      assert {:ok, _,
+              %{has_previous_page?: false, has_next_page?: true, start_cursor: start_cursor}} =
+               ActivityLog.list_activity_log(%{first: 5})
+
+      assert {:ok, [],
+              %{
+                end_cursor: nil,
+                start_cursor: nil
+              }} =
+               ActivityLog.list_activity_log(%{last: 5, before: start_cursor})
+
+      assert {:ok, _, %{has_previous_page?: true, has_next_page?: true}} =
+               ActivityLog.list_activity_log(%{first: 5, after: start_cursor})
+
+      assert {:ok, _, %{has_previous_page?: true, has_next_page?: false, end_cursor: end_cursor}} =
+               ActivityLog.list_activity_log(%{last: 5})
+
+      assert {:ok, [],
+              %{
+                end_cursor: nil,
+                start_cursor: nil
+              }} =
+               ActivityLog.list_activity_log(%{first: 5, after: end_cursor})
+
+      assert {:ok, _, %{has_previous_page?: true, has_next_page?: true}} =
+               ActivityLog.list_activity_log(%{last: 5, before: end_cursor})
+    end
   end
 end