diff --git a/lib/atomic/organizations.ex b/lib/atomic/organizations.ex index 1c6396bd5..96e5e3b0d 100644 --- a/lib/atomic/organizations.ex +++ b/lib/atomic/organizations.ex @@ -136,17 +136,25 @@ defmodule Atomic.Organizations do end @doc """ - Returns the list of organizations where an user is an admin or owner. + Returns the list of organizations which are connected with the user. + By default, it returns the organizations where the user is an admin or owner. ## Examples - iex> list_user_organizations(user_id) + iex> list_user_organizations(123) [%Organization{}, ...] + + iex> list_user_organizations(456) + [] + + iex> list_user_organizations(123, [:follower]) + [%Organization{}, ...] + """ - def list_user_organizations(user_id, opts \\ []) do + def list_user_organizations(user_id, roles \\ [:admin, :owner], opts \\ []) do Organization |> join(:inner, [o], m in Membership, on: m.organization_id == o.id) - |> where([o, m], m.user_id == ^user_id and m.role in [:admin, :owner]) + |> where([o, m], m.user_id == ^user_id and m.role in ^roles) |> apply_filters(opts) |> Repo.all() end @@ -256,30 +264,19 @@ defmodule Atomic.Organizations do end @doc """ - Returns the list of memberships. + Returns the list of members in an organization. + A member is someone who is connected to the organization with a role other than `:follower`. ## Examples - iex> list_memberships(%{"organization_id" => id}) - [%Organization{}, ...] - - iex> list_memberships(%{"user_id" => id}) + iex> list_memberships(123) [%Organization{}, ...] """ - def list_memberships(params, preloads \\ []) - - def list_memberships(%{"organization_id" => organization_id}, preloads) do + def list_memberships(organization_id, opts \\ []) do Membership - |> where([a], a.organization_id == ^organization_id and a.role != :follower) - |> Repo.all() - |> Repo.preload(preloads) - end - - def list_memberships(%{"user_id" => user_id}, preloads) do - Membership - |> where([a], a.user_id == ^user_id) - |> Repo.preload(preloads) + |> where([m], m.organization_id == ^organization_id and m.role != :follower) + |> apply_filters(opts) |> Repo.all() end diff --git a/lib/atomic_web/live/home_live/index.ex b/lib/atomic_web/live/home_live/index.ex index f4ebf82a5..a30dab65a 100644 --- a/lib/atomic_web/live/home_live/index.ex +++ b/lib/atomic_web/live/home_live/index.ex @@ -75,8 +75,8 @@ defmodule AtomicWeb.HomeLive.Index do current_user = socket.assigns.current_user %{entries: entries, metadata: metadata} = - Organizations.list_memberships(%{"user_id" => current_user.id}) - |> Enum.map(& &1.organization_id) + Organizations.list_user_organizations(current_user.id, [:follower]) + |> Enum.map(& &1.id) |> Feed.list_posts_following_paginated([]) {:noreply, diff --git a/lib/atomic_web/live/organization_live/components/organization_about.ex b/lib/atomic_web/live/organization_live/components/about.ex similarity index 96% rename from lib/atomic_web/live/organization_live/components/organization_about.ex rename to lib/atomic_web/live/organization_live/components/about.ex index bd186fb85..27400dcba 100644 --- a/lib/atomic_web/live/organization_live/components/organization_about.ex +++ b/lib/atomic_web/live/organization_live/components/about.ex @@ -1,4 +1,4 @@ -defmodule AtomicWeb.OrganizationLive.Components.OrganizationAbout do +defmodule AtomicWeb.OrganizationLive.Components.About do @moduledoc false use AtomicWeb, :component @@ -7,7 +7,7 @@ defmodule AtomicWeb.OrganizationLive.Components.OrganizationAbout do attr :organization, Organization, required: true, doc: "the organization which about to display" - def organization_about(assigns) do + def about(assigns) do ~H"""

<%= gettext("Description") %>

diff --git a/lib/atomic_web/live/organization_live/components/organization_departments.ex b/lib/atomic_web/live/organization_live/components/departments_grid.ex similarity index 91% rename from lib/atomic_web/live/organization_live/components/organization_departments.ex rename to lib/atomic_web/live/organization_live/components/departments_grid.ex index 9c03680df..967482f24 100644 --- a/lib/atomic_web/live/organization_live/components/organization_departments.ex +++ b/lib/atomic_web/live/organization_live/components/departments_grid.ex @@ -1,4 +1,4 @@ -defmodule AtomicWeb.OrganizationLive.Components.OrganizationDepartments do +defmodule AtomicWeb.OrganizationLive.Components.DepartmentsGrid do @moduledoc """ Internal organization-related component for displaying its departments. """ @@ -14,7 +14,7 @@ defmodule AtomicWeb.OrganizationLive.Components.OrganizationDepartments do required: true, doc: "the organization which departments to display" - def organization_departments(assigns) do + def departments_grid(assigns) do ~H"""
<%= for department <- list_departments(@organization) do %> diff --git a/lib/atomic_web/live/organization_live/components/membership_banner.ex b/lib/atomic_web/live/organization_live/components/membership_banner.ex new file mode 100644 index 000000000..4f15f97d6 --- /dev/null +++ b/lib/atomic_web/live/organization_live/components/membership_banner.ex @@ -0,0 +1,55 @@ +defmodule AtomicWeb.OrganizationLive.Components.MembershipBanner do + @moduledoc """ + Organization membership banner component. Displays information about the organization's membership benefits and price. + """ + use AtomicWeb, :component + + alias Atomic.Organizations.Organization + + attr :organization, Organization, + required: true, + doc: "the organization which membership banner to display" + + def membership_banner(assigns) do + ~H""" +
+
+

<%= gettext("Lifetime membership") %>

+
+

<%= gettext("What’s included") %>

+
+
+ +
    +
  • + <.icon name={:check} class="h-6 w-5 flex-none text-orange-600" /> +

    Access to our room facilities

    +
  • +
  • + <.icon name={:check} class="h-6 w-5 flex-none text-orange-600" /> +

    Free access to all activities

    +
  • +
  • + <.icon name={:check} class="h-6 w-5 flex-none text-orange-600" /> +

    Official member t-shirt

    +
  • +
+
+ +
+
+
+

<%= gettext("Pay once, be a member forever") %>

+

+ 10€ + EUR +

+ <.button icon={:banknotes} class="mt-10 text-sm"><%= gettext("Request your membership") %> +

<%= gettext("Payments should be made within our location.") %> <%= @organization.location %>

+
+
+
+
+ """ + end +end diff --git a/lib/atomic_web/live/organization_live/components/memberships_table.ex b/lib/atomic_web/live/organization_live/components/memberships_table.ex new file mode 100644 index 000000000..aab028646 --- /dev/null +++ b/lib/atomic_web/live/organization_live/components/memberships_table.ex @@ -0,0 +1,52 @@ +defmodule AtomicWeb.OrganizationLive.Components.MembershipsTable do + @moduledoc """ + Internal organization-related component for displaying its memberships in the form of a table. + """ + use AtomicWeb, :component + + import AtomicWeb.Components.Avatar + + attr :members, :list, required: true, doc: "the list of memberships to display" + + # TODO: Make use of table component + def memberships_table(assigns) do + ~H""" +
+
+
+ + + + + + + + + + + + + + + + +
<%= gettext("Name") %><%= gettext("Role") %><%= gettext("Joined At") %>
+
+ <.avatar name={member.user.name} size={:sm} color={:light_gray} class="ring-1 ring-white" /> +
+
<%= member.user.name %>
+
<%= member.user.email %>
+
+
+
<%= capitalize_first_letter(member.role) %><%= relative_datetime(member.inserted_at) %>
+
+
+
+ """ + end + + defp row_click(member) do + Routes.profile_show_path(AtomicWeb.Endpoint, :show, member.user) + |> JS.navigate() + end +end diff --git a/lib/atomic_web/live/organization_live/show.ex b/lib/atomic_web/live/organization_live/show.ex index 8897753b4..05334371f 100644 --- a/lib/atomic_web/live/organization_live/show.ex +++ b/lib/atomic_web/live/organization_live/show.ex @@ -4,7 +4,13 @@ defmodule AtomicWeb.OrganizationLive.Show do alias Atomic.{Accounts, Organizations} import AtomicWeb.Components.{Gradient, Tabs} - import AtomicWeb.OrganizationLive.Components.{OrganizationAbout, OrganizationDepartments} + + import AtomicWeb.OrganizationLive.Components.{ + About, + DepartmentsGrid, + MembershipsTable, + MembershipBanner + } @impl true def mount(_params, _session, socket) do @@ -14,6 +20,7 @@ defmodule AtomicWeb.OrganizationLive.Show do @impl true def handle_params(%{"id" => id} = params, _, socket) do organization = Organizations.get_organization!(id) + members = maybe_list_members(organization.id, params["tab"]) {:noreply, socket @@ -21,9 +28,15 @@ defmodule AtomicWeb.OrganizationLive.Show do |> assign(:current_page, :organization) |> assign(:current_tab, current_tab(socket, params)) |> assign(:organization, organization) + |> assign(:members, members) |> assign(:has_permissions?, has_permissions?(socket))} end + defp maybe_list_members(organization_id, "members"), + do: Organizations.list_memberships(organization_id, preloads: [:user]) + + defp maybe_list_members(_organization, _tab), do: nil + defp current_tab(_socket, params) when is_map_key(params, "tab"), do: params["tab"] defp current_tab(_socket, _params), do: "about" diff --git a/lib/atomic_web/live/organization_live/show.html.heex b/lib/atomic_web/live/organization_live/show.html.heex index b151c7828..039c6f3e6 100644 --- a/lib/atomic_web/live/organization_live/show.html.heex +++ b/lib/atomic_web/live/organization_live/show.html.heex @@ -70,13 +70,24 @@ -
-
- <.organization_about organization={@organization} /> +
+
+ <.about organization={@organization} />
-
- <.organization_departments organization={@organization} /> +
+ <.departments_grid organization={@organization} /> +
+ +
+ <.membership_banner organization={@organization} /> +
+ +
+ +
+ + <.memberships_table members={@members} />
diff --git a/test/atomic/organizations_test.exs b/test/atomic/organizations_test.exs index a116ba5a0..b42d25f88 100644 --- a/test/atomic/organizations_test.exs +++ b/test/atomic/organizations_test.exs @@ -78,17 +78,7 @@ defmodule Atomic.OrganizationsTest do membership = insert(:membership, role: :admin) memberships = - Organizations.list_memberships(%{"organization_id" => membership.organization_id}) - |> Enum.map(& &1.id) - - assert memberships == [membership.id] - end - - test "list_memberships/1 returns all memberships of user" do - membership = insert(:membership) - - memberships = - Organizations.list_memberships(%{"user_id" => membership.user_id}) + Organizations.list_memberships(membership.organization_id) |> Enum.map(& &1.id) assert memberships == [membership.id]