2016-04-18 16:51:45 -04:00
|
|
|
var injectIntl = require('react-intl').injectIntl;
|
|
|
|
var FormattedMessage = require('react-intl').FormattedMessage;
|
|
|
|
var React = require('react');
|
2016-10-31 10:19:35 -04:00
|
|
|
var connect = require('react-redux').connect;
|
2016-04-18 16:51:45 -04:00
|
|
|
var render = require('../../lib/render.jsx');
|
|
|
|
|
2016-06-14 17:33:54 -04:00
|
|
|
var api = require('../../lib/api');
|
2016-04-18 16:51:45 -04:00
|
|
|
|
2016-04-30 14:07:11 -04:00
|
|
|
var Page = require('../../components/page/www/page.jsx');
|
2016-08-12 16:31:09 -04:00
|
|
|
var TitleBanner = require('../../components/title-banner/title-banner.jsx');
|
|
|
|
var Button = require('../../components/forms/button.jsx');
|
2016-04-30 14:07:11 -04:00
|
|
|
var Tabs = require('../../components/tabs/tabs.jsx');
|
2016-05-10 00:54:46 -04:00
|
|
|
var Grid = require('../../components/grid/grid.jsx');
|
2016-11-09 12:48:39 -05:00
|
|
|
var navigationActions = require('../../redux/navigation.js');
|
2016-04-18 16:51:45 -04:00
|
|
|
|
|
|
|
require('./search.scss');
|
|
|
|
|
2016-05-10 00:54:46 -04:00
|
|
|
// @todo migrate to React-Router once available
|
2016-04-18 16:51:45 -04:00
|
|
|
var Search = injectIntl(React.createClass({
|
|
|
|
type: 'Search',
|
2016-05-10 00:54:46 -04:00
|
|
|
getDefaultProps: function () {
|
2016-06-09 07:32:25 -04:00
|
|
|
var pathname = window.location.pathname.toLowerCase();
|
|
|
|
if (pathname[pathname.length - 1] === '/') {
|
|
|
|
pathname = pathname.substring(0, pathname.length - 1);
|
|
|
|
}
|
2016-05-10 08:16:46 -04:00
|
|
|
var start = pathname.lastIndexOf('/');
|
2016-06-09 07:32:25 -04:00
|
|
|
var type = pathname.substring(start + 1, pathname.length);
|
2016-05-10 00:54:46 -04:00
|
|
|
return {
|
2016-05-10 08:16:46 -04:00
|
|
|
tab: type,
|
2016-05-10 00:54:46 -04:00
|
|
|
loadNumber: 16
|
|
|
|
};
|
2016-04-18 16:51:45 -04:00
|
|
|
},
|
2016-05-10 00:54:46 -04:00
|
|
|
getInitialState: function () {
|
|
|
|
return {
|
|
|
|
loaded: [],
|
2017-07-07 14:10:44 -04:00
|
|
|
offset: 0,
|
|
|
|
loadMore: false
|
2016-05-10 00:54:46 -04:00
|
|
|
};
|
|
|
|
},
|
|
|
|
componentDidMount: function () {
|
2017-02-10 18:54:20 -05:00
|
|
|
var query = window.location.search;
|
|
|
|
var q = query.lastIndexOf('q=');
|
|
|
|
var term = '';
|
|
|
|
if (q !== -1) {
|
|
|
|
term = query.substring(q + 2, query.length).toLowerCase();
|
|
|
|
}
|
|
|
|
while (term.indexOf('/') > -1) {
|
|
|
|
term = term.substring(0, term.indexOf('/'));
|
|
|
|
}
|
|
|
|
while (term.indexOf('&') > -1) {
|
|
|
|
term = term.substring(0, term.indexOf('&'));
|
|
|
|
}
|
2017-02-20 11:08:36 -05:00
|
|
|
term = decodeURI(term.split('+').join(' '));
|
|
|
|
this.props.dispatch(navigationActions.setSearchTerm(term));
|
|
|
|
},
|
2017-02-21 09:42:34 -05:00
|
|
|
componentDidUpdate: function (prevProps) {
|
|
|
|
if (this.props.searchTerm !== prevProps.searchTerm) this.getSearchMore();
|
2016-04-18 16:51:45 -04:00
|
|
|
},
|
|
|
|
getSearchMore: function () {
|
|
|
|
var termText = '';
|
2016-06-09 07:32:25 -04:00
|
|
|
if (this.props.searchTerm !== '') {
|
2017-02-20 11:08:36 -05:00
|
|
|
termText = '&q=' + encodeURIComponent(this.props.searchTerm.split(' ').join('+'));
|
2016-04-30 16:38:48 -04:00
|
|
|
}
|
2016-06-14 17:33:54 -04:00
|
|
|
api({
|
2016-06-09 07:32:25 -04:00
|
|
|
uri: '/search/' + this.props.tab +
|
|
|
|
'?limit=' + this.props.loadNumber +
|
|
|
|
'&offset=' + this.state.offset +
|
2016-07-07 08:38:10 -04:00
|
|
|
'&language=' + this.props.intl.locale +
|
2016-08-12 16:31:09 -04:00
|
|
|
'&mode=popular' +
|
2016-06-09 07:32:25 -04:00
|
|
|
termText
|
2016-04-18 16:51:45 -04:00
|
|
|
}, function (err, body) {
|
2016-05-10 00:54:46 -04:00
|
|
|
var loadedSoFar = this.state.loaded;
|
2016-06-09 07:32:25 -04:00
|
|
|
Array.prototype.push.apply(loadedSoFar, body);
|
2016-05-10 00:54:46 -04:00
|
|
|
var currentOffset = this.state.offset + this.props.loadNumber;
|
2017-07-07 14:10:44 -04:00
|
|
|
var willLoadMore = body.length === this.props.loadNumber;
|
|
|
|
this.setState({loaded: loadedSoFar, offset: currentOffset, loadMore: willLoadMore});
|
2016-04-18 16:51:45 -04:00
|
|
|
}.bind(this));
|
|
|
|
},
|
2016-08-12 16:31:09 -04:00
|
|
|
onSearchSubmit: function (formData) {
|
2017-02-20 11:08:05 -05:00
|
|
|
window.location.href = '/search/projects?q=' + encodeURIComponent(formData.q);
|
2016-08-12 16:31:09 -04:00
|
|
|
},
|
2016-04-30 16:38:48 -04:00
|
|
|
getTab: function (type) {
|
2016-05-10 08:16:46 -04:00
|
|
|
var term = this.props.searchTerm.split(' ').join('+');
|
2016-06-09 07:32:25 -04:00
|
|
|
var allTab = <a href={'/search/' + type + '?q=' + term + '/'}>
|
2016-08-22 13:30:44 -04:00
|
|
|
<li>
|
2016-08-12 16:31:09 -04:00
|
|
|
<img src={'/svgs/tabs/' + type + '-inactive.svg'} className={'tab-icon ' + type} />
|
2016-06-09 07:32:25 -04:00
|
|
|
<FormattedMessage id={'general.' + type} />
|
2016-04-18 16:51:45 -04:00
|
|
|
</li>
|
|
|
|
</a>;
|
2016-05-10 00:54:46 -04:00
|
|
|
if (this.props.tab == type) {
|
2016-06-09 07:32:25 -04:00
|
|
|
allTab = <a href={'/search/' + type + '?q=' + term + '/'}>
|
2016-04-30 16:38:48 -04:00
|
|
|
<li className='active'>
|
2016-08-12 16:31:09 -04:00
|
|
|
<img src={'/svgs/tabs/' + type + '-active.svg'} className={'tab-icon ' + type} />
|
2016-06-09 07:32:25 -04:00
|
|
|
<FormattedMessage id={'general.' + type} />
|
2016-04-18 16:51:45 -04:00
|
|
|
</li>
|
|
|
|
</a>;
|
|
|
|
}
|
|
|
|
return allTab;
|
|
|
|
},
|
2017-07-07 14:10:44 -04:00
|
|
|
getProjectBox: function () {
|
|
|
|
var results = <Grid
|
|
|
|
items={this.state.loaded}
|
|
|
|
itemType={this.props.tab}
|
|
|
|
cards={true}
|
|
|
|
showAvatar={true}
|
|
|
|
showLoves={false}
|
|
|
|
showFavorites={false}
|
|
|
|
showViews={false}
|
|
|
|
/>;
|
|
|
|
var searchAction = null;
|
|
|
|
if (this.state.loaded.length === 0 && this.state.offset !== 0) {
|
|
|
|
searchAction = <h2 className="search-prompt"><FormattedMessage id="general.searchEmpty" /></h2>;
|
|
|
|
} else if (this.state.loadMore) {
|
|
|
|
searchAction = <Button onClick={this.getSearchMore} className="white">
|
|
|
|
<FormattedMessage id='general.loadMore' />
|
|
|
|
</Button>;
|
|
|
|
}
|
|
|
|
return (
|
|
|
|
<div id='projectBox' key='projectBox'>
|
|
|
|
{results}
|
|
|
|
{searchAction}
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
},
|
2016-04-18 16:51:45 -04:00
|
|
|
render: function () {
|
|
|
|
return (
|
|
|
|
<div>
|
2016-04-30 16:38:48 -04:00
|
|
|
<div className='outer'>
|
2016-08-12 16:31:09 -04:00
|
|
|
<TitleBanner className="masthead">
|
|
|
|
<div className="inner">
|
2016-12-02 10:55:38 -05:00
|
|
|
<h1 className="title-banner-h1"><FormattedMessage id="general.search" /></h1>
|
2016-08-12 16:31:09 -04:00
|
|
|
</div>
|
|
|
|
</TitleBanner>
|
2016-04-30 14:07:11 -04:00
|
|
|
<Tabs>
|
2016-04-30 16:38:48 -04:00
|
|
|
{this.getTab('projects')}
|
|
|
|
{this.getTab('studios')}
|
2016-04-30 14:07:11 -04:00
|
|
|
</Tabs>
|
2017-07-07 14:10:44 -04:00
|
|
|
{this.getProjectBox()}
|
2016-04-18 16:51:45 -04:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}));
|
|
|
|
|
2016-10-31 10:05:08 -04:00
|
|
|
var mapStateToProps = function (state) {
|
|
|
|
return {
|
2017-02-10 18:54:20 -05:00
|
|
|
searchTerm: state.navigation
|
2016-10-31 10:05:08 -04:00
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2016-11-07 11:02:33 -05:00
|
|
|
var ConnectedSearch = connect(mapStateToProps)(Search);
|
2016-10-31 10:05:08 -04:00
|
|
|
|
2017-08-31 17:05:22 -04:00
|
|
|
render(
|
|
|
|
<Page><ConnectedSearch /></Page>,
|
|
|
|
document.getElementById('app'),
|
|
|
|
{navigation: navigationActions.navigationReducer}
|
|
|
|
);
|