pagination component

This commit is contained in:
Sergey Yarkov 2019-12-22 19:00:56 +03:00
parent dba4b98260
commit 1b7428c37b
10 changed files with 176 additions and 41 deletions

View File

@ -26,6 +26,17 @@ module.exports = function(server, db) {
} else res.send({error: 'Товаров в магазине пока что нет.'});
});
server.get('/api/items/page/:page', async (req, res) => {
try {
const page = parseInt(req.params.page),
limit = parseInt(req.query.limit),
items = await db.collection('items').find({}, {skip: limit * (page - 1), limit}).toArray();
items.length > 0 && !isNaN(page) ? res.json(items) : res.json({error: 'Такой страницы не существует.'});
} catch (error) {
res.render('main/404');
}
});
server.get('/api/items/:category', async (req, res) => {
const items = await db.collection('items').find({category: req.params.category}).toArray(),
sortBy = req.query.sorting;

View File

@ -20,14 +20,17 @@ module.exports = function(server, db) {
res.render('main/404');
}
});
server.get('/control-panel/items', checkAuthenticated, (req, res) => {
server.get('/control-panel/items', checkAuthenticated, async (req, res) => {
try {
const items = await db.collection('items').find({}).toArray();
const count = items.length;
res.render('admin/items', {
name: req.user.name,
email: req.user.email,
title: 'Digital-Store | Товары',
host: req.headers.host,
pageName: ['Товары', 'items'],
count: count / 2
});
} catch (error) {
res.render('main/404');

View File

@ -707,6 +707,9 @@ footer.main-footer {
max-height: 385px;
overflow-y: hidden;
}
#items .card-content {
min-height: 519px;
}
footer.admin-footer{
background-color: #fff;
border-top: 1px solid #e0e0e0;

View File

@ -33,20 +33,8 @@ body.has-fixed-sidenav
tbody
#loader.progress
.indeterminate
.divider
ul.pagination.center
li.active
a(href="#" class="disabled")
i.material-icons chevron_left
li
a(href="#" class="active") 1
li
a(href="#") 2
li
a(href="#") 3
li
a(href="#" class="disabled")
i.material-icons chevron_right
ul#pagination.pagination.center(data-page="1")
include ./assets/templates/footer.pug
include ./assets/scripts.pug

View File

@ -9,16 +9,16 @@ export class CategoriesComponent extends Component {
}
setElems() {
// обозначим все селекты для рендера в них наши категории и киноки в дальнейшем
// обозначим все селекты для рендера в них наши категории и иконки в дальнейшем
this.$editSelect = this.$el.querySelector('#edit select');
this.$dellSelect = this.$el.querySelector('#delete select');
this.$iconsSelect = this.$el.querySelector('#icons select');
this.$dellIconsSelect = this.$el.querySelector('#dellIcon select');
// формы
this.$dellIconFrom = this.$el.querySelector('#dellIcon');
this.$addForm = this.$el.querySelector('#addCategory');
this.$dellForm = this.$el.querySelector('#dellCategory');
this.$dellIconFrom = this.$el.querySelector('#dellIcon'); // удаление иконки
this.$addForm = this.$el.querySelector('#addCategory'); // добавление категории
this.$dellForm = this.$el.querySelector('#dellCategory'); // удаление категории
// добавим ивенты на наши формы
this.$dellIconFrom.addEventListener('submit', this.dellIcon.bind(this));
@ -27,10 +27,10 @@ export class CategoriesComponent extends Component {
}
async init() {
const categories = await apiService.getCategories();
const icons = await apiService.getIcons();
const icons_html = renderIcons(icons);
const categories_html = renderCategories(categories);
const categories = await apiService.getCategories(),
icons = await apiService.getIcons(),
icons_html = renderIcons(icons),
categories_html = renderCategories(categories);
this.$editSelect.insertAdjacentHTML('beforeend', categories_html);
this.$dellSelect.insertAdjacentHTML('beforeend', categories_html);
@ -41,25 +41,28 @@ export class CategoriesComponent extends Component {
async addCategory(e) {
e.preventDefault();
const categories = await apiService.getCategories();
const title = this.$addForm.elements[0].value.toLowerCase().trim();
const index = categories.map((category) => {return category.title}).indexOf(title);
const categories = await apiService.getCategories(),
title = this.$addForm.elements[0].value.toLowerCase().trim(),
index = categories.map((category) => {return category.title}).indexOf(title);
index != -1 ? alert('Такая категория уже существует, придумайте другое название.') : this.$addForm.submit();
}
async deleteCategory(e) {
e.preventDefault();
const categories = await apiService.getCategories();
const title = this.$dellForm.elements[0].value.toLowerCase().trim();
const index = categories.map((category) => {return category.title}).indexOf(title);
const categories = await apiService.getCategories(),
title = this.$dellForm.elements[0].value.toLowerCase().trim(),
index = categories.map((category) => {return category.title}).indexOf(title);
index != -1 ? this.$dellForm.submit() : alert('Выберите категорию для удаления.');
}
async dellIcon(e) {
e.preventDefault();
const icons = await apiService.getIcons();
const currIcon = e.target.elements[0].value;
const index = icons.indexOf(currIcon);
const icons = await apiService.getIcons(),
currIcon = e.target.elements[0].value,
index = icons.indexOf(currIcon);
index != -1 ? e.target.submit() : alert('Выберите иконку для удаления.');
}
}

View File

@ -8,16 +8,30 @@ export class ItemsComponent extends Component {
this.loader = loader;
}
setElems() {
async init() {
const items = await apiService.getItemsOffset(1, 5),
categories = await apiService.getCategories(),
html = renderItems(items, categories);
this.$table = this.$el.querySelector('table tbody');
this.$table.insertAdjacentHTML('afterbegin', html);
this.onHide();
}
async init() {
const categories = await apiService.getCategories();
const items = await apiService.getItems();
const html = renderItems(items, categories);
this.$table.insertAdjacentHTML('afterbegin', html);
onHide() {
this.loader.hide();
}
onShow() {
this.loader.show();
this.$table.innerHTML = '';
}
async insertItems(page, limit) {
const items = await apiService.getItemsOffset(page, limit),
categories = await apiService.getCategories(),
html = renderItems(items, categories);
this.$table.insertAdjacentHTML('afterbegin', html);
}
}

View File

@ -0,0 +1,100 @@
import { Component } from "../core/component";
import { apiService } from "../services/api.service";
export class PaginationComponent extends Component {
constructor(id, {items}) {
super(id);
this.limit = 5;
this.items = items;
}
async init() {
await this.insertPages();
this.$pages = this.$el.querySelectorAll('li');
this.$el.addEventListener('click', this.buttonHandler.bind(this));
this.$el.querySelector('li').nextElementSibling.classList.add('active');
}
buttonHandler(e) {
e.preventDefault();
if (e.target.dataset.move) {
const value = parseInt(e.target.dataset.move),
target = e.target.parentNode;
this.removeActive();
target.classList.add('active');
this.moveTo(value);
} else if (e.target.tagName.toLowerCase() === 'i') {
const moveType = e.target.parentNode.dataset.type,
value = parseInt(this.$el.dataset.page);
moveType === 'prev' ? this.movePrev(value, this.$pages) : this.moveNext(value, this.$pages);
}
}
updatePage(value) {
this.$el.setAttribute('data-page', value);
}
removeActive() {
this.$pages.forEach(li => li.classList.remove('active'));
}
setActive(li, value) {
li.forEach(li => {const page = parseInt(li.querySelector('a').dataset.move);page === value ? li.classList.add('active') : false;});
}
movePrev(value, li) {
if (value === 1) {
return 0;
} else {
--value;
this.removeActive();
this.setActive(li, value);
this.updatePage(value);
this.items.onShow();
this.items.insertItems(value, this.limit);
this.items.onHide();
}
}
moveTo(value) {
this.updatePage(value);
this.items.onShow();
this.items.insertItems(value, this.limit);
this.items.onHide();
}
moveNext(value, li) {
const length = this.$pages.length - 2;
if (value === length) {
return 0;
} else {
++value;
this.removeActive();
this.setActive(li, value);
this.updatePage(value);
this.items.onShow();
this.items.insertItems(value, this.limit);
this.items.onHide();
}
}
async insertPages() {
const pages = await apiService.getItems(),
count = pages.length / this.limit;
let html = '';
// назад
html += '<li><a class="disabled" href="#" data-type="prev"><i class="material-icons">chevron_left</i></a></li>';
// все страницы
for (let i = 1; i <= count; i++) {
html += `<li><a href="#" data-move="${i}">${i}</a></li>`;
}
// вперед
html += '<li><a class="disabled" href="#" data-type="next"><i class="material-icons">chevron_right</i></a></li>';
this.$el.insertAdjacentHTML('afterbegin', html);
}
}

View File

@ -14,10 +14,12 @@ export class Component {
onHide() {}
hide() {
this.$el ? this.$el.classList.add('hide') : false
this.$el ? this.$el.classList.add('hide') : false;
this.onHide();
}
show() {
this.$el ? this.$el.classList.remove('hide') : false
this.$el ? this.$el.classList.remove('hide') : false;
this.onShow();
}
}

View File

@ -3,10 +3,12 @@ import { CategoriesComponent } from "./components/categories.component.js";
import { editCategoryModal } from "./modals/editCategory.modal.js";
import { ItemsComponent } from "./components/items.component.js";
import { LoaderComponent } from "./components/loader.component.js";
import { PaginationComponent } from "./components/pagination.component.js";
const loader = new LoaderComponent('loader');
const categories = new CategoriesComponent('categories');
const items = new ItemsComponent('items', {loader});
const pagination = new PaginationComponent('pagination', {items});
const editCategory = new editCategoryModal('editCategory', 'edit', 'editCategoryClose');
const materialize = new MaterializeConfig();
console.log('Control-Panel v1.0.0');

View File

@ -38,6 +38,15 @@ class ApiService {
}
}
async getItemsOffset(page, limit) {
try {
const request = `${this.url}/api/items/page/${page}?limit=${limit}`;
return useRequest(request);
} catch (err) {
console.error(err);
}
}
async getItemsOne(category, sorting) {
try {
if (sorting) {