component categories

This commit is contained in:
Sergey Yarkov 2019-12-15 18:26:20 +03:00
parent d8adf40c5c
commit a4a7f14146
15 changed files with 219 additions and 53 deletions

View File

@ -97,6 +97,9 @@ function getItemsRoute(req, res, dbo) {
? res.send(result) ? res.send(result)
: res.send({error: 'На сайте нету категорий'}); : res.send({error: 'На сайте нету категорий'});
}); });
} else if (req.query.icons === 'all') {
const icons = fs.readdirSync('dist/public/img/service-icons');
res.send(icons);
} else if (req.query.category) { } else if (req.query.category) {
dbo.collection('categories').find({title: req.query.category}).toArray((err, result) => { dbo.collection('categories').find({title: req.query.category}).toArray((err, result) => {
res.send(result); res.send(result);
@ -228,10 +231,9 @@ function controlPanelDatabaseRoute(req, res) {
function controlPanelAddCategory(req, res, db) { function controlPanelAddCategory(req, res, db) {
try { try {
const filedata = req.file;
const data = { const data = {
title: req.body.title.toLowerCase().trim(), title: req.body.title.toLowerCase().trim(),
img: filedata.filename, img: req.body.img,
type: req.body.type, type: req.body.type,
format: req.body.format format: req.body.format
} }
@ -246,14 +248,46 @@ function controlPanelDellCategory(req, res, db) {
try { try {
const data = JSON.parse(req.body.category); const data = JSON.parse(req.body.category);
db.collection('categories').deleteOne({"_id": ObjectID(data.id)}); db.collection('categories').deleteOne({"_id": ObjectID(data.id)});
res.redirect('/control-panel/categories');
// Удаляем иконку
const path = `./dist/public/img/service-icons/${data.img}`
try {
fs.unlinkSync(path);
} catch (error) { } catch (error) {
console.log(error); console.log(error);
res.render('main/404');
} }
}
function controlPanelUpdCategory(req, res, db) {
try {
const data = {
id: req.body.id,
title: req.body.title.toLowerCase().trim(),
originalTitle: req.body.originalTitle.toLowerCase().trim(),
img: req.body.img,
type: req.body.type,
format: req.body.format
}
db.collection('categories').updateOne({"_id": ObjectID(data.id)}, {$set: {title: data.title, img: data.img, type: data.type, format: data.format}});
db.collection('items').updateMany({"category": data.originalTitle}, {$set: {category: data.title}});
res.redirect('/control-panel/categories');
} catch (error) {
console.log(error);
res.render('main/404');
}
}
function controlPanelAddIcon(req, res, db) {
try {
res.redirect('/control-panel/categories');
} catch (error) {
console.log(error);
res.render('main/404');
}
}
function controlPanelDellIcon(req, res, db) {
const path = `./dist/public/img/service-icons/${req.body.img}`
try {
fs.unlinkSync(path);
res.redirect('/control-panel/categories'); res.redirect('/control-panel/categories');
} catch (error) { } catch (error) {
console.log(error); console.log(error);
@ -278,4 +312,7 @@ module.exports = function (server, db) {
server.post('/control-panel/categories/create', checkAuthenticated, (req, res) => controlPanelAddCategory(req, res, db)); server.post('/control-panel/categories/create', checkAuthenticated, (req, res) => controlPanelAddCategory(req, res, db));
server.post('/control-panel/categories/delete', checkAuthenticated, (req, res) => controlPanelDellCategory(req, res, db)); server.post('/control-panel/categories/delete', checkAuthenticated, (req, res) => controlPanelDellCategory(req, res, db));
server.post('/control-panel/categories/update', checkAuthenticated, (req, res) => controlPanelUpdCategory(req, res, db));
server.post('/control-panel/categories/addicon', checkAuthenticated, (req, res) => controlPanelAddIcon(req, res, db));
server.post('/control-panel/categories/dellicon', checkAuthenticated, (req, res) => controlPanelDellIcon(req, res, db));
} }

View File

@ -123,16 +123,14 @@ hr {
background-color: #fff; background-color: #fff;
} }
.cart, .c_modal {
.pay {
display: flex; display: flex;
justify-content: center; justify-content: center;
padding-right: 10px; padding-right: 10px;
padding-left: 10px; padding-left: 10px;
} }
.cart-wrap, .c_modal-wrap {
.pay-wrap {
position: fixed; position: fixed;
background: rgba(0, 0, 0, .5); background: rgba(0, 0, 0, .5);
top: 0; top: 0;
@ -143,14 +141,16 @@ hr {
overflow-y: auto; overflow-y: auto;
} }
.cart-content, .c_modal-content {
.pay-content {
background-color: #fff; background-color: #fff;
margin-top: 7rem; margin-top: 7rem;
padding: 25px; padding: 25px;
width: 460px; width: 460px;
min-height: 230px; min-height: 230px;
} }
.c_modal-content.editCategory {
width: 760px;
}
.modal-content__header .small-title { .modal-content__header .small-title {
color: #404751; color: #404751;
@ -163,13 +163,11 @@ hr {
margin-bottom: 15px; margin-bottom: 15px;
} }
.cart-close, .modal-close {
.pay-close {
cursor: pointer; cursor: pointer;
} }
.cart-close i, .modal-close i {
.pay-close i {
color: #8d8d8d; color: #8d8d8d;
} }
@ -682,6 +680,9 @@ footer.main-footer {
.admin-main { .admin-main {
margin-top: 20px; margin-top: 20px;
} }
.admin-main p {
margin-bottom: 1rem;
}
.admin-main h2 { .admin-main h2 {
margin: 23px 0px 20px 0px; margin: 23px 0px 20px 0px;
} }

View File

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

Before

Width:  |  Height:  |  Size: 675 B

After

Width:  |  Height:  |  Size: 675 B

View File

@ -0,0 +1,36 @@
// Edit Category
#editCategory.c_modal-wrap.hide
.container
.row
.c_modal
.c_modal-content.editCategory
.modal-content
.modal-content__header(style="margin-bottom: 1rem;")
h4.small-title Редактирование категории
span#editCategoryClose.modal-close
i.material-icons close
.modal-content__form
form(action="/control-panel/categories/update" method="POST")
.input-field.id
input(style="color: gray;" type="text" name="id" required readonly)
label ID категории
.input-field.originalTitle
input(style="color: gray;" type="text" name="originalTitle" required readonly)
label Старое название категории
.input-field.title
input(type="text" name="title" required)
label Новое название категории
.input-field.type
input(type="text" name="type" required)
label Тип аккаунтов
.input-field.img
select(name="img" id="img" required)
option(value="" disabled selected)
| Выберите иконку
label(for="img") Иконка
.input-field.format
input(type="text" name="format" required)
label Формат аккаунтов
.edit_success
button(type="submit" class="btn green waves-effect" style="width: 100%;height:50px") Редактировать
// Edit Category END

View File

View File

@ -6,6 +6,13 @@ body.has-fixed-sidenav
.row .row
.col.s12 .col.s12
h2 Редактирование категорий h2 Редактирование категорий
p На этой странице есть возможность добавлять новые категории, удалять старые и редактировать существующие.
.col.s12
.card
.card-content
span.card-title Кол-во категорий
.divider
h3#categoriesCount 0
.col.s12 .col.s12
#categories.card #categories.card
.card-content .card-content
@ -14,14 +21,13 @@ body.has-fixed-sidenav
.row .row
form(id="categoryAdd" action="/control-panel/categories/create" method="POST" enctype="multipart/form-data") form(id="categoryAdd" action="/control-panel/categories/create" method="POST" enctype="multipart/form-data")
.input-field.col.l6.s12 .input-field.col.l6.s12
input(id="title" name="title" type="text" data-length="20" required) input(id="title" name="title" type="text" required)
label(for="title") Название категории label(for="title") Название категории
.file-field.input-field.col.l6.s12 #img.input-field.col.l6.s12
.btn.orange select(name="img" id="img" required)
span Иконка option(value="" disabled selected)
input(type="file" name="img" required) | Выберите иконку
.file-path-wrapper label(for="img") Иконка
input(type="text" class="file-path" placeholder="Загрузите иконку в формате .svg")
.input-field.col.l6.s12 .input-field.col.l6.s12
textarea(class="materialize-textarea" type="text" id="type" name="type" required) textarea(class="materialize-textarea" type="text" id="type" name="type" required)
label(for="type") Тип аккаунтов label(for="type") Тип аккаунтов
@ -29,9 +35,20 @@ body.has-fixed-sidenav
input(type="text" id="format" name="format" required) input(type="text" id="format" name="format" required)
label(for="format") Формат аккаунтов label(for="format") Формат аккаунтов
.col.s12 .col.s12
button(type="submit" class="btn green") Добавить категорию button(type="submit" class="btn") Добавить категорию
.divider .divider
.under-block .under-block
.icon-add
h5 Добавить иконку
.row
form(id="iconAdd" action="/control-panel/categories/addicon" method="POST" enctype="multipart/form-data")
.file-field.input-field.col.s12
.btn.orange
span Иконка
input(type="file" name="img" required)
.file-path-wrapper
input(type="text" class="file-path" placeholder="Загрузите иконку в формате .svg")
button(type="submit" class="btn right" style="margin-right: 10px;") Добавить
.category-edit .category-edit
.row .row
#edit.input-field.col.s12 #edit.input-field.col.s12
@ -39,6 +56,16 @@ body.has-fixed-sidenav
option(value="" disabled selected) option(value="" disabled selected)
| Выберите категорию для редактирования | Выберите категорию для редактирования
label Редактирование label Редактирование
.icon-dell
.row
form(id="iconDell" action="/control-panel/categories/dellicon" method="POST")
#imgDell.input-field.col.s12
select(name="img")
option(value="" disabled selected)
| Выберите иконку для удаления
label Удаление иконки
.col.s12
button(type="submit" class="btn red ") Удалить
.category-delete .category-delete
.row .row
form(id="categoryDelete" action="/control-panel/categories/delete" method="POST") form(id="categoryDelete" action="/control-panel/categories/delete" method="POST")
@ -47,9 +74,9 @@ body.has-fixed-sidenav
option(value="" disabled selected) option(value="" disabled selected)
| Выберите категорию для удаления | Выберите категорию для удаления
label Удаление label Удаление
.col.s6 .col.s12
button(type="submit" class="btn red ") Удалить button(type="submit" class="btn red ") Удалить
include ./assets/templates/modals/edit_category.pug
include ./assets/templates/footer.pug include ./assets/templates/footer.pug
include ./assets/scripts.pug include ./assets/scripts.pug

View File

@ -1,13 +1,13 @@
// Cart Modal // Cart Modal
#cart.cart-wrap.hide #cart.c_modal-wrap.hide
.container .container
.row .row
.cart .c_modal
.cart-content .c_modal-content
.modal-content .modal-content
.modal-content__header .modal-content__header
h4.small-title Корзина h4.small-title Корзина
span#cartClose.cart-close span#cartClose.modal-close
i.material-icons close i.material-icons close
#modalList.modal-content__items #modalList.modal-content__items
.modal-content__info .modal-content__info

View File

@ -1,13 +1,13 @@
// Pay Modal // Pay Modal
#pay.pay-wrap.hide #pay.c_modal-wrap.hide
.container .container
.row .row
.pay .c_modal
.pay-content .c_modal-content
.modal-content .modal-content
.modal-content__header .modal-content__header
h4.small-title Оплатить товар h4.small-title Оплатить товар
span#payClose.cart-close span#payClose.modal-close
i.material-icons close i.material-icons close
form(action='#') form(action='#')
.modal-content__fields .modal-content__fields

View File

@ -1,6 +1,7 @@
import { Component } from "../core/component"; import { Component } from "../core/component";
import { apiService } from "../services/api.service"; import { apiService } from "../services/api.service";
import { renderCategories } from "../templates/categories.template"; import { renderCategories } from "../templates/categories.template";
import { renderIcons } from "../templates/icons.template";
export class CategoriesComponent extends Component { export class CategoriesComponent extends Component {
constructor(id) { constructor(id) {
@ -8,9 +9,14 @@ export class CategoriesComponent extends Component {
if (this.$el) { if (this.$el) {
this.$editSelect = this.$el.querySelector('#edit select'); this.$editSelect = this.$el.querySelector('#edit select');
this.$deleteSelect = this.$el.querySelector('#delete select'); this.$deleteSelect = this.$el.querySelector('#delete select');
this.$iconsSelect = this.$el.querySelector('#img select');
this.$dellIconsSelect = this.$el.querySelector('#imgDell select');
this.$dellIconFrom = this.$el.querySelector('#iconDell');
this.$addForm = this.$el.querySelector('#categoryAdd'); this.$addForm = this.$el.querySelector('#categoryAdd');
this.$deleteForm = this.$el.querySelector('#categoryDelete'); this.$deleteForm = this.$el.querySelector('#categoryDelete');
this.$dellIconFrom.addEventListener('submit', this.dellIcon.bind(this));
this.$addForm.addEventListener('submit', this.addCategory.bind(this)); this.$addForm.addEventListener('submit', this.addCategory.bind(this));
this.$deleteForm.addEventListener('submit', this.deleteCategory.bind(this)); this.$deleteForm.addEventListener('submit', this.deleteCategory.bind(this));
this.$editSelect.addEventListener('change', this.insertData); this.$editSelect.addEventListener('change', this.insertData);
@ -19,10 +25,16 @@ export class CategoriesComponent extends Component {
async init() { async init() {
const categories = await apiService.getCategories(); const categories = await apiService.getCategories();
const icons = await apiService.getIcons();
const icons_html = renderIcons(icons);
const html = renderCategories(categories); const html = renderCategories(categories);
document.querySelector('#categoriesCount').textContent = categories.length;
this.$editSelect.insertAdjacentHTML('beforeend', html); this.$editSelect.insertAdjacentHTML('beforeend', html);
this.$deleteSelect.insertAdjacentHTML('beforeend', html); this.$deleteSelect.insertAdjacentHTML('beforeend', html);
this.$iconsSelect.insertAdjacentHTML('beforeend', icons_html);
this.$dellIconsSelect.insertAdjacentHTML('beforeend', icons_html);
M.FormSelect.init(document.querySelectorAll('select')); // Инициализируем все селекты только после их рендера! M.FormSelect.init(document.querySelectorAll('select')); // Инициализируем все селекты только после их рендера!
} }
@ -39,6 +51,14 @@ export class CategoriesComponent extends Component {
const categories = await apiService.getCategories(); const categories = await apiService.getCategories();
const title = this.$deleteForm.elements[0].value.toLowerCase().trim(); const title = this.$deleteForm.elements[0].value.toLowerCase().trim();
const index = categories.map((category) => {return category.title}).indexOf(title); const index = categories.map((category) => {return category.title}).indexOf(title);
index != -1 ? this.$deleteForm.submit() : alert('Выберите категорию.'); index != -1 ? this.$deleteForm.submit() : alert('Выберите категорию для удаления.');
}
async dellIcon(e) {
e.preventDefault();
const icons = await apiService.getIcons();
const currIcon = e.target.elements[0].value;
const index = icons.indexOf(currIcon);
index != -1 ? e.target.submit() : alert('Выберите иконку для удаления.');
} }
} }

View File

@ -3,15 +3,12 @@ export class Modal {
this.$el = document.getElementById(id); this.$el = document.getElementById(id);
this.open = document.getElementById(open); this.open = document.getElementById(open);
this.close = document.getElementById(close); this.close = document.getElementById(close);
this.open ? this.close.addEventListener('click', this.hide.bind(this)) : false;
this.init(); this.init();
} }
init() { init() {}
if (this.open != null) {
this.open.addEventListener('click', openHandler.bind(this));
this.close.addEventListener('click', closeHandler.bind(this));
}
}
show() { show() {
this.$el.classList.remove('hide'); this.$el.classList.remove('hide');
@ -23,11 +20,3 @@ export class Modal {
document.body.style.overflowY = ''; document.body.style.overflowY = '';
} }
} }
function openHandler() {
this.show();
}
function closeHandler() {
this.hide();
}

View File

@ -1,6 +1,8 @@
import { MaterializeConfig } from "./config/materialize.config.js"; import { MaterializeConfig } from "./config/materialize.config.js";
import { CategoriesComponent } from "./components/categories.component.js"; import { CategoriesComponent } from "./components/categories.component.js";
import { editCategoryModal } from "./modals/editCategory.modal.js";
const categories = new CategoriesComponent('categories'); const categories = new CategoriesComponent('categories');
const editCategory = new editCategoryModal('editCategory', 'edit', 'editCategoryClose');
const materialize = new MaterializeConfig(); const materialize = new MaterializeConfig();
console.log('Control-Panel v1.0.0'); console.log('Control-Panel v1.0.0');

View File

@ -0,0 +1,38 @@
import { Modal } from "../core/modal";
import { apiService } from "../services/api.service";
import { renderIcons } from "../templates/icons.template";
export class editCategoryModal extends Modal {
constructor(id, open, close) {
super(id, open, close);
if (this.open) {
this.open.addEventListener('change', this.openHandler.bind(this));
this.$el.querySelector('form').addEventListener('submit', this.updateCategory.bind(this));
}
}
async openHandler(e) {
this.show();
const data = JSON.parse(e.target.value);
this.$el.querySelector('form .id input').value = data.id;
this.$el.querySelector('form .originalTitle input').value = data.title[0].toUpperCase() + data.title.slice(1);
this.$el.querySelector('form .title input').value = data.title[0].toUpperCase() + data.title.slice(1);
this.$el.querySelector('form .type input').value = data.type;
this.$el.querySelector('form .format input').value = data.format;
const icons = await apiService.getIcons();
const icons_html = renderIcons(icons);
this.$el.querySelector('form .img select').insertAdjacentHTML('beforeend', icons_html);
M.FormSelect.init(this.$el.querySelector('form .img select'));
M.updateTextFields();
}
async updateCategory(e) {
e.preventDefault();
const form = this.$el.querySelector('form');
const categories = await apiService.getCategories();
const id = form.elements[0].value.toLowerCase().trim();
const index = categories.map((category) => {return category._id}).indexOf(id);
index != -1 ? form.submit() : alert('Категории с таким ID не существует.');
}
}

View File

@ -52,6 +52,15 @@ class ApiService {
console.error(err); console.error(err);
} }
} }
async getIcons() {
try {
const request = `${this.url}api?token=${API_TOKEN}&icons=all`;
return useRequest(request);
} catch (err) {
console.error(err);
}
}
} }
async function useRequest(request) { async function useRequest(request) {

View File

@ -0,0 +1,7 @@
export function renderIcons(icons) {
let html = '';
icons.forEach(icon => {
html += `<option value='${icon}' data-icon="../img/service-icons/${icon}">${icon}</option>`;
});
return html;
}