kopia lustrzana https://github.com/wagtail/wagtail
Slim sidebar: remember collapsed state
rodzic
2c4db8f2b1
commit
952264a2ab
|
|
@ -307,6 +307,7 @@ body.explorer-open {
|
|||
}
|
||||
|
||||
body.sidebar-collapsed .wrapper {
|
||||
@include transition(padding-left $menu-transition-duration ease);
|
||||
padding-left: $menu-width-slim;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -237,6 +237,7 @@ function renderSidebarStory(
|
|||
return (
|
||||
<div className="wrapper">
|
||||
<Sidebar
|
||||
collapsedOnLoad={false}
|
||||
modules={modules}
|
||||
currentPath={currentPath}
|
||||
strings={strings || STRINGS}
|
||||
|
|
|
|||
|
|
@ -30,17 +30,23 @@ export interface SidebarProps {
|
|||
modules: ModuleDefinition[];
|
||||
currentPath: string;
|
||||
strings: Strings;
|
||||
collapsedOnLoad: boolean;
|
||||
navigate(url: string): Promise<void>;
|
||||
onExpandCollapse?(collapsed: boolean);
|
||||
}
|
||||
|
||||
export const Sidebar: React.FunctionComponent<SidebarProps> = (
|
||||
{ modules, currentPath, strings, navigate, onExpandCollapse }) => {
|
||||
{ modules, currentPath, collapsedOnLoad, strings, navigate, onExpandCollapse }) => {
|
||||
// 'collapsed' is a persistent state that is controlled by the arrow icon at the top
|
||||
// It records the user's general preference for a collapsed/uncollapsed menu
|
||||
// This is just a hint though, and we may still collapse the menu if the screen is too small
|
||||
// Also, we may display the full menu temporarily in collapsed mode (see 'peeking' below)
|
||||
const [collapsed, setCollapsed] = React.useState(window.innerWidth < 800);
|
||||
const [collapsed, setCollapsed] = React.useState((): boolean => {
|
||||
if (window.innerWidth < 800 || collapsedOnLoad) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
// Call onExpandCollapse(true) if menu is initialised in collapsed state
|
||||
React.useEffect(() => {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,11 @@
|
|||
import * as React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import Cookies from 'js-cookie';
|
||||
|
||||
import { Sidebar } from './Sidebar';
|
||||
|
||||
export const SIDEBAR_COLLAPSED_COOKIE_NAME = 'wagtail_sidebar_collapsed';
|
||||
|
||||
export function initSidebar() {
|
||||
const element = document.getElementById('wagtail-sidebar');
|
||||
|
||||
|
|
@ -20,11 +23,17 @@ export function initSidebar() {
|
|||
if (element instanceof HTMLElement && element.dataset.props) {
|
||||
const props = window.telepath.unpack(JSON.parse(element.dataset.props));
|
||||
|
||||
const onExpandCollapse = (collapsed: boolean) => {
|
||||
if (collapsed) {
|
||||
const collapsedCookie: any = Cookies.get(SIDEBAR_COLLAPSED_COOKIE_NAME);
|
||||
// Cast to boolean
|
||||
const collapsed = !((collapsedCookie === undefined || collapsedCookie === '0'));
|
||||
|
||||
const onExpandCollapse = (_collapsed: boolean) => {
|
||||
if (_collapsed) {
|
||||
document.body.classList.add('sidebar-collapsed');
|
||||
Cookies.set(SIDEBAR_COLLAPSED_COOKIE_NAME, 1);
|
||||
} else {
|
||||
document.body.classList.remove('sidebar-collapsed');
|
||||
Cookies.set(SIDEBAR_COLLAPSED_COOKIE_NAME, 0);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -32,6 +41,7 @@ export function initSidebar() {
|
|||
<Sidebar
|
||||
modules={props.modules}
|
||||
strings={wagtailConfig.STRINGS}
|
||||
collapsedOnLoad={collapsed}
|
||||
currentPath={window.location.pathname}
|
||||
navigate={navigate}
|
||||
onExpandCollapse={onExpandCollapse}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@ declare global {
|
|||
/* eslint-disable-next-line camelcase */
|
||||
display_name: string;
|
||||
}[];
|
||||
|
||||
STRINGS: any;
|
||||
}
|
||||
const wagtailConfig: WagtailConfig;
|
||||
|
|
|
|||
|
|
@ -20259,6 +20259,11 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"js-cookie": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-2.2.1.tgz",
|
||||
"integrity": "sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ=="
|
||||
},
|
||||
"js-string-escape": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/js-string-escape/-/js-string-escape-1.0.1.tgz",
|
||||
|
|
|
|||
|
|
@ -107,6 +107,7 @@
|
|||
"focus-trap-react": "^8.4.2",
|
||||
"formdata-polyfill": "^3.0.20",
|
||||
"immer": "^9.0.1",
|
||||
"js-cookie": "^2.2.1",
|
||||
"postcss-calc": "^7.0.5",
|
||||
"prop-types": "^15.6.2",
|
||||
"react": "^16.14.0",
|
||||
|
|
|
|||
|
|
@ -3,32 +3,32 @@
|
|||
|
||||
{% block furniture %}
|
||||
{% slim_sidebar_enabled as slim_sidebar_enabled %}
|
||||
<aside id="wagtail-sidebar" class="nav-wrapper" {% if slim_sidebar_enabled %}data-props="{% menu_props %}"{% else %}data-nav-primary{% endif %}>
|
||||
{% if slim_sidebar_enabled %}
|
||||
<aside id="wagtail-sidebar" data-props="{% menu_props %}"></aside>
|
||||
{% else %}
|
||||
<aside id="wagtail-sidebar" class="nav-wrapper" data-nav-primary>
|
||||
<div class="inner">
|
||||
<a href="{% url 'wagtailadmin_home' %}" class="logo" aria-label="{% trans 'Dashboard' %}">
|
||||
{% block branding_logo %}
|
||||
{% if not slim_sidebar_enabled %}
|
||||
{# Mobile-only logo: #}
|
||||
<div class="wagtail-logo-container__mobile u-hidden@sm">
|
||||
<img class="wagtail-logo wagtail-logo__full" src="{% versioned_static 'wagtailadmin/images/wagtail-logo.svg' %}" alt="" width="80" />
|
||||
</div>
|
||||
{# Mobile-only logo: #}
|
||||
<div class="wagtail-logo-container__mobile u-hidden@sm">
|
||||
<img class="wagtail-logo wagtail-logo__full" src="{% versioned_static 'wagtailadmin/images/wagtail-logo.svg' %}" alt="" width="80" />
|
||||
</div>
|
||||
|
||||
{# Desktop logo (animated): #}
|
||||
{% include "wagtailadmin/shared/animated_logo.html" %}
|
||||
{% endif %}
|
||||
{# Desktop logo (animated): #}
|
||||
{% include "wagtailadmin/shared/animated_logo.html" %}
|
||||
{% endblock %}
|
||||
<span class="u-hidden@sm">{% trans "Dashboard" %}</span>
|
||||
</a>
|
||||
|
||||
{% if not slim_sidebar_enabled %}
|
||||
{% menu_search %}
|
||||
{% main_nav %}
|
||||
{% endif %}
|
||||
{% menu_search %}
|
||||
{% main_nav %}
|
||||
</div>
|
||||
<div class="explorer__wrapper" data-explorer-menu></div>
|
||||
</aside>
|
||||
{% endif %}
|
||||
|
||||
<main class="content-wrapper" role="main" id="main">
|
||||
<main class="content-wrapper {% if slim_sidebar_enabled %}sidebar--open{% endif %}" role="main" id="main">
|
||||
<div class="content">
|
||||
{# Always show messages div so it can be appended to by JS #}
|
||||
<div class="messages">
|
||||
|
|
|
|||
|
|
@ -18,7 +18,9 @@
|
|||
|
||||
{% block branding_favicon %}{% endblock %}
|
||||
</head>
|
||||
<body id="wagtail" class="{% block bodyclass %}{% endblock %} {% if messages %}has-messages{% endif %} focus-outline-on">
|
||||
{% slim_sidebar_enabled as slim_sidebar_enabled %}
|
||||
{% sidebar_collapsed as sidebar_collapsed %}
|
||||
<body id="wagtail" class="{% block bodyclass %}{% endblock %} {% if slim_sidebar_enabled and sidebar_collapsed %}sidebar-collapsed{% endif %} {% if messages %}has-messages{% endif %} focus-outline-on">
|
||||
<div data-sprite></div>
|
||||
<script>
|
||||
function loadIconSprite() {
|
||||
|
|
|
|||
|
|
@ -678,6 +678,15 @@ def slim_sidebar_enabled():
|
|||
return 'slim-sidebar' in getattr(settings, 'WAGTAIL_EXPERIMENTAL_FEATURES', [])
|
||||
|
||||
|
||||
@register.simple_tag(takes_context=True)
|
||||
def sidebar_collapsed(context):
|
||||
request = context.get('request')
|
||||
collapsed = request.COOKIES.get('wagtail_sidebar_collapsed', '0')
|
||||
if collapsed == '0':
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
@register.simple_tag(takes_context=True)
|
||||
def menu_props(context):
|
||||
request = context['request']
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
from django.test import RequestFactory, TestCase
|
||||
from django.test import RequestFactory, TestCase, override_settings
|
||||
from django.urls import reverse
|
||||
|
||||
from wagtail.admin.menu import AdminOnlyMenuItem, Menu, MenuItem, SubmenuMenuItem
|
||||
from wagtail.admin.ui import sidebar
|
||||
|
|
@ -17,6 +18,28 @@ class TestMenuRendering(TestCase, WagtailTestUtils):
|
|||
def setUp(self):
|
||||
self.request = RequestFactory().get('/admin')
|
||||
self.request.user = self.create_superuser(username='admin')
|
||||
self.user = self.login()
|
||||
|
||||
@override_settings(WAGTAIL_EXPERIMENTAL_FEATURES={"slim-sidebar"})
|
||||
def test_remember_collapsed(self):
|
||||
'''Sidebar should render with collapsed class applied.'''
|
||||
# Sidebar should not be collapsed
|
||||
self.client.cookies['wagtail_sidebar_collapsed'] = '0'
|
||||
response = self.client.get(reverse('wagtailadmin_home'))
|
||||
self.assertNotContains(response, 'sidebar-collapsed')
|
||||
|
||||
# Sidebar should be collapsed
|
||||
self.client.cookies['wagtail_sidebar_collapsed'] = '1'
|
||||
response = self.client.get(reverse('wagtailadmin_home'))
|
||||
self.assertContains(response, 'sidebar-collapsed')
|
||||
|
||||
@override_settings(WAGTAIL_EXPERIMENTAL_FEATURES={})
|
||||
def test_collapsed_only_with_feature_flag(self):
|
||||
'''Sidebar should only remember its collapsed state with the right feature flag set.'''
|
||||
# Sidebar should not be collapsed because the feature flag is not enabled
|
||||
self.client.cookies['wagtail_sidebar_collapsed'] = '1'
|
||||
response = self.client.get(reverse('wagtailadmin_home'))
|
||||
self.assertNotContains(response, 'sidebar-collapsed')
|
||||
|
||||
def test_simple_menu(self):
|
||||
# Note: initialise the menu before registering hooks as this is what happens in reality.
|
||||
|
|
|
|||
Ładowanie…
Reference in New Issue