From b61d12b5fdc2cd9ea5856be01b3e40970a6c9d53 Mon Sep 17 00:00:00 2001
From: Thomas Citharel
Date: Thu, 18 Jun 2020 15:23:05 +0200
Subject: [PATCH] Participation panel revamp and fixes
Apollo is a pain in the ass with pagination & filters, so this removes
the tabs system and uses a to filter instead
Signed-off-by: Thomas Citharel
---
js/.env | 1 -
js/public/index.html | 2 -
js/src/common.scss | 3 +-
js/src/components/Comment/Comment.vue | 2 +-
js/src/components/Event/EventListCard.vue | 16 +-
.../components/Event/ParticipationTable.vue | 205 --------
js/src/graphql/actor.ts | 1 +
js/src/graphql/event.ts | 3 +-
js/src/router/user.ts | 3 +-
js/src/views/Event/Event.vue | 13 +-
js/src/views/Event/Participants.vue | 476 ++++++++++--------
lib/graphql/resolvers/event.ex | 16 +-
lib/mobilizon/events/events.ex | 4 +-
lib/web/views/error_view.ex | 6 +-
lib/web/views/page_view.ex | 36 +-
lib/web/views/utils.ex | 41 ++
.../20190929170817_rename_postgres_types.exs | 2 +-
.../activity_pub/transmogrifier_test.exs | 3 +-
18 files changed, 347 insertions(+), 486 deletions(-)
delete mode 100644 js/.env
delete mode 100644 js/src/components/Event/ParticipationTable.vue
create mode 100644 lib/web/views/utils.ex
diff --git a/js/.env b/js/.env
deleted file mode 100644
index 2b749cb2d..000000000
--- a/js/.env
+++ /dev/null
@@ -1 +0,0 @@
-VUE_APP_INJECT_COMMENT =
\ No newline at end of file
diff --git a/js/public/index.html b/js/public/index.html
index 7a8eae898..19244db53 100644
--- a/js/public/index.html
+++ b/js/public/index.html
@@ -6,8 +6,6 @@
-
-
diff --git a/js/src/common.scss b/js/src/common.scss
index 172e5d1cc..c1682e0b7 100644
--- a/js/src/common.scss
+++ b/js/src/common.scss
@@ -10,7 +10,8 @@ a {
&[href="#comments"],
&.router-link-active,
&.comment-link,
- &.pagination-link {
+ &.pagination-link,
+ &.datepicker-cell {
text-decoration: none;
}
}
diff --git a/js/src/components/Comment/Comment.vue b/js/src/components/Comment/Comment.vue
index 1b84aee3b..884b7ea35 100644
--- a/js/src/components/Comment/Comment.vue
+++ b/js/src/components/Comment/Comment.vue
@@ -100,7 +100,7 @@
{{ $t("Post a reply") }}
diff --git a/js/src/components/Event/EventListCard.vue b/js/src/components/Event/EventListCard.vue
index 541b8abf6..df9558abe 100644
--- a/js/src/components/Event/EventListCard.vue
+++ b/js/src/components/Event/EventListCard.vue
@@ -60,10 +60,17 @@
>
{{
- $t("{approved} / {total} seats", {
- approved: participation.event.participantStats.participant,
- total: participation.event.options.maximumAttendeeCapacity,
- })
+ $tc(
+ "{available}/{capacity} available places",
+ participation.event.options.maximumAttendeeCapacity -
+ (participation.event.participantStats.going - 1),
+ {
+ available:
+ participation.event.options.maximumAttendeeCapacity -
+ (participation.event.participantStats.going - 1),
+ capacity: participation.event.options.maximumAttendeeCapacity,
+ }
+ )
}}
@@ -79,6 +86,7 @@
@click="
gotToWithCheck(participation, {
name: RouteName.PARTICIPATIONS,
+ query: { role: ParticipantRole.NOT_APPROVED },
params: { eventId: participation.event.uuid },
})
"
diff --git a/js/src/components/Event/ParticipationTable.vue b/js/src/components/Event/ParticipationTable.vue
deleted file mode 100644
index 38622ef3b..000000000
--- a/js/src/components/Event/ParticipationTable.vue
+++ /dev/null
@@ -1,205 +0,0 @@
-
- $emit('page-change', page)"
- @sort="(field, order) => $emit('sort', field, order)"
- >
-
-
- {{ props.row.insertedAt | formatDateString }} {{
- props.row.insertedAt | formatTimeString
- }}
-
-
-
- {{ $t("Organizer") }}
-
-
- {{ $t("Participant") }}
-
-
-
-
-
-
-
-
-
-
-
-
- {{ props.row.actor.name }}
- @{{ props.row.actor.preferredUsername }}
-
-
- {{ $t("Anonymous participant") }}
-
-
-
-
-
-
-
- {{ props.row.metadata.message | ellipsize }}
-
-
- {{ $t("No message") }}
-
-
-
-
-
-
-
-
-
- {{
- $tc(
- "No participant to approve|Approve participant|Approve {number} participants",
- checkedRows.length,
- { number: checkedRows.length }
- )
- }}
-
-
- {{
- $tc(
- "No participant to reject|Reject participant|Reject {number} participants",
- checkedRows.length,
- { number: checkedRows.length }
- )
- }}
-
-
-
-
-
-
-
diff --git a/js/src/graphql/actor.ts b/js/src/graphql/actor.ts
index fe00d8345..981d2a87d 100644
--- a/js/src/graphql/actor.ts
+++ b/js/src/graphql/actor.ts
@@ -212,6 +212,7 @@ export const LOGGED_USER_PARTICIPATIONS = gql`
}
}
participantStats {
+ going
notApproved
participant
}
diff --git a/js/src/graphql/event.ts b/js/src/graphql/event.ts
index bc97e7985..41e8274be 100644
--- a/js/src/graphql/event.ts
+++ b/js/src/graphql/event.ts
@@ -1,5 +1,4 @@
import gql from "graphql-tag";
-import { COMMENT_FIELDS_FRAGMENT } from "@/graphql/comment";
const participantQuery = `
role,
@@ -466,6 +465,8 @@ export const PARTICIPANTS = gql`
query($uuid: UUID!, $page: Int, $limit: Int, $roles: String, $actorId: ID!) {
event(uuid: $uuid) {
id,
+ uuid,
+ title,
participants(page: $page, limit: $limit, roles: $roles, actorId: $actorId) {
${participantsQuery}
},
diff --git a/js/src/router/user.ts b/js/src/router/user.ts
index 92126205d..e5f5e98e0 100644
--- a/js/src/router/user.ts
+++ b/js/src/router/user.ts
@@ -7,6 +7,7 @@ export enum UserRouteName {
RESEND_CONFIRMATION = "ResendConfirmation",
SEND_PASSWORD_RESET = "SendPasswordReset",
PASSWORD_RESET = "PasswordReset",
+ EMAIL_VALIDATE = "EMAIL_VALIDATE",
VALIDATE = "Validate",
LOGIN = "Login",
}
@@ -54,7 +55,7 @@ export const userRoutes: RouteConfig[] = [
},
{
path: "/validate/email/:token",
- name: UserRouteName.VALIDATE,
+ name: UserRouteName.EMAIL_VALIDATE,
component: () => import("@/views/User/EmailValidate.vue"),
props: true,
meta: { requiresAuth: false },
diff --git a/js/src/views/Event/Event.vue b/js/src/views/Event/Event.vue
index 37f97ddc6..e0e9c9dfe 100644
--- a/js/src/views/Event/Event.vue
+++ b/js/src/views/Event/Event.vue
@@ -168,14 +168,17 @@
v-if="actorIsOrganizer && event.draft === false"
:to="{ name: RouteName.PARTICIPATIONS, params: { eventId: event.uuid } }"
>
+
{{
$tc(
"{available}/{capacity} available places",
- event.options.maximumAttendeeCapacity - event.participantStats.going,
+ event.options.maximumAttendeeCapacity -
+ (event.participantStats.going - 1),
{
available:
- event.options.maximumAttendeeCapacity - event.participantStats.going,
+ event.options.maximumAttendeeCapacity -
+ (event.participantStats.going - 1),
capacity: event.options.maximumAttendeeCapacity,
}
)
@@ -183,8 +186,8 @@
{{
- $tc("No one is going to this event", event.participantStats.going, {
- going: event.participantStats.going,
+ $tc("No one is going to this event", event.participantStats.going - 1, {
+ going: event.participantStats.going - 1,
})
}}
@@ -226,7 +229,7 @@
- Actions
+ {{ $t("Actions") }}
-
-
-
-
- {{ $t("Participants") }} {{ participantStats.going }}
-
+
+
+
+
+ {{ $t("My events") }}
+
+
+ {{ event.title }}
+
+
+ {{ $t("Participants") }}
+
+
+
+ {{ $t("Participants") }}
+
+
+
+ {{ $t("Everything") }}
+
+
+ {{ $t("Organizer") }}
+
+
+ {{ $t("Participant") }}
+
+
+ {{ $t("Not approved") }}
+
+
+ {{ $t("Rejected") }}
+
+
+
+ (page = newPage)"
+ @sort="(field, order) => $emit('sort', field, order)"
+ >
+
+
+
+
+
+
+
+
+
+
+
+ {{ props.row.actor.name }}
+ @{{ props.row.actor.preferredUsername }}
+
+
+ {{ $t("Anonymous participant") }}
+
+
+
+
+
+
+
+ {{ $t("Organizer") }}
+
+
+ {{ $t("Participant") }}
+
+
+ {{ $t("Not approved") }}
+
+
+ {{ $t("Rejected") }}
+
+
+
+
+ {{ props.row.metadata.message | ellipsize }}
+
+
+ {{ $t("No message") }}
+
+
+
+
+ {{ props.row.insertedAt | formatDateString }} {{
+ props.row.insertedAt | formatTimeString
+ }}
+
+
-
-
- {{ $t("Participants") }}
- (participantPage = page)"
- />
+
+
+
+
+
+
+
{{ $t("No participant matches the filters") }}
+
-
-
-
-
- {{ $t("Requests") }} {{ participantStats.notApproved }}
-
+
+
+
+ {{
+ $tc(
+ "No participant to approve|Approve participant|Approve {number} participants",
+ checkedRows.length,
+ { number: checkedRows.length }
+ )
+ }}
+
+
+ {{
+ $tc(
+ "No participant to reject|Reject participant|Reject {number} participants",
+ checkedRows.length,
+ { number: checkedRows.length }
+ )
+ }}
+
+
-
-
- {{ $t("Waiting list") }}
- (queuePage = page)"
- />
-
-
-
-
-
-
- {{ $t("Rejected") }} {{ participantStats.rejected }}
-
-
-
-
- {{ $t("Rejected participations") }}
- (rejectedPage = page)"
- />
-
-
-
-
+
+
-
diff --git a/lib/graphql/resolvers/event.ex b/lib/graphql/resolvers/event.ex
index 824c5e869..808de4fd3 100644
--- a/lib/graphql/resolvers/event.ex
+++ b/lib/graphql/resolvers/event.ex
@@ -92,7 +92,8 @@ defmodule Mobilizon.GraphQL.Resolvers.Event do
|> Enum.map(&String.to_existing_atom/1)
end
- {:ok, Events.list_participants_for_event(event_id, roles, page, limit)}
+ participants = Events.list_participants_for_event(event_id, roles, page, limit)
+ {:ok, participants}
else
{:is_owned, nil} ->
{:error, "Moderator Actor ID is not owned by authenticated user"}
@@ -115,17 +116,12 @@ defmodule Mobilizon.GraphQL.Resolvers.Event do
_args,
%{context: %{current_user: %User{id: user_id} = _user}} = _resolution
) do
- if Events.is_user_moderator_for_event?(user_id, event_id) do
- stats =
- Map.put(
- stats,
- :going,
- stats.participant + stats.moderator + stats.administrator + stats.creator
- )
+ going = stats.participant + stats.moderator + stats.administrator + stats.creator
- {:ok, stats}
+ if Events.is_user_moderator_for_event?(user_id, event_id) do
+ {:ok, Map.put(stats, :going, going)}
else
- {:ok, %EventParticipantStats{}}
+ {:ok, %{going: going}}
end
end
diff --git a/lib/mobilizon/events/events.ex b/lib/mobilizon/events/events.ex
index 4a942b78b..f9f01e6e5 100644
--- a/lib/mobilizon/events/events.ex
+++ b/lib/mobilizon/events/events.ex
@@ -752,7 +752,6 @@ defmodule Mobilizon.Events do
end
@moderator_roles [:moderator, :administrator, :creator]
- @default_participant_roles [:participant] ++ @moderator_roles
@doc """
Returns the list of participants for an event.
@@ -762,13 +761,14 @@ defmodule Mobilizon.Events do
Page.t()
def list_participants_for_event(
id,
- roles \\ @default_participant_roles,
+ roles \\ [],
page \\ nil,
limit \\ nil
) do
id
|> list_participants_for_event_query()
|> filter_role(roles)
+ |> order_by(asc: :role)
|> Page.build_page(page, limit)
end
diff --git a/lib/web/views/error_view.ex b/lib/web/views/error_view.ex
index d52d16fe3..398c8b954 100644
--- a/lib/web/views/error_view.ex
+++ b/lib/web/views/error_view.ex
@@ -4,11 +4,11 @@ defmodule Mobilizon.Web.ErrorView do
"""
use Mobilizon.Web, :view
alias Mobilizon.Service.Metadata.Instance
- alias Mobilizon.Web.PageView
+ import Mobilizon.Web.Views.Utils
- def render("404.html", _assigns) do
+ def render("404.html", %{conn: conn}) do
tags = Instance.build_tags()
- PageView.inject_tags(tags)
+ inject_tags(tags, get_locale(conn))
end
def render("404.json", _assigns) do
diff --git a/lib/web/views/page_view.ex b/lib/web/views/page_view.ex
index 7bbd75f45..3615ddc15 100644
--- a/lib/web/views/page_view.ex
+++ b/lib/web/views/page_view.ex
@@ -13,10 +13,10 @@ defmodule Mobilizon.Web.PageView do
alias Mobilizon.Service.Metadata
alias Mobilizon.Service.Metadata.Instance
- alias Mobilizon.Service.Metadata.Utils, as: MetadataUtils
alias Mobilizon.Federation.ActivityPub.Utils
alias Mobilizon.Federation.ActivityStream.Convertible
+ import Mobilizon.Web.Views.Utils
def render("actor.activity-json", %{conn: %{assigns: %{object: %Actor{} = actor}}}) do
actor
@@ -59,38 +59,4 @@ defmodule Mobilizon.Web.PageView do
tags = Instance.build_tags()
inject_tags(tags, get_locale(conn))
end
-
- @spec inject_tags(List.t(), String.t()) :: {:safe, String.t()}
- def inject_tags(tags, locale \\ "en") do
- with {:ok, index_content} <- File.read(index_file_path()) do
- do_replacements(index_content, MetadataUtils.stringify_tags(tags), locale)
- end
- end
-
- @spec index_file_path :: String.t()
- defp index_file_path do
- Path.join(Application.app_dir(:mobilizon, "priv/static"), "index.html")
- end
-
- @spec replace_meta(String.t(), String.t()) :: String.t()
- # TODO: Find why it's different in dev/prod and during tests
- defp replace_meta(index_content, tags) do
- index_content
- |> String.replace(" ", tags)
- |> String.replace(" ", tags)
- end
-
- @spec do_replacements(String.t(), String.t(), String.t()) :: {:safe, String.t()}
- defp do_replacements(index_content, tags, locale) do
- index_content
- |> replace_meta(tags)
- |> String.replace("", "")
- |> String.replace("", "")
- |> (&{:safe, &1}).()
- end
-
- @spec get_locale(Conn.t()) :: String.t()
- defp get_locale(%{private: %{cldr_locale: nil}}), do: "en"
- defp get_locale(%{private: %{cldr_locale: %{requested_locale_name: locale}}}), do: locale
- defp get_locale(_), do: "en"
end
diff --git a/lib/web/views/utils.ex b/lib/web/views/utils.ex
new file mode 100644
index 000000000..234e222cf
--- /dev/null
+++ b/lib/web/views/utils.ex
@@ -0,0 +1,41 @@
+defmodule Mobilizon.Web.Views.Utils do
+ @moduledoc """
+ Utils for views
+ """
+
+ alias Mobilizon.Service.Metadata.Utils, as: MetadataUtils
+
+ @spec inject_tags(List.t(), String.t()) :: {:safe, String.t()}
+ def inject_tags(tags, locale \\ "en") do
+ with {:ok, index_content} <- File.read(index_file_path()) do
+ do_replacements(index_content, MetadataUtils.stringify_tags(tags), locale)
+ end
+ end
+
+ @spec index_file_path :: String.t()
+ defp index_file_path do
+ Path.join(Application.app_dir(:mobilizon, "priv/static"), "index.html")
+ end
+
+ @spec replace_meta(String.t(), String.t()) :: String.t()
+ # TODO: Find why it's different in dev/prod and during tests
+ defp replace_meta(index_content, tags) do
+ index_content
+ |> String.replace(" ", tags)
+ |> String.replace(" ", tags)
+ end
+
+ @spec do_replacements(String.t(), String.t(), String.t()) :: {:safe, String.t()}
+ defp do_replacements(index_content, tags, locale) do
+ index_content
+ |> replace_meta(tags)
+ |> String.replace("", "")
+ |> String.replace("", "")
+ |> (&{:safe, &1}).()
+ end
+
+ @spec get_locale(Conn.t()) :: String.t()
+ def get_locale(%{private: %{cldr_locale: nil}}), do: "en"
+ def get_locale(%{private: %{cldr_locale: %{requested_locale_name: locale}}}), do: locale
+ def get_locale(_), do: "en"
+end
diff --git a/priv/repo/migrations/20190929170817_rename_postgres_types.exs b/priv/repo/migrations/20190929170817_rename_postgres_types.exs
index cb129d5b5..a46d0d28b 100644
--- a/priv/repo/migrations/20190929170817_rename_postgres_types.exs
+++ b/priv/repo/migrations/20190929170817_rename_postgres_types.exs
@@ -2,7 +2,7 @@ defmodule Mobilizon.Storage.Repo.Migrations.RenamePostgresTypes do
use Ecto.Migration
alias Mobilizon.Actors.{ActorVisibility, MemberRole}
- alias alias Mobilizon.Conversations.CommentVisibility
+ alias Mobilizon.Conversations.CommentVisibility
alias Mobilizon.Events.{
JoinOptions,
diff --git a/test/federation/activity_pub/transmogrifier_test.exs b/test/federation/activity_pub/transmogrifier_test.exs
index 56ed28449..1960c46b3 100644
--- a/test/federation/activity_pub/transmogrifier_test.exs
+++ b/test/federation/activity_pub/transmogrifier_test.exs
@@ -1365,8 +1365,7 @@ defmodule Mobilizon.Federation.ActivityPub.TransmogrifierTest do
assert event.id
|> Events.list_participants_for_event()
|> Map.get(:elements)
- |> Enum.map(& &1.id) ==
- []
+ |> Enum.map(& &1.role) == [:rejected]
end
end