Added basic pagination to homepage.

This commit is contained in:
ThePendulum 2020-05-22 04:32:16 +02:00
parent f38be7a706
commit 2fcd426b49
13 changed files with 214 additions and 66 deletions

View File

@ -1,59 +1,76 @@
<template> <template>
<div class="content"> <div class="content">
<FilterBar <FilterBar
:fetch-releases="fetchReleases" :fetch-releases="fetchReleases"
:is-home="true" :is-home="true"
/> />
<div class="content-inner"> <div class="content-inner">
<Releases :releases="releases" /> <Pagination
</div> :items-total="totalCount"
</div> :items-per-page="limit"
class="pagination-top"
/>
<Releases :releases="releases" />
<Pagination
:items-total="totalCount"
:items-per-page="limit"
class="pagination-bottom"
/>
</div>
</div>
</template> </template>
<script> <script>
import FilterBar from '../header/filter-bar.vue'; import FilterBar from '../header/filter-bar.vue';
import Releases from '../releases/releases.vue'; import Releases from '../releases/releases.vue';
import Pagination from '../pagination/pagination.vue';
async function fetchReleases() { async function fetchReleases() {
this.releases = await this.$store.dispatch('fetchReleases', { const { releases, totalCount } = await this.$store.dispatch('fetchReleases', {
limit: (this.$route.query && this.$route.query.limit && Number(this.$route.query.limit)) || 30, limit: this.limit,
range: this.$route.name, pageNumber: Number(this.$route.params.pageNumber) || 1,
}); range: this.$route.name,
});
this.totalCount = totalCount;
this.releases = releases;
} }
async function route() { async function route() {
await this.fetchReleases(); await this.fetchReleases();
} }
async function mounted() { async function mounted() {
this.pageTitle = ''; this.pageTitle = '';
await this.fetchReleases(); await this.fetchReleases();
} }
export default { export default {
components: { components: {
FilterBar, FilterBar,
Releases, Releases,
}, Pagination,
data() { },
return { data() {
releases: [], return {
networks: [], releases: [],
pageTitle: null, networks: [],
from: null, pageTitle: null,
}; limit: 15,
}, totalCount: 0,
beforeRouteEnter(to, from, next) { from: null,
next(vm => vm.$set(vm, 'from', from)); };
}, },
watch: { watch: {
$route: route, $route: route,
}, },
mounted, mounted,
methods: { methods: {
fetchReleases, fetchReleases,
}, },
}; };
</script> </script>

View File

@ -0,0 +1,112 @@
<template>
<div class="pagination">
<template v-if="pageNumber > 1">
<router-link
class="pagination-page"
:to="{ params: { pageNumber: 1 } }"
>&lt;&lt;</router-link>
<router-link
class="pagination-page"
:to="{ params: { pageNumber: pageNumber - 1 } }"
>&lt;</router-link>
</template>
<template v-else>
<span class="pagination-page disabled">&lt;&lt;</span>
<span class="pagination-page disabled">&lt;</span>
</template>
<router-link
v-for="pageX in pageCount"
:key="`page-${pageX}`"
:to="{ params: { pageNumber: pageX } }"
:class="{ active: pageX === pageNumber }"
class="pagination-page"
> {{ pageX }} </router-link>
<template v-if="pageNumber < pageCount">
<router-link
class="pagination-page"
:to="{ params: { pageNumber: pageNumber + 1 } }"
>&gt;</router-link>
<router-link
class="pagination-page"
:to="{ params: { pageNumber: pageCount } }"
>&gt;&gt;</router-link>
</template>
<template v-else>
<span class="pagination-page disabled">&gt;</span>
<span class="pagination-page disabled">&gt;&gt;</span>
</template>
</div>
</template>
<script>
function pageNumber() {
return Number(this.$route.params.pageNumber) || 1;
}
function pageCount() {
return Math.ceil(this.itemsTotal / this.itemsPerPage);
}
export default {
props: {
itemsTotal: {
type: Number,
default: 0,
},
itemsPerPage: {
type: Number,
default: 10,
},
},
computed: {
pageNumber,
pageCount,
},
};
</script>
<style lang="scss" scoped>
.pagination {
width: 100%;
display: flex;
justify-content: center;
}
.pagination-page {
width: 2rem;
height: 2rem;
display: inline-flex;
align-items: center;
margin: 0 .5rem 0 0;
justify-content: center;
color: var(--shadow);
font-weight: bold;
text-decoration: none;
&:hover:not(.active, .disabled) {
color: var(--text);
}
&.active {
color: var(--primary);
}
&.disabled {
color: var(--shadow-weak);
}
}
.pagination-top {
margin: 0 0 1rem 0;
}
.pagination-bottom{
margin: 1rem 0 0 0;
}
</style>

View File

@ -3,6 +3,8 @@
v-if="release" v-if="release"
class="content" class="content"
> >
<Banner :release="release" />
<div class="details"> <div class="details">
<div class="column"> <div class="column">
<a <a
@ -93,8 +95,6 @@
</div> </div>
</div> </div>
<Banner :release="release" />
<div class="info column"> <div class="info column">
<h2 class="row title">{{ release.title }}</h2> <h2 class="row title">{{ release.title }}</h2>

View File

