fix: enhance duty marker hint rendering and styling
- Introduced a new function `getDutyMarkerHintHtml` to generate HTML for duty hints, improving the display of duty times and names. - Updated the CSS for `.calendar-event-hint` to enhance layout and styling, ensuring better visual alignment and readability. - Adjusted the handling of duty items to include non-breaking spaces for improved formatting of time displays. - Removed deprecated CSS rules related to sticky elements to streamline styles and improve maintainability.
This commit is contained in:
@@ -431,6 +431,7 @@
|
|||||||
});
|
});
|
||||||
if (dutyItems.length >= 1 && hasTimes) {
|
if (dutyItems.length >= 1 && hasTimes) {
|
||||||
var hintDay = marker.getAttribute("data-date") || "";
|
var hintDay = marker.getAttribute("data-date") || "";
|
||||||
|
var nbsp = "\u00a0";
|
||||||
body = dutyItems.map(function (item, idx) {
|
body = dutyItems.map(function (item, idx) {
|
||||||
var startAt = item.start_at != null ? item.start_at : item.startAt;
|
var startAt = item.start_at != null ? item.start_at : item.startAt;
|
||||||
var endAt = item.end_at != null ? item.end_at : item.endAt;
|
var endAt = item.end_at != null ? item.end_at : item.endAt;
|
||||||
@@ -439,19 +440,19 @@
|
|||||||
var startSameDay = hintDay && startAt && localDateString(new Date(startAt)) === hintDay;
|
var startSameDay = hintDay && startAt && localDateString(new Date(startAt)) === hintDay;
|
||||||
var endSameDay = hintDay && endAt && localDateString(new Date(endAt)) === hintDay;
|
var endSameDay = hintDay && endAt && localDateString(new Date(endAt)) === hintDay;
|
||||||
var fullName = item.full_name != null ? item.full_name : item.fullName;
|
var fullName = item.full_name != null ? item.full_name : item.fullName;
|
||||||
var parts = [fullName];
|
var timePrefix = "";
|
||||||
if (idx === 0) {
|
if (idx === 0) {
|
||||||
if (startSameDay && startHHMM) {
|
if (dutyItems.length === 1 && startSameDay && startHHMM) {
|
||||||
parts.push("с " + startHHMM);
|
timePrefix = "с" + nbsp + startHHMM;
|
||||||
if (endSameDay && endHHMM && endHHMM !== startHHMM) { parts.push("до " + endHHMM); }
|
if (endSameDay && endHHMM && endHHMM !== startHHMM) { timePrefix += " до" + nbsp + endHHMM; }
|
||||||
} else if (endHHMM) {
|
} else if (endHHMM) {
|
||||||
parts.push("до " + endHHMM);
|
timePrefix = "до" + nbsp + endHHMM;
|
||||||
}
|
}
|
||||||
} else if (idx > 0) {
|
} else if (idx > 0) {
|
||||||
if (startHHMM) { parts.push("с " + startHHMM); }
|
if (startHHMM) { timePrefix = "с" + nbsp + startHHMM; }
|
||||||
if (endHHMM && endSameDay && endHHMM !== startHHMM) { parts.push("до " + endHHMM); }
|
if (endHHMM && endSameDay && endHHMM !== startHHMM) { timePrefix += (timePrefix ? " " : "") + "до" + nbsp + endHHMM; }
|
||||||
}
|
}
|
||||||
return parts.join(", ");
|
return timePrefix ? timePrefix + " — " + fullName : fullName;
|
||||||
}).join("\n");
|
}).join("\n");
|
||||||
} else {
|
} else {
|
||||||
body = names;
|
body = names;
|
||||||
@@ -462,6 +463,61 @@
|
|||||||
return body ? label + ":\n" + body : label;
|
return body ? label + ":\n" + body : label;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Returns HTML for duty hint with aligned times and no wrap inside name, or null to use textContent. */
|
||||||
|
function getDutyMarkerHintHtml(marker) {
|
||||||
|
var type = marker.getAttribute("data-event-type") || "duty";
|
||||||
|
if (type !== "duty") { return null; }
|
||||||
|
var names = marker.getAttribute("data-names") || "";
|
||||||
|
var dutyItemsRaw = marker.getAttribute("data-duty-items") || (marker.dataset && marker.dataset.dutyItems) || "";
|
||||||
|
var dutyItems = [];
|
||||||
|
try {
|
||||||
|
if (dutyItemsRaw) { dutyItems = JSON.parse(dutyItemsRaw); }
|
||||||
|
} catch (e) { /* ignore */ }
|
||||||
|
var hasTimes = dutyItems.length > 0 && dutyItems.some(function (it) {
|
||||||
|
var start = it.start_at != null ? it.start_at : it.startAt;
|
||||||
|
var end = it.end_at != null ? it.end_at : it.endAt;
|
||||||
|
return start || end;
|
||||||
|
});
|
||||||
|
var hintDay = marker.getAttribute("data-date") || "";
|
||||||
|
var nbsp = "\u00a0";
|
||||||
|
var rows;
|
||||||
|
if (dutyItems.length >= 1 && hasTimes) {
|
||||||
|
rows = dutyItems.map(function (item, idx) {
|
||||||
|
var startAt = item.start_at != null ? item.start_at : item.startAt;
|
||||||
|
var endAt = item.end_at != null ? item.end_at : item.endAt;
|
||||||
|
var endHHMM = endAt ? formatHHMM(endAt) : "";
|
||||||
|
var startHHMM = startAt ? formatHHMM(startAt) : "";
|
||||||
|
var startSameDay = hintDay && startAt && localDateString(new Date(startAt)) === hintDay;
|
||||||
|
var endSameDay = hintDay && endAt && localDateString(new Date(endAt)) === hintDay;
|
||||||
|
var fullName = item.full_name != null ? item.full_name : item.fullName;
|
||||||
|
var timePrefix = "";
|
||||||
|
if (idx === 0) {
|
||||||
|
if (dutyItems.length === 1 && startSameDay && startHHMM) {
|
||||||
|
timePrefix = "с" + nbsp + startHHMM;
|
||||||
|
if (endSameDay && endHHMM && endHHMM !== startHHMM) { timePrefix += " до" + nbsp + endHHMM; }
|
||||||
|
} else if (endHHMM) {
|
||||||
|
timePrefix = "до" + nbsp + endHHMM;
|
||||||
|
}
|
||||||
|
} else if (idx > 0) {
|
||||||
|
if (startHHMM) { timePrefix = "с" + nbsp + startHHMM; }
|
||||||
|
if (endHHMM && endSameDay && endHHMM !== startHHMM) { timePrefix += (timePrefix ? " " : "") + "до" + nbsp + endHHMM; }
|
||||||
|
}
|
||||||
|
var timeHtml = timePrefix ? escapeHtml(timePrefix) : "";
|
||||||
|
var nameHtml = escapeHtml(fullName);
|
||||||
|
var namePart = timePrefix ? " — " + nameHtml : nameHtml;
|
||||||
|
return "<span class=\"calendar-event-hint-time\">" + timeHtml + "</span><span class=\"calendar-event-hint-name\">" + namePart + "</span>";
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
rows = (names ? names.split("\n") : []).map(function (fullName) {
|
||||||
|
var nameHtml = escapeHtml(fullName.trim());
|
||||||
|
return "<span class=\"calendar-event-hint-time\"></span><span class=\"calendar-event-hint-name\">" + nameHtml + "</span>";
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (rows.length === 0) { return null; }
|
||||||
|
return "<div class=\"calendar-event-hint-title\">Дежурство:</div><div class=\"calendar-event-hint-rows\">" +
|
||||||
|
rows.map(function (r) { return "<div class=\"calendar-event-hint-row\">" + r + "</div>"; }).join("") + "</div>";
|
||||||
|
}
|
||||||
|
|
||||||
function clearActiveDutyMarker() {
|
function clearActiveDutyMarker() {
|
||||||
calendarEl.querySelectorAll(".duty-marker.calendar-marker-active, .unavailable-marker.calendar-marker-active, .vacation-marker.calendar-marker-active")
|
calendarEl.querySelectorAll(".duty-marker.calendar-marker-active, .unavailable-marker.calendar-marker-active, .vacation-marker.calendar-marker-active")
|
||||||
.forEach(function (m) { m.classList.remove("calendar-marker-active"); });
|
.forEach(function (m) { m.classList.remove("calendar-marker-active"); });
|
||||||
@@ -485,7 +541,12 @@
|
|||||||
clearTimeout(hideTimeout);
|
clearTimeout(hideTimeout);
|
||||||
hideTimeout = null;
|
hideTimeout = null;
|
||||||
}
|
}
|
||||||
hintEl.textContent = getDutyMarkerHintContent(marker);
|
var html = getDutyMarkerHintHtml(marker);
|
||||||
|
if (html) {
|
||||||
|
hintEl.innerHTML = html;
|
||||||
|
} else {
|
||||||
|
hintEl.textContent = getDutyMarkerHintContent(marker);
|
||||||
|
}
|
||||||
var rect = marker.getBoundingClientRect();
|
var rect = marker.getBoundingClientRect();
|
||||||
positionHint(hintEl, rect);
|
positionHint(hintEl, rect);
|
||||||
hintEl.hidden = false;
|
hintEl.hidden = false;
|
||||||
@@ -506,7 +567,12 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
clearActiveDutyMarker();
|
clearActiveDutyMarker();
|
||||||
hintEl.textContent = getDutyMarkerHintContent(marker);
|
var html = getDutyMarkerHintHtml(marker);
|
||||||
|
if (html) {
|
||||||
|
hintEl.innerHTML = html;
|
||||||
|
} else {
|
||||||
|
hintEl.textContent = getDutyMarkerHintContent(marker);
|
||||||
|
}
|
||||||
var rect = marker.getBoundingClientRect();
|
var rect = marker.getBoundingClientRect();
|
||||||
positionHint(hintEl, rect);
|
positionHint(hintEl, rect);
|
||||||
hintEl.hidden = false;
|
hintEl.hidden = false;
|
||||||
|
|||||||
@@ -70,6 +70,7 @@ body {
|
|||||||
max-width: 420px;
|
max-width: 420px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
padding: 12px;
|
padding: 12px;
|
||||||
|
padding-top: 0px;
|
||||||
padding-bottom: env(safe-area-inset-bottom, 12px);
|
padding-bottom: env(safe-area-inset-bottom, 12px);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,17 +132,6 @@ body {
|
|||||||
touch-action: pan-y;
|
touch-action: pan-y;
|
||||||
}
|
}
|
||||||
|
|
||||||
.calendar-sticky.is-scrolled {
|
|
||||||
box-shadow: 0 4px 6px -4px rgba(0, 0, 0, 0.25);
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-theme="light"] .calendar-sticky.is-scrolled {
|
|
||||||
box-shadow: 0 4px 6px -4px rgba(0, 0, 0, 0.08);
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-theme="dark"] .calendar-sticky.is-scrolled {
|
|
||||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.15);
|
|
||||||
}
|
|
||||||
|
|
||||||
.calendar {
|
.calendar {
|
||||||
display: grid;
|
display: grid;
|
||||||
@@ -228,7 +218,7 @@ body {
|
|||||||
position: fixed;
|
position: fixed;
|
||||||
z-index: 1000;
|
z-index: 1000;
|
||||||
width: max-content;
|
width: max-content;
|
||||||
max-width: min(280px, calc(100vw - 24px));
|
max-width: min(90vw, 600px);
|
||||||
padding: 8px 12px;
|
padding: 8px 12px;
|
||||||
background: var(--surface);
|
background: var(--surface);
|
||||||
color: var(--text);
|
color: var(--text);
|
||||||
@@ -236,15 +226,49 @@ body {
|
|||||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
|
||||||
font-size: 0.85rem;
|
font-size: 0.85rem;
|
||||||
line-height: 1.4;
|
line-height: 1.4;
|
||||||
white-space: pre-wrap;
|
white-space: pre;
|
||||||
word-break: break-word;
|
overflow: visible;
|
||||||
transform: translateY(-100%);
|
transform: translateY(-100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.calendar-event-hint .calendar-event-hint-rows {
|
||||||
|
white-space: normal;
|
||||||
|
}
|
||||||
|
|
||||||
.calendar-event-hint.below {
|
.calendar-event-hint.below {
|
||||||
transform: none;
|
transform: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.calendar-event-hint-title {
|
||||||
|
margin-bottom: 4px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-event-hint-rows {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-event-hint-row {
|
||||||
|
display: table;
|
||||||
|
width: max-content;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-event-hint-row .calendar-event-hint-time {
|
||||||
|
display: table-cell;
|
||||||
|
white-space: nowrap;
|
||||||
|
min-width: 8.5em;
|
||||||
|
vertical-align: top;
|
||||||
|
padding-right: 0.35em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-event-hint-row .calendar-event-hint-name {
|
||||||
|
display: table-cell;
|
||||||
|
white-space: nowrap !important;
|
||||||
|
}
|
||||||
|
|
||||||
/* Маркеры: компактный размер 11px, кнопки для доступности и тапа */
|
/* Маркеры: компактный размер 11px, кнопки для доступности и тапа */
|
||||||
.duty-marker,
|
.duty-marker,
|
||||||
.unavailable-marker,
|
.unavailable-marker,
|
||||||
|
|||||||
Reference in New Issue
Block a user