/* 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 // удаляется все, что находится между тегами // но не атрибуты 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 // удаляется все, что находится между тегами
// но не атрибуты 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(); }