Corp/backend/static/js/api/calendarApi.js
Игорь Надеин 28e2f1615f feat: реализован drag & drop для перемещения событий между календарями
- Создан модуль calendarEventDragDrop.js с классами DragDropState и CalendarUtils
- Реализовано перетаскивание событий между календарями через модальное окно
- Добавлена кнопка 'Переместить все' для массового перемещения
- Модальное окно отображает источник и цель перемещения
- Поддержка legacy-календарей (company/department/personal)
- Добавлены стили для подсветки drop-target (папки и календари)
- Backend: исправлена обработка null значений в serializer
- Backend: добавлен endpoint list_raw для получения немодерируемых событий
- Использованы стандартные Bootstrap стили для модалов
- Исправлено всплытие событий dragover/drop (stopPropagation)
- Эмодзи иконки для типов календарей (����)
- Toast уведомления об успехе/ошибках перемещения
2026-02-12 15:59:53 +03:00

137 lines
4.1 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* @fileoverview Calendar API - обертка над API календаря с кешированием
* @module api/calendarApi
*/
import { dataManager } from "../managers/dataManager.js";
import { authHeaders } from "../utils/authUtils.js";
import { API_URLS, API_DEFAULTS } from "../constants/apiUrls.js";
/**
* Получить события календаря
* @param {Object} params - Параметры запроса
* @param {string} params.start - Дата начала (YYYY-MM-DD)
* @param {string} params.end - Дата конца (YYYY-MM-DD)
* @param {number} [params.department_id] - ID отдела (опционально)
* @param {number} [ttl] - Time to live кеша в мс
* @returns {Promise<Array>} Массив событий
*/
export async function getCalendarEvents(params, ttl = API_DEFAULTS.TTL.EVENTS) {
// Создаем уникальный ключ для кеша
const sortedParams = Object.keys(params)
.sort()
.reduce((acc, key) => {
acc[key] = params[key];
return acc;
}, {});
const key = `calendar:events:${JSON.stringify(sortedParams)}`;
return dataManager.fetch(
key,
async () => {
const url = new URL(API_URLS.EVENTS, window.location.origin);
Object.keys(params).forEach((k) => {
if (params[k] != null) {
url.searchParams.set(k, String(params[k]));
}
});
const response = await fetch(url.toString(), {
headers: authHeaders(),
});
if (response.status === 401) {
console.warn("[CalendarAPI] 401 Unauthorized");
return [];
}
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const data = await response.json();
// Поддержка разных форматов ответа
return Array.isArray(data)
? data
: data.results || data.items || data.events || [];
},
ttl,
);
}
/**
* Получить событие по ID
* @param {number|string} eventId - ID события
* @param {number} [ttl] - Time to live кеша в мс
* @returns {Promise<Object>} Событие
*/
export async function getCalendarEvent(
eventId,
ttl = API_DEFAULTS.TTL.EVENT_DETAIL,
) {
const key = `calendar:event:${eventId}`;
return dataManager.fetch(
key,
async () => {
const url = API_URLS.EVENT_DETAIL(eventId);
const response = await fetch(url, {
headers: authHeaders(false),
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
return response.json();
},
ttl,
);
}
/**
* Инвалидировать кеш событий календаря
* @param {Object} [params] - Параметры для инвалидации (если не указаны, инвалидируется весь кеш)
*/
export function invalidateCalendarEvents(params = null) {
if (params) {
const sortedParams = Object.keys(params)
.sort()
.reduce((acc, key) => {
acc[key] = params[key];
return acc;
}, {});
const key = `calendar:events:${JSON.stringify(sortedParams)}`;
dataManager.invalidate(key);
} else {
// Инвалидируем все события календаря
dataManager.invalidatePattern(/^calendar:events:/);
}
}
/**
* Инвалидировать кеш конкретного события
* @param {number|string} eventId - ID события
*/
export function invalidateCalendarEvent(eventId) {
dataManager.invalidate(`calendar:event:${eventId}`);
}
/**
* Пре-загрузить события в кеш (например, из SSR данных)
* @param {Object} params - Параметры запроса
* @param {Array} events - Данные событий
*/
export function preloadCalendarEvents(params, events) {
const sortedParams = Object.keys(params)
.sort()
.reduce((acc, key) => {
acc[key] = params[key];
return acc;
}, {});
const key = `calendar:events:${JSON.stringify(sortedParams)}`;
dataManager.preload(key, events);
}