Task Pagination (#38)
This commit is contained in:
parent
99cc06edee
commit
2302a46d9b
4 changed files with 93 additions and 7 deletions
|
@ -58,7 +58,7 @@
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
// call again the method if the route changes
|
// call again the method if the route changes
|
||||||
'$route': 'loadList'
|
'$route.path': 'loadList'
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
loadList() {
|
loadList() {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="loader-container" :class="{ 'is-loading': listService.loading}">
|
<div class="loader-container" :class="{ 'is-loading': listService.loading || taskCollectionService.loading}">
|
||||||
<form @submit.prevent="addTask()">
|
<form @submit.prevent="addTask()">
|
||||||
<div class="field is-grouped">
|
<div class="field is-grouped">
|
||||||
<p class="control has-icons-left is-expanded" :class="{ 'is-loading': taskService.loading}">
|
<p class="control has-icons-left is-expanded" :class="{ 'is-loading': taskService.loading}">
|
||||||
|
@ -21,8 +21,8 @@
|
||||||
|
|
||||||
<div class="columns">
|
<div class="columns">
|
||||||
<div class="column">
|
<div class="column">
|
||||||
<div class="tasks" v-if="this.list.tasks && this.list.tasks.length > 0" :class="{'short': isTaskEdit}">
|
<div class="tasks" v-if="tasks && tasks.length > 0" :class="{'short': isTaskEdit}">
|
||||||
<div class="task" v-for="l in list.tasks" :key="l.id">
|
<div class="task" v-for="l in tasks" :key="l.id">
|
||||||
<span>
|
<span>
|
||||||
<div class="fancycheckbox">
|
<div class="fancycheckbox">
|
||||||
<input @change="markAsDone" type="checkbox" :id="l.id" :checked="l.done" style="display: none;">
|
<input @change="markAsDone" type="checkbox" :id="l.id" :checked="l.done" style="display: none;">
|
||||||
|
@ -69,6 +69,19 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<nav class="pagination is-centered" role="navigation" aria-label="pagination" v-if="taskCollectionService.totalPages > 1">
|
||||||
|
<button class="pagination-previous" @click="loadTasks(currentPage - 1)" :disabled="currentPage === 1">Previous</button>
|
||||||
|
<button class="pagination-next" @click="loadTasks(currentPage + 1)" :disabled="currentPage === taskCollectionService.totalPages">Next page</button>
|
||||||
|
<ul class="pagination-list">
|
||||||
|
<template v-for="(p, i) in pages">
|
||||||
|
<li :key="'page'+i" v-if="p.isEllipsis"><span class="pagination-ellipsis">…</span></li>
|
||||||
|
<li :key="'page'+i" v-else>
|
||||||
|
<router-link :to="{name: 'showList', query: { page: p.number }}" :class="{'is-current': p.number === currentPage}" class="pagination-link" :aria-label="'Goto page ' + p.number">{{ p.number }}</router-link>
|
||||||
|
</li>
|
||||||
|
</template>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -81,6 +94,7 @@
|
||||||
import EditTask from './edit-task'
|
import EditTask from './edit-task'
|
||||||
import TaskModel from '../../models/task'
|
import TaskModel from '../../models/task'
|
||||||
import PriorityLabel from './reusable/priorityLabel'
|
import PriorityLabel from './reusable/priorityLabel'
|
||||||
|
import TaskCollectionService from '../../services/taskCollection'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
|
@ -88,7 +102,11 @@
|
||||||
listID: this.$route.params.id,
|
listID: this.$route.params.id,
|
||||||
listService: ListService,
|
listService: ListService,
|
||||||
taskService: TaskService,
|
taskService: TaskService,
|
||||||
|
taskCollectionService: TaskCollectionService,
|
||||||
|
pages: [],
|
||||||
|
currentPage: 0,
|
||||||
list: {},
|
list: {},
|
||||||
|
tasks: [],
|
||||||
isTaskEdit: false,
|
isTaskEdit: false,
|
||||||
taskEditTask: TaskModel,
|
taskEditTask: TaskModel,
|
||||||
newTaskText: '',
|
newTaskText: '',
|
||||||
|
@ -107,11 +125,14 @@
|
||||||
watch: {
|
watch: {
|
||||||
theList() {
|
theList() {
|
||||||
this.list = this.theList
|
this.list = this.theList
|
||||||
}
|
this.loadTasks(1)
|
||||||
|
},
|
||||||
|
'$route.query': 'loadTasksForPage', // Only listen for query path changes
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.listService = new ListService()
|
this.listService = new ListService()
|
||||||
this.taskService = new TaskService()
|
this.taskService = new TaskService()
|
||||||
|
this.taskCollectionService = new TaskCollectionService()
|
||||||
this.taskEditTask = null
|
this.taskEditTask = null
|
||||||
this.isTaskEdit = false
|
this.isTaskEdit = false
|
||||||
},
|
},
|
||||||
|
@ -128,6 +149,48 @@
|
||||||
message.error(e, this)
|
message.error(e, this)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
loadTasks(page) {
|
||||||
|
this.taskCollectionService.getAll({listID: this.$route.params.id}, {}, page)
|
||||||
|
.then(r => {
|
||||||
|
this.$set(this, 'tasks', r)
|
||||||
|
this.$set(this, 'pages', [])
|
||||||
|
this.currentPage = page
|
||||||
|
|
||||||
|
for (let i = 0; i < this.taskCollectionService.totalPages; i++) {
|
||||||
|
|
||||||
|
// Show ellipsis instead of all pages
|
||||||
|
if(
|
||||||
|
i > 0 && // Always at least the first page
|
||||||
|
(i + 1) < this.taskCollectionService.totalPages && // And the last page
|
||||||
|
(
|
||||||
|
// And the current with current + 1 and current - 1
|
||||||
|
(i + 1) > this.currentPage + 1 ||
|
||||||
|
(i + 1) < this.currentPage - 1
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
// Only add an ellipsis if the last page isn't already one
|
||||||
|
if(this.pages[i - 1] && !this.pages[i - 1].isEllipsis) {
|
||||||
|
this.pages.push({
|
||||||
|
number: 0,
|
||||||
|
isEllipsis: true,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
this.pages.push({
|
||||||
|
number: i + 1,
|
||||||
|
isEllipsis: false,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(e => {
|
||||||
|
message.error(e, this)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
loadTasksForPage(e) {
|
||||||
|
this.loadTasks(e.page)
|
||||||
|
},
|
||||||
markAsDone(e) {
|
markAsDone(e) {
|
||||||
let updateFunc = () => {
|
let updateFunc = () => {
|
||||||
// We get the task, update the 'done' property and then push it to the api.
|
// We get the task, update the 'done' property and then push it to the api.
|
||||||
|
|
|
@ -18,6 +18,9 @@ export default class AbstractService {
|
||||||
update: '',
|
update: '',
|
||||||
delete: '',
|
delete: '',
|
||||||
}
|
}
|
||||||
|
// This contains the total number of pages and the number of results for the current page
|
||||||
|
totalPages = 0
|
||||||
|
resultCount = 0
|
||||||
|
|
||||||
/////////////
|
/////////////
|
||||||
// Service init
|
// Service init
|
||||||
|
@ -96,7 +99,7 @@ export default class AbstractService {
|
||||||
useDeleteInterceptor() {
|
useDeleteInterceptor() {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////////////
|
/////////////////////
|
||||||
// Global error handler
|
// Global error handler
|
||||||
///////////////////
|
///////////////////
|
||||||
|
@ -298,13 +301,16 @@ export default class AbstractService {
|
||||||
* The difference between this and get() is this one is used to get a bunch of data (an array), not just a single object.
|
* The difference between this and get() is this one is used to get a bunch of data (an array), not just a single object.
|
||||||
* @param model The model to use. The request path is built using the values from the model.
|
* @param model The model to use. The request path is built using the values from the model.
|
||||||
* @param params Optional query parameters
|
* @param params Optional query parameters
|
||||||
|
* @param page The page to get
|
||||||
* @returns {Q.Promise<any>}
|
* @returns {Q.Promise<any>}
|
||||||
*/
|
*/
|
||||||
getAll(model = {}, params = {}) {
|
getAll(model = {}, params = {}, page = 1) {
|
||||||
if (this.paths.getAll === '') {
|
if (this.paths.getAll === '') {
|
||||||
return Promise.reject({message: 'This model is not able to get data.'})
|
return Promise.reject({message: 'This model is not able to get data.'})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
params.page = page
|
||||||
|
|
||||||
const cancel = this.setLoading()
|
const cancel = this.setLoading()
|
||||||
model = this.beforeGet(model)
|
model = this.beforeGet(model)
|
||||||
return this.http.get(this.getReplacedRoute(this.paths.getAll, model), {params: params})
|
return this.http.get(this.getReplacedRoute(this.paths.getAll, model), {params: params})
|
||||||
|
@ -312,6 +318,9 @@ export default class AbstractService {
|
||||||
return this.errorHandler(error)
|
return this.errorHandler(error)
|
||||||
})
|
})
|
||||||
.then(response => {
|
.then(response => {
|
||||||
|
this.resultCount = Number(response.headers['x-pagination-result-count'])
|
||||||
|
this.totalPages = Number(response.headers['x-pagination-total-pages'])
|
||||||
|
|
||||||
if (Array.isArray(response.data)) {
|
if (Array.isArray(response.data)) {
|
||||||
return Promise.resolve(response.data.map(entry => {
|
return Promise.resolve(response.data.map(entry => {
|
||||||
return this.modelGetAllFactory(entry)
|
return this.modelGetAllFactory(entry)
|
||||||
|
|
14
src/services/taskCollection.js
Normal file
14
src/services/taskCollection.js
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
import AbstractService from './abstractService'
|
||||||
|
import TaskModel from '../models/task'
|
||||||
|
|
||||||
|
export default class TaskCollectionService extends AbstractService {
|
||||||
|
constructor() {
|
||||||
|
super({
|
||||||
|
getAll: '/lists/{listID}/tasks',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
modelFactory(data) {
|
||||||
|
return new TaskModel(data)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue