Refactor calendar rendering and duty list display
- Updated the calendar cell rendering to conditionally show duty and event markers based on the month view. - Introduced a new HTML structure for day markers to improve layout and styling. - Enhanced the duty list rendering to filter duties based on the current month, ensuring only relevant duties are displayed. - Added CSS styles for day markers to improve visual presentation and alignment.
This commit is contained in:
@@ -207,25 +207,29 @@
|
||||
const hasEvent = eventSummaries.length > 0;
|
||||
|
||||
const cell = document.createElement("div");
|
||||
cell.className = "day" + (isOther ? " other-month" : "") + (isToday ? " today" : "") + (hasAny ? " has-duty" : "") + (hasEvent ? " holiday" : "");
|
||||
const showMarkers = !isOther;
|
||||
cell.className = "day" + (isOther ? " other-month" : "") + (isToday ? " today" : "") + (showMarkers && hasAny ? " has-duty" : "") + (showMarkers && hasEvent ? " holiday" : "");
|
||||
|
||||
function namesAttr(list) { return list.length ? escapeHtml(list.map(function (x) { return x.full_name; }).join("\n")) : ""; }
|
||||
function titleAttr(list) { return list.length ? escapeHtml(list.map(function (x) { return x.full_name; }).join(", ")) : ""; }
|
||||
|
||||
let markers = "<span class=\"num\">" + d.getDate() + "</span>";
|
||||
if (dutyList.length) {
|
||||
markers += "<span class=\"duty-marker\" data-names=\"" + namesAttr(dutyList) + "\" title=\"" + titleAttr(dutyList) + "\" aria-label=\"Дежурные\">Д</span>";
|
||||
let html = "<span class=\"num\">" + d.getDate() + "</span><div class=\"day-markers\">";
|
||||
if (showMarkers) {
|
||||
if (dutyList.length) {
|
||||
html += "<span class=\"duty-marker\" data-names=\"" + namesAttr(dutyList) + "\" title=\"" + titleAttr(dutyList) + "\" aria-label=\"Дежурные\">Д</span>";
|
||||
}
|
||||
if (unavailableList.length) {
|
||||
html += "<span class=\"unavailable-marker\" data-names=\"" + namesAttr(unavailableList) + "\" title=\"" + titleAttr(unavailableList) + "\" aria-label=\"Недоступен\">Н</span>";
|
||||
}
|
||||
if (vacationList.length) {
|
||||
html += "<span class=\"vacation-marker\" data-names=\"" + namesAttr(vacationList) + "\" title=\"" + titleAttr(vacationList) + "\" aria-label=\"Отпуск\">О</span>";
|
||||
}
|
||||
if (hasEvent) {
|
||||
html += "<button type=\"button\" class=\"info-btn\" aria-label=\"Информация о дне\" data-summary=\"" + escapeHtml(eventSummaries.join("\n")) + "\">i</button>";
|
||||
}
|
||||
}
|
||||
if (unavailableList.length) {
|
||||
markers += "<span class=\"unavailable-marker\" data-names=\"" + namesAttr(unavailableList) + "\" title=\"" + titleAttr(unavailableList) + "\" aria-label=\"Недоступен\">Н</span>";
|
||||
}
|
||||
if (vacationList.length) {
|
||||
markers += "<span class=\"vacation-marker\" data-names=\"" + namesAttr(vacationList) + "\" title=\"" + titleAttr(vacationList) + "\" aria-label=\"Отпуск\">О</span>";
|
||||
}
|
||||
if (hasEvent) {
|
||||
markers += "<button type=\"button\" class=\"info-btn\" aria-label=\"Информация о дне\" data-summary=\"" + escapeHtml(eventSummaries.join("\n")) + "\">i</button>";
|
||||
}
|
||||
cell.innerHTML = markers;
|
||||
html += "</div>";
|
||||
cell.innerHTML = html;
|
||||
calendarEl.appendChild(cell);
|
||||
d.setDate(d.getDate() + 1);
|
||||
}
|
||||
@@ -470,8 +474,12 @@
|
||||
setNavEnabled(false);
|
||||
loadingEl.classList.remove("hidden");
|
||||
errorEl.hidden = true;
|
||||
const from = localDateString(firstDayOfMonth(current));
|
||||
const to = localDateString(lastDayOfMonth(current));
|
||||
const first = firstDayOfMonth(current);
|
||||
const start = getMonday(first);
|
||||
const gridEnd = new Date(start);
|
||||
gridEnd.setDate(gridEnd.getDate() + 41);
|
||||
const from = localDateString(start);
|
||||
const to = localDateString(gridEnd);
|
||||
try {
|
||||
const dutiesPromise = fetchDuties(from, to);
|
||||
const eventsPromise = fetchCalendarEvents(from, to);
|
||||
@@ -480,7 +488,16 @@
|
||||
const byDate = dutiesByDate(duties);
|
||||
const calendarByDate = calendarEventsByDate(events);
|
||||
renderCalendar(current.getFullYear(), current.getMonth(), byDate, calendarByDate);
|
||||
renderDutyList(duties);
|
||||
const last = lastDayOfMonth(current);
|
||||
const firstKey = localDateString(first);
|
||||
const lastKey = localDateString(last);
|
||||
const dutiesInMonth = duties.filter(function (d) {
|
||||
const byDateLocal = dutiesByDate([d]);
|
||||
return Object.keys(byDateLocal).some(function (key) {
|
||||
return key >= firstKey && key <= lastKey;
|
||||
});
|
||||
});
|
||||
renderDutyList(dutiesInMonth);
|
||||
} catch (e) {
|
||||
if (e.message === "ACCESS_DENIED") {
|
||||
showAccessDenied(e.serverDetail);
|
||||
|
||||
@@ -143,6 +143,17 @@ body {
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.day-markers {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
gap: 2px;
|
||||
align-items: center;
|
||||
margin-top: 2px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.calendar-event-hint {
|
||||
position: fixed;
|
||||
z-index: 1000;
|
||||
@@ -170,10 +181,9 @@ body {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-top: 2px;
|
||||
font-size: 0.65rem;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
font-size: 0.6rem;
|
||||
font-weight: 700;
|
||||
border-radius: 50%;
|
||||
flex-shrink: 0;
|
||||
@@ -205,6 +215,10 @@ body {
|
||||
}
|
||||
|
||||
.duty-item {
|
||||
display: grid;
|
||||
grid-template-columns: 5.5em 1fr;
|
||||
gap: 0 8px;
|
||||
align-items: baseline;
|
||||
padding: 8px 10px;
|
||||
margin-bottom: 6px;
|
||||
border-radius: 8px;
|
||||
@@ -221,16 +235,23 @@ body {
|
||||
}
|
||||
|
||||
.duty-item .duty-item-type {
|
||||
grid-column: 1;
|
||||
grid-row: 1;
|
||||
font-size: 0.75rem;
|
||||
color: var(--muted);
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.duty-item .name {
|
||||
grid-column: 2;
|
||||
grid-row: 1 / -1;
|
||||
min-width: 0;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.duty-item .time {
|
||||
grid-column: 1;
|
||||
grid-row: 2;
|
||||
align-self: start;
|
||||
font-size: 0.8rem;
|
||||
color: var(--muted);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user