From f6480cb37e9ecea71f52144dc34d09f5c0d5ccf3 Mon Sep 17 00:00:00 2001 From: Thomas Citharel Date: Thu, 15 Oct 2020 11:04:05 +0200 Subject: [PATCH] Improve dashboard Signed-off-by: Thomas Citharel --- js/src/graphql/admin.ts | 15 +++++ js/src/i18n/en_US.json | 7 +- js/src/i18n/fr_FR.json | 7 +- js/src/types/admin.model.ts | 6 ++ js/src/views/Admin/Dashboard.vue | 84 +++++++++++++++++++----- lib/graphql/resolvers/admin.ex | 14 +++- lib/graphql/schema/admin.ex | 10 ++- lib/mobilizon/discussions/discussions.ex | 29 +++++--- lib/mobilizon/events/events.ex | 17 +++++ lib/service/statistics/statistics.ex | 8 ++- 10 files changed, 163 insertions(+), 34 deletions(-) diff --git a/js/src/graphql/admin.ts b/js/src/graphql/admin.ts index b135a0016..292ef2414 100644 --- a/js/src/graphql/admin.ts +++ b/js/src/graphql/admin.ts @@ -4,6 +4,7 @@ export const DASHBOARD = gql` query { dashboard { lastPublicEventPublished { + id uuid title picture { @@ -12,10 +13,24 @@ export const DASHBOARD = gql` url } } + lastGroupCreated { + id + preferredUsername + domain + name + avatar { + id + url + } + } numberOfUsers numberOfEvents numberOfComments numberOfReports + numberOfGroups + numberOfFollowers + numberOfFollowings + numberOfConfirmedParticipationsToLocalEvents } } `; diff --git a/js/src/i18n/en_US.json b/js/src/i18n/en_US.json index 33f56d792..44a48d423 100644 --- a/js/src/i18n/en_US.json +++ b/js/src/i18n/en_US.json @@ -281,7 +281,7 @@ "Public feeds": "Public feeds", "Public iCal Feed": "Public iCal Feed", "Publish": "Publish", - "Published events": "Published events", + "Published events with {comments} comments and {participations} confirmed participations": "Published events with {comments} comments and {participations} confirmed participations", "RSS/Atom Feed": "RSS/Atom Feed", "Read Framasoft’s statement of intent on the Framablog": "Read Framasoft’s statement of intent on the Framablog", "Redirecting to event…": "Redirecting to event…", @@ -800,5 +800,8 @@ "To register for an event by choosing one of your identities": "To register for an event by choosing one of your identities", "To create or join an group and start organizing with other people": "To create or join an group and start organizing with other people", "About {instance}": "About {instance}", - "Please read the {fullRules} published by {instance}'s administrators.": "Please read the {fullRules} published by {instance}'s administrators." + "Please read the {fullRules} published by {instance}'s administrators.": "Please read the {fullRules} published by {instance}'s administrators.", + "Instances following you": "Instances following you", + "Instances you follow": "Instances you follow", + "Last group created": "Last group created" } diff --git a/js/src/i18n/fr_FR.json b/js/src/i18n/fr_FR.json index f2591f631..5ae9009cc 100644 --- a/js/src/i18n/fr_FR.json +++ b/js/src/i18n/fr_FR.json @@ -532,7 +532,7 @@ "Public page": "Page publique", "Publication date": "Date de publication", "Publish": "Publier", - "Published events": "Événements publiés", + "Published events with {comments} comments and {participations} confirmed participations": "Événements publiés avec {comments} commentaires et {participations} participations confirmées", "RSS/Atom Feed": "Flux RSS/Atom", "Radius": "Rayon", "Read Framasoft’s statement of intent on the Framablog": "Lire la note d’intention de Framasoft sur le Framablog", @@ -850,5 +850,8 @@ "To register for an event by choosing one of your identities": "Pour s'inscrire à un évènement en choisissant une de vos identités", "To create or join an group and start organizing with other people": "Pour créer ou rejoindre un groupe et commencer à vous organiser avec d'autres personnes", "About {instance}": "À propos de {instance}", - "Please read the {fullRules} published by {instance}'s administrators.": "Merci de lire les {fullRules} publiées par les administrateur·ices de {instance}." + "Please read the {fullRules} published by {instance}'s administrators.": "Merci de lire les {fullRules} publiées par les administrateur·ices de {instance}.", + "Instances following you": "Instances vous suivant", + "Instances you follow": "Instances que vous suivez", + "Last group created": "Dernier groupe créé" } diff --git a/js/src/types/admin.model.ts b/js/src/types/admin.model.ts index cf50a4f32..16534d355 100644 --- a/js/src/types/admin.model.ts +++ b/js/src/types/admin.model.ts @@ -1,11 +1,17 @@ import { IEvent } from "@/types/event.model"; +import { IGroup } from "./actor"; export interface IDashboard { lastPublicEventPublished: IEvent; + lastGroupCreated: IGroup; numberOfUsers: number; numberOfEvents: number; numberOfComments: number; numberOfReports: number; + numberOfGroups: number; + numberOfFollowers: number; + numberOfFollowings: number; + numberOfConfirmedParticipationsToLocalEvents: number; } export enum InstanceTermsType { diff --git a/js/src/views/Admin/Dashboard.vue b/js/src/views/Admin/Dashboard.vue index 18b55838b..c71866422 100644 --- a/js/src/views/Admin/Dashboard.vue +++ b/js/src/views/Admin/Dashboard.vue @@ -18,11 +18,23 @@

{{ dashboard.numberOfEvents }}

-

{{ $t("Published events") }}

+

-

{{ dashboard.numberOfComments }}

-

{{ $t("Comments") }}

+ +

{{ dashboard.numberOfGroups }}

+

{{ $t("Groups") }}

+
@@ -32,29 +44,66 @@

{{ $t("Users") }}

+
+ +

{{ dashboard.numberOfFollowers }}

+

{{ $t("Instances following you") }}

+
+
+
+

{{ dashboard.numberOfReports }}

{{ $t("Opened reports") }}

+
+ +

{{ dashboard.numberOfFollowings }}

+

{{ $t("Instances you follow") }}

+
+
-
- +
+
-

{{ $t("Last published event") }}

-

{{ dashboard.lastPublicEventPublished.title }}

-
- -
+ +

{{ $t("Last published event") }}

+

{{ dashboard.lastPublicEventPublished.title }}

+
+ +
+
- +
+
+
+ +

{{ $t("Last group created") }}

+

+ {{ + dashboard.lastGroupCreated.name || + dashboard.lastGroupCreated.preferredUsername + }} +

+
+ +
+
+
+
@@ -65,6 +114,7 @@ import { Component, Vue } from "vue-property-decorator"; import { DASHBOARD } from "@/graphql/admin"; import { IDashboard } from "@/types/admin.model"; +import { usernameWithDomain } from "@/types/actor"; import RouteName from "../../router/name"; @Component({ @@ -85,6 +135,8 @@ export default class Dashboard extends Vue { dashboard!: IDashboard; RouteName = RouteName; + + usernameWithDomain = usernameWithDomain; } diff --git a/lib/graphql/resolvers/admin.ex b/lib/graphql/resolvers/admin.ex index 3cb9024a2..19927d43e 100644 --- a/lib/graphql/resolvers/admin.ex +++ b/lib/graphql/resolvers/admin.ex @@ -178,13 +178,25 @@ defmodule Mobilizon.GraphQL.Resolvers.Admin do _ -> nil end + last_group_created = + case Actors.list_actors(:Group) do + %Page{elements: [group | _]} -> group + _ -> nil + end + {:ok, %{ number_of_users: Statistics.get_cached_value(:local_users), number_of_events: Statistics.get_cached_value(:local_events), + number_of_groups: Statistics.get_cached_value(:local_groups), number_of_comments: Statistics.get_cached_value(:local_comments), + number_of_confirmed_participations_to_local_events: + Statistics.get_cached_value(:confirmed_participations_to_local_events), number_of_reports: Mobilizon.Reports.count_opened_reports(), - last_public_event_published: last_public_event_published + number_of_followers: Statistics.get_cached_value(:instance_followers), + number_of_followings: Statistics.get_cached_value(:instance_followings), + last_public_event_published: last_public_event_published, + last_group_created: last_group_created }} end diff --git a/lib/graphql/schema/admin.ex b/lib/graphql/schema/admin.ex index a5b58cd03..4126f7214 100644 --- a/lib/graphql/schema/admin.ex +++ b/lib/graphql/schema/admin.ex @@ -70,11 +70,19 @@ defmodule Mobilizon.GraphQL.Schema.AdminType do end object :dashboard do - field(:last_public_event_published, :event, description: "Last public event publish") + field(:last_public_event_published, :event, description: "Last public event published") + field(:last_group_created, :group, description: "Last public group created") 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_reports, :integer, description: "The number of current opened reports") + field(:number_of_followers, :integer, description: "The number of instance followers") + field(:number_of_followings, :integer, description: "The number of instance followings") + + field(:number_of_confirmed_participations_to_local_events, :integer, + description: "The number of total confirmed participations to local events" + ) end object :admin_settings do diff --git a/lib/mobilizon/discussions/discussions.ex b/lib/mobilizon/discussions/discussions.ex index 630788b46..132fb647b 100644 --- a/lib/mobilizon/discussions/discussions.ex +++ b/lib/mobilizon/discussions/discussions.ex @@ -283,16 +283,24 @@ defmodule Mobilizon.Discussions do end @doc """ - Counts local comments. + Counts local comments under events """ - @spec count_local_comments :: integer - def count_local_comments, do: Repo.one(count_local_comments_query()) + @spec count_local_comments_under_events :: integer + def count_local_comments_under_events do + count_local_comments_query() + |> filter_comments_under_events() + |> Repo.one() + end @doc """ Counts all comments. """ - @spec count_comments :: integer - def count_comments, do: Repo.one(count_comments_query()) + @spec count_comments_under_events :: integer + def count_comments_under_events do + count_comments_query() + |> filter_comments_under_events() + |> Repo.one() + end def get_discussion(discussion_id) do Discussion @@ -423,11 +431,8 @@ defmodule Mobilizon.Discussions do @spec count_local_comments_query :: Ecto.Query.t() defp count_local_comments_query do - from( - c in Comment, - select: count(c.id), - where: c.local == ^true and c.visibility in ^@public_visibility - ) + count_comments_query() + |> where([c], local: true) end @spec count_comments_query :: Ecto.Query.t() @@ -439,6 +444,10 @@ defmodule Mobilizon.Discussions do ) end + defp filter_comments_under_events(query) do + where(query, [c], is_nil(c.discussion_id) and not is_nil(c.event_id)) + end + @spec preload_for_comment(Ecto.Query.t()) :: Ecto.Query.t() defp preload_for_comment(query), do: preload(query, ^@comment_preloads) end diff --git a/lib/mobilizon/events/events.ex b/lib/mobilizon/events/events.ex index bb94c67e6..92d40e9b5 100644 --- a/lib/mobilizon/events/events.ex +++ b/lib/mobilizon/events/events.ex @@ -798,6 +798,15 @@ defmodule Mobilizon.Events do @moderator_roles [:moderator, :administrator, :creator] + @doc """ + Returns the number of participations for all local events + """ + @spec count_confirmed_participants_for_local_events :: integer() + def count_confirmed_participants_for_local_events do + count_confirmed_participants_for_local_events_query() + |> Repo.one() + end + @doc """ Returns the list of participants for an event. Default behaviour is to not return :not_approved or :not_confirmed participants @@ -1548,6 +1557,14 @@ defmodule Mobilizon.Events do from(s in Session, where: s.track_id == ^track_id) end + @spec count_confirmed_participants_for_local_events_query :: Ecto.Query.t() + defp count_confirmed_participants_for_local_events_query do + Participant + |> join(:inner, [p], e in Event, on: p.event_id == e.id) + |> where([p, e], e.local and p.role not in [^:not_approved, ^:not_confirmed, ^:rejected]) + |> select([p], count(p.id)) + end + @spec list_participants_for_event_query(String.t()) :: Ecto.Query.t() defp list_participants_for_event_query(event_id) do from( diff --git a/lib/service/statistics/statistics.ex b/lib/service/statistics/statistics.ex index 42998b968..99494726d 100644 --- a/lib/service/statistics/statistics.ex +++ b/lib/service/statistics/statistics.ex @@ -26,8 +26,12 @@ defmodule Mobilizon.Service.Statistics do Events.count_local_events() end + defp create_cache(:confirmed_participations_to_local_events) do + Events.count_confirmed_participants_for_local_events() + end + defp create_cache(:local_comments) do - Discussions.count_local_comments() + Discussions.count_local_comments_under_events() end defp create_cache(:local_groups) do @@ -39,7 +43,7 @@ defmodule Mobilizon.Service.Statistics do end defp create_cache(:federation_comments) do - Discussions.count_comments() + Discussions.count_comments_under_events() end defp create_cache(:federation_groups) do