bug fixes and qol changes
This commit is contained in:
parent
7486c80656
commit
bae6c16a6b
|
|
@ -253,7 +253,8 @@ input.list-header-checkbox:checked::after {
|
|||
Sidebar — Full Width button
|
||||
========================================================================== */
|
||||
|
||||
.jey-fullwidth-link {
|
||||
.jey-fullwidth-link,
|
||||
.jey-theme-switch-link {
|
||||
text-decoration: none;
|
||||
font-size: var(--text-sm);
|
||||
display: flex;
|
||||
|
|
@ -262,18 +263,28 @@ input.list-header-checkbox:checked::after {
|
|||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.jey-fullwidth-link svg {
|
||||
.jey-fullwidth-link svg,
|
||||
.jey-theme-switch-link svg {
|
||||
margin: 0;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.jey-fullwidth-link span {
|
||||
.jey-fullwidth-link span,
|
||||
.jey-theme-switch-link span {
|
||||
margin-left: 10px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* Hide dropdown items now surfaced as sidebar buttons */
|
||||
.dropdown-menu-item[onclick*="toggle_full_width"],
|
||||
.dropdown-menu-item[onclick*="ThemeSwitcher"],
|
||||
.dropdown-menu-item[data-name="website"],
|
||||
.dropdown-menu-item.jey-hidden-item {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
|
||||
/* ==========================================================================
|
||||
Desktop Icons — Shared base (all themes)
|
||||
|
|
@ -467,7 +478,14 @@ input.list-header-checkbox:checked::after {
|
|||
transition: transform 0.3s cubic-bezier(0.22, 1, 0.36, 1),
|
||||
box-shadow 0.35s ease;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Allow dropdown menus (card actions) to escape the widget box.
|
||||
Without this, .widget-control .dropdown-menu is clipped/hidden behind
|
||||
the widget because Popper renders it as a sibling inside the box. */
|
||||
.ce-block .links-widget-box .widget-control .dropdown-menu,
|
||||
.ce-block .number-widget-box .widget-control .dropdown-menu {
|
||||
z-index: 1050;
|
||||
}
|
||||
|
||||
/* Stagger delays */
|
||||
|
|
@ -503,7 +521,7 @@ input.list-header-checkbox:checked::after {
|
|||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0) scale(1);
|
||||
transform: none;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -535,6 +553,18 @@ input.list-header-checkbox:checked::after {
|
|||
0 2px 6px rgba(0, 0, 0, 0.04);
|
||||
}
|
||||
|
||||
/* Lift widget above its siblings while hovered or while its card-actions
|
||||
dropdown is open, so the dropdown menu (which lives inside the widget's
|
||||
own stacking context due to transform) is not covered by neighbours. */
|
||||
.ce-block .links-widget-box:hover,
|
||||
.ce-block .number-widget-box:hover,
|
||||
.ce-block .links-widget-box:focus-within,
|
||||
.ce-block .number-widget-box:focus-within,
|
||||
.ce-block .links-widget-box:has(.dropdown-menu.show),
|
||||
.ce-block .number-widget-box:has(.dropdown-menu.show) {
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
|
||||
/* Link items: colored left accent bar slides in */
|
||||
.links-widget-box .link-item {
|
||||
|
|
@ -604,6 +634,90 @@ input.list-header-checkbox:checked::after {
|
|||
background-position: center;
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Notification Bell — Top-right position
|
||||
========================================================================== */
|
||||
|
||||
/* Hide original notification button in sidebar */
|
||||
.sidebar-notification {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Fixed wrapper */
|
||||
.jey-topright-wrapper {
|
||||
position: fixed;
|
||||
top: 16px;
|
||||
right: 24px;
|
||||
z-index: 1039;
|
||||
}
|
||||
|
||||
/* Bell button */
|
||||
.jey-topright-bell {
|
||||
position: relative;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
border-radius: 50%;
|
||||
background: var(--card-bg, #fff);
|
||||
border: 1px solid var(--border-color, #e2e2e2);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
box-shadow: 0 1px 4px rgba(0,0,0,0.08);
|
||||
transition: box-shadow 0.2s, background 0.2s;
|
||||
color: var(--text-muted, #74808b);
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.jey-topright-bell:hover {
|
||||
background: var(--subtle-fg, #f5f5f5);
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.12);
|
||||
color: var(--text-color, #333);
|
||||
}
|
||||
|
||||
/* Unread count badge */
|
||||
.jey-notif-badge {
|
||||
position: absolute;
|
||||
top: -4px;
|
||||
right: -4px;
|
||||
background: var(--red-500, #e53e3e);
|
||||
color: #fff;
|
||||
font-size: 10px;
|
||||
font-weight: 600;
|
||||
min-width: 16px;
|
||||
height: 16px;
|
||||
line-height: 16px;
|
||||
border-radius: 8px;
|
||||
text-align: center;
|
||||
padding: 0 4px;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* Notification dropdown panel */
|
||||
.jey-topright-wrapper .dropdown-notifications {
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 44px;
|
||||
right: 0;
|
||||
width: 360px;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 8px 24px rgba(0,0,0,0.12), 0 2px 6px rgba(0,0,0,0.04);
|
||||
background: var(--card-bg, #fff);
|
||||
border: 1px solid var(--border-color, #e2e2e2);
|
||||
max-height: 70vh;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.jey-topright-wrapper .dropdown-notifications.hidden {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
@media (max-width: 400px) {
|
||||
.jey-topright-wrapper .dropdown-notifications {
|
||||
width: calc(100vw - 32px);
|
||||
}
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Hide "Getting Started" onboarding panels
|
||||
========================================================================== */
|
||||
|
|
|
|||
|
|
@ -677,6 +677,238 @@
|
|||
$(document).on("page-change", addFullWidthButton);
|
||||
})();
|
||||
|
||||
/* ==========================================================================
|
||||
Toggle Theme button in sidebar (above Collapse)
|
||||
========================================================================== */
|
||||
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
function addThemeSwitchButton() {
|
||||
var collapse = document.querySelector(".collapse-sidebar-link");
|
||||
if (!collapse || document.querySelector(".jey-theme-switch-link")) return;
|
||||
|
||||
var link = document.createElement("a");
|
||||
link.className = "jey-theme-switch-link";
|
||||
link.innerHTML =
|
||||
frappe.utils.icon("palette", "sm", "", "", "text-ink-gray-7 current-color", true) +
|
||||
"<span>" + __("Switch Theme") + "</span>";
|
||||
|
||||
link.addEventListener("click", function () {
|
||||
new frappe.ui.ThemeSwitcher().show();
|
||||
});
|
||||
|
||||
collapse.parentNode.insertBefore(link, collapse);
|
||||
}
|
||||
|
||||
$(document).ready(addThemeSwitchButton);
|
||||
$(document).on("page-change", addThemeSwitchButton);
|
||||
})();
|
||||
|
||||
/* ==========================================================================
|
||||
Hide "Website" item from sidebar user dropdown
|
||||
========================================================================== */
|
||||
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
function tagWebsiteItem() {
|
||||
var label = __("Website");
|
||||
document.querySelectorAll(".dropdown-menu-item:not(.jey-hidden-item)").forEach(function (el) {
|
||||
var title = el.querySelector(".menu-item-title");
|
||||
if (title && title.textContent.trim() === label) {
|
||||
el.classList.add("jey-hidden-item");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$(document).ready(tagWebsiteItem);
|
||||
var observer = new MutationObserver(tagWebsiteItem);
|
||||
observer.observe(document.body, { childList: true, subtree: true });
|
||||
})();
|
||||
|
||||
/* ==========================================================================
|
||||
Reload button next to Notifications in sidebar
|
||||
========================================================================== */
|
||||
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
function addReloadButton() {
|
||||
var notif = document.querySelector(".sidebar-notification");
|
||||
if (!notif || document.querySelector(".jey-reload-btn")) return;
|
||||
|
||||
var btn = notif.cloneNode(true);
|
||||
btn.classList.remove("sidebar-notification");
|
||||
btn.classList.remove("hidden");
|
||||
btn.classList.add("jey-reload-btn");
|
||||
btn.removeAttribute("id");
|
||||
btn.setAttribute("title", __("Reload"));
|
||||
|
||||
var iconWrap = btn.querySelector(".sidebar-item-icon");
|
||||
if (iconWrap) {
|
||||
iconWrap.setAttribute("item-icon", "rotate-ccw");
|
||||
iconWrap.innerHTML = frappe.utils.icon(
|
||||
"rotate-ccw", "sm", "", "", "text-ink-gray-7 current-color", true
|
||||
);
|
||||
}
|
||||
var label = btn.querySelector(".sidebar-item-label");
|
||||
if (label) label.textContent = __("Reload");
|
||||
|
||||
btn.addEventListener("click", function (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
frappe.ui.toolbar.clear_cache();
|
||||
});
|
||||
|
||||
notif.parentNode.insertBefore(btn, notif.nextSibling);
|
||||
}
|
||||
|
||||
$(document).ready(function () {
|
||||
addReloadButton();
|
||||
var tries = 0;
|
||||
var poll = setInterval(function () {
|
||||
addReloadButton();
|
||||
if (++tries > 30 || document.querySelector(".jey-reload-btn")) {
|
||||
clearInterval(poll);
|
||||
}
|
||||
}, 300);
|
||||
});
|
||||
$(document).on("page-change", addReloadButton);
|
||||
})();
|
||||
|
||||
/* ==========================================================================
|
||||
Notification Bell — Move to top-right corner
|
||||
========================================================================== */
|
||||
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
function moveNotifications() {
|
||||
var dropdown = document.querySelector(".standard-items-sections .dropdown-notifications, .body-sidebar .dropdown-notifications:not(.jey-moved)");
|
||||
var wrapper = document.querySelector(".jey-topright-wrapper");
|
||||
|
||||
// A new dropdown appeared after page rebuild — move it into existing wrapper
|
||||
if (dropdown && wrapper) {
|
||||
dropdown.classList.add("jey-moved", "hidden");
|
||||
dropdown.parentNode.removeChild(dropdown);
|
||||
var old = wrapper.querySelector(".dropdown-notifications");
|
||||
if (old) old.remove();
|
||||
wrapper.appendChild(dropdown);
|
||||
return;
|
||||
}
|
||||
|
||||
if (wrapper) return; // already set up
|
||||
if (!dropdown) return; // nothing to move yet
|
||||
|
||||
// --- First-time setup ---
|
||||
wrapper = document.createElement("div");
|
||||
wrapper.className = "jey-topright-wrapper";
|
||||
|
||||
var bell = document.createElement("button");
|
||||
bell.className = "jey-topright-bell btn-reset";
|
||||
bell.setAttribute("title", __("Notifications"));
|
||||
bell.innerHTML =
|
||||
'<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" ' +
|
||||
'fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">' +
|
||||
'<path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"/>' +
|
||||
'<path d="M13.73 21a2 2 0 0 1-3.46 0"/>' +
|
||||
'</svg>';
|
||||
wrapper.appendChild(bell);
|
||||
|
||||
dropdown.classList.add("jey-moved", "hidden");
|
||||
dropdown.parentNode.removeChild(dropdown);
|
||||
wrapper.appendChild(dropdown);
|
||||
|
||||
document.body.appendChild(wrapper);
|
||||
|
||||
function updateBadge() {
|
||||
var dd = wrapper.querySelector(".dropdown-notifications");
|
||||
if (!dd) return;
|
||||
var unread = dd.querySelectorAll(".notification-item.unread").length;
|
||||
var badge = bell.querySelector(".jey-notif-badge");
|
||||
if (unread > 0) {
|
||||
if (!badge) {
|
||||
badge = document.createElement("span");
|
||||
badge.className = "jey-notif-badge";
|
||||
bell.appendChild(badge);
|
||||
}
|
||||
badge.textContent = unread > 9 ? "9+" : unread;
|
||||
} else if (badge) {
|
||||
badge.remove();
|
||||
}
|
||||
}
|
||||
|
||||
bell.addEventListener("click", function (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
var dd = wrapper.querySelector(".dropdown-notifications");
|
||||
if (dd) dd.classList.toggle("hidden");
|
||||
updateBadge();
|
||||
});
|
||||
|
||||
document.addEventListener("click", function (e) {
|
||||
if (!wrapper.contains(e.target)) {
|
||||
var dd = wrapper.querySelector(".dropdown-notifications");
|
||||
if (dd) dd.classList.add("hidden");
|
||||
}
|
||||
});
|
||||
|
||||
wrapper.addEventListener("click", function (e) {
|
||||
if (e.target.closest(".close-notification-dialogue")) {
|
||||
var dd = wrapper.querySelector(".dropdown-notifications");
|
||||
if (dd) dd.classList.add("hidden");
|
||||
}
|
||||
});
|
||||
|
||||
updateBadge();
|
||||
var obs = new MutationObserver(updateBadge);
|
||||
obs.observe(dropdown, { childList: true, subtree: true, attributes: true, attributeFilter: ["class"] });
|
||||
}
|
||||
|
||||
$(document).ready(function () {
|
||||
moveNotifications();
|
||||
var tries = 0;
|
||||
var poll = setInterval(function () {
|
||||
moveNotifications();
|
||||
if (++tries > 30) clearInterval(poll);
|
||||
}, 300);
|
||||
});
|
||||
$(document).on("page-change", moveNotifications);
|
||||
})();
|
||||
|
||||
/* ==========================================================================
|
||||
Fix: nested menus left orphaned when parent menu is toggled closed
|
||||
(sidebar-header app-switcher → Workspaces submenu stays on screen)
|
||||
========================================================================== */
|
||||
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
function patchMenuHide() {
|
||||
if (!window.frappe || !frappe.ui || !frappe.ui.menu) return false;
|
||||
var proto = frappe.ui.menu.prototype;
|
||||
if (proto.__jeyHidePatched) return true;
|
||||
var origHide = proto.hide;
|
||||
proto.hide = function () {
|
||||
if (this.nested_menus && this.nested_menus.length) {
|
||||
this.nested_menus.forEach(function (m) { m && m.hide && m.hide(); });
|
||||
}
|
||||
this.current_menu = null;
|
||||
return origHide.apply(this, arguments);
|
||||
};
|
||||
proto.__jeyHidePatched = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!patchMenuHide()) {
|
||||
var tries = 0;
|
||||
var poll = setInterval(function () {
|
||||
if (patchMenuHide() || ++tries > 50) clearInterval(poll);
|
||||
}, 200);
|
||||
}
|
||||
})();
|
||||
|
||||
/* ==========================================================================
|
||||
Override Frappe Theme Switcher — Jey themes
|
||||
========================================================================== */
|
||||
|
|
|
|||
Loading…
Reference in New Issue