Skip to content

Commit

Permalink
feat(stark-ui): implementation of the app sidebar
Browse files Browse the repository at this point in the history
  • Loading branch information
catlabs committed Aug 29, 2018
1 parent 436e215 commit ea077f5
Show file tree
Hide file tree
Showing 32 changed files with 996 additions and 414 deletions.
530 changes: 304 additions & 226 deletions package-lock.json

Large diffs are not rendered by default.

154 changes: 80 additions & 74 deletions packages/stark-testing/package-lock.json

Large diffs are not rendered by default.

21 changes: 21 additions & 0 deletions packages/stark-ui/assets/themes/_menu-theme.scss
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,24 @@
color: map-get($mat-light-theme-foreground, disabled-button);
}
}

/* TODO: This code soul be moved when the app menu is implemented */
stark-app-sidebar {
.stark-app-sidenav-menu {
background-color: #16385a;
.mat-nav-list {
padding-top: 0;
.mat-list-item {
color: #fff;
font-size: 13px;
&:hover a {
background-color: rgba($color: #fff, $alpha: 0.3);
}
}
.mat-list-item-focus.active,
a.active {
background-color: rgba($color: #fff, $alpha: 0.4);
}
}
}
}
2 changes: 2 additions & 0 deletions packages/stark-ui/src/modules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ export * from "./modules/action-bar";
export * from "./modules/app-logo";
export * from "./modules/app-logout";
export * from "./modules/breadcrumb";
export * from "./modules/app-sidebar";
export * from "./modules/keyboard-directives";
export * from "./modules/date-picker";
export * from "./modules/date-range-picker";
export * from "./modules/dropdown";
Expand Down
3 changes: 3 additions & 0 deletions packages/stark-ui/src/modules/app-sidebar.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from "./app-sidebar/app-sidebar.module";
export * from "./app-sidebar/components";
export * from "./app-sidebar/services";
13 changes: 13 additions & 0 deletions packages/stark-ui/src/modules/app-sidebar/app-sidebar.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { NgModule } from "@angular/core";
import { CommonModule } from "@angular/common";
import { MatSidenavModule } from "@angular/material/sidenav";
import { StarkAppSidebarComponent } from "./components";
import { StarkAppSidebarService } from "./services";

@NgModule({
declarations: [StarkAppSidebarComponent],
imports: [CommonModule, MatSidenavModule],
exports: [StarkAppSidebarComponent],
providers: [StarkAppSidebarService]
})
export class StarkAppSidebarModule {}
1 change: 1 addition & 0 deletions packages/stark-ui/src/modules/app-sidebar/components.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./components/app-sidebar.component";
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/* ============================================================================== */
/* S t a r k A p p S i d e b a r - T h e m e */
/* ============================================================================== */
/* stark-ui: src/modules/app-sidebar/components/_app-sidebar-theme.scss */

/* END stark-ui: src/modules/app-sidebar/components/_app-sidebar-theme.scss */
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/* ============================================================================== */
/* S t a r k A p p S i d e b a r */
/* ============================================================================== */
/* stark-ui: src/modules/app-sidebar/components/_app-sidebar.component.scss */

stark-app-sidebar {
.mat-sidenav-content {
margin-top: $stark-header-size;
}

.mat-sidenav-container {
min-height: 100%;
}

.mat-sidenav {
display: flex;
flex-direction: column;
justify-content: space-between;
}

.stark-app-sidenav-left {
width: 150px;
}
.stark-app-sidenav-right {
width: 300px;
}
.stark-app-sidenav-menu {
margin-top: $stark-header-size;
width: 200px;
}
}

@media #{$tablet-query} {
stark-app-sidebar {
.stark-app-sidenav-menu,
.mat-sidenav-content {
margin-top: $stark-header-size-desktop;
}
}
}

/* END stark-ui: src/modules/app-sidebar/components/_app-sidebar.component.scss */
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<mat-sidenav-container #appSidenavContainer>
<mat-sidenav #appSidenavLeft class="stark-app-sidenav-left" [ngClass]="{'stark-app-sidenav-menu': sidenavLeftMode==='menu'}" closed mode="over" [fixedInViewport]="true"
[fixedBottomGap]="0">
<ng-container *ngIf="sidenavLeftMode==='regular'">
<ng-content class="regular" select="[stark-app-sidenav-left]"></ng-content>
</ng-container>
<ng-container class="menu" *ngIf="sidenavLeftMode==='menu'">
<ng-content select="[stark-app-sidenav-menu]"></ng-content>
</ng-container>
</mat-sidenav>
<mat-sidenav #appSidenavRight class="stark-app-sidenav-right" closed mode="over" position="end" [fixedInViewport]="true"
[fixedBottomGap]="0">
<ng-content select="[stark-app-sidenav-right]"></ng-content>
</mat-sidenav>
<mat-sidenav-content>
<div class="stark-container">
<ng-content select="[stark-app-sidenav-content]"></ng-content>
</div>
</mat-sidenav-content>
</mat-sidenav-container>
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import { CommonModule } from "@angular/common";
import { NoopAnimationsModule } from "@angular/platform-browser/animations";
import { async, ComponentFixture, TestBed } from "@angular/core/testing";
import { MatSidenavModule } from "@angular/material/sidenav";
import { STARK_LOGGING_SERVICE } from "@nationalbankbelgium/stark-core";
import { MockStarkLoggingService } from "@nationalbankbelgium/stark-core/testing";
import { StarkAppSidebarComponent } from "./app-sidebar.component";
import { StarkAppSidebarService } from "./../services/app-sidebar.service";

describe("AppSidebarComponent", () => {
let fixture: ComponentFixture<StarkAppSidebarComponent>;
let component: StarkAppSidebarComponent;

beforeEach(async(() => {
return TestBed.configureTestingModule({
declarations: [StarkAppSidebarComponent],
imports: [CommonModule, MatSidenavModule, NoopAnimationsModule],
providers: [{ provide: STARK_LOGGING_SERVICE, useValue: new MockStarkLoggingService() }, StarkAppSidebarService]
}).compileComponents();
}));

beforeEach(() => {
fixture = TestBed.createComponent(StarkAppSidebarComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

describe("sidenavs opening features ", () => {
it("left sidebar should be opened", () => {
component.onOpenSideNav({
sidebar: "left"
});
expect(component.appSidenavLeft.opened).toBe(true);
});

it("right sidebar should be opened", () => {
component.onOpenSideNav({
sidebar: "right"
});
expect(component.appSidenavRight.opened).toBe(true);
});

it("left sidebar should show the menu in menu mode", () => {
component.onOpenSideNav({
mode: "menu",
sidebar: "left"
});
fixture.detectChanges();
const sidenav: HTMLElement = fixture.nativeElement.querySelector(".stark-app-sidenav-menu");
expect(sidenav).toBeTruthy();
});

it("left sidebar should hide the menu in regular mode", () => {
component.onOpenSideNav({
mode: "regular",
sidebar: "left"
});
fixture.detectChanges();
const sidenav: HTMLElement = fixture.nativeElement.querySelector(".stark-app-sidenav-menu");
expect(sidenav).toBeFalsy();
});
});

describe("sidenavs closing features ", () => {
it("left sidebar should close", () => {
component.onOpenSideNav({
sidebar: "left"
});
component.onCloseSideNavs();
expect(component.appSidenavLeft.opened).toBe(false);
});

it("right sidebar should close", () => {
component.onOpenSideNav({
sidebar: "right"
});
component.onCloseSideNavs();
expect(component.appSidenavRight.opened).toBe(false);
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import { Component, Inject, Input, OnDestroy, ViewChild, ViewEncapsulation } from "@angular/core";
import { from, Subscription } from "rxjs";
import { MatSidenav, MatSidenavContainer, MatDrawerToggleResult } from "@angular/material/sidenav";
import { STARK_LOGGING_SERVICE, StarkLoggingService } from "@nationalbankbelgium/stark-core";
import { StarkAppSidebarService, StarkOpenSidebarEvent } from "../services/app-sidebar.service";

/**
* Component to display the application's sidebar
* Only 2 sidebars are allowed: https://github.com/angular/material2/issues/1514
*/
@Component({
selector: "stark-app-sidebar",
templateUrl: "./app-sidebar.component.html",
encapsulation: ViewEncapsulation.None
})
export class StarkAppSidebarComponent implements OnDestroy {
/**
* Mode for the left sidebar: either the menu is shown or the regular sidebar
*/
@Input()
public sidenavLeftMode: "regular" | "menu";

/**
* Reference to the MatSidenavContainer embedded in this component
*/
@ViewChild("appSidenavContainer")
public appSidenavContainer: MatSidenavContainer;

/**
* Reference to the left MatSidenav embedded in this component
*/
@ViewChild("appSidenavLeft")
public appSidenavLeft: MatSidenav;

/**
* Reference to the right MatSidenav embedded in this component
*/
@ViewChild("appSidenavRight")
public appSidenavRight: MatSidenav;

/**
* Subscription to the open sidebar Observable
*/
public openSidebarSubscription: Subscription;

/**
* Subscription to the close sidebar Observable
*/
public closeSidebarSubscription: Subscription;

/**
* Class constructor
* @param sidebarService - The sidebar service of the application
*/
public constructor(@Inject(STARK_LOGGING_SERVICE) public logger: StarkLoggingService, public sidebarService: StarkAppSidebarService) {
this.openSidebarSubscription = this.sidebarService.openSidebar$.subscribe((event: StarkOpenSidebarEvent) => {
this.onOpenSideNav(event);
});

this.closeSidebarSubscription = this.sidebarService.closeSidebar$.subscribe(() => {
this.onCloseSideNavs();
});
}

/**
* open sidenav handler
*/
public onOpenSideNav(event: StarkOpenSidebarEvent): void {
if (event.mode) {
this.sidenavLeftMode = event.mode;
}
switch (event.sidebar) {
case "left":
from(this.appSidenavLeft.open()).subscribe(
(result: MatDrawerToggleResult) => this.logger.debug("left sidenav " + result),
(error: Error) => this.logger.warn(error)
);
break;
case "right":
from(this.appSidenavRight.open()).subscribe(
(result: MatDrawerToggleResult) => this.logger.debug("right sidebar " + result),
(error: Error) => this.logger.warn(error)
);
break;
default:
break;
}
}

/**
* close sidenav handler
*/
public onCloseSideNavs(): void {
this.appSidenavContainer.close();
}

/**
* Component lifecycle OnDestroy hook
* Prevent memory leak when component destroyed
*/
public ngOnDestroy(): void {
this.openSidebarSubscription.unsubscribe();
this.closeSidebarSubscription.unsubscribe();
}
}
1 change: 1 addition & 0 deletions packages/stark-ui/src/modules/app-sidebar/services.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./services/app-sidebar.service";
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { StarkAppSidebarService, StarkOpenSidebarEvent } from "./app-sidebar.service";
import createSpy = jasmine.createSpy;

describe("ValueService", () => {
let service: StarkAppSidebarService;
beforeEach(() => {
service = new StarkAppSidebarService();
});

it("openMenu() should raise the correct event", () => {
service.openSidebar$.subscribe((event: StarkOpenSidebarEvent) => {
expect(event).toEqual({ mode: "menu", sidebar: "left" });
});
service.openMenu();
});

it("openLeft() should raise the correct event", () => {
service.openSidebar$.subscribe((event: StarkOpenSidebarEvent) => {
expect(event).toEqual({ mode: "regular", sidebar: "left" });
});
service.openLeft();
});

it("openRight() should raise the correct event", () => {
service.openSidebar$.subscribe((event: StarkOpenSidebarEvent) => {
expect(event).toEqual({ sidebar: "right" });
});
service.openRight();
});

it("close() should raise an event", () => {
const closeSidebars: jasmine.Spy = createSpy("closeSidebarsSpy");
service.closeSidebar$.subscribe(() => {
closeSidebars();
});
service.close();
expect(closeSidebars).toHaveBeenCalled();
});
});
Loading

0 comments on commit ea077f5

Please sign in to comment.