This commit is contained in:
mgabdev
2020-02-20 19:57:29 -05:00
parent e37500c0cf
commit bebc39f150
61 changed files with 1181 additions and 802 deletions

View File

@@ -1,69 +0,0 @@
import { defineMessages, injectIntl } from 'react-intl';
import Search from '../../../../components/search';
const messages = defineMessages({
placeholder: { id: 'search.placeholder', defaultMessage: 'Search' },
});
export default @injectIntl
class ComposeSearch extends PureComponent {
static contextTypes = {
router: PropTypes.object.isRequired,
};
static propTypes = {
value: PropTypes.string.isRequired,
submitted: PropTypes.bool,
onChange: PropTypes.func.isRequired,
onSubmit: PropTypes.func.isRequired,
onClear: PropTypes.func.isRequired,
onShow: PropTypes.func.isRequired,
openInRoute: PropTypes.bool,
intl: PropTypes.object.isRequired,
};
handleChange = (e) => {
this.props.onChange(e.target.value);
}
handleClear = (e) => {
e.preventDefault();
if (this.props.value.length > 0 || this.props.submitted) {
this.props.onClear();
}
}
handleKeyUp = (e) => {
if (e.key === 'Enter') {
e.preventDefault();
this.props.onSubmit();
if (this.props.openInRoute) {
this.context.router.history.push('/search');
}
} else if (e.key === 'Escape') {
document.querySelector('.ui').parentElement.focus();
}
}
render () {
const { intl, value, onShow, openInRoute } = this.props;
return (
<Search
value={value}
placeholder={intl.formatMessage(messages.placeholder)}
onChange={this.handleChange}
onKeyUp={this.handleKeyUp}
handleClear={this.handleClear}
onShow={onShow}
withOverlay
openInRoute
/>
)
}
}

View File

@@ -1 +0,0 @@
export { default } from './compose_search';

View File

@@ -1,7 +1,7 @@
import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { FormattedMessage } from 'react-intl';
import TrendingItem from '../../../../components/trending_item';
import TrendingItem from '../../../../components/trends_panel_item';
import Icon from '../../../../components/icon';
import { WhoToFollowPanel } from '../../../../components/panel';
// import TrendsPanel from '../../ui/components/trends_panel';

View File

