feat: унифицированный список календарей (legacy + новые)
- calendarManager.js: добавлена функция createLegacyCalendars() для создания pseudo-calendar объектов
- loadCalendars() теперь объединяет legacy (Компания, Личный, Отделы) и новые календари в единый массив
- calendarWidgetIntegration.js: обновлена логика fetchEventsForVisibleCalendars для работы с legacy ID
- legacy-company: все события без фильтров
- legacy-personal: события текущего сотрудника (employee_id)
- legacy-dept-{id}: события конкретного отдела (department_id)
- calendar_desktop.html: удален старый dropdown, оставлен только унифицированный список с чекбоксами
- Все календари теперь в одном списке с возможностью выбора через чекбоксы
- Цвета: Компания (красный), Личный (синий), Отделы (зеленый), новые календари (свои цвета)
This commit is contained in:
parent
299559ab4f
commit
024d3085ea
@ -35,25 +35,78 @@ export function initCalendarManager(options = {}) {
|
||||
let calendars = [];
|
||||
let visibleCalendarIds = new Set();
|
||||
|
||||
/**
|
||||
* Создать псевдо-календари для legacy режима
|
||||
* @returns {Array} Legacy календари
|
||||
*/
|
||||
function createLegacyCalendars() {
|
||||
const legacyCalendars = [
|
||||
{
|
||||
id: 'legacy-company',
|
||||
title: 'Компания',
|
||||
description: 'Корпоративные события',
|
||||
color: '#dc3545',
|
||||
calendar_type: 'company',
|
||||
is_legacy: true,
|
||||
is_global: true,
|
||||
user_can_edit: false,
|
||||
user_can_view: true,
|
||||
is_subscribed: true
|
||||
},
|
||||
{
|
||||
id: 'legacy-personal',
|
||||
title: 'Личный календарь',
|
||||
description: 'Мои личные события',
|
||||
color: '#0d6efd',
|
||||
calendar_type: 'personal',
|
||||
is_legacy: true,
|
||||
is_personal: true,
|
||||
user_can_edit: true,
|
||||
user_can_view: true,
|
||||
is_subscribed: true
|
||||
}
|
||||
];
|
||||
|
||||
// Добавить календари отделов
|
||||
const deptIds = window.calendarWidget?.getDepartments?.() || [];
|
||||
deptIds.forEach((deptId, index) => {
|
||||
legacyCalendars.push({
|
||||
id: `legacy-dept-${deptId}`,
|
||||
title: `Отдел ${deptId}`,
|
||||
description: 'События отдела',
|
||||
color: '#198754',
|
||||
calendar_type: 'department',
|
||||
department_id: deptId,
|
||||
is_legacy: true,
|
||||
is_department: true,
|
||||
user_can_edit: false,
|
||||
user_can_view: true,
|
||||
is_subscribed: true
|
||||
});
|
||||
});
|
||||
|
||||
return legacyCalendars;
|
||||
}
|
||||
|
||||
/**
|
||||
* Загрузить список календарей
|
||||
*/
|
||||
async function loadCalendars() {
|
||||
try {
|
||||
calendars = await getMyCalendars();
|
||||
// Загрузить новые Calendar записи
|
||||
const newCalendars = await getMyCalendars();
|
||||
|
||||
// Если календарей нет - не обновляем состояние (используем legacy режим)
|
||||
if (calendars.length === 0) {
|
||||
console.log('[CalendarManager] No calendars found, keeping legacy mode');
|
||||
container.innerHTML = `
|
||||
<div class="text-center text-muted py-3">
|
||||
<i class="bi-calendar-x mb-2" style="font-size: 2rem;"></i>
|
||||
<p class="mb-0">Календари не настроены</p>
|
||||
<small>События отображаются в классическом режиме</small>
|
||||
</div>
|
||||
`;
|
||||
return;
|
||||
}
|
||||
// Добавить legacy календари
|
||||
const legacyCalendars = createLegacyCalendars();
|
||||
|
||||
// Объединить оба списка
|
||||
calendars = [...legacyCalendars, ...newCalendars];
|
||||
|
||||
console.log('[CalendarManager] Loaded calendars:', {
|
||||
legacy: legacyCalendars.length,
|
||||
new: newCalendars.length,
|
||||
total: calendars.length
|
||||
});
|
||||
|
||||
// По умолчанию все календари видимы
|
||||
visibleCalendarIds = new Set(calendars.map(cal => cal.id));
|
||||
|
||||
@ -41,27 +41,65 @@ export function integrateCalendarManager(calendarWidgetInstance, options = {}) {
|
||||
range: `${startStr} - ${endStr}`
|
||||
});
|
||||
|
||||
// Если нет календарей в новой системе, используем legacy режим (показываем ВСЕ события)
|
||||
if (calendars.length === 0) {
|
||||
console.log('[CalendarIntegration] No calendars configured, using legacy mode (showing all events)');
|
||||
return await getCalendarEvents({
|
||||
start: startStr,
|
||||
end: endStr
|
||||
});
|
||||
}
|
||||
|
||||
// Если ни один календарь не выбран, ТОЖЕ показываем все события (legacy режим)
|
||||
// Если ни один календарь не выбран, показываем пустой результат
|
||||
if (visibleCalendarIds.length === 0) {
|
||||
console.log('[CalendarIntegration] No calendars selected, falling back to legacy mode');
|
||||
return await getCalendarEvents({
|
||||
start: startStr,
|
||||
end: endStr
|
||||
});
|
||||
console.log('[CalendarIntegration] No calendars selected, showing empty');
|
||||
return [];
|
||||
}
|
||||
|
||||
// Загружаем события для каждого видимого календаря
|
||||
const eventChunks = await Promise.all(
|
||||
visibleCalendarIds.map(async (calendarId) => {
|
||||
// Разделяем legacy и новые календари
|
||||
const legacyIds = [...visibleCalendarIds].filter(id => typeof id === 'string' && id.startsWith('legacy-'));
|
||||
const newIds = [...visibleCalendarIds].filter(id => typeof id === 'number');
|
||||
|
||||
console.log('[CalendarIntegration] Processing calendars:', { legacyIds, newIds });
|
||||
|
||||
let allEvents = [];
|
||||
|
||||
// Загружаем события для legacy календарей
|
||||
for (const legacyId of legacyIds) {
|
||||
try {
|
||||
let events = [];
|
||||
const calendar = calendars.find(c => c.id === legacyId);
|
||||
|
||||
if (legacyId === 'legacy-company') {
|
||||
// Компания: все события без фильтров
|
||||
console.log('[CalendarIntegration] Loading company events (all)');
|
||||
events = await getCalendarEvents({ start: startStr, end: endStr });
|
||||
} else if (legacyId === 'legacy-personal') {
|
||||
// Личный: события текущего сотрудника
|
||||
console.log('[CalendarIntegration] Loading personal events for current employee');
|
||||
events = await getCalendarEvents({
|
||||
start: startStr,
|
||||
end: endStr,
|
||||
employee_id: window.currentEmployeeId || null
|
||||
});
|
||||
} else if (legacyId.startsWith('legacy-dept-')) {
|
||||
// Отдел: события конкретного отдела
|
||||
const deptId = parseInt(legacyId.replace('legacy-dept-', ''), 10);
|
||||
console.log(`[CalendarIntegration] Loading department events for dept ${deptId}`);
|
||||
events = await getCalendarEvents({
|
||||
start: startStr,
|
||||
end: endStr,
|
||||
department_id: deptId
|
||||
});
|
||||
}
|
||||
|
||||
// Добавляем информацию о legacy календаре
|
||||
allEvents.push(...(events || []).map(event => ({
|
||||
...event,
|
||||
__calendar: calendar,
|
||||
color: calendar?.color || event.color
|
||||
})));
|
||||
|
||||
console.log(`[CalendarIntegration] Loaded ${events?.length || 0} events for legacy calendar ${legacyId}`);
|
||||
} catch (error) {
|
||||
console.error(`[CalendarIntegration] Error loading legacy calendar ${legacyId}:`, error);
|
||||
}
|
||||
}
|
||||
|
||||
// Загружаем события для новых календарей
|
||||
const newEventChunks = await Promise.all(
|
||||
newIds.map(async (calendarId) => {
|
||||
try {
|
||||
const events = await getCalendarEvents({
|
||||
start: startStr,
|
||||
@ -69,14 +107,13 @@ export function integrateCalendarManager(calendarWidgetInstance, options = {}) {
|
||||
calendar_id: calendarId
|
||||
});
|
||||
|
||||
console.log(`[CalendarIntegration] Loaded ${events?.length || 0} events for calendar ${calendarId}`);
|
||||
console.log(`[CalendarIntegration] Loaded ${events?.length || 0} events for new calendar ${calendarId}`);
|
||||
|
||||
// Добавляем информацию о календаре к каждому событию
|
||||
// Добавляем информацию о календаре
|
||||
const calendar = calendars.find(c => c.id === calendarId);
|
||||
return (events || []).map(event => ({
|
||||
...event,
|
||||
__calendar: calendar,
|
||||
// Переопределяем цвет события цветом календаря
|
||||
color: calendar?.color || event.color
|
||||
}));
|
||||
} catch (error) {
|
||||
@ -86,8 +123,9 @@ export function integrateCalendarManager(calendarWidgetInstance, options = {}) {
|
||||
})
|
||||
);
|
||||
|
||||
// Объединяем все события
|
||||
const allEvents = eventChunks.flat();
|
||||
// Объединяем события из новых календарей
|
||||
allEvents.push(...newEventChunks.flat());
|
||||
|
||||
console.log(`[CalendarIntegration] Total events loaded: ${allEvents.length}`);
|
||||
|
||||
// Дедупликация по ID
|
||||
|
||||
@ -6,28 +6,7 @@
|
||||
<div class="d-flex align-items-center gap-2 flex-shrink-1 min-w-0">
|
||||
<h6 class="card-title fw-semibold mb-0">Календарь</h6>
|
||||
|
||||
{# Выпадающий выбор: Компания / Отделы / Личный (LEGACY) #}
|
||||
<div class="dropdown">
|
||||
<button
|
||||
class="btn btn-sm btn-outline-secondary dropdown-toggle text-truncate"
|
||||
type="button"
|
||||
id="calendarChooserBtn"
|
||||
data-bs-toggle="dropdown"
|
||||
aria-expanded="false"
|
||||
style="max-width: 150px;"
|
||||
>
|
||||
Компания
|
||||
</button>
|
||||
<ul class="dropdown-menu" aria-labelledby="calendarChooserBtn" id="calendarChooserMenu">
|
||||
<li><button class="dropdown-item" type="button" data-cal="personal">Личный</button></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><button class="dropdown-item" type="button" data-cal="company">Компания</button></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
{# пункты отделов добавим из JS по data-dept-id #}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{# Кнопка списка календарей (NEW) #}
|
||||
{# Кнопка списка календарей #}
|
||||
<button
|
||||
class="btn btn-sm btn-outline-primary"
|
||||
type="button"
|
||||
@ -35,9 +14,10 @@
|
||||
data-bs-target="#calendarListCollapse"
|
||||
aria-expanded="false"
|
||||
aria-controls="calendarListCollapse"
|
||||
title="Мои календари"
|
||||
title="Список календарей"
|
||||
>
|
||||
<i class="bi-list-check"></i>
|
||||
<span class="ms-1">Календари</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@ -65,16 +45,16 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# Список календарей (сворачиваемый) - НОВАЯ ФУНКЦИЯ #}
|
||||
{# Список календарей (сворачиваемый) - унифицированный список legacy + новые #}
|
||||
<div class="collapse" id="calendarListCollapse">
|
||||
<div class="card-body border-bottom py-2">
|
||||
<small class="text-muted d-block mb-2">
|
||||
<i class="bi-info-circle me-1"></i>
|
||||
Управление несколькими календарями
|
||||
Выберите календари для отображения
|
||||
</small>
|
||||
<div id="calendarListContainer" class="calendar-list-container" style="max-height: 200px;">
|
||||
<div id="calendarListContainer" class="calendar-list-container" style="max-height: 250px; overflow-y: auto;">
|
||||
|
||||
{# Здесь будет JS-генерируемый список календарей #}
|
||||
{# Здесь будет JS-генерируемый список календарей (legacy + новые) #}
|
||||
<div class="text-center py-3">
|
||||
<div class="spinner-border spinner-border-sm text-primary" role="status">
|
||||
<span class="visually-hidden">Загрузка...</span>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user