|
|
@@ -203,13 +203,13 @@
|
|
|
.error-popover-arrow {
|
|
|
position: absolute;
|
|
|
top: -6px;
|
|
|
- left: 12px;
|
|
|
+ left: 50%;
|
|
|
width: 12px;
|
|
|
height: 12px;
|
|
|
background: var(--color-bg-card);
|
|
|
border-left: 1px solid rgba(220, 53, 69, 0.3);
|
|
|
border-top: 1px solid rgba(220, 53, 69, 0.3);
|
|
|
- transform: rotate(45deg);
|
|
|
+ transform: rotate(45deg) translateX(-50%);
|
|
|
}
|
|
|
</style>
|
|
|
{% endblock %}
|
|
|
@@ -459,31 +459,37 @@ function confirmDelete(id, name) {
|
|
|
let currentPopover = null;
|
|
|
|
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
|
- document.querySelectorAll('.error-indicator').forEach(indicator => {
|
|
|
- indicator.addEventListener('mouseenter', function(e) {
|
|
|
- showErrorPopover(this, e);
|
|
|
+ document.addEventListener('mouseenter', function(e) {
|
|
|
+ const indicator = e.target.closest('.error-indicator');
|
|
|
+ if (indicator) {
|
|
|
+ showErrorPopover(indicator, e);
|
|
|
+ }
|
|
|
});
|
|
|
|
|
|
- indicator.addEventListener('mouseleave', function() {
|
|
|
- hideErrorPopover();
|
|
|
+ document.addEventListener('mouseleave', function(e) {
|
|
|
+ const indicator = e.target.closest('.error-indicator');
|
|
|
+ if (indicator) {
|
|
|
+ const relatedTarget = e.relatedTarget;
|
|
|
+ if (!relatedTarget || !relatedTarget.closest('.error-indicator') || !relatedTarget.closest('.error-popover')) {
|
|
|
+ hideErrorPopover();
|
|
|
+ }
|
|
|
+ }
|
|
|
});
|
|
|
|
|
|
- indicator.addEventListener('click', function(e) {
|
|
|
- e.stopPropagation();
|
|
|
- if (currentPopover && currentPopover.dataset.visible === 'true') {
|
|
|
+ document.addEventListener('click', function(e) {
|
|
|
+ const indicator = e.target.closest('.error-indicator');
|
|
|
+ if (indicator) {
|
|
|
+ e.stopPropagation();
|
|
|
+ if (currentPopover && currentPopover.dataset.visible === 'true') {
|
|
|
+ hideErrorPopover();
|
|
|
+ } else {
|
|
|
+ showErrorPopover(indicator, e);
|
|
|
+ }
|
|
|
+ } else if (currentPopover && !currentPopover.contains(e.target)) {
|
|
|
hideErrorPopover();
|
|
|
- } else {
|
|
|
- showErrorPopover(this, e);
|
|
|
}
|
|
|
});
|
|
|
});
|
|
|
-
|
|
|
- document.addEventListener('click', function(e) {
|
|
|
- if (currentPopover && !currentPopover.contains(e.target) && !e.target.classList.contains('error-indicator')) {
|
|
|
- hideErrorPopover();
|
|
|
- }
|
|
|
- });
|
|
|
-});
|
|
|
|
|
|
function showErrorPopover(indicator, event) {
|
|
|
hideErrorPopover();
|
|
|
@@ -505,8 +511,30 @@ function showErrorPopover(indicator, event) {
|
|
|
`;
|
|
|
|
|
|
const rect = indicator.getBoundingClientRect();
|
|
|
+ const arrowOffset = 12;
|
|
|
+ const gap = 8;
|
|
|
+
|
|
|
popover.style.left = rect.left + 'px';
|
|
|
- popover.style.top = (rect.bottom + 8) + 'px';
|
|
|
+ popover.style.top = (rect.bottom + gap) + 'px';
|
|
|
+
|
|
|
+ const arrow = popover.querySelector('.error-popover-arrow');
|
|
|
+ arrow.style.left = (rect.width / 2 - arrowOffset / 2) + 'px';
|
|
|
+
|
|
|
+ const popoverRect = popover.getBoundingClientRect();
|
|
|
+ const viewportWidth = window.innerWidth;
|
|
|
+ const viewportHeight = window.innerHeight;
|
|
|
+
|
|
|
+ if (popoverRect.right > viewportWidth) {
|
|
|
+ popover.style.left = (viewportWidth - popoverRect.width - 10) + 'px';
|
|
|
+ arrow.style.left = (rect.left + rect.width / 2 - popoverRect.left - arrowOffset / 2) + 'px';
|
|
|
+ }
|
|
|
+
|
|
|
+ if (popoverRect.bottom > viewportHeight) {
|
|
|
+ popover.style.top = (rect.top - popoverRect.height - gap) + 'px';
|
|
|
+ arrow.style.top = 'auto';
|
|
|
+ arrow.style.bottom = '-6px';
|
|
|
+ arrow.style.transform = 'rotate(225deg)';
|
|
|
+ }
|
|
|
|
|
|
document.body.appendChild(popover);
|
|
|
currentPopover = popover;
|