feat: enhance CI workflow and update webapp styles
Some checks failed
CI / lint-and-test (push) Failing after 45s
Some checks failed
CI / lint-and-test (push) Failing after 45s
- Added Node.js setup and webapp testing steps to the CI workflow for improved integration. - Updated HTML to link multiple CSS files for better modularity and organization of styles. - Removed deprecated `style.css` and introduced new CSS files for base styles, calendar, day detail, hints, markers, states, and duty list to enhance maintainability and readability. - Implemented new styles for improved presentation of duty information and user interactions. - Added unit tests for new API functions and contact link rendering to ensure functionality and reliability.
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
* Tooltips for calendar info buttons and duty markers.
|
||||
*/
|
||||
|
||||
import { calendarEl, state } from "./dom.js";
|
||||
import { getCalendarEl, state } from "./dom.js";
|
||||
import { t } from "./i18n.js";
|
||||
import { escapeHtml } from "./utils.js";
|
||||
import { localDateString, formatHHMM } from "./dateUtils.js";
|
||||
@@ -250,6 +250,7 @@ export function getDutyMarkerHintHtml(marker) {
|
||||
* Remove active class from all duty/unavailable/vacation markers.
|
||||
*/
|
||||
export function clearActiveDutyMarker() {
|
||||
const calendarEl = getCalendarEl();
|
||||
if (!calendarEl) return;
|
||||
calendarEl
|
||||
.querySelectorAll(
|
||||
@@ -261,6 +262,25 @@ export function clearActiveDutyMarker() {
|
||||
/** Timeout for hiding duty marker hint on mouseleave (delegated). */
|
||||
let dutyMarkerHideTimeout = null;
|
||||
|
||||
const HINT_FADE_MS = 150;
|
||||
|
||||
/**
|
||||
* Dismiss a hint with fade-out: remove visible class, then after delay set hidden and remove data-active.
|
||||
* @param {HTMLElement} hintEl - The hint element to dismiss
|
||||
* @param {{ clearActive?: boolean, afterHide?: () => void }} opts - Optional: call clearActiveDutyMarker after hide; callback after hide
|
||||
* @returns {number} Timeout id (for use with clearTimeout, e.g. when delegating hide to mouseout)
|
||||
*/
|
||||
export function dismissHint(hintEl, opts = {}) {
|
||||
hintEl.classList.remove("calendar-event-hint--visible");
|
||||
const id = setTimeout(() => {
|
||||
hintEl.hidden = true;
|
||||
hintEl.removeAttribute("data-active");
|
||||
if (opts.clearActive) clearActiveDutyMarker();
|
||||
if (typeof opts.afterHide === "function") opts.afterHide();
|
||||
}, HINT_FADE_MS);
|
||||
return id;
|
||||
}
|
||||
|
||||
const DUTY_MARKER_SELECTOR = ".duty-marker, .unavailable-marker, .vacation-marker";
|
||||
|
||||
/**
|
||||
@@ -304,6 +324,7 @@ function getOrCreateDutyMarkerHint() {
|
||||
export function initHints() {
|
||||
const calendarEventHint = getOrCreateCalendarEventHint();
|
||||
const dutyMarkerHint = getOrCreateDutyMarkerHint();
|
||||
const calendarEl = getCalendarEl();
|
||||
if (!calendarEl) return;
|
||||
|
||||
calendarEl.addEventListener("click", (e) => {
|
||||
@@ -317,11 +338,7 @@ export function initHints() {
|
||||
positionHint(calendarEventHint, btn.getBoundingClientRect());
|
||||
calendarEventHint.dataset.active = "1";
|
||||
} else {
|
||||
calendarEventHint.classList.remove("calendar-event-hint--visible");
|
||||
setTimeout(() => {
|
||||
calendarEventHint.hidden = true;
|
||||
calendarEventHint.removeAttribute("data-active");
|
||||
}, 150);
|
||||
dismissHint(calendarEventHint);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -330,11 +347,7 @@ export function initHints() {
|
||||
if (marker) {
|
||||
e.stopPropagation();
|
||||
if (marker.classList.contains("calendar-marker-active")) {
|
||||
dutyMarkerHint.classList.remove("calendar-event-hint--visible");
|
||||
setTimeout(() => {
|
||||
dutyMarkerHint.hidden = true;
|
||||
dutyMarkerHint.removeAttribute("data-active");
|
||||
}, 150);
|
||||
dismissHint(dutyMarkerHint);
|
||||
marker.classList.remove("calendar-marker-active");
|
||||
return;
|
||||
}
|
||||
@@ -377,31 +390,23 @@ export function initHints() {
|
||||
const toMarker = e.relatedTarget instanceof HTMLElement ? e.relatedTarget.closest(DUTY_MARKER_SELECTOR) : null;
|
||||
if (toMarker) return;
|
||||
if (dutyMarkerHint.dataset.active) return;
|
||||
dutyMarkerHint.classList.remove("calendar-event-hint--visible");
|
||||
dutyMarkerHideTimeout = setTimeout(() => {
|
||||
dutyMarkerHint.hidden = true;
|
||||
dutyMarkerHideTimeout = null;
|
||||
}, 150);
|
||||
dutyMarkerHideTimeout = dismissHint(dutyMarkerHint, {
|
||||
afterHide: () => {
|
||||
dutyMarkerHideTimeout = null;
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
if (!state.calendarHintBound) {
|
||||
state.calendarHintBound = true;
|
||||
document.addEventListener("click", () => {
|
||||
if (calendarEventHint.dataset.active) {
|
||||
calendarEventHint.classList.remove("calendar-event-hint--visible");
|
||||
setTimeout(() => {
|
||||
calendarEventHint.hidden = true;
|
||||
calendarEventHint.removeAttribute("data-active");
|
||||
}, 150);
|
||||
dismissHint(calendarEventHint);
|
||||
}
|
||||
});
|
||||
document.addEventListener("keydown", (e) => {
|
||||
if (e.key === "Escape" && calendarEventHint.dataset.active) {
|
||||
calendarEventHint.classList.remove("calendar-event-hint--visible");
|
||||
setTimeout(() => {
|
||||
calendarEventHint.hidden = true;
|
||||
calendarEventHint.removeAttribute("data-active");
|
||||
}, 150);
|
||||
dismissHint(calendarEventHint);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -410,22 +415,12 @@ export function initHints() {
|
||||
state.dutyMarkerHintBound = true;
|
||||
document.addEventListener("click", () => {
|
||||
if (dutyMarkerHint.dataset.active) {
|
||||
dutyMarkerHint.classList.remove("calendar-event-hint--visible");
|
||||
setTimeout(() => {
|
||||
dutyMarkerHint.hidden = true;
|
||||
dutyMarkerHint.removeAttribute("data-active");
|
||||
clearActiveDutyMarker();
|
||||
}, 150);
|
||||
dismissHint(dutyMarkerHint, { clearActive: true });
|
||||
}
|
||||
});
|
||||
document.addEventListener("keydown", (e) => {
|
||||
if (e.key === "Escape" && dutyMarkerHint.dataset.active) {
|
||||
dutyMarkerHint.classList.remove("calendar-event-hint--visible");
|
||||
setTimeout(() => {
|
||||
dutyMarkerHint.hidden = true;
|
||||
dutyMarkerHint.removeAttribute("data-active");
|
||||
clearActiveDutyMarker();
|
||||
}, 150);
|
||||
dismissHint(dutyMarkerHint, { clearActive: true });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user