Merge pull request #28967 from sokumon/better-sidebar
fix: improved sidebar
This commit is contained in:
commit
171eab1387
11 changed files with 434 additions and 225 deletions
|
|
@ -973,4 +973,12 @@ Tip: use lucide.svg in /icons for all downloaded icons
|
|||
<path fill-rule="evenodd" clip-rule="evenodd" d="M19 0a1 1 0 011 1v10a3 3 0 003 3h12a2 2 0 012 2v26a4 4 0 01-4 4H4a4 4 0 01-4-4V3a3 3 0 013-3h16zM8 37a1 1 0 100 2h21a1 1 0 100-2H8zm-1-7a1 1 0 011-1h21a1 1 0 110 2H8a1 1 0 01-1-1zm1-9a1 1 0 100 2h6a1 1 0 100-2H8z"></path>
|
||||
</g>
|
||||
</symbol>
|
||||
|
||||
<symbol xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" id="icon-arrow-right-to-line">
|
||||
<path d="M17 12H3" /> <path d="m11 18 6-6-6-6" /> <path d="M21 5v14" />
|
||||
</symbol>
|
||||
|
||||
<symbol xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" id="icon-arrow-left-to-line">
|
||||
<path d="M3 19V5" /> <path d="m13 6-6 6 6 6" /> <path d="M7 12h14" />
|
||||
</symbol>
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 87 KiB After Width: | Height: | Size: 87 KiB |
1
frappe/public/images/settings-gear.svg
Normal file
1
frappe/public/images/settings-gear.svg
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-settings"><path d="M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z"/><circle cx="12" cy="12" r="3"/></svg>
|
||||
|
After Width: | Height: | Size: 826 B |
|
|
@ -11,6 +11,8 @@ import "./frappe/ui/keyboard.js";
|
|||
import "./frappe/ui/colors.js";
|
||||
import "./frappe/ui/sidebar.html";
|
||||
import "./frappe/ui/sidebar.js";
|
||||
import "./frappe/ui/apps_switcher.js";
|
||||
import "./frappe/ui/apps_switcher.html";
|
||||
import "./frappe/ui/link_preview.js";
|
||||
|
||||
import "./frappe/request.js";
|
||||
|
|
|
|||
|
|
@ -140,6 +140,7 @@ frappe.router = {
|
|||
this.current_sub_path = sub_path;
|
||||
this.current_route = await this.parse();
|
||||
this.set_history(sub_path);
|
||||
this.set_active_sidebar_item();
|
||||
this.render();
|
||||
this.set_title(sub_path);
|
||||
this.trigger("change");
|
||||
|
|
@ -162,7 +163,6 @@ frappe.router = {
|
|||
// /app/user/user-001 = ["Form", "User", "user-001"]
|
||||
// /app/user/user-001 = ["Form", "User", "user-001"]
|
||||
// /app/event/view/calendar/default = ["List", "Event", "Calendar", "Default"]
|
||||
|
||||
if (frappe.workspaces[route[0]]) {
|
||||
// public workspace
|
||||
route = ["Workspaces", frappe.workspaces[route[0]].name];
|
||||
|
|
@ -280,6 +280,10 @@ frappe.router = {
|
|||
frappe.ui.hide_open_dialog();
|
||||
},
|
||||
|
||||
async set_active_sidebar_item() {
|
||||
frappe.app.sidebar.set_active_workspace_item();
|
||||
},
|
||||
|
||||
render() {
|
||||
if (this.current_route[0]) {
|
||||
this.render_page();
|
||||
|
|
|
|||
23
frappe/public/js/frappe/ui/apps_switcher.html
Normal file
23
frappe/public/js/frappe/ui/apps_switcher.html
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
<a class="app-switcher-dropdown" style="text-decoration: none;">
|
||||
<div class="standard-sidebar-item">
|
||||
<div class="d-flex">
|
||||
<div class="sidebar-item-icon app-logo-container">
|
||||
<img class="app-logo"
|
||||
src="{%= app_logo_url %}" alt="{%= ("App Logo") %}">
|
||||
</div>
|
||||
<div class="sidebar-item-label app-title" style="margin-left: 10px; margin-top: 1px">
|
||||
{%= app_title %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-item-control">
|
||||
<button class="btn-reset drop-icon show-in-edit-mode">
|
||||
<svg class="es-icon es-line icon-sm" style="display: block;margin:auto;" aria-hidden="true">
|
||||
<use class="" href="#es-line-down"></use>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<div class="app-switcher-menu hidden" role="menu">
|
||||
</div>
|
||||
154
frappe/public/js/frappe/ui/apps_switcher.js
Normal file
154
frappe/public/js/frappe/ui/apps_switcher.js
Normal file
|
|
@ -0,0 +1,154 @@
|
|||
frappe.ui.AppsSwitcher = class AppsSwitcher {
|
||||
constructor(sidebar_wrapper) {
|
||||
this.drop_down_state = false;
|
||||
this.sidebar_wrapper = sidebar_wrapper;
|
||||
this.setup_app_switcher();
|
||||
}
|
||||
|
||||
setup_app_switcher() {
|
||||
this.app_switcher_menu = $(".app-switcher-menu");
|
||||
$(".app-switcher-dropdown").on("click", () => {
|
||||
this.app_switcher_menu.toggleClass("hidden");
|
||||
});
|
||||
|
||||
// hover out of the sidebar move this to sidebar.js
|
||||
this.sidebar_wrapper.find(".body-sidebar").on("mouseleave", () => {
|
||||
this.app_switcher_menu.addClass("hidden");
|
||||
|
||||
// hide any expanded menus as they leave a blank space in the sidebar
|
||||
this.sidebar_wrapper.find(".drop-icon[data-state='opened'").click();
|
||||
});
|
||||
}
|
||||
create_app_data_map() {
|
||||
frappe.boot.app_data_map = {};
|
||||
for (var app of frappe.boot.app_data) {
|
||||
frappe.boot.app_data_map[app.app_name] = app;
|
||||
if (app.workspaces?.length) {
|
||||
this.add_app_item(app);
|
||||
}
|
||||
}
|
||||
}
|
||||
populate_apps_menu() {
|
||||
this.add_private_app();
|
||||
|
||||
this.add_website_select();
|
||||
this.add_settings_select();
|
||||
this.setup_select_app();
|
||||
}
|
||||
|
||||
add_app_item(app) {
|
||||
$(`<div class="app-item" data-app-name="${app.app_name}"
|
||||
data-app-route="${app.app_route}">
|
||||
<a>
|
||||
<div class="sidebar-item-icon">
|
||||
<img
|
||||
class="app-logo"
|
||||
src="${app.app_logo_url}"
|
||||
alt="${__("App Logo")}"
|
||||
>
|
||||
</div>
|
||||
<span class="app-item-title">${app.app_title}</span>
|
||||
</a>
|
||||
</div>`).appendTo(this.app_switcher_menu);
|
||||
}
|
||||
|
||||
add_private_app() {
|
||||
let private_pages = frappe.app.sidebar.all_pages.filter((p) => p.public === 0);
|
||||
if (private_pages.length === 0) return;
|
||||
|
||||
const app = {
|
||||
app_name: "private",
|
||||
app_title: __("My Workspaces"),
|
||||
app_route: "/app/private",
|
||||
app_logo_url: "/assets/frappe/images/frappe-framework-logo.svg",
|
||||
workspaces: private_pages,
|
||||
};
|
||||
|
||||
frappe.boot.app_data_map["private"] = app;
|
||||
$(`<div class="divider"></div>`).prependTo(this.app_switcher_menu);
|
||||
$(`<div class="app-item" data-app-name="${app.app_name}"
|
||||
data-app-route="${app.app_route}">
|
||||
<a>
|
||||
<div class="sidebar-item-icon">
|
||||
<img
|
||||
class="app-logo"
|
||||
src="${app.app_logo_url}"
|
||||
alt="${__("App Logo")}"
|
||||
>
|
||||
</div>
|
||||
<span class="app-item-title">${app.app_title}</span>
|
||||
</a>
|
||||
</div>`).prependTo(this.app_switcher_menu);
|
||||
}
|
||||
|
||||
setup_select_app() {
|
||||
this.app_switcher_menu.find(".app-item").on("click", (e) => {
|
||||
let item = $(e.delegateTarget);
|
||||
let route = item.attr("data-app-route");
|
||||
this.app_switcher_menu.toggleClass("hidden");
|
||||
|
||||
if (item.attr("data-app-name") == "settings") {
|
||||
frappe.quick_edit("Workspace Settings");
|
||||
return;
|
||||
}
|
||||
if (route.startsWith("/app/private")) {
|
||||
this.set_current_app("private");
|
||||
let ws = Object.values(frappe.workspace_map).find((ws) => ws.public === 0);
|
||||
route += "/" + frappe.router.slug(ws.title);
|
||||
frappe.set_route(route);
|
||||
} else if (route.startsWith("/app")) {
|
||||
frappe.set_route(route);
|
||||
this.set_current_app(item.attr("data-app-name"));
|
||||
} else {
|
||||
// new page
|
||||
window.open(route);
|
||||
}
|
||||
});
|
||||
}
|
||||
// refactor them into one single function
|
||||
add_website_select() {
|
||||
$(`<div class="divider"></div>`).appendTo(this.app_switcher_menu);
|
||||
this.add_app_item(
|
||||
{
|
||||
app_name: "website",
|
||||
app_title: __("Website"),
|
||||
app_route: "/",
|
||||
app_logo_url: "/assets/frappe/images/web.svg",
|
||||
},
|
||||
this.app_switcher_menu
|
||||
);
|
||||
}
|
||||
|
||||
add_settings_select() {
|
||||
$(`<div class="divider"></div>`).appendTo(this.app_switcher_menu);
|
||||
this.add_app_item({
|
||||
app_name: "settings",
|
||||
app_title: __("Settings"),
|
||||
app_logo_url: "/assets/frappe/images/settings-gear.svg",
|
||||
});
|
||||
let settings_item = this.app_switcher_menu.children().last();
|
||||
}
|
||||
|
||||
set_current_app(app) {
|
||||
if (!app) {
|
||||
console.warn("set_current_app: app not defined");
|
||||
return;
|
||||
}
|
||||
let app_data = frappe.boot.app_data_map[app] || frappe.boot.app_data_map["frappe"];
|
||||
|
||||
this.sidebar_wrapper
|
||||
.find(".app-switcher-dropdown .sidebar-item-icon img")
|
||||
.attr("src", app_data.app_logo_url);
|
||||
this.sidebar_wrapper
|
||||
.find(".app-switcher-dropdown .sidebar-item-label")
|
||||
.html(app_data.app_title);
|
||||
|
||||
$(".navbar-brand .app-logo").attr("src", app_data.app_logo_url);
|
||||
|
||||
if (frappe.current_app === app) return;
|
||||
frappe.current_app = app;
|
||||
|
||||
// re-render the sidebar
|
||||
frappe.app.sidebar.make_sidebar();
|
||||
}
|
||||
};
|
||||
|
|
@ -2,41 +2,13 @@
|
|||
<div class="body-sidebar-placeholder"></div>
|
||||
<div class="body-sidebar">
|
||||
<div class="body-sidebar-top">
|
||||
<a class="app-switcher-dropdown"
|
||||
style="text-decoration: none; width: 100%; position: relative;">
|
||||
|
||||
<div class="standard-sidebar-item">
|
||||
<div class="d-flex">
|
||||
<div class="sidebar-item-icon">
|
||||
<img class="app-logo"
|
||||
src="{%= app_logo_url %}" alt="{%= ("App Logo") %}">
|
||||
</div>
|
||||
<div class="sidebar-item-label" style="margin-left: 5px; margin-top: 1px">
|
||||
{%= app_title %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-item-control">
|
||||
<button class="btn-reset drop-icon show-in-edit-mode">
|
||||
<svg class="es-icon es-line icon-sm" style="" aria-hidden="true">
|
||||
<use class="" href="#es-line-down"></use>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<div class="app-switcher-menu hidden" role="menu">
|
||||
</div>
|
||||
<div class="sidebar-items">
|
||||
</div>
|
||||
</div>
|
||||
<div class="body-sidebar-bottom">
|
||||
<a class="edit-sidebar-link text-extra-muted hidden">
|
||||
<svg class="icon icon-sm" style="margin-top: -2px;">
|
||||
<use href="#icon-setting-gear"></use></svg> {%= __("Settings") %}</a>
|
||||
<a class="close-sidebar-link text-extra-muted hidden">
|
||||
<svg class="icon icon-sm" style="margin-top: -2px;">
|
||||
<use href="#icon-close"></use></svg> {%= __("Close") %}</a>
|
||||
<a class="collapse-sidebar-link">
|
||||
<svg class="icon" style="margin-top: -2px">
|
||||
<use href="#icon-arrow-right-to-line"></use></svg> {%= __("Collapse") %}</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
frappe.provide("frappe.ui");
|
||||
|
||||
frappe.ui.Sidebar = class Sidebar {
|
||||
constructor() {
|
||||
this.items = {};
|
||||
this.sidebar_expanded = false;
|
||||
|
||||
if (!frappe.boot.setup_complete) {
|
||||
// no sidebar if setup is not complete
|
||||
|
|
@ -35,25 +34,34 @@ frappe.ui.Sidebar = class Sidebar {
|
|||
|
||||
make_dom() {
|
||||
this.set_default_app();
|
||||
this.wrapper = $(
|
||||
frappe.render_template("sidebar", {
|
||||
this.wrapper = $(frappe.render_template("sidebar")).prependTo("body");
|
||||
|
||||
this.app_switcher_dropdown = $(
|
||||
frappe.render_template("apps_switcher", {
|
||||
app_logo_url: frappe.boot.app_data[0].app_logo_url,
|
||||
app_title: __(frappe.boot.app_data[0].app_title),
|
||||
})
|
||||
).prependTo("body");
|
||||
).prependTo(this.wrapper.find(".body-sidebar"));
|
||||
|
||||
this.$sidebar = this.wrapper.find(".sidebar-items");
|
||||
|
||||
if (this.has_access) {
|
||||
this.wrapper
|
||||
.find(".body-sidebar .edit-sidebar-link")
|
||||
.removeClass("hidden")
|
||||
.on("click", () => {
|
||||
frappe.quick_edit("Workspace Settings");
|
||||
});
|
||||
}
|
||||
this.wrapper.find(".body-sidebar .collapse-sidebar-link").on("click", () => {
|
||||
this.toggle_sidebar();
|
||||
});
|
||||
|
||||
this.setup_app_switcher();
|
||||
this.apps_switcher = new frappe.ui.AppsSwitcher(this.wrapper);
|
||||
this.apps_switcher.create_app_data_map();
|
||||
}
|
||||
|
||||
set_hover() {
|
||||
$(".standard-sidebar-item > .item-anchor").on("mouseover", function (event) {
|
||||
if ($(this).parent().hasClass("active-sidebar")) return;
|
||||
$(this).parent().addClass("hover");
|
||||
});
|
||||
|
||||
$(".standard-sidebar-item > .item-anchor").on("mouseleave", function () {
|
||||
$(this).parent().removeClass("hover");
|
||||
});
|
||||
}
|
||||
|
||||
set_all_pages() {
|
||||
|
|
@ -69,137 +77,29 @@ frappe.ui.Sidebar = class Sidebar {
|
|||
frappe.current_app = frappe.boot.app_data[0].app_name;
|
||||
}
|
||||
|
||||
setup_app_switcher() {
|
||||
let app_switcher_menu = $(".app-switcher-menu");
|
||||
|
||||
$(".app-switcher-dropdown").on("click", () => {
|
||||
app_switcher_menu.toggleClass("hidden");
|
||||
});
|
||||
|
||||
// hover out of the sidebar
|
||||
this.wrapper.find(".body-sidebar").on("mouseleave", () => {
|
||||
app_switcher_menu.addClass("hidden");
|
||||
|
||||
// hide any expanded menus as they leave a blank space in the sidebar
|
||||
this.wrapper.find(".drop-icon[data-state='opened'").click();
|
||||
});
|
||||
|
||||
frappe.boot.app_data_map = {};
|
||||
this.add_private_app(app_switcher_menu);
|
||||
|
||||
for (var app of frappe.boot.app_data) {
|
||||
frappe.boot.app_data_map[app.app_name] = app;
|
||||
if (app.workspaces?.length) {
|
||||
this.add_app_item(app, app_switcher_menu);
|
||||
}
|
||||
set_active_workspace_item() {
|
||||
if (this.is_route_in_sidebar(decodeURIComponent(window.location.pathname))) {
|
||||
this.active_item.addClass("active-sidebar");
|
||||
}
|
||||
this.add_website_select(app_switcher_menu);
|
||||
this.setup_select_app(app_switcher_menu);
|
||||
}
|
||||
|
||||
add_app_item(app, app_switcher_menu) {
|
||||
$(`<div class="app-item" data-app-name="${app.app_name}"
|
||||
data-app-route="${app.app_route}">
|
||||
<a>
|
||||
<div class="sidebar-item-icon">
|
||||
<img
|
||||
class="app-logo"
|
||||
src="${app.app_logo_url}"
|
||||
alt="${__("App Logo")}"
|
||||
>
|
||||
</div>
|
||||
<span class="app-item-title">${app.app_title}</span>
|
||||
</a>
|
||||
</div>`).appendTo(app_switcher_menu);
|
||||
}
|
||||
|
||||
add_private_app(app_switcher_menu) {
|
||||
let private_pages = this.all_pages.filter((p) => p.public === 0);
|
||||
if (private_pages.length === 0) return;
|
||||
|
||||
const app = {
|
||||
app_name: "private",
|
||||
app_title: __("My Workspaces"),
|
||||
app_route: "/app/private",
|
||||
app_logo_url: "/assets/frappe/images/frappe-framework-logo.svg",
|
||||
workspaces: private_pages,
|
||||
};
|
||||
|
||||
frappe.boot.app_data_map["private"] = app;
|
||||
$(`<div class="divider"></div>`).prependTo(app_switcher_menu);
|
||||
$(`<div class="app-item" data-app-name="${app.app_name}"
|
||||
data-app-route="${app.app_route}">
|
||||
<a>
|
||||
<div class="sidebar-item-icon">
|
||||
<img
|
||||
class="app-logo"
|
||||
src="${app.app_logo_url}"
|
||||
alt="${__("App Logo")}"
|
||||
>
|
||||
</div>
|
||||
<span class="app-item-title">${app.app_title}</span>
|
||||
</a>
|
||||
</div>`).prependTo(app_switcher_menu);
|
||||
}
|
||||
|
||||
setup_select_app(app_switcher_menu) {
|
||||
app_switcher_menu.find(".app-item").on("click", (e) => {
|
||||
let item = $(e.delegateTarget);
|
||||
let route = item.attr("data-app-route");
|
||||
app_switcher_menu.toggleClass("hidden");
|
||||
|
||||
if (route.startsWith("/app/private")) {
|
||||
this.set_current_app("private");
|
||||
let ws = Object.values(frappe.workspace_map).find((ws) => ws.public === 0);
|
||||
route += "/" + frappe.router.slug(ws.title);
|
||||
frappe.set_route(route);
|
||||
} else if (route.startsWith("/app")) {
|
||||
frappe.set_route(route);
|
||||
this.set_current_app(item.attr("data-app-name"));
|
||||
} else {
|
||||
// new page
|
||||
window.open(route);
|
||||
is_route_in_sidebar(route_name) {
|
||||
let match = false;
|
||||
const that = this;
|
||||
$(".item-anchor").each(function () {
|
||||
if ($(this).attr("href") == route_name) {
|
||||
match = true;
|
||||
if (that.active_item) that.active_item.removeClass("active-sidebar");
|
||||
that.active_item = $(this).parent();
|
||||
// this exists the each loop
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
set_current_app(app) {
|
||||
if (!app) {
|
||||
console.warn("set_current_app: app not defined");
|
||||
return;
|
||||
}
|
||||
let app_data = frappe.boot.app_data_map[app] || frappe.boot.app_data_map["frappe"];
|
||||
|
||||
this.wrapper
|
||||
.find(".app-switcher-dropdown .sidebar-item-icon img")
|
||||
.attr("src", app_data.app_logo_url);
|
||||
this.wrapper.find(".app-switcher-dropdown .sidebar-item-label").html(app_data.app_title);
|
||||
|
||||
$(".navbar-brand .app-logo").attr("src", app_data.app_logo_url);
|
||||
|
||||
if (frappe.current_app === app) return;
|
||||
frappe.current_app = app;
|
||||
|
||||
// re-render the sidebar
|
||||
this.make_sidebar();
|
||||
}
|
||||
|
||||
add_website_select(app_switcher_menu) {
|
||||
$(`<div class="divider"></div>`).appendTo(app_switcher_menu);
|
||||
this.add_app_item(
|
||||
{
|
||||
app_name: "website",
|
||||
app_title: __("Website"),
|
||||
app_route: "/",
|
||||
app_logo_url: "/assets/frappe/images/web.svg",
|
||||
},
|
||||
app_switcher_menu
|
||||
);
|
||||
return match;
|
||||
}
|
||||
|
||||
setup_pages() {
|
||||
this.set_all_pages();
|
||||
|
||||
this.all_pages.forEach((page) => {
|
||||
page.is_editable = !page.public || this.has_access;
|
||||
if (typeof page.content == "string") {
|
||||
|
|
@ -224,6 +124,11 @@ frappe.ui.Sidebar = class Sidebar {
|
|||
}
|
||||
this.make_sidebar();
|
||||
}
|
||||
this.set_hover();
|
||||
if (localStorage.getItem("sidebar-expanded") !== null) {
|
||||
this.sidebar_expanded = JSON.parse(localStorage.getItem("sidebar-expanded"));
|
||||
this.expand_sidebar();
|
||||
}
|
||||
}
|
||||
|
||||
make_sidebar() {
|
||||
|
|
@ -248,6 +153,7 @@ frappe.ui.Sidebar = class Sidebar {
|
|||
this.wrapper.find(".selected")[0].scrollIntoView();
|
||||
|
||||
this.setup_sorting();
|
||||
this.set_active_workspace_item();
|
||||
}
|
||||
|
||||
build_sidebar_section(title, root_pages) {
|
||||
|
|
@ -263,7 +169,7 @@ frappe.ui.Sidebar = class Sidebar {
|
|||
|
||||
$(".item-anchor").on("click", () => {
|
||||
$(".list-sidebar.hidden-xs.hidden-sm").removeClass("opened");
|
||||
$(".close-sidebar").css("display", "none");
|
||||
// $(".close-sidebar").css("display", "none");
|
||||
$("body").css("overflow", "auto");
|
||||
});
|
||||
|
||||
|
|
@ -290,6 +196,30 @@ frappe.ui.Sidebar = class Sidebar {
|
|||
}
|
||||
child_container.appendTo(item_container);
|
||||
}
|
||||
toggle_sidebar() {
|
||||
if (!this.sidebar_expanded) {
|
||||
this.open_sidebar();
|
||||
} else {
|
||||
this.close_sidebar();
|
||||
}
|
||||
}
|
||||
expand_sidebar() {
|
||||
let direction;
|
||||
if (this.sidebar_expanded) {
|
||||
this.wrapper.addClass("expanded");
|
||||
// this.sidebar_expanded = false
|
||||
direction = "left";
|
||||
} else {
|
||||
this.wrapper.removeClass("expanded");
|
||||
// this.sidebar_expanded = true
|
||||
direction = "right";
|
||||
}
|
||||
localStorage.setItem("sidebar-expanded", this.sidebar_expanded);
|
||||
this.wrapper
|
||||
.find(".body-sidebar .collapse-sidebar-link")
|
||||
.find("use")
|
||||
.attr("href", `#icon-arrow-${direction}-to-line`);
|
||||
}
|
||||
|
||||
append_item(item, container) {
|
||||
let is_current_page = false;
|
||||
|
|
@ -454,6 +384,15 @@ frappe.ui.Sidebar = class Sidebar {
|
|||
}
|
||||
}
|
||||
|
||||
close_sidebar() {
|
||||
this.sidebar_expanded = false;
|
||||
this.expand_sidebar();
|
||||
}
|
||||
open_sidebar() {
|
||||
this.sidebar_expanded = true;
|
||||
this.expand_sidebar();
|
||||
}
|
||||
|
||||
reload() {
|
||||
return frappe.workspace.get_pages().then((r) => {
|
||||
frappe.boot.sidebar_pages = r;
|
||||
|
|
|
|||
|
|
@ -29,18 +29,7 @@ frappe.ui.toolbar.Toolbar = class {
|
|||
this.bind_events();
|
||||
$(document).trigger("toolbar_setup");
|
||||
$(".navbar-brand .app-logo").on("click", () => {
|
||||
$(".body-sidebar-container")
|
||||
.toggleClass("expanded")
|
||||
.find(".edit-sidebar-link")
|
||||
.addClass("hidden");
|
||||
|
||||
// show close link
|
||||
$(".body-sidebar-container")
|
||||
.find(".close-sidebar-link")
|
||||
.removeClass("hidden")
|
||||
.on("click", () => {
|
||||
$(".body-sidebar-container").removeClass("expanded");
|
||||
});
|
||||
frappe.app.sidebar.toggle_sidebar();
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -46,7 +46,9 @@ frappe.views.Workspace = class Workspace {
|
|||
|
||||
this.prepare_container();
|
||||
this.sidebar = frappe.app.sidebar;
|
||||
this.app_switcher_menu = frappe.app.app_switcher_menu;
|
||||
this.sidebar.setup_pages();
|
||||
this.sidebar.apps_switcher.populate_apps_menu();
|
||||
this.cached_pages = $.extend(true, {}, frappe.boot.sidebar_pages);
|
||||
this.has_access = frappe.boot.sidebar_pages.has_access;
|
||||
this.has_create_access = frappe.boot.sidebar_pages.has_create_access;
|
||||
|
|
@ -232,10 +234,9 @@ frappe.views.Workspace = class Workspace {
|
|||
|
||||
this.prepare_editorjs();
|
||||
$(".item-anchor").removeClass("disable-click");
|
||||
$(".body-sidebar-container").removeClass("expanded");
|
||||
|
||||
this.remove_page_skeleton();
|
||||
frappe.app.sidebar.set_current_app(app);
|
||||
frappe.app.sidebar.apps_switcher.set_current_app(app);
|
||||
this.wrapper.find(".workspace-title").html(__(this._page.title));
|
||||
this.wrapper
|
||||
.find(".workspace-icon")
|
||||
|
|
@ -545,7 +546,7 @@ frappe.views.Workspace = class Workspace {
|
|||
|
||||
if (!frappe.boot.app_data_map["private"] && new_page.public === 0) {
|
||||
let app_switcher_menu = $(".app-switcher-menu");
|
||||
this.sidebar.add_private_app(app_switcher_menu);
|
||||
this.sidebar.apps_switcher.add_private_app(app_switcher_menu);
|
||||
}
|
||||
resolve();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,34 +69,47 @@ body {
|
|||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
height: 100vh;
|
||||
z-index: 1030;
|
||||
padding: 8px 8px 10px 8px;
|
||||
|
||||
.body-sidebar-top {
|
||||
flex: 1 1;
|
||||
padding: 1px;
|
||||
width: 34px;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
flex-direction: column;
|
||||
flex-wrap: nowrap;
|
||||
|
||||
gap: 2px;
|
||||
justify-content: flex-start;
|
||||
overflow: hidden;
|
||||
padding: 13px;
|
||||
position: static;
|
||||
font-size: var(--text-base);
|
||||
// transition: width 200ms;
|
||||
}
|
||||
|
||||
.body-sidebar-bottom {
|
||||
padding: 15px;
|
||||
overflow: hidden;
|
||||
padding: 7px;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
// position: relative;
|
||||
// top:10px;
|
||||
}
|
||||
.app-title {
|
||||
font-weight: 500;
|
||||
line-height: 16.1px;
|
||||
}
|
||||
|
||||
.app-logo {
|
||||
width: 23px;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
.sidebar-items {
|
||||
width: 204px;
|
||||
padding-left: 1px;
|
||||
padding-right: 1px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
|
@ -107,6 +120,8 @@ body {
|
|||
|
||||
.standard-sidebar-section {
|
||||
margin-bottom: var(--margin-xl);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
&:last-of-type {
|
||||
margin-bottom: var(--margin-sm);
|
||||
|
|
@ -115,72 +130,103 @@ body {
|
|||
&:first-child {
|
||||
margin-top: 24px;
|
||||
}
|
||||
|
||||
.sidebar-item-container {
|
||||
width: 30px;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
.standard-sidebar-item {
|
||||
display: flex;
|
||||
line-height: 0px;
|
||||
justify-content: space-between;
|
||||
padding: 0px;
|
||||
|
||||
.sidebar-item-control {
|
||||
display: none;
|
||||
|
||||
> * {
|
||||
align-self: center;
|
||||
margin-left: 3px;
|
||||
box-shadow: none;
|
||||
// margin-left: 3px;
|
||||
// box-shadow: none;
|
||||
}
|
||||
|
||||
.drop-icon {
|
||||
padding: 0px 12px 0px 2px;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
padding: 6px;
|
||||
}
|
||||
|
||||
svg {
|
||||
margin-right: 0;
|
||||
margin-top: 3px;
|
||||
margin: -1px;
|
||||
}
|
||||
}
|
||||
|
||||
.sidebar-item-label {
|
||||
display: none;
|
||||
font-size: var(--text-sm);
|
||||
font-size: var(--text-md);
|
||||
}
|
||||
|
||||
.item-anchor {
|
||||
line-height: 10px;
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
gap: 5px;
|
||||
align-items: center;
|
||||
padding: 3px 0px 3px 11px;
|
||||
// padding: 3px 0px 3px 11px;
|
||||
flex: 1;
|
||||
|
||||
&:hover {
|
||||
text-decoration: none !important;
|
||||
}
|
||||
|
||||
.sidebar-item-icon {
|
||||
padding: 7px;
|
||||
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
|
||||
svg {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.edit-sidebar-link {
|
||||
display: none;
|
||||
.collapse-sidebar-link {
|
||||
width: 2px;
|
||||
height: 12px;
|
||||
visibility: collapse;
|
||||
text-decoration: none;
|
||||
font-size: var(--text-md);
|
||||
svg {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.collapse-sidebar-link svg {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.sidebar-item-container {
|
||||
width: 30px;
|
||||
position: relative;
|
||||
margin-left: -10px;
|
||||
margin-bottom: 6px;
|
||||
|
||||
// &:hover{
|
||||
// background-color: #f3f3f3;
|
||||
// border-radius: 8px;
|
||||
// }
|
||||
// margin-left: -10px;
|
||||
// margin-bottom: 6px;
|
||||
/* nested container */
|
||||
.sidebar-item-container {
|
||||
margin-left: 20px;
|
||||
padding-left: 12px;
|
||||
|
||||
.standard-sidebar-item {
|
||||
justify-content: start;
|
||||
}
|
||||
}
|
||||
|
||||
.indicator {
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -188,25 +234,46 @@ body {
|
|||
.body-sidebar {
|
||||
// make it an overlay on hover
|
||||
position: absolute;
|
||||
width: 200px;
|
||||
|
||||
width: 220px;
|
||||
.app-switcher-dropdown {
|
||||
width: 204px;
|
||||
left: 0px;
|
||||
padding: 2px 0px 2px 3px;
|
||||
}
|
||||
.body-sidebar-top {
|
||||
overflow-y: auto;
|
||||
width: 204px;
|
||||
overflow-y: hidden;
|
||||
.app-switcher-dropdown {
|
||||
width: 204px;
|
||||
}
|
||||
}
|
||||
.sidebar-item-container {
|
||||
width: 100%;
|
||||
}
|
||||
.sidebar-item-label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.sidebar-item-control {
|
||||
display: block;
|
||||
}
|
||||
.edit-sidebar-link {
|
||||
display: block;
|
||||
|
||||
.sidebar-items {
|
||||
padding: 0px;
|
||||
}
|
||||
.collapse-sidebar-link {
|
||||
visibility: visible;
|
||||
}
|
||||
.body-sidebar-bottom {
|
||||
width: 220px;
|
||||
position: static;
|
||||
}
|
||||
}
|
||||
|
||||
// show placeholder so that main section remains static
|
||||
.body-sidebar-placeholder {
|
||||
display: flex;
|
||||
width: 220px;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -218,6 +285,7 @@ body {
|
|||
// body sidebar hidded in mobile view
|
||||
.body-sidebar-container {
|
||||
.body-sidebar {
|
||||
padding: 0px;
|
||||
width: 0px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
|
@ -226,21 +294,42 @@ body {
|
|||
// expands when navbar-brand is clicked
|
||||
.body-sidebar-container.expanded {
|
||||
.body-sidebar {
|
||||
width: 200px;
|
||||
padding: 8px 8px 10px 8px;
|
||||
width: 220px;
|
||||
}
|
||||
// acts a overlay when in mobile view
|
||||
.body-sidebar-placeholder {
|
||||
display: flex;
|
||||
width: 0px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include media-breakpoint-up(sm) {
|
||||
// for bigger screens, expand / collapse on hover
|
||||
.body-sidebar-container:hover {
|
||||
@include body-sidebar-expanded();
|
||||
}
|
||||
// .body-sidebar-container:hover {
|
||||
// @include body-sidebar-expanded();
|
||||
// }
|
||||
}
|
||||
|
||||
.app-switcher-dropdown {
|
||||
position: relative;
|
||||
text-decoration: none;
|
||||
width: 38px;
|
||||
height: 38px;
|
||||
left: -2px;
|
||||
padding: 3px;
|
||||
.standard-sidebar-item {
|
||||
padding-top: 1px;
|
||||
padding-bottom: 1px;
|
||||
.d-flex {
|
||||
width: 161px;
|
||||
}
|
||||
gap: 12px;
|
||||
}
|
||||
.sidebar-item-control {
|
||||
margin-top: -2px;
|
||||
margin: 2px;
|
||||
margin-right: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -248,27 +337,40 @@ body {
|
|||
position: absolute;
|
||||
top: 44px;
|
||||
left: 7px;
|
||||
width: 183px; /* 200 - 7px */
|
||||
padding: var(--padding-xs);
|
||||
box-shadow: var(--shadow-base);
|
||||
background-color: var(--neutral);
|
||||
width: 220px; /* 200 - 7px */
|
||||
padding: 6px;
|
||||
border-radius: var(--border-radius-lg);
|
||||
background: var(--surface-modal, rgba(255, 255, 255, 1));
|
||||
box-shadow: 0px 10px 24px -3px rgba(0, 0, 0, 0.1);
|
||||
// box-shadow: 0px 1px 3px 0px rgba(0, 0, 0, 0.05);
|
||||
// box-shadow: 0px 0px 1px 0px rgba(0, 0, 0, 0.2);
|
||||
z-index: 1;
|
||||
border-radius: var(--border-radius-tiny);
|
||||
}
|
||||
|
||||
.app-item {
|
||||
padding: var(--padding-xs);
|
||||
// padding: var(--padding-xs);
|
||||
border-radius: var(--border-radius-tiny);
|
||||
|
||||
opacity: 0px;
|
||||
&:hover {
|
||||
background-color: var(--subtle-accent);
|
||||
}
|
||||
|
||||
a {
|
||||
width: 208px;
|
||||
height: 28px;
|
||||
padding: 6px 8px 6px 8px;
|
||||
gap: 8px;
|
||||
text-decoration: none;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--margin-sm);
|
||||
.sidebar-item-icon {
|
||||
line-height: 0px;
|
||||
.app-logo {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.app-item-title {
|
||||
|
|
@ -277,7 +379,21 @@ body {
|
|||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
// sidebar-item states
|
||||
@mixin hover-mixin {
|
||||
background-color: #f3f3f3;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.hover {
|
||||
@include hover-mixin();
|
||||
}
|
||||
|
||||
.active-sidebar {
|
||||
background: var(--surface-selected, rgba(255, 255, 255, 1));
|
||||
box-shadow: 0px 1px 2px 0px rgba(0, 0, 0, 0.1);
|
||||
border-radius: 8px;
|
||||
}
|
||||
// form sidebar
|
||||
.form-sidebar {
|
||||
.sidebar-section {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue