diff options
Diffstat (limited to 'packages/gitbook-plugin-search/src/actions/search.js')
-rw-r--r-- | packages/gitbook-plugin-search/src/actions/search.js | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/packages/gitbook-plugin-search/src/actions/search.js b/packages/gitbook-plugin-search/src/actions/search.js new file mode 100644 index 0000000..24151c6 --- /dev/null +++ b/packages/gitbook-plugin-search/src/actions/search.js @@ -0,0 +1,121 @@ +const { Promise, Immutable } = require('gitbook-core'); +const { List } = Immutable; + +const TYPES = require('./types'); +const Result = require('../models/Result'); + +/* + Search workflow: + + 1. Typing in the search input + 2. Trigger an update of the url + 3. An update of the url, trigger an update of search results + */ + +/** + * Start a search query + * @param {String} q + * @return {Action} + */ +function query(q) { + return (dispatch, getState, { History }) => { + const searchState = getState().search; + const currentQuery = searchState.query; + + const queryString = q ? { q } : {}; + + if (currentQuery && q) { + dispatch(History.replace({ query: queryString })); + } else { + dispatch(History.push({ query: queryString })); + } + }; +} + +/** + * Update results for a query + * @param {String} q + * @return {Action} + */ +function handleQuery(q) { + if (!q) { + return clear(); + } + + return (dispatch, getState, actions) => { + const { handlers } = getState().search; + + dispatch({ type: TYPES.START, query: q }); + + return Promise.reduce( + handlers.toArray(), + (results, handler) => { + return Promise.resolve(handler(q, dispatch, getState, actions)) + .then(handlerResults => { + return handlerResults.map(result => new Result(result)); + }) + .then(handlerResults => results.concat(handlerResults)); + }, + List() + ) + .then( + results => { + dispatch({ type: TYPES.END, query: q, results }); + } + ); + }; +} + +/** + * Refresh current search (when handlers have changed) + * @return {Action} + */ +function refresh() { + return (dispatch, getState) => { + const q = getState().search.query; + if (q) { + dispatch(handleQuery(q)); + } + }; +} + +/** + * Clear the whole search + * @return {Action} + */ +function clear() { + return { type: TYPES.CLEAR }; +} + +/** + * Register a search handler + * @param {String} name + * @param {Function} handler + * @return {Action} + */ +function registerHandler(name, handler) { + return (dispatch) => { + dispatch({ type: TYPES.REGISTER_HANDLER, name, handler }); + dispatch(refresh()); + }; +} + +/** + * Unregister a search handler + * @param {String} name + * @return {Action} + */ +function unregisterHandler(name) { + return (dispatch) => { + dispatch({ type: TYPES.UNREGISTER_HANDLER, name }); + dispatch(refresh()); + }; +} + +module.exports = { + clear, + query, + handleQuery, + registerHandler, + unregisterHandler +}; |