Added effects
This commit is contained in:
@@ -2,7 +2,10 @@ import { NgModule, ReflectiveInjector } from '@angular/core';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
|
||||
import { EffectsModule } from '@ngrx/effects';
|
||||
import { StoreModule } from '@ngrx/store';
|
||||
import { StoreDevtoolsModule } from '@ngrx/store-devtools';
|
||||
import { StoreLogMonitorModule, useLogMonitor } from '@ngrx/store-log-monitor';
|
||||
|
||||
import { DragulaModule } from 'ng2-dragula/ng2-dragula';
|
||||
import { Select2Module } from 'ng2-select2/ng2-select2';
|
||||
@@ -54,11 +57,9 @@ import { DataProviderService } from './services/data-provider.service';
|
||||
import { MapperService } from './services/mapper.service';
|
||||
import { UhkConfigurationService } from './services/uhk-configuration.service';
|
||||
|
||||
import { DataStorage } from './store/storage';
|
||||
import { StoreDevtoolsModule } from '@ngrx/store-devtools';
|
||||
import { StoreLogMonitorModule, useLogMonitor } from '@ngrx/store-log-monitor';
|
||||
|
||||
import { KeymapEffects, MacroEffects } from './store/effects';
|
||||
import { keymapReducer, macroReducer, presetReducer } from './store/reducers';
|
||||
import { DataStorage } from './store/storage';
|
||||
|
||||
// Create DataStorage dependency injection
|
||||
const storageProvider = ReflectiveInjector.resolve([DataStorage]);
|
||||
@@ -127,7 +128,9 @@ const storeConfig = {
|
||||
})
|
||||
}),
|
||||
StoreLogMonitorModule,
|
||||
Select2Module
|
||||
Select2Module,
|
||||
EffectsModule.runAfterBootstrap(KeymapEffects),
|
||||
EffectsModule.runAfterBootstrap(MacroEffects)
|
||||
],
|
||||
providers: [
|
||||
DataProviderService,
|
||||
|
||||
@@ -15,6 +15,7 @@ import { Keymap } from '../../config-serializer/config-items/Keymap';
|
||||
import { Tab } from './tab/tab';
|
||||
|
||||
import { AppState } from '../../store';
|
||||
import { getKeymapEntities } from '../../store/reducers';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
|
||||
enum TabName {
|
||||
@@ -48,7 +49,7 @@ export class PopoverComponent implements OnInit {
|
||||
private keymaps$: Observable<Keymap[]>;
|
||||
|
||||
constructor(private store: Store<AppState>) {
|
||||
this.keymaps$ = store.select((appState: AppState) => appState.keymaps);
|
||||
this.keymaps$ = store.let(getKeymapEntities());
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
|
||||
@@ -4,6 +4,7 @@ import { Keymap } from '../../config-serializer/config-items/Keymap';
|
||||
import { Macro } from '../../config-serializer/config-items/Macro';
|
||||
|
||||
import { AppState } from '../../store';
|
||||
import { getKeymapEntities, getMacroEntities } from '../../store/reducers';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
|
||||
@@ -35,8 +36,8 @@ export class SideMenuComponent {
|
||||
addon: 'active'
|
||||
};
|
||||
|
||||
this.keymaps$ = store.select(appState => appState.keymaps);
|
||||
this.macros$ = store.select(appState => appState.macros);
|
||||
this.keymaps$ = store.let(getKeymapEntities());
|
||||
this.macros$ = store.let(getMacroEntities());
|
||||
}
|
||||
|
||||
toggleHide(event: Event, type: string) {
|
||||
|
||||
2
src/store/effects/index.ts
Normal file
2
src/store/effects/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export * from './keymap';
|
||||
export * from './macro';
|
||||
@@ -1,32 +1,38 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
import { Actions, Effect } from '@ngrx/effects';
|
||||
import { Store } from '@ngrx/store';
|
||||
|
||||
import 'rxjs/add/operator/map';
|
||||
import 'rxjs/add/operator/do';
|
||||
import 'rxjs/add/operator/withLatestFrom';
|
||||
|
||||
import { KeymapActions } from '../actions/keymap';
|
||||
import { KeymapActions } from '../actions';
|
||||
import { AppState } from '../index';
|
||||
|
||||
@Injectable()
|
||||
export class KeymapEffects {
|
||||
|
||||
@Effect()remove$: any = this.actions$
|
||||
@Effect({ dispatch: false })remove$: any = this.actions$
|
||||
.ofType(KeymapActions.REMOVE)
|
||||
.map(() => {
|
||||
// TODO: Waiting for the fix: https://github.com/angular/angular/issues/10770
|
||||
// If state is empty router.navigate(['/keymap']);
|
||||
// Else router.navigate(['/keymap']);
|
||||
.withLatestFrom(this.store)
|
||||
.do((latest) => {
|
||||
let state: AppState = latest[1];
|
||||
|
||||
if (state.keymaps.entities.length === 0) {
|
||||
this.router.navigate(['/keymap/add']);
|
||||
} else {
|
||||
this.router.navigate(['/keymap']);
|
||||
}
|
||||
});
|
||||
|
||||
@Effect() editAbbr$: any = this.actions$
|
||||
@Effect({ dispatch: false }) editAbbr$: any = this.actions$
|
||||
.ofType(KeymapActions.EDIT_ABBR)
|
||||
.map<string>(action => action.payload.abbr)
|
||||
.map((abbr: string) => {
|
||||
console.log(abbr);
|
||||
// TODO: Waiting for the fix: https://github.com/angular/angular/issues/10770
|
||||
// // router.navigate(['/keymap', abbr]);
|
||||
.withLatestFrom(this.store)
|
||||
.do((latest) => {
|
||||
let state: AppState = latest[1];
|
||||
this.router.navigate(['/keymap', state.keymaps.newAbbr]);
|
||||
});
|
||||
|
||||
constructor(
|
||||
private actions$: Actions
|
||||
) {}
|
||||
constructor(private actions$: Actions, private router: Router, private store: Store<AppState>) {}
|
||||
}
|
||||
|
||||
@@ -1,21 +1,30 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
import { Actions, Effect } from '@ngrx/effects';
|
||||
import { Store } from '@ngrx/store';
|
||||
|
||||
import 'rxjs/add/operator/map';
|
||||
import 'rxjs/add/operator/do';
|
||||
import 'rxjs/add/operator/withLatestFrom';
|
||||
|
||||
import { MacroActions } from '../actions';
|
||||
import { AppState } from '../index';
|
||||
|
||||
@Injectable()
|
||||
export class MacroEffects {
|
||||
|
||||
@Effect()remove$: any = this.actions$
|
||||
@Effect({dispatch: false}) remove$: any = this.actions$
|
||||
.ofType(MacroActions.REMOVE)
|
||||
.map(() => {
|
||||
// TODO: Waiting for the fix: https://github.com/angular/angular/issues/10770
|
||||
// If state is empty router.navigate(['/macro']);
|
||||
// Else router.navigate(['/macro']);
|
||||
.withLatestFrom(this.store)
|
||||
.do((latest) => {
|
||||
let state: AppState = latest[1];
|
||||
|
||||
if (state.macros.entities.length === 0) {
|
||||
this.router.navigate(['/macro/add']);
|
||||
} else {
|
||||
this.router.navigate(['/macro']);
|
||||
}
|
||||
});
|
||||
|
||||
constructor(private actions$: Actions) {}
|
||||
constructor(private actions$: Actions, private router: Router, private store: Store<AppState>) {}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,18 @@
|
||||
import { Keymap } from '../config-serializer/config-items/Keymap';
|
||||
import { Macro } from '../config-serializer/config-items/Macro';
|
||||
|
||||
export interface KeymapState {
|
||||
entities: Keymap[];
|
||||
newAbbr?: string;
|
||||
}
|
||||
|
||||
export interface MacroState {
|
||||
entities: Macro[];
|
||||
}
|
||||
|
||||
// State interface for the application
|
||||
export interface AppState {
|
||||
keymaps: Keymap[];
|
||||
macros: Macro[];
|
||||
keymaps: KeymapState;
|
||||
macros: MacroState;
|
||||
presetKeymaps: Keymap[];
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import keymapReducer from './keymap';
|
||||
import macroReducer from './macro';
|
||||
import keymapReducer, { getKeymapEntities } from './keymap';
|
||||
import macroReducer, { getMacroEntities } from './macro';
|
||||
import presetReducer from './preset';
|
||||
|
||||
export { keymapReducer, macroReducer, presetReducer };
|
||||
export { keymapReducer, macroReducer, presetReducer, getKeymapEntities, getMacroEntities };
|
||||
|
||||
@@ -6,56 +6,75 @@ import { Observable } from 'rxjs/Observable';
|
||||
|
||||
import { Keymap } from '../../config-serializer/config-items/Keymap';
|
||||
import { KeymapActions } from '../actions';
|
||||
import { AppState } from '../index';
|
||||
import { AppState, KeymapState } from '../index';
|
||||
|
||||
const initialState: Keymap[] = [];
|
||||
const initialState: KeymapState = {
|
||||
entities: []
|
||||
};
|
||||
|
||||
export default function(state = initialState, action: Action): KeymapState {
|
||||
let newState: Keymap[];
|
||||
|
||||
export default function(state = initialState, action: Action): Keymap[] {
|
||||
switch (action.type) {
|
||||
case KeymapActions.ADD:
|
||||
case KeymapActions.DUPLICATE:
|
||||
|
||||
let newKeymap: Keymap = new Keymap(action.payload);
|
||||
|
||||
newKeymap.abbreviation = generateAbbr(state, newKeymap.abbreviation);
|
||||
newKeymap.name = generateName(state, newKeymap.name);
|
||||
newKeymap.isDefault = false;
|
||||
newKeymap.abbreviation = generateAbbr(state.entities, newKeymap.abbreviation);
|
||||
newKeymap.name = generateName(state.entities, newKeymap.name);
|
||||
newKeymap.isDefault = (state.entities.length === 0);
|
||||
|
||||
return [...state, newKeymap];
|
||||
return {
|
||||
entities: [...state.entities, newKeymap]
|
||||
};
|
||||
|
||||
case KeymapActions.EDIT_NAME:
|
||||
let name: string = generateName(state, action.payload.name);
|
||||
let name: string = generateName(state.entities, action.payload.name);
|
||||
|
||||
return state.map((keymap: Keymap) => {
|
||||
if (keymap.abbreviation === action.payload.abbr) {
|
||||
keymap.name = name;
|
||||
}
|
||||
newState = state.entities.map((keymap: Keymap) => {
|
||||
if (keymap.abbreviation === action.payload.abbr) {
|
||||
keymap.name = name;
|
||||
}
|
||||
|
||||
return keymap;
|
||||
});
|
||||
return keymap;
|
||||
});
|
||||
|
||||
return {
|
||||
entities: newState
|
||||
};
|
||||
|
||||
case KeymapActions.EDIT_ABBR:
|
||||
let abbr: string = generateAbbr(state, action.payload.newAbbr);
|
||||
let abbr: string = generateAbbr(state.entities, action.payload.newAbbr);
|
||||
|
||||
return state.map((keymap: Keymap) => {
|
||||
if (keymap.abbreviation === action.payload.abbr) {
|
||||
keymap.abbreviation = abbr;
|
||||
}
|
||||
newState = state.entities.map((keymap: Keymap) => {
|
||||
if (keymap.abbreviation === action.payload.abbr) {
|
||||
keymap.abbreviation = abbr;
|
||||
}
|
||||
|
||||
return keymap;
|
||||
});
|
||||
return keymap;
|
||||
});
|
||||
|
||||
return {
|
||||
entities: newState,
|
||||
newAbbr: abbr
|
||||
};
|
||||
|
||||
case KeymapActions.SET_DEFAULT:
|
||||
return state.map((keymap: Keymap) => {
|
||||
keymap.isDefault = (keymap.abbreviation === action.payload);
|
||||
newState = state.entities.map((keymap: Keymap) => {
|
||||
keymap.isDefault = (keymap.abbreviation === action.payload);
|
||||
|
||||
return keymap;
|
||||
});
|
||||
return keymap;
|
||||
});
|
||||
|
||||
return {
|
||||
entities: newState
|
||||
};
|
||||
|
||||
case KeymapActions.REMOVE:
|
||||
let isDefault: boolean;
|
||||
|
||||
let filtered: Keymap[] = state.filter((keymap: Keymap) => {
|
||||
let filtered: Keymap[] = state.entities.filter((keymap: Keymap) => {
|
||||
if (keymap.abbreviation === action.payload) {
|
||||
isDefault = keymap.isDefault;
|
||||
return false;
|
||||
@@ -70,12 +89,14 @@ export default function(state = initialState, action: Action): Keymap[] {
|
||||
filtered[0].isDefault = true;
|
||||
}
|
||||
|
||||
return filtered;
|
||||
return {
|
||||
entities: filtered
|
||||
};
|
||||
|
||||
case KeymapActions.SAVE_KEY:
|
||||
let changedKeymap: Keymap = new Keymap;
|
||||
|
||||
return state.map((keymap: Keymap) => {
|
||||
newState = state.entities.map((keymap: Keymap) => {
|
||||
if (keymap.abbreviation === action.payload.abbreviation) {
|
||||
keymap = Object.assign(changedKeymap, action.payload);
|
||||
}
|
||||
@@ -83,19 +104,28 @@ export default function(state = initialState, action: Action): Keymap[] {
|
||||
return keymap;
|
||||
});
|
||||
|
||||
return {
|
||||
entities: newState
|
||||
};
|
||||
|
||||
default: {
|
||||
return state;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function getKeymapEntities(): (state$: Observable<AppState>) => Observable<Keymap[]> {
|
||||
return (state$: Observable<AppState>) => state$
|
||||
.select(state => state.keymaps.entities);
|
||||
}
|
||||
|
||||
export function getKeymap(abbr: string) {
|
||||
if (abbr === undefined) {
|
||||
return getDefault();
|
||||
}
|
||||
|
||||
return (state$: Observable<AppState>) => state$
|
||||
.select(appState => appState.keymaps)
|
||||
.select(appState => appState.keymaps.entities)
|
||||
.map((keymaps: Keymap[]) =>
|
||||
keymaps.find((keymap: Keymap) => keymap.abbreviation === abbr)
|
||||
);
|
||||
@@ -103,7 +133,7 @@ export function getKeymap(abbr: string) {
|
||||
|
||||
export function getDefault() {
|
||||
return (state$: Observable<AppState>) => state$
|
||||
.select(appState => appState.keymaps)
|
||||
.select(appState => appState.keymaps.entities)
|
||||
.map((keymaps: Keymap[]) =>
|
||||
keymaps.find((keymap: Keymap) => keymap.isDefault)
|
||||
);
|
||||
|
||||
@@ -7,26 +7,31 @@ import { Observable } from 'rxjs/Observable';
|
||||
import { Macro } from '../../config-serializer/config-items/Macro';
|
||||
|
||||
import { MacroActions } from '../actions';
|
||||
import { AppState } from '../index';
|
||||
import { AppState, MacroState } from '../index';
|
||||
|
||||
const initialState: Macro[] = [];
|
||||
const initialState: MacroState = {
|
||||
entities: []
|
||||
};
|
||||
|
||||
export default function(state = initialState, action: Action): Macro[] {
|
||||
export default function(state = initialState, action: Action): MacroState {
|
||||
let newMacro: Macro;
|
||||
let newState: Macro[];
|
||||
|
||||
switch (action.type) {
|
||||
case MacroActions.DUPLICATE:
|
||||
|
||||
newMacro = new Macro(action.payload);
|
||||
newMacro.name = generateName(state, newMacro.name);
|
||||
newMacro.id = generateId(state);
|
||||
newMacro.name = generateName(state.entities, newMacro.name);
|
||||
newMacro.id = generateId(state.entities);
|
||||
|
||||
return [...state, newMacro];
|
||||
return {
|
||||
entities: [...state.entities, newMacro]
|
||||
};
|
||||
|
||||
case MacroActions.EDIT_NAME:
|
||||
let name: string = generateName(state, action.payload.name);
|
||||
let name: string = generateName(state.entities, action.payload.name);
|
||||
|
||||
return state.map((macro: Macro) => {
|
||||
newState = state.entities.map((macro: Macro) => {
|
||||
if (macro.id === action.payload.id) {
|
||||
macro.name = name;
|
||||
}
|
||||
@@ -34,11 +39,19 @@ export default function(state = initialState, action: Action): Macro[] {
|
||||
return macro;
|
||||
});
|
||||
|
||||
return {
|
||||
entities: newState
|
||||
};
|
||||
|
||||
case MacroActions.REMOVE:
|
||||
return state.filter((macro: Macro) => macro.id !== action.payload);
|
||||
newState = state.entities.filter((macro: Macro) => macro.id !== action.payload);
|
||||
|
||||
return {
|
||||
entities: newState
|
||||
};
|
||||
|
||||
case MacroActions.ADD_ACTION:
|
||||
return state.map((macro: Macro) => {
|
||||
newState = state.entities.map((macro: Macro) => {
|
||||
if (macro.id === action.payload.id) {
|
||||
newMacro = new Macro(macro);
|
||||
newMacro.macroActions.push(action.payload.action);
|
||||
@@ -49,8 +62,12 @@ export default function(state = initialState, action: Action): Macro[] {
|
||||
return macro;
|
||||
});
|
||||
|
||||
return {
|
||||
entities: newState
|
||||
};
|
||||
|
||||
case MacroActions.SAVE_ACTION:
|
||||
return state.map((macro: Macro) => {
|
||||
newState = state.entities.map((macro: Macro) => {
|
||||
if (macro.id === action.payload.id) {
|
||||
newMacro = new Macro(macro);
|
||||
newMacro.macroActions[action.payload.index] = action.payload.action;
|
||||
@@ -61,8 +78,12 @@ export default function(state = initialState, action: Action): Macro[] {
|
||||
return macro;
|
||||
});
|
||||
|
||||
return {
|
||||
entities: newState
|
||||
};
|
||||
|
||||
case MacroActions.DELETE_ACTION:
|
||||
return state.map((macro: Macro) => {
|
||||
newState = state.entities.map((macro: Macro) => {
|
||||
if (macro.id === action.payload.id) {
|
||||
newMacro = new Macro(macro);
|
||||
newMacro.macroActions.splice(action.payload.index, 1);
|
||||
@@ -73,8 +94,12 @@ export default function(state = initialState, action: Action): Macro[] {
|
||||
return macro;
|
||||
});
|
||||
|
||||
return {
|
||||
entities: newState
|
||||
};
|
||||
|
||||
case MacroActions.REORDER_ACTION:
|
||||
return state.map((macro: Macro) => {
|
||||
newState = state.entities.map((macro: Macro) => {
|
||||
if (macro.id === action.payload.id) {
|
||||
let newIndex: number = action.payload.newIndex;
|
||||
|
||||
@@ -96,16 +121,24 @@ export default function(state = initialState, action: Action): Macro[] {
|
||||
return macro;
|
||||
});
|
||||
|
||||
default: {
|
||||
return {
|
||||
entities: newState
|
||||
};
|
||||
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function getMacroEntities(): (state$: Observable<AppState>) => Observable<Macro[]> {
|
||||
return (state$: Observable<AppState>) => state$
|
||||
.select(state => state.macros.entities);
|
||||
}
|
||||
|
||||
export function getMacro(id: number) {
|
||||
if (isNaN(id)) {
|
||||
return (state$: Observable<AppState>) => state$
|
||||
.select(appState => appState.macros)
|
||||
.select(appState => appState.macros.entities)
|
||||
.map((macros: Macro[]) => {
|
||||
if (macros.length > 0) {
|
||||
return macros[0];
|
||||
@@ -115,7 +148,7 @@ export function getMacro(id: number) {
|
||||
});
|
||||
} else {
|
||||
return (state$: Observable<AppState>) => state$
|
||||
.select(appState => appState.macros)
|
||||
.select(appState => appState.macros.entities)
|
||||
.map((macros: Macro[]) => macros.find((macro: Macro) => macro.id === id));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,8 +32,12 @@ export class Local {
|
||||
}
|
||||
|
||||
return {
|
||||
keymaps: config.keymaps,
|
||||
macros: config.macros,
|
||||
keymaps: {
|
||||
entities: config.keymaps
|
||||
},
|
||||
macros: {
|
||||
entities: config.macros
|
||||
},
|
||||
presetKeymaps: presetAll
|
||||
};
|
||||
}
|
||||
@@ -44,17 +48,29 @@ export class Local {
|
||||
let config: UhkConfiguration;
|
||||
|
||||
// Save elements to the UhkConfiguration
|
||||
if (action.type.startsWith(KeymapActions.PREFIX) && state.length && state[0] instanceof Keymap) {
|
||||
if (
|
||||
action.type.startsWith(KeymapActions.PREFIX) &&
|
||||
(
|
||||
(nextState.entities && nextState.entities.length && nextState.entities[0] instanceof Keymap) ||
|
||||
(state.entities && state.entities.length && state.entities[0] instanceof Keymap)
|
||||
)
|
||||
) {
|
||||
config = new UhkConfiguration().fromJsObject(
|
||||
JSON.parse(localStorage.getItem('config'))
|
||||
);
|
||||
config.keymaps = Object.values(nextState);
|
||||
config.keymaps = Object.values(nextState.entities);
|
||||
localStorage.setItem('config', JSON.stringify(config.toJsObject()));
|
||||
} else if (action.type.startsWith(MacroActions.PREFIX) && state.length && state[0] instanceof Macro) {
|
||||
} else if (
|
||||
action.type.startsWith(MacroActions.PREFIX) &&
|
||||
(
|
||||
(nextState.entities && nextState.entities.length && nextState.entities[0] instanceof Macro) ||
|
||||
(state.entities && state.entities.length && state.entities[0] instanceof Macro)
|
||||
)
|
||||
) {
|
||||
config = new UhkConfiguration().fromJsObject(
|
||||
JSON.parse(localStorage.getItem('config'))
|
||||
);
|
||||
config.macros = Object.values(nextState);
|
||||
config.macros = Object.values(nextState.entities);
|
||||
localStorage.setItem('config', JSON.stringify(config.toJsObject()));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user