Skip to content
This repository has been archived by the owner on Jan 3, 2025. It is now read-only.

Commit

Permalink
feat(DockMonitor): Added dock monitor to wrap devtools.
Browse files Browse the repository at this point in the history
  • Loading branch information
MikeRyanDev committed Mar 10, 2016
1 parent 257c8a8 commit d10fb7a
Show file tree
Hide file tree
Showing 10 changed files with 361 additions and 6 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
"reflect-metadata": "0.1.2",
"rimraf": "^2.5.1",
"tslint": "^3.4.0",
"typescript": "^1.7.3",
"typescript": "^1.8.7",
"typings": "^0.6.6",
"zone.js": "0.5.15"
},
Expand Down
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from './store';
export {LogMonitor} from './monitors/log-monitor';
export * from './monitors/dock-monitor';
26 changes: 26 additions & 0 deletions src/monitors/dock-monitor/actions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import {Injectable} from 'angular2/core';
import {Action} from '@ngrx/store';


@Injectable()
export class DockActions{
static TOGGLE_VISIBILITY = '@@redux-devtools-log-monitor/TOGGLE_VISIBILITY';
toggleVisibility(): Action {
return { type: DockActions.TOGGLE_VISIBILITY };
}

static CHANGE_POSITION = '@@redux-devtools-log-monitor/CHANGE_POSITION';
changePosition(): Action {
return { type: DockActions.CHANGE_POSITION };
}

static CHANGE_SIZE = '@@redux-devtools-log-monitor/CHANGE_SIZE';
changeSize(size: number): Action {
return { type: DockActions.CHANGE_SIZE, payload: size };
}

static CHANGE_MONITOR = '@@redux-devtools-log-monitor/CHANGE_MONITOR';
changeMonitor(): Action {
return { type: DockActions.CHANGE_MONITOR };
}
}
94 changes: 94 additions & 0 deletions src/monitors/dock-monitor/commander.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import 'rxjs/add/operator/filter';
import 'rxjs/add/operator/map';
import {Component, Input, Output, Injectable, Renderer} from 'angular2/core';
import {Observable} from 'rxjs/Observable';
import {Subject} from 'rxjs/Subject';
import {Subscriber} from 'rxjs/Subscriber';

import {keycodes} from './keycodes';

export interface ParsedCommand{
name?: string;
ctrl: boolean;
meta: boolean;
shift: boolean;
alt: boolean;
sequence?: string;
}

@Component({
selector: 'ngrx-commander',
template: '',
styles: [':host{ display: none }'],
host: {
'(document.keydown)': 'keydown$.next($event)'
}
})
export class Commander{
private keydown$ = new Subject<KeyboardEvent>();
private _ignoreTags = ['INPUT', 'SELECT', 'TEXTAREA'];

constructor(private _renderer: Renderer){ }

@Input() command: string;
@Output() press = this.keydown$
.filter(e => this._ignoreTags.indexOf((e.target as HTMLElement).tagName) < 0)
.filter(e => !((e.target as HTMLElement).isContentEditable))
.filter(e => {
const command = this.parseCommand(this.command);

if (!command) {
return false;
}

const charCode = e.keyCode || e.which;
const char = String.fromCharCode(charCode);
return command.name.toUpperCase() === char.toUpperCase() &&
command.alt === e.altKey &&
command.ctrl === e.ctrlKey &&
command.meta === e.metaKey &&
command.shift === e.shiftKey;
})
.map(e => {
e.preventDefault();

return { command: this.command };
});

parseCommand(s: string): ParsedCommand {
var keyString = s.trim().toLowerCase();

if ( !/^(ctrl-|shift-|alt-|meta-){0,4}\w+$/.test(keyString) ){
throw new Error('The string to parse needs to be of the format "c", "ctrl-c", "shift-ctrl-c".');
}

const parts = keyString.split('-');
const key: ParsedCommand = {
ctrl: false,
meta: false,
shift: false,
alt: false
};

let c;

key.name = parts.pop();

while((c = parts.pop())) {
key[c] = true;
}

if(key.ctrl) {
key.sequence = keycodes.ctrl[key.name] || key.name;
}
else {
key.sequence = keycodes.nomod[key.name] || key.name;
}

if (key.shift && key.sequence && key.sequence.length === 1) {
key.sequence = key.sequence.toUpperCase();
}

return key;
}
}
59 changes: 59 additions & 0 deletions src/monitors/dock-monitor/dock-monitor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import 'rxjs/add/observable/merge';
import 'rxjs/add/operator/filter';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/distinctUntilChanged';
import {StoreDevtools} from '../../store/devtools';
import {Component, ChangeDetectionStrategy} from 'angular2/core';
import {Subject} from 'rxjs/Subject';
import {Observable} from 'rxjs/Observable';
import {Subscription} from 'rxjs/Subscription';

