Paginate the list of conversations

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
Thomas Citharel 2021-05-20 16:51:41 +02:00
parent 3abd97fc91
commit c9700906f5
No known key found for this signature in database
GPG key ID: A061B9DDE0CA0773
4 changed files with 62 additions and 3 deletions

View file

@ -119,7 +119,7 @@ export const GROUP_FIELDS_FRAGMENTS = gql`
} }
total total
} }
discussions { discussions(page: $discussionsPage, limit: $discussionsLimit) {
total total
elements { elements {
...DiscussionBasicFields ...DiscussionBasicFields
@ -198,6 +198,8 @@ export const FETCH_GROUP = gql`
$postsLimit: Int $postsLimit: Int
$membersPage: Int $membersPage: Int
$membersLimit: Int $membersLimit: Int
$discussionsPage: Int
$discussionsLimit: Int
) { ) {
group(preferredUsername: $name) { group(preferredUsername: $name) {
...GroupFullFields ...GroupFullFields
@ -220,6 +222,8 @@ export const GET_GROUP = gql`
$postsLimit: Int $postsLimit: Int
$membersPage: Int $membersPage: Int
$membersLimit: Int $membersLimit: Int
$discussionsPage: Int
$discussionsLimit: Int
) { ) {
getGroup(id: $id) { getGroup(id: $id) {
mediaSize mediaSize

View file

@ -49,6 +49,17 @@
v-for="discussion in group.discussions.elements" v-for="discussion in group.discussions.elements"
:key="discussion.id" :key="discussion.id"
/> />
<b-pagination
class="discussion-pagination"
:total="group.discussions.total"
v-model="page"
:per-page="DISCUSSIONS_PER_PAGE"
:aria-next-label="$t('Next page')"
:aria-previous-label="$t('Previous page')"
:aria-page-label="$t('Page')"
:aria-current-label="$t('Current page')"
>
</b-pagination>
</div> </div>
<empty-content v-else icon="chat"> <empty-content v-else icon="chat">
{{ $t("There's no discussions yet") }} {{ $t("There's no discussions yet") }}
@ -82,6 +93,10 @@ import {
} from "@/graphql/actor"; } from "@/graphql/actor";
import { IMember } from "@/types/actor/member.model"; import { IMember } from "@/types/actor/member.model";
import EmptyContent from "@/components/Utils/EmptyContent.vue"; import EmptyContent from "@/components/Utils/EmptyContent.vue";
import VueRouter from "vue-router";
const { isNavigationFailure, NavigationFailureType } = VueRouter;
const DISCUSSIONS_PER_PAGE = 10;
@Component({ @Component({
components: { DiscussionListItem, EmptyContent }, components: { DiscussionListItem, EmptyContent },
@ -92,6 +107,8 @@ import EmptyContent from "@/components/Utils/EmptyContent.vue";
variables() { variables() {
return { return {
name: this.preferredUsername, name: this.preferredUsername,
discussionsPage: this.page,
discussionsLimit: DISCUSSIONS_PER_PAGE,
}; };
}, },
skip() { skip() {
@ -154,6 +171,18 @@ export default class DiscussionsList extends Vue {
usernameWithDomain = usernameWithDomain; usernameWithDomain = usernameWithDomain;
DISCUSSIONS_PER_PAGE = DISCUSSIONS_PER_PAGE;
get page(): number {
return parseInt((this.$route.query.page as string) || "1", 10);
}
set page(page: number) {
this.pushRouter(RouteName.DISCUSSION_LIST, {
page: page.toString(),
});
}
get groupMemberships(): (string | undefined)[] { get groupMemberships(): (string | undefined)[] {
if (!this.person || !this.person.id) return []; if (!this.person || !this.person.id) return [];
return this.person.memberships.elements return this.person.memberships.elements
@ -174,10 +203,30 @@ export default class DiscussionsList extends Vue {
this.groupMemberships.includes(this.group.id) this.groupMemberships.includes(this.group.id)
); );
} }
protected async pushRouter(
routeName: string,
args: Record<string, string>
): Promise<void> {
try {
await this.$router.push({
name: routeName,
query: { ...this.$route.query, ...args },
});
} catch (e) {
if (isNavigationFailure(e, NavigationFailureType.redirected)) {
throw Error(e.toString());
}
}
}
} }
</script> </script>
<style lang="scss"> <style lang="scss">
div.container.section { div.container.section {
background: white; background: white;
.discussion-pagination {
margin-top: 1rem;
}
} }
</style> </style>

View file

@ -14,7 +14,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Discussion do
def find_discussions_for_actor( def find_discussions_for_actor(
%Actor{id: group_id}, %Actor{id: group_id},
_args, %{page: page, limit: limit},
%{ %{
context: %{ context: %{
current_user: %User{} = user current_user: %User{} = user
@ -24,7 +24,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Discussion do
with {:actor, %Actor{id: actor_id} = _actor} <- {:actor, Users.get_actor_for_user(user)}, with {:actor, %Actor{id: actor_id} = _actor} <- {:actor, Users.get_actor_for_user(user)},
{:member, true} <- {:member, Actors.is_member?(actor_id, group_id)}, {:member, true} <- {:member, Actors.is_member?(actor_id, group_id)},
{:ok, %Actor{type: :Group} = group} <- Actors.get_group_by_actor_id(group_id) do {:ok, %Actor{type: :Group} = group} <- Actors.get_group_by_actor_id(group_id) do
{:ok, Discussions.find_discussions_for_actor(group)} {:ok, Discussions.find_discussions_for_actor(group, page, limit)}
else else
{:member, false} -> {:member, false} ->
{:ok, %Page{total: 0, elements: []}} {:ok, %Page{total: 0, elements: []}}

View file

@ -86,6 +86,12 @@ defmodule Mobilizon.GraphQL.Schema.Actors.GroupType do
end end
field :discussions, :paginated_discussion_list do field :discussions, :paginated_discussion_list do
arg(:page, :integer,
default_value: 1,
description: "The page in the paginated discussion list"
)
arg(:limit, :integer, default_value: 10, description: "The limit of discussions per page")
resolve(&Discussion.find_discussions_for_actor/3) resolve(&Discussion.find_discussions_for_actor/3)
description("A list of the discussions for this group") description("A list of the discussions for this group")
end end