diff --git a/resources/i18n/en.json b/resources/i18n/en.json index f4ef2741c4..0aa71ff43b 100644 --- a/resources/i18n/en.json +++ b/resources/i18n/en.json @@ -213,7 +213,8 @@ }, "sidebar": { "section": { - "toggle": "Toggle sidebar", + "pin": "Pin sidebar", + "unpin": "Unpin sidebar", "new": "New", "new_community": "Community", "new_collection": "Collection", diff --git a/src/app/+admin/admin-sidebar/admin-sidebar.component.html b/src/app/+admin/admin-sidebar/admin-sidebar.component.html index 9ddf2500e8..e5fb846d2f 100644 --- a/src/app/+admin/admin-sidebar/admin-sidebar.component.html +++ b/src/app/+admin/admin-sidebar/admin-sidebar.component.html @@ -39,7 +39,8 @@ - {{'admin.sidebar.section.toggle' | translate }} + {{'admin.sidebar.section.pin' | translate }} + {{'admin.sidebar.section.unpin' | translate }} diff --git a/src/app/+admin/admin-sidebar/admin-sidebar.component.spec.ts b/src/app/+admin/admin-sidebar/admin-sidebar.component.spec.ts index 54ce6b9953..c99e8adc58 100644 --- a/src/app/+admin/admin-sidebar/admin-sidebar.component.spec.ts +++ b/src/app/+admin/admin-sidebar/admin-sidebar.component.spec.ts @@ -1,4 +1,4 @@ -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { async, ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { TranslateModule } from '@ngx-translate/core'; import { ChangeDetectionStrategy, Injector, NO_ERRORS_SCHEMA } from '@angular/core'; @@ -117,25 +117,26 @@ describe('AdminSidebarComponent', () => { }); describe('when the the mouse enters the nav tag', () => { - beforeEach(() => { + it('should call expandPreview on the menuService after 100ms', fakeAsync(() => { spyOn(menuService, 'expandMenuPreview'); const sidebarToggler = fixture.debugElement.query(By.css('nav.navbar')); sidebarToggler.triggerEventHandler('mouseenter', {preventDefault: () => {/**/}}); - }); - - it('should call expandPreview on the menuService', () => { + tick(99); + expect(menuService.expandMenuPreview).not.toHaveBeenCalled(); + tick(1); expect(menuService.expandMenuPreview).toHaveBeenCalled(); - }); + })); }); + describe('when the the mouse leaves the nav tag', () => { - beforeEach(() => { + it('should call collapseMenuPreview on the menuService after 400ms', fakeAsync(() => { spyOn(menuService, 'collapseMenuPreview'); const sidebarToggler = fixture.debugElement.query(By.css('nav.navbar')); sidebarToggler.triggerEventHandler('mouseleave', {preventDefault: () => {/**/}}); - }); - - it('should call collapseMenuPreview on the menuService', () => { + tick(399); + expect(menuService.collapseMenuPreview).not.toHaveBeenCalled(); + tick(1); expect(menuService.collapseMenuPreview).toHaveBeenCalled(); - }); + })); }); }); diff --git a/src/app/+logout-page/logout-page.component.html b/src/app/+logout-page/logout-page.component.html index 9c6185b665..b5012ed53b 100644 --- a/src/app/+logout-page/logout-page.component.html +++ b/src/app/+logout-page/logout-page.component.html @@ -1,6 +1,6 @@
-
+

{{"logout.form.header" | translate}}

diff --git a/src/app/+search-page/search-filters/search-filter/search-filter.component.scss b/src/app/+search-page/search-filters/search-filter/search-filter.component.scss index 6e49172a48..d0c1d561e5 100644 --- a/src/app/+search-page/search-filters/search-filter/search-filter.component.scss +++ b/src/app/+search-page/search-filters/search-filter/search-filter.component.scss @@ -3,8 +3,9 @@ :host { border: 1px solid map-get($theme-colors, light); - .search-filter-wrapper.closed { - overflow: hidden; + overflow: hidden; + .search-filter-wrapper:not(.closed) { + overflow: visible; } .filter-toggle { line-height: $line-height-base; diff --git a/src/app/+search-page/search-filters/search-filter/search-filter.component.ts b/src/app/+search-page/search-filters/search-filter/search-filter.component.ts index 87f8edc1ea..d63b744ba7 100644 --- a/src/app/+search-page/search-filters/search-filter/search-filter.component.ts +++ b/src/app/+search-page/search-filters/search-filter/search-filter.component.ts @@ -89,7 +89,7 @@ export class SearchFilterComponent implements OnInit { * @param event The animation event */ finishSlide(event: any): void { - if (event.fromState === 'collapsed') { + if (event.fromState === 'void') { this.collapsed = false; } } @@ -99,7 +99,7 @@ export class SearchFilterComponent implements OnInit { * @param event The animation event */ startSlide(event: any): void { - if (event.toState === 'collapsed') { + if (event.toState === 'void') { this.collapsed = true; } } diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 27ff2e1ad5..a7b9fd59bf 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -75,6 +75,7 @@ export class AppComponent implements OnInit, AfterViewInit { } ngOnInit() { + const env: string = this.config.production ? 'Production' : 'Development'; const color: string = this.config.production ? 'red' : 'green'; console.info(`Environment: %c${env}`, `color: ${color}; font-weight: bold;`); diff --git a/src/app/header/header.component.scss b/src/app/header/header.component.scss index 7834cfbaaa..df4c0b8fb8 100644 --- a/src/app/header/header.component.scss +++ b/src/app/header/header.component.scss @@ -2,6 +2,9 @@ .navbar-brand img { height: $header-logo-height; + @media screen and (max-width: map-get($grid-breakpoints, sm)) { + height: $header-logo-height-xs; + } } .navbar-toggler .navbar-toggler-icon { background-image: none !important; diff --git a/src/app/navbar/navbar.component.scss b/src/app/navbar/navbar.component.scss index f8cc6992c2..947b785196 100644 --- a/src/app/navbar/navbar.component.scss +++ b/src/app/navbar/navbar.component.scss @@ -30,11 +30,9 @@ nav.navbar { .navbar-expand-md.navbar-container { @media screen and (max-width: map-get($grid-breakpoints, md)) { > .container { - padding-left: $spacer; - padding-right: $spacer; + padding: 0 $spacer; } - padding-left: 0; - padding-right: 0; + padding: 0; } } diff --git a/src/app/shared/host-window.service.ts b/src/app/shared/host-window.service.ts index 9d16ca8f6e..840b134996 100644 --- a/src/app/shared/host-window.service.ts +++ b/src/app/shared/host-window.service.ts @@ -29,7 +29,8 @@ export class HostWindowService { private variableService: CSSVariableService ) { /* See _exposed_variables.scss */ - variableService.getAllVariables().pipe(first()).subscribe((variables) => { + variableService.getAllVariables() + .subscribe((variables) => { this.breakPoints.XL_MIN = parseInt(variables.xlMin, 10); this.breakPoints.LG_MIN = parseInt(variables.lgMin, 10); this.breakPoints.MD_MIN = parseInt(variables.mdMin, 10); diff --git a/src/app/shared/menu/menu.component.spec.ts b/src/app/shared/menu/menu.component.spec.ts index f45f5ad391..52cdebbe91 100644 --- a/src/app/shared/menu/menu.component.spec.ts +++ b/src/app/shared/menu/menu.component.spec.ts @@ -1,4 +1,4 @@ -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { async, ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { TranslateModule } from '@ngx-translate/core'; import { ChangeDetectionStrategy, Injector, NO_ERRORS_SCHEMA } from '@angular/core'; @@ -67,22 +67,24 @@ describe('MenuComponent', () => { }); describe('expandPreview', () => { - beforeEach(() => { + it('should trigger the expandPreview function on the menu service after 100ms', fakeAsync(() => { spyOn(menuService, 'expandMenuPreview'); comp.expandPreview(new Event('click')); - }); - it('should trigger the expandPreview function on the menu service', () => { + tick(99); + expect(menuService.expandMenuPreview).not.toHaveBeenCalled(); + tick(1); expect(menuService.expandMenuPreview).toHaveBeenCalledWith(comp.menuID); - }) + })) }); describe('collapsePreview', () => { - beforeEach(() => { + it('should trigger the collapsePreview function on the menu service after 400ms', fakeAsync(() => { spyOn(menuService, 'collapseMenuPreview'); comp.collapsePreview(new Event('click')); - }); - it('should trigger the collapsePreview function on the menu service', () => { + tick(399); + expect(menuService.collapseMenuPreview).not.toHaveBeenCalled(); + tick(1); expect(menuService.collapseMenuPreview).toHaveBeenCalledWith(comp.menuID); - }) + })) }); }); diff --git a/src/app/shared/menu/menu.component.ts b/src/app/shared/menu/menu.component.ts index 98bdcc3d66..763da86c4b 100644 --- a/src/app/shared/menu/menu.component.ts +++ b/src/app/shared/menu/menu.component.ts @@ -5,8 +5,10 @@ import { MenuID } from '../../shared/menu/initial-menus-state'; import { MenuSection } from '../../shared/menu/menu.reducer'; import { first, map } from 'rxjs/operators'; import { GenericConstructor } from '../../core/shared/generic-constructor'; +import { hasValue } from '../empty.util'; import { MenuSectionComponent } from './menu-section/menu-section.component'; import { getComponentForMenu } from './menu-section.decorator'; +import Timer = NodeJS.Timer; /** * A basic implementation of a MenuComponent @@ -56,6 +58,11 @@ export class MenuComponent implements OnInit { */ changeDetection: ChangeDetectionStrategy.OnPush; + /** + * Timer to briefly delay the sidebar preview from opening or closing + */ + private previewTimer: Timer; + constructor(protected menuService: MenuService, protected injector: Injector) { } @@ -108,7 +115,7 @@ export class MenuComponent implements OnInit { */ expandPreview(event: Event) { event.preventDefault(); - this.menuService.expandMenuPreview(this.menuID); + this.previewToggleDebounce(() => this.menuService.expandMenuPreview(this.menuID), 100); } /** @@ -117,7 +124,20 @@ export class MenuComponent implements OnInit { */ collapsePreview(event: Event) { event.preventDefault(); - this.menuService.collapseMenuPreview(this.menuID); + this.previewToggleDebounce(() => this.menuService.collapseMenuPreview(this.menuID), 400); + } + + /** + * delay the handler function by the given amount of time + * + * @param {Function} handler The function to delay + * @param {number} ms The amount of ms to delay the handler function by + */ + private previewToggleDebounce(handler: () => void, ms: number): void { + if (hasValue(this.previewTimer)) { + clearTimeout(this.previewTimer); + } + this.previewTimer = setTimeout(handler, ms); } /** diff --git a/src/styles/_custom_variables.scss b/src/styles/_custom_variables.scss index de5ea9be48..e8d839826d 100644 --- a/src/styles/_custom_variables.scss +++ b/src/styles/_custom_variables.scss @@ -14,6 +14,7 @@ $nav-z-index: 10; $sidebar-z-index: 20; $header-logo-height: 80px; +$header-logo-height-xs: 50px; $admin-sidebar-bg: $dark; $admin-sidebar-active-bg: darken($dark, 3%);