import {DockState} from './reducer';
import {Commander} from './commander';
import {Dock} from './dock';
import {DockActions} from './actions';


@Component({
selector: 'dock-monitor',
changeDetection: ChangeDetectionStrategy.OnPush,
directives: [ Dock, Commander ],
providers: [ DockActions ],
template: `
<ngrx-commander [command]="toggleCommand" (press)="toggle$.next($event)"></ngrx-commander>
<ngrx-commander [command]="positionCommand" (press)="changePosition$.next($event)"></ngrx-commander>
<ngrx-dock
[visible]="visible$ | async"
[position]="position$ | async"
[size]="size$ | async">
<ng-content></ng-content>
</ngrx-dock>
`
})
export class DockMonitor {
constructor(
private tools: StoreDevtools,
private actions: DockActions,
private commander: Commander
){
Observable
.merge(this.toggleAction$, this.positionAction$)
.subscribe(this.tools);
}

private state$ = this.tools.liftedState.map<DockState>(s => s.monitorState.dock);
private visible$ = this.state$.map(s => s.visible).distinctUntilChanged();
private position$ = this.state$.map(s => s.position).distinctUntilChanged();
private size$ = this.state$.map(s => s.size).distinctUntilChanged();

private toggleCommand = 'ctrl-h';
private toggle$ = new Subject();
private toggleAction$ = this.toggle$
.map(() => this.actions.toggleVisibility());

private positionCommand = 'ctrl-m';
private changePosition$ = new Subject();
private positionAction$ = this.changePosition$
.map(() => this.actions.changePosition());
}
92 changes: 92 additions & 0 deletions src/monitors/dock-monitor/dock.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import {Component, HostListener, HostBinding, Input} from 'angular2/core';
import {PositionsType} from './reducer';


