Maybe it works

This commit is contained in:
Zakharov_Rostislav 2023-12-02 17:50:30 +04:00
parent ded9e916a0
commit ada7d99c43
5 changed files with 55 additions and 178 deletions

View File

@ -67,7 +67,6 @@
import validation from "./js/validation"; import validation from "./js/validation";
import { linesPageForm } from "./js/lines"; import { linesPageForm } from "./js/lines";
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {
validation();
linesPageForm(); linesPageForm();
}); });
</script> </script>

View File

@ -1,5 +1,5 @@
{ {
"items": [ "categories": [
{ {
"id": 1, "id": 1,
"name": "Ода" "name": "Ода"
@ -13,35 +13,35 @@
"name": "Лирическое стихотворение" "name": "Лирическое стихотворение"
} }
], ],
"lines": [ "books": [
{ {
"itemsId": "3", "categoriesId": "3",
"authorsId": "1",
"name": "Зимний вечер", "name": "Зимний вечер",
"authorId": "1",
"year": "1830", "year": "1830",
"image": "", "image": "",
"id": 2 "id": 2
}, },
{ {
"itemsId": "1", "categoriesId": "1",
"authorsId": "2",
"name": "Властителям и судиям", "name": "Властителям и судиям",
"authorId": "2",
"year": "1780", "year": "1780",
"image": "", "image": "",
"id": 3 "id": 3
}, },
{ {
"itemsId": "1", "categoriesId": "1",
"authorsId": "3",
"name": "Exegi monumentum", "name": "Exegi monumentum",
"authorId": "3",
"year": "23 до н. э.", "year": "23 до н. э.",
"image": "", "image": "",
"id": 4 "id": 4
}, },
{ {
"itemsId": "2", "categoriesId": "2",
"authorsId": "4",
"name": "К бедному поэту", "name": "К бедному поэту",
"authorId": "4",
"year": "1796", "year": "1796",
"image": "", "image": "",
"id": 5 "id": 5

View File

@ -3,19 +3,8 @@
// адрес сервера // адрес сервера
const serverUrl = "http://localhost:8081"; const serverUrl = "http://localhost:8081";
// функция возвращает объект нужной структуры для отправки на сервер // обращение к серверу для получения всех типов авторов (get)
function createLineObject(item, name, authorId, year, image) { export async function getAllAuthors() {
return {
itemsId: item,
name,
authorId,
year,
image,
};
}
// обращение к серверу для получения всех типов товара (get)
export async function getAllAuthorsTypes() {
const response = await fetch(`${serverUrl}/authors`); const response = await fetch(`${serverUrl}/authors`);
if (!response.ok) { if (!response.ok) {
throw response.statusText; throw response.statusText;
@ -23,9 +12,9 @@ export async function getAllAuthorsTypes() {
return response.json(); return response.json();
} }
// обращение к серверу для получения всех типов товара (get) // обращение к серверу для получения всех категорий книг (get)
export async function getAllItemTypes() { export async function getAllCategories() {
const response = await fetch(`${serverUrl}/items`); const response = await fetch(`${serverUrl}/categories`);
if (!response.ok) { if (!response.ok) {
throw response.statusText; throw response.statusText;
} }
@ -33,8 +22,8 @@ export async function getAllItemTypes() {
} }
// обращение к серверу для получения всех записей (get) // обращение к серверу для получения всех записей (get)
export async function getAllLines() { export async function getAllBooks() {
const response = await fetch(`${serverUrl}/lines?_expand=items`); const response = await fetch(`${serverUrl}/books?_expand=categories&_expand=authors`);
if (!response.ok) { if (!response.ok) {
throw response.statusText; throw response.statusText;
} }
@ -43,8 +32,8 @@ export async function getAllLines() {
// обращение к серверу для получения записи по первичному ключу (id) (get) // обращение к серверу для получения записи по первичному ключу (id) (get)
// id передается в качестве части пути URL get-запроса // id передается в качестве части пути URL get-запроса
export async function getLine(id) { export async function getBook(id) {
const response = await fetch(`${serverUrl}/lines/${id}?_expand=items`); const response = await fetch(`${serverUrl}/books/${id}?_expand=categories&_expand=authors`);
if (!response.ok) { if (!response.ok) {
throw response.statusText; throw response.statusText;
} }
@ -107,3 +96,14 @@ export async function deleteLine(id) {
} }
return response.json(); return response.json();
} }
// функция возвращает объект нужной структуры для отправки на сервер
function createLineObject(item, name, authorId, year, image) {
return {
itemsId: item,
name,
authorId,
year,
image,
};
}

View File

@ -72,23 +72,18 @@ function createTableColumn(value) {
// <td><a href="#" onclick="editPageCallback()"><i class="fa-solid fa-pen-to-square"></i></a></td> // <td><a href="#" onclick="editPageCallback()"><i class="fa-solid fa-pen-to-square"></i></a></td>
// <td><a href="#" onclick="deleteCallback()"><i class="fa-solid fa-trash"></i></a></td> // <td><a href="#" onclick="deleteCallback()"><i class="fa-solid fa-trash"></i></a></td>
// </tr> // </tr>
export function createTableRow(item, author, index, editPageCallback, deleteCallback) { export function createTableRow(book, index, editPageCallback, deleteCallback) {
const rowNumber = document.createElement("th"); const rowNumber = document.createElement("th");
rowNumber.scope = "row"; rowNumber.scope = "row";
rowNumber.textContent = index + 1; rowNumber.textContent = index + 1;
const row = document.createElement("tr"); const row = document.createElement("tr");
row.id = `line-${item.id}`; row.id = `line-${book.id}`;
row.appendChild(rowNumber); row.appendChild(rowNumber);
row.appendChild(createTableColumn(item.items.name)); row.appendChild(createTableColumn(book.categories.name));
row.appendChild(createTableColumn(item.name)); row.appendChild(createTableColumn(book.name));
// row.appendChild(createTableColumn(item.authors.name)); row.appendChild(createTableColumn(book.authors.name));
row.appendChild(createTableColumn("item.authors.name")); row.appendChild(createTableColumn(book.year));
row.appendChild(createTableColumn(item.year));
// редактировать на странице page-edit
row.appendChild(createTableAnchor("fa-pen-to-square", editPageCallback)); row.appendChild(createTableAnchor("fa-pen-to-square", editPageCallback));
// удаление
row.appendChild(createTableAnchor("fa-trash", deleteCallback)); row.appendChild(createTableAnchor("fa-trash", deleteCallback));
return row; return row;
} }

View File

@ -1,28 +1,21 @@
/* eslint-disable import/prefer-default-export */
// модуль с логикой // модуль с логикой
import { import {
createLine, deleteLine, getAllItemTypes, getAllAuthorsTypes, getAllLines, getLine, updateLine, createLine, deleteLine, getAllCategories, getAllAuthors, getAllBooks, getBook, updateLine,
} from "./lines-rest-api"; } from "./lines-rest-api";
import { import {
cntrls, createItemsOption, createTableRow, imagePlaceholder, cntrls, createItemsOption, createTableRow, imagePlaceholder,
} from "./lines-ui"; } from "./lines-ui";
async function drawItemsSelect() { // функция для заполнения списков авторов и категорий книг
// вызов метода REST API для получения списка типов товаров async function drawLists() {
const data = await getAllItemTypes(); const data = await getAllCategories();
// вызов метода REST API для получения списка авторов const authors = await getAllAuthors();
const authors = await getAllAuthorsTypes();
// очистка содержимого select
// удаляется все, что находится между тегами <select></select>
// но не атрибуты
cntrls.itemsType.innerHTML = ""; cntrls.itemsType.innerHTML = "";
cntrls.authorType.innerHTML = ""; cntrls.authorType.innerHTML = "";
// пустое значение
cntrls.itemsType.appendChild(createItemsOption("Выберите значение", "", true)); cntrls.itemsType.appendChild(createItemsOption("Выберите значение", "", true));
cntrls.authorType.appendChild(createItemsOption("Выберите значение", "", true)); cntrls.authorType.appendChild(createItemsOption("Выберите значение", "", true));
// цикл по результату ответа от сервера
// используется лямбда-выражение
// (item) => {} аналогично function(item) {}
data.forEach((item) => { data.forEach((item) => {
cntrls.itemsType.appendChild(createItemsOption(item.name, item.id)); cntrls.itemsType.appendChild(createItemsOption(item.name, item.id));
}); });
@ -31,31 +24,21 @@ async function drawItemsSelect() {
}); });
} }
async function drawLinesTable() { // функция отрисовки таблицы
async function drawTable() {
console.info("Try to load data"); console.info("Try to load data");
if (!cntrls.table) { if (!cntrls.table) {
return; return;
} }
// вызов метода REST API для получения всех записей const data = await getAllBooks();
const data = await getAllLines();
// очистка содержимого table
// удаляется все, что находится между тегами <table></table>
// но не атрибуты
cntrls.table.innerHTML = ""; cntrls.table.innerHTML = "";
// цикл по результату ответа от сервера data.forEach((book, index) => {
// используется лямбда-выражение
// (item, index) => {} аналогично function(item, index) {}
data.forEach((item, author, index) => {
cntrls.table.appendChild( cntrls.table.appendChild(
createTableRow( createTableRow(
item, book,
author,
index, index,
// функции передаются в качестве параметра () => location.assign(`page-edit.html?id=${book.id}`),
// это очень удобно, так как аргументы функций доступны только () => removeLine(book.id),
// в данном месте кода и не передаются в сервисные модули
() => location.assign(`page-edit.html?id=${item.id}`),
() => removeLine(item.id),
), ),
); );
}); });
@ -68,7 +51,7 @@ async function addLine(item, name, authorId, year, image) {
console.info("Added"); console.info("Added");
console.info(data); console.info(data);
// загрузка и заполнение table // загрузка и заполнение table
drawLinesTable(); drawTable();
} }
async function editLine(id, item, name, authorId, year, image) { async function editLine(id, item, name, authorId, year, image) {
@ -78,7 +61,7 @@ async function editLine(id, item, name, authorId, year, image) {
console.info("Updated"); console.info("Updated");
console.info(data); console.info(data);
// загрузка и заполнение table // загрузка и заполнение table
drawLinesTable(); drawTable();
} }
async function removeLine(id) { async function removeLine(id) {
@ -91,7 +74,7 @@ async function removeLine(id) {
const data = await deleteLine(id); const data = await deleteLine(id);
console.info(data); console.info(data);
// загрузка и заполнение table // загрузка и заполнение table
drawLinesTable(); drawTable();
} }
// функция для получения содержимого файла в виде base64 строки // функция для получения содержимого файла в виде base64 строки
@ -142,9 +125,9 @@ export async function linesPageForm() {
console.info("linesPageForm"); console.info("linesPageForm");
// загрузка и заполнение select со списком товаров // загрузка и заполнение select со списком товаров
drawItemsSelect(); drawLists();
// загрузка и заполнение table // загрузка и заполнение table
drawLinesTable(); drawTable();
// func1 = (id) => {} аналогично function func1(id) {} // func1 = (id) => {} аналогично function func1(id) {}
const goBack = () => location.assign("./admin-page.html"); const goBack = () => location.assign("./admin-page.html");
@ -164,107 +147,7 @@ export async function linesPageForm() {
if (currentId) { if (currentId) {
try { try {
// вызов метода REST API для получения записи по первичному ключу(id) // вызов метода REST API для получения записи по первичному ключу(id)
const line = await getLine(currentId); 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();
});
}
export async function linesUserForm() {
console.info("linesPageForm");
// загрузка и заполнение select со списком товаров
drawItemsSelect();
// загрузка и заполнение table
drawLinesTable();
// 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 getLine(currentId);
// заполнение формы для редактирования // заполнение формы для редактирования
cntrls.itemsType.value = line.itemsId; cntrls.itemsType.value = line.itemsId;
cntrls.name.value = line.name; cntrls.name.value = line.name;