- Реализована возможность загрузки файлов (PDF, DOC, XLS и др.) к заметкам с помощью нового API. - Добавлены функции для получения, удаления и отображения прикрепленных файлов в интерфейсе заметок. - Обновлены стили и обработчики событий для работы с файлами в режиме редактирования и создания заметок. - Улучшена логика обработки файлов, включая проверку на дубликаты и ограничения по размеру.
482 lines
17 KiB
HTML
482 lines
17 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="UTF-8" />
|
||
<meta
|
||
name="viewport"
|
||
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"
|
||
/>
|
||
<title>Заметки - NoteJS</title>
|
||
|
||
<!-- Предотвращение мерцания темы -->
|
||
<script>
|
||
(function () {
|
||
try {
|
||
const savedTheme = localStorage.getItem("theme");
|
||
const systemPrefersDark = window.matchMedia(
|
||
"(prefers-color-scheme: dark)"
|
||
).matches;
|
||
const theme = savedTheme || (systemPrefersDark ? "dark" : "light");
|
||
|
||
if (theme === "dark") {
|
||
document.documentElement.setAttribute("data-theme", "dark");
|
||
}
|
||
} catch (e) {}
|
||
})();
|
||
</script>
|
||
|
||
<!-- PWA Meta Tags -->
|
||
<meta
|
||
name="description"
|
||
content="NoteJS - современная система заметок с поддержкой Markdown, изображений, тегов и календаря"
|
||
/>
|
||
<meta name="theme-color" content="#007bff" />
|
||
<meta name="mobile-web-app-capable" content="yes" />
|
||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||
<meta
|
||
name="apple-mobile-web-app-status-bar-style"
|
||
content="black-translucent"
|
||
/>
|
||
<meta name="apple-mobile-web-app-title" content="NoteJS" />
|
||
<meta name="apple-touch-fullscreen" content="yes" />
|
||
<meta name="msapplication-TileColor" content="#007bff" />
|
||
<meta name="msapplication-config" content="/browserconfig.xml" />
|
||
<meta name="msapplication-TileImage" content="/icons/icon-144x144.png" />
|
||
<meta name="application-name" content="NoteJS" />
|
||
<meta name="format-detection" content="telephone=no" />
|
||
|
||
<!-- Icons -->
|
||
<link rel="icon" type="image/svg+xml" href="/icon.svg" />
|
||
<link
|
||
rel="icon"
|
||
type="image/png"
|
||
sizes="32x32"
|
||
href="/icons/icon-32x32.png"
|
||
/>
|
||
<link
|
||
rel="icon"
|
||
type="image/png"
|
||
sizes="16x16"
|
||
href="/icons/icon-16x16.png"
|
||
/>
|
||
<link rel="apple-touch-icon" sizes="57x57" href="/icons/icon-48x48.png" />
|
||
<link rel="apple-touch-icon" sizes="60x60" href="/icons/icon-48x48.png" />
|
||
<link rel="apple-touch-icon" sizes="72x72" href="/icons/icon-72x72.png" />
|
||
<link rel="apple-touch-icon" sizes="76x76" href="/icons/icon-72x72.png" />
|
||
<link
|
||
rel="apple-touch-icon"
|
||
sizes="114x114"
|
||
href="/icons/icon-128x128.png"
|
||
/>
|
||
<link
|
||
rel="apple-touch-icon"
|
||
sizes="120x120"
|
||
href="/icons/icon-128x128.png"
|
||
/>
|
||
<link
|
||
rel="apple-touch-icon"
|
||
sizes="144x144"
|
||
href="/icons/icon-144x144.png"
|
||
/>
|
||
<link
|
||
rel="apple-touch-icon"
|
||
sizes="152x152"
|
||
href="/icons/icon-152x152.png"
|
||
/>
|
||
<link
|
||
rel="apple-touch-icon"
|
||
sizes="180x180"
|
||
href="/icons/icon-192x192.png"
|
||
/>
|
||
<link rel="mask-icon" href="/icon.svg" color="#007bff" />
|
||
|
||
<!-- Manifest -->
|
||
<link rel="manifest" href="/manifest.json" />
|
||
|
||
<!-- Styles -->
|
||
<link rel="stylesheet" href="/style.css?v=4" />
|
||
|
||
<!-- Scripts -->
|
||
<script src="https://cdnjs.cloudflare.com/ajax/libs/iconify/2.0.0/iconify.min.js"></script>
|
||
</head>
|
||
<body>
|
||
<!-- Кнопка открытия слайдера для мобильной версии -->
|
||
<div class="mobile-menu-btn" id="mobileMenuBtn">
|
||
<span class="iconify" data-icon="mdi:menu"></span>
|
||
</div>
|
||
|
||
<!-- Слайдер для мобильной версии -->
|
||
<div class="mobile-sidebar" id="mobileSidebar">
|
||
<div class="sidebar-close-btn" id="sidebarCloseBtn">
|
||
<span class="iconify" data-icon="mdi:close"></span>
|
||
</div>
|
||
<div class="sidebar-content">
|
||
<div class="mini-calendar">
|
||
<div class="calendar-header">
|
||
<button class="calendar-nav" id="prevMonthMobile">‹</button>
|
||
<span class="calendar-month-year" id="monthYearMobile"></span>
|
||
<button class="calendar-nav" id="nextMonthMobile">›</button>
|
||
</div>
|
||
<div class="calendar-weekdays">
|
||
<div class="calendar-weekday">Пн</div>
|
||
<div class="calendar-weekday">Вт</div>
|
||
<div class="calendar-weekday">Ср</div>
|
||
<div class="calendar-weekday">Чт</div>
|
||
<div class="calendar-weekday">Пт</div>
|
||
<div class="calendar-weekday">Сб</div>
|
||
<div class="calendar-weekday">Вс</div>
|
||
</div>
|
||
<div class="calendar-days" id="calendarDaysMobile"></div>
|
||
</div>
|
||
|
||
<!-- Секция поиска -->
|
||
<div class="search-section">
|
||
<div class="search-header">
|
||
<span class="search-title"
|
||
><span class="iconify" data-icon="mdi:magnify"></span> Поиск</span
|
||
>
|
||
</div>
|
||
<div class="search-container">
|
||
<input
|
||
type="text"
|
||
id="searchInputMobile"
|
||
placeholder="Поиск по заметкам..."
|
||
class="search-input"
|
||
/>
|
||
<button
|
||
id="clearSearchBtnMobile"
|
||
class="clear-search-btn"
|
||
style="display: none"
|
||
>
|
||
✕
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Секция тегов -->
|
||
<div class="tags-section">
|
||
<div class="tags-header">
|
||
<span class="tags-title"
|
||
><span class="iconify" data-icon="mdi:tag"></span> Теги</span
|
||
>
|
||
</div>
|
||
<div class="tags-container" id="tagsContainerMobile">
|
||
<!-- Теги будут добавлены динамически -->
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Оверлей для закрытия слайдера -->
|
||
<div class="mobile-sidebar-overlay" id="sidebarOverlay"></div>
|
||
|
||
<div class="container-leftside">
|
||
<div class="mini-calendar">
|
||
<div class="calendar-header">
|
||
<button class="calendar-nav" id="prevMonth">‹</button>
|
||
<span class="calendar-month-year" id="monthYear"></span>
|
||
<button class="calendar-nav" id="nextMonth">›</button>
|
||
</div>
|
||
<div class="calendar-weekdays">
|
||
<div class="calendar-weekday">Пн</div>
|
||
<div class="calendar-weekday">Вт</div>
|
||
<div class="calendar-weekday">Ср</div>
|
||
<div class="calendar-weekday">Чт</div>
|
||
<div class="calendar-weekday">Пт</div>
|
||
<div class="calendar-weekday">Сб</div>
|
||
<div class="calendar-weekday">Вс</div>
|
||
</div>
|
||
<div class="calendar-days" id="calendarDays"></div>
|
||
</div>
|
||
|
||
<!-- Секция поиска -->
|
||
<div class="search-section">
|
||
<div class="search-header">
|
||
<span class="search-title"
|
||
><span class="iconify" data-icon="mdi:magnify"></span> Поиск</span
|
||
>
|
||
</div>
|
||
<div class="search-container">
|
||
<input
|
||
type="text"
|
||
id="searchInput"
|
||
placeholder="Поиск по заметкам..."
|
||
class="search-input"
|
||
/>
|
||
<button
|
||
id="clearSearchBtn"
|
||
class="clear-search-btn"
|
||
style="display: none"
|
||
>
|
||
✕
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Секция тегов -->
|
||
<div class="tags-section">
|
||
<div class="tags-header">
|
||
<span class="tags-title"
|
||
><span class="iconify" data-icon="mdi:tag"></span> Теги</span
|
||
>
|
||
</div>
|
||
<div class="tags-container" id="tagsContainer">
|
||
<!-- Теги будут добавлены динамически -->
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="center">
|
||
<div class="container">
|
||
<header class="notes-header">
|
||
<div class="notes-header-left">
|
||
<span
|
||
><span class="iconify" data-icon="mdi:note-text"></span> Мои
|
||
заметки</span
|
||
>
|
||
<div
|
||
id="filter-indicator"
|
||
class="filter-indicator"
|
||
style="display: none"
|
||
></div>
|
||
</div>
|
||
<div class="user-info">
|
||
<div
|
||
id="user-avatar-container"
|
||
class="user-avatar-mini"
|
||
style="display: none"
|
||
title="Перейти в профиль"
|
||
>
|
||
<img id="user-avatar" src="" alt="Аватар" loading="lazy" />
|
||
</div>
|
||
<div
|
||
id="user-avatar-placeholder"
|
||
class="user-avatar-mini user-avatar-placeholder-mini"
|
||
style="display: none"
|
||
title="Перейти в профиль"
|
||
>
|
||
<span class="iconify" data-icon="mdi:account"></span>
|
||
</div>
|
||
<button
|
||
id="theme-toggle-btn"
|
||
class="theme-toggle-btn"
|
||
title="Переключить тему"
|
||
>
|
||
<span class="iconify" data-icon="mdi:theme-light-dark"></span>
|
||
</button>
|
||
<button
|
||
id="settings-btn"
|
||
class="settings-icon-btn"
|
||
title="Настройки"
|
||
>
|
||
<span class="iconify" data-icon="mdi:cog"></span>
|
||
</button>
|
||
<form action="/logout" method="POST" style="display: inline">
|
||
<button type="submit" class="logout-btn" title="Выйти">
|
||
<span class="iconify" data-icon="mdi:logout"></span>
|
||
</button>
|
||
</form>
|
||
</div>
|
||
</header>
|
||
<div class="main">
|
||
<div class="markdown-buttons">
|
||
<button class="btnMarkdown" id="boldBtn" title="Жирный текст">
|
||
<span class="iconify" data-icon="mdi:format-bold"></span>
|
||
</button>
|
||
<button class="btnMarkdown" id="italicBtn" title="Курсив">
|
||
<span class="iconify" data-icon="mdi:format-italic"></span>
|
||
</button>
|
||
<button
|
||
class="btnMarkdown"
|
||
id="strikethroughBtn"
|
||
title="Перечеркнутый"
|
||
>
|
||
<span class="iconify" data-icon="mdi:format-strikethrough"></span>
|
||
</button>
|
||
<button class="btnMarkdown" id="colorBtn" title="Цвет текста">
|
||
<span class="iconify" data-icon="mdi:palette"></span>
|
||
</button>
|
||
<button class="btnMarkdown" id="spoilerBtn" title="Скрытый текст">
|
||
<span class="iconify" data-icon="mdi:eye-off"></span>
|
||
</button>
|
||
<div class="header-dropdown">
|
||
<button class="btnMarkdown" id="headerBtn" title="Заголовок">
|
||
<span
|
||
class="iconify"
|
||
data-icon="mdi:format-header-pound"
|
||
></span>
|
||
<span
|
||
class="iconify"
|
||
data-icon="mdi:menu-down"
|
||
style="font-size: 10px; margin-left: -2px"
|
||
></span>
|
||
</button>
|
||
<div class="header-dropdown-menu" id="headerDropdown">
|
||
<button data-level="1">H1</button>
|
||
<button data-level="2">H2</button>
|
||
<button data-level="3">H3</button>
|
||
<button data-level="4">H4</button>
|
||
<button data-level="5">H5</button>
|
||
<button data-level="6">H6</button>
|
||
</div>
|
||
</div>
|
||
<button class="btnMarkdown" id="listBtn" title="Список">
|
||
<span class="iconify" data-icon="mdi:format-list-bulleted"></span>
|
||
</button>
|
||
<button
|
||
class="btnMarkdown"
|
||
id="numberedListBtn"
|
||
title="Нумерованный список"
|
||
>
|
||
<span class="iconify" data-icon="mdi:format-list-numbered"></span>
|
||
</button>
|
||
<button class="btnMarkdown" id="quoteBtn" title="Цитата">
|
||
<span class="iconify" data-icon="mdi:format-quote-close"></span>
|
||
</button>
|
||
<button class="btnMarkdown" id="codeBtn" title="Код">
|
||
<span class="iconify" data-icon="mdi:code-tags"></span>
|
||
</button>
|
||
<button class="btnMarkdown" id="linkBtn" title="Ссылка">
|
||
<span class="iconify" data-icon="mdi:link"></span>
|
||
</button>
|
||
<button class="btnMarkdown" id="checkboxBtn" title="To-Do список">
|
||
<span
|
||
class="iconify"
|
||
data-icon="mdi:checkbox-marked-outline"
|
||
></span>
|
||
</button>
|
||
<button
|
||
class="btnMarkdown"
|
||
id="imageBtn"
|
||
title="Загрузить изображения"
|
||
>
|
||
<span class="iconify" data-icon="mdi:image-plus"></span>
|
||
</button>
|
||
<button class="btnMarkdown" id="fileBtn" title="Прикрепить файлы">
|
||
<span class="iconify" data-icon="mdi:file-plus"></span>
|
||
</button>
|
||
<button class="btnMarkdown" id="previewBtn" title="Предпросмотр">
|
||
<span class="iconify" data-icon="mdi:eye"></span>
|
||
</button>
|
||
</div>
|
||
|
||
<textarea
|
||
class="textInput"
|
||
id="noteInput"
|
||
placeholder="Ваша заметка..."
|
||
></textarea>
|
||
|
||
<!-- Контейнер для предпросмотра заметки -->
|
||
<div
|
||
id="notePreviewContainer"
|
||
class="note-preview-container"
|
||
style="display: none"
|
||
>
|
||
<div class="note-preview-header">
|
||
<span>Предпросмотр:</span>
|
||
</div>
|
||
<div id="notePreviewContent" class="note-preview-content"></div>
|
||
</div>
|
||
|
||
<!-- Скрытый input для загрузки изображений -->
|
||
<input
|
||
type="file"
|
||
id="imageInput"
|
||
accept="image/*"
|
||
multiple
|
||
style="display: none"
|
||
/>
|
||
|
||
<!-- Скрытый input для загрузки файлов -->
|
||
<input
|
||
type="file"
|
||
id="fileInput"
|
||
accept=".pdf,.doc,.docx,.xls,.xlsx,.txt,.zip,.rar,.7z"
|
||
multiple
|
||
style="display: none"
|
||
/>
|
||
|
||
<!-- Контейнер для отображения загруженных изображений -->
|
||
<div
|
||
id="imagePreviewContainer"
|
||
class="image-preview-container"
|
||
style="display: none"
|
||
>
|
||
<div class="image-preview-header">
|
||
<span>Загруженные изображения:</span>
|
||
<button
|
||
type="button"
|
||
id="clearImagesBtn"
|
||
class="clear-images-btn"
|
||
>
|
||
Очистить все
|
||
</button>
|
||
</div>
|
||
<div id="imagePreviewList" class="image-preview-list"></div>
|
||
</div>
|
||
|
||
<!-- Контейнер для отображения прикрепленных файлов -->
|
||
<div
|
||
id="filePreviewContainer"
|
||
class="file-preview-container"
|
||
style="display: none"
|
||
>
|
||
<div class="file-preview-header">
|
||
<span>Прикрепленные файлы:</span>
|
||
<button type="button" id="clearFilesBtn" class="clear-files-btn">
|
||
Очистить все
|
||
</button>
|
||
</div>
|
||
<div id="filePreviewList" class="file-preview-list"></div>
|
||
</div>
|
||
|
||
<div class="save-button-container">
|
||
<div class="action-buttons">
|
||
<button
|
||
class="btnSave btnAI"
|
||
id="aiImproveBtn"
|
||
title="Улучшить или создать текст через ИИ"
|
||
>
|
||
<span class="iconify" data-icon="mdi:robot"></span>
|
||
Помощь ИИ
|
||
</button>
|
||
<button class="btnSave" id="saveBtn">Сохранить</button>
|
||
</div>
|
||
<span class="save-hint">или нажмите Alt + Enter</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="notes-container" class="notes-container"></div>
|
||
</div>
|
||
|
||
<div class="footer">
|
||
<p>Создатель: <span>Fovway</span></p>
|
||
</div>
|
||
|
||
<!-- Модальное окно для просмотра изображений -->
|
||
<div id="imageModal" class="image-modal">
|
||
<span class="image-modal-close">×</span>
|
||
<img class="image-modal-content" id="modalImage" loading="lazy" />
|
||
</div>
|
||
<script src="https://cdnjs.cloudflare.com/ajax/libs/marked/11.1.0/marked.min.js"></script>
|
||
<script src="/app.js"></script>
|
||
|
||
<!-- PWA Script -->
|
||
<script src="/pwa.js"></script>
|
||
|
||
<script>
|
||
// Проверяем загрузку Iconify
|
||
document.addEventListener("DOMContentLoaded", function () {
|
||
if (typeof Iconify === "undefined") {
|
||
console.warn(
|
||
"Iconify не загружен, загружаем альтернативную версию..."
|
||
);
|
||
const script = document.createElement("script");
|
||
script.src =
|
||
"https://cdnjs.cloudflare.com/ajax/libs/iconify/2.0.0/iconify.min.js";
|
||
document.head.appendChild(script);
|
||
}
|
||
});
|
||
</script>
|
||
</body>
|
||
</html>
|