Yes, it works
This commit is contained in:
parent
ada7d99c43
commit
fe05d8ddc1
@ -20,7 +20,7 @@
|
||||
"name": "Зимний вечер",
|
||||
"year": "1830",
|
||||
"image": "",
|
||||
"id": 2
|
||||
"id": 1
|
||||
},
|
||||
{
|
||||
"categoriesId": "1",
|
||||
@ -28,7 +28,7 @@
|
||||
"name": "Властителям и судиям",
|
||||
"year": "1780",
|
||||
"image": "",
|
||||
"id": 3
|
||||
"id": 2
|
||||
},
|
||||
{
|
||||
"categoriesId": "1",
|
||||
@ -36,7 +36,7 @@
|
||||
"name": "Exegi monumentum",
|
||||
"year": "23 до н. э.",
|
||||
"image": "",
|
||||
"id": 4
|
||||
"id": 3
|
||||
},
|
||||
{
|
||||
"categoriesId": "2",
|
||||
@ -44,6 +44,14 @@
|
||||
"name": "К бедному поэту",
|
||||
"year": "1796",
|
||||
"image": "",
|
||||
"id": 4
|
||||
},
|
||||
{
|
||||
"categoriesId": "3",
|
||||
"authorsId": "2",
|
||||
"name": "Exegi monumentum",
|
||||
"year": "23 до н. э.",
|
||||
"image": "",
|
||||
"id": 5
|
||||
}
|
||||
],
|
||||
|
@ -42,8 +42,8 @@ export async function getBook(id) {
|
||||
|
||||
// обращение к серверу для создания записи (post)
|
||||
// объект отправляется в теле запроса (body)
|
||||
export async function createLine(item, name, authorId, year, image) {
|
||||
const itemObject = createLineObject(item, name, authorId, year, image);
|
||||
export async function addBook(categoriesId, name, authorsId, year, image) {
|
||||
const itemObject = createBookObject(categoriesId, name, authorsId, year, image);
|
||||
|
||||
const options = {
|
||||
method: "POST",
|
||||
@ -54,7 +54,7 @@ export async function createLine(item, name, authorId, year, image) {
|
||||
},
|
||||
};
|
||||
|
||||
const response = await fetch(`${serverUrl}/lines`, options);
|
||||
const response = await fetch(`${serverUrl}/books`, options);
|
||||
if (!response.ok) {
|
||||
throw response.statusText;
|
||||
}
|
||||
@ -64,8 +64,8 @@ export async function createLine(item, name, authorId, year, image) {
|
||||
// обращение к серверу для обновления записи по id (put)
|
||||
// объект отправляется в теле запроса (body)
|
||||
// id передается в качестве части пути URL get-запроса
|
||||
export async function updateLine(id, item, name, authorId, year, image) {
|
||||
const itemObject = createLineObject(item, name, authorId, year, image);
|
||||
export async function updateBook(id, categoriesId, name, authorsId, year, image) {
|
||||
const itemObject = createBookObject(categoriesId, name, authorsId, year, image);
|
||||
|
||||
const options = {
|
||||
method: "PUT",
|
||||
@ -76,7 +76,7 @@ export async function updateLine(id, item, name, authorId, year, image) {
|
||||
},
|
||||
};
|
||||
|
||||
const response = await fetch(`${serverUrl}/lines/${id}`, options);
|
||||
const response = await fetch(`${serverUrl}/books/${id}`, options);
|
||||
if (!response.ok) {
|
||||
throw response.statusText;
|
||||
}
|
||||
@ -90,7 +90,7 @@ export async function deleteLine(id) {
|
||||
method: "DELETE",
|
||||
};
|
||||
|
||||
const response = await fetch(`${serverUrl}/lines/${id}`, options);
|
||||
const response = await fetch(`${serverUrl}/books/${id}`, options);
|
||||
if (!response.ok) {
|
||||
throw response.statusText;
|
||||
}
|
||||
@ -98,11 +98,11 @@ export async function deleteLine(id) {
|
||||
}
|
||||
|
||||
// функция возвращает объект нужной структуры для отправки на сервер
|
||||
function createLineObject(item, name, authorId, year, image) {
|
||||
function createBookObject(categoriesId, name, authorsId, year, image) {
|
||||
return {
|
||||
itemsId: item,
|
||||
categoriesId,
|
||||
authorsId,
|
||||
name,
|
||||
authorId,
|
||||
year,
|
||||
image,
|
||||
};
|
||||
|
@ -1,27 +1,26 @@
|
||||
// модуль для работы с элементами управления
|
||||
|
||||
// объект для удобного получения элементов
|
||||
// при обращении к атрибуту объекта вызывается
|
||||
// нужная функция для поиска элемента
|
||||
// при обращении к атрибуту объекта вызывается нужная функция для поиска элемента
|
||||
export const cntrls = {
|
||||
button: document.getElementById("items-add"),
|
||||
table: document.querySelector("#items-table tbody"),
|
||||
button: document.getElementById("items-add"),
|
||||
form: document.getElementById("items-form"),
|
||||
lineId: document.getElementById("items-line-id"),
|
||||
itemsType: document.getElementById("item"),
|
||||
name: document.getElementById("name"),
|
||||
authorType: document.getElementById("author"),
|
||||
year: document.getElementById("year"),
|
||||
image: document.getElementById("image"),
|
||||
categoryInput: document.getElementById("item"),
|
||||
nameInput: document.getElementById("name"),
|
||||
authorInput: document.getElementById("author"),
|
||||
yearInput: document.getElementById("year"),
|
||||
imageInput: document.getElementById("image"),
|
||||
imagePreview: document.getElementById("image-preview"),
|
||||
};
|
||||
|
||||
// Дефолтное превью
|
||||
export const imagePlaceholder = "https://via.placeholder.com/200";
|
||||
|
||||
// функция создает тег option для select
|
||||
// функция создает тег option для select (для списков категорий, авторов и т. д.)
|
||||
// <option value="" selected>name</option>
|
||||
export function createItemsOption(name, value = "", isSelected = false) {
|
||||
export function createOption(name, value = "", isSelected = false) {
|
||||
const option = document.createElement("option");
|
||||
option.value = value || "";
|
||||
option.selected = isSelected;
|
||||
@ -37,7 +36,6 @@ export function createItemsOption(name, value = "", isSelected = false) {
|
||||
function createTableAnchor(icon, callback) {
|
||||
const i = document.createElement("i");
|
||||
i.classList.add("fa-solid", icon);
|
||||
|
||||
const a = document.createElement("a");
|
||||
a.href = "#";
|
||||
a.appendChild(i);
|
||||
@ -47,7 +45,6 @@ function createTableAnchor(icon, callback) {
|
||||
event.stopPropagation();
|
||||
callback();
|
||||
};
|
||||
|
||||
const td = document.createElement("td");
|
||||
td.appendChild(a);
|
||||
return td;
|
||||
|
@ -2,25 +2,25 @@
|
||||
// модуль с логикой
|
||||
|
||||
import {
|
||||
createLine, deleteLine, getAllCategories, getAllAuthors, getAllBooks, getBook, updateLine,
|
||||
addBook, deleteLine, getAllCategories, getAllAuthors, getAllBooks, getBook, updateBook,
|
||||
} from "./lines-rest-api";
|
||||
import {
|
||||
cntrls, createItemsOption, createTableRow, imagePlaceholder,
|
||||
cntrls, createOption, createTableRow, imagePlaceholder,
|
||||
} from "./lines-ui";
|
||||
|
||||
// функция для заполнения списков авторов и категорий книг
|
||||
async function drawLists() {
|
||||
async function drawSelects() {
|
||||
const data = await getAllCategories();
|
||||
const authors = await getAllAuthors();
|
||||
cntrls.itemsType.innerHTML = "";
|
||||
cntrls.authorType.innerHTML = "";
|
||||
cntrls.itemsType.appendChild(createItemsOption("Выберите значение", "", true));
|
||||
cntrls.authorType.appendChild(createItemsOption("Выберите значение", "", true));
|
||||
cntrls.categoryInput.innerHTML = "";
|
||||
cntrls.authorInput.innerHTML = "";
|
||||
cntrls.categoryInput.appendChild(createOption("Выберите значение", "", true));
|
||||
cntrls.authorInput.appendChild(createOption("Выберите значение", "", true));
|
||||
data.forEach((item) => {
|
||||
cntrls.itemsType.appendChild(createItemsOption(item.name, item.id));
|
||||
cntrls.categoryInput.appendChild(createOption(item.name, item.id));
|
||||
});
|
||||
authors.forEach((author) => {
|
||||
cntrls.authorType.appendChild(createItemsOption(author.name, author.id));
|
||||
cntrls.authorInput.appendChild(createOption(author.name, author.id));
|
||||
});
|
||||
}
|
||||
|
||||
@ -47,7 +47,7 @@ async function drawTable() {
|
||||
async function addLine(item, name, authorId, year, image) {
|
||||
console.info("Try to add item");
|
||||
// вызов метода REST API для добавления записи
|
||||
const data = await createLine(item, name, authorId, year, image);
|
||||
const data = await addBook(item, name, authorId, year, image);
|
||||
console.info("Added");
|
||||
console.info(data);
|
||||
// загрузка и заполнение table
|
||||
@ -57,7 +57,7 @@ async function addLine(item, name, authorId, year, image) {
|
||||
async function editLine(id, item, name, authorId, year, image) {
|
||||
console.info("Try to update item");
|
||||
// вызов метода REST API для обновления записи
|
||||
const data = await updateLine(id, item, name, authorId, year, image);
|
||||
const data = await updateBook(id, item, name, authorId, year, image);
|
||||
console.info("Updated");
|
||||
console.info(data);
|
||||
// загрузка и заполнение table
|
||||
@ -77,6 +77,86 @@ async function removeLine(id) {
|
||||
drawTable();
|
||||
}
|
||||
|
||||
// функция для обновления блока с превью выбранного изображения
|
||||
async function updateImagePreview() {
|
||||
// получение выбранного файла
|
||||
// возможен выбор нескольких файлов, поэтому необходимо получить только первый
|
||||
const file = cntrls.imageInput.files[0];
|
||||
// чтение содержимого файла в виде base64 строки
|
||||
const fileContent = await readFile(file);
|
||||
console.info("base64 ", fileContent);
|
||||
// обновление атрибута src для тега img с id image-preview
|
||||
cntrls.imagePreview.src = fileContent;
|
||||
}
|
||||
|
||||
// Функция для обработки создания и редактирования элементов таблицы через страницу
|
||||
export async function linesPageForm() {
|
||||
console.info("linesPageForm");
|
||||
drawSelects();
|
||||
drawTable();
|
||||
const goBack = () => location.assign("./admin-page.html");
|
||||
cntrls.imageInput.addEventListener("change", () => updateImagePreview());
|
||||
// получение параметров GET-запроса из URL
|
||||
// параметры перечислены после символа ? (?id=1&color=black&...)
|
||||
const urlParams = new URLSearchParams(location.search);
|
||||
// получение значения конкретного параметра (id)
|
||||
// указан только при редактировании
|
||||
const currentId = urlParams.get("id");
|
||||
// если id задан
|
||||
if (currentId) {
|
||||
try {
|
||||
const book = await getBook(currentId);
|
||||
cntrls.categoryInput.value = book.itemsId;
|
||||
cntrls.nameInput.value = book.name;
|
||||
cntrls.authorInput.value = book.authorId;
|
||||
cntrls.yearInput.value = book.year;
|
||||
cntrls.imagePreview.src = book.image ? book.image : imagePlaceholder;
|
||||
} catch {
|
||||
goBack();
|
||||
}
|
||||
}
|
||||
cntrls.form.addEventListener("submit", async (event) => {
|
||||
console.info("Form onSubmit");
|
||||
// отключение стандартного поведения формы при отправке
|
||||
// при отправке страница обновляется и JS перестает работать
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
// если форма не прошла валидацию, то ничего делать не нужно
|
||||
if (!cntrls.form.checkValidity()) {
|
||||
return;
|
||||
}
|
||||
let imageBase64 = "";
|
||||
if (cntrls.imagePreview.src !== imagePlaceholder) {
|
||||
// Загрузка содержимого атрибута src тэга img с id image-preview
|
||||
// Здесь выполняется HTTP запрос с типом GET
|
||||
const result = await fetch(cntrls.imagePreview.src);
|
||||
// Получение из HTTP-ответа бинарного содержимого
|
||||
const blob = await result.blob();
|
||||
// Получение base64 строки для файла
|
||||
imageBase64 = await readFile(blob);
|
||||
}
|
||||
if (!currentId) {
|
||||
await addLine(
|
||||
cntrls.categoryInput.value,
|
||||
cntrls.nameInput.value,
|
||||
cntrls.authorInput.value,
|
||||
cntrls.yearInput.value,
|
||||
imageBase64,
|
||||
);
|
||||
} else {
|
||||
await editLine(
|
||||
currentId,
|
||||
cntrls.categoryInput.value,
|
||||
cntrls.nameInput.value,
|
||||
cntrls.authorInput.value,
|
||||
cntrls.yearInput.value,
|
||||
imageBase64,
|
||||
);
|
||||
}
|
||||
goBack();
|
||||
});
|
||||
}
|
||||
|
||||
// функция для получения содержимого файла в виде base64 строки
|
||||
// https://ru.wikipedia.org/wiki/Base64
|
||||
async function readFile(file) {
|
||||
@ -106,117 +186,3 @@ async function readFile(file) {
|
||||
reader.readAsDataURL(file);
|
||||
});
|
||||
}
|
||||
|
||||
// функция для обновления блока с превью выбранного изображения
|
||||
async function updateImagePreview() {
|
||||
// получение выбранного файла
|
||||
// возможен выбор нескольких файлов, поэтому необходимо получить только первый
|
||||
const file = cntrls.image.files[0];
|
||||
// чтение содержимого файла в виде base64 строки
|
||||
const fileContent = await readFile(file);
|
||||
console.info("base64 ", fileContent);
|
||||
// обновление атрибута src для тега img с id image-preview
|
||||
cntrls.imagePreview.src = fileContent;
|
||||
}
|
||||
|
||||
// Функция для обработки создания и редактирования элементов таблицы через страницу page-edit.html
|
||||
// Если хотите делать через модальное окно, то удалите эту функцию
|
||||
export async function linesPageForm() {
|
||||
console.info("linesPageForm");
|
||||
|
||||
// загрузка и заполнение select со списком товаров
|
||||
drawLists();
|
||||
// загрузка и заполнение table
|
||||
drawTable();
|
||||
|
||||
// func1 = (id) => {} аналогично function func1(id) {}
|
||||
const goBack = () => location.assign("./admin-page.html");
|
||||
|
||||
// Вызов функции обновления превью изображения при возникновении
|
||||
// события onchange в тэге input с id image
|
||||
cntrls.image.addEventListener("change", () => updateImagePreview());
|
||||
|
||||
// получение параметров GET-запроса из URL
|
||||
// параметры перечислены после символа ? (?id=1&color=black&...)
|
||||
const urlParams = new URLSearchParams(location.search);
|
||||
|
||||
// получение значения конкретного параметра (id)
|
||||
// указан только при редактировании
|
||||
const currentId = urlParams.get("id");
|
||||
// если id задан
|
||||
if (currentId) {
|
||||
try {
|
||||
// вызов метода REST API для получения записи по первичному ключу(id)
|
||||
const line = await getBook(currentId);
|
||||
// заполнение формы для редактирования
|
||||
cntrls.itemsType.value = line.itemsId;
|
||||
cntrls.name.value = line.name;
|
||||
cntrls.authorType.value = line.authorId;
|
||||
cntrls.year.value = line.year;
|
||||
// заполнение превью
|
||||
// Если пользователь выбрал изображение, то оно загружается
|
||||
// в тэг image с id image - preview
|
||||
// иначе устанавливается заглушка, адрес которой указан в imagePlaceholder
|
||||
cntrls.imagePreview.src = line.image ? line.image : imagePlaceholder;
|
||||
} catch {
|
||||
// в случае ошибки происходит возврат к admin-page
|
||||
goBack();
|
||||
}
|
||||
}
|
||||
|
||||
// обработчик события отправки формы
|
||||
// возникает при нажатии на кнопку (button) с типом submit
|
||||
// кнопка должна находится внутри тега form
|
||||
cntrls.form.addEventListener("submit", async (event) => {
|
||||
console.info("Form onSubmit");
|
||||
// отключение стандартного поведения формы при отправке
|
||||
// при отправке страница обновляется и JS перестает работать
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
// если форма не прошла валидацию, то ничего делать не нужно
|
||||
if (!cntrls.form.checkValidity()) {
|
||||
return;
|
||||
}
|
||||
|
||||
let imageBase64 = "";
|
||||
// Получение выбранного пользователем изображения в виде base64 строки
|
||||
// Если пользователь ничего не выбрал, то не нужно сохранять в БД
|
||||
// дефолтное изображение
|
||||
if (cntrls.imagePreview.src !== imagePlaceholder) {
|
||||
// Загрузка содержимого атрибута src тэга img с id image-preview
|
||||
// Здесь выполняется HTTP запрос с типом GET
|
||||
const result = await fetch(cntrls.imagePreview.src);
|
||||
// Получение из HTTP-ответа бинарного содержимого
|
||||
const blob = await result.blob();
|
||||
// Получение base64 строки для файла
|
||||
// Здесь выполняется Promise из функции readFile
|
||||
// Promise позволяет писать линейный код для работы с асинхронными методами
|
||||
// без использования обработчиков (callback) с помощью await
|
||||
imageBase64 = await readFile(blob);
|
||||
}
|
||||
|
||||
// если значение параметра запроса не задано,
|
||||
// то необходимо выполнить добавление записи
|
||||
// иначе обновление записи
|
||||
if (!currentId) {
|
||||
await addLine(
|
||||
cntrls.itemsType.value,
|
||||
cntrls.name.value,
|
||||
cntrls.authorType.value,
|
||||
cntrls.year.value,
|
||||
imageBase64,
|
||||
);
|
||||
} else {
|
||||
await editLine(
|
||||
currentId,
|
||||
cntrls.itemsType.value,
|
||||
cntrls.name.value,
|
||||
cntrls.authorType.value,
|
||||
cntrls.year.value,
|
||||
imageBase64,
|
||||
);
|
||||
}
|
||||
// возврат к странице admin-page
|
||||
goBack();
|
||||
});
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user