summaryrefslogtreecommitdiffstats
path: root/packages/gitbook-plugin-search/src/actions/search.js
diff options
context:
space:
mode:
Diffstat (limited to 'packages/gitbook-plugin-search/src/actions/search.js')
-rw-r--r--packages/gitbook-plugin-search/src/actions/search.js121
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
+};