Add pagination to resources

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
Thomas Citharel 2021-06-14 15:12:38 +02:00
parent 9d64a80434
commit 24b94d1860
No known key found for this signature in database
GPG Key ID: A061B9DDE0CA0773
4 changed files with 79 additions and 4 deletions

View File

@ -11,7 +11,12 @@ export const RESOURCE_METADATA_BASIC_FIELDS_FRAGMENT = gql`
`; `;
export const GET_RESOURCE = gql` export const GET_RESOURCE = gql`
query GetResource($path: String!, $username: String!) { query GetResource(
$path: String!
$username: String!
$page: Int
$limit: Int
) {
resource(path: $path, username: $username) { resource(path: $path, username: $username) {
id id
title title
@ -38,7 +43,7 @@ export const GET_RESOURCE = gql`
name name
domain domain
} }
children { children(page: $page, limit: $limit) {
total total
elements { elements {
id id

View File

@ -145,6 +145,17 @@
<p>{{ $t("No resources in this folder") }}</p> <p>{{ $t("No resources in this folder") }}</p>
</div> </div>
</section> </section>
<b-pagination
v-if="resource.children.total > RESOURCES_PER_PAGE"
:total="resource.children.total"
v-model="page"
:per-page="RESOURCES_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>
<b-modal :active.sync="renameModal" has-modal-card> <b-modal :active.sync="renameModal" has-modal-card>
<div class="modal-card"> <div class="modal-card">
<section class="modal-card-body"> <section class="modal-card-body">
@ -250,6 +261,8 @@ import { IConfig } from "../../types/config.model";
import ResourceMixin from "../../mixins/resource"; import ResourceMixin from "../../mixins/resource";
import ResourceSelector from "../../components/Resource/ResourceSelector.vue"; import ResourceSelector from "../../components/Resource/ResourceSelector.vue";
import { ApolloCache, FetchResult } from "@apollo/client/core"; import { ApolloCache, FetchResult } from "@apollo/client/core";
import VueRouter from "vue-router";
const { isNavigationFailure, NavigationFailureType } = VueRouter;
@Component({ @Component({
components: { FolderItem, ResourceItem, Draggable, ResourceSelector }, components: { FolderItem, ResourceItem, Draggable, ResourceSelector },
@ -265,6 +278,8 @@ import { ApolloCache, FetchResult } from "@apollo/client/core";
return { return {
path, path,
username: this.$route.params.preferredUsername, username: this.$route.params.preferredUsername,
page: this.page,
limit: this.RESOURCES_PER_PAGE,
}; };
}, },
error({ graphQLErrors }) { error({ graphQLErrors }) {
@ -303,6 +318,8 @@ export default class Resources extends Mixins(ResourceMixin) {
usernameWithDomain = usernameWithDomain; usernameWithDomain = usernameWithDomain;
RESOURCES_PER_PAGE = 10;
newResource: IResource = { newResource: IResource = {
title: "", title: "",
summary: "", summary: "",
@ -344,6 +361,16 @@ export default class Resources extends Mixins(ResourceMixin) {
mapServiceTypeToIcon = mapServiceTypeToIcon; mapServiceTypeToIcon = mapServiceTypeToIcon;
get page(): number {
return parseInt((this.$route.query.page as string) || "1", 10);
}
set page(page: number) {
this.pushRouter({
page: page.toString(),
});
}
get actualPath(): string { get actualPath(): string {
const path = Array.isArray(this.$route.params.path) const path = Array.isArray(this.$route.params.path)
? this.$route.params.path.join("/") ? this.$route.params.path.join("/")
@ -641,16 +668,51 @@ export default class Resources extends Mixins(ResourceMixin) {
} }
} }
@Watch("page")
loadMoreResources(): void {
this.$apollo.queries.resource.fetchMore({
// New variables
variables: {
page: this.page,
limit: this.RESOURCES_PER_PAGE,
},
});
}
handleErrors(errors: any[]): void { handleErrors(errors: any[]): void {
if (errors.some((error) => error.status_code === 404)) { if (errors.some((error) => error.status_code === 404)) {
this.$router.replace({ name: RouteName.PAGE_NOT_FOUND }); this.$router.replace({ name: RouteName.PAGE_NOT_FOUND });
} }
} }
async pushRouter(args: Record<string, string>): Promise<void> {
try {
const path = this.filteredPath.toString();
const routeName =
path === ""
? RouteName.RESOURCE_FOLDER_ROOT
: RouteName.RESOURCE_FOLDER;
await this.$router.push({
name: routeName,
params: { path },
query: { ...this.$route.query, ...args },
});
} catch (e) {
if (isNavigationFailure(e, NavigationFailureType.redirected)) {
throw Error(e.toString());
}
}
}
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.container.section { .container.section {
background: $white; background: $white;
& > nav.pagination {
margin-top: 1rem;
}
} }
nav.breadcrumb ul { nav.breadcrumb ul {

View File

@ -50,7 +50,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Resource do
def find_resources_for_parent( def find_resources_for_parent(
%Resource{actor_id: group_id} = parent, %Resource{actor_id: group_id} = parent,
_args, %{page: page, limit: limit},
%{ %{
context: %{ context: %{
current_user: %User{} = user current_user: %User{} = user
@ -59,7 +59,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Resource do
) do ) do
with %Actor{id: actor_id} <- Users.get_actor_for_user(user), with %Actor{id: actor_id} <- 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)},
%Page{} = page <- Resources.get_resources_for_folder(parent) do %Page{} = page <- Resources.get_resources_for_folder(parent, page, limit) do
{:ok, page} {:ok, page}
end end
end end

View File

@ -27,6 +27,14 @@ defmodule Mobilizon.GraphQL.Schema.ResourceType do
field :children, :paginated_resource_list do field :children, :paginated_resource_list do
description("Children resources in folder") description("Children resources in folder")
arg(:page, :integer,
default_value: 1,
description: "The page in the paginated resource list"
)
arg(:limit, :integer, default_value: 10, description: "The limit of resources per page")
resolve(&Resource.find_resources_for_parent/3) resolve(&Resource.find_resources_for_parent/3)
end end
end end