From 2302a46d9bd4c212a7d0a11a2a61fabbc651e5ff Mon Sep 17 00:00:00 2001 From: konrad Date: Tue, 3 Dec 2019 18:09:12 +0000 Subject: [PATCH] Task Pagination (#38) --- src/components/lists/ShowList.vue | 2 +- src/components/tasks/ShowListTasks.vue | 71 ++++++++++++++++++++++++-- src/services/abstractService.js | 13 ++++- src/services/taskCollection.js | 14 +++++ 4 files changed, 93 insertions(+), 7 deletions(-) create mode 100644 src/services/taskCollection.js diff --git a/src/components/lists/ShowList.vue b/src/components/lists/ShowList.vue index ef24f398..da41c47c 100644 --- a/src/components/lists/ShowList.vue +++ b/src/components/lists/ShowList.vue @@ -58,7 +58,7 @@ }, watch: { // call again the method if the route changes - '$route': 'loadList' + '$route.path': 'loadList' }, methods: { loadList() { diff --git a/src/components/tasks/ShowListTasks.vue b/src/components/tasks/ShowListTasks.vue index 676e8dfe..40652083 100644 --- a/src/components/tasks/ShowListTasks.vue +++ b/src/components/tasks/ShowListTasks.vue @@ -1,5 +1,5 @@ @@ -81,6 +94,7 @@ import EditTask from './edit-task' import TaskModel from '../../models/task' import PriorityLabel from './reusable/priorityLabel' + import TaskCollectionService from '../../services/taskCollection' export default { data() { @@ -88,7 +102,11 @@ listID: this.$route.params.id, listService: ListService, taskService: TaskService, + taskCollectionService: TaskCollectionService, + pages: [], + currentPage: 0, list: {}, + tasks: [], isTaskEdit: false, taskEditTask: TaskModel, newTaskText: '', @@ -107,11 +125,14 @@ watch: { theList() { this.list = this.theList - } + this.loadTasks(1) + }, + '$route.query': 'loadTasksForPage', // Only listen for query path changes }, created() { this.listService = new ListService() this.taskService = new TaskService() + this.taskCollectionService = new TaskCollectionService() this.taskEditTask = null this.isTaskEdit = false }, @@ -128,6 +149,48 @@ 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) { let updateFunc = () => { // We get the task, update the 'done' property and then push it to the api. diff --git a/src/services/abstractService.js b/src/services/abstractService.js index 4a5bb9f0..0ac60f32 100644 --- a/src/services/abstractService.js +++ b/src/services/abstractService.js @@ -18,6 +18,9 @@ export default class AbstractService { update: '', delete: '', } + // This contains the total number of pages and the number of results for the current page + totalPages = 0 + resultCount = 0 ///////////// // Service init @@ -96,7 +99,7 @@ export default class AbstractService { useDeleteInterceptor() { return true } - + ///////////////////// // 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. * @param model The model to use. The request path is built using the values from the model. * @param params Optional query parameters + * @param page The page to get * @returns {Q.Promise} */ - getAll(model = {}, params = {}) { + getAll(model = {}, params = {}, page = 1) { if (this.paths.getAll === '') { return Promise.reject({message: 'This model is not able to get data.'}) } + params.page = page + const cancel = this.setLoading() model = this.beforeGet(model) return this.http.get(this.getReplacedRoute(this.paths.getAll, model), {params: params}) @@ -312,6 +318,9 @@ export default class AbstractService { return this.errorHandler(error) }) .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)) { return Promise.resolve(response.data.map(entry => { return this.modelGetAllFactory(entry) diff --git a/src/services/taskCollection.js b/src/services/taskCollection.js new file mode 100644 index 00000000..28808e33 --- /dev/null +++ b/src/services/taskCollection.js @@ -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) + } +} \ No newline at end of file