Commit 0b3d6de0063bb7c35df5b39e6302532e98b20069

Thomas de Grivel 2022-01-27T13:00:32

[admin] repository index sorted by columns

diff --git a/lib/kmxgit/organisation_manager.ex b/lib/kmxgit/organisation_manager.ex
index 2086c49..bb86630 100644
--- a/lib/kmxgit/organisation_manager.ex
+++ b/lib/kmxgit/organisation_manager.ex
@@ -11,52 +11,59 @@ defmodule Kmxgit.OrganisationManager do
                  :slug]
 
   def list_organisations() do
+    update_disk_usage()
     Repo.all from org in Organisation,
       join: s in Slug,
       on: s.organisation_id == org.id,
       preload: ^@list_preload,
       order_by: s.slug
   end
-  def list_organisations(%{sort: "du", reverse: true}) do
+  def list_organisations(%{column: "du", reverse: true}) do
     update_disk_usage()
     Repo.all from org in Organisation,
       preload: ^@list_preload,
       order_by: [desc: :disk_usage]
   end
-  def list_organisations(%{sort: "du"}) do
+  def list_organisations(%{column: "du"}) do
     update_disk_usage()
     Repo.all from org in Organisation,
       preload: ^@list_preload,
       order_by: :disk_usage
   end
-  def list_organisations(%{sort: "id", reverse: true}) do
+  def list_organisations(%{column: "id", reverse: true}) do
+    update_disk_usage()
     Repo.all from org in Organisation,
       preload: ^@list_preload,
       order_by: [desc: :id]
   end
-  def list_organisations(%{sort: "id"}) do
+  def list_organisations(%{column: "id"}) do
+    update_disk_usage()
     Repo.all from org in Organisation,
       preload: ^@list_preload,
       order_by: :id
   end
-  def list_organisations(%{sort: "name", reverse: true}) do
+  def list_organisations(%{column: "name", reverse: true}) do
+    update_disk_usage()
     Repo.all from org in Organisation,
       preload: ^@list_preload,
       order_by: [desc: :name]
   end
-  def list_organisations(%{sort: "name"}) do
+  def list_organisations(%{column: "name"}) do
+    update_disk_usage()
     Repo.all from org in Organisation,
       preload: ^@list_preload,
       order_by: :name
   end
-  def list_organisations(%{sort: "slug", reverse: true}) do
+  def list_organisations(%{column: "slug", reverse: true}) do
+    update_disk_usage()
     Repo.all from org in Organisation,
       join: s in Slug,
       on: s.organisation_id == org.id,
       preload: ^@list_preload,
       order_by: [desc: s.slug]
   end
-  def list_organisations(%{sort: "slug"}) do
+  def list_organisations(%{column: "slug"}) do
+    update_disk_usage()
     Repo.all from org in Organisation,
       join: s in Slug,
       on: s.organisation_id == org.id,
diff --git a/lib/kmxgit/repository_manager.ex b/lib/kmxgit/repository_manager.ex
index 63bde13..c6bb64e 100644
--- a/lib/kmxgit/repository_manager.ex
+++ b/lib/kmxgit/repository_manager.ex
@@ -10,13 +10,110 @@ defmodule Kmxgit.RepositoryManager do
   alias Kmxgit.UserManager
   alias Kmxgit.UserManager.User
 
+  @list_preload [members: :slug,
+                 organisation: [:slug, users: :slug],
+                 user: :slug]
+
   def list_repositories do
     Repo.all(from r in Repository,
-      preload: [members: :slug,
-                organisation: [:slug, users: :slug],
-                user: :slug])
+      preload: ^@list_preload)
     |> Enum.sort_by(&Repository.full_slug/1)
   end
+  def list_repositories(%{column: "du", reverse: true}) do
+    update_disk_usage()
+    Repo.all from r in Repository,
+      preload: ^@list_preload,
+      order_by: [desc: :disk_usage]
+  end
+  def list_repositories(%{column: "du"}) do
+    update_disk_usage()
+    Repo.all from r in Repository,
+      preload: ^@list_preload,
+      order_by: :disk_usage
+  end
+  def list_repositories(%{column: "id", reverse: true}) do
+    update_disk_usage()
+    Repo.all from r in Repository,
+      preload: ^@list_preload,
+      order_by: [desc: :id]
+  end
+  def list_repositories(%{column: "id"}) do
+    update_disk_usage()
+    Repo.all from r in Repository,
+      preload: ^@list_preload,
+      order_by: :id
+  end
+  def list_repositories(%{column: "owner", reverse: true}) do
+    update_disk_usage()
+    Repo.all from r in Repository,
+      full_join: o in Organisation,
+      on: o.id == r.organisation_id,
+      full_join: os in Slug,
+      on: os.organisation_id == o.id,
+      full_join: u in User,
+      on: u.id == r.user_id,
+      full_join: us in Slug,
+      on: us.user_id == u.id,
+      where: not is_nil(r),
+      preload: ^@list_preload,
+      order_by: [desc: fragment("concat(lower(?), lower(?))", os.slug, us.slug)]
+  end
+  def list_repositories(%{column: "owner"}) do
+    update_disk_usage()
+    Repo.all from r in Repository,
+      full_join: o in Organisation,
+      on: o.id == r.organisation_id,
+      full_join: os in Slug,
+      on: os.organisation_id == o.id,
+      full_join: u in User,
+      on: u.id == r.user_id,
+      full_join: us in Slug,
+      on: us.user_id == u.id,
+      where: not is_nil(r),
+      preload: ^@list_preload,
+      order_by: fragment("concat(lower(?), lower(?))", os.slug, us.slug)
+  end
+  def list_repositories(%{column: "slug", reverse: true}) do
+    update_disk_usage()
+    Repo.all from r in Repository,
+      full_join: o in Organisation,
+      on: o.id == r.organisation_id,
+      full_join: os in Slug,
+      on: os.organisation_id == o.id,
+      full_join: u in User,
+      on: u.id == r.user_id,
+      full_join: us in Slug,
+      on: us.user_id == u.id,
+      where: not is_nil(r),
+      preload: ^@list_preload,
+      order_by: [desc: fragment("concat(lower(?), lower(?))", os.slug, us.slug), desc: :slug]
+  end
+  def list_repositories(%{column: "slug"}) do
+    update_disk_usage()
+    Repo.all from r in Repository,
+      full_join: o in Organisation,
+      on: o.id == r.organisation_id,
+      full_join: os in Slug,
+      on: os.organisation_id == o.id,
+      full_join: u in User,
+      on: u.id == r.user_id,
+      full_join: us in Slug,
+      on: us.user_id == u.id,
+      where: not is_nil(r),
+      preload: ^@list_preload,
+      order_by: [fragment("concat(lower(?), lower(?))", os.slug, us.slug), :slug]
+  end
+
+  def update_disk_usage() do
+    repos = Repo.all(from repo in Repository, preload: [organisation: :slug,
+                                                        user: :slug])
+    |> Enum.map(fn repo ->
+      repo
+      |> Ecto.Changeset.cast(%{}, [])
+      |> Ecto.Changeset.put_change(:disk_usage, Repository.disk_usage(repo))
+      |> Repo.update!()
+    end)
+  end
 
   def put_disk_usage(repo = %Repository{}) do
     %Repository{repo | disk_usage: Repository.disk_usage(repo)}
diff --git a/lib/kmxgit/repository_manager/repository.ex b/lib/kmxgit/repository_manager/repository.ex
index bd58f79..533e797 100644
--- a/lib/kmxgit/repository_manager/repository.ex
+++ b/lib/kmxgit/repository_manager/repository.ex
@@ -11,7 +11,7 @@ defmodule Kmxgit.RepositoryManager.Repository do
   schema "repositories" do
     field :deploy_keys, :string
     field :description, :string
-    field :disk_usage, :integer, virtual: true, default: 0
+    field :disk_usage, :integer, default: 0
     field :fork_to, :string, virtual: true
     belongs_to :forked_from, __MODULE__
     belongs_to :organisation, Organisation, on_replace: :nilify
diff --git a/lib/kmxgit_web/controllers/admin.ex b/lib/kmxgit_web/controllers/admin.ex
new file mode 100644
index 0000000..9423516
--- /dev/null
+++ b/lib/kmxgit_web/controllers/admin.ex
@@ -0,0 +1,14 @@
+defmodule KmxgitWeb.Admin do
+
+  def sort_param(param) do
+    if param do
+      case String.split(param, "-") do
+        [col, _] -> %{column: col, reverse: true}
+        [col] -> %{column: col, reverse: false}
+        _ -> %{column: "id", reverse: false}
+      end
+    else
+      %{column: "id", reverse: false}
+    end
+  end
+end
diff --git a/lib/kmxgit_web/controllers/admin/organisation_controller.ex b/lib/kmxgit_web/controllers/admin/organisation_controller.ex
index fe5baca..85f0300 100644
--- a/lib/kmxgit_web/controllers/admin/organisation_controller.ex
+++ b/lib/kmxgit_web/controllers/admin/organisation_controller.ex
@@ -7,21 +7,10 @@ defmodule KmxgitWeb.Admin.OrganisationController do
   alias KmxgitWeb.ErrorView
 
   def index(conn, params) do
-    sort = params["sort"]
-    {sort, rev} = if sort do
-      case String.split(sort, "-") do
-        [sort, _] -> {sort, true}
-        [sort] -> {sort, false}
-        _ -> {nil, false}
-      end
-    else
-      {nil, false}
-    end
-    sort = sort || "id"
-    orgs = OrganisationManager.list_organisations(%{sort: sort, reverse: rev})
+    sort = KmxgitWeb.Admin.sort_param(params["sort"])
+    orgs = OrganisationManager.list_organisations(sort)
     conn
     |> assign(:orgs, orgs)
-    |> assign(:rev, rev)
     |> assign(:sort, sort)
     |> render("index.html")
   end
diff --git a/lib/kmxgit_web/controllers/admin/repository_controller.ex b/lib/kmxgit_web/controllers/admin/repository_controller.ex
index aac1edf..90aedf5 100644
--- a/lib/kmxgit_web/controllers/admin/repository_controller.ex
+++ b/lib/kmxgit_web/controllers/admin/repository_controller.ex
@@ -8,11 +8,12 @@ defmodule KmxgitWeb.Admin.RepositoryController do
   alias Kmxgit.SlugManager
   alias KmxgitWeb.ErrorView
 
-  def index(conn, _params) do
-    repos = RepositoryManager.list_repositories
-    |> RepositoryManager.put_disk_usage()
+  def index(conn, params) do
+    sort = KmxgitWeb.Admin.sort_param(params["sort"])
+    repos = RepositoryManager.list_repositories(sort)
     conn
     |> assign(:repos, repos)
+    |> assign(:sort, sort)
     |> render("index.html")
   end
 
diff --git a/lib/kmxgit_web/templates/admin/organisation/index.html.heex b/lib/kmxgit_web/templates/admin/organisation/index.html.heex
index 7379ef3..941674a 100644
--- a/lib/kmxgit_web/templates/admin/organisation/index.html.heex
+++ b/lib/kmxgit_web/templates/admin/organisation/index.html.heex
@@ -10,10 +10,10 @@
   <table class="table admin-index">
     <thead>
       <tr>
-        <th><%= link gettext("Id"), to: Routes.admin_organisation_path(@conn, :index, sort: "id#{if @sort == "id" && !@rev, do: "-"}") %><%= if @sort == "id" do %><%= if @rev do %> <i class="fa fa-angle-down"></i><% else %> <i class="fa fa-angle-up"></i><% end %><% end %></th>
-        <th><%= link gettext("Name"), to: Routes.admin_organisation_path(@conn, :index, sort: "name#{if @sort == "name" && !@rev, do: "-"}") %><%= if @sort == "name" do %><%= if @rev do %> <i class="fa fa-angle-down"></i><% else %> <i class="fa fa-angle-up"></i><% end %><% end %></th>
-        <th><%= link gettext("Slug"), to: Routes.admin_organisation_path(@conn, :index, sort: "slug#{if @sort == "slug" && !@rev, do: "-"}") %><%= if @sort == "slug" do %><%= if @rev do %> <i class="fa fa-angle-down"></i><% else %> <i class="fa fa-angle-up"></i><% end %><% end %></th>
-        <th><%= link gettext("Disk usage"), to: Routes.admin_organisation_path(@conn, :index, sort: "du#{if @sort != "du" || (@sort == "du" && !@rev), do: "-"}") %><%= if @sort == "du" do %><%= if @rev do %> <i class="fa fa-angle-down"></i><% else %> <i class="fa fa-angle-up"></i><% end %><% end %></th>
+        <th><%= link gettext("Id"), to: Routes.admin_organisation_path(@conn, :index, sort: "id#{if @sort.column == "id" && !@sort.reverse, do: "-"}") %><%= if @sort.column == "id" do %><%= if @sort.reverse do %> <i class="fa fa-angle-down"></i><% else %> <i class="fa fa-angle-up"></i><% end %><% end %></th>
+        <th><%= link gettext("Name"), to: Routes.admin_organisation_path(@conn, :index, sort: "name#{if @sort.column == "name" && !@sort.reverse, do: "-"}") %><%= if @sort.column == "name" do %><%= if @sort.reverse do %> <i class="fa fa-angle-down"></i><% else %> <i class="fa fa-angle-up"></i><% end %><% end %></th>
+        <th><%= link gettext("Slug"), to: Routes.admin_organisation_path(@conn, :index, sort: "slug#{if @sort.column == "slug" && !@sort.reverse, do: "-"}") %><%= if @sort.column == "slug" do %><%= if @sort.reverse do %> <i class="fa fa-angle-down"></i><% else %> <i class="fa fa-angle-up"></i><% end %><% end %></th>
+        <th><%= link gettext("Disk usage"), to: Routes.admin_organisation_path(@conn, :index, sort: "du#{if @sort.column != "du" || (@sort.column == "du" && !@sort.reverse), do: "-"}") %><%= if @sort.column == "du" do %><%= if @sort.reverse do %> <i class="fa fa-angle-down"></i><% else %> <i class="fa fa-angle-up"></i><% end %><% end %></th>
         <th><%= gettext("Actions") %></th>
       </tr>
     </thead>
