From 1fd94e79020eb47068bbeea447d1733bd109886d Mon Sep 17 00:00:00 2001 From: 6ea86b96 <6ea86b96@gmail.com> Date: Mon, 24 Apr 2017 21:17:36 +0700 Subject: [PATCH] Working on search --- ui/js/actions/content.js | 5 ++- ui/js/actions/search.js | 28 +++++++++++++ ui/js/component/header/index.js | 4 ++ ui/js/constants/action_types.js | 4 ++ ui/js/page/discover/index.js | 11 ++++++ ui/js/page/discover/view.jsx | 4 +- ui/js/page/showPage/view.jsx | 69 ++++++++++++++++++--------------- ui/js/reducers/search.js | 36 +++++++++++++++++ ui/js/selectors/search.js | 29 ++++++++++++++ ui/js/store.js | 2 + 10 files changed, 158 insertions(+), 34 deletions(-) create mode 100644 ui/js/actions/search.js create mode 100644 ui/js/reducers/search.js create mode 100644 ui/js/selectors/search.js diff --git a/ui/js/actions/content.js b/ui/js/actions/content.js index 20d1e8423..d29b40003 100644 --- a/ui/js/actions/content.js +++ b/ui/js/actions/content.js @@ -1,9 +1,12 @@ import * as types from 'constants/action_types' import lbry from 'lbry' -import lbryio from 'lbryio'; +import lbryio from 'lbryio' import { selectCurrentUri, } from 'selectors/app' +import { + selectSearchTerm, +} from 'selectors/content' import { selectCurrentResolvedUriClaimOutpoint, } from 'selectors/content' diff --git a/ui/js/actions/search.js b/ui/js/actions/search.js new file mode 100644 index 000000000..e88515bcf --- /dev/null +++ b/ui/js/actions/search.js @@ -0,0 +1,28 @@ +import * as types from 'constants/action_types' +import lbry from 'lbry' +import lbryio from 'lbryio' +import lighthouse from 'lighthouse' +import { + selectSearchQuery, +} from 'selectors/search' + +export function doSearchContent(query) { + return function(dispatch, getState) { + const state = getState() + + dispatch({ + type: types.SEARCH_STARTED, + data: { query } + }) + + lighthouse.search(query).then(results => { + dispatch({ + type: types.SEARCH_COMPLETED, + data: { + query, + results, + } + }) + }) + } +} diff --git a/ui/js/component/header/index.js b/ui/js/component/header/index.js index 3b9cb57ef..90b9293f6 100644 --- a/ui/js/component/header/index.js +++ b/ui/js/component/header/index.js @@ -9,6 +9,9 @@ import { import { doNavigate, } from 'actions/app' +import { + doSearchContent, +} from 'actions/search' import Header from './view' const select = (state) => ({ @@ -18,6 +21,7 @@ const select = (state) => ({ const perform = (dispatch) => ({ navigate: (path) => dispatch(doNavigate(path)), + search: (query) => dispatch(doSearchContent(query)), }) export default connect(select, perform)(Header) diff --git a/ui/js/constants/action_types.js b/ui/js/constants/action_types.js index 869208b4d..85347e43a 100644 --- a/ui/js/constants/action_types.js +++ b/ui/js/constants/action_types.js @@ -47,3 +47,7 @@ export const FETCH_FILE_INFO_STARTED = 'FETCH_FILE_INFO_STARTED' export const FETCH_FILE_INFO_COMPLETED = 'FETCH_FILE_INFO_COMPLETED' export const FETCH_COST_INFO_STARTED = 'FETCH_COST_INFO_STARTED' export const FETCH_COST_INFO_COMPLETED = 'FETCH_COST_INFO_COMPLETED' + +// Search +export const SEARCH_STARTED = 'SEARCH_STARTED' +export const SEARCH_COMPLETED = 'SEARCH_COMPLETED' diff --git a/ui/js/page/discover/index.js b/ui/js/page/discover/index.js index cdea28f62..e279ff4d6 100644 --- a/ui/js/page/discover/index.js +++ b/ui/js/page/discover/index.js @@ -5,10 +5,21 @@ import { import { selectFeaturedContentByCategory } from 'selectors/content' +import { + doSearchContent, +} from 'actions/search' +import { + selectIsSearching, + selectSearchQuery, + selectCurrentSearchResults, +} from 'selectors/search' import DiscoverPage from './view' const select = (state) => ({ featuredContentByCategory: selectFeaturedContentByCategory(state), + isSearching: selectIsSearching(state), + query: selectSearchQuery(state), + results: selectCurrentSearchResults(state), }) const perform = (dispatch) => ({ diff --git a/ui/js/page/discover/view.jsx b/ui/js/page/discover/view.jsx index f9edc00dd..fc0eb8220 100644 --- a/ui/js/page/discover/view.jsx +++ b/ui/js/page/discover/view.jsx @@ -14,7 +14,7 @@ const FeaturedCategory = (props) => { resolvedUris, names, } = props - + return

{category} {category && category.match(/^community/i) && } @@ -60,6 +60,6 @@ let DiscoverPage = React.createClass({

}; } -}); +}) export default DiscoverPage; diff --git a/ui/js/page/showPage/view.jsx b/ui/js/page/showPage/view.jsx index 4905738a6..55c88d5ed 100644 --- a/ui/js/page/showPage/view.jsx +++ b/ui/js/page/showPage/view.jsx @@ -2,7 +2,7 @@ import React from 'react'; import lbry from 'lbry.js'; import lighthouse from 'lighthouse.js'; import lbryuri from 'lbryuri.js'; -import {Video} from 'page/watch.js' +import Video from 'page/video' import { TruncatedText, Thumbnail, @@ -13,37 +13,44 @@ import {FileActions} from 'component/file-actions.js'; import Link from 'component/link'; import UriIndicator from 'component/channel-indicator.js'; -var FormatItem = React.createClass({ - propTypes: { - metadata: React.PropTypes.object, - contentType: React.PropTypes.string, - uri: React.PropTypes.string, - outpoint: React.PropTypes.string, - }, - render: function() { - const {thumbnail, author, title, description, language, license} = this.props.metadata; - const mediaType = lbry.getMediaType(this.props.contentType); +const FormatItem = (props) => { + const { + contentType, + metadata, + cost, + uri, + outpoint, + costIncludesData, + } = props + const { + thumbnail, + author, + title, + description, + language, + license + } = metadata; + const mediaType = lbry.getMediaType(contentType); - return ( - - - - - - - - - - - - - - - -
Content-Type{this.props.contentType}
Author{author}
Language{language}
License{license}
- ); - } -}); + return ( + + + + + + + + + + + + + + + +
Content-Type{contentType}
Author{author}
Language{language}
License{license}
+ ) +} let ChannelPage = React.createClass({ render: function() { diff --git a/ui/js/reducers/search.js b/ui/js/reducers/search.js new file mode 100644 index 000000000..cabb98b61 --- /dev/null +++ b/ui/js/reducers/search.js @@ -0,0 +1,36 @@ +import * as types from 'constants/action_types' + +const reducers = {} +const defaultState = { +} + +reducers[types.SEARCH_STARTED] = function(state, action) { + const { + query, + } = action.data + + return Object.assign({}, state, { + searching: true, + query: query, + }) +} + +reducers[types.SEARCH_COMPLETED] = function(state, action) { + const { + query, + } = action.data + const newResults = Object.assign({}, state.results) + const newByQuery = Object.assign({}, newResults.byQuery) + newByQuery[query] = action.data.results + + return Object.assign({}, state, { + searching: false, + results: newResults, + }) +} + +export default function reducer(state = defaultState, action) { + const handler = reducers[action.type]; + if (handler) return handler(state, action); + return state; +} diff --git a/ui/js/selectors/search.js b/ui/js/selectors/search.js new file mode 100644 index 000000000..240a4b6bc --- /dev/null +++ b/ui/js/selectors/search.js @@ -0,0 +1,29 @@ +import { createSelector } from 'reselect' + +export const _selectState = state => state.search || {} + +export const selectSearchQuery = createSelector( + _selectState, + (state) => state.query +) + +export const selectIsSearching = createSelector( + _selectState, + (state) => !!state.searching +) + +export const selectSearchResults = createSelector( + _selectState, + (state) => state.results || {} +) + +export const selectSearchResultsByQuery = createSelector( + selectSearchResults, + (results) => results.byQuery || {} +) + +export const selectCurrentSearchResults = createSelector( + selectSearchQuery, + selectSearchResultsByQuery, + (query, byQuery) => byQuery[query] || [] +) diff --git a/ui/js/store.js b/ui/js/store.js index 2aeef6730..ac789a824 100644 --- a/ui/js/store.js +++ b/ui/js/store.js @@ -8,6 +8,7 @@ import { import appReducer from 'reducers/app'; import contentReducer from 'reducers/content'; import rewardsReducer from 'reducers/rewards' +import searchReducer from 'reducers/search' import walletReducer from 'reducers/wallet' function isFunction(object) { @@ -22,6 +23,7 @@ const reducers = redux.combineReducers({ app: appReducer, content: contentReducer, rewards: rewardsReducer, + search: searchReducer, wallet: walletReducer, });