Updated pages, layout component structures

• Updated:
- pages, layout component structures
This commit is contained in:
mgabdev 2020-08-14 12:45:59 -05:00
parent 67e1082cf5
commit 014e476b5d
23 changed files with 461 additions and 500 deletions

View File

@ -1,18 +1,6 @@
import Layout from './layout' import Layout from './layout'
export default class DefaultLayout extends PureComponent { class DefaultLayout extends PureComponent {
static propTypes = {
actions: PropTypes.array,
children: PropTypes.node.isRequired,
layout: PropTypes.object,
noComposeButton: PropTypes.bool,
noRightSidebar: PropTypes.bool,
page: PropTypes.string,
showBackBtn: PropTypes.bool,
tabs: PropTypes.array,
title: PropTypes.string.isRequired,
}
render() { render() {
const { const {
@ -44,3 +32,17 @@ export default class DefaultLayout extends PureComponent {
} }
} }
DefaultLayout.propTypes = {
actions: PropTypes.array,
children: PropTypes.node.isRequired,
layout: PropTypes.object,
noComposeButton: PropTypes.bool,
noRightSidebar: PropTypes.bool,
page: PropTypes.string,
showBackBtn: PropTypes.bool,
tabs: PropTypes.array,
title: PropTypes.string.isRequired,
}
export default DefaultLayout

View File

@ -14,37 +14,21 @@ import {
GroupInfoPanel, GroupInfoPanel,
} from '../features/ui/util/async_components' } from '../features/ui/util/async_components'
export default class GroupLayout extends ImmutablePureComponent { class GroupLayout extends ImmutablePureComponent {
static propTypes = {
actions: PropTypes.array,
children: PropTypes.node,
group: ImmutablePropTypes.map,
groupId: PropTypes.string,
isTimeline: PropTypes.bool,
layout: PropTypes.object,
relationships: ImmutablePropTypes.map,
showBackBtn: PropTypes.bool,
title: PropTypes.string,
}
render() { render() {
const { const {
actions,
children, children,
group, group,
groupId, groupId,
isTimeline,
relationships, relationships,
showBackBtn,
title, title,
} = this.props } = this.props
return ( return (
<Layout <Layout
noRightSidebar noRightSidebar
actions={actions} showBackBtn
showBackBtn={showBackBtn}
title={title} title={title}
page='group' page='group'
> >
@ -97,3 +81,13 @@ export default class GroupLayout extends ImmutablePureComponent {
} }
} }
GroupLayout.propTypes = {
children: PropTypes.node,
group: ImmutablePropTypes.map,
groupId: PropTypes.string,
relationships: ImmutablePropTypes.map,
title: PropTypes.string,
}
export default GroupLayout

View File

@ -20,22 +20,7 @@ import {
SidebarXS, SidebarXS,
} from '../features/ui/util/async_components' } from '../features/ui/util/async_components'
export default class Layout extends PureComponent { class Layout extends PureComponent {
static propTypes = {
actions: PropTypes.array,
children: PropTypes.node,
layout: PropTypes.array,
noComposeButton: PropTypes.bool,
noRightSidebar: PropTypes.bool,
noSidebar: PropTypes.bool,
page: PropTypes.string,
showBackBtn: PropTypes.bool,
showLinkFooterInSidebar: PropTypes.bool,
showGlobalFooter: PropTypes.bool,
tabs: PropTypes.array,
title: PropTypes.string,
}
render() { render() {
const { const {
@ -176,3 +161,20 @@ export default class Layout extends PureComponent {
} }
} }
Layout.propTypes = {
actions: PropTypes.array,
children: PropTypes.node,
layout: PropTypes.array,
noComposeButton: PropTypes.bool,
noRightSidebar: PropTypes.bool,
noSidebar: PropTypes.bool,
page: PropTypes.string,
showBackBtn: PropTypes.bool,
showLinkFooterInSidebar: PropTypes.bool,
showGlobalFooter: PropTypes.bool,
tabs: PropTypes.array,
title: PropTypes.string,
}
export default Layout

View File

@ -1,27 +1,24 @@
import PageTitle from '../features/ui/util/page_title' import PageTitle from '../features/ui/util/page_title'
import AboutLayout from '../layouts/about_layout' import AboutLayout from '../layouts/about_layout'
export default class AboutPage extends PureComponent { class AboutPage extends PureComponent {
static propTypes = {
title: PropTypes.string.isRequired,
children: PropTypes.node.isRequired,
}
render() { render() {
const { children, title } = this.props const { children, title } = this.props
return ( return (
<AboutLayout <AboutLayout title={title}>
noComposeButton
showBackBtn
title={title}
page='about'
>
<PageTitle path={title} /> <PageTitle path={title} />
{children} {children}
</AboutLayout> </AboutLayout>
) )
} }
} }
AboutPage.propTypes = {
title: PropTypes.string.isRequired,
children: PropTypes.node.isRequired,
}
export default AboutPage

View File

@ -6,13 +6,7 @@ import {
WhoToFollowPanel, WhoToFollowPanel,
} from '../features/ui/util/async_components' } from '../features/ui/util/async_components'
export default class BasicPage extends PureComponent { class BasicPage extends PureComponent {
static propTypes = {
children: PropTypes.node.isRequired,
page: PropTypes.string.isRequired,
title: PropTypes.string.isRequired,
}
render() { render() {
const { const {
@ -39,4 +33,12 @@ export default class BasicPage extends PureComponent {
) )
} }
} }
BasicPage.propTypes = {
children: PropTypes.node.isRequired,
page: PropTypes.string.isRequired,
title: PropTypes.string.isRequired,
}
export default BasicPage

View File

@ -2,6 +2,7 @@ import { defineMessages, injectIntl } from 'react-intl'
import { openModal } from '../actions/modal' import { openModal } from '../actions/modal'
import PageTitle from '../features/ui/util/page_title' import PageTitle from '../features/ui/util/page_title'
import DefaultLayout from '../layouts/default_layout' import DefaultLayout from '../layouts/default_layout'
import { MODAL_COMMUNITY_TIMELINE_SETTINGS } from '../constants'
import { import {
LinkFooter, LinkFooter,
GroupsPanel, GroupsPanel,
@ -10,29 +11,14 @@ import {
WhoToFollowPanel, WhoToFollowPanel,
} from '../features/ui/util/async_components' } from '../features/ui/util/async_components'
const messages = defineMessages({
community: { 'id': 'column.community', 'defaultMessage': 'Community feed' },
})
const mapDispatchToProps = (dispatch) => ({
onOpenCommunityPageSettingsModal() {
dispatch(openModal('COMMUNITY_TIMELINE_SETTINGS'))
},
})
export default
@injectIntl
@connect(null, mapDispatchToProps)
class CommunityPage extends PureComponent { class CommunityPage extends PureComponent {
static propTypes = { onOpenCommunityPageSettingsModal = () => {
intl: PropTypes.object.isRequired, this.props.dispatch(openModal(MODAL_COMMUNITY_TIMELINE_SETTINGS))
children: PropTypes.node.isRequired,
onOpenCommunityPageSettingsModal: PropTypes.func.isRequired,
} }
render() { render() {
const { intl, children, onOpenCommunityPageSettingsModal } = this.props const { children, intl } = this.props
const title = intl.formatMessage(messages.community) const title = intl.formatMessage(messages.community)
@ -43,7 +29,7 @@ class CommunityPage extends PureComponent {
actions={[ actions={[
{ {
icon: 'ellipsis', icon: 'ellipsis',
onClick: onOpenCommunityPageSettingsModal, onClick: this.onOpenCommunityPageSettingsModal,
}, },
]} ]}
layout={[ layout={[
@ -59,4 +45,16 @@ class CommunityPage extends PureComponent {
</DefaultLayout> </DefaultLayout>
) )
} }
} }
const messages = defineMessages({
community: { 'id': 'column.community', 'defaultMessage': 'Community feed' },
})
CommunityPage.propTypes = {
children: PropTypes.node.isRequired,
dispatch: PropTypes.func.isRequired,
intl: PropTypes.object.isRequired,
}
export default injectIntl(connect()(CommunityPage))

View File

@ -1,9 +1,7 @@
export default class ErrorPage extends PureComponent { export default class ErrorPage extends PureComponent {
render() { render() {
const { children } = this.props; const { children } = this.props
// : todo :
return ( return (
<div> <div>

View File

@ -1,25 +1,24 @@
import PageTitle from '../features/ui/util/page_title' import PageTitle from '../features/ui/util/page_title'
import ExploreLayout from '../layouts/explore_layout' import ExploreLayout from '../layouts/explore_layout'
export default class ExplorePage extends PureComponent { class ExplorePage extends PureComponent {
static propTypes = {
title: PropTypes.string.isRequired,
children: PropTypes.node.isRequired,
}
render() { render() {
const { children, title } = this.props const { children, title } = this.props
return ( return (
<ExploreLayout <ExploreLayout title={title}>
page='explore'
title={title}
>
<PageTitle path={title} /> <PageTitle path={title} />
{children} {children}
</ExploreLayout> </ExploreLayout>
) )
} }
} }
ExplorePage.propTypes = {
title: PropTypes.string.isRequired,
children: PropTypes.node.isRequired,
}
export default ExplorePage

View File

@ -8,39 +8,10 @@ import GroupLayout from '../layouts/group_layout'
import TimelineComposeBlock from '../components/timeline_compose_block' import TimelineComposeBlock from '../components/timeline_compose_block'
import Divider from '../components/divider' import Divider from '../components/divider'
const messages = defineMessages({
group: { id: 'group', defaultMessage: 'Group' },
})
const mapStateToProps = (state, { params: { id } }) => ({
group: state.getIn(['groups', id]),
relationships: state.getIn(['group_relationships', id]),
})
const mapDispatchToProps = (dispatch) => ({
onFetchGroup(groupId) {
dispatch(fetchGroup(groupId))
},
})
export default
@injectIntl
@connect(mapStateToProps, mapDispatchToProps)
class GroupPage extends ImmutablePureComponent { class GroupPage extends ImmutablePureComponent {
static propTypes = {
intl: PropTypes.object.isRequired,
group: ImmutablePropTypes.map,
children: PropTypes.node.isRequired,
relationships: ImmutablePropTypes.map,
onFetchGroup: PropTypes.func.isRequired,
sortByValue: PropTypes.string.isRequired,
sortByTopValue: PropTypes.string.isRequired,
}
componentDidMount() { componentDidMount() {
this.props.onFetchGroup(this.props.params.id) this.props.dispatch(fetchGroup(this.props.params.id))
// this.props.onFetchGroup(this.props.params.slug)
} }
render() { render() {
@ -54,15 +25,13 @@ class GroupPage extends ImmutablePureComponent {
const groupTitle = !!group ? group.get('title') : '' const groupTitle = !!group ? group.get('title') : ''
const groupId = !!group ? group.get('id') : undefined const groupId = !!group ? group.get('id') : undefined
return ( return (
<GroupLayout <GroupLayout
showBackBtn
title={'Group'} title={'Group'}
group={group} group={group}
groupId={groupId} groupId={groupId}
relationships={relationships} relationships={relationships}
isTimeline={isTimeline}
> >
<PageTitle path={[groupTitle, intl.formatMessage(messages.group)]} /> <PageTitle path={[groupTitle, intl.formatMessage(messages.group)]} />
@ -78,4 +47,25 @@ class GroupPage extends ImmutablePureComponent {
</GroupLayout> </GroupLayout>
) )
} }
} }
const messages = defineMessages({
group: { id: 'group', defaultMessage: 'Group' },
})
const mapStateToProps = (state, { params: { id } }) => ({
group: state.getIn(['groups', id]),
relationships: state.getIn(['group_relationships', id]),
})
GroupPage.propTypes = {
intl: PropTypes.object.isRequired,
group: ImmutablePropTypes.map,
children: PropTypes.node.isRequired,
relationships: ImmutablePropTypes.map,
dispatch: PropTypes.func.isRequired,
sortByValue: PropTypes.string.isRequired,
sortByTopValue: PropTypes.string.isRequired,
}
export default injectIntl(connect(mapStateToProps)(GroupPage))

View File

@ -1,4 +1,3 @@
import { Fragment } from 'react'
import { me } from '../initial_state' import { me } from '../initial_state'
import { defineMessages, injectIntl } from 'react-intl' import { defineMessages, injectIntl } from 'react-intl'
import PageTitle from '../features/ui/util/page_title' import PageTitle from '../features/ui/util/page_title'
@ -11,31 +10,8 @@ import {
LinkFooter, LinkFooter,
} from '../features/ui/util/async_components' } from '../features/ui/util/async_components'
const messages = defineMessages({
groups: { id: 'groups', defaultMessage: 'Groups' },
new: { id: 'new', defaultMessage: 'Recently Added Groups' },
featured: { id: 'featured', defaultMessage: 'Featured Groups' },
myGroupsTimeline: { id: 'my_groups_timeline', defaultMessage: 'Timeline' },
myGroups: { id: 'my_groups', defaultMessage: 'My Groups' },
admin: { id: 'admin', defaultMessage: 'Admin' },
})
const mapStateToProps = (state) => ({
isPro: state.getIn(['accounts', me, 'is_pro']),
})
export default
@injectIntl
@connect(mapStateToProps)
class GroupsPage extends PureComponent { class GroupsPage extends PureComponent {
static propTypes = {
activeTab: PropTypes.string.isRequired,
intl: PropTypes.object.isRequired,
children: PropTypes.node.isRequired,
isPro: PropTypes.bool,
}
render() { render() {
const { const {
activeTab, activeTab,
@ -46,13 +22,6 @@ class GroupsPage extends PureComponent {
const dontShowChildren = (activeTab === 'timeline' && !me) const dontShowChildren = (activeTab === 'timeline' && !me)
const actions = isPro ? [
{
icon: 'add',
to: '/groups/create',
},
] : []
const tabs = !!me ? [ const tabs = !!me ? [
{ {
title: intl.formatMessage(messages.myGroupsTimeline), title: intl.formatMessage(messages.myGroupsTimeline),
@ -80,7 +49,7 @@ class GroupsPage extends PureComponent {
} }
const title = intl.formatMessage(messages.groups) const title = intl.formatMessage(messages.groups)
const layout = [] const layout = []
if (!!me) { if (!!me) {
layout.push(<WrappedBundle component={GroupsPanel} componentParams={{ groupType: 'member' }} />) layout.push(<WrappedBundle component={GroupsPanel} componentParams={{ groupType: 'member' }} />)
@ -90,14 +59,22 @@ class GroupsPage extends PureComponent {
return ( return (
<DefaultLayout <DefaultLayout
title={title} title={title}
actions={actions} actions={[
{
title: 'Create',
icon: 'add',
to: '/groups/create',
},
]}
tabs={tabs} tabs={tabs}
page='groups' page='groups'
layout={layout} layout={layout}
> >
<PageTitle path={title} /> <PageTitle path={title} />
{ !dontShowChildren && children } {
!dontShowChildren && children
}
{ {
dontShowChildren && dontShowChildren &&
@ -108,3 +85,25 @@ class GroupsPage extends PureComponent {
} }
} }
const messages = defineMessages({
groups: { id: 'groups', defaultMessage: 'Groups' },
new: { id: 'new', defaultMessage: 'Recently Added Groups' },
featured: { id: 'featured', defaultMessage: 'Featured Groups' },
myGroupsTimeline: { id: 'my_groups_timeline', defaultMessage: 'Timeline' },
myGroups: { id: 'my_groups', defaultMessage: 'My Groups' },
admin: { id: 'admin', defaultMessage: 'Admin' },
})
const mapStateToProps = (state) => ({
isPro: state.getIn(['accounts', me, 'is_pro']),
})
GroupsPage.propTypes = {
activeTab: PropTypes.string.isRequired,
intl: PropTypes.object.isRequired,
children: PropTypes.node.isRequired,
isPro: PropTypes.bool,
}
export default injectIntl(connect(mapStateToProps)(GroupsPage))

View File

@ -3,6 +3,7 @@ import { defineMessages, injectIntl } from 'react-intl'
import isObject from 'lodash.isobject' import isObject from 'lodash.isobject'
import PageTitle from '../features/ui/util/page_title' import PageTitle from '../features/ui/util/page_title'
import DefaultLayout from '../layouts/default_layout' import DefaultLayout from '../layouts/default_layout'
import { MODAL_HASHTAG_TIMELINE_SETTINGS } from '../constants'
import { import {
LinkFooter, LinkFooter,
ProgressPanel, ProgressPanel,
@ -10,36 +11,23 @@ import {
WhoToFollowPanel, WhoToFollowPanel,
} from '../features/ui/util/async_components' } from '../features/ui/util/async_components'
const messages = defineMessages({
hashtag: { id: 'hashtag', defaultMessage: 'Hashtag' },
hashtagTimeline: { id: 'hashtag_timeline', defaultMessage: 'Hashtag timeline' },
})
const mapDispatchToProps = (dispatch) => ({
onOpenHashtagPageSettingsModal(hashtag) {
dispatch(openModal('HASHTAG_TIMELINE_SETTINGS', {
hashtag,
}))
},
})
export default
@injectIntl
@connect(null, mapDispatchToProps)
class HashtagPage extends PureComponent { class HashtagPage extends PureComponent {
static propTypes = { onOpenHashtagPageSettingsModal = () => {
intl: PropTypes.object.isRequired, const { params } = this.props
children: PropTypes.node.isRequired,
onOpenHashtagPageSettingsModal: PropTypes.func.isRequired, const hashtag = isObject(params) ? params.id : ''
params: PropTypes.object.isRequired, if (!hashtag) return
this.props.dispatch(openModal(MODAL_HASHTAG_TIMELINE_SETTINGS, {
hashtag,
}))
} }
render() { render() {
const { const {
intl,
children, children,
onOpenHashtagPageSettingsModal, intl,
params, params,
} = this.props } = this.props
@ -52,7 +40,7 @@ class HashtagPage extends PureComponent {
actions={[ actions={[
{ {
icon: 'ellipsis', icon: 'ellipsis',
onClick: onOpenHashtagPageSettingsModal, onClick: this.onOpenHashtagPageSettingsModal,
}, },
]} ]}
layout={[ layout={[
@ -67,4 +55,18 @@ class HashtagPage extends PureComponent {
</DefaultLayout> </DefaultLayout>
) )
} }
} }
const messages = defineMessages({
hashtag: { id: 'hashtag', defaultMessage: 'Hashtag' },
hashtagTimeline: { id: 'hashtag_timeline', defaultMessage: 'Hashtag timeline' },
})
HashtagPage.propTypes = {
children: PropTypes.node.isRequired,
dispatch: PropTypes.func.isRequired,
intl: PropTypes.object.isRequired,
params: PropTypes.object.isRequired,
}
export default injectIntl(connect()(HashtagPage))

View File

@ -21,34 +21,8 @@ import {
ProgressPanel, ProgressPanel,
} from '../features/ui/util/async_components' } from '../features/ui/util/async_components'
const messages = defineMessages({
home: { id: 'home', defaultMessage: 'Home' },
})
const mapStateToProps = (state) => ({
totalQueuedItemsCount: state.getIn(['timelines', 'home', 'totalQueuedItemsCount']),
isPro: state.getIn(['accounts', me, 'is_pro']),
})
const mapDispatchToProps = (dispatch) => ({
onOpenHomePageSettingsModal() {
dispatch(openModal(MODAL_HOME_TIMELINE_SETTINGS))
},
})
export default
@injectIntl
@connect(mapStateToProps, mapDispatchToProps)
class HomePage extends PureComponent { class HomePage extends PureComponent {
static propTypes = {
children: PropTypes.node.isRequired,
intl: PropTypes.object.isRequired,
onOpenHomePageSettingsModal: PropTypes.func.isRequired,
totalQueuedItemsCount: PropTypes.number.isRequired,
isPro: PropTypes.bool,
}
state = { state = {
lazyLoaded: false, lazyLoaded: false,
} }
@ -81,24 +55,29 @@ class HomePage extends PureComponent {
trailing: true, trailing: true,
}) })
onOpenHomePageSettingsModal = () => {
this.props.dispatch(openModal(MODAL_HOME_TIMELINE_SETTINGS))
}
render() { render() {
const { const {
intl,
children, children,
totalQueuedItemsCount, intl,
onOpenHomePageSettingsModal,
isPro, isPro,
totalQueuedItemsCount,
} = this.props } = this.props
const { lazyLoaded } = this.state const { lazyLoaded } = this.state
const title = intl.formatMessage(messages.home)
return ( return (
<DefaultLayout <DefaultLayout
page='home' page='home'
title={intl.formatMessage(messages.home)} title={title}
actions={[ actions={[
{ {
icon: 'ellipsis', icon: 'ellipsis',
onClick: onOpenHomePageSettingsModal, onClick: this.onOpenHomePageSettingsModal,
}, },
]} ]}
layout={[ layout={[
@ -115,7 +94,7 @@ class HomePage extends PureComponent {
> >
<PageTitle <PageTitle
path={intl.formatMessage(messages.home)} path={title}
badge={totalQueuedItemsCount} badge={totalQueuedItemsCount}
/> />
@ -130,4 +109,23 @@ class HomePage extends PureComponent {
</DefaultLayout> </DefaultLayout>
) )
} }
} }
const messages = defineMessages({
home: { id: 'home', defaultMessage: 'Home' },
})
const mapStateToProps = (state) => ({
totalQueuedItemsCount: state.getIn(['timelines', 'home', 'totalQueuedItemsCount']),
isPro: state.getIn(['accounts', me, 'is_pro']),
})
HomePage.propTypes = {
children: PropTypes.node.isRequired,
dispatch: PropTypes.func.isRequired,
intl: PropTypes.object.isRequired,
isPro: PropTypes.bool,
totalQueuedItemsCount: PropTypes.number.isRequired,
}
export default injectIntl(connect(mapStateToProps)(HomePage))

View File

@ -4,12 +4,10 @@ import IntroductionLayout from '../layouts/introduction_layout'
export default class IntroductionPage extends PureComponent { export default class IntroductionPage extends PureComponent {
render() { render() {
const { children } = this.props
return ( return (
<IntroductionLayout> <IntroductionLayout>
<PageTitle path='Welcome to Gab' /> <PageTitle path='Welcome to Gab' />
{children} {this.props.children}
</IntroductionLayout> </IntroductionLayout>
) )
} }

View File

@ -4,7 +4,6 @@ import { defineMessages, injectIntl } from 'react-intl'
import { openModal } from '../actions/modal' import { openModal } from '../actions/modal'
import { import {
MODAL_LIST_EDITOR, MODAL_LIST_EDITOR,
// MODAL_LIST_TIMELINE_SETTINGS,
} from '../constants' } from '../constants'
import PageTitle from '../features/ui/util/page_title' import PageTitle from '../features/ui/util/page_title'
import DefaultLayout from '../layouts/default_layout' import DefaultLayout from '../layouts/default_layout'
@ -16,68 +15,38 @@ import {
WhoToFollowPanel, WhoToFollowPanel,
} from '../features/ui/util/async_components' } from '../features/ui/util/async_components'
const messages = defineMessages({
list: { id: 'list', defaultMessage: 'List' },
})
const mapStateToProps = (state, props) => ({
list: state.getIn(['lists', props.params.id]),
})
const mapDispatchToProps = (dispatch) => ({
onOpenListEditModal(list) {
if (!list) return
const listId = list.get('id')
dispatch(openModal(MODAL_LIST_EDITOR, { id: listId }))
},
// : todo :
// onOpenListTimelineSettingsModal() {
// dispatch(openModal(MODAL_LIST_TIMELINE_SETTINGS))
// },
})
export default
@injectIntl
@connect(mapStateToProps, mapDispatchToProps)
class ListPage extends ImmutablePureComponent { class ListPage extends ImmutablePureComponent {
static propTypes = {
intl: PropTypes.object.isRequired,
list: ImmutablePropTypes.map,
children: PropTypes.node.isRequired,
onOpenListEditModal: PropTypes.func.isRequired,
// onOpenListTimelineSettingsModal: PropTypes.func.isRequired,
}
handleOnOpenListEditModal = () => { onOpenListEditModal = () => {
this.props.onOpenListEditModal(this.props.list) const { list } = this.props
if (!list) return
this.props.dispatch(openModal(MODAL_LIST_EDITOR, {
id: list.get('id'),
}))
} }
render() { render() {
const { const {
intl,
children, children,
intl,
list, list,
onOpenListEditModal,
// onOpenListTimelineSettingsModal
} = this.props } = this.props
const title = !!list ? list.get('title') : '' const listTitle = !!list ? list.get('title') : ''
const title = intl.formatMessage(messages.list)
return ( return (
<DefaultLayout <DefaultLayout
showBackBtn showBackBtn
title={intl.formatMessage(messages.list)} title={title}
page='list' page='list'
actions={[ actions={[
{ {
icon: 'cog', icon: 'cog',
onClick: this.handleOnOpenListEditModal, onClick: this.onOpenListEditModal,
}, },
// {
// icon: 'ellipsis',
// onClick: onOpenListTimelineSettingsModal,
// },
]} ]}
layout={[ layout={[
<WrappedBundle component={ListDetailsPanel} componentParams={{ list: list, onEdit: this.handleOnOpenListEditModal }} />, <WrappedBundle component={ListDetailsPanel} componentParams={{ list: list, onEdit: this.handleOnOpenListEditModal }} />,
@ -86,9 +55,26 @@ class ListPage extends ImmutablePureComponent {
LinkFooter, LinkFooter,
]} ]}
> >
<PageTitle path={[title, intl.formatMessage(messages.list)]} /> <PageTitle path={[listTitle, title]} />
{ children } { children }
</DefaultLayout> </DefaultLayout>
) )
} }
} }
const messages = defineMessages({
list: { id: 'list', defaultMessage: 'List' },
})
const mapStateToProps = (state, props) => ({
list: state.getIn(['lists', props.params.id]),
})
ListPage.propTypes = {
children: PropTypes.node.isRequired,
dispatch: PropTypes.func.isRequired,
intl: PropTypes.object.isRequired,
list: ImmutablePropTypes.map,
}
export default injectIntl(connect(mapStateToProps)(ListPage))

View File

@ -2,48 +2,33 @@ import { openModal } from '../actions/modal'
import { defineMessages, injectIntl } from 'react-intl' import { defineMessages, injectIntl } from 'react-intl'
import PageTitle from '../features/ui/util/page_title' import PageTitle from '../features/ui/util/page_title'
import DefaultLayout from '../layouts/default_layout' import DefaultLayout from '../layouts/default_layout'
import { MODAL_LIST_CREATE } from '../constants'
import { import {
LinkFooter, LinkFooter,
TrendsPanel, TrendsPanel,
WhoToFollowPanel, WhoToFollowPanel,
} from '../features/ui/util/async_components' } from '../features/ui/util/async_components'
const messages = defineMessages({
lists: { id: 'lists', defaultMessage: 'Lists' },
})
const mapDispatchToProps = (dispatch) => ({
onOpenListCreateModal() {
dispatch(openModal('LIST_CREATE'))
},
})
export default
@injectIntl
@connect(null, mapDispatchToProps)
class ListsPage extends PureComponent { class ListsPage extends PureComponent {
static propTypes = { onOpenListCreateModal = () => {
intl: PropTypes.object.isRequired, this.props.dispatch(openModal(MODAL_LIST_CREATE))
children: PropTypes.node.isRequired,
onOpenListCreateModal: PropTypes.func.isRequired,
} }
render() { render() {
const { const { children, intl } = this.props
intl,
children, const title = intl.formatMessage(messages.lists)
onOpenListCreateModal,
} = this.props
return ( return (
<DefaultLayout <DefaultLayout
title={intl.formatMessage(messages.lists)} showBackBtn
title={title}
page='lists' page='lists'
actions={[ actions={[
{ {
icon: 'add', icon: 'add',
onClick: onOpenListCreateModal, onClick: this.onOpenListCreateModal,
}, },
]} ]}
layout={[ layout={[
@ -51,12 +36,23 @@ class ListsPage extends PureComponent {
WhoToFollowPanel, WhoToFollowPanel,
LinkFooter, LinkFooter,
]} ]}
showBackBtn
> >
<PageTitle path={intl.formatMessage(messages.lists)} /> <PageTitle path={title} />
{children} {children}
</DefaultLayout> </DefaultLayout>
) )
} }
} }
const messages = defineMessages({
lists: { id: 'lists', defaultMessage: 'Lists' },
})
ListsPage.propTypes = {
intl: PropTypes.object.isRequired,
children: PropTypes.node.isRequired,
dispatch: PropTypes.func.isRequired,
}
export default injectIntl(connect()(ListsPage))

View File

@ -6,13 +6,7 @@ import {
WhoToFollowPanel, WhoToFollowPanel,
} from '../features/ui/util/async_components' } from '../features/ui/util/async_components'
export default class ModalPage extends PureComponent { class ModalPage extends PureComponent {
static propTypes = {
title: PropTypes.string,
page: PropTypes.string,
children: PropTypes.node,
}
render() { render() {
const { const {
@ -42,4 +36,12 @@ export default class ModalPage extends PureComponent {
) )
} }
} }
ModalPage.propTypes = {
title: PropTypes.string,
page: PropTypes.string,
children: PropTypes.node,
}
export default ModalPage

View File

@ -8,19 +8,14 @@ import {
VerifiedAccountsPanel, VerifiedAccountsPanel,
} from '../features/ui/util/async_components' } from '../features/ui/util/async_components'
export default class NewsPage extends PureComponent { class NewsPage extends PureComponent {
static propTypes = {
title: PropTypes.string.isRequired,
children: PropTypes.node.isRequired,
}
render() { render() {
const { children, title } = this.props const { children, title } = this.props
return ( return (
<DefaultLayout <DefaultLayout
page='explore' page='news'
title={title} title={title}
noComposeButton noComposeButton
showBackBtn showBackBtn
@ -39,3 +34,10 @@ export default class NewsPage extends PureComponent {
} }
} }
NewsPage.propTypes = {
children: PropTypes.node.isRequired,
title: PropTypes.string.isRequired,
}
export default NewsPage

View File

@ -12,6 +12,61 @@ import {
WhoToFollowPanel, WhoToFollowPanel,
} from '../features/ui/util/async_components' } from '../features/ui/util/async_components'
class NotificationsPage extends PureComponent {
onChangeActiveFilter(notificationType) {
this.props.dispatch(setFilter('active', notificationType))
if (notificationType === 'all') {
this.context.router.history.push('/notifications')
} else if (notificationType === 'follow_requests') {
this.context.router.history.push(`/notifications/follow_requests`)
} else {
this.context.router.history.push(`/notifications?view=${notificationType}`)
}
}
render() {
const {
children,
intl,
locked,
notificationCount,
selectedFilter,
} = this.props
let filters = NOTIFICATION_FILTERS
if (!locked && filters.indexOf('follow_requests') > -1) {
filters.splice(filters.indexOf('follow_requests'))
}
const tabs = filters.map((filter) => ({
title: intl.formatMessage(messages[filter]),
onClick: () => this.onChangeActiveFilter(filter),
active: selectedFilter.toLowerCase() === filter.toLowerCase(),
}))
const title = intl.formatMessage(messages.notifications)
return (
<DefaultLayout
title={title}
page='notifications'
layout={[
NotificationFilterPanel,
TrendsPanel,
WhoToFollowPanel,
LinkFooter,
]}
tabs={tabs}
>
<PageTitle badge={notificationCount} path={title} />
{children}
</DefaultLayout>
)
}
}
const messages = defineMessages({ const messages = defineMessages({
notifications: { id: 'tabs_bar.notifications', defaultMessage: 'Notifications' }, notifications: { id: 'tabs_bar.notifications', defaultMessage: 'Notifications' },
mention: { id: 'notifications.filter.mentions', defaultMessage: 'Mentions' }, mention: { id: 'notifications.filter.mentions', defaultMessage: 'Mentions' },
@ -29,80 +84,17 @@ const mapStateToProps = (state) => ({
locked: !!state.getIn(['accounts', me, 'locked']), locked: !!state.getIn(['accounts', me, 'locked']),
}) })
const mapDispatchToProps = (dispatch) => ({ NotificationsPage.contextTypes = {
setFilter(value) { router: PropTypes.object.isRequired,
dispatch(setFilter('active', value)) }
},
})
export default NotificationsPage.propTypes = {
@injectIntl children: PropTypes.node.isRequired,
@connect(mapStateToProps, mapDispatchToProps) dispatch: PropTypes.func.isRequired,
class NotificationsPage extends PureComponent { intl: PropTypes.object.isRequired,
locked: PropTypes.bool,
notificationCount: PropTypes.number.isRequired,
selectedFilter: PropTypes.string.isRequired,
}
static contextTypes = { export default injectIntl(connect(mapStateToProps)(NotificationsPage))
router: PropTypes.object.isRequired,
}
static propTypes = {
children: PropTypes.node.isRequired,
intl: PropTypes.object.isRequired,
notificationCount: PropTypes.number.isRequired,
setFilter: PropTypes.func.isRequired,
selectedFilter: PropTypes.string.isRequired,
locked: PropTypes.bool,
}
onChangeActiveFilter(notificationType) {
this.props.setFilter(notificationType)
if (notificationType === 'all') {
this.context.router.history.push('/notifications')
} else if (notificationType === 'follow_requests') {
this.context.router.history.push(`/notifications/follow_requests`)
} else {
this.context.router.history.push(`/notifications?view=${notificationType}`)
}
}
render() {
const {
children,
intl,
notificationCount,
selectedFilter,
locked
} = this.props
let filters = NOTIFICATION_FILTERS
if (!locked && filters.indexOf('follow_requests') > -1) {
filters.splice(filters.indexOf('follow_requests'))
}
const tabs = filters.map((filter) => ({
title: intl.formatMessage(messages[filter]),
onClick: () => this.onChangeActiveFilter(filter),
active: selectedFilter.toLowerCase() === filter.toLowerCase(),
}))
return (
<DefaultLayout
title={intl.formatMessage(messages.notifications)}
page='notifications'
layout={[
NotificationFilterPanel,
TrendsPanel,
WhoToFollowPanel,
LinkFooter,
]}
tabs={tabs}
>
<PageTitle
badge={notificationCount}
path={intl.formatMessage(messages.notifications)}
/>
{children}
</DefaultLayout>
)
}
}{}

View File

@ -7,19 +7,8 @@ import {
ProgressPanel, ProgressPanel,
} from '../features/ui/util/async_components' } from '../features/ui/util/async_components'
const messages = defineMessages({
title: { 'id': 'column.pro', 'defaultMessage': 'Pro feed' },
})
export default
@injectIntl
class ProPage extends PureComponent { class ProPage extends PureComponent {
static propTypes = {
intl: PropTypes.object.isRequired,
children: PropTypes.node.isRequired,
}
render() { render() {
const { intl, children } = this.props const { intl, children } = this.props
@ -40,4 +29,16 @@ class ProPage extends PureComponent {
</DefaultLayout> </DefaultLayout>
) )
} }
}
}
const messages = defineMessages({
title: { 'id': 'column.pro', 'defaultMessage': 'Pro feed' },
})
ProPage.propTypes = {
children: PropTypes.node.isRequired,
intl: PropTypes.object.isRequired,
}
export default injectIntl(ProPage)

View File

@ -9,46 +9,10 @@ import ColumnIndicator from '../components/column_indicator'
import Block from '../components/block' import Block from '../components/block'
import ProfileLayout from '../layouts/profile_layout' import ProfileLayout from '../layouts/profile_layout'
const mapStateToProps = (state, { params: { username } }) => {
const accounts = state.getIn(['accounts'])
const account = accounts.find(acct => username.toLowerCase() === acct.getIn(['acct'], '').toLowerCase())
const accountId = !!account ? account.get('id') : -1
const isBlocked = state.getIn(['relationships', accountId, 'blocked_by'], false)
const isLocked = state.getIn(['accounts', accountId, 'locked'], false)
const isFollowing = state.getIn(['relationships', accountId, 'following'], false)
const unavailable = (me === accountId) ? false : (isBlocked || (isLocked && !isFollowing))
const getAccount = makeGetAccount()
return {
unavailable,
account: accountId !== -1 ? getAccount(state, accountId) : null,
}
}
const mapDispatchToProps = (dispatch) => ({
onFetchAccountByUsername(username) {
dispatch(fetchAccountByUsername(username))
},
})
export default
@connect(mapStateToProps, mapDispatchToProps)
class ProfilePage extends ImmutablePureComponent { class ProfilePage extends ImmutablePureComponent {
static propTypes = {
children: PropTypes.node,
params: PropTypes.object.isRequired,
account: ImmutablePropTypes.map,
onFetchAccountByUsername: PropTypes.func.isRequired,
unavailable: PropTypes.bool.isRequired,
noSidebar: PropTypes.bool,
}
componentDidMount() { componentDidMount() {
this.props.onFetchAccountByUsername(this.props.params.username) this.props.dispatch(fetchAccountByUsername(this.props.params.username))
} }
render() { render() {
@ -89,4 +53,34 @@ class ProfilePage extends ImmutablePureComponent {
) )
} }
} }
const mapStateToProps = (state, { params: { username } }) => {
const accounts = state.getIn(['accounts'])
const account = accounts.find(acct => username.toLowerCase() === acct.getIn(['acct'], '').toLowerCase())
const accountId = !!account ? account.get('id') : -1
const isBlocked = state.getIn(['relationships', accountId, 'blocked_by'], false)
const isLocked = state.getIn(['accounts', accountId, 'locked'], false)
const isFollowing = state.getIn(['relationships', accountId, 'following'], false)
const unavailable = (me === accountId) ? false : (isBlocked || (isLocked && !isFollowing))
const getAccount = makeGetAccount()
return {
unavailable,
account: accountId !== -1 ? getAccount(state, accountId) : null,
}
}
ProfilePage.propTypes = {
account: ImmutablePropTypes.map,
children: PropTypes.node,
dispatch: PropTypes.func.isRequired,
noSidebar: PropTypes.bool,
params: PropTypes.object.isRequired,
unavailable: PropTypes.bool.isRequired,
}
export default connect(mapStateToProps)(ProfilePage)

View File

@ -11,34 +11,12 @@ import {
SignUpPanel, SignUpPanel,
} from '../features/ui/util/async_components' } from '../features/ui/util/async_components'
const messages = defineMessages({
search: { id: 'search', defaultMessage: 'Search' },
top: { id: 'top', defaultMessage: 'Top' },
people: { id: 'people', defaultMessage: 'People' },
groups: { id: 'groups', defaultMessage: 'Groups' },
hashtags: { id: 'hashtags', defaultMessage: 'Hashtags' },
})
const mapStateToProps = (state) => ({
value: state.getIn(['search', 'value']),
})
export default
@injectIntl
@connect(mapStateToProps)
class SearchPage extends PureComponent { class SearchPage extends PureComponent {
static propTypes = { componentWillMount() {
intl: PropTypes.object.isRequired, const { intl } = this.props
children: PropTypes.node.isRequired,
value: PropTypes.string,
}
render() { this.tabs = [
const { intl, children, value } = this.props
const title = intl.formatMessage(messages.search)
const tabs = [
{ {
title: intl.formatMessage(messages.top), title: intl.formatMessage(messages.top),
to: '/search' to: '/search'
@ -56,7 +34,16 @@ class SearchPage extends PureComponent {
to: '/search/hashtags' to: '/search/hashtags'
}, },
] ]
}
render() {
const {
children,
intl,
value,
} = this.props
const title = intl.formatMessage(messages.search)
const qos = !!value ? value : '' const qos = !!value ? value : ''
return ( return (
@ -64,7 +51,7 @@ class SearchPage extends PureComponent {
noComposeButton noComposeButton
title={title} title={title}
showBackBtn showBackBtn
tabs={tabs} tabs={this.tabs}
page={`search.${qos}`} page={`search.${qos}`}
layout={[ layout={[
SignUpPanel, SignUpPanel,
@ -74,7 +61,7 @@ class SearchPage extends PureComponent {
]} ]}
> >
<PageTitle path={title} /> <PageTitle path={title} />
<Responsive max={BREAKPOINT_EXTRA_SMALL}> <Responsive max={BREAKPOINT_EXTRA_SMALL}>
<div className={[_s.default, _s.px10].join(' ')}> <div className={[_s.default, _s.px10].join(' ')}>
<Search /> <Search />
@ -86,4 +73,24 @@ class SearchPage extends PureComponent {
) )
} }
} }
const messages = defineMessages({
search: { id: 'search', defaultMessage: 'Search' },
top: { id: 'top', defaultMessage: 'Top' },
people: { id: 'people', defaultMessage: 'People' },
groups: { id: 'groups', defaultMessage: 'Groups' },
hashtags: { id: 'hashtags', defaultMessage: 'Hashtags' },
})
const mapStateToProps = (state) => ({
value: state.getIn(['search', 'value']),
})
SearchPage.propTypes = {
intl: PropTypes.object.isRequired,
children: PropTypes.node.isRequired,
value: PropTypes.string,
}
export default injectIntl(connect(mapStateToProps)(SearchPage))

View File

@ -1,14 +1,13 @@
import SettingsLayout from '../layouts/settings_layout' import SettingsLayout from '../layouts/settings_layout'
export default class SettingsPage extends PureComponent { class SettingsPage extends PureComponent {
static propTypes = {
tabs: PropTypes.array,
title: PropTypes.string,
}
render() { render() {
const { children, title, tabs } = this.props; const {
children,
tabs,
title,
} = this.props
return ( return (
<SettingsLayout <SettingsLayout
@ -19,4 +18,13 @@ export default class SettingsPage extends PureComponent {
</SettingsLayout> </SettingsLayout>
) )
} }
}
}
SettingsPage.propTypes = {
children: PropTypes.node.isRequired,
tabs: PropTypes.array,
title: PropTypes.string,
}
export default SettingsPage

View File

@ -9,28 +9,10 @@ import {
WhoToFollowPanel, WhoToFollowPanel,
} from '../features/ui/util/async_components' } from '../features/ui/util/async_components'
const messages = defineMessages({
shortcuts: { id: 'shortcuts', defaultMessage: 'Shortcuts' },
})
const mapDispatchToProps = (dispatch) => ({
onOpenEditShortcutsModal() {
dispatch(openModal(MODAL_EDIT_SHORTCUTS))
},
})
export default
@injectIntl
@connect(null, mapDispatchToProps)
class ShortcutsPage extends PureComponent { class ShortcutsPage extends PureComponent {
static propTypes = {
intl: PropTypes.object.isRequired,
onOpenEditShortcutsModal: PropTypes.func.isRequired,
}
handleOnOpenEditShortcutsModal = () => { handleOnOpenEditShortcutsModal = () => {
this.props.onOpenEditShortcutsModal() this.props.dispatch(openModal(MODAL_EDIT_SHORTCUTS))
} }
render() { render() {
@ -59,4 +41,16 @@ class ShortcutsPage extends PureComponent {
</DefaultLayout> </DefaultLayout>
) )
} }
} }
const messages = defineMessages({
shortcuts: { id: 'shortcuts', defaultMessage: 'Shortcuts' },
})
ShortcutsPage.propTypes = {
children: PropTypes.node.isRequired,
dispatch: PropTypes.func.isRequired,
intl: PropTypes.object.isRequired,
}
export default injectIntl(connect()(ShortcutsPage))