icons component

This commit is contained in:
Sergey Yarkov 2019-12-30 14:02:57 +03:00
parent 2fa5c40bd3
commit 292f8cadb6
13 changed files with 177 additions and 62 deletions

View File

@ -52,6 +52,19 @@ module.exports = function(server, db) {
res.render('main/404'); res.render('main/404');
} }
}); });
server.get('/control-panel/icons', checkAuthenticated, async (req, res) => {
try {
res.render('admin/icons', {
name: req.user.name,
email: req.user.email,
title: 'Digital-Store | Категории',
host: req.headers.host,
pageName: ['Иконки', 'icons']
});
} catch (error) {
res.render('main/404');
}
});
server.get('/control-panel/content', checkAuthenticated, (req, res) => { server.get('/control-panel/content', checkAuthenticated, (req, res) => {
try { try {
res.render('admin/content', { res.render('admin/content', {
@ -114,6 +127,7 @@ module.exports = function(server, db) {
db.collection('categories').deleteOne({"_id": ObjectID(data.id)}); db.collection('categories').deleteOne({"_id": ObjectID(data.id)});
res.redirect('/control-panel/categories'); res.redirect('/control-panel/categories');
} catch (error) { } catch (error) {
console.log(error);
res.render('main/404'); res.render('main/404');
} }
}); });
@ -134,24 +148,60 @@ module.exports = function(server, db) {
res.render('main/404'); res.render('main/404');
} }
}); });
server.post('/control-panel/categories/addicon', checkAuthenticated, (req, res) => {
// иконки
server.post('/control-panel/icons/create', checkAuthenticated, (req, res) => {
try { try {
res.redirect('/control-panel/categories'); res.redirect('/control-panel/icons');
} catch (error) { } catch (error) {
res.render('main/404'); res.render('main/404');
} }
}); });
server.post('/control-panel/categories/dellicon', checkAuthenticated, (req, res) => { server.post('/control-panel/icons/delete', checkAuthenticated, (req, res) => {
const path = `./dist/public/img/service-icons/${req.body.img}` const path = `./dist/public/img/service-icons/${req.body.img}`
try { try {
fs.unlinkSync(path); fs.unlinkSync(path);
res.redirect('/control-panel/categories'); res.redirect('/control-panel/icons');
} catch (error) { } catch (error) {
res.render('main/404'); res.render('main/404');
} }
}); });
// товары // товары
server.post('/control-panel/items/create', checkAuthenticated, (req, res) => {
try {
// документ с информацией товара для отдачи клиенту
const item = {
_id: new ObjectID(),
title: req.body.title,
count: req.body.data.split(',').length,
price: parseFloat(req.body.price),
category: JSON.parse(req.body.category).title,
description: req.body.description,
date: new Date()
}
// документ куда мы записываем данные товара
const info = {
_id: item._id,
title: item.title,
data: req.body.data.split(',')
}
db.collection('info').insertOne(info);
db.collection('items').insertOne(item);
res.redirect('/control-panel/items');
} catch (error) {
res.render('main/404');
}
});
server.post('/control-panel/items/delete', checkAuthenticated, (req, res) => {
try {
db.collection('items').deleteOne({"_id": ObjectID(req.body.id)});
res.redirect('/control-panel/items');
} catch (error) {
res.render('main/404');
}
});
server.post('/control-panel/items/update', checkAuthenticated, (req, res) => { server.post('/control-panel/items/update', checkAuthenticated, (req, res) => {
try { try {
const data = { const data = {
@ -167,12 +217,4 @@ module.exports = function(server, db) {
res.render('main/404'); res.render('main/404');
} }
}); });
server.post('/control-panel/items/delete', checkAuthenticated, (req, res) => {
try {
db.collection('items').deleteOne({"_id": ObjectID(req.body.id)});
res.redirect('/control-panel/items');
} catch (error) {
res.render('main/404');
}
});
} }

View File

@ -697,6 +697,12 @@ footer.main-footer {
.admin-header nav.navbar { .admin-header nav.navbar {
padding-left: 10px; padding-left: 10px;
} }
.card .card-content {
padding: 0;
}
.card {
padding: 24px;
}
.card .card-content .card-title { .card .card-content .card-title {
font-size: 16px; font-size: 16px;
} }
@ -761,9 +767,9 @@ div.table > table > tbody > tr > td:nth-child(7) > button.btn.orange {
.sidenav .collapsible-body>ul:not(.collapsible)>li.active a, .sidenav.sidenav-fixed .collapsible-body>ul:not(.collapsible)>li.active a, .sidenav.sidenav-fixed .collapsible-body>ul:not(.collapsible)>li.active i { .sidenav .collapsible-body>ul:not(.collapsible)>li.active a, .sidenav.sidenav-fixed .collapsible-body>ul:not(.collapsible)>li.active a, .sidenav.sidenav-fixed .collapsible-body>ul:not(.collapsible)>li.active i {
color: #f6f6f6; color: #f6f6f6;
} }
.category-add h5, .category-delete h5 { .card h5 {
margin-top: 2rem; margin-top: 2rem;
margin-bottom: 1rem; margin-bottom: 2rem;
} }
.select-dropdown { .select-dropdown {
max-height: 200px; max-height: 200px;

View File

@ -47,6 +47,10 @@ header.admin-header
a(href='http://'+host+'/control-panel/categories') a(href='http://'+host+'/control-panel/categories')
i.material-icons category i.material-icons category
| Категории | Категории
li(data-page="icons")
a(href='http://'+host+'/control-panel/icons')
i.material-icons add_photo_alternate
| Иконки
li(data-page="content") li(data-page="content")
a(href='http://'+host+'/control-panel/content') a(href='http://'+host+'/control-panel/content')
i.material-icons visibility i.material-icons visibility

View File

@ -19,7 +19,7 @@
label(for="title") Новое название товара label(for="title") Новое название товара
.input-field .input-field
input.price(id="price" type="text" name="price" required) input.price(id="price" type="text" name="price" required)
label(for="price") Цена label(for="price") Цена товара ₽
.input-field .input-field
textarea.description(id="description" class="materialize-textarea" type="text" name="description") textarea.description(id="description" class="materialize-textarea" type="text" name="description")
label(for="description") Описание товара label(for="description") Описание товара

View File

@ -38,17 +38,6 @@ body.has-fixed-sidenav
button(type="submit" class="btn") Добавить категорию button(type="submit" class="btn") Добавить категорию
.divider .divider
.under-block .under-block
.icon-add
h5 Добавить иконку
.row
form(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
.input-field.col.s12 .input-field.col.s12
@ -56,16 +45,6 @@ body.has-fixed-sidenav
option(value="" disabled selected) option(value="" disabled selected)
| Выберите категорию для редактирования | Выберите категорию для редактирования
label Редактирование категории label Редактирование категории
.icon-dell
.row
form(id="dellIcon" action="/control-panel/categories/dellicon" method="POST")
.input-field.col.s12
select#dellIcon_select(name="img")
option(value="" disabled selected)
| Выберите иконку для удаления
label Удаление иконки
.col.s12
button(type="submit" class="btn red ") Удалить
.category-delete .category-delete
.row .row
form(id="dellCategory" action="/control-panel/categories/delete" method="POST") form(id="dellCategory" action="/control-panel/categories/delete" method="POST")

35
dist/views/admin/icons.pug vendored Normal file
View File

@ -0,0 +1,35 @@
include ./assets/head.pug
body.has-fixed-sidenav
include ./assets/templates/header.pug
main.admin-main
.container
.row
.col.s12
h2 Редактирование иконок
.col.s12
#icons.card
.card-content
.icon-add
h5 Добавить иконку
.row
form(action="/control-panel/icons/create" 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;") Добавить
.icon-dell
h5 Удалить иконку
.row
form(id="dellIcon" action="/control-panel/icons/delete" method="POST")
.input-field.col.s12
select#selectIcons(name="img")
option(value="" disabled selected)
| Выберите иконку для удаления
.col.s12
button(type="submit" class="btn red right") Удалить
include ./assets/templates/footer.pug
include ./assets/scripts.pug

View File

@ -34,6 +34,30 @@ body.has-fixed-sidenav
#loader.progress #loader.progress
.indeterminate .indeterminate
ul#pagination.pagination.center(data-page="1") ul#pagination.pagination.center(data-page="1")
.divider
.items-add
h5 Добавить новый товар
.row
form(action="/control-panel/items/create" method="POST")
.input-field.col.l6.s12
input(id="title" type="text" name="title")
label(for="title") Название товара
.input-field.col.l6.s12
input(id="price" type="text" name="price")
label(for="price") Цена товара ₽
.input-field.col.l6.s12
textarea(id="description" class="materialize-textarea" type="text" name="description")
label(for="description") Описание товара
.input-field.col.l6.s12
select#selectCategories(name="category")
option(value="" disabled selected)
| Выберите категорию
label Категория товара
.input-field.col.s12
textarea(class="materialize-textarea" type="text" placeholder="Пречеслите аккаунты в вашем формате через запятую." name="data")
label Данные товара
.col.s12
button(type="submit" class="btn") Добавить товар
include ./assets/templates/modals/delete_item.pug include ./assets/templates/modals/delete_item.pug
include ./assets/templates/modals/edit_item.pug include ./assets/templates/modals/edit_item.pug

View File

@ -13,30 +13,24 @@ export class CategoriesComponent extends Component {
this.$editSelect = this.$el.querySelector('#editCategory_select'); // редактирование категории this.$editSelect = this.$el.querySelector('#editCategory_select'); // редактирование категории
this.$dellSelect = this.$el.querySelector('#delete_select'); // удаление категории this.$dellSelect = this.$el.querySelector('#delete_select'); // удаление категории
this.$iconsSelect = this.$el.querySelector('#icons_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.$addForm = this.$el.querySelector('#addCategory'); // добавление категории
this.$dellForm = this.$el.querySelector('#dellCategory'); // удаление категории this.$dellForm = this.$el.querySelector('#dellCategory'); // удаление категории
// добавим ивенты на наши формы // добавим ивенты на наши формы
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.$dellForm.addEventListener('submit', this.deleteCategory.bind(this)); this.$dellForm.addEventListener('submit', this.deleteCategory.bind(this));
} }
async init() { async init() {
const categories = await apiService.getCategories(), const categories = await apiService.getCategories(),
icons = await apiService.getIcons(), icons = await apiService.getIcons();
icons_html = renderIcons(icons),
categories_html = renderCategories(categories);
this.$editSelect.insertAdjacentHTML('beforeend', categories_html); this.$editSelect.insertAdjacentHTML('beforeend', renderCategories(categories));
this.$dellSelect.insertAdjacentHTML('beforeend', categories_html); this.$dellSelect.insertAdjacentHTML('beforeend', renderCategories(categories));
this.$iconsSelect.insertAdjacentHTML('beforeend', icons_html); this.$iconsSelect.insertAdjacentHTML('beforeend', renderIcons(icons));
this.$dellIconsSelect.insertAdjacentHTML('beforeend', icons_html); M.FormSelect.init(document.querySelectorAll('select'));
M.FormSelect.init(document.querySelectorAll('select')); // Инициализируем все селекты только после их рендера!
} }
async addCategory(e) { async addCategory(e) {
@ -56,13 +50,4 @@ export class CategoriesComponent extends Component {
index != -1 ? this.$dellForm.submit() : alert('Выберите категорию для удаления.'); index != -1 ? this.$dellForm.submit() : alert('Выберите категорию для удаления.');
} }
async dellIcon(e) {
e.preventDefault();
const icons = await apiService.getIcons(),
currIcon = e.target.elements[0].value,
index = icons.indexOf(currIcon);
index != -1 ? e.target.submit() : alert('Выберите иконку для удаления.');
}
} }

View File

@ -0,0 +1,31 @@
import { Component } from "../core/component";
import { apiService } from "../services/api.service";
import { renderIcons } from "../templates/icons.template";
export class IconsComponent extends Component {
constructor(id) {
super(id);
}
setElems() {
this.$icons = this.$el.querySelector('#selectIcons');
this.$delete = this.$el.querySelector('#dellIcon');
this.$delete.addEventListener('submit', this.dellIcon.bind(this));
}
async init() {
const icons = await apiService.getIcons();
this.$icons.insertAdjacentHTML('beforeend', renderIcons(icons));
M.FormSelect.init(this.$icons);
}
async dellIcon(e) {
e.preventDefault();
const icons = await apiService.getIcons(),
currIcon = e.target.elements[0].value,
index = icons.indexOf(currIcon);
index != -1 ? e.target.submit() : alert('Выберите иконку для удаления.');
}
}

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 { renderItems } from "../templates/items.template"; import { renderItems } from "../templates/items.template";
import { renderCategories } from "../templates/categories.template";
export class ItemsComponent extends Component { export class ItemsComponent extends Component {
constructor(id, {pagination}, {search}) { constructor(id, {pagination}, {search}) {
@ -9,11 +10,19 @@ export class ItemsComponent extends Component {
this.search = search; this.search = search;
} }
setElems() {
this.$categories = this.$el.querySelector('#selectCategories');
}
async init() { async init() {
const items = await apiService.getItems(); const items = await apiService.getItems(),
categories = await apiService.getCategories();
this.$table = this.$el.querySelector('table tbody'); this.$table = this.$el.querySelector('table tbody');
this.search.initialize(this.$table, this.getItemsByText); this.search.initialize(this.$table, this.getItemsByText);
this.pagination.initialize(items.length, this.$table, this.getItemsByPage); this.pagination.initialize(items.length, this.$table, this.getItemsByPage);
this.$categories.insertAdjacentHTML('beforeend', renderCategories(categories));
M.FormSelect.init(this.$categories);
} }
async getItemsByText(text) { async getItemsByText(text) {

View File

@ -90,8 +90,4 @@ export class PaginationComponent extends Component {
html += '<li><a class="disabled" href="#" data-type="next"><i class="material-icons">chevron_right</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); this.$el.insertAdjacentHTML('afterbegin', html);
} }
hide() {
this.$el.classList.add('hide');
}
} }

View File

@ -7,11 +7,13 @@ import { PaginationComponent } from "./components/pagination.component.js";
import { editItemModal } from "./modals/editItem.modal.js"; import { editItemModal } from "./modals/editItem.modal.js";
import { deleteItemModal } from "./modals/deleteItem.modal.js"; import { deleteItemModal } from "./modals/deleteItem.modal.js";
import { SearchComponent } from "./components/search.component.js"; import { SearchComponent } from "./components/search.component.js";
import { IconsComponent } from "./components/icons.component.js";
const loader = new LoaderComponent('loader'); const loader = new LoaderComponent('loader');
const pagination = new PaginationComponent('pagination', {loader}); const pagination = new PaginationComponent('pagination', {loader});
const search = new SearchComponent('search', {loader}); const search = new SearchComponent('search', {loader});
const categories = new CategoriesComponent('categories'); const categories = new CategoriesComponent('categories');
const icons = new IconsComponent('icons');
const items = new ItemsComponent('items', {pagination}, {search}); const items = new ItemsComponent('items', {pagination}, {search});
const editCategory = new editCategoryModal('editCategoryModal', 'editCategory_select', 'editCategoryClose'); const editCategory = new editCategoryModal('editCategoryModal', 'editCategory_select', 'editCategoryClose');

View File

@ -16,16 +16,18 @@ export class deleteItemModal extends Modal {
setElems() { setElems() {
this.$content = this.$el.querySelector('.modal-content__form p'); this.$content = this.$el.querySelector('.modal-content__form p');
this.$button = this.$el.querySelector('.delete-item');
} }
openHandler(e) { openHandler(e) {
const data = JSON.parse(e.target.parentNode.parentNode.dataset.info); const data = JSON.parse(e.target.parentNode.parentNode.dataset.info);
this.$content.innerHTML = `Вы действительно хотите удалить товар: <br> "${data.title}"?`; this.$content.innerHTML = `Вы действительно хотите удалить товар: <br> "${data.title}"?`;
this.$el.querySelector('.delete-item').onclick = this.deleteHandler.bind(this, data.id); this.$button.onclick = this.deleteHandler.bind(this, data.id);
} }
async deleteHandler(id) { async deleteHandler(id) {
try { try {
this.$button.classList.add('hide');
this.$content.innerHTML = '<div class="progress"><div class="indeterminate"></div></div>' this.$content.innerHTML = '<div class="progress"><div class="indeterminate"></div></div>'
await axios.post('/control-panel/items/delete', {id}); await axios.post('/control-panel/items/delete', {id});
alert('Товар был успешно удален.'); alert('Товар был успешно удален.');