Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extract Initializer #757

Merged
merged 27 commits into from
Nov 16, 2017
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
73db68b
Enable Storybook source-map
dahlbyk Sep 23, 2017
82bde75
Extract initializer util from Griddle constructor
dahlbyk Sep 23, 2017
0d83e0c
Add basic initializer tests
dahlbyk Sep 24, 2017
75bcb8d
Fix reducer composition for tests
dahlbyk Sep 24, 2017
a2a53eb
Attach individual reducers to Griddle reducer to help debugging/testing
dahlbyk Sep 24, 2017
df08a82
Test initialState.data
dahlbyk Sep 24, 2017
e48f427
Test initialState.renderProperties
dahlbyk Sep 24, 2017
b8e45b9
Test initialState.pageProperties
dahlbyk Sep 24, 2017
9704acf
Test initialState.sortProperties
dahlbyk Sep 24, 2017
4c15ac7
Test initialState.styleConfig
dahlbyk Sep 24, 2017
c4c6728
Test extra initialState props
dahlbyk Sep 24, 2017
24f27cc
Avoid initialState key in init defaults
dahlbyk Sep 24, 2017
5acfc42
Avoid special treatment for pageProperties
dahlbyk Sep 24, 2017
5e6b457
Avoid special treatment for sortProperties
dahlbyk Sep 25, 2017
8bff341
Test initializer reducers
dahlbyk Sep 25, 2017
9eec496
Test initializer reduxMiddleware
dahlbyk Sep 25, 2017
bc60559
Guard against invalid props-specified reduxMiddleware
dahlbyk Sep 25, 2017
1c0e5b2
Test initializer components
dahlbyk Sep 25, 2017
cee63fb
Test initializer settingsComponentObjects
dahlbyk Sep 25, 2017
0576fbb
Test initializer events (bugs?!)
dahlbyk Sep 25, 2017
3811319
Test initializer selectors
dahlbyk Sep 25, 2017
764a47e
Remove unused defaultEvents
dahlbyk Oct 19, 2017
5f1e8ed
Test initializer listeners
dahlbyk Oct 19, 2017
227e35b
Fix deferred load setState warning
dahlbyk Oct 19, 2017
3577f8f
Extract core plugin-ish
dahlbyk Oct 20, 2017
1ddd84f
Handle null core
dahlbyk Oct 20, 2017
d2931e9
Export CorePlugin; add to types
dahlbyk Oct 20, 2017
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
1 change: 1 addition & 0 deletions .storybook/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const include = path.resolve(__dirname, '../');
// to "React Create App". This only has babel loader to load JavaScript.

