Skip to content

Commit

Permalink
Merge pull request #7 from ritz078/feat/fuzzy-search
Browse files Browse the repository at this point in the history
Added fuzzy search
  • Loading branch information
arunoda authored Jun 27, 2016
2 parents a2369a0 + 28487b6 commit 4340c80
Show file tree
Hide file tree
Showing 8 changed files with 142 additions and 5 deletions.
7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,16 +46,17 @@
},
"dependencies": {
"@kadira/react-split-pane": "^1.4.0",
"redux": "^3.5.2",
"mantra-core": "^1.6.1",
"babel-runtime": "^6.5.0",
"deep-equal": "^1.0.1",
"fuzzysearch": "^1.0.3",
"json-stringify-safe": "^5.0.1",
"keycode": "^2.1.1",
"lodash.pick": "^4.2.1",
"mantra-core": "^1.6.1",
"qs": "^6.2.0",
"react-modal": "^1.2.1"
"react-fuzzy": "^0.2.2",
"react-modal": "^1.2.1",
"redux": "^3.5.2"
},
"main": "dist/index.js",
"engines": {
Expand Down
4 changes: 4 additions & 0 deletions src/libs/key_events.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export const features = {
ESCAPE: 5,
NEXT_STORY: 6,
PREV_STORY: 7,
SEARCH: 8,
};

export function isModifierPressed(e) {
Expand Down Expand Up @@ -39,6 +40,9 @@ export default function handle(e) {
case keycode('left'):
e.preventDefault();
return features.PREV_STORY;
case keycode('P'):
e.preventDefault();
return features.SEARCH;
default:
return false;
}
Expand Down
3 changes: 3 additions & 0 deletions src/modules/shortcuts/configs/reducers/shortcuts.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const defaultState = {
goFullScreen: false,
showLeftPanel: true,
showDownPanel: true,
showSearchBox: false,
};

export function keyEventToState(state, event) {
Expand All @@ -15,6 +16,8 @@ export function keyEventToState(state, event) {
return { showDownPanel: !state.showDownPanel };
case features.LEFT_PANEL:
return { showLeftPanel: !state.showLeftPanel };
case features.SEARCH:
return { showSearchBox: !state.showSearchBox };
default:
return {};
}
Expand Down
99 changes: 99 additions & 0 deletions src/modules/ui/components/search_box.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import React from 'react';
import FuzzySearch from 'react-fuzzy';

import { features } from '../../../libs/key_events';
import { baseFonts } from './theme';

const searchBoxStyle = {
position: 'absolute',
backgroundColor: '#FFF',
top: '100px',
left: '50%',
marginLeft: '-215px',
...baseFonts
};

const formatStories = function (stories) {
const formattedStories = [];
let i = 0;
stories.forEach((val) => {
formattedStories.push({
type: 'kind',
value: val.kind,
id: i++,
});

val.stories.forEach((story) => {
formattedStories.push({
type: 'story',
value: story,
id: i++,
kind: val.kind,
});
});
});

return formattedStories;
};

const suggestionTemplate = function (props, state, styles) {
return state.results.map((val, i) => {
const style = state.selectedIndex === i ? styles.selectedResultStyle : styles.resultsStyle;
return (
<div key={i} style={style}>
{val.value}
<span style={{ float: 'right', opacity: 0.5 }}>
{val.type === 'story' ? `in ${val.kind}` : 'Kind'}
</span>
</div>
);
});
};

export default class SearchBox extends React.Component {
constructor(props) {
super(props);

this.onSelect = this.onSelect.bind(this);
this.fireOnStory = this.fireOnStory.bind(this);
this.fireOnKind = this.fireOnKind.bind(this);
}

onSelect(selected) {
const { handleEvent } = this.props;
if (selected.type === 'story') this.fireOnStory(selected.value, selected.kind);
else this.fireOnKind(selected.value);
handleEvent(features.SEARCH);
}

fireOnKind(kind) {
const { onSelectStory } = this.props;
if (onSelectStory) onSelectStory(kind, null);
}

fireOnStory(story, kind) {
const { onSelectStory } = this.props;
if (onSelectStory) onSelectStory(kind, story);
}

render() {
return (
<div style={searchBoxStyle}>
{this.props.showSearchBox && <FuzzySearch
list={formatStories(this.props.stories)}
onSelect={this.onSelect}
keys={['value', 'type']}
resultsTemplate={suggestionTemplate}
autoFocus
/>}
</div>
);
}
}

SearchBox.propTypes = {
showSearchBox: React.PropTypes.bool.isRequired,
stories: React.PropTypes.arrayOf(React.PropTypes.object).isRequired,
onSelectStory: React.PropTypes.func.isRequired,
handleEvent: React.PropTypes.func.isRequired,
};
5 changes: 5 additions & 0 deletions src/modules/ui/components/shortcuts_help.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ const modalStyles = {
export const Content = () => (
<div>
<h4 style={h4Style}>Keyboard Shortcuts</h4>
<div>
<b style={commandStyle}>&#8984; &#8679; P</b> / &nbsp;
<b style={commandStyle}>&#8963; &#8679; P</b>
Toggle SearchBox
</div>
<div>
<b style={commandStyle}>&#8984; &#8679; F</b> / &nbsp;
<b style={commandStyle}>&#8963; &#8679; F</b>
Expand Down
8 changes: 6 additions & 2 deletions src/modules/ui/containers/layout.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,12 @@ import pick from 'lodash.pick';
import reduxComposer from '../libs/redux_composer';

export const composer = ({ shortcuts }) => {
const data = pick(shortcuts, 'showLeftPanel', 'showDownPanel', 'goFullScreen');
return data;
return pick(
shortcuts,
'showLeftPanel',
'showDownPanel',
'goFullScreen'
);
};

export default composeAll(
Expand Down
18 changes: 18 additions & 0 deletions src/modules/ui/containers/search_box.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import SearchBox from '../components/search_box';
import { useDeps, composeAll } from 'mantra-core';
import reduxComposer from '../libs/redux_composer';

export const composer = ({ api, shortcuts }, { actions }) => {
const actionMap = actions();
return {
showSearchBox: shortcuts.showSearchBox,
stories: api.stories,
onSelectStory: actionMap.api.selectStory,
handleEvent: actionMap.shortcuts.handleEvent,
};
};

export default composeAll(
reduxComposer(composer),
useDeps()
)(SearchBox);
3 changes: 3 additions & 0 deletions src/modules/ui/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ import Layout from './containers/layout';
import LeftPanel from './containers/left_panel';
import ActionLogger from './containers/action_logger';
import ShortcutsHelp from './containers/shortcuts_help';
import SearchBox from './containers/search_box';

export default function (injectDeps, { reduxStore, provider, domNode }) {
const InjectedLayout = injectDeps(Layout);
const InjectedShortcutsHelp = injectDeps(ShortcutsHelp);
const InjectedSearchBox = injectDeps(SearchBox);

// generate preview
const Preview = () => {
Expand All @@ -25,6 +27,7 @@ export default function (injectDeps, { reduxStore, provider, domNode }) {
downPanel={() => (<ActionLogger />)}
/>
<InjectedShortcutsHelp />
<InjectedSearchBox />
</div>
);
ReactDOM.render(root, domNode);
Expand Down

0 comments on commit 4340c80

Please sign in to comment.