diff --git a/lib/kmxgit_web/templates/admin/repository/index.html.heex b/lib/kmxgit_web/templates/admin/repository/index.html.heex
index ae9231c..6492d81 100644
--- a/lib/kmxgit_web/templates/admin/repository/index.html.heex
+++ b/lib/kmxgit_web/templates/admin/repository/index.html.heex
@@ -3,11 +3,11 @@
 
   <table class="table admin-index">
     <tr>
-      <th><%= gettext "Id" %></th>
-      <th><%= gettext "Owner" %></th>
-      <th><%= gettext "Slug" %></th>
-      <th><%= gettext "Disk usage" %></th>
-      <th><%= gettext "Actions" %></th>
+      <th><%= link gettext("Id"), to: Routes.admin_repository_path(@conn, :index, sort: "id#{if @sort.column == "id" && !@sort.reverse, do: "-"}") %><%= if @sort.column == "id" do %><%= if @sort.reverse do %> <i class="fa fa-angle-down"></i><% else %> <i class="fa fa-angle-up"></i><% end %><% end %></th>
+      <th><%= link gettext("Owner"), to: Routes.admin_repository_path(@conn, :index, sort: "owner#{if @sort.column == "owner" && !@sort.reverse, do: "-"}") %><%= if @sort.column == "owner" do %><%= if @sort.reverse do %> <i class="fa fa-angle-down"></i><% else %> <i class="fa fa-angle-up"></i><% end %><% end %></th>
+      <th><%= link gettext("Slug"), to: Routes.admin_repository_path(@conn, :index, sort: "slug#{if @sort.column == "slug" && !@sort.reverse, do: "-"}") %><%= if @sort.column == "slug" do %><%= if @sort.reverse do %> <i class="fa fa-angle-down"></i><% else %> <i class="fa fa-angle-up"></i><% end %><% end %></th>
+      <th><%= link gettext("Disk usage"), to: Routes.admin_repository_path(@conn, :index, sort: "du#{if @sort.column == "du" && !@sort.reverse, do: "-"}") %><%= if @sort.column == "du" do %><%= if @sort.reverse do %> <i class="fa fa-angle-down"></i><% else %> <i class="fa fa-angle-up"></i><% end %><% end %></th>
+      <th><%= gettext("Actions") %></th>
     </tr>
     <%= Enum.map @repos, fn(repo) -> %>
       <tr>
diff --git a/priv/repo/migrations/20220127115236_add_disk_usage_to_repositories.exs b/priv/repo/migrations/20220127115236_add_disk_usage_to_repositories.exs
new file mode 100644
index 0000000..1e25992
--- /dev/null
+++ b/priv/repo/migrations/20220127115236_add_disk_usage_to_repositories.exs
@@ -0,0 +1,9 @@
+defmodule Kmxgit.Repo.Migrations.AddDiskUsageToRepositories do
+  use Ecto.Migration
+
+  def change do
+    alter table(:repositories) do
+      add :disk_usage, :integer, default: 0
+    end
+  end
+end