Expose more statistics
* differenciate local & all events/comments/groups * add instance follows/followings Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
parent
09a0cbf3f1
commit
02eac30c9b
@ -5,8 +5,13 @@ export const STATISTICS = gql`
|
||||
statistics {
|
||||
numberOfUsers
|
||||
numberOfEvents
|
||||
numberOfLocalEvents
|
||||
numberOfComments
|
||||
numberOfLocalComments
|
||||
numberOfGroups
|
||||
numberOfLocalGroups
|
||||
numberOfInstanceFollowings
|
||||
numberOfInstanceFollowers
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
@ -1,6 +1,11 @@
|
||||
export interface IStatistics {
|
||||
numberOfUsers: number;
|
||||
numberOfEvents: number;
|
||||
numberOfLocalEvents: number;
|
||||
numberOfComments: number;
|
||||
numberOfLocalComments: number;
|
||||
numberOfGroups: number;
|
||||
numberOfLocalGroups: number;
|
||||
numberOfInstanceFollowings: number;
|
||||
numberOfInstanceFollowers: number;
|
||||
}
|
||||
|
@ -14,13 +14,13 @@
|
||||
<strong slot="number">{{ statistics.numberOfUsers }}</strong>
|
||||
</i18n>
|
||||
<i18n tag="p" path="and {number} groups">
|
||||
<strong slot="number">{{ statistics.numberOfGroups }}</strong>
|
||||
<strong slot="number">{{ statistics.numberOfLocalGroups }}</strong>
|
||||
</i18n>
|
||||
<i18n tag="p" path="Who published {number} events">
|
||||
<strong slot="number">{{ statistics.numberOfEvents }}</strong>
|
||||
<strong slot="number">{{ statistics.numberOfLocalEvents }}</strong>
|
||||
</i18n>
|
||||
<i18n tag="p" path="And {number} comments">
|
||||
<strong slot="number">{{ statistics.numberOfComments }}</strong>
|
||||
<strong slot="number">{{ statistics.numberOfLocalComments }}</strong>
|
||||
</i18n>
|
||||
</div>
|
||||
<div class="column contact">
|
||||
@ -140,7 +140,7 @@ section {
|
||||
.statistics {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, 150px);
|
||||
grid-template-rows: repeat(2, 1fr);
|
||||
gap: 2rem 0;
|
||||
p {
|
||||
text-align: right;
|
||||
padding: 0 15px;
|
||||
@ -157,6 +157,9 @@ section {
|
||||
}
|
||||
}
|
||||
.contact {
|
||||
h4 {
|
||||
font-weight: bold;
|
||||
}
|
||||
p {
|
||||
width: 200px;
|
||||
white-space: nowrap;
|
||||
|
@ -12,9 +12,14 @@ defmodule Mobilizon.GraphQL.Resolvers.Statistics do
|
||||
{:ok,
|
||||
%{
|
||||
number_of_users: StatisticsModule.get_cached_value(:local_users),
|
||||
number_of_events: StatisticsModule.get_cached_value(:local_events),
|
||||
number_of_comments: StatisticsModule.get_cached_value(:local_comments),
|
||||
number_of_groups: StatisticsModule.get_cached_value(:local_groups)
|
||||
number_of_events: StatisticsModule.get_cached_value(:federation_events),
|
||||
number_of_local_events: StatisticsModule.get_cached_value(:local_events),
|
||||
number_of_comments: StatisticsModule.get_cached_value(:federation_comments),
|
||||
number_of_local_comments: StatisticsModule.get_cached_value(:local_comments),
|
||||
number_of_groups: StatisticsModule.get_cached_value(:federation_groups),
|
||||
number_of_local_groups: StatisticsModule.get_cached_value(:local_groups),
|
||||
number_of_instance_followings: StatisticsModule.get_cached_value(:instance_followings),
|
||||
number_of_instance_followers: StatisticsModule.get_cached_value(:instance_followers)
|
||||
}}
|
||||
end
|
||||
end
|
||||
|
@ -10,9 +10,20 @@ defmodule Mobilizon.GraphQL.Schema.StatisticsType do
|
||||
object :statistics do
|
||||
# Instance name
|
||||
field(:number_of_users, :integer, description: "The number of local users")
|
||||
field(:number_of_events, :integer, description: "The number of local events")
|
||||
field(:number_of_comments, :integer, description: "The number of local comments")
|
||||
field(:number_of_groups, :integer, description: "The number of local groups")
|
||||
field(:number_of_events, :integer, description: "The total number of events")
|
||||
field(:number_of_local_events, :integer, description: "The number of local events")
|
||||
field(:number_of_comments, :integer, description: "The total number of comments")
|
||||
field(:number_of_local_comments, :integer, description: "The number of local events")
|
||||
field(:number_of_groups, :integer, description: "The total number of groups")
|
||||
field(:number_of_local_groups, :integer, description: "The number of local groups")
|
||||
|
||||
field(:number_of_instance_followers, :integer,
|
||||
description: "The number of this instance's followers"
|
||||
)
|
||||
|
||||
field(:number_of_instance_followings, :integer,
|
||||
description: "The number of instances this instance follows"
|
||||
)
|
||||
end
|
||||
|
||||
object :statistics_queries do
|
||||
|
@ -1076,6 +1076,17 @@ defmodule Mobilizon.Actors do
|
||||
|> Page.build_page(page, limit)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Returns the number of followers for an actor
|
||||
"""
|
||||
@spec count_followers_for_actor(Actor.t()) :: integer()
|
||||
def count_followers_for_actor(%Actor{id: actor_id}) do
|
||||
actor_id
|
||||
|> follower_for_actor_query()
|
||||
|> where(approved: true)
|
||||
|> Repo.aggregate(:count)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Returns the list of followings for an actor.
|
||||
If actor A follows actor B and C, actor A's followings are B and C.
|
||||
@ -1087,6 +1098,17 @@ defmodule Mobilizon.Actors do
|
||||
|> Repo.all()
|
||||
end
|
||||
|
||||
@doc """
|
||||
Returns the number of followings for an actor
|
||||
"""
|
||||
@spec count_followings_for_actor(Actor.t()) :: integer()
|
||||
def count_followings_for_actor(%Actor{id: actor_id}) do
|
||||
actor_id
|
||||
|> followings_for_actor_query()
|
||||
|> where(approved: true)
|
||||
|> Repo.aggregate(:count)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Returns the list of external followings for an actor.
|
||||
"""
|
||||
|
@ -4,6 +4,7 @@ defmodule Mobilizon.Service.Statistics do
|
||||
"""
|
||||
|
||||
alias Mobilizon.{Actors, Discussions, Events, Users}
|
||||
alias Mobilizon.Federation.ActivityPub.Relay
|
||||
|
||||
def get_cached_value(key) do
|
||||
case Cachex.fetch(:statistics, key, fn key ->
|
||||
@ -44,4 +45,14 @@ defmodule Mobilizon.Service.Statistics do
|
||||
defp create_cache(:federation_groups) do
|
||||
Actors.count_groups()
|
||||
end
|
||||
|
||||
defp create_cache(:instance_followers) do
|
||||
relay_actor = Relay.get_actor()
|
||||
Actors.count_followers_for_actor(relay_actor)
|
||||
end
|
||||
|
||||
defp create_cache(:instance_followings) do
|
||||
relay_actor = Relay.get_actor()
|
||||
Actors.count_followings_for_actor(relay_actor)
|
||||
end
|
||||
end
|
||||
|
46
test/graphql/resolvers/statistics_test.exs
Normal file
46
test/graphql/resolvers/statistics_test.exs
Normal file
@ -0,0 +1,46 @@
|
||||
defmodule Mobilizon.GraphQL.Resolvers.StatisticsTest do
|
||||
use Mobilizon.Web.ConnCase
|
||||
|
||||
import Mobilizon.Factory
|
||||
|
||||
alias Mobilizon.GraphQL.AbsintheHelpers
|
||||
|
||||
describe "statistics resolver" do
|
||||
@statistics_query """
|
||||
query {
|
||||
statistics {
|
||||
numberOfUsers
|
||||
numberOfEvents
|
||||
numberOfLocalEvents
|
||||
numberOfComments
|
||||
numberOfLocalComments
|
||||
numberOfGroups
|
||||
numberOfLocalGroups
|
||||
numberOfInstanceFollowings
|
||||
numberOfInstanceFollowers
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
test "get statistics", %{conn: conn} do
|
||||
Cachex.clear(:statistics)
|
||||
insert(:event)
|
||||
insert(:comment)
|
||||
insert(:group)
|
||||
actor = insert(:actor, user: nil, domain: "toto.tld")
|
||||
insert(:event, organizer_actor: actor, local: false)
|
||||
|
||||
res = AbsintheHelpers.graphql_query(conn, query: @statistics_query)
|
||||
|
||||
assert res["data"]["statistics"]["numberOfUsers"] == 6
|
||||
assert res["data"]["statistics"]["numberOfLocalEvents"] == 2
|
||||
assert res["data"]["statistics"]["numberOfEvents"] == 3
|
||||
assert res["data"]["statistics"]["numberOfLocalComments"] == 1
|
||||
assert res["data"]["statistics"]["numberOfLocalGroups"] == 1
|
||||
|
||||
insert(:event)
|
||||
# We keep the value in cache
|
||||
assert res["data"]["statistics"]["numberOfLocalEvents"] == 2
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue
Block a user