Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
15 changes: 15 additions & 0 deletions src/core/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import components from '../components';
import * as reducer from '../reducers/dataReducer';
import * as selectors from '../selectors/dataSelectors';
import * as actions from '../actions';
import initialState from './initialState';

const CorePlugin = {
components,
reducer,
selectors,
actions,
...initialState,
};

export default CorePlugin;
45 changes: 45 additions & 0 deletions src/core/initialState.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
const styleConfig = {
icons: {
TableHeadingCell: {
sortDescendingIcon: '▼',
sortAscendingIcon: '▲'
},
},
classNames: {
Cell: 'griddle-cell',
Filter: 'griddle-filter',
Loading: 'griddle-loadingResults',
NextButton: 'griddle-next-button',
NoResults: 'griddle-noResults',
PageDropdown: 'griddle-page-select',
Pagination: 'griddle-pagination',
PreviousButton: 'griddle-previous-button',
Row: 'griddle-row',
RowDefinition: 'griddle-row-definition',
Settings: 'griddle-settings',
SettingsToggle: 'griddle-settings-toggle',
Table: 'griddle-table',
TableBody: 'griddle-table-body',
TableHeading: 'griddle-table-heading',
TableHeadingCell: 'griddle-table-heading-cell',
TableHeadingCellAscending: 'griddle-heading-ascending',
TableHeadingCellDescending: 'griddle-heading-descending',
},
styles: {
}
};

export default {
styleConfig,

pageProperties: {
currentPage: 1,
pageSize: 10
},
enableSettings: true,
textProperties: {
next: 'Next',
previous: 'Previous',
settingsToggle: 'Settings'
},
};
123 changes: 9 additions & 114 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,60 +1,14 @@
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';
import _ from 'lodash';

import * as dataReducers from './reducers/dataReducer';
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 corePlugin from './core';
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: {
sortDescendingIcon: '▼',
sortAscendingIcon: '▲'
},
},
classNames: {
Cell: 'griddle-cell',
Filter: 'griddle-filter',
Loading: 'griddle-loadingResults',
NextButton: 'griddle-next-button',
NoResults: 'griddle-noResults',
PageDropdown: 'griddle-page-select',
Pagination: 'griddle-pagination',
PreviousButton: 'griddle-previous-button',
Row: 'griddle-row',
RowDefinition: 'griddle-row-definition',
Settings: 'griddle-settings',
SettingsToggle: 'griddle-settings-toggle',
Table: 'griddle-table',
TableBody: 'griddle-table-body',
TableHeading: 'griddle-table-heading',
TableHeadingCell: 'griddle-table-heading-cell',
TableHeadingCellAscending: 'griddle-heading-ascending',
TableHeadingCellDescending: 'griddle-heading-descending',
},
styles: {
}
};

class Griddle extends Component {
static childContextTypes = {
components: PropTypes.object.isRequired,
Expand All @@ -69,86 +23,23 @@ class Griddle extends Component {
super(props);

const {
plugins=[],
data,
children:rowPropertiesComponent,
events={},
sortProperties={},
styleConfig={},
pageProperties:importedPageProperties,
components:userComponents,
renderProperties:userRenderProperties={},
settingsComponentObjects:userSettingsComponentObjects,
core = corePlugin,
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));

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

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

const pageProperties = Object.assign({}, {
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'
},
},
...plugins.map(p => p.initialState),
userInitialState,
{
data,
pageProperties,
renderProperties,
sortProperties,
styleConfig: mergedStyleConfig,
}
);
const { initialState, reducers, reduxMiddleware } = init.call(this, core);

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 Expand Up @@ -188,6 +79,10 @@ class Griddle extends Component {
}

render() {
if (!this.components.Layout) {
return null;
}

return (
<this.provider store={this.store}>
<this.components.Layout />
Expand Down
7 changes: 5 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 @@ -399,10 +401,9 @@ export interface GriddlePlugin extends GriddleExtensibility {
}

export interface GriddleProps<T> extends GriddlePlugin, GriddleInitialState {
core?: GriddlePlugin;
plugins?: GriddlePlugin[];
data?: T[];
sortProperties?: GriddleSortKey[];
pageProperties?: GriddlePageProperties;
storeKey?: string;
}

Expand Down Expand Up @@ -441,6 +442,8 @@ export namespace utils {
}

export namespace plugins {
var CorePlugin : GriddlePlugin;

var LegacyStylePlugin : GriddlePlugin;

var LocalPlugin : GriddlePlugin;
Expand Down
2 changes: 2 additions & 0 deletions src/module.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@ import * as selectors from './selectors/dataSelectors';
import settingsComponentObjects from './settingsComponentObjects';
import utils from './utils';

import CorePlugin from './core';
import LegacyStylePlugin from './plugins/legacyStyle';
import LocalPlugin from './plugins/local';
import PositionPlugin from './plugins/position';

const plugins = {
CorePlugin,
LegacyStylePlugin,
LocalPlugin,
PositionPlugin,
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