Internet_Programming_PIbd-2.../js/lines.js
2023-12-08 22:40:11 +04:00

367 lines
14 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* eslint-disable import/prefer-default-export */
// модуль с логикой
import {
createLine, deleteLine, getAllCategoryTypes, getAllLines, getLine, updateLine,
} from "./lines-rest-api";
import {
cntrls, createCategoriesOption, createTableRow, imagePlaceholder, createCatalogItem,
} from "./lines-ui";
async function drawCategoriesSelect() {
// вызов метода REST API для получения списка категорий каталога
const data = await getAllCategoryTypes();
// очистка содержимого select
// удаляется все, что находится между тегами <select></select>
// но не атрибуты
if (cntrls.сategoriesType) {
cntrls.сategoriesType.innerHTML = "";
// пустое значение
cntrls.сategoriesType.appendChild(createCategoriesOption("Выберите значение", "", true));
// цикл по результату ответа от сервера
data.forEach((category) => {
cntrls.сategoriesType.appendChild(createCategoriesOption(category.name, category.id));
});
}
}
async function drawLinesTable() {
console.info("Try to load data");
if (!cntrls.table) {
return;
}
// вызов метода REST API для получения всех записей
const data = await getAllLines();
// очистка содержимого table
// удаляется все, что находится между тегами <table></table>
// но не атрибуты
cntrls.table.innerHTML = "";
// цикл по результату ответа от сервера
// используется лямбда-выражение
// (item, index) => {} аналогично function(item, index) {}
data.forEach((item, index) => {
cntrls.table.appendChild(
createTableRow(
item,
index,
// функции передаются в качестве параметра
// это очень удобно, так как аргументы функций доступны только
// в данном месте кода и не передаются в сервисные модули
() => location.assign(`add-item.html?id=${item.id}`),
() => removeLine(item.id),
),
);
});
}
async function addLine(
title,
author,
price,
count,
descrition,
annotation,
itemId,
publisher,
series,
publicationYear,
pagesNum,
size,
coverType,
circulation,
weight,
category,
image,
) {
console.info("Try to add item");
// вызов метода REST API для добавления записи
const data = await createLine(
title,
author,
price,
count,
descrition,
annotation,
itemId,
publisher,
series,
publicationYear,
pagesNum,
size,
coverType,
circulation,
weight,
category,
image,
);
console.info("Added");
console.info(data);
// загрузка и заполнение table
drawLinesTable();
}
async function editLine(
id,
title,
author,
price,
count,
descrition,
annotation,
itemId,
publisher,
series,
publicationYear,
pagesNum,
size,
coverType,
circulation,
weight,
category,
image,
) {
console.info("Try to update item");
// вызов метода REST API для обновления записи
const data = await updateLine(
id,
title,
author,
price,
count,
descrition,
annotation,
itemId,
publisher,
series,
publicationYear,
pagesNum,
size,
coverType,
circulation,
weight,
category,
image,
);
console.info("Updated");
console.info(data);
// загрузка и заполнение table
drawLinesTable();
}
async function removeLine(id) {
if (!confirm("Вы действительно хотите удалить этот товар?")) {
console.info("Отменено");
return;
}
console.info("Попытка удалить элемент");
// вызов метода REST API для удаления записи
const data = await deleteLine(id);
console.info(data);
// загрузка и заполнение table
drawLinesTable();
}
// функция для получения содержимого файла в виде base64 строки
// https://ru.wikipedia.org/wiki/Base64
async function readFile(file) {
const reader = new FileReader();
// создание Promise-объекта для использования функции
// с помощью await (асинхронно) без коллбэков (callback)
// https://learn.javascript.ru/promise
return new Promise((resolve, reject) => {
// 2. "Возвращаем" содержимое когда файл прочитан
// через вызов resolve
// Если не использовать Promise, то всю работу по взаимодействию
// с REST API пришлось бы делать в обработчике (callback) функции
// onloadend
reader.onloadend = () => {
const fileContent = reader.result;
// Здесь могла бы быть работа с REST API
// Чтение заканчивает выполняться здесь
resolve(fileContent);
};
// 3. Возвращаем ошибку
reader.onerror = () => {
// Или здесь в случае ошибки
reject(new Error("oops, something went wrong with the file reader."));
};
// Шаг 1. Сначала читаем файл
// Чтение начинает выполняться здесь
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;
}
export async function fillOutCatalog() {
console.info("Try to load catalog data");
const data = await getAllLines();
if (cntrls.catalogBooks) {
cntrls.catalogBooks.innerHTML = "";
data.forEach((item) => {
cntrls.catalogBooks.appendChild(
createCatalogItem(
item,
() => location.assign(`product_card.html`),
),
);
});
}
}
// Функция для обработки создания и редактирования элементов таблицы через страницу add-item.html
export async function linesPageForm() {
console.info("linesPageForm");
// загрузка и заполнение select со списком товаров
drawCategoriesSelect();
// загрузка и заполнение table
drawLinesTable();
// func1 = (id) => {} аналогично function func1(id) {}
const goBack = () => location.assign("/admin.html");
// Вызов функции обновления превью изображения при возникновении
// события onchange в тэге input с id image
if (cntrls.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 getLine(currentId);
// заполнение формы для редактирования
cntrls.сategoriesType.value = line.categoriesId;
cntrls.title.value = line.title;
cntrls.author.value = line.author;
cntrls.price.value = line.price;
cntrls.count.value = line.count;
cntrls.descrition.value = line.descrition;
cntrls.annotation.value = line.annotation;
cntrls.itemId.value = line.itemId;
cntrls.publisher.value = line.publisher;
cntrls.series.value = line.series;
cntrls.publicationYear.value = line.publicationYear;
cntrls.pagesNum.value = line.pagesNum;
cntrls.size.value = line.size;
cntrls.coverType.value = line.coverType;
cntrls.circulation.value = line.circulation;
cntrls.weight.value = line.weight;
// заполнение превью
// Если пользователь выбрал изображение, то оно загружается
// в тэг image с id image - preview
// иначе устанавливается заглушка, адрес которой указан в imagePlaceholder
cntrls.imagePreview.src = line.image ? line.image : imagePlaceholder;
} catch {
// в случае ошибки происходит возврат к admin
goBack();
}
}
// обработчик события отправки формы
// возникает при нажатии на кнопку (button) с типом submit
// кнопка должна находится внутри тега form
if (cntrls.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.title.value,
cntrls.author.value,
cntrls.price.value,
cntrls.count.value,
cntrls.descrition.value,
cntrls.annotation.value,
cntrls.itemId.value,
cntrls.publisher.value,
cntrls.series.value,
cntrls.publicationYear.value,
cntrls.pagesNum.value,
cntrls.size.value,
cntrls.coverType.value,
cntrls.circulation.value,
cntrls.weight.value,
cntrls.сategoriesType.value,
imageBase64,
);
} else {
await editLine(
currentId,
cntrls.title.value,
cntrls.author.value,
cntrls.price.value,
cntrls.count.value,
cntrls.descrition.value,
cntrls.annotation.value,
cntrls.itemId.value,
cntrls.publisher.value,
cntrls.series.value,
cntrls.publicationYear.value,
cntrls.pagesNum.value,
cntrls.size.value,
cntrls.coverType.value,
cntrls.circulation.value,
cntrls.weight.value,
cntrls.сategoriesType.value,
imageBase64,
);
}
// возврат к странице admin
goBack();
});
}
fillOutCatalog();
}