feat: добавлен режим "Каникулы" и улучшения админ-панели

- Добавлен режим "Каникулы" который полностью заменяет главную страницу:
  * Карточка с эмодзи 🎉 и праздничным сообщением
  * Поддержка произвольного текста в формате Markdown
  * Карточка центрируется по вертикали при отсутствии текста

- Улучшения админ-панели:
  * Переключатель режима "Каникулы"
  * Редактор текста с подсказками по форматированию Markdown
  * Исправлена проблема с обновлением настроек (сохранение существующих значений)
  * Исправлена проблема с debug опциями в production (не блокируют обновление обычных настроек)

- Оптимизация загрузки:
  * Проверка режима каникул перед загрузкой групп
  * Динамическая загрузка ReactMarkdown только при необходимости
  * Кеш настроек сбрасывается на главной странице для актуальности

- Добавлен скрипт для сброса пароля администратора (scripts/reset-admin-password.js)

- Установлена библиотека react-markdown для рендеринга Markdown контента
This commit is contained in:
kilyabin
2025-12-04 23:22:42 +04:00
parent e46a2419c3
commit 3f74709513
9 changed files with 1562 additions and 23 deletions

View File

@@ -19,8 +19,12 @@ async function handler(
}
if (req.method === 'PUT') {
// Сначала загружаем текущие настройки из базы данных
clearSettingsCache()
const currentSettings = loadSettings(true)
// Обновление настроек
const { weekNavigationEnabled, showAddGroupButton, debug } = req.body
const { weekNavigationEnabled, showAddGroupButton, vacationModeEnabled, vacationModeContent, debug } = req.body
if (typeof weekNavigationEnabled !== 'boolean') {
res.status(400).json({ error: 'weekNavigationEnabled must be a boolean' })
@@ -32,31 +36,50 @@ async function handler(
return
}
if (vacationModeEnabled !== undefined && typeof vacationModeEnabled !== 'boolean') {
res.status(400).json({ error: 'vacationModeEnabled must be a boolean' })
return
}
if (vacationModeContent !== undefined && typeof vacationModeContent !== 'string') {
res.status(400).json({ error: 'vacationModeContent must be a string' })
return
}
// Валидация debug опций (только в dev режиме)
// В production режиме debug опции просто игнорируются
let validatedDebug = undefined
if (debug !== undefined) {
if (typeof debug !== 'object' || debug === null) {
res.status(400).json({ error: 'debug must be an object' })
return
}
if (process.env.NODE_ENV !== 'development') {
res.status(403).json({ error: 'Debug options are only available in development mode' })
return
}
const debugKeys = ['forceCache', 'forceEmpty', 'forceError', 'forceTimeout', 'showCacheInfo']
for (const key of debugKeys) {
if (key in debug && typeof debug[key] !== 'boolean' && debug[key] !== undefined) {
res.status(400).json({ error: `debug.${key} must be a boolean` })
return
if (process.env.NODE_ENV === 'development') {
// В development режиме разрешаем debug опции
const debugKeys = ['forceCache', 'forceEmpty', 'forceError', 'forceTimeout', 'showCacheInfo']
// Валидация типов debug опций
for (const key of debugKeys) {
if (key in debug && typeof debug[key] !== 'boolean' && debug[key] !== undefined) {
res.status(400).json({ error: `debug.${key} must be a boolean` })
return
}
}
validatedDebug = debug
}
// В production режиме debug опции просто игнорируются (не сохраняются)
}
// Объединяем текущие настройки с новыми (новые значения перезаписывают старые)
const settings: AppSettings = {
...currentSettings,
weekNavigationEnabled,
showAddGroupButton: showAddGroupButton !== undefined ? showAddGroupButton : true,
...(debug !== undefined && { debug })
showAddGroupButton: showAddGroupButton !== undefined ? showAddGroupButton : (currentSettings.showAddGroupButton ?? true),
vacationModeEnabled: vacationModeEnabled !== undefined ? vacationModeEnabled : (currentSettings.vacationModeEnabled ?? false),
vacationModeContent: vacationModeContent !== undefined ? vacationModeContent : (currentSettings.vacationModeContent || ''),
...(validatedDebug !== undefined && { debug: validatedDebug })
}
saveSettings(settings)