InternetProgramming/Lab3/js/lines.js
2023-11-30 18:13:57 +03:00

214 lines
10 KiB
JavaScript
Raw Permalink 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.

import {
createLine, deleteLine, updateLine, getAllGenreTypes, getAllLines, getLine,
} from "./lines-rest-api";
import {
controls, createGenresOption, createTableRow, imagePlaceholder,
} from "./lines-ui";
// ОТОБРАЖЕНИЕ ВОЗМОЖНЫХ ЖАНРОВ ИГРЫ ПРИ СОЗДАНИИ/ИЗМЕНЕНИИ В SELECT
async function drawGenresSelect() {
// вызов метода REST API для получения списка жанров
const data = await getAllGenreTypes();
// очистка содержимого select, удаление всего между тегами <select></select>
controls.genresType.innerHTML = '';
// пустое значение
controls.genresType.appendChild(createGenresOption("Выберите жанр", "", true));
// цикл по результату ответа от сервера
// используется лямбда-выражение
// (item) => {} аналогично function(item) {}
data.forEach((genre) => {
controls.genresType.appendChild(createGenresOption(genre.name, genre.id));
});
}
// ОБНОВЛЕНИЕ СОДЕРЖИМОГО TABLE ПРИ СОЗДАНИИ, РЕДАКТИРОВАНИИ, УДАЛЕНИИ
export async function drawLinesTable() {
console.info("Try to load data");
if (!controls.table) {
return;
}
// вызов метода REST API для получения всех записей
const data = await getAllLines();
// очистка содержимого table, удаление всего между тегами <table></table>
controls.table.innerHTML = "";
// цикл по результату ответа от сервера с лямбда выражением (сокращение от function)
// ДОБАВИЛ async И await
data.forEach(async (item) => {
// добавление строки в конец таблицы
controls.table.appendChild(
await createTableRow(
item,
// функции в качестве параметра
// location - адрес текущей страницы, ей меняем адрес на страницу админки
() => location.assign(`admin.html?id=${item.id}`),
() => removeLine(item.id),
),
);
});
}
// ДОБАВЛЕНИЕ НОВОЙ ЗАПИСИ НА СЕРВЕР, ОБНОВЛЕНИЕ ТАБЛИЦЫ
async function addLine(genre, name, price, image) {
console.info("Try to add item");
// вызов метода REST API для добавления записи
const data = await createLine(genre, name, price, image);
console.info("Added");
console.info(data);
// загрузка и заполнение table
drawLinesTable();
}
// РЕДАКТИРОВАНИЕ ЗАПИСИ НА СЕРВЕРЕ, ОБНОВЛЕНИЕ ТАБЛИЦЫ
async function editLine(id, genre, name, price, image) {
console.info("Try to update item");
// вызов метода REST API для обновления записи
const data = await updateLine(id, genre, name, price, image);
console.info("Updated");
console.info(data);
// загрузка и заполнение table
drawLinesTable();
}
// УДАЛЕНИЕ ЗАПИСИ НА СЕРВЕРЕ, ОБНОВЛЕНИЕ ТАБЛИЦЫ
async function removeLine(id) {
if (!confirm("Удалить игру?")) {
console.info("Canceled");
return;
}
console.info("Try to remove item");
// вызов метода REST API для удаления записи
const data = await deleteLine(id);
console.info(data);
// загрузка и заполнение table
drawLinesTable();
}
// ПОЛУЧЕНИЕ ДАННЫХ ФАЙЛА (ФОТКИ)
async function readFile(file) {
const reader = new FileReader();
return new Promise((resolve, reject) => {
// Шаг 1. Чтение файла
reader.readAsDataURL(file);
// Шаг 2. "Возвращение" содержимого, если файл нормально прочитан, через вызов resolve
reader.onloadend = () => {
const fileContent = reader.result;
resolve(fileContent);
};
// 3. Возвращение ошибки, если файл был прочитан с ошбикой
reader.onerror = () => {
// Или здесь в случае ошибки
reject(new Error("Something went wrong with the file reader."));
};
});
}
// Обновление превью выбранного изображения при изменении/создании
async function updateImagePreview() {
// получение выбранного файла
// возможен выбор нескольких файлов, поэтому надо получить только первый
const file = controls.image.files[0];
// чтение содержимого файла в виде base64 строки
const fileContent = await readFile(file);
console.info("base64 ", fileContent);
// обновление источника src для тега img с id image-preview
controls.imagePreview.src = fileContent;
}
// Функция для обработки создания и редактирования элементов таблицы через страницу admin.html
export async function linesPageForm() {
console.info("linesPageForm");
// загрузка и заполнение select со списком товаров
drawGenresSelect();
// аналог function goBack() {}
const goBack = () => location.assign("/index.html");
// Вызов функции обновления превью изображения при возникновении
// события onchange в тэге input с id image
controls.image.addEventListener("change", () => updateImagePreview());
// получение параметров GET-запроса из URL
// параметры перечислены после символа ?
const urlParams = new URLSearchParams(location.search);
// получение значения конкретного параметра (id)
// указан только при редактировании
const currentId = urlParams.get("id");
// если id задан
if (currentId) {
try {
// вызов метода REST API для получения записи по первичному ключу(id)
const line = await getLine(currentId);
// заполнение формы для редактирования
controls.genresType.value = line.genresId;
controls.price.value = line.price;
controls.name.value = line.name;
// заполнение превью
// Если пользователь выбрал изображение, то оно загружается
// в тэг image с id image - preview
// иначе устанавливается заглушка, адрес которой указан в imagePlaceholder
controls.imagePreview.src = line.image ? line.image : imagePlaceholder;
} catch {
// в случае ошибки происходит возврат к странице index
goBack();
}
}
// обработчик события отправки формы
// возникает при нажатии на кнопку (button) с типом submit
// кнопка должна находится внутри тега form
controls.form.addEventListener("submit", async (event) => {
console.info("Form onSubmit");
// отключение стандартного поведения формы при отправке
// при отправке страница обновляется и JS перестает работать
event.preventDefault();
event.stopPropagation();
// если форма не прошла валидацию, то ничего делать не нужно
if (!controls.form.checkValidity()) {
return;
}
let imageBase64 = "";
// Получение выбранного пользователем изображения в виде base64 строки
// Если пользователь ничего не выбрал, то не нужно сохранять в БД
// дефолтное изображение
if (controls.imagePreview.src !== imagePlaceholder) {
// Загрузка содержимого атрибута src тэга img с id image-preview
// Здесь выполняется HTTP запрос с типом GET
const result = await fetch(controls.imagePreview.src);
// Получение из HTTP-ответа бинарного содержимого
const blob = await result.blob();
// Получение base64 строки для файла
// Здесь выполняется Promise из функции readFile
// Promise позволяет писать линейный код для работы с асинхронными методами
// без использования обработчиков (callback) с помощью await
imageBase64 = await readFile(blob);
}
// если значение параметра запроса не задано,
// то значит сейчас делается добавление записи
// если не задано, значит это обновление записи
if (!currentId) {
await addLine(
controls.genresType.value,
controls.name.value,
controls.price.value,
imageBase64,
);
} else {
await editLine(
currentId,
controls.genresType.value,
controls.name.value,
controls.price.value,
imageBase64,
);
}
// возврат к странице index
goBack();
});
}