diff --git a/package.json b/package.json index 951c1706d..9324dfa8e 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,9 @@ "@angular/platform-browser": "^4.0.0", "@angular/platform-browser-dynamic": "^4.0.0", "@angular/router": "^4.0.0", + "@ngrx/core": "^1.2.0", + "@ngrx/effects": "^2.0.3", + "@ngrx/store": "^2.2.2", "classlist.js": "^1.1.20150312", "core-js": "^2.4.1", "hammerjs": "^2.0.8", diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 5b7d25b9a..763ce6846 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -1,10 +1,15 @@ import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; +import { SettingsComponent } from './settings'; + const routes: Routes = [ { path: '', children: [] + }, { + path: 'settings', + component: SettingsComponent } ]; diff --git a/src/app/app.component.html b/src/app/app.component.html index 0786c69c4..8d6609b83 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -1,3 +1,4 @@ +
Angular NGrx Material Starter @@ -12,7 +13,7 @@ person Manage account - @@ -25,4 +26,6 @@

{{title}}

+ +
diff --git a/src/app/app.component.spec.ts b/src/app/app.component.spec.ts index c08fd9bb8..35a7302af 100644 --- a/src/app/app.component.spec.ts +++ b/src/app/app.component.spec.ts @@ -1,7 +1,9 @@ import { TestBed, async } from '@angular/core/testing'; import { RouterTestingModule } from '@angular/router/testing'; -import { SharedModule } from './shared/shared.module'; +import { SharedModule } from './shared'; +import { CoreModule } from './core'; + import { AppComponent } from './app.component'; describe('AppComponent', () => { @@ -9,7 +11,8 @@ describe('AppComponent', () => { TestBed.configureTestingModule({ imports: [ RouterTestingModule, - SharedModule + SharedModule, + CoreModule ], declarations: [ AppComponent diff --git a/src/app/app.component.ts b/src/app/app.component.ts index d76397cd1..26d5af139 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -1,10 +1,38 @@ -import { Component } from '@angular/core'; +import { Component, OnDestroy } from '@angular/core'; +import { OverlayContainer } from '@angular/material'; +import { Store } from '@ngrx/store'; +import { Subject } from 'rxjs/Subject'; +import 'rxjs/add/operator/takeUntil'; @Component({ selector: 'anms-root', templateUrl: './app.component.html', styleUrls: ['./app.component.scss'] }) -export class AppComponent { +export class AppComponent implements OnDestroy { + + private unsubscribe$: Subject = new Subject(); + + themeClass: string; + title = 'anms works!'; + + constructor( + overlayContainer: OverlayContainer, + private store: Store + ) { + store.select('settings') + .takeUntil(this.unsubscribe$) + .subscribe(({ theme }) => { + const themeClass = theme.toLowerCase(); + overlayContainer.themeClass = themeClass; + this.themeClass = themeClass; + }); + } + + ngOnDestroy(): void { + this.unsubscribe$.next(); + this.unsubscribe$.complete(); + } + } diff --git a/src/app/app.module.ts b/src/app/app.module.ts index a9e81d110..aae6825bd 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -5,6 +5,9 @@ import { HttpModule } from '@angular/http'; import { SharedModule } from './shared/shared.module'; +import { CoreModule } from './core'; +import { SettingsModule } from './settings'; + import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; @@ -14,7 +17,11 @@ import { AppComponent } from './app.component'; BrowserModule, HttpModule, AppRoutingModule, - SharedModule + + CoreModule, + SharedModule, + + SettingsModule ], declarations: [ AppComponent diff --git a/src/app/core/core.module.ts b/src/app/core/core.module.ts index ece94b3e0..a5cb3e754 100644 --- a/src/app/core/core.module.ts +++ b/src/app/core/core.module.ts @@ -1,9 +1,13 @@ import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; +import { StoreModule } from '@ngrx/store'; + +import { settingsReducer } from '../settings'; @NgModule({ imports: [ - CommonModule + CommonModule, + StoreModule.provideStore({ settings: settingsReducer }) ], declarations: [] }) diff --git a/src/app/core/index.ts b/src/app/core/index.ts new file mode 100644 index 000000000..a30d0c716 --- /dev/null +++ b/src/app/core/index.ts @@ -0,0 +1 @@ +export * from './core.module'; diff --git a/src/app/settings/index.ts b/src/app/settings/index.ts new file mode 100644 index 000000000..9a0168fb3 --- /dev/null +++ b/src/app/settings/index.ts @@ -0,0 +1,3 @@ +export * from './settings.module'; +export * from './settings.reducer'; +export * from './settings/settings.component'; diff --git a/src/app/settings/settings.module.ts b/src/app/settings/settings.module.ts new file mode 100644 index 000000000..ae5363f8e --- /dev/null +++ b/src/app/settings/settings.module.ts @@ -0,0 +1,15 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; + +import { SharedModule } from '../shared'; + +import { SettingsComponent } from './settings/settings.component'; + +@NgModule({ + imports: [ + CommonModule, + SharedModule + ], + declarations: [SettingsComponent] +}) +export class SettingsModule { } diff --git a/src/app/settings/settings.reducer.ts b/src/app/settings/settings.reducer.ts new file mode 100644 index 000000000..dc4402967 --- /dev/null +++ b/src/app/settings/settings.reducer.ts @@ -0,0 +1,18 @@ +import { Action } from '@ngrx/store'; + +export const SETTINGS_THEME = 'SETTINGS_THEME'; + +export const initialState = { + theme: 'default' +}; + +export function settingsReducer(state = initialState, action: Action) { + switch (action.type) { + case SETTINGS_THEME: + return { theme: action.payload }; + + default: + return state; + } +} + diff --git a/src/app/settings/settings/settings.component.html b/src/app/settings/settings/settings.component.html new file mode 100644 index 000000000..00c1e8358 --- /dev/null +++ b/src/app/settings/settings/settings.component.html @@ -0,0 +1,5 @@ + + + {{t.label}} + + diff --git a/src/styles-theme.scss b/src/app/settings/settings/settings.component.scss similarity index 100% rename from src/styles-theme.scss rename to src/app/settings/settings/settings.component.scss diff --git a/src/app/settings/settings/settings.component.spec.ts b/src/app/settings/settings/settings.component.spec.ts new file mode 100644 index 000000000..8b45d5d75 --- /dev/null +++ b/src/app/settings/settings/settings.component.spec.ts @@ -0,0 +1,34 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { NoopAnimationsModule } from '@angular/platform-browser/animations'; + +import { CoreModule } from '../../core'; +import { SharedModule } from '../../shared'; + +import { SettingsComponent } from './settings.component'; + +describe('SettingsComponent', () => { + let component: SettingsComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [ + NoopAnimationsModule, + CoreModule, + SharedModule + ], + declarations: [ SettingsComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(SettingsComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should be created', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/settings/settings/settings.component.ts b/src/app/settings/settings/settings.component.ts new file mode 100644 index 000000000..44d624eb0 --- /dev/null +++ b/src/app/settings/settings/settings.component.ts @@ -0,0 +1,40 @@ +import { Component, OnInit, OnDestroy } from '@angular/core'; +import { Store } from '@ngrx/store'; +import { Subject } from 'rxjs/Subject'; +import 'rxjs/add/operator/takeUntil'; +import { SETTINGS_THEME } from '../settings.reducer'; + +@Component({ + selector: 'anms-settings', + templateUrl: './settings.component.html', + styleUrls: ['./settings.component.scss'] +}) +export class SettingsComponent implements OnInit, OnDestroy { + + private unsubscribe$: Subject = new Subject(); + theme: string; + + themes = [ + { value: 'DEFAULT-THEME', label: 'Default' }, + { value: 'DARK-THEME', label: 'Dark' } + ]; + + constructor(private store: Store) { + store.select('settings') + .takeUntil(this.unsubscribe$) + .subscribe(({ theme }) => this.theme = theme); + } + + ngOnInit() { + } + + ngOnDestroy(): void { + this.unsubscribe$.next(); + this.unsubscribe$.complete(); + } + + onThemeSelect({ value }) { + this.store.dispatch({ type: SETTINGS_THEME, payload: value }); + } + +} diff --git a/src/app/shared/index.ts b/src/app/shared/index.ts new file mode 100644 index 000000000..bc349d6c0 --- /dev/null +++ b/src/app/shared/index.ts @@ -0,0 +1 @@ +export * from './shared.module'; diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts index 7eb7b2842..eca85845c 100644 --- a/src/app/shared/shared.module.ts +++ b/src/app/shared/shared.module.ts @@ -5,6 +5,7 @@ import { MdButtonModule, MdToolbarModule, MdMenuModule, + MdSelectModule, MdIconModule } from '@angular/material'; @@ -15,6 +16,7 @@ import { MdButtonModule, MdToolbarModule, + MdSelectModule, MdMenuModule, MdIconModule ], @@ -25,6 +27,7 @@ import { MdButtonModule, MdMenuModule, + MdSelectModule, MdToolbarModule, MdIconModule ] diff --git a/src/styles-theme-dark.scss b/src/styles-theme-dark.scss new file mode 100644 index 000000000..f4e8cda75 --- /dev/null +++ b/src/styles-theme-dark.scss @@ -0,0 +1,4 @@ +$anms-dark-primary: mat-palette($mat-indigo, 900); +$anms-dark-accent: mat-palette($mat-amber, A200, A100, A400); +$anms-dark-warn: mat-palette($mat-deep-orange); +$anms-dark-theme: mat-dark-theme($anms-dark-primary, $anms-dark-accent, $anms-dark-warn); diff --git a/src/styles-theme-default.scss b/src/styles-theme-default.scss new file mode 100644 index 000000000..da2d0519f --- /dev/null +++ b/src/styles-theme-default.scss @@ -0,0 +1,5 @@ +$anms-primary: mat-palette($mat-amber); +$anms-accent: mat-palette($mat-pink, A200, A100, A400); +$anms-warn: mat-palette($mat-red); + +$anms-theme: mat-light-theme($anms-primary, $anms-accent, $anms-warn); diff --git a/src/styles.scss b/src/styles.scss index adce80ec7..3b5d7f2a1 100644 --- a/src/styles.scss +++ b/src/styles.scss @@ -1,26 +1,14 @@ @import 'reset.scss'; @import '~@angular/material/theming'; -// Plus imports for other components in your app. -// Include the common styles for Angular Material. We include this here so that you only -// have to load a single css file for Angular Material in your app. -// Be sure that you only ever include this mixin once! @include mat-core(); -// Define the palettes for your theme using the Material Design palettes available in palette.scss -// (imported above). For each palette, you can optionally specify a default, lighter, and darker -// hue. -$anms-primary: mat-palette($mat-amber); -$anms-accent: mat-palette($mat-pink, A200, A100, A400); +@import 'styles-theme-default.scss'; +@import 'styles-theme-dark.scss'; -// The warn palette is optional (defaults to red). -$anms-warn: mat-palette($mat-red); - -// Create the theme object (a Sass map containing all of the palettes). -$anms-theme: mat-light-theme($anms-primary, $anms-accent, $anms-warn); - -// Include theme styles for core and each component used in your app. -// Alternatively, you can import and @include the theme mixins for each component -// that you are using. @include angular-material-theme($anms-theme); + +.dark-theme { + @include angular-material-theme($anms-dark-theme); +}