diff --git a/public/app.js b/public/app.js index ec8b8e1..9eeb3ed 100644 --- a/public/app.js +++ b/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 = ` + Новые изображения: + + `; + + 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 = ` + Preview + +
${file.name}
+ `; + + 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); + } }); });