diff --git a/js/src/graphql/event.ts b/js/src/graphql/event.ts
index d6e98cff7..791339dc6 100644
--- a/js/src/graphql/event.ts
+++ b/js/src/graphql/event.ts
@@ -95,6 +95,10 @@ export const FETCH_EVENT = gql`
participants {
${participantQuery}
},
+ participantStats {
+ approved,
+ unapproved
+ },
tags {
${tagsQuery}
},
diff --git a/js/src/types/event.model.ts b/js/src/types/event.model.ts
index f83e91e94..b6a4d53c6 100644
--- a/js/src/types/event.model.ts
+++ b/js/src/types/event.model.ts
@@ -92,6 +92,10 @@ export interface IEvent {
organizerActor?: IActor;
attributedTo: IActor;
+ participantStats: {
+ approved: number;
+ unapproved: number;
+ };
participants: IParticipant[];
relatedEvents: IEvent[];
@@ -154,6 +158,7 @@ export class EventModel implements IEvent {
publishAt = new Date();
+ participantStats = { approved: 0, unapproved: 0};
participants: IParticipant[] = [];
relatedEvents: IEvent[] = [];
diff --git a/js/src/views/Event/Event.vue b/js/src/views/Event/Event.vue
index 0faf56c42..82346453f 100644
--- a/js/src/views/Event/Event.vue
+++ b/js/src/views/Event/Event.vue
@@ -18,6 +18,25 @@
{{ event.title }}
+
+
+ One person is going
+
+
+
+
+ You and one other person are going to this event
+
+
+
+ You're the only one going to this event
+
@@ -406,6 +425,7 @@ export default class Event extends Vue {
event.participants = event.participants
.filter(p => p.actor.id !== data.leaveEvent.actor.id);
+ event.participantStats.approved = event.participantStats.approved - 1;
store.writeQuery({ query: FETCH_EVENT, data: { event } });
},
diff --git a/lib/mobilizon/events/events.ex b/lib/mobilizon/events/events.ex
index cc6d71702..33521d4cc 100644
--- a/lib/mobilizon/events/events.ex
+++ b/lib/mobilizon/events/events.ex
@@ -747,6 +747,28 @@ defmodule Mobilizon.Events do
|> paginate(page, limit)
end
+ def count_approved_participants(id) do
+ query =
+ from(
+ p in Participant,
+ where: p.role != ^:not_approved,
+ where: p.event_id == ^id
+ )
+
+ Repo.aggregate(query, :count, :id)
+ end
+
+ def count_unapproved_participants(id) do
+ query =
+ from(
+ p in Participant,
+ where: p.role == ^:not_approved,
+ where: p.event_id == ^id
+ )
+
+ Repo.aggregate(query, :count, :id)
+ end
+
@doc """
Returns the list of participations for an actor.
diff --git a/lib/mobilizon_web/resolvers/event.ex b/lib/mobilizon_web/resolvers/event.ex
index d5c4734fd..ed6a9aa45 100644
--- a/lib/mobilizon_web/resolvers/event.ex
+++ b/lib/mobilizon_web/resolvers/event.ex
@@ -6,7 +6,7 @@ defmodule MobilizonWeb.Resolvers.Event do
alias Mobilizon.Addresses
alias Mobilizon.Addresses.Address
alias Mobilizon.Events
- alias Mobilizon.Events.{Event, Participant}
+ alias Mobilizon.Events.{Event, Participant, EventOptions}
alias Mobilizon.Media.Picture
alias Mobilizon.Users.User
alias Mobilizon.Actors
@@ -51,6 +51,14 @@ defmodule MobilizonWeb.Resolvers.Event do
{:ok, Mobilizon.Events.list_participants_for_event(uuid, 1, 10)}
end
+ def stats_participants_for_event(%Event{id: id}, _args, _resolution) do
+ {:ok,
+ %{
+ approved: Mobilizon.Events.count_approved_participants(id),
+ unapproved: Mobilizon.Events.count_unapproved_participants(id)
+ }}
+ end
+
@doc """
List related events
"""
diff --git a/lib/mobilizon_web/schema/event.ex b/lib/mobilizon_web/schema/event.ex
index c2f2fbfe3..5190384d9 100644
--- a/lib/mobilizon_web/schema/event.ex
+++ b/lib/mobilizon_web/schema/event.ex
@@ -54,6 +54,8 @@ defmodule MobilizonWeb.Schema.EventType do
field(:category, :string, description: "The event's category")
+ field(:participant_stats, :participant_stats, resolve: &Event.stats_participants_for_event/3)
+
field(:participants, list_of(:participant),
resolve: &Event.list_participants_for_event/3,
description: "The event's participants"
@@ -92,6 +94,11 @@ defmodule MobilizonWeb.Schema.EventType do
value(:cancelled, description: "The event is cancelled")
end
+ object :participant_stats do
+ field(:approved, :integer, description: "The number of approved participants")
+ field(:unapproved, :integer, description: "The number of unapproved participants")
+ end
+
object :event_offer do
field(:price, :float, description: "The price amount for this offer")
field(:price_currency, :string, description: "The currency for this price offer")
diff --git a/schema.graphql b/schema.graphql
index df2395faf..6cc837e60 100644
--- a/schema.graphql
+++ b/schema.graphql
@@ -1,5 +1,5 @@
# source: http://localhost:4000/api
-# timestamp: Mon Sep 09 2019 20:33:17 GMT+0200 (GMT+02:00)
+# timestamp: Wed Sep 11 2019 11:53:12 GMT+0200 (GMT+02:00)
schema {
query: RootQueryType
@@ -280,6 +280,7 @@ type Event implements ActionLogObject {
"""The event's organizer (as a person)"""
organizerActor: Actor
+ participantStats: ParticipantStats
"""The event's participants"""
participants: [Participant]
@@ -648,6 +649,14 @@ type Participant {
role: Int
}
+type ParticipantStats {
+ """The number of approved participants"""
+ approved: Int
+
+ """The number of unapproved participants"""
+ unapproved: Int
+}
+
"""
Represents a person identity
diff --git a/test/mobilizon_web/resolvers/participant_resolver_test.exs b/test/mobilizon_web/resolvers/participant_resolver_test.exs
index dc2b287fb..046199338 100644
--- a/test/mobilizon_web/resolvers/participant_resolver_test.exs
+++ b/test/mobilizon_web/resolvers/participant_resolver_test.exs
@@ -12,7 +12,8 @@ defmodule MobilizonWeb.Resolvers.ParticipantResolverTest do
|> DateTime.truncate(:second),
uuid: "b5126423-f1af-43e4-a923-002a03003ba4",
url: "some url",
- category: "meeting"
+ category: "meeting",
+ options: %{}
}
setup %{conn: conn} do
@@ -387,5 +388,72 @@ defmodule MobilizonWeb.Resolvers.ParticipantResolverTest do
}
]
end
+
+ test "stats_participants_for_event/3 give the number of (un)approved participants", %{
+ conn: conn,
+ actor: actor
+ } do
+ event =
+ @event
+ |> Map.put(:organizer_actor_id, actor.id)
+
+ {:ok, event} = Events.create_event(event)
+
+ query = """
+ {
+ event(uuid: "#{event.uuid}") {
+ uuid,
+ participantStats {
+ approved,
+ unapproved
+ }
+ }
+ }
+ """
+
+ res =
+ conn
+ |> get("/api", AbsintheHelpers.query_skeleton(query, "event"))
+
+ assert json_response(res, 200)["data"]["event"]["uuid"] == to_string(event.uuid)
+ assert json_response(res, 200)["data"]["event"]["participantStats"]["approved"] == 1
+ assert json_response(res, 200)["data"]["event"]["participantStats"]["unapproved"] == 0
+
+ moderator = insert(:actor)
+
+ Events.create_participant(%{
+ role: :moderator,
+ event_id: event.id,
+ actor_id: moderator.id
+ })
+
+ unapproved = insert(:actor)
+
+ Events.create_participant(%{
+ role: :not_approved,
+ event_id: event.id,
+ actor_id: unapproved.id
+ })
+
+ query = """
+ {
+ event(uuid: "#{event.uuid}") {
+ uuid,
+ participantStats {
+ approved,
+ unapproved
+ }
+ }
+ }
+ """
+
+ res =
+ conn
+ |> get("/api", AbsintheHelpers.query_skeleton(query, "event"))
+
+ assert json_response(res, 200)["data"]["event"]["uuid"] == to_string(event.uuid)
+ assert json_response(res, 200)["data"]["event"]["participantStats"]["approved"] == 2
+ assert json_response(res, 200)["data"]["event"]["participantStats"]["unapproved"] == 1
+ end
end
end