✨ Добавлена возможность загрузки и предварительного просмотра изображений при редактировании заметок
- Реализована кнопка для загрузки изображений в режиме редактирования заметок - Добавлены элементы для предварительного просмотра загруженных изображений - Обновлена функция сохранения заметки для поддержки изображений - Добавлены обработчики для управления загруженными изображениями, включая удаление и очистку
This commit is contained in:
parent
092c01dff4
commit
431d51c483
134
public/app.js
134
public/app.js
@ -815,6 +815,7 @@ function addNoteEventListeners() {
|
||||
{ id: "editQuoteBtn", icon: "mdi:format-quote-close", tag: "> " },
|
||||
{ id: "editCodeBtn", icon: "mdi:code-tags", tag: "`" },
|
||||
{ id: "editLinkBtn", icon: "mdi:link", tag: "[Текст ссылки](URL)" },
|
||||
{ id: "editImageBtn", icon: "mdi:image-plus", tag: "image" },
|
||||
];
|
||||
|
||||
markdownButtons.forEach((button) => {
|
||||
@ -837,6 +838,36 @@ function addNoteEventListeners() {
|
||||
autoExpandTextarea(textarea);
|
||||
});
|
||||
|
||||
// Создаем элементы для загрузки изображений в режиме редактирования
|
||||
const editImageInput = document.createElement("input");
|
||||
editImageInput.type = "file";
|
||||
editImageInput.accept = "image/*";
|
||||
editImageInput.multiple = true;
|
||||
editImageInput.style.display = "none";
|
||||
editImageInput.id = `editImageInput-${noteId}`;
|
||||
|
||||
const editImagePreviewContainer = document.createElement("div");
|
||||
editImagePreviewContainer.id = `editImagePreviewContainer-${noteId}`;
|
||||
editImagePreviewContainer.classList.add("image-preview-container");
|
||||
editImagePreviewContainer.style.display = "none";
|
||||
|
||||
const editImagePreviewHeader = document.createElement("div");
|
||||
editImagePreviewHeader.classList.add("image-preview-header");
|
||||
editImagePreviewHeader.innerHTML = `
|
||||
<span>Новые изображения:</span>
|
||||
<button type="button" class="clear-images-btn" id="editClearImagesBtn-${noteId}">Очистить все</button>
|
||||
`;
|
||||
|
||||
const editImagePreviewList = document.createElement("div");
|
||||
editImagePreviewList.id = `editImagePreviewList-${noteId}`;
|
||||
editImagePreviewList.classList.add("image-preview-list");
|
||||
|
||||
editImagePreviewContainer.appendChild(editImagePreviewHeader);
|
||||
editImagePreviewContainer.appendChild(editImagePreviewList);
|
||||
|
||||
// Массив для хранения новых изображений в режиме редактирования
|
||||
const editSelectedImages = [];
|
||||
|
||||
// Контейнер для кнопки сохранения и подсказки
|
||||
const saveButtonContainer = document.createElement("div");
|
||||
saveButtonContainer.classList.add("save-button-container");
|
||||
@ -854,9 +885,73 @@ function addNoteEventListeners() {
|
||||
saveButtonContainer.appendChild(saveEditBtn);
|
||||
saveButtonContainer.appendChild(saveHint);
|
||||
|
||||
// Функция обновления превью изображений для режима редактирования
|
||||
const updateEditImagePreview = function() {
|
||||
if (editSelectedImages.length === 0) {
|
||||
editImagePreviewContainer.style.display = "none";
|
||||
return;
|
||||
}
|
||||
|
||||
editImagePreviewContainer.style.display = "block";
|
||||
editImagePreviewList.innerHTML = "";
|
||||
|
||||
editSelectedImages.forEach((file, index) => {
|
||||
const reader = new FileReader();
|
||||
reader.onload = function (e) {
|
||||
const previewItem = document.createElement("div");
|
||||
previewItem.className = "image-preview-item";
|
||||
|
||||
previewItem.innerHTML = `
|
||||
<img src="${e.target.result}" alt="Preview">
|
||||
<button class="remove-image-btn" data-index="${index}">×</button>
|
||||
<div class="image-info">${file.name}</div>
|
||||
`;
|
||||
|
||||
editImagePreviewList.appendChild(previewItem);
|
||||
|
||||
// Обработчик удаления изображения
|
||||
const removeBtn = previewItem.querySelector(".remove-image-btn");
|
||||
removeBtn.addEventListener("click", function () {
|
||||
editSelectedImages.splice(index, 1);
|
||||
updateEditImagePreview();
|
||||
});
|
||||
};
|
||||
reader.readAsDataURL(file);
|
||||
});
|
||||
};
|
||||
|
||||
// Функция загрузки изображений для режима редактирования
|
||||
const uploadEditImages = async function(noteId) {
|
||||
if (editSelectedImages.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const formData = new FormData();
|
||||
editSelectedImages.forEach(file => {
|
||||
formData.append("images", file);
|
||||
});
|
||||
|
||||
try {
|
||||
const response = await fetch(`/api/notes/${noteId}/images`, {
|
||||
method: "POST",
|
||||
body: formData,
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error("Ошибка загрузки изображений");
|
||||
}
|
||||
|
||||
const result = await response.json();
|
||||
return result.images || [];
|
||||
} catch (error) {
|
||||
console.error("Ошибка загрузки изображений:", error);
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
// Функция сохранения для редактирования
|
||||
const saveEditNote = async function () {
|
||||
if (textarea.value.trim() !== "") {
|
||||
if (textarea.value.trim() !== "" || editSelectedImages.length > 0) {
|
||||
try {
|
||||
const { date, time } = getFormattedDateTime();
|
||||
const response = await fetch(`/api/notes/${noteId}`, {
|
||||
@ -865,7 +960,7 @@ function addNoteEventListeners() {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
content: textarea.value,
|
||||
content: textarea.value || " ", // Минимальный контент, если только изображения
|
||||
date: date,
|
||||
time: time,
|
||||
}),
|
||||
@ -875,6 +970,11 @@ function addNoteEventListeners() {
|
||||
throw new Error("Ошибка сохранения заметки");
|
||||
}
|
||||
|
||||
// Загружаем новые изображения, если они есть
|
||||
if (editSelectedImages.length > 0) {
|
||||
await uploadEditImages(noteId);
|
||||
}
|
||||
|
||||
// Перезагружаем заметки
|
||||
await loadNotes(true);
|
||||
} catch (error) {
|
||||
@ -892,10 +992,31 @@ function addNoteEventListeners() {
|
||||
}
|
||||
});
|
||||
|
||||
// Очищаем текущий контент и вставляем markdown кнопки, textarea и контейнер с кнопкой сохранить
|
||||
// Обработчики для загрузки изображений в режиме редактирования
|
||||
editImageInput.addEventListener("change", function (event) {
|
||||
const files = Array.from(event.target.files);
|
||||
files.forEach(file => {
|
||||
if (file.type.startsWith('image/')) {
|
||||
editSelectedImages.push(file);
|
||||
}
|
||||
});
|
||||
updateEditImagePreview();
|
||||
});
|
||||
|
||||
// Обработчик очистки всех изображений в режиме редактирования
|
||||
const editClearImagesBtn = editImagePreviewHeader.querySelector(`#editClearImagesBtn-${noteId}`);
|
||||
editClearImagesBtn.addEventListener("click", function () {
|
||||
editSelectedImages.length = 0;
|
||||
updateEditImagePreview();
|
||||
editImageInput.value = "";
|
||||
});
|
||||
|
||||
// Очищаем текущий контент и вставляем markdown кнопки, textarea, элементы для изображений и контейнер с кнопкой сохранить
|
||||
noteContent.innerHTML = "";
|
||||
noteContent.appendChild(markdownButtonsContainer);
|
||||
noteContent.appendChild(textarea);
|
||||
noteContent.appendChild(editImageInput);
|
||||
noteContent.appendChild(editImagePreviewContainer);
|
||||
noteContent.appendChild(saveButtonContainer);
|
||||
|
||||
// Применяем авторасширение после добавления в DOM
|
||||
@ -908,7 +1029,12 @@ function addNoteEventListeners() {
|
||||
markdownButtons.forEach((button) => {
|
||||
const btn = document.getElementById(button.id);
|
||||
btn.addEventListener("click", function () {
|
||||
insertMarkdownForEdit(textarea, button.tag);
|
||||
if (button.tag === "image") {
|
||||
// Для кнопки изображения открываем диалог выбора файлов
|
||||
editImageInput.click();
|
||||
} else {
|
||||
insertMarkdownForEdit(textarea, button.tag);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user