Add suggestions columns
This commit is contained in:
parent
cfce94fb24
commit
2de85178bd
8 changed files with 139 additions and 2 deletions
|
@ -37,6 +37,7 @@ const messages = defineMessages({
|
|||
menu: { id: 'getting_started.heading', defaultMessage: 'Getting started' },
|
||||
group_directory: { id: 'getting_started.group_directory', defaultMessage: 'Group directory' },
|
||||
profile_directory: { id: 'getting_started.directory', defaultMessage: 'Profile directory' },
|
||||
suggestions: { id: 'navigation_bar.suggestions', defaultMessage: 'Suggestions' },
|
||||
trends: { id: 'navigation_bar.trends', defaultMessage: 'Trends' },
|
||||
information_acct: { id: 'navigation_bar.information_acct', defaultMessage: 'Fedibird info' },
|
||||
hashtag_fedibird: { id: 'navigation_bar.hashtag_fedibird', defaultMessage: 'fedibird' },
|
||||
|
@ -122,10 +123,11 @@ class GettingStarted extends ImmutablePureComponent {
|
|||
}
|
||||
|
||||
navItems.push(
|
||||
<ColumnLink key='suggestions' icon='user-plus' text={intl.formatMessage(messages.suggestions)} to='/suggestions' />,
|
||||
<ColumnLink key='trends' icon='line-chart' text={intl.formatMessage(messages.trends)} to='/trends' />,
|
||||
);
|
||||
|
||||
height += 48;
|
||||
height += 48*2;
|
||||
|
||||
navItems.push(
|
||||
<ColumnLink key='information_acct' icon='info-circle' text={intl.formatMessage(messages.information_acct)} to='/accounts/2' />,
|
||||
|
@ -155,10 +157,11 @@ class GettingStarted extends ImmutablePureComponent {
|
|||
}
|
||||
|
||||
navItems.push(
|
||||
<ColumnLink key='suggestions' icon='user-plus' text={intl.formatMessage(messages.suggestions)} to='/suggestions' />,
|
||||
<ColumnLink key='trends' icon='line-chart' text={intl.formatMessage(messages.trends)} to='/trends' />,
|
||||
);
|
||||
|
||||
height += 48;
|
||||
height += 48*2;
|
||||
|
||||
navItems.push(
|
||||
<ColumnLink key='information_acct' icon='info-circle' text={intl.formatMessage(messages.information_acct)} to='/accounts/2' />,
|
||||
|
|
119
app/javascript/mastodon/features/suggestions/index.js
Normal file
119
app/javascript/mastodon/features/suggestions/index.js
Normal file
|
@ -0,0 +1,119 @@
|
|||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import PropTypes from 'prop-types';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import { fetchSuggestions, dismissSuggestion } from 'mastodon/actions/suggestions';
|
||||
import Column from '../ui/components/column';
|
||||
import ColumnHeader from '../../components/column_header';
|
||||
import ColumnSubheading from '../ui/components/column_subheading';
|
||||
import { addColumn, removeColumn, moveColumn } from '../../actions/columns';
|
||||
import ScrollableList from 'mastodon/components/scrollable_list';
|
||||
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
||||
import AccountContainer from 'mastodon/containers/account_container';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
|
||||
const messages = defineMessages({
|
||||
heading: { id: 'suggestions.heading', defaultMessage: 'Suggestions' },
|
||||
subheading: { id: 'suggestions.header', defaultMessage: 'You might be interested in…' },
|
||||
dismissSuggestion: { id: 'suggestions.dismiss', defaultMessage: 'Dismiss suggestion' },
|
||||
});
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
suggestions: state.getIn(['suggestions', 'items']),
|
||||
isLoading: state.getIn(['suggestions', 'isLoading'], true),
|
||||
});
|
||||
|
||||
export default @connect(mapStateToProps)
|
||||
@injectIntl
|
||||
class Suggestions extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
suggestions: ImmutablePropTypes.list.isRequired,
|
||||
intl: PropTypes.object.isRequired,
|
||||
columnId: PropTypes.string,
|
||||
multiColumn: PropTypes.bool,
|
||||
isLoading: PropTypes.bool,
|
||||
};
|
||||
|
||||
componentDidMount () {
|
||||
this.fetchSuggestions();
|
||||
}
|
||||
|
||||
fetchSuggestions = () => {
|
||||
const { dispatch } = this.props;
|
||||
|
||||
dispatch(fetchSuggestions());
|
||||
}
|
||||
|
||||
dismissSuggestion = account => {
|
||||
const { dispatch } = this.props;
|
||||
|
||||
dispatch(dismissSuggestion(account.get('id')));
|
||||
}
|
||||
|
||||
handlePin = () => {
|
||||
const { columnId, dispatch } = this.props;
|
||||
|
||||
if (columnId) {
|
||||
dispatch(removeColumn(columnId));
|
||||
} else {
|
||||
dispatch(addColumn('SUGGESTIONS', {}));
|
||||
}
|
||||
}
|
||||
|
||||
handleMove = (dir) => {
|
||||
const { columnId, dispatch } = this.props;
|
||||
dispatch(moveColumn(columnId, dir));
|
||||
}
|
||||
|
||||
handleHeaderClick = () => {
|
||||
this.column.scrollTop();
|
||||
}
|
||||
|
||||
setRef = c => {
|
||||
this.column = c;
|
||||
}
|
||||
|
||||
render () {
|
||||
const { intl, suggestions, columnId, multiColumn, isLoading } = this.props;
|
||||
const pinned = !!columnId;
|
||||
|
||||
const emptyMessage = <FormattedMessage id='empty_column.suggestions' defaultMessage='No one has suggestions yet.' />;
|
||||
|
||||
return (
|
||||
<Column bindToDocument={!multiColumn} ref={this.setRef} label={intl.formatMessage(messages.heading)}>
|
||||
<ColumnHeader
|
||||
icon='user-plus'
|
||||
title={intl.formatMessage(messages.heading)}
|
||||
onPin={this.handlePin}
|
||||
onMove={this.handleMove}
|
||||
onClick={this.handleHeaderClick}
|
||||
pinned={pinned}
|
||||
multiColumn={multiColumn}
|
||||
showBackButton
|
||||
/>
|
||||
|
||||
<ScrollableList
|
||||
trackScroll={!pinned}
|
||||
scrollKey={`suggestions-${columnId}`}
|
||||
isLoading={isLoading}
|
||||
emptyMessage={emptyMessage}
|
||||
prepend={<ColumnSubheading text={intl.formatMessage(messages.subheading)} />}
|
||||
bindToDocument={!multiColumn}
|
||||
>
|
||||
{suggestions && suggestions.map(suggestion => (
|
||||
<AccountContainer
|
||||
key={suggestion.get('account')}
|
||||
id={suggestion.get('account')}
|
||||
actionIcon={suggestion.get('source') === 'past_interaction' ? 'times' : null}
|
||||
actionTitle={suggestion.get('source') === 'past_interaction' ? intl.formatMessage(messages.dismissSuggestion) : null}
|
||||
onActionClick={dismissSuggestion}
|
||||
/>
|
||||
))}
|
||||
</ScrollableList>
|
||||
</Column>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -29,6 +29,7 @@ import {
|
|||
GroupDirectory,
|
||||
Directory,
|
||||
Trends,
|
||||
Suggestions,
|
||||
} from '../../ui/util/async-components';
|
||||
import Icon from 'mastodon/components/icon';
|
||||
import ComposePanel from './compose_panel';
|
||||
|
@ -56,6 +57,7 @@ const componentMap = {
|
|||
'GROUP_DIRECTORY': GroupDirectory,
|
||||
'DIRECTORY': Directory,
|
||||
'TRENDS': Trends,
|
||||
'SUGGESTIONS': Suggestions,
|
||||
};
|
||||
|
||||
const messages = defineMessages({
|
||||
|
|
|
@ -25,6 +25,7 @@ const NavigationPanel = () => (
|
|||
<NavLink className='column-link column-link--transparent' to='/circles'><Icon className='column-link__icon' id='user-circle' fixedWidth /><FormattedMessage id='navigation_bar.circles' defaultMessage='Circles' /></NavLink>
|
||||
<NavLink className='column-link column-link--transparent' to='/group_directory'><Icon className='column-link__icon' id='address-book-o' fixedWidth /><FormattedMessage id='getting_started.group_directory' defaultMessage='Group directory' /></NavLink>
|
||||
{profile_directory && <NavLink className='column-link column-link--transparent' to='/directory'><Icon className='column-link__icon' id='address-book-o' fixedWidth /><FormattedMessage id='getting_started.directory' defaultMessage='Profile directory' /></NavLink>}
|
||||
<NavLink className='column-link column-link--transparent' to='/suggestions'><Icon className='column-link__icon' id='user-plus' fixedWidth /><FormattedMessage id='navigation_bar.suggestions' defaultMessage='Suggestions' /></NavLink>
|
||||
<NavLink className='column-link column-link--transparent' to='/trends'><Icon className='column-link__icon' id='line-chart' fixedWidth /><FormattedMessage id='navigation_bar.trends' defaultMessage='Trends' /></NavLink>
|
||||
|
||||
<ListPanel />
|
||||
|
|
|
@ -58,6 +58,7 @@ import {
|
|||
Directory,
|
||||
FollowRecommendations,
|
||||
Trends,
|
||||
Suggestions,
|
||||
} from './util/async-components';
|
||||
import { me } from '../../initial_state';
|
||||
import { closeOnboarding, INTRODUCTION_VERSION } from 'mastodon/actions/onboarding';
|
||||
|
@ -175,6 +176,7 @@ class SwitchingColumnsArea extends React.PureComponent {
|
|||
<WrappedRoute path='/group_directory' component={GroupDirectory} content={children} />
|
||||
<WrappedRoute path='/directory' component={Directory} content={children} />
|
||||
<WrappedRoute path='/trends' component={Trends} content={children} />
|
||||
<WrappedRoute path='/suggestions' component={Suggestions} content={children} />
|
||||
|
||||
<WrappedRoute path='/statuses/new' component={Compose} content={children} />
|
||||
<WrappedRoute path='/statuses/:statusId' exact component={Status} content={children} />
|
||||
|
|
|
@ -189,3 +189,7 @@ export function FollowRecommendations () {
|
|||
export function Trends () {
|
||||
return import(/* webpackChunkName: "features/trends" */'../../trends');
|
||||
}
|
||||
|
||||
export function Suggestions () {
|
||||
return import(/* webpackChunkName: "features/suggestions" */'../../suggestions');
|
||||
}
|
||||
|
|
|
@ -203,6 +203,7 @@
|
|||
"empty_column.mutes": "You haven't muted any users yet.",
|
||||
"empty_column.notifications": "You don't have any notifications yet. When other people interact with you, you will see it here.",
|
||||
"empty_column.public": "There is nothing here! Write something publicly, or manually follow users from other servers to fill it up",
|
||||
"empty_column.suggestions": "No one has suggestions yet.",
|
||||
"empty_column.trends": "No one has trends yet.",
|
||||
"error.unexpected_crash.explanation": "Due to a bug in our code or a browser compatibility issue, this page could not be displayed correctly.",
|
||||
"error.unexpected_crash.explanation_addons": "This page could not be displayed correctly. This error is likely caused by a browser add-on or automatic translation tools.",
|
||||
|
@ -346,6 +347,7 @@
|
|||
"navigation_bar.short.preferences": "Pref.",
|
||||
"navigation_bar.short.public_timeline": "FTL",
|
||||
"navigation_bar.short.search": "Search",
|
||||
"navigation_bar.suggestions": "Suggestions",
|
||||
"navigation_bar.trends": "Trends",
|
||||
"notification.favourite": "{name} favourited your post",
|
||||
"notification.follow": "{name} followed you",
|
||||
|
@ -489,6 +491,7 @@
|
|||
"status.unpin": "Unpin from profile",
|
||||
"suggestions.dismiss": "Dismiss suggestion",
|
||||
"suggestions.header": "You might be interested in…",
|
||||
"suggestions.heading": "Suggestions",
|
||||
"tabs_bar.federated_timeline": "Federated",
|
||||
"tabs_bar.home": "Home",
|
||||
"tabs_bar.lists": "List",
|
||||
|
|
|
@ -202,6 +202,7 @@
|
|||
"empty_column.lists": "まだリストがありません。リストを作るとここに表示されます。",
|
||||
"empty_column.mutes": "まだ誰もミュートしていません。",
|
||||
"empty_column.notifications": "まだ通知がありません。他の人とふれ合って会話を始めましょう。",
|
||||
"empty_column.suggestions": "まだおすすめできるユーザーがいません。",
|
||||
"empty_column.trends": "まだ何もトレンドがありません。",
|
||||
"empty_column.public": "ここにはまだ何もありません! 公開で何かを投稿したり、他のサーバーのユーザーをフォローしたりしていっぱいにしましょう",
|
||||
"error.unexpected_crash.explanation": "不具合かブラウザの互換性問題のため、このページを正しく表示できませんでした。",
|
||||
|
@ -346,6 +347,7 @@
|
|||
"navigation_bar.short.preferences": "設定",
|
||||
"navigation_bar.short.public_timeline": "連合",
|
||||
"navigation_bar.short.search": "検索",
|
||||
"navigation_bar.suggestions": "おすすめユーザー",
|
||||
"navigation_bar.trends": "トレンド",
|
||||
"notification.favourite": "{name}さんがあなたの投稿をお気に入りに登録しました",
|
||||
"notification.follow": "{name}さんにフォローされました",
|
||||
|
@ -489,6 +491,7 @@
|
|||
"status.unpin": "プロフィールへの固定を解除",
|
||||
"suggestions.dismiss": "隠す",
|
||||
"suggestions.header": "興味あるかもしれません…",
|
||||
"suggestions.heading": "おすすめユーザー",
|
||||
"tabs_bar.federated_timeline": "連合",
|
||||
"tabs_bar.home": "ホーム",
|
||||
"tabs_bar.lists": "リスト",
|
||||
|
|
Loading…
Reference in a new issue