diff --git a/cypress/integration/sidebar.spec.js b/cypress/integration/sidebar.spec.js index c7adc82b..5314bd41 100644 --- a/cypress/integration/sidebar.spec.js +++ b/cypress/integration/sidebar.spec.js @@ -1,77 +1,75 @@ /** * Copyright (C) 2019 The Software Heritage developers * See the AUTHORS file at the top-level directory of this distribution * License: GNU Affero General Public License version 3, or any later version * See top-level LICENSE file for more information */ const url = '/'; describe('Sidebar tests On Large Screen', function() { beforeEach(function() { cy.visit(url, { onBeforeLoad: (win) => { win.localStorage.clear(); } }); }); it('should toggle sidebar when swh-push-menu is clicked', function() { cy.get('.swh-push-menu') .click(); cy.get('body') .should('have.class', 'sidebar-collapse') .get('.nav-link > p') .should('not.be.visible'); cy.get('.swh-push-menu') .click(); cy.get('body') .should('not.have.class', 'sidebar-collapse') .get('.nav-link > p') .should('be.visible'); }); it('should have less width when collapsed compared to open', function() { let collapseWidth; cy.get('.swh-push-menu') .click() - .get('.swh-sidebar') - .wait(250) + .get('.swh-sidebar-collapsed') .invoke('width') .then((width) => { collapseWidth = width; }) .get('.swh-push-menu') .click() - .get('.swh-sidebar') - .wait(250) + .get('.swh-sidebar-expanded') .invoke('width') .then(openWidth => { assert.isBelow(collapseWidth, openWidth); }); }); }); describe('Sidebar Tests on small screens', function() { beforeEach(function() { cy.viewport('iphone-6'); cy.visit(url); }); it('should be collapsed by default', function() { cy.get('.swh-sidebar') .should('not.be.visible'); }); it('should toggle sidebar when swh-push-menu is clicked', function() { cy.get('.swh-push-menu') .click() .get('.swh-sidebar') .should('be.visible') .get('#sidebar-overlay') .click({force: true}) .get('.swh-sidebar') .should('not.be.visible'); }); }); diff --git a/swh/web/assets/src/bundles/webapp/webapp-utils.js b/swh/web/assets/src/bundles/webapp/webapp-utils.js index e91c06be..3799863e 100644 --- a/swh/web/assets/src/bundles/webapp/webapp-utils.js +++ b/swh/web/assets/src/bundles/webapp/webapp-utils.js @@ -1,264 +1,291 @@ /** * Copyright (C) 2018-2019 The Software Heritage developers * See the AUTHORS file at the top-level directory of this distribution * License: GNU Affero General Public License version 3, or any later version * See top-level LICENSE file for more information */ import objectFitImages from 'object-fit-images'; import {selectText} from 'utils/functions'; import {BREAKPOINT_MD} from 'utils/constants'; let collapseSidebar = false; -let previousSidebarState = localStorage.getItem('swh-sidebar-collapsed'); +let previousSidebarState = localStorage.getItem('remember.lte.pushmenu'); if (previousSidebarState !== undefined) { - collapseSidebar = JSON.parse(previousSidebarState); + collapseSidebar = previousSidebarState === 'sidebar-collapse'; } $(document).on('DOMContentLoaded', () => { // set state to collapsed on smaller devices if ($(window).width() < BREAKPOINT_MD) { collapseSidebar = true; } // restore previous sidebar state (collapsed/expanded) if (collapseSidebar) { // hack to avoid animated transition for collapsing sidebar // when loading a page let sidebarTransition = $('.main-sidebar, .main-sidebar:before').css('transition'); let sidebarEltsTransition = $('.sidebar .nav-link p, .main-sidebar .brand-text, .sidebar .user-panel .info').css('transition'); $('.main-sidebar, .main-sidebar:before').css('transition', 'none'); $('.sidebar .nav-link p, .main-sidebar .brand-text, .sidebar .user-panel .info').css('transition', 'none'); $('body').addClass('sidebar-collapse'); $('.swh-words-logo-swh').css('visibility', 'visible'); // restore transitions for user navigation setTimeout(() => { $('.main-sidebar, .main-sidebar:before').css('transition', sidebarTransition); $('.sidebar .nav-link p, .main-sidebar .brand-text, .sidebar .user-panel .info').css('transition', sidebarEltsTransition); }); } }); $(document).on('collapsed.lte.pushmenu', event => { if ($('body').width() >= BREAKPOINT_MD) { $('.swh-words-logo-swh').css('visibility', 'visible'); } }); $(document).on('shown.lte.pushmenu', event => { $('.swh-words-logo-swh').css('visibility', 'hidden'); }); function ensureNoFooterOverflow() { $('body').css('padding-bottom', $('footer').outerHeight() + 'px'); } $(document).ready(() => { // redirect to last browse page if any when clicking on the 'Browse' entry // in the sidebar $(`.swh-browse-link`).click(event => { let lastBrowsePage = sessionStorage.getItem('last-browse-page'); if (lastBrowsePage) { event.preventDefault(); window.location = lastBrowsePage; } }); + const mainSideBar = $('.main-sidebar'); + + function updateSidebarState() { + const body = $('body'); + if (body.hasClass('sidebar-collapse') && + !mainSideBar.hasClass('swh-sidebar-collapsed')) { + mainSideBar.removeClass('swh-sidebar-expanded'); + mainSideBar.addClass('swh-sidebar-collapsed'); + $('.swh-words-logo-swh').css('visibility', 'visible'); + } else if (!body.hasClass('sidebar-collapse') && + !mainSideBar.hasClass('swh-sidebar-expanded')) { + mainSideBar.removeClass('swh-sidebar-collapsed'); + mainSideBar.addClass('swh-sidebar-expanded'); + $('.swh-words-logo-swh').css('visibility', 'hidden'); + } + // ensure correct sidebar state when loading a page + if (body.hasClass('hold-transition')) { + setTimeout(() => { + updateSidebarState(); + }); + } + } + + // set sidebar state after collapse / expand animation + mainSideBar.on('transitionend', evt => { + updateSidebarState(); + }); + + updateSidebarState(); + // ensure footer do not overflow main content for mobile devices // or after resizing the browser window ensureNoFooterOverflow(); $(window).resize(function() { ensureNoFooterOverflow(); if ($('body').hasClass('sidebar-collapse') && $('body').width() >= BREAKPOINT_MD) { $('.swh-words-logo-swh').css('visibility', 'visible'); } }); // activate css polyfill 'object-fit: contain' in old browsers objectFitImages(); // reparent the modals to the top navigation div in order to be able // to display them $('.swh-browse-top-navigation').append($('.modal')); let selectedCode = null; function getCodeOrPreEltUnderPointer(e) { let elts = document.elementsFromPoint(e.clientX, e.clientY); for (let elt of elts) { if (elt.nodeName === 'CODE' || elt.nodeName === 'PRE') { return elt; } } return null; } // click handler to set focus on code block for copy $(document).click(e => { selectedCode = getCodeOrPreEltUnderPointer(e); }); function selectCode(event, selectedCode) { if (selectedCode) { let hljsLnCodeElts = $(selectedCode).find('.hljs-ln-code'); if (hljsLnCodeElts.length) { selectText(hljsLnCodeElts[0], hljsLnCodeElts[hljsLnCodeElts.length - 1]); } else { selectText(selectedCode.firstChild, selectedCode.lastChild); } event.preventDefault(); } } // select the whole text of focused code block when user // double clicks or hits Ctrl+A $(document).dblclick(e => { if ((e.ctrlKey || e.metaKey)) { selectCode(e, getCodeOrPreEltUnderPointer(e)); } }); $(document).keydown(e => { if ((e.ctrlKey || e.metaKey) && e.key === 'a') { selectCode(e, selectedCode); } }); // show/hide back-to-top button let scrollThreshold = 0; scrollThreshold += $('.swh-top-bar').height() || 0; scrollThreshold += $('.navbar').height() || 0; $(window).scroll(() => { if ($(window).scrollTop() > scrollThreshold) { $('#back-to-top').css('display', 'block'); } else { $('#back-to-top').css('display', 'none'); } }); }); export function initPage(page) { $(document).ready(() => { // set relevant sidebar link to page active $(`.swh-${page}-item`).addClass('active'); $(`.swh-${page}-link`).addClass('active'); // triggered when unloading the current page $(window).on('unload', () => { - // backup sidebar state (collapsed/expanded) - let sidebarCollapsed = $('body').hasClass('sidebar-collapse'); - localStorage.setItem('swh-sidebar-collapsed', JSON.stringify(sidebarCollapsed)); // backup current browse page if (page === 'browse') { sessionStorage.setItem('last-browse-page', window.location); } }); }); } export function initHomePage() { $(document).ready(() => { $('.swh-coverage-list').iFrameResize({heightCalculationMethod: 'taggedElement'}); fetch(Urls.stat_counters()) .then(response => response.json()) .then(data => { if (data.stat_counters.content) { $('#swh-contents-count').html(data.stat_counters.content.toLocaleString()); $('#swh-revisions-count').html(data.stat_counters.revision.toLocaleString()); $('#swh-origins-count').html(data.stat_counters.origin.toLocaleString()); $('#swh-directories-count').html(data.stat_counters.directory.toLocaleString()); $('#swh-persons-count').html(data.stat_counters.person.toLocaleString()); $('#swh-releases-count').html(data.stat_counters.release.toLocaleString()); } if (data.stat_counters_history.content) { swh.webapp.drawHistoryCounterGraph('#swh-contents-count-history', data.stat_counters_history.content); swh.webapp.drawHistoryCounterGraph('#swh-revisions-count-history', data.stat_counters_history.revision); swh.webapp.drawHistoryCounterGraph('#swh-origins-count-history', data.stat_counters_history.origin); } else { $('#swh-contents-count-history').hide(); $('#swh-revisions-count-history').hide(); $('#swh-origins-count-history').hide(); } }); }); initPage('home'); } export function showModalMessage(title, message) { $('#swh-web-modal-message .modal-title').text(title); $('#swh-web-modal-message .modal-content p').text(message); $('#swh-web-modal-message').modal('show'); } export function showModalConfirm(title, message, callback) { $('#swh-web-modal-confirm .modal-title').text(title); $('#swh-web-modal-confirm .modal-content p').text(message); $('#swh-web-modal-confirm #swh-web-modal-confirm-ok-btn').bind('click', () => { callback(); $('#swh-web-modal-confirm').modal('hide'); $('#swh-web-modal-confirm #swh-web-modal-confirm-ok-btn').unbind('click'); }); $('#swh-web-modal-confirm').modal('show'); } export function showModalHtml(title, html) { $('#swh-web-modal-html .modal-title').text(title); $('#swh-web-modal-html .modal-body').html(html); $('#swh-web-modal-html').modal('show'); } export function addJumpToPagePopoverToDataTable(dataTableElt) { dataTableElt.on('draw.dt', function() { $('.paginate_button.disabled').css('cursor', 'pointer'); $('.paginate_button.disabled').on('click', event => { const pageInfo = dataTableElt.page.info(); let content = ' / ${pageInfo.pages}`; $(event.target).popover({ 'title': 'Jump to page', 'content': content, 'html': true, 'placement': 'top', 'sanitizeFn': swh.webapp.filterXSS }); $(event.target).popover('show'); $('.jump-to-page').on('change', function() { $('.paginate_button.disabled').popover('hide'); const pageNumber = parseInt($(this).val()) - 1; dataTableElt.page(pageNumber).draw('page'); }); }); }); dataTableElt.on('preXhr.dt', () => { $('.paginate_button.disabled').popover('hide'); }); } let swhObjectIcons; export function setSwhObjectIcons(icons) { swhObjectIcons = icons; } export function getSwhObjectIcon(swhObjectType) { return swhObjectIcons[swhObjectType]; } let browsedSwhObjectMetadata = {}; export function setBrowsedSwhObjectMetadata(metadata) { browsedSwhObjectMetadata = metadata; } export function getBrowsedSwhObjectMetadata() { return browsedSwhObjectMetadata; } diff --git a/swh/web/templates/layout.html b/swh/web/templates/layout.html index 5d5ad3ad..b5dbdfbd 100644 --- a/swh/web/templates/layout.html +++ b/swh/web/templates/layout.html @@ -1,231 +1,233 @@ {% comment %} Copyright (C) 2015-2019 The Software Heritage developers See the AUTHORS file at the top-level directory of this distribution License: GNU Affero General Public License version 3, or any later version See top-level LICENSE file for more information {% endcomment %} {% load js_reverse %} {% load static %} {% load render_bundle from webpack_loader %} {% load swh_templatetags %} {% block title %}{% endblock %} {% render_bundle 'vendors' %} {% render_bundle 'webapp' %} {% block header %}{% endblock %}
{% block content %}{% endblock %}
{% include "includes/global-modals.html" %}
back to top