module.exports = {
devtool: 'source-map',
entry: './stories/index.tsx',
output: {
filename: include + '/dist/examples/storybook.js'
Expand Down
88 changes: 15 additions & 73 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { createStore, combineReducers, bindActionCreators, applyMiddleware, compose } from 'redux';
import Immutable from 'immutable';
import { createProvider } from 'react-redux';
import React, { Component } from 'react';
import PropTypes from 'prop-types';
Expand All @@ -10,20 +9,10 @@ import components from './components';
import settingsComponentObjects from './settingsComponentObjects';
import * as selectors from './selectors/dataSelectors';

import { buildGriddleReducer, buildGriddleComponents } from './utils/compositionUtils';
import { getColumnProperties } from './utils/columnUtils';
import { getRowProperties } from './utils/rowUtils';
import { setSortProperties } from './utils/sortUtils';
import init from './utils/initializer';
import { StoreListener } from './utils/listenerUtils';
import * as actions from './actions';

const defaultEvents = {
...actions,
onFilter: actions.setFilter,
setSortProperties
};


const defaultStyleConfig = {
icons: {
TableHeadingCell: {
Expand Down Expand Up @@ -69,86 +58,39 @@ class Griddle extends Component {
super(props);

const {
plugins=[],
data,
children:rowPropertiesComponent,
events={},
sortProperties={},
styleConfig={},
pageProperties:importedPageProperties,
components:userComponents,
renderProperties:userRenderProperties={},
settingsComponentObjects:userSettingsComponentObjects,
storeKey = Griddle.storeKey || 'store',
reduxMiddleware = [],
listeners = {},
...userInitialState
} = props;

const rowProperties = getRowProperties(rowPropertiesComponent);
const columnProperties = getColumnProperties(rowPropertiesComponent);

//Combine / compose the reducers to make a single, unified reducer
const reducers = buildGriddleReducer([dataReducers, ...plugins.map(p => p.reducer)]);

//Combine / Compose the components to make a single component for each component type
this.components = buildGriddleComponents([components, ...plugins.map(p => p.components), userComponents]);

this.settingsComponentObjects = Object.assign({}, settingsComponentObjects, ...plugins.map(p => p.settingsComponentObjects), userSettingsComponentObjects);

this.events = Object.assign({}, events, ...plugins.map(p => p.events));
const { initialState, reducers, reduxMiddleware } = init.call(this, {
reducers: dataReducers,
components,
settingsComponentObjects,
selectors,
styleConfig: defaultStyleConfig,

this.selectors = plugins.reduce((combined, plugin) => ({ ...combined, ...plugin.selectors }), {...selectors});

const mergedStyleConfig = _.merge({}, defaultStyleConfig, ...plugins.map(p => p.styleConfig), styleConfig);

const pageProperties = Object.assign({}, {
pageProperties: {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like the pageProperties and sortProperties properties were removed. Can this be re-added?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I could/can tell, there's actually nothing special about pageProperties and sortProperties relative to any other "extra" properties that are treated as initialState: note tests don't change in d69275a and 0cbc7d8.

currentPage: 1,
pageSize: 10
},
importedPageProperties,
);

//TODO: This should also look at the default and plugin initial state objects
const renderProperties = Object.assign({
rowProperties,
columnProperties
}, ...plugins.map(p => p.renderProperties), userRenderProperties);

// TODO: Make this its own method
const initialState = _.merge(
{
enableSettings: true,
textProperties: {
next: 'Next',
previous: 'Previous',
settingsToggle: 'Settings'
},
enableSettings: true,
textProperties: {
next: 'Next',
previous: 'Previous',
settingsToggle: 'Settings'
},
...plugins.map(p => p.initialState),
userInitialState,
{
data,
pageProperties,
renderProperties,
sortProperties,
styleConfig: mergedStyleConfig,
}
);
});

const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose
this.store = createStore(
reducers,
initialState,
composeEnhancers(
applyMiddleware(..._.compact(_.flatten(plugins.map(p => p.reduxMiddleware))), ...reduxMiddleware)
applyMiddleware(...reduxMiddleware)
)
);

this.provider = createProvider(storeKey);

const sanitizedListeners = _.pickBy(listeners, (value, key) => typeof value === "function");
this.listeners = plugins.reduce((combined, plugin) => ({...combined, ..._.pickBy(plugin.listeners, (value, key) => typeof value === "function")}), {...sanitizedListeners});
this.storeListener = new StoreListener(this.store);
_.forIn(this.listeners, (listener, name) => {
this.storeListener.addListener(listener, name, {events: this.events, selectors: this.selectors});
Expand Down
4 changes: 2 additions & 2 deletions src/module.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,9 @@ interface GriddleExtensibility {

interface GriddleInitialState {
enableSettings?: boolean;
pageProperties?: GriddlePageProperties;
sortMethod?: (data: any[], column: string, sortAscending?: boolean) => number;
sortProperties?: GriddleSortKey[];
textProperties?: {
next?: string,
previous?: string,
Expand All @@ -401,8 +403,6 @@ export interface GriddlePlugin extends GriddleExtensibility {
export interface GriddleProps<T> extends GriddlePlugin, GriddleInitialState {
plugins?: GriddlePlugin[];
data?: T[];
sortProperties?: GriddleSortKey[];
pageProperties?: GriddlePageProperties;
storeKey?: string;
}

Expand Down
20 changes: 18 additions & 2 deletions src/utils/__tests__/compositionUtilsTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import {
removeHooksFromObject,
isKeyGriddleHook,
buildGriddleReducer,
buildGriddleReducerObject,
getAfterHooksFromObject,
getBeforeHooksFromObject,
removeKeyNamePartFromObject,
Expand Down Expand Up @@ -326,7 +325,7 @@ test('builds griddle reducer', test => {
}
}

const griddleReducer = buildGriddleReducerObject([reducer1, reducer2, reducer3]);
const griddleReducer = buildGriddleReducer([reducer1, reducer2, reducer3]);

test.deepEqual(Object.keys(griddleReducer), ['REDUCE_THING', 'REDUCE_OTHER']);
test.deepEqual(griddleReducer.REDUCE_THING({ number: 5}), { number: -45 });
Expand Down Expand Up @@ -357,6 +356,7 @@ test('builds griddle reducer with BEFORE_REDUCE and AFTER_REDUCE', (t) => {
const griddleReducer = buildGriddleReducer([reducer1, reducer2]);
const output = griddleReducer({number: 5}, { type: 'REDUCE_THING'});

t.deepEqual(Object.keys(griddleReducer), ['AFTER_REDUCE', 'REDUCE_THING', 'BEFORE_REDUCE']);
t.deepEqual(output, { number: 55 });
});

Expand All @@ -376,9 +376,25 @@ test('builds griddle reducer without BEFORE / AFTER if they dont exist', (t) =>
const griddleReducer = buildGriddleReducer([reducer1, reducer2]);
const output = griddleReducer({number: 5}, { type: 'REDUCE_THING'});

t.deepEqual(Object.keys(griddleReducer), ['REDUCE_THING']);
t.deepEqual(output, { number: 15 });
});

test('builds griddle reducer that calls GRIDDLE_INITIALIZED for missing action type, if it exists', (assert) => {
const initReducer = { GRIDDLE_INITIALIZED: () => ({ init: true }) };
const griddleReducer = buildGriddleReducer([initReducer]);
const output = griddleReducer({}, { type: 'MISSING' });

assert.deepEqual(output, { init: true });
});

test('builds griddle reducer that does noop for missing action type, if GRIDDLE_INITIALIZED is also missing', (assert) => {
const griddleReducer = buildGriddleReducer([]);
const output = griddleReducer({}, { type: 'MISSING' });

assert.deepEqual(output, {});
});

test('combineAndEnhanceComponents', test => {
const initial = { one: (someNumber) => (someNumber + 5)}
const enhancing = { oneEnhancer: originalMethod => (someNumber) => originalMethod(someNumber * 5)};
Expand Down
Loading