- Создан модуль calendarEventDragDrop.js с классами DragDropState и CalendarUtils - Реализовано перетаскивание событий между календарями через модальное окно - Добавлена кнопка 'Переместить все' для массового перемещения - Модальное окно отображает источник и цель перемещения - Поддержка legacy-календарей (company/department/personal) - Добавлены стили для подсветки drop-target (папки и календари) - Backend: исправлена обработка null значений в serializer - Backend: добавлен endpoint list_raw для получения немодерируемых событий - Использованы стандартные Bootstrap стили для модалов - Исправлено всплытие событий dragover/drop (stopPropagation) - Эмодзи иконки для типов календарей (����) - Toast уведомления об успехе/ошибках перемещения
133 lines
4.1 KiB
JavaScript
133 lines
4.1 KiB
JavaScript
/**
|
||
* @fileoverview Date utilities - работа с датами и временем
|
||
* @module utils/dateUtils
|
||
*/
|
||
|
||
/**
|
||
* Дополнить число нулём до двух символов
|
||
* @param {number} n - Число
|
||
* @returns {string} Строка с ведущим нулём
|
||
* @private
|
||
*/
|
||
function pad(n) {
|
||
return String(n).padStart(2, "0");
|
||
}
|
||
|
||
/**
|
||
* Форматировать дату в формат YYYY-MM-DD
|
||
* @param {Date} date - Объект Date
|
||
* @returns {string} Дата в формате YYYY-MM-DD
|
||
*/
|
||
export function formatDate(date) {
|
||
const y = date.getFullYear();
|
||
const m = pad(date.getMonth() + 1);
|
||
const d = pad(date.getDate());
|
||
return `${y}-${m}-${d}`;
|
||
}
|
||
|
||
/**
|
||
* Форматировать дату в локальный формат YYYY-MM-DD (без UTC)
|
||
* @param {Date} date - Объект Date
|
||
* @returns {string} Дата в формате YYYY-MM-DD
|
||
*/
|
||
export function ymdLocal(date) {
|
||
const y = date.getFullYear();
|
||
const m = pad(date.getMonth() + 1);
|
||
const d = pad(date.getDate());
|
||
return `${y}-${m}-${d}`;
|
||
}
|
||
|
||
/**
|
||
* Форматировать дату для отображения пользователю
|
||
* @param {Date|string} date - Дата
|
||
* @returns {string} Дата в формате ДД.ММ.ГГГГ
|
||
*/
|
||
export function fmtDate(date) {
|
||
const d = typeof date === "string" ? new Date(date) : date;
|
||
return `${pad(d.getDate())}.${pad(d.getMonth() + 1)}.${d.getFullYear()}`;
|
||
}
|
||
|
||
/**
|
||
* Форматировать время для отображения пользователю
|
||
* @param {Date|string} date - Дата/время
|
||
* @returns {string} Время в формате ЧЧ:ММ
|
||
*/
|
||
export function fmtTime(date) {
|
||
const d = typeof date === "string" ? new Date(date) : date;
|
||
return `${pad(d.getHours())}:${pad(d.getMinutes())}`;
|
||
}
|
||
|
||
/**
|
||
* Форматировать период события для отображения
|
||
* @param {Object} event - Объект события
|
||
* @param {string} event.start_date - Дата начала
|
||
* @param {string} event.end_date - Дата окончания
|
||
* @param {string} [event.start_time] - Время начала
|
||
* @param {string} [event.end_time] - Время окончания
|
||
* @param {boolean} [event.all_day] - Флаг целодневного события
|
||
* @returns {string} Форматированная строка периода
|
||
*/
|
||
export function formatEventPeriod(event) {
|
||
const start = fmtDate(event.start_date);
|
||
const end = fmtDate(event.end_date);
|
||
|
||
if (event.all_day) {
|
||
return start === end ? start : `${start} — ${end}`;
|
||
}
|
||
|
||
const startTime = event.start_time || "00:00";
|
||
const endTime = event.end_time || "23:59";
|
||
|
||
if (start === end) {
|
||
return `${start} ${startTime} — ${endTime}`;
|
||
}
|
||
|
||
return `${start} ${startTime} — ${end} ${endTime}`;
|
||
}
|
||
|
||
/**
|
||
* Добавить параметры диапазона дат к URL
|
||
* @param {URL} url - URL объект
|
||
* @param {Date} start - Начало периода
|
||
* @param {Date} end - Конец периода
|
||
* @returns {URL} URL с добавленными параметрами
|
||
*/
|
||
export function addDateRangeToUrl(url, start, end) {
|
||
url.searchParams.set("start", formatDate(start));
|
||
url.searchParams.set("end", formatDate(end));
|
||
return url;
|
||
}
|
||
|
||
/**
|
||
* Парсить дату из строки в формате YYYY-MM-DD
|
||
* @param {string} dateStr - Строка даты
|
||
* @returns {Date|null} Объект Date или null если невалидная дата
|
||
*/
|
||
export function parseDate(dateStr) {
|
||
if (!dateStr) return null;
|
||
const date = new Date(dateStr);
|
||
return isNaN(date.getTime()) ? null : date;
|
||
}
|
||
|
||
/**
|
||
* Получить начало дня для даты
|
||
* @param {Date} date - Дата
|
||
* @returns {Date} Дата с временем 00:00:00
|
||
*/
|
||
export function startOfDay(date) {
|
||
const d = new Date(date);
|
||
d.setHours(0, 0, 0, 0);
|
||
return d;
|
||
}
|
||
|
||
/**
|
||
* Получить конец дня для даты
|
||
* @param {Date} date - Дата
|
||
* @returns {Date} Дата с временем 23:59:59
|
||
*/
|
||
export function endOfDay(date) {
|
||
const d = new Date(date);
|
||
d.setHours(23, 59, 59, 999);
|
||
return d;
|
||
}
|