Skip to content
This repository was archived by the owner on Dec 18, 2024. It is now read-only.

feat: add the ability to link to the site with a particular theme #549

Merged
merged 1 commit into from
Oct 24, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 9 additions & 5 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/app/shared/theme-picker/theme-picker.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<mat-menu class="docs-theme-picker-menu" #themeMenu="matMenu" x-position="before">
<mat-grid-list cols="2">
<mat-grid-tile *ngFor="let theme of themes">
<div mat-menu-item (click)="installTheme(theme)">
<div mat-menu-item (click)="installTheme(theme.name)">
<div class="docs-theme-picker-swatch">
<mat-icon class="docs-theme-chosen-icon" *ngIf="currentTheme === theme">check_circle</mat-icon>
<div class="docs-theme-picker-primary" [style.background]="theme.primary"></div>
Expand Down
12 changes: 4 additions & 8 deletions src/app/shared/theme-picker/theme-picker.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,13 @@ describe('ThemePicker', () => {
}).compileComponents();
}));

it('should install theme based on href', () => {
it('should install theme based on name', () => {
const fixture = TestBed.createComponent(ThemePicker);
const component = fixture.componentInstance;
const href = 'pink-bluegrey.css';
const name = 'pink-bluegrey';
spyOn(component.styleManager, 'setStyle');
component.installTheme({
primary: '#E91E63',
accent: '#607D8B',
href,
});
component.installTheme(name);
expect(component.styleManager.setStyle).toHaveBeenCalled();
expect(component.styleManager.setStyle).toHaveBeenCalledWith('theme', `assets/${href}`);
expect(component.styleManager.setStyle).toHaveBeenCalledWith('theme', `assets/${name}.css`);
});
});
69 changes: 46 additions & 23 deletions src/app/shared/theme-picker/theme-picker.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,24 @@
import {Component, ViewEncapsulation, ChangeDetectionStrategy, NgModule} from '@angular/core';
import {
Component,
ViewEncapsulation,
ChangeDetectionStrategy,
NgModule,
OnInit,
OnDestroy,
} from '@angular/core';
import {StyleManager} from '../style-manager/style-manager';
import {ThemeStorage, DocsSiteTheme} from './theme-storage/theme-storage';
import {
MatButtonModule, MatGridListModule, MatIconModule, MatMenuModule,
MatTooltipModule
MatButtonModule,
MatGridListModule,
MatIconModule,
MatMenuModule,
MatTooltipModule,
} from '@angular/material';
import {CommonModule} from '@angular/common';
import {ActivatedRoute} from '@angular/router';
import {Subscription} from 'rxjs';
import {map, filter} from 'rxjs/operators';