@ -172,6 +172,7 @@ export default {
color: var(--text-light); color: var(--text-light);
display: flex; display: flex;
flex-direction: column; flex-direction: column;
flex-shrink: 0;
width: 25rem; width: 25rem;
box-sizing: border-box; box-sizing: border-box;
overflow: hidden; overflow: hidden;

View File

@ -136,7 +136,7 @@ function initActorActions(store, _router) {
lessThan: $before, lessThan: $before,
greaterThan: $after, greaterThan: $after,
}, },
releasesTags: { releasesTagsConnection: {
none: { none: {
tag: { tag: {
slug: { slug: {

View File

@ -176,13 +176,13 @@ const releaseFields = `
`; `;
const releasesFragment = ` const releasesFragment = `
releases( connection: releasesConnection(
filter: { filter: {
date: { date: {
lessThan: $before, lessThan: $before,
greaterThan: $after, greaterThan: $after,
} }
releasesTags: { releasesTagsConnection: {
none: { none: {
tag: { tag: {
slug: { slug: {
@ -193,21 +193,25 @@ const releasesFragment = `
} }
}, },
first: $limit, first: $limit,
offset: $offset,
orderBy: $orderBy, orderBy: $orderBy,
) { ) {
${releaseFields} releases: nodes {
movieActors: movieActorsByMovieId(orderBy: ACTOR_BY_ACTOR_ID__GENDER_ASC) { ${releaseFields}
actor { movieActors: movieActorsByMovieId(orderBy: ACTOR_BY_ACTOR_ID__GENDER_ASC) {
${actorFields} actor {
} ${actorFields}
} }
movieTags: movieTagsByMovieId(orderBy: TAG_BY_TAG_ID__PRIORITY_DESC) { }
tag { movieTags: movieTagsByMovieId(orderBy: TAG_BY_TAG_ID__PRIORITY_DESC) {
id tag {
name id
slug name
} slug
} }
}
}
totalCount
} }
`; `;

View File

@ -92,7 +92,7 @@ function initNetworksActions(store, _router) {
} }
} }
] ]
releasesTags: { releasesTagsConnection: {
none: { none: {
tag: { tag: {
slug: { slug: {

View File

@ -4,12 +4,13 @@ import { curateRelease } from '../curate';
import getDateRange from '../get-date-range'; import getDateRange from '../get-date-range';
function initReleasesActions(store, _router) { function initReleasesActions(store, _router) {
async function fetchReleases({ _commit }, { limit = 100, range = 'latest' }) { async function fetchReleases({ _commit }, { limit = 10, pageNumber = 1, range = 'latest' }) {
const { before, after, orderBy } = getDateRange(range); const { before, after, orderBy } = getDateRange(range);
const { releases } = await graphql(` const { connection: { releases, totalCount } } = await graphql(`
query Releases( query Releases(
$limit:Int = 1000, $limit:Int = 1000,
$offset:Int = 0,
$after:Date = "1900-01-01", $after:Date = "1900-01-01",
$before:Date = "2100-01-01", $before:Date = "2100-01-01",
$orderBy:[ReleasesOrderBy!], $orderBy:[ReleasesOrderBy!],
@ -19,13 +20,17 @@ function initReleasesActions(store, _router) {
} }
`, { `, {
limit, limit,
offset: Math.max(0, (pageNumber - 1)) * limit,
after, after,
before, before,
orderBy, orderBy,
exclude: store.state.ui.filter, exclude: store.state.ui.filter,
}); });
return releases.map(release => curateRelease(release)); return {
releases: releases.map(release => curateRelease(release)),
totalCount,
};
} }
async function fetchReleaseById({ _commit }, releaseId) { async function fetchReleaseById({ _commit }, releaseId) {

View File

@ -20,26 +20,32 @@ const routes = [
path: '/', path: '/',
redirect: { redirect: {
name: 'latest', name: 'latest',
params: {
page: 1,
},
}, },
}, },
{ {
path: '/home', path: '/home',
redirect: { redirect: {
name: 'latest', name: 'latest',
params: {
page: 1,
},
}, },
}, },
{ {
path: '/latest', path: '/latest/:pageNumber',
component: Home, component: Home,
name: 'latest', name: 'latest',
}, },
{ {
path: '/upcoming', path: '/upcoming/:pageNumber',
component: Home, component: Home,
name: 'upcoming', name: 'upcoming',
}, },
{ {
path: '/new', path: '/new/:pageNumber',
component: Home, component: Home,
name: 'new', name: 'new',
}, },

View File

@ -64,7 +64,7 @@ function initTagsActions(store, _router) {
lessThan: $before, lessThan: $before,
greaterThan: $after, greaterThan: $after,
}, },
releasesTags: { releasesTagsConnection: {
none: { none: {
tag: { tag: {
slug: { slug: {

View File

@ -644,7 +644,10 @@ exports.up = knex => Promise.resolve()
table.string('url', 1000); table.string('url', 1000);
table.string('title'); table.string('title');
table.string('slug'); table.string('slug');
table.date('date'); table.date('date');
table.index('date');
table.text('description'); table.text('description');
table.integer('duration') table.integer('duration')

View File

@ -7,7 +7,6 @@ const cheerio = require('cheerio');
const { JSDOM } = require('jsdom'); const { JSDOM } = require('jsdom');
const moment = require('moment'); const moment = require('moment');
const logger = require('../logger')(__filename);
const { get, geta, ctxa, parseDate } = require('../utils/q'); const { get, geta, ctxa, parseDate } = require('../utils/q');
const { heightToCm } = require('../utils/convert'); const { heightToCm } = require('../utils/convert');
const slugify = require('../utils/slugify'); const slugify = require('../utils/slugify');

View File

@ -41,7 +41,8 @@ function initServer() {
graphiql: true, graphiql: true,
enhanceGraphiql: true, enhanceGraphiql: true,
allowExplain: () => true, allowExplain: () => true,
simpleCollections: 'only', // simpleCollections: 'only',
simpleCollections: 'both',
graphileBuildOptions: { graphileBuildOptions: {
pgOmitListSuffix: true, pgOmitListSuffix: true,
connectionFilterRelations: true, connectionFilterRelations: true,