forked from NationalBankBelgium/stark
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(stark-ui): implementation of the app sidebar
ISSUES CLOSED: NationalBankBelgium#592
- Loading branch information
Showing
36 changed files
with
774 additions
and
112 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
export * from "./app-sidebar/app-sidebar.module"; | ||
export * from "./app-sidebar/components"; | ||
export * from "./app-sidebar/services"; | ||
export * from "./app-sidebar/testing"; |
41 changes: 41 additions & 0 deletions
41
packages/stark-ui/src/modules/app-sidebar/app-sidebar.module.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import { NgModule, Optional, SkipSelf } from "@angular/core"; | ||
import { CommonModule } from "@angular/common"; | ||
import { MatSidenavModule } from "@angular/material/sidenav"; | ||
import { StarkAppSidebarComponent } from "./components"; | ||
import { STARK_APP_SIDEBAR_SERVICE, StarkAppSidebarServiceImpl } from "./services"; | ||
import { ModuleWithProviders } from "@angular/compiler/src/core"; | ||
|
||
@NgModule({ | ||
declarations: [StarkAppSidebarComponent], | ||
imports: [CommonModule, MatSidenavModule], | ||
exports: [StarkAppSidebarComponent] | ||
}) | ||
export class StarkAppSidebarModule { | ||
/** | ||
* Instantiates the services only once since they should be singletons | ||
* so the forRoot() should be called only by the AppModule | ||
* @link https://angular.io/guide/singleton-services#forroot | ||
* @returns a module with providers | ||
*/ | ||
public static forRoot(): ModuleWithProviders { | ||
return { | ||
ngModule: StarkAppSidebarModule, | ||
providers: [{ provide: STARK_APP_SIDEBAR_SERVICE, useClass: StarkAppSidebarServiceImpl }] | ||
}; | ||
} | ||
|
||
/** | ||
* Prevents this module from being re-imported | ||
* @link https://angular.io/guide/singleton-services#prevent-reimport-of-the-coremodule | ||
* @param parentModule - the parent module | ||
*/ | ||
public constructor( | ||
@Optional() | ||
@SkipSelf() | ||
parentModule: StarkAppSidebarModule | ||
) { | ||
if (parentModule) { | ||
throw new Error("StarkAppSidebarModule is already loaded. Import it in the AppModule only"); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from "./components/app-sidebar.component"; |
6 changes: 6 additions & 0 deletions
6
packages/stark-ui/src/modules/app-sidebar/components/_app-sidebar-theme.scss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 */ |
42 changes: 42 additions & 0 deletions
42
packages/stark-ui/src/modules/app-sidebar/components/_app-sidebar.component.scss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 */ |
20 changes: 20 additions & 0 deletions
20
packages/stark-ui/src/modules/app-sidebar/components/app-sidebar.component.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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'}" 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" 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> |
86 changes: 86 additions & 0 deletions
86
packages/stark-ui/src/modules/app-sidebar/components/app-sidebar.component.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
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 { MockAppSidebarService } from "./../testing/app-sidebar.mock"; | ||
import { STARK_APP_SIDEBAR_SERVICE } from "./../services/app-sidebar.service.intf"; | ||
|
||
describe("AppSidebarComponent", () => { | ||
let fixture: ComponentFixture<StarkAppSidebarComponent>; | ||
let component: StarkAppSidebarComponent; | ||
|
||
beforeEach(async(() => { | ||
const mockLogger: MockStarkLoggingService = new MockStarkLoggingService(); | ||
return TestBed.configureTestingModule({ | ||
declarations: [StarkAppSidebarComponent], | ||
imports: [CommonModule, MatSidenavModule, NoopAnimationsModule], | ||
providers: [ | ||
{ provide: STARK_LOGGING_SERVICE, useValue: mockLogger }, | ||
{ provide: STARK_APP_SIDEBAR_SERVICE, useValue: new MockAppSidebarService() } | ||
] | ||
}).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); | ||
}); | ||
}); | ||
}); |
127 changes: 127 additions & 0 deletions
127
packages/stark-ui/src/modules/app-sidebar/components/app-sidebar.component.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
import { Component, HostBinding, Inject, Input, OnDestroy, OnInit, 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 { StarkAppSidebarOpenEvent, StarkAppSidebarService, STARK_APP_SIDEBAR_SERVICE } from "../services"; | ||
|
||
export type StarkAppSidebarLeftMode = "regular" | "menu"; | ||
|
||
/** | ||
* Name of the component | ||
*/ | ||
const componentName: string = "stark-app-sidebar"; | ||
|
||
/** | ||
* 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, OnInit { | ||
/** | ||
* Adds class="stark-app-sidebar" attribute on the host component | ||
*/ | ||
@HostBinding("class") | ||
public class: string = componentName; | ||
|
||
/** | ||
* Mode for the left sidebar: either the menu is shown or the regular sidebar | ||
*/ | ||
@Input() | ||
public sidenavLeftMode: StarkAppSidebarLeftMode; | ||
|
||
/** | ||
* 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, | ||
@Inject(STARK_APP_SIDEBAR_SERVICE) public sidebarService: StarkAppSidebarService | ||
) {} | ||
|
||
/** | ||
* Component lifecycle OnInit hook | ||
*/ | ||
public ngOnInit(): void { | ||
this.logger.debug(componentName + ": component initialized"); | ||
this.openSidebarSubscription = this.sidebarService.openSidebar$.subscribe((event: StarkAppSidebarOpenEvent) => { | ||
this.onOpenSideNav(event); | ||
}); | ||
|
||
this.closeSidebarSubscription = this.sidebarService.closeSidebar$.subscribe(() => { | ||
this.onCloseSideNavs(); | ||
}); | ||
} | ||
|
||
/** | ||
* Component lifecycle OnDestroy hook | ||
* Prevent memory leak when component destroyed | ||
*/ | ||
public ngOnDestroy(): void { | ||
this.openSidebarSubscription.unsubscribe(); | ||
this.closeSidebarSubscription.unsubscribe(); | ||
} | ||
|
||
/** | ||
* Open sidenav handler | ||
*/ | ||
public onOpenSideNav(event: StarkAppSidebarOpenEvent): void { | ||
if (event.mode) { | ||
this.sidenavLeftMode = event.mode; | ||
} | ||
switch (event.sidebar) { | ||
case "left": | ||
from(this.appSidenavLeft.open()).subscribe( | ||
(result: MatDrawerToggleResult) => this.logger.debug(componentName + ": left sidenav " + result), | ||
(error: Error) => this.logger.warn(componentName + ": ", error) | ||
); | ||
break; | ||
case "right": | ||
from(this.appSidenavRight.open()).subscribe( | ||
(result: MatDrawerToggleResult) => this.logger.debug(componentName + ": right sidebar " + result), | ||
(error: Error) => this.logger.warn(componentName + ": ", error) | ||
); | ||
break; | ||
default: | ||
break; | ||
} | ||
} | ||
|
||
/** | ||
* Close sidenav handler | ||
*/ | ||
public onCloseSideNavs(): void { | ||
this.appSidenavContainer.close(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export * from "./services/app-sidebar.service"; | ||
export * from "./services/app-sidebar.service.intf"; | ||
export * from "./services/app-sidebar-open-event.intf"; |
7 changes: 7 additions & 0 deletions
7
packages/stark-ui/src/modules/app-sidebar/services/app-sidebar-open-event.intf.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
/** | ||
* StarkAppSidebarOpenEvent interface | ||
*/ | ||
export interface StarkAppSidebarOpenEvent { | ||
mode?: "regular" | "menu"; | ||
sidebar: "left" | "right"; | ||
} |
Oops, something went wrong.