@Component({
Expand All @@ -16,64 +29,74 @@ import {CommonModule} from '@angular/common';
encapsulation: ViewEncapsulation.None,
host: {'aria-hidden': 'true'},
})
export class ThemePicker {
currentTheme;
export class ThemePicker implements OnInit, OnDestroy {
private _queryParamSubscription = Subscription.EMPTY;
currentTheme: DocsSiteTheme;

themes = [
themes: DocsSiteTheme[] = [
{
primary: '#673AB7',
accent: '#FFC107',
href: 'deeppurple-amber.css',
name: 'deeppurple-amber',
isDark: false,
},
{
primary: '#3F51B5',
accent: '#E91E63',
href: 'indigo-pink.css',
name: 'indigo-pink',
isDark: false,
isDefault: true,
},
{
primary: '#E91E63',
accent: '#607D8B',
href: 'pink-bluegrey.css',
name: 'pink-bluegrey',
isDark: true,
},
{
primary: '#9C27B0',
accent: '#4CAF50',
href: 'purple-green.css',
name: 'purple-green',
isDark: true,
},
];

constructor(
public styleManager: StyleManager,
private _themeStorage: ThemeStorage
) {
const currentTheme = this._themeStorage.getStoredTheme();
if (currentTheme) {
this.installTheme(currentTheme);
}
private _themeStorage: ThemeStorage,
private _activatedRoute: ActivatedRoute) {
this.installTheme(this._themeStorage.getStoredThemeName());
}

ngOnInit() {
this._queryParamSubscription = this._activatedRoute.queryParamMap
.pipe(map(params => params.get('theme')), filter(Boolean))
.subscribe(themeName => this.installTheme(themeName));
}

ngOnDestroy() {
this._queryParamSubscription.unsubscribe();
}

installTheme(theme: DocsSiteTheme) {
this.currentTheme = this._getCurrentThemeFromHref(theme.href);
installTheme(themeName: string) {
const theme = this.themes.find(currentTheme => currentTheme.name === themeName);

if (!theme) {
return;
}

this.currentTheme = theme;

if (theme.isDefault) {
this.styleManager.removeStyle('theme');
} else {
this.styleManager.setStyle('theme', `assets/${theme.href}`);
this.styleManager.setStyle('theme', `assets/${theme.name}.css`);
}

if (this.currentTheme) {
this._themeStorage.storeTheme(this.currentTheme);
}
}

private _getCurrentThemeFromHref(href: string): DocsSiteTheme {
return this.themes.find(theme => theme.href === href);
}
}

@NgModule({
Expand Down
37 changes: 18 additions & 19 deletions src/app/shared/theme-picker/theme-storage/theme-storage.spec.ts
Original file line number Diff line number Diff line change
@@ -1,40 +1,39 @@
import {ThemeStorage} from './theme-storage';
import {ThemeStorage, DocsSiteTheme} from './theme-storage';


const testStorageKey = ThemeStorage.storageKey;
const testTheme = {
const testTheme: DocsSiteTheme = {
primary: '#000000',
accent: '#ffffff',
href: 'test/path/to/theme'
};
const createTestData = () => {
window.localStorage[testStorageKey] = JSON.stringify(testTheme);
};
const clearTestData = () => {
window.localStorage.clear();
name: 'test-theme'
};

describe('ThemeStorage Service', () => {
const service = new ThemeStorage();
const getCurrTheme = () => JSON.parse(window.localStorage.getItem(testStorageKey));
const getCurrTheme = () => window.localStorage.getItem(testStorageKey);
const secondTestTheme = {
primary: '#666666',
accent: '#333333',
href: 'some/cool/path'
name: 'other-test-theme'
};

beforeEach(createTestData);
afterEach(clearTestData);
beforeEach(() => {
window.localStorage[testStorageKey] = testTheme.name;
});

afterEach(() => {
window.localStorage.clear();
});

it('should set the current theme', () => {
expect(getCurrTheme()).toEqual(testTheme);
it('should set the current theme name', () => {
expect(getCurrTheme()).toEqual(testTheme.name);
service.storeTheme(secondTestTheme);
expect(getCurrTheme()).toEqual(secondTestTheme);
expect(getCurrTheme()).toEqual(secondTestTheme.name);
});

it('should get the current theme', () => {
const theme = service.getStoredTheme();
expect(theme).toEqual(testTheme);
it('should get the current theme name', () => {
const theme = service.getStoredThemeName();
expect(theme).toEqual(testTheme.name);
});

it('should clear the stored theme data', () => {
Expand Down
16 changes: 8 additions & 8 deletions src/app/shared/theme-picker/theme-storage/theme-storage.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {Injectable, EventEmitter} from '@angular/core';

export interface DocsSiteTheme {
href: string;
name: string;
accent: string;
primary: string;
isDark?: boolean;
Expand All @@ -11,29 +11,29 @@ export interface DocsSiteTheme {

@Injectable()
export class ThemeStorage {
static storageKey = 'docs-theme-storage-current';
static storageKey = 'docs-theme-storage-current-name';

onThemeUpdate: EventEmitter<DocsSiteTheme> = new EventEmitter<DocsSiteTheme>();

storeTheme(theme: DocsSiteTheme) {
try {
window.localStorage[ThemeStorage.storageKey] = JSON.stringify(theme);
} catch (e) { }
window.localStorage[ThemeStorage.storageKey] = theme.name;
} catch { }

this.onThemeUpdate.emit(theme);
}

getStoredTheme(): DocsSiteTheme {
getStoredThemeName(): string | null {
try {
return JSON.parse(window.localStorage[ThemeStorage.storageKey] || null);
} catch (e) {
return window.localStorage[ThemeStorage.storageKey] || null;
} catch {
return null;
}
}

clearStorage() {
try {
window.localStorage.removeItem(ThemeStorage.storageKey);
} catch (e) { }
} catch { }
}
}