@Component({
selector: 'ngrx-dock',
template: `
<div class="dock">
<div class="dock-content">
<ng-content></ng-content>
</div>
</div>
`,
styles: [`
:host {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
transition: all 0.3s;
z-index: 9999;
}
.dock {
position: absolute;
z-index: 1;
box-shadow: 0 0 4px rgba(0, 0, 0, 0.3);
background-color: white;
left: 0;
top: 0;
width: 100%;
height: 100%;
}
.dock-content {
width: 100%;
height: 100%;
overflow: auto;
}
`]
})
export class Dock{
@Input() position: PositionsType = 'right';
@Input() size: number = 0.3;
@Input() visible: boolean = true;

get absoluteSize(){
return `${100 * this.size}%`;
}

get restSize(){
return `${100 - (100 * this.size)}%`;
}

@HostBinding('style.left') get leftPosition(){
return this.calculatePosition('left', 'right');
}

@HostBinding('style.right') get rightPosition(){
return this.calculatePosition('right', 'left');
}

@HostBinding('style.top') get topPosition(){
return this.calculatePosition('top', 'bottom');
}

@HostBinding('style.bottom') get bottomPosition(){
return this.calculatePosition('bottom', 'top');
}

calculatePosition(primary: PositionsType, secondary: PositionsType) {
if(this.visible){
switch (this.position) {
case secondary:
return this.restSize;
default:
return '0%';
}
}
else {
switch (this.position) {
case primary:
return `-${this.absoluteSize}`;
case secondary:
return '100%';
default:
return '0%';
}
}
}
}
43 changes: 43 additions & 0 deletions src/monitors/dock-monitor/keycodes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Most of these are according to this table: http://www.ssicom.org/js/x171166.htm
// However where nodejs readline diverges, they are adjusted to conform to it
export const keycodes = {
nomod: {
escape: '\u001b',
space: ' ' // actually '\u0020'
},
ctrl: {
' ': '\u0000',
'a': '\u0001',
'b': '\u0002',
'c': '\u0003',
'd': '\u0004',
'e': '\u0005',
'f': '\u0006',
'g': '\u0007',
'h': '\u0008',
'i': '\u0009',
'j': '\u000a',
'k': '\u000b',
'm': '\u000c',
'n': '\u000d',
'l': '\u000e',
'o': '\u000f',
'p': '\u0010',
'q': '\u0011',
'r': '\u0012',
's': '\u0013',
't': '\u0014',
'u': '\u0015',
'v': '\u0016',
'w': '\u0017',
'x': '\u0018',
'y': '\u0019',
'z': '\u001a',
'[': '\u001b',
'\\':'\u001c',
']': '\u001d',
'^': '\u001e',
'_': '\u001f',
'space': '\u0000'
}
};
35 changes: 35 additions & 0 deletions src/monitors/dock-monitor/reducer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import {combineReducers, Reducer} from '@ngrx/store';
import {DockActions} from './actions';

export const POSITIONS = ['left', 'top', 'right', 'bottom'];
export type PositionsType = 'left' | 'top' | 'right' | 'bottom';

function position(state: PositionsType = 'right', action) {
return (action.type === DockActions.CHANGE_POSITION) ?
POSITIONS[(POSITIONS.indexOf(state) + 1) % POSITIONS.length] :
state;
}

function size(state: number = 0.3, action) {
return (action.type === DockActions.CHANGE_SIZE) ?
action.size :
state;
}

function visible(state: boolean = true, action) {
return (action.type === DockActions.TOGGLE_VISIBILITY) ?
!state :
state;
}

export interface DockState{
position?: PositionsType;
visible?: boolean;
size?: number;
}

export const dockReducer = combineReducers({
position,
visible,
size
});
6 changes: 2 additions & 4 deletions src/monitors/log-monitor/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,11 @@ import {LogMonitorButton} from './log-monitor-button';
display: block;
background-color: #2A2F3A;
font-family: 'monaco', 'Consolas', 'Lucida Console', monospace;
position: absolute;
top: 0;
right: 0;
position: relative;
overflow-y: hidden;
width: 100%;
height: 100%;
max-width: 300px;
min-width: 300px;
direction: ltr;
}
Expand Down
9 changes: 8 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,14 @@
"src/monitors/log-monitor/index.ts",
"src/monitors/log-monitor/log-entry-item.ts",
"src/monitors/log-monitor/log-monitor-button.ts",
"src/monitors/log-monitor/log-monitor-entry.ts"
"src/monitors/log-monitor/log-monitor-entry.ts",
"src/monitors/dock-monitor/actions.ts",
"src/monitors/dock-monitor/commander.ts",
"src/monitors/dock-monitor/dock.ts",
"src/monitors/dock-monitor/index.ts",
"src/monitors/dock-monitor/monitor.ts",
"src/monitors/dock-monitor/parse-key.ts",
"src/monitors/dock-monitor/reducer.ts"
],
"exclude": [
"node_modules"
Expand Down

0 comments on commit d10fb7a

Please sign in to comment.