@@ -10,7 +10,7 @@ import {
import { mascot } from '../../initial_state';
import Motion from '../ui/util/optional_motion';
import ComposeFormContainer from './containers/compose_form_container';
import SearchContainer from './containers/search_container';
// import SearchContainer from './containers/search_container';
import SearchResultsContainer from './containers/search_results_container';
import NavigationBar from './components/navigation_bar';
import elephantUIPlane from '../../../images/logo_ui_column_footer.png';
@@ -76,7 +76,7 @@ class Compose extends ImmutablePureComponent {
<div className='drawer' role='region' aria-label={intl.formatMessage(messages.compose)}>
{header}
{isSearchPage && <SearchContainer /> }
{ /* isSearchPage && <SearchContainer /> */ }
<div className='drawer__pager'>
{!isSearchPage && <div className='drawer__inner' onFocus={this.onFocus}>

View File

@@ -1,34 +0,0 @@
import {
changeSearch,
clearSearch,
submitSearch,
showSearch,
} from '../../../actions/search';
import ComposeSearch from '../components/compose_search';
const mapStateToProps = state => ({
value: state.getIn(['search', 'value']),
submitted: state.getIn(['search', 'submitted']),
});
const mapDispatchToProps = dispatch => ({
onChange (value) {
dispatch(changeSearch(value));
},
onClear () {
dispatch(clearSearch());
},
onSubmit () {
dispatch(submitSearch());
},
onShow () {
dispatch(showSearch());
},
});
export default connect(mapStateToProps, mapDispatchToProps)(ComposeSearch);

View File

@@ -0,0 +1,104 @@
import ImmutablePropTypes from 'react-immutable-proptypes';
import { defineMessages, injectIntl } from 'react-intl';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { Link } from 'react-router-dom';
import classNames from 'classnames';
import { fetchGroups } from '../../../actions/groups';
import { openModal } from '../../../actions/modal';
import { me } from '../../../initial_state';
import GroupCard from './card';
import GroupCreate from '../create';
const messages = defineMessages({
heading: { id: 'column.groups', defaultMessage: 'Groups' },
create: { id: 'groups.create', defaultMessage: 'Create group' },
tab_featured: { id: 'groups.tab_featured', defaultMessage: 'Featured' },
tab_member: { id: 'groups.tab_member', defaultMessage: 'Member' },
tab_admin: { id: 'groups.tab_admin', defaultMessage: 'Manage' },
});
const mapStateToProps = (state, { activeTab }) => ({
groupIds: state.getIn(['group_lists', activeTab]),
account: state.getIn(['accounts', me]),
});
export default @connect(mapStateToProps)
@injectIntl
class Groups extends ImmutablePureComponent {
static propTypes = {
params: PropTypes.object.isRequired,
activeTab: PropTypes.string.isRequired,
showCreateForm: PropTypes.bool,
dispatch: PropTypes.func.isRequired,
groups: ImmutablePropTypes.map,
groupIds: ImmutablePropTypes.list,
intl: PropTypes.object.isRequired,
};
componentWillMount () {
this.props.dispatch(fetchGroups(this.props.activeTab));
}
componentDidUpdate(oldProps) {
if (this.props.activeTab && this.props.activeTab !== oldProps.activeTab) {
this.props.dispatch(fetchGroups(this.props.activeTab));
}
}
handleOpenProUpgradeModal = () => {
this.props.dispatch(openModal('PRO_UPGRADE'));
}
renderHeader() {
const { intl, activeTab, account, onOpenProUpgradeModal } = this.props;
const isPro = account.get('is_pro');
return (
<div className="group-column-header">
<div className="group-column-header__cta">
{
account && isPro &&
<Link to="/groups/create" className="button standard-small">{intl.formatMessage(messages.create)}</Link>
}
{
account && !isPro &&
<button onClick={this.handleOpenProUpgradeModal} className="button standard-small">{intl.formatMessage(messages.create)}</button>
}
</div>
<div className="group-column-header__title">{intl.formatMessage(messages.heading)}</div>
<div className="column-header__wrapper">
<h1 className="column-header">
<Link to='/groups' className={classNames('btn grouped', {'active': 'featured' === activeTab})}>
{intl.formatMessage(messages.tab_featured)}
</Link>
<Link to='/groups/browse/member' className={classNames('btn grouped', {'active': 'member' === activeTab})}>
{intl.formatMessage(messages.tab_member)}
</Link>
<Link to='/groups/browse/admin' className={classNames('btn grouped', {'active': 'admin' === activeTab})}>
{intl.formatMessage(messages.tab_admin)}
</Link>
</h1>
</div>
</div>
);
}
render () {
const { groupIds, showCreateForm } = this.props;
return (
<div>
{!showCreateForm && this.renderHeader()}
{showCreateForm && <GroupCreate /> }
<div className="group-card-list">
{groupIds.map(id => <GroupCard key={id} id={id} />)}
</div>
</div>
);
}
}

View File

@@ -0,0 +1 @@
export { default } from './group_timeline';

View File

@@ -0,0 +1,104 @@
import ImmutablePropTypes from 'react-immutable-proptypes';
import { defineMessages, injectIntl } from 'react-intl';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { Link } from 'react-router-dom';
import classNames from 'classnames';
import { fetchGroups } from '../../../actions/groups';
import { openModal } from '../../../actions/modal';
import { me } from '../../../initial_state';
import GroupCard from './card';
import GroupCreate from '../create';
const messages = defineMessages({
heading: { id: 'column.groups', defaultMessage: 'Groups' },
create: { id: 'groups.create', defaultMessage: 'Create group' },
tab_featured: { id: 'groups.tab_featured', defaultMessage: 'Featured' },
tab_member: { id: 'groups.tab_member', defaultMessage: 'Member' },
tab_admin: { id: 'groups.tab_admin', defaultMessage: 'Manage' },
});
const mapStateToProps = (state, { activeTab }) => ({
groupIds: state.getIn(['group_lists', activeTab]),
account: state.getIn(['accounts', me]),
});
export default @connect(mapStateToProps)
@injectIntl
class Groups extends ImmutablePureComponent {
static propTypes = {
params: PropTypes.object.isRequired,
activeTab: PropTypes.string.isRequired,
showCreateForm: PropTypes.bool,
dispatch: PropTypes.func.isRequired,
groups: ImmutablePropTypes.map,
groupIds: ImmutablePropTypes.list,
intl: PropTypes.object.isRequired,
};
componentWillMount () {
this.props.dispatch(fetchGroups(this.props.activeTab));
}
componentDidUpdate(oldProps) {
if (this.props.activeTab && this.props.activeTab !== oldProps.activeTab) {
this.props.dispatch(fetchGroups(this.props.activeTab));
}
}
handleOpenProUpgradeModal = () => {
this.props.dispatch(openModal('PRO_UPGRADE'));
}
renderHeader() {
const { intl, activeTab, account, onOpenProUpgradeModal } = this.props;
const isPro = account.get('is_pro');
return (
<div className="group-column-header">
<div className="group-column-header__cta">
{
account && isPro &&
<Link to="/groups/create" className="button standard-small">{intl.formatMessage(messages.create)}</Link>
}
{
account && !isPro &&
<button onClick={this.handleOpenProUpgradeModal} className="button standard-small">{intl.formatMessage(messages.create)}</button>
}
</div>
<div className="group-column-header__title">{intl.formatMessage(messages.heading)}</div>
<div className="column-header__wrapper">
<h1 className="column-header">
<Link to='/groups' className={classNames('btn grouped', {'active': 'featured' === activeTab})}>
{intl.formatMessage(messages.tab_featured)}
</Link>
<Link to='/groups/browse/member' className={classNames('btn grouped', {'active': 'member' === activeTab})}>
{intl.formatMessage(messages.tab_member)}
</Link>
<Link to='/groups/browse/admin' className={classNames('btn grouped', {'active': 'admin' === activeTab})}>
{intl.formatMessage(messages.tab_admin)}
</Link>
</h1>
</div>
</div>
);
}
render () {
const { groupIds, showCreateForm } = this.props;
return (
<div>
{!showCreateForm && this.renderHeader()}
{showCreateForm && <GroupCreate /> }
<div className="group-card-list">
{groupIds.map(id => <GroupCard key={id} id={id} />)}
</div>
</div>
);
}
}

View File

@@ -0,0 +1 @@
export { default } from './groups_directory';

View File

@@ -6,7 +6,7 @@ import { setupListAdder, resetListAdder } from '../../actions/lists';
import List from './components/list';
import Account from '../../components/account';
import IconButton from '../../components/icon_button';
import NewListForm from '../lists/components/new_list_form';
import NewListForm from '../lists_directory/components/new_list_form';
const getOrderedLists = createSelector([state => state.get('lists')], lists => {
if (!lists) {

View File

@@ -1 +0,0 @@
export { default } from './lists';

View File

@@ -0,0 +1 @@
export { default } from './lists_directory';

View File

@@ -1,13 +1,10 @@
import ImmutablePureComponent from 'react-immutable-pure-component'
import ImmutablePropTypes from 'react-immutable-proptypes'
import { NavLink } from 'react-router-dom'
import { createSelector } from 'reselect'
import { defineMessages, injectIntl } from 'react-intl'
import classNames from 'classnames/bind'
import { fetchLists } from '../../actions/lists'
import ColumnIndicator from '../../components/column_indicator'
import ScrollableList from '../../components/scrollable_list'
import Icon from '../../components/icon'
import List from '../../components/list'
const messages = defineMessages({
add: { id: 'lists.new.create', defaultMessage: 'Add List' },
@@ -30,11 +27,9 @@ const mapDispatchToProps = (dispatch) => ({
},
})
const cx = classNames.bind(_s)
export default @connect(mapStateToProps, mapDispatchToProps)
@injectIntl
class Lists extends ImmutablePureComponent {
class ListsDirectory extends ImmutablePureComponent {
static propTypes = {
params: PropTypes.object.isRequired,
@@ -63,56 +58,18 @@ class Lists extends ImmutablePureComponent {
const emptyMessage = intl.formatMessage(messages.empty)
const listItems = lists.map(list => ({
to: `/list/${list.get('id')}`,
title: list.get('title'),
}))
return (
<ScrollableList
<List
scrollKey='lists'
emptyMessage={emptyMessage}
>
<div className={[_s.default, _s.backgroundWhite, _s.radiusSmall, _s.overflowHidden, _s.border1PX, _s.bordercolorSecondary].join(' ')}>
{
lists.map((list, i) => {
const isLast = lists.length - 1 === i
return (
<ListItem key={list.get('id')} list={list} isLast={isLast} />
)
})
}
</div>
</ScrollableList>
items={listItems}
/>
)
}
}
class ListItem extends ImmutablePureComponent {
static propTypes = {
isLast: PropTypes.bool,
list: ImmutablePropTypes.map,
}
render() {
const { list, isLast } = this.props
const containerClasses = cx({
default: 1,
cursorPointer: 1,
noUnderline: 1,
paddingHorizontal15PX: 1,
paddingVertical15PX: 1,
flexRow: 1,
alignItemsCenter: 1,
backgroundSubtle_onHover: 1,
bordercolorSecondary: !isLast,
borderBottom1PX: !isLast,
})
return (
<NavLink to={`/list/${list.get('id')}`} className={containerClasses} >
<span className={[_s.default, _s.text, _s.colorPrimary, _s.fontSize14PX].join(' ')}>
{list.get('title')}
</span>
<Icon id='angle-right' className={[_s.marginLeftAuto, _s.fillColorBlack].join(' ')} width='10px' height='10px' />
</NavLink>
)
}
}

View File

@@ -1,4 +1,4 @@
import SearchContainer from '../compose/containers/search_container';
// import SearchContainer from '../compose/containers/search_container';
import SearchResultsContainer from '../compose/containers/search_results_container';
export default class Search extends PureComponent {
@@ -6,7 +6,7 @@ export default class Search extends PureComponent {
render() {
return (
<div className='column search-page'>
<SearchContainer />
{ /* <SearchContainer /> */ }
<div className='drawer__pager'>
<div className='drawer__inner darker'>

View File

@@ -161,7 +161,7 @@ export default class Card extends ImmutablePureComponent {
)
const description = (
<div className={[_s.default, _s.flexNormal, _s.paddingHorizontal10PX, _s.paddingVertical10PX, _s.bordercolorSecondary, _s.borderLeft1PX].join(' ')}>
<div className={[_s.default, _s.flexNormal, _s.paddingHorizontal10PX, _s.paddingVertical10PX, _s.borderColorSecondary, _s.borderLeft1PX].join(' ')}>
{title}
<p className={[_s.default, _s.displayFlex, _s.text, _s.marginVertical5PX, _s.overflowWrapBreakWord, _s.colorSecondary, _s.fontSize13PX, _s.fontWeightNormal].join(' ')}>
{trim(card.get('description') || '', maxDescription)}
@@ -192,7 +192,7 @@ export default class Card extends ImmutablePureComponent {
return (
<div className={[_s.default, _s.width100PC, _s.paddingHorizontal10PX].join(' ')}>
<div className={[_s.default, _s.overflowHidden, _s.width100PC, _s.bordercolorSecondary2, _s.border1PX, _s.radiusSmall].join(' ')}>
<div className={[_s.default, _s.overflowHidden, _s.width100PC, _s.borderColorSecondary2, _s.border1PX, _s.radiusSmall].join(' ')}>
<div className={[_s.default, _s.width100PC].join(' ')}>
<div className={[_s.default, _s.width100PC, _s.paddingTop5625PC].join(' ')}>
{ !!embed && embed}
@@ -231,7 +231,7 @@ export default class Card extends ImmutablePureComponent {
<div className={[_s.default, _s.width100PC, _s.paddingHorizontal10PX].join(' ')}>
<a
href={card.get('url')}
className={[_s.default, _s.cursorPointer, _s.flexRow, _s.overflowHidden, _s.noUnderline, _s.width100PC, _s.bordercolorSecondary2, _s.border1PX, _s.radiusSmall].join(' ')}
className={[_s.default, _s.cursorPointer, _s.flexRow, _s.overflowHidden, _s.noUnderline, _s.width100PC, _s.borderColorSecondary2, _s.border1PX, _s.radiusSmall].join(' ')}
rel='noopener'
ref={this.setRef}
>

View File

@@ -60,7 +60,7 @@ import {
// Groups,
// GroupTimeline,
ListTimeline,
Lists,
ListsDirectory,
// GroupMembers,
// GroupRemovedAccounts,
// GroupCreate,
@@ -195,7 +195,7 @@ class SwitchingColumnsArea extends PureComponent {
<WrappedRoute path='/tags/:id' publicRoute component={HashtagTimeline} content={children} />
*/}
<WrappedRoute path='/lists' page={ListsPage} component={Lists} content={children} />
<WrappedRoute path='/lists' page={ListsPage} component={ListsDirectory} content={children} />
<WrappedRoute path='/list/:id' page={ListPage} component={ListTimeline} content={children} />
<WrappedRoute path='/notifications' page={NotificationsPage} component={Notifications} content={children} />

View File

@@ -50,8 +50,8 @@ export function Groups () {
return import(/* webpackChunkName: "features/groups/index" */'../../groups/index');
}
export function Lists () {
return import(/* webpackChunkName: "features/lists" */'../../lists');
export function ListsDirectory () {
return import(/* webpackChunkName: "features/lists_directory" */'../../lists_directory');
}
export function Status () {