Progress
This commit is contained in:
parent
e37500c0cf
commit
bebc39f150
@ -8,6 +8,8 @@ import Avatar from '../avatar'
|
|||||||
import DisplayName from '../display_name'
|
import DisplayName from '../display_name'
|
||||||
import IconButton from '../icon_button'
|
import IconButton from '../icon_button'
|
||||||
import Icon from '../icon'
|
import Icon from '../icon'
|
||||||
|
import Button from '../button'
|
||||||
|
import Text from '../text'
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
follow: { id: 'account.follow', defaultMessage: 'Follow' },
|
follow: { id: 'account.follow', defaultMessage: 'Follow' },
|
||||||
@ -126,9 +128,17 @@ class Account extends ImmutablePureComponent {
|
|||||||
>
|
>
|
||||||
<DisplayName account={account} />
|
<DisplayName account={account} />
|
||||||
</NavLink>
|
</NavLink>
|
||||||
<button className={[_s.default, _s.marginTop5PX, _s.colorBrand, _s.text, _s.cursorPointer, _s.fontSize14PX, _s.circle, _s.border1PX, _s.borderColorBrand, _s.paddingHorizontal20PX, _s.paddingVertical5PX].join(' ')}>
|
<Button
|
||||||
|
outline
|
||||||
|
narrow
|
||||||
|
color='brand'
|
||||||
|
backgroundColor='none'
|
||||||
|
className={_s.marginTop5PX}
|
||||||
|
>
|
||||||
|
<Text color='inherit'>
|
||||||
{intl.formatMessage(messages.follow)}
|
{intl.formatMessage(messages.follow)}
|
||||||
</button>
|
</Text>
|
||||||
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={[_s.default, _s.marginLeftAuto].join(' ')}>
|
<div className={[_s.default, _s.marginLeftAuto].join(' ')}>
|
||||||
|
@ -203,7 +203,7 @@ export default class AutosuggestTextbox extends ImmutablePureComponent {
|
|||||||
<div className={[_s.default, _s.marginLeft5PX].join(' ')}>
|
<div className={[_s.default, _s.marginLeft5PX].join(' ')}>
|
||||||
<Textarea
|
<Textarea
|
||||||
inputRef={this.setTextbox}
|
inputRef={this.setTextbox}
|
||||||
className={[_s.default, _s.backgroundWhite, _s.lineHeight125, _s.resizeNone, _s.paddingVertical15PX, _s.outlineFocusBrand, _s.fontSize16PX, _s.text, _s.displayBlock].join(' ')}
|
className={[_s.default, _s.backgroundColorPrimary, _s.lineHeight125, _s.resizeNone, _s.paddingVertical15PX, _s.outlineFocusBrand, _s.fontSize16PX, _s.text, _s.displayBlock].join(' ')}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
autoFocus={autoFocus}
|
autoFocus={autoFocus}
|
||||||
|
@ -3,7 +3,7 @@ import Text from './text'
|
|||||||
export default class Badge extends PureComponent {
|
export default class Badge extends PureComponent {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
children: PropTypes.string,
|
children: PropTypes.string,
|
||||||
popover: PropTypes.string,
|
description: PropTypes.string,
|
||||||
}
|
}
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
@ -19,15 +19,17 @@ export default class Badge extends PureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { children, popover } = this.props
|
const { children, description } = this.props
|
||||||
const { hovering } = this.state
|
const { hovering } = this.state
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<Text
|
||||||
<Text color='secondary' size='small' className={_s.marginVertical5PX}>
|
color='white'
|
||||||
|
size='extraSmall'
|
||||||
|
className={[_s.backgroundColorBrand, _s.paddingHorizontal5PX, _s.lineHeight125, _s.radiusSmall].join(' ')}
|
||||||
|
>
|
||||||
{children}
|
{children}
|
||||||
</Text>
|
</Text>
|
||||||
</div>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,5 +1,7 @@
|
|||||||
|
import { Fragment } from 'react'
|
||||||
import { NavLink } from 'react-router-dom'
|
import { NavLink } from 'react-router-dom'
|
||||||
import classNames from 'classnames/bind'
|
import classNames from 'classnames/bind'
|
||||||
|
import Icon from './icon'
|
||||||
|
|
||||||
const cx = classNames.bind(_s)
|
const cx = classNames.bind(_s)
|
||||||
|
|
||||||
@ -7,6 +9,7 @@ const COLORS = {
|
|||||||
primary: 'primary',
|
primary: 'primary',
|
||||||
secondary: 'secondary',
|
secondary: 'secondary',
|
||||||
tertiary: 'tertiary',
|
tertiary: 'tertiary',
|
||||||
|
white: 'white',
|
||||||
brand: 'brand',
|
brand: 'brand',
|
||||||
error: 'error',
|
error: 'error',
|
||||||
none: 'none',
|
none: 'none',
|
||||||
@ -21,15 +24,22 @@ export default class Button extends PureComponent {
|
|||||||
onClick: PropTypes.func,
|
onClick: PropTypes.func,
|
||||||
className: PropTypes.string,
|
className: PropTypes.string,
|
||||||
icon: PropTypes.string,
|
icon: PropTypes.string,
|
||||||
|
iconWidth: PropTypes.string,
|
||||||
|
iconHeight: PropTypes.string,
|
||||||
|
iconClassName: PropTypes.string,
|
||||||
color: PropTypes.string,
|
color: PropTypes.string,
|
||||||
|
backgroundColor: PropTypes.string,
|
||||||
block: PropTypes.bool,
|
block: PropTypes.bool,
|
||||||
text: PropTypes.bool,
|
text: PropTypes.bool,
|
||||||
disabled: PropTypes.bool,
|
disabled: PropTypes.bool,
|
||||||
outline: PropTypes.bool,
|
outline: PropTypes.bool,
|
||||||
|
narrow: PropTypes.bool,
|
||||||
|
underlineOnHover: PropTypes.bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
color: COLORS.brand,
|
color: COLORS.white,
|
||||||
|
backgroundColor: COLORS.brand,
|
||||||
}
|
}
|
||||||
|
|
||||||
handleClick = (e) => {
|
handleClick = (e) => {
|
||||||
@ -47,7 +57,27 @@ export default class Button extends PureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { block, className, disabled, text, to, children, href, outline, color } = this.props
|
const {
|
||||||
|
block,
|
||||||
|
className,
|
||||||
|
disabled,
|
||||||
|
text,
|
||||||
|
to,
|
||||||
|
icon,
|
||||||
|
iconWidth,
|
||||||
|
iconHeight,
|
||||||
|
iconClassName,
|
||||||
|
children,
|
||||||
|
href,
|
||||||
|
outline,
|
||||||
|
color,
|
||||||
|
backgroundColor,
|
||||||
|
underlineOnHover,
|
||||||
|
narrow,
|
||||||
|
...otherProps
|
||||||
|
} = this.props
|
||||||
|
|
||||||
|
const theIcon = !!icon ? <Icon id={icon} width={iconWidth} height={iconWidth} className={iconClassName} /> : undefined
|
||||||
|
|
||||||
// : todo :
|
// : todo :
|
||||||
const classes = cx(className, {
|
const classes = cx(className, {
|
||||||
@ -57,26 +87,43 @@ export default class Button extends PureComponent {
|
|||||||
cursorPointer: 1,
|
cursorPointer: 1,
|
||||||
textAlignCenter: 1,
|
textAlignCenter: 1,
|
||||||
|
|
||||||
backgroundColorBrand: !text && !outline,
|
backgroundColorPrimary: backgroundColor === COLORS.white,
|
||||||
|
backgroundColorBrand: backgroundColor === COLORS.brand,
|
||||||
|
backgroundTransparent: backgroundColor === COLORS.none,
|
||||||
|
|
||||||
// colorPrimary: 1,
|
colorPrimary: color === COLORS.primary,
|
||||||
// colorSecondary: 1,
|
colorSecondary: color === COLORS.secondary,
|
||||||
colorWhite: [].indexOf(color) > -1,
|
colorWhite: color === COLORS.white,
|
||||||
colorBrand: text || [].indexOf(color) > -1,
|
colorBrand: color === COLORS.brand,
|
||||||
|
|
||||||
// borderColorBrand: 1,
|
borderColorBrand: color === COLORS.brand && outline,
|
||||||
// border1PX: 1,
|
border1PX: outline,
|
||||||
|
|
||||||
circle: !text,
|
circle: !text,
|
||||||
|
|
||||||
paddingVertical10PX: !text,
|
paddingVertical5PX: narrow,
|
||||||
|
paddingVertical10PX: !text && !narrow,
|
||||||
paddingHorizontal15PX: !text,
|
paddingHorizontal15PX: !text,
|
||||||
|
|
||||||
width100PC: block,
|
width100PC: block,
|
||||||
|
|
||||||
|
underline_onHover: underlineOnHover,
|
||||||
|
|
||||||
|
backgroundColorBrandDark_onHover: backgroundColor === COLORS.brand,
|
||||||
|
|
||||||
|
backgroundColorBrand_onHover: color === COLORS.brand && outline,
|
||||||
|
colorWhite_onHover: color === COLORS.brand && outline,
|
||||||
})
|
})
|
||||||
|
|
||||||
const tagName = !!href ? 'a' : !!to ? 'NavLink' : 'button'
|
const tagName = !!href ? 'a' : !!to ? 'NavLink' : 'button'
|
||||||
|
|
||||||
|
const theChildren = !!icon ? (
|
||||||
|
<Fragment>
|
||||||
|
{theIcon}
|
||||||
|
{children}
|
||||||
|
</Fragment>
|
||||||
|
) : children
|
||||||
|
|
||||||
return React.createElement(
|
return React.createElement(
|
||||||
tagName,
|
tagName,
|
||||||
{
|
{
|
||||||
@ -86,8 +133,9 @@ export default class Button extends PureComponent {
|
|||||||
to: to || undefined,
|
to: to || undefined,
|
||||||
to: href || undefined,
|
to: href || undefined,
|
||||||
onClick: this.handleClick || undefined,
|
onClick: this.handleClick || undefined,
|
||||||
|
...otherProps
|
||||||
},
|
},
|
||||||
children,
|
theChildren,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
import { injectIntl, defineMessages } from 'react-intl'
|
import { injectIntl, defineMessages } from 'react-intl'
|
||||||
import Icon from './icon'
|
import Icon from './icon'
|
||||||
|
import Button from './button'
|
||||||
|
import Heading from './heading'
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
show: { id: 'column_header.show_settings', defaultMessage: 'Show settings' },
|
show: { id: 'column_header.show_settings', defaultMessage: 'Show settings' },
|
||||||
@ -58,11 +60,13 @@ class ColumnHeader extends PureComponent {
|
|||||||
<Icon className={[_s.marginRight5PX, _s.fillColorBrand].join(' ')} id='back' width='20px' height='20px' />
|
<Icon className={[_s.marginRight5PX, _s.fillColorBrand].join(' ')} id='back' width='20px' height='20px' />
|
||||||
</button>
|
</button>
|
||||||
}
|
}
|
||||||
<h1 role='heading' className={[_s.default, _s.height100PC, _s.justifyContentCenter].join(' ')}>
|
|
||||||
<span className={[_s.default, _s.text, _s.fontSize24PX, _s.fontWeightMedium, _s.colorPrimary].join(' ')}>
|
<div className={[_s.default, _s.height100PC, _s.justifyContentCenter].join(' ')}>
|
||||||
|
<Heading size='h1'>
|
||||||
{title}
|
{title}
|
||||||
</span>
|
</Heading>
|
||||||
</h1>
|
</div>
|
||||||
|
|
||||||
{
|
{
|
||||||
!!actions &&
|
!!actions &&
|
||||||
<div className={[_s.default, _s.backgroundTransparent, _s.flexRow, _s.alignItemsCenter, _s.justifyContentCenter, _s.marginLeftAuto].join(' ')}>
|
<div className={[_s.default, _s.backgroundTransparent, _s.flexRow, _s.alignItemsCenter, _s.justifyContentCenter, _s.marginLeftAuto].join(' ')}>
|
||||||
@ -81,75 +85,6 @@ class ColumnHeader extends PureComponent {
|
|||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
||||||
// const wrapperClassName = classNames('column-header__wrapper', {
|
|
||||||
// 'column-header__wrapper--active': active,
|
|
||||||
// })
|
|
||||||
|
|
||||||
// const buttonClassName = classNames('column-header', {
|
|
||||||
// 'column-header--active': active,
|
|
||||||
// })
|
|
||||||
|
|
||||||
// const btnTitle = formatMessage(collapsed ? messages.show : messages.hide)
|
|
||||||
// const hasTitle = icon && title
|
|
||||||
// const hasChildren = !!children
|
|
||||||
|
|
||||||
// if (!hasChildren && !hasTitle) {
|
|
||||||
// return null
|
|
||||||
// } else if (!hasChildren && hasTitle) {
|
|
||||||
// return (
|
|
||||||
// <div className={wrapperClassName}>
|
|
||||||
// <h1 className={buttonClassName}>
|
|
||||||
// <Icon id={icon} fixedWidth className='column-header__icon' />
|
|
||||||
// {title}
|
|
||||||
// </h1>
|
|
||||||
// </div>
|
|
||||||
// )
|
|
||||||
// }
|
|
||||||
|
|
||||||
// const collapsibleClassName = classNames('column-header__collapsible', {
|
|
||||||
// 'column-header__collapsible--collapsed': collapsed,
|
|
||||||
// })
|
|
||||||
|
|
||||||
// const collapsibleButtonClassName = classNames('column-header__button', {
|
|
||||||
// 'column-header__button--active': !collapsed,
|
|
||||||
// })
|
|
||||||
|
|
||||||
// return (
|
|
||||||
// <div className={wrapperClassName}>
|
|
||||||
// <h1 className={buttonClassName}>
|
|
||||||
// {
|
|
||||||
// hasTitle && (
|
|
||||||
// <Fragment>
|
|
||||||
// <Icon id={icon} fixedWidth className='column-header__icon' />
|
|
||||||
// {title}
|
|
||||||
// </Fragment>
|
|
||||||
// )
|
|
||||||
// }
|
|
||||||
|
|
||||||
// <button
|
|
||||||
// className={collapsibleButtonClassName}
|
|
||||||
// title={btnTitle}
|
|
||||||
// aria-label={btnTitle}
|
|
||||||
// aria-pressed={!collapsed}
|
|
||||||
// onClick={this.handleToggleClick}
|
|
||||||
// >
|
|
||||||
// <Icon id='sliders' />
|
|
||||||
// </button>
|
|
||||||
// </h1>
|
|
||||||
|
|
||||||
// <div className={collapsibleClassName} tabIndex={collapsed ? -1 : null}>
|
|
||||||
// <div className='column-header__collapsible-inner'>
|
|
||||||
// {
|
|
||||||
// !collapsed &&
|
|
||||||
// <div key='extra-content' className='column-header__collapsible__extra'>
|
|
||||||
// {children}
|
|
||||||
// </div>
|
|
||||||
// }
|
|
||||||
// </div>
|
|
||||||
// </div>
|
|
||||||
// </div>
|
|
||||||
// )
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,19 @@
|
|||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||||
import Icon from './icon';
|
import Badge from './badge'
|
||||||
|
import Icon from './icon'
|
||||||
|
|
||||||
export default class DisplayName extends ImmutablePureComponent {
|
export default class DisplayName extends ImmutablePureComponent {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
account: ImmutablePropTypes.map.isRequired,
|
account: ImmutablePropTypes.map.isRequired,
|
||||||
multiline: PropTypes.bool,
|
multiline: PropTypes.bool,
|
||||||
};
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { account } = this.props;
|
const { account, multiline } = this.props
|
||||||
|
|
||||||
|
// : todo :
|
||||||
return (
|
return (
|
||||||
<span className={[_s.default, _s.flexRow, _s.maxWidth100PC, _s.alignItemsCenter].join(' ')}>
|
<span className={[_s.default, _s.flexRow, _s.maxWidth100PC, _s.alignItemsCenter].join(' ')}>
|
||||||
<bdi className={[_s.text, _s.whiteSpaceNoWrap, _s.textOverflowEllipsis].join(' ')}>
|
<bdi className={[_s.text, _s.whiteSpaceNoWrap, _s.textOverflowEllipsis].join(' ')}>
|
||||||
@ -23,15 +25,24 @@ export default class DisplayName extends ImmutablePureComponent {
|
|||||||
{
|
{
|
||||||
account.get('is_verified') &&
|
account.get('is_verified') &&
|
||||||
<Icon id='verified' width='16px' height='16px' className={_s.default} title='Verified Account' />
|
<Icon id='verified' width='16px' height='16px' className={_s.default} title='Verified Account' />
|
||||||
/*<Icon id='verified' width='15px' height='15px' className={[_s.default]} title='PRO' />
|
|
||||||
<Icon id='verified' width='15px' height='15px' className={[_s.default]} title='Donor' />
|
|
||||||
<Icon id='verified' width='15px' height='15px' className={[_s.default]} title='Investor' />*/
|
|
||||||
}
|
}
|
||||||
|
{ /*
|
||||||
|
account.get('is_pro') &&
|
||||||
|
<Icon id='verified' width='16px' height='16px' className={_s.default} title='Gab PRO' />
|
||||||
|
*/ }
|
||||||
|
{ /*
|
||||||
|
account.get('is_donor') &&
|
||||||
|
<Icon id='verified' width='16px' height='16px' className={_s.default} title='Gab Donor' />
|
||||||
|
*/ }
|
||||||
|
{ /*
|
||||||
|
account.get('is_investor') &&
|
||||||
|
<Icon id='verified' width='16px' height='16px' className={_s.default} title='Gab Investor' />
|
||||||
|
*/ }
|
||||||
<span className={[_s.text, _s.displayFlex, _s.flexNormal, _s.flexShrink1, _s.fontSize15PX, _s.overflowWrapBreakWord, _s.textOverflowEllipsis, _s.marginLeft5PX, _s.colorSecondary, _s.fontWeightNormal, _s.lineHeight125].join(' ')}>
|
<span className={[_s.text, _s.displayFlex, _s.flexNormal, _s.flexShrink1, _s.fontSize15PX, _s.overflowWrapBreakWord, _s.textOverflowEllipsis, _s.marginLeft5PX, _s.colorSecondary, _s.fontWeightNormal, _s.lineHeight125].join(' ')}>
|
||||||
@{account.get('acct')}
|
@{account.get('acct')}
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
export default class Divider extends PureComponent {
|
export default class Divider extends PureComponent {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div className={[_s.default, _s.borderBottom1PX, _s.bordercolorSecondary2, _s.marginBottom15PX, _s.width100PC].join(' ')} />
|
<div className={[_s.default, _s.borderBottom1PX, _s.borderColorSecondary2, _s.marginBottom15PX, _s.width100PC].join(' ')} />
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
11
app/javascript/gabsocial/components/dot_text_seperator.js
Normal file
11
app/javascript/gabsocial/components/dot_text_seperator.js
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import Text from './text'
|
||||||
|
|
||||||
|
export default class DotTextSeperator extends PureComponent {
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<Text size='small' color='secondary' className={_s.marginLeft5PX}>•</Text>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -57,7 +57,7 @@ class GroupListItem extends ImmutablePureComponent {
|
|||||||
return (
|
return (
|
||||||
<NavLink
|
<NavLink
|
||||||
to={`/groups/${group.get('id')}`}
|
to={`/groups/${group.get('id')}`}
|
||||||
className={[_s.default, _s.noUnderline, _s.marginTop5PX, _s.overflowHidden, _s.radiusSmall, _s.marginBottom10PX, _s.border1PX, _s.bordercolorSecondary, _s.backgroundSubtle_onHover].join(' ')}
|
className={[_s.default, _s.noUnderline, _s.marginTop5PX, _s.overflowHidden, _s.radiusSmall, _s.marginBottom10PX, _s.border1PX, _s.borderColorSecondary, _s.backgroundSubtle_onHover].join(' ')}
|
||||||
onMouseEnter={() => this.handleOnMouseEnter()}
|
onMouseEnter={() => this.handleOnMouseEnter()}
|
||||||
onMouseLeave={() => this.handleOnMouseLeave()}
|
onMouseLeave={() => this.handleOnMouseLeave()}
|
||||||
>
|
>
|
||||||
|
@ -4,6 +4,7 @@ import ImmutablePureComponent from 'react-immutable-pure-component'
|
|||||||
import { NavLink } from 'react-router-dom'
|
import { NavLink } from 'react-router-dom'
|
||||||
import { shortNumberFormat } from '../utils/numbers'
|
import { shortNumberFormat } from '../utils/numbers'
|
||||||
import Text from './text'
|
import Text from './text'
|
||||||
|
import Button from './button'
|
||||||
|
|
||||||
export default class HashtagItem extends ImmutablePureComponent {
|
export default class HashtagItem extends ImmutablePureComponent {
|
||||||
|
|
||||||
@ -29,15 +30,29 @@ export default class HashtagItem extends ImmutablePureComponent {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<NavLink
|
<NavLink
|
||||||
to='/test'
|
to='/tags/test'
|
||||||
className={[_s.default, _s.noUnderline, _s.backgroundSubtle_onHover, _s.paddingHorizontal15PX, _s.paddingVertical5PX].join(' ')}
|
className={[_s.default, _s.noUnderline, _s.backgroundSubtle_onHover, _s.paddingHorizontal15PX, _s.paddingVertical5PX].join(' ')}
|
||||||
onMouseEnter={() => this.handleOnMouseEnter()}
|
onMouseEnter={() => this.handleOnMouseEnter()}
|
||||||
onMouseLeave={() => this.handleOnMouseLeave()}
|
onMouseLeave={() => this.handleOnMouseLeave()}
|
||||||
>
|
>
|
||||||
<Text color='brand' size='medium' weight='bold' className={_s.paddingVertical2PX}>
|
<div className={[_s.default, _s.flexRow, _s.alignItemsCenter].join(' ')}>
|
||||||
|
<div>
|
||||||
|
<Text color='brand' size='medium' weight='bold' className={[_s.paddingVertical2PX, _s.lineHeight15].join(' ')}>
|
||||||
#randomhashtag
|
#randomhashtag
|
||||||
</Text>
|
</Text>
|
||||||
<Text color='secondary' size='small' underline={hovering} className={_s.paddingVertical2PX}>
|
</div>
|
||||||
|
<Button
|
||||||
|
text
|
||||||
|
backgroundColor='none'
|
||||||
|
color='none'
|
||||||
|
icon='caret-down'
|
||||||
|
iconWidth='8px'
|
||||||
|
iconHeight='8px'
|
||||||
|
iconClassName={_s.fillcolorSecondary}
|
||||||
|
className={_s.marginLeftAuto}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<Text color='secondary' size='small' className={_s.paddingVertical2PX}>
|
||||||
10,240 Gabs
|
10,240 Gabs
|
||||||
</Text>
|
</Text>
|
||||||
</NavLink>
|
</NavLink>
|
||||||
|
@ -13,7 +13,6 @@ const SIZES = {
|
|||||||
|
|
||||||
export default class Heading extends PureComponent {
|
export default class Heading extends PureComponent {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
className: PropTypes.string,
|
|
||||||
children: PropTypes.any,
|
children: PropTypes.any,
|
||||||
size: PropTypes.oneOf(Object.keys(SIZES)),
|
size: PropTypes.oneOf(Object.keys(SIZES)),
|
||||||
}
|
}
|
||||||
@ -23,31 +22,36 @@ export default class Heading extends PureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { className, children, size } = this.props
|
const { children, size } = this.props
|
||||||
|
|
||||||
const classes = cx({
|
const classes = cx({
|
||||||
default: 1,
|
default: 1,
|
||||||
text: 1,
|
text: 1,
|
||||||
|
|
||||||
colorPrimary: [SIZES.h1, SIZES.h3].indexOf(size) > -1,
|
colorPrimary: [SIZES.h1, SIZES.h3].indexOf(size) > -1,
|
||||||
colorSecondary: [SIZES.h2, SIZES.h4].indexOf(size) > -1,
|
colorSecondary: [SIZES.h2, SIZES.h4, SIZES.h5].indexOf(size) > -1,
|
||||||
|
|
||||||
fontSize24PX: size === SIZES.h1,
|
fontSize24PX: size === SIZES.h1,
|
||||||
fontSize19PX: size === SIZES.h2,
|
fontSize19PX: size === SIZES.h2,
|
||||||
fontSize16PX: size === SIZES.h3,
|
fontSize16PX: size === SIZES.h3,
|
||||||
fontSize13PX: size === SIZES.h4,
|
fontSize13PX: size === SIZES.h4,
|
||||||
|
fontSize12PX: size === SIZES.h5,
|
||||||
|
|
||||||
marginTop5PX: [SIZES.h2, SIZES.h4].indexOf(size) > -1,
|
marginTop5PX: [SIZES.h2, SIZES.h4].indexOf(size) > -1,
|
||||||
|
|
||||||
|
lineHeight2: size === SIZES.h5,
|
||||||
|
paddingVertical2PX: size === SIZES.h5,
|
||||||
|
|
||||||
// fontWeightNormal: weight === WEIGHTS.normal,
|
// fontWeightNormal: weight === WEIGHTS.normal,
|
||||||
// fontWeightMedium: weight === WEIGHTS.medium,
|
fontWeightMedium: [SIZES.h1, SIZES.h5].indexOf(size) > -1,
|
||||||
fontWeightBold: [SIZES.h3, SIZES.h4].indexOf(size) > -1
|
fontWeightBold: [SIZES.h3, SIZES.h4].indexOf(size) > -1,
|
||||||
})
|
})
|
||||||
|
|
||||||
return React.createElement(
|
return React.createElement(
|
||||||
size,
|
size,
|
||||||
{
|
{
|
||||||
className: classes,
|
className: classes,
|
||||||
|
role: 'heading',
|
||||||
},
|
},
|
||||||
children,
|
children,
|
||||||
)
|
)
|
||||||
|
@ -1,9 +1,65 @@
|
|||||||
|
import classNames from 'classnames/bind'
|
||||||
|
import Button from './button'
|
||||||
|
import Icon from './icon'
|
||||||
|
|
||||||
|
const cx = classNames.bind(_s)
|
||||||
|
|
||||||
export default class Input extends PureComponent {
|
export default class Input extends PureComponent {
|
||||||
|
static propTypes = {
|
||||||
|
placeholder: PropTypes.string,
|
||||||
|
prependIcon: PropTypes.string,
|
||||||
|
value: PropTypes.string,
|
||||||
|
hasClear: PropTypes.bool,
|
||||||
|
onChange: PropTypes.func,
|
||||||
|
onKeyUp: PropTypes.func,
|
||||||
|
onFocus: PropTypes.func,
|
||||||
|
onBlur: PropTypes.func,
|
||||||
|
onClear: PropTypes.func,
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { children } = this.props
|
const { placeholder, prependIcon, value, hasClear, onChange, onKeyUp, onFocus, onBlur, onClear } = this.props
|
||||||
|
|
||||||
|
const inputClasses = cx({
|
||||||
|
default: 1,
|
||||||
|
text: 1,
|
||||||
|
outlineNone: 1,
|
||||||
|
lineHeight125: 1,
|
||||||
|
displayBlock: 1,
|
||||||
|
paddingVertical10PX: 1,
|
||||||
|
backgroundTransparent: 1,
|
||||||
|
fontSize15PX: 1,
|
||||||
|
flexGrow1: 1,
|
||||||
|
paddingHorizontal5PX: !!prependIcon,
|
||||||
|
paddingLeft15PX: !prependIcon,
|
||||||
|
paddingRight15PX: !hasClear,
|
||||||
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<input />
|
<div className={[_s.default, _s.backgroundColorPrimary, _s.border1PX, _s.borderColorSecondary, _s.flexRow, _s.circle, _s.alignItemsCenter].join(' ')}>
|
||||||
|
{
|
||||||
|
!!prependIcon &&
|
||||||
|
<Icon id={prependIcon} width='16px' height='16px' className={[_s.marginLeft15PX, _s.marginRight5PX].join(' ')} />
|
||||||
|
}
|
||||||
|
|
||||||
|
<input
|
||||||
|
className={inputClasses}
|
||||||
|
type='text'
|
||||||
|
placeholder={placeholder}
|
||||||
|
value={value}
|
||||||
|
onChange={onChange}
|
||||||
|
onKeyUp={onKeyUp}
|
||||||
|
onFocus={onFocus}
|
||||||
|
onBlur={onBlur}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{
|
||||||
|
hasClear &&
|
||||||
|
<div role='button' tabIndex='0' className={'btnClasses'} onClick={onClear}>
|
||||||
|
<Icon id='close' width='10px' height='10px' className={_s.fillColorWhite} aria-label='Clear' />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -19,14 +19,14 @@ export default class DefaultLayout extends PureComponent {
|
|||||||
|
|
||||||
<Sidebar />
|
<Sidebar />
|
||||||
|
|
||||||
<main role='main' className={[_s.default, _s.flexShrink1, _s.flexGrow1, _s.bordercolorSecondary2, _s.borderLeft1PX].join(' ')}>
|
<main role='main' className={[_s.default, _s.flexShrink1, _s.flexGrow1, _s.borderColorSecondary2, _s.borderLeft1PX].join(' ')}>
|
||||||
|
|
||||||
<div className={[_s.default, _s.height53PX, _s.borderBottom1PX, _s.bordercolorSecondary2, _s.backgroundcolorSecondary3, _s.z3, _s.top0, _s.positionFixed].join(' ')}>
|
<div className={[_s.default, _s.height53PX, _s.borderBottom1PX, _s.borderColorSecondary2, _s.backgroundcolorSecondary3, _s.z3, _s.top0, _s.positionFixed].join(' ')}>
|
||||||
<div className={[_s.default, _s.height53PX, _s.paddingLeft15PX, _s.width1015PX, _s.flexRow, _s.justifyContentSpaceBetween].join(' ')}>
|
<div className={[_s.default, _s.height53PX, _s.paddingLeft15PX, _s.width1015PX, _s.flexRow, _s.justifyContentSpaceBetween].join(' ')}>
|
||||||
<div className={[_s.default, _s.width660PX].join(' ')}>
|
<div className={[_s.default, _s.width645PX].join(' ')}>
|
||||||
<ColumnHeader title={title} showBackBtn={showBackBtn} actions={actions} />
|
<ColumnHeader title={title} showBackBtn={showBackBtn} actions={actions} />
|
||||||
</div>
|
</div>
|
||||||
<div className={[_s.default, _s.width325PX].join(' ')}>
|
<div className={[_s.default, _s.width340PX].join(' ')}>
|
||||||
<Search />
|
<Search />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -35,15 +35,15 @@ export default class DefaultLayout extends PureComponent {
|
|||||||
<div className={[_s.default, _s.height53PX].join(' ')}></div>
|
<div className={[_s.default, _s.height53PX].join(' ')}></div>
|
||||||
|
|
||||||
<div className={[_s.default, _s.width1015PX, _s.flexRow, _s.justifyContentSpaceBetween, _s.paddingLeft15PX, _s.paddingVertical15PX].join(' ')}>
|
<div className={[_s.default, _s.width1015PX, _s.flexRow, _s.justifyContentSpaceBetween, _s.paddingLeft15PX, _s.paddingVertical15PX].join(' ')}>
|
||||||
<div className={[_s.default, _s.width660PX, _s.z1].join(' ')}>
|
<div className={[_s.default, _s.width645PX, _s.z1].join(' ')}>
|
||||||
<div className={_s.default}>
|
<div className={_s.default}>
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={[_s.default, _s.width325PX].join(' ')}>
|
<div className={[_s.default, _s.width340PX].join(' ')}>
|
||||||
<Sticky top={73} enabled>
|
<Sticky top={73} enabled>
|
||||||
<div className={[_s.default, _s.width325PX].join(' ')}>
|
<div className={[_s.default, _s.width340PX].join(' ')}>
|
||||||
{layout}
|
{layout}
|
||||||
</div>
|
</div>
|
||||||
</Sticky>
|
</Sticky>
|
||||||
|
@ -16,7 +16,7 @@ export default class ProfileLayout extends PureComponent {
|
|||||||
|
|
||||||
<Sidebar />
|
<Sidebar />
|
||||||
|
|
||||||
<main role='main' className={[_s.default, _s.flexShrink1, _s.flexGrow1, _s.bordercolorSecondary2, _s.borderLeft1PX].join(' ')}>
|
<main role='main' className={[_s.default, _s.flexShrink1, _s.flexGrow1, _s.borderColorSecondary2, _s.borderLeft1PX].join(' ')}>
|
||||||
|
|
||||||
<div className={[_s.default, _s.height350PX, _s.width100PC].join(' ')}>
|
<div className={[_s.default, _s.height350PX, _s.width100PC].join(' ')}>
|
||||||
<img
|
<img
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import moment from 'moment'
|
import moment from 'moment'
|
||||||
import classNames from 'classnames/bind'
|
|
||||||
import {
|
import {
|
||||||
FormattedMessage,
|
FormattedMessage,
|
||||||
defineMessages,
|
defineMessages,
|
||||||
@ -11,8 +10,11 @@ import {
|
|||||||
source_url,
|
source_url,
|
||||||
me,
|
me,
|
||||||
} from '../initial_state'
|
} from '../initial_state'
|
||||||
|
import Text from './text'
|
||||||
|
import Button from './button'
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
|
help: { id: 'getting_started.help', defaultMessage: 'Help' },
|
||||||
invite: { id: 'getting_started.invite', defaultMessage: 'Invite people' },
|
invite: { id: 'getting_started.invite', defaultMessage: 'Invite people' },
|
||||||
hotkeys: { id: 'navigation_bar.keyboard_shortcuts', defaultMessage: 'Hotkeys' },
|
hotkeys: { id: 'navigation_bar.keyboard_shortcuts', defaultMessage: 'Hotkeys' },
|
||||||
security: { id: 'getting_started.security', defaultMessage: 'Security' },
|
security: { id: 'getting_started.security', defaultMessage: 'Security' },
|
||||||
@ -20,7 +22,7 @@ const messages = defineMessages({
|
|||||||
developers: { id: 'getting_started.developers', defaultMessage: 'Developers' },
|
developers: { id: 'getting_started.developers', defaultMessage: 'Developers' },
|
||||||
terms: { id: 'getting_started.terms', defaultMessage: 'Terms of Service' },
|
terms: { id: 'getting_started.terms', defaultMessage: 'Terms of Service' },
|
||||||
dmca: { id: 'getting_started.dmca', defaultMessage: 'DMCA' },
|
dmca: { id: 'getting_started.dmca', defaultMessage: 'DMCA' },
|
||||||
terms: { id: 'getting_started.terms_of_sale', defaultMessage: 'Terms of Sale' },
|
salesTerms: { id: 'getting_started.terms_of_sale', defaultMessage: 'Terms of Sale' },
|
||||||
privacy: { id: 'getting_started.privacy', defaultMessage: 'Privacy Policy' },
|
privacy: { id: 'getting_started.privacy', defaultMessage: 'Privacy Policy' },
|
||||||
logout: { id: 'navigation_bar.logout', defaultMessage: 'Logout' },
|
logout: { id: 'navigation_bar.logout', defaultMessage: 'Logout' },
|
||||||
})
|
})
|
||||||
@ -31,9 +33,6 @@ const mapDispatchToProps = (dispatch) => ({
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const cx = classNames.bind(_s)
|
|
||||||
const currentYear = moment().format('YYYY')
|
|
||||||
|
|
||||||
export default @connect(null, mapDispatchToProps)
|
export default @connect(null, mapDispatchToProps)
|
||||||
@injectIntl
|
@injectIntl
|
||||||
class LinkFooter extends PureComponent {
|
class LinkFooter extends PureComponent {
|
||||||
@ -43,29 +42,18 @@ class LinkFooter extends PureComponent {
|
|||||||
onOpenHotkeys: PropTypes.func.isRequired,
|
onOpenHotkeys: PropTypes.func.isRequired,
|
||||||
}
|
}
|
||||||
|
|
||||||
state = {
|
|
||||||
hoveringItemIndex: null,
|
|
||||||
}
|
|
||||||
|
|
||||||
onMouseEnterLinkFooterItem = (i) => {
|
|
||||||
this.setState({
|
|
||||||
hoveringItemIndex: i,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
onMouseLeaveLinkFooterItem = () => {
|
|
||||||
this.setState({
|
|
||||||
hoveringItemIndex: null,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { onOpenHotkeys, intl } = this.props
|
const { onOpenHotkeys, intl } = this.props
|
||||||
const { hoveringItemIndex } = this.state
|
|
||||||
|
const currentYear = moment().format('YYYY')
|
||||||
|
|
||||||
const linkFooterItems = [
|
const linkFooterItems = [
|
||||||
{
|
{
|
||||||
to: '#',
|
to: '/help',
|
||||||
|
text: intl.formatMessage(messages.help),
|
||||||
|
requiresUser: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
onClick: onOpenHotkeys,
|
onClick: onOpenHotkeys,
|
||||||
text: intl.formatMessage(messages.hotkeys),
|
text: intl.formatMessage(messages.hotkeys),
|
||||||
requiresUser: true,
|
requiresUser: true,
|
||||||
@ -93,7 +81,7 @@ class LinkFooter extends PureComponent {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
to: '/about/sales',
|
to: '/about/sales',
|
||||||
text: intl.formatMessage(messages.terms),
|
text: intl.formatMessage(messages.salesTerms),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
to: '/about/privacy',
|
to: '/about/privacy',
|
||||||
@ -108,64 +96,50 @@ class LinkFooter extends PureComponent {
|
|||||||
]
|
]
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={[_s.default, _s.paddingHorizontal10PX].join(' ')}>
|
<div className={[_s.default, _s.paddingHorizontal10PX, _s.marginBottom15PX].join(' ')}>
|
||||||
<nav aria-label='Footer' role='navigation' className={[_s.default, _s.flexWrap, _s.flexRow].join(' ')}>
|
<nav aria-label='Footer' role='navigation' className={[_s.default, _s.flexWrap, _s.flexRow].join(' ')}>
|
||||||
{
|
{
|
||||||
linkFooterItems.map((linkFooterItem, i) => {
|
linkFooterItems.map((linkFooterItem, i) => {
|
||||||
if (linkFooterItem.requiresUser && !me) return null
|
if (linkFooterItem.requiresUser && !me) return null
|
||||||
const classes = cx({
|
|
||||||
default: 1,
|
|
||||||
fontSize13PX: 1,
|
|
||||||
text: 1,
|
|
||||||
marginVertical5PX: 1,
|
|
||||||
paddingRight15PX: 1,
|
|
||||||
cursorPointer: 1,
|
|
||||||
backgroundTransparent: 1,
|
|
||||||
colorSecondary: i !== hoveringItemIndex,
|
|
||||||
noUnderline: i !== hoveringItemIndex,
|
|
||||||
colorPrimary: i === hoveringItemIndex,
|
|
||||||
underline: i === hoveringItemIndex,
|
|
||||||
})
|
|
||||||
|
|
||||||
if (linkFooterItem.onClick) {
|
|
||||||
return (
|
|
||||||
<button
|
|
||||||
key={`link-footer-item-${i}`}
|
|
||||||
data-method={linkFooterItem.logout ? 'delete' : null}
|
|
||||||
onClick={linkFooterItem.onClick || null}
|
|
||||||
onMouseEnter={() => this.onMouseEnterLinkFooterItem(i)}
|
|
||||||
onMouseLeave={() => this.onMouseLeaveLinkFooterItem(i)}
|
|
||||||
className={classes}
|
|
||||||
>
|
|
||||||
{linkFooterItem.text}
|
|
||||||
</button>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<a
|
<Button
|
||||||
|
text
|
||||||
|
underlineOnHover
|
||||||
|
color='none'
|
||||||
|
backgroundColor='none'
|
||||||
key={`link-footer-item-${i}`}
|
key={`link-footer-item-${i}`}
|
||||||
href={linkFooterItem.to}
|
href={linkFooterItem.to}
|
||||||
data-method={linkFooterItem.logout ? 'delete' : null}
|
data-method={linkFooterItem.logout ? 'delete' : null}
|
||||||
onMouseEnter={() => this.onMouseEnterLinkFooterItem(i)}
|
onClick={linkFooterItem.onClick || null}
|
||||||
onMouseLeave={() => this.onMouseLeaveLinkFooterItem(i)}
|
className={[_s.marginVertical5PX, _s.paddingRight15PX].join(' ')}
|
||||||
className={classes}
|
|
||||||
>
|
>
|
||||||
|
<Text size='small' color='secondary'>
|
||||||
{linkFooterItem.text}
|
{linkFooterItem.text}
|
||||||
</a>
|
</Text>
|
||||||
|
</Button>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
<span className={[_s.default, _s.text, _s.fontSize13PX, _s.colorSecondary, _s.marginVertical5PX].join(' ')}>© {currentYear} Gab AI, Inc.</span>
|
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<p className={[_s.default, _s.text, _s.fontSize13PX, _s.colorSecondary, _s.marginTop10PX, _s.marginBottom15PX].join(' ')}>
|
<Text size='small' color='secondary' className={_s.marginTop10PX}>
|
||||||
|
© {currentYear} Gab AI, Inc.
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<Text size='small' color='secondary' tagName='p' className={_s.marginTop10PX}>
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
id='getting_started.open_source_notice'
|
id='getting_started.open_source_notice'
|
||||||
defaultMessage='Gab Social is open source software. You can contribute or report issues on our self-hosted GitLab at {gitlab}.'
|
defaultMessage='Gab Social is open source software. You can contribute or report issues on our self-hosted GitLab at {gitlab}.'
|
||||||
values={{ gitlab: <a href={source_url} className={[_s.inherit].join(' ')} rel='noopener' target='_blank'>{repository}</a> }}
|
values={{
|
||||||
|
gitlab: (
|
||||||
|
<a href={source_url} className={_s.inherit} rel='noopener' target='_blank'>
|
||||||
|
{repository}
|
||||||
|
</a>
|
||||||
|
)
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</p>
|
</Text>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
38
app/javascript/gabsocial/components/list.js
Normal file
38
app/javascript/gabsocial/components/list.js
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
import ScrollableList from './scrollable_list'
|
||||||
|
import ListItem from './list_item'
|
||||||
|
|
||||||
|
export default class List extends PureComponent {
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
items: PropTypes.array,
|
||||||
|
scrollKey: PropTypes.string,
|
||||||
|
emptyMessage: PropTypes.any,
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { items, scrollKey, emptyMessage } = this.props
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={[_s.default, _s.backgroundColorPrimary, _s.radiusSmall, _s.overflowHidden, _s.border1PX, _s.borderColorSecondary].join(' ')}>
|
||||||
|
<ScrollableList
|
||||||
|
scrollKey={scrollKey}
|
||||||
|
emptyMessage={emptyMessage}
|
||||||
|
>
|
||||||
|
{
|
||||||
|
items.map((item, i) => {
|
||||||
|
return (
|
||||||
|
<ListItem
|
||||||
|
key={`list-item-${i}`}
|
||||||
|
to={item.to}
|
||||||
|
title={item.title}
|
||||||
|
isLast={items.length - 1 === i}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</ScrollableList>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
44
app/javascript/gabsocial/components/list_item.js
Normal file
44
app/javascript/gabsocial/components/list_item.js
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
import { NavLink } from 'react-router-dom'
|
||||||
|
import classNames from 'classnames/bind'
|
||||||
|
import Icon from './icon'
|
||||||
|
|
||||||
|
const cx = classNames.bind(_s)
|
||||||
|
|
||||||
|
export default class ListItem extends PureComponent {
|
||||||
|
static propTypes = {
|
||||||
|
isLast: PropTypes.bool,
|
||||||
|
to: PropTypes.string,
|
||||||
|
title: PropTypes.string,
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { to, title, 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={to} className={containerClasses} >
|
||||||
|
<span className={[_s.default, _s.text, _s.colorPrimary, _s.fontSize14PX].join(' ')}>
|
||||||
|
{title}
|
||||||
|
</span>
|
||||||
|
<Icon
|
||||||
|
id='angle-right'
|
||||||
|
width='10px'
|
||||||
|
height='10px'
|
||||||
|
className={[_s.marginLeftAuto, _s.fillColorBlack].join(' ')}
|
||||||
|
/>
|
||||||
|
</NavLink>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -517,7 +517,7 @@ class MediaGallery extends PureComponent {
|
|||||||
default: 1,
|
default: 1,
|
||||||
displayBlock: 1,
|
displayBlock: 1,
|
||||||
overflowHidden: 1,
|
overflowHidden: 1,
|
||||||
bordercolorSecondary: size === 1,
|
borderColorSecondary: size === 1,
|
||||||
borderTop1PX: size === 1,
|
borderTop1PX: size === 1,
|
||||||
borderBottom1PX: size === 1,
|
borderBottom1PX: size === 1,
|
||||||
paddingHorizontal5PX: size > 1,
|
paddingHorizontal5PX: size > 1,
|
||||||
|
@ -31,24 +31,17 @@ class GroupSidebarPanel extends ImmutablePureComponent {
|
|||||||
return (
|
return (
|
||||||
<PanelLayout
|
<PanelLayout
|
||||||
title={intl.formatMessage(messages.title)}
|
title={intl.formatMessage(messages.title)}
|
||||||
buttonTitle={intl.formatMessage(messages.all)}
|
headerButtonTitle={intl.formatMessage(messages.all)}
|
||||||
buttonTo='/groups/browse/member'
|
headerButtonTo='/groups/browse/member'
|
||||||
|
footerButtonTitle={count > 6 ? intl.formatMessage(messages.show_all) : undefined}
|
||||||
|
footerButtonTo={count > 6 ? '/groups/browse/member' : undefined}
|
||||||
>
|
>
|
||||||
<div className={_s.default}>
|
<div className={_s.default}>
|
||||||
{
|
{
|
||||||
groupIds.slice(0, 6).map(groupId => (
|
groupIds.slice(0, 6).map(groupId => (
|
||||||
<GroupListItem
|
<GroupListItem key={`group-panel-item-${groupId}`} id={groupId} />
|
||||||
key={`group-panel-item-${groupId}`}
|
|
||||||
id={groupId}
|
|
||||||
/>
|
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
{
|
|
||||||
count > 6 &&
|
|
||||||
<Button to='/groups/browse/member' block text>
|
|
||||||
{intl.formatMessage(messages.show_all)}
|
|
||||||
</Button>
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
</PanelLayout>
|
</PanelLayout>
|
||||||
)
|
)
|
||||||
|
@ -44,7 +44,12 @@ class HashtagsPanel extends ImmutablePureComponent {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PanelLayout title={intl.formatMessage(messages.title)} noPadding>
|
<PanelLayout
|
||||||
|
noPadding
|
||||||
|
title={intl.formatMessage(messages.title)}
|
||||||
|
footerButtonTitle={intl.formatMessage(messages.show_all)}
|
||||||
|
footerButtonTo='/explore'
|
||||||
|
>
|
||||||
<div className={_s.default}>
|
<div className={_s.default}>
|
||||||
{ /* hashtags && hashtags.map(hashtag => (
|
{ /* hashtags && hashtags.map(hashtag => (
|
||||||
<HashtagingItem key={hashtag.get('name')} hashtag={hashtag} />
|
<HashtagingItem key={hashtag.get('name')} hashtag={hashtag} />
|
||||||
@ -55,9 +60,6 @@ class HashtagsPanel extends ImmutablePureComponent {
|
|||||||
<HashtagItem />
|
<HashtagItem />
|
||||||
<HashtagItem />
|
<HashtagItem />
|
||||||
</div>
|
</div>
|
||||||
<Button to='/groups/browse/member' block text>
|
|
||||||
{intl.formatMessage(messages.show_all)}
|
|
||||||
</Button>
|
|
||||||
</PanelLayout>
|
</PanelLayout>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -40,8 +40,8 @@ class ListDetailsPanel extends ImmutablePureComponent {
|
|||||||
return (
|
return (
|
||||||
<PanelLayout
|
<PanelLayout
|
||||||
title={intl.formatMessage(messages.title, { count })}
|
title={intl.formatMessage(messages.title, { count })}
|
||||||
buttonTitle={intl.formatMessage(messages.show_all)}
|
headerButtonTitle={intl.formatMessage(messages.show_all)}
|
||||||
buttonAction={this.handleShowAllLists}
|
headerButtonAction={this.handleShowAllLists}
|
||||||
>
|
>
|
||||||
<div className={_s.default}>
|
<div className={_s.default}>
|
||||||
|
|
||||||
|
@ -1,39 +1,57 @@
|
|||||||
import Heading from '../heading'
|
import Heading from '../heading'
|
||||||
import Button from '../button'
|
import Button from '../button'
|
||||||
|
import Text from '../text'
|
||||||
|
|
||||||
export default class PanelLayout extends PureComponent {
|
export default class PanelLayout extends PureComponent {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
title: PropTypes.string,
|
title: PropTypes.string,
|
||||||
subtitle: PropTypes.string,
|
subtitle: PropTypes.string,
|
||||||
children: PropTypes.node,
|
children: PropTypes.node,
|
||||||
buttonTitle: PropTypes.string,
|
headerButtonTitle: PropTypes.string,
|
||||||
buttonAction: PropTypes.func,
|
headerButtonAction: PropTypes.func,
|
||||||
buttonTo: PropTypes.func,
|
headerButtonTo: PropTypes.func,
|
||||||
|
footerButtonTitle: PropTypes.string,
|
||||||
|
footerButtonAction: PropTypes.func,
|
||||||
|
footerButtonTo: PropTypes.func,
|
||||||
noPadding: PropTypes.bool,
|
noPadding: PropTypes.bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { title, subtitle, buttonTitle, buttonAction, buttonTo, noPadding, children } = this.props
|
const {
|
||||||
|
title,
|
||||||
|
subtitle,
|
||||||
|
headerButtonTitle,
|
||||||
|
headerButtonAction,
|
||||||
|
headerButtonTo,
|
||||||
|
footerButtonTitle,
|
||||||
|
footerButtonAction,
|
||||||
|
footerButtonTo,
|
||||||
|
noPadding,
|
||||||
|
children,
|
||||||
|
} = this.props
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<aside className={[_s.default, _s.backgroundWhite, _s.overflowHidden, _s.radiusSmall, _s.marginBottom15PX, _s.bordercolorSecondary, _s.border1PX].join(' ')}>
|
<aside className={[_s.default, _s.backgroundColorPrimary, _s.overflowHidden, _s.radiusSmall, _s.marginBottom15PX, _s.borderColorSecondary, _s.border1PX].join(' ')}>
|
||||||
{
|
{
|
||||||
(title || subtitle) &&
|
(title || subtitle) &&
|
||||||
<div className={[_s.default, _s.paddingHorizontal15PX, _s.paddingVertical10PX, _s.bordercolorSecondary, _s.borderBottom1PX].join(' ')}>
|
<div className={[_s.default, _s.paddingHorizontal15PX, _s.paddingVertical10PX, _s.borderColorSecondary, _s.borderBottom1PX].join(' ')}>
|
||||||
<div className={[_s.default, _s.flexRow, _s.alignItemsCenter].join(' ')}>
|
<div className={[_s.default, _s.flexRow, _s.alignItemsCenter].join(' ')}>
|
||||||
<Heading size='h3'>
|
<Heading size='h3'>
|
||||||
{title}
|
{title}
|
||||||
</Heading>
|
</Heading>
|
||||||
{
|
{
|
||||||
(!!buttonTitle && (!!buttonAction || !!buttonTo)) &&
|
(!!headerButtonTitle && (!!headerButtonAction || !!headerButtonTo)) &&
|
||||||
<div className={[_s.default, _s.marginLeftAuto].join(' ')}>
|
<div className={[_s.default, _s.marginLeftAuto].join(' ')}>
|
||||||
<Button
|
<Button
|
||||||
text
|
text
|
||||||
to={buttonTo}
|
backgroundColor='none'
|
||||||
onClick={buttonAction}
|
color='brand'
|
||||||
className={[_s.default, _s.cursorPointer, _s.fontWeightBold, _s.text, _s.colorBrand, _s.fontSize13PX, _s.noUnderline].join(' ')}
|
to={headerButtonTo}
|
||||||
|
onClick={headerButtonAction}
|
||||||
>
|
>
|
||||||
{buttonTitle}
|
<Text size='small' color='inherit' weight='bold'>
|
||||||
|
{headerButtonTitle}
|
||||||
|
</Text>
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
@ -57,6 +75,24 @@ export default class PanelLayout extends PureComponent {
|
|||||||
{
|
{
|
||||||
noPadding && children
|
noPadding && children
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
(!!footerButtonTitle && (!!footerButtonAction || !!footerButtonTo)) &&
|
||||||
|
<div className={[_s.default, _s.borderColorSecondary, _s.borderTop1PX].join(' ')}>
|
||||||
|
<Button
|
||||||
|
text
|
||||||
|
color='none'
|
||||||
|
backgroundColor='none'
|
||||||
|
to={footerButtonTo}
|
||||||
|
onClick={footerButtonAction}
|
||||||
|
className={[_s.paddingHorizontal15PX, _s.paddingVertical15PX, _s.backgroundSubtle_onHover].join(' ')}
|
||||||
|
>
|
||||||
|
<Text color='brand' align='left' size='medium'>
|
||||||
|
{footerButtonTitle}
|
||||||
|
</Text>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
</aside>
|
</aside>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -2,11 +2,12 @@ import { injectIntl, defineMessages } from 'react-intl'
|
|||||||
// import { fetchTrends } from '../../actions/trends'
|
// import { fetchTrends } from '../../actions/trends'
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||||
import TrendingItem from '../../components/trending_item'
|
import TrendingItem from '../trends_panel_item'
|
||||||
import PanelLayout from './panel_layout'
|
import PanelLayout from './panel_layout'
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
title: { id:'trends.title', defaultMessage: 'Trending right now' },
|
title: { id:'trends.title', defaultMessage: 'Trending right now' },
|
||||||
|
show_all: { id: 'groups.sidebar-panel.show_all', defaultMessage: 'Show all' },
|
||||||
})
|
})
|
||||||
|
|
||||||
// const mapStateToProps = state => ({
|
// const mapStateToProps = state => ({
|
||||||
@ -43,7 +44,12 @@ class TrendsPanel extends ImmutablePureComponent {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PanelLayout title={intl.formatMessage(messages.title)}>
|
<PanelLayout
|
||||||
|
noPadding
|
||||||
|
title={intl.formatMessage(messages.title)}
|
||||||
|
footerButtonTitle={intl.formatMessage(messages.show_all)}
|
||||||
|
footerButtonTo='/explore'
|
||||||
|
>
|
||||||
<div className={_s.default}>
|
<div className={_s.default}>
|
||||||
{ /* trends && trends.map(hashtag => (
|
{ /* trends && trends.map(hashtag => (
|
||||||
<TrendingItem key={hashtag.get('name')} hashtag={hashtag} />
|
<TrendingItem key={hashtag.get('name')} hashtag={hashtag} />
|
||||||
@ -52,7 +58,6 @@ class TrendsPanel extends ImmutablePureComponent {
|
|||||||
<TrendingItem />
|
<TrendingItem />
|
||||||
<TrendingItem />
|
<TrendingItem />
|
||||||
<TrendingItem />
|
<TrendingItem />
|
||||||
<TrendingItem />
|
|
||||||
</div>
|
</div>
|
||||||
</PanelLayout>
|
</PanelLayout>
|
||||||
)
|
)
|
||||||
|
@ -8,6 +8,7 @@ import PanelLayout from './panel_layout';
|
|||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
dismissSuggestion: { id: 'suggestions.dismiss', defaultMessage: 'Dismiss suggestion' },
|
dismissSuggestion: { id: 'suggestions.dismiss', defaultMessage: 'Dismiss suggestion' },
|
||||||
title: { id: 'who_to_follow.title', defaultMessage: 'Who to Follow' },
|
title: { id: 'who_to_follow.title', defaultMessage: 'Who to Follow' },
|
||||||
|
show_more: { id: 'who_to_follow.more', defaultMessage: 'Show more' },
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = state => ({
|
||||||
@ -47,7 +48,11 @@ class WhoToFollowPanel extends ImmutablePureComponent {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PanelLayout title={intl.formatMessage(messages.title)}>
|
<PanelLayout
|
||||||
|
title={intl.formatMessage(messages.title)}
|
||||||
|
footerButtonTitle={intl.formatMessage(messages.show_more)}
|
||||||
|
footerButtonTo='/explore'
|
||||||
|
>
|
||||||
<div className={_s.default}>
|
<div className={_s.default}>
|
||||||
{suggestions && suggestions.map(accountId => (
|
{suggestions && suggestions.map(accountId => (
|
||||||
<AccountContainer
|
<AccountContainer
|
||||||
|
105
app/javascript/gabsocial/components/search.js
Normal file
105
app/javascript/gabsocial/components/search.js
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
import classNames from 'classnames/bind'
|
||||||
|
import Overlay from 'react-overlays/lib/Overlay'
|
||||||
|
import {
|
||||||
|
changeSearch,
|
||||||
|
clearSearch,
|
||||||
|
submitSearch,
|
||||||
|
showSearch,
|
||||||
|
} from '../actions/search'
|
||||||
|
import SearchPopout from './search_popout'
|
||||||
|
import Input from './input'
|
||||||
|
|
||||||
|
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)
|
||||||
|
class Search extends PureComponent {
|
||||||
|
|
||||||
|
static contextTypes = {
|
||||||
|
router: PropTypes.object.isRequired,
|
||||||
|
}
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
value: PropTypes.string.isRequired,
|
||||||
|
submitted: PropTypes.bool,
|
||||||
|
onShow: PropTypes.func.isRequired,
|
||||||
|
openInRoute: PropTypes.bool,
|
||||||
|
onChange: PropTypes.func.isRequired,
|
||||||
|
onKeyUp: PropTypes.func.isRequired,
|
||||||
|
handleSubmit: PropTypes.func,
|
||||||
|
withOverlay: PropTypes.bool,
|
||||||
|
handleClear: PropTypes.func.isRequired,
|
||||||
|
}
|
||||||
|
|
||||||
|
state = {
|
||||||
|
expanded: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
handleChange = (e) => {
|
||||||
|
this.props.onChange(e.target.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
handleFocus = () => {
|
||||||
|
this.setState({ expanded: true })
|
||||||
|
this.props.onShow()
|
||||||
|
}
|
||||||
|
|
||||||
|
handleBlur = () => {
|
||||||
|
this.setState({ expanded: false })
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { value, submitted, onKeyUp, handleClear, handleSubmit, withOverlay } = this.props
|
||||||
|
const { expanded } = this.state
|
||||||
|
|
||||||
|
const hasValue = value ? value.length > 0 || submitted : 0
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={[_s.default, _s.justifyContentCenter, _s.height53PX].join(' ')}>
|
||||||
|
<Input
|
||||||
|
hasClear
|
||||||
|
value={value}
|
||||||
|
prependIcon='search'
|
||||||
|
placeholder='Search on Gab...'
|
||||||
|
onChange={this.handleChange}
|
||||||
|
onKeyUp={onKeyUp}
|
||||||
|
onFocus={this.handleFocus}
|
||||||
|
onBlur={this.handleBlur}
|
||||||
|
onClear={handleClear}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{
|
||||||
|
withOverlay &&
|
||||||
|
<Overlay show={expanded && !hasValue} placement='bottom' target={this}>
|
||||||
|
<SearchPopout />
|
||||||
|
</Overlay>
|
||||||
|
}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1 +0,0 @@
|
|||||||
export { default } from './search';
|
|
@ -1,93 +0,0 @@
|
|||||||
import classNames from 'classnames/bind';
|
|
||||||
import Overlay from 'react-overlays/lib/Overlay';
|
|
||||||
import Icon from '../icon';
|
|
||||||
import SearchPopout from '../search_popout';
|
|
||||||
|
|
||||||
const cx = classNames.bind(_s)
|
|
||||||
|
|
||||||
export default class Search extends PureComponent {
|
|
||||||
|
|
||||||
static contextTypes = {
|
|
||||||
router: PropTypes.object.isRequired,
|
|
||||||
};
|
|
||||||
|
|
||||||
static propTypes = {
|
|
||||||
// value: PropTypes.string.isRequired,
|
|
||||||
submitted: PropTypes.bool,
|
|
||||||
// onShow: PropTypes.func.isRequired,
|
|
||||||
openInRoute: PropTypes.bool,
|
|
||||||
// placeholder: PropTypes.string.isRequired,
|
|
||||||
searchTitle: PropTypes.string,
|
|
||||||
// onChange: PropTypes.func.isRequired,
|
|
||||||
// onKeyUp: PropTypes.func.isRequired,
|
|
||||||
handleSubmit: PropTypes.func,
|
|
||||||
withOverlay: PropTypes.bool,
|
|
||||||
// handleClear: PropTypes.func.isRequired,
|
|
||||||
};
|
|
||||||
|
|
||||||
state = {
|
|
||||||
expanded: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
handleFocus = () => {
|
|
||||||
this.setState({ expanded: true });
|
|
||||||
this.props.onShow();
|
|
||||||
}
|
|
||||||
|
|
||||||
handleBlur = () => {
|
|
||||||
this.setState({ expanded: false });
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { value, submitted, placeholder, searchTitle, onKeyUp, handleClear, handleSubmit, withOverlay, onChange } = this.props;
|
|
||||||
const { expanded } = this.state;
|
|
||||||
|
|
||||||
const hasValue = value ? value.length > 0 || submitted : 0;
|
|
||||||
|
|
||||||
const btnClasses = cx({
|
|
||||||
default: 1,
|
|
||||||
cursorPointer: 1,
|
|
||||||
marginRight5PX: 1,
|
|
||||||
paddingHorizontal10PX: 1,
|
|
||||||
paddingVertical10PX: 1,
|
|
||||||
circle: 1,
|
|
||||||
backgroundColorBrandLight: 1,
|
|
||||||
displayNone: !hasValue,
|
|
||||||
})
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={[_s.default, _s.justifyContentCenter, _s.height53PX].join(' ')}>
|
|
||||||
<div className={[_s.default, _s.backgroundWhite, _s.border1PX, _s.bordercolorSecondary, _s.flexRow, _s.circle, _s.alignItemsCenter].join(' ')}>
|
|
||||||
<Icon id='search' width='16px' height='16px' className={[_s.default, _s.marginLeft15PX, _s.marginRight10PX].join(' ')} />
|
|
||||||
<input
|
|
||||||
className={[_s.default, _s.text, _s.outlineFocusBrand, _s.lineHeight125, _s.displayBlock, _s.paddingVertical10PX, _s.paddingHorizontal10PX, _s.backgroundTransparent, _s.fontSize15PX, _s.flexGrow1].join(' ')}
|
|
||||||
type='text'
|
|
||||||
placeholder='Search on Gab...'
|
|
||||||
value={value}
|
|
||||||
onChange={onChange}
|
|
||||||
onKeyUp={onKeyUp}
|
|
||||||
onFocus={this.handleFocus}
|
|
||||||
onBlur={this.handleBlur}
|
|
||||||
/>
|
|
||||||
<div role='button' tabIndex='0' className={btnClasses} onClick={handleClear}>
|
|
||||||
<Icon id='close' width='10px' height='10px' className={_s.fillColorWhite} aria-label={placeholder} />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{
|
|
||||||
withOverlay &&
|
|
||||||
<Overlay show={expanded && !hasValue} placement='bottom' target={this}>
|
|
||||||
<SearchPopout />
|
|
||||||
</Overlay>
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
(searchTitle && handleSubmit) &&
|
|
||||||
<Button onClick={handleSubmit}>{intl.formatMessage(messages.searchTitle)}</Button>
|
|
||||||
}
|
|
||||||
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,69 +0,0 @@
|
|||||||
.search {
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
&__input {
|
|
||||||
display: block;
|
|
||||||
padding: 7px 30px 6px 10px;
|
|
||||||
@include search-input();
|
|
||||||
}
|
|
||||||
|
|
||||||
&__icon {
|
|
||||||
&::-moz-focus-inner {
|
|
||||||
border: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
&::-moz-focus-inner,
|
|
||||||
&:focus {
|
|
||||||
outline: 0 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.fa {
|
|
||||||
cursor: default;
|
|
||||||
display: inline-block;
|
|
||||||
position: absolute;
|
|
||||||
top: 8px;
|
|
||||||
right: 6px;
|
|
||||||
z-index: 2;
|
|
||||||
font-size: 16px;
|
|
||||||
color: $gab-placeholder-accent;
|
|
||||||
opacity: 0;
|
|
||||||
pointer-events: none;
|
|
||||||
|
|
||||||
@include size(18px);
|
|
||||||
|
|
||||||
&.active {
|
|
||||||
pointer-events: auto;
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.fa-search.active {
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.fa-times-circle {
|
|
||||||
cursor: pointer;
|
|
||||||
font-size: 17px;
|
|
||||||
color: $gab-alert-red;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: lighten($gab-alert-red, 7%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (max-width: 630px) and (max-height: 400px) {
|
|
||||||
will-change: margin-top;
|
|
||||||
transition: margin-top 400ms 100ms;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (min-width: 360px) {
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (min-width: 895px) {
|
|
||||||
.search-page .search {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
@ -275,7 +275,7 @@ class HeaderMenuItem extends PureComponent {
|
|||||||
alignItemsCenter: 1,
|
alignItemsCenter: 1,
|
||||||
radiusSmall: 1,
|
radiusSmall: 1,
|
||||||
// border1PX: shouldShowActive,
|
// border1PX: shouldShowActive,
|
||||||
// bordercolorSecondary: shouldShowActive,
|
// borderColorSecondary: shouldShowActive,
|
||||||
backgroundSubtle2: shouldShowActive,
|
backgroundSubtle2: shouldShowActive,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ export default class SidebarSectionItem extends PureComponent {
|
|||||||
alignItemsCenter: 1,
|
alignItemsCenter: 1,
|
||||||
radiusSmall: 1,
|
radiusSmall: 1,
|
||||||
// border1PX: shouldShowActive,
|
// border1PX: shouldShowActive,
|
||||||
// bordercolorSecondary: shouldShowActive,
|
// borderColorSecondary: shouldShowActive,
|
||||||
backgroundSubtle2: shouldShowActive,
|
backgroundSubtle2: shouldShowActive,
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -86,7 +86,7 @@ export default class SidebarSectionItem extends PureComponent {
|
|||||||
to={to}
|
to={to}
|
||||||
onMouseEnter={() => this.handleOnMouseEnter()}
|
onMouseEnter={() => this.handleOnMouseEnter()}
|
||||||
onMouseLeave={() => this.handleOnMouseLeave()}
|
onMouseLeave={() => this.handleOnMouseLeave()}
|
||||||
className={[_s.default, _s.noUnderline, _s.cursorPointer, _s.width100PC, _s.alignItemsStart, _s.flexGrow1].join(' ')}
|
className={[_s.default, _s.noUnderline, _s.cursorPointer, _s.width100PC, _s.alignItemsStart].join(' ')}
|
||||||
>
|
>
|
||||||
<div className={containerClasses}>
|
<div className={containerClasses}>
|
||||||
<div className={[_s.default]}>
|
<div className={[_s.default]}>
|
||||||
|
@ -16,6 +16,7 @@ import StatusContent from '../status_content';
|
|||||||
import StatusActionBar from '../status_action_bar';
|
import StatusActionBar from '../status_action_bar';
|
||||||
import Icon from '../icon';
|
import Icon from '../icon';
|
||||||
import Poll from '../poll';
|
import Poll from '../poll';
|
||||||
|
import StatusHeader from '../status_header'
|
||||||
|
|
||||||
// We use the component (and not the container) since we do not want
|
// We use the component (and not the container) since we do not want
|
||||||
// to use the progress bar to show download progress
|
// to use the progress bar to show download progress
|
||||||
@ -403,10 +404,6 @@ class Status extends ImmutablePureComponent {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (account === undefined || account === null) {
|
|
||||||
statusAvatar = <Avatar account={status.get('account')} size={50} />;
|
|
||||||
}
|
|
||||||
|
|
||||||
const handlers = this.props.muted
|
const handlers = this.props.muted
|
||||||
? {}
|
? {}
|
||||||
: {
|
: {
|
||||||
@ -427,7 +424,7 @@ class Status extends ImmutablePureComponent {
|
|||||||
return (
|
return (
|
||||||
<HotKeys handlers={handlers}>
|
<HotKeys handlers={handlers}>
|
||||||
<div
|
<div
|
||||||
className={[_s.default, _s.backgroundWhite, _s.radiusSmall, _s.marginBottom15PX, _s.border1PX, _s.bordercolorSecondary].join(' ')}
|
className={[_s.default, _s.backgroundColorPrimary, _s.radiusSmall, _s.marginBottom15PX, _s.border1PX, _s.borderColorSecondary].join(' ')}
|
||||||
tabIndex={this.props.muted ? null : 0}
|
tabIndex={this.props.muted ? null : 0}
|
||||||
data-featured={featured ? 'true' : null}
|
data-featured={featured ? 'true' : null}
|
||||||
aria-label={textForScreenReader(intl, status, rebloggedByText)}
|
aria-label={textForScreenReader(intl, status, rebloggedByText)}
|
||||||
@ -445,60 +442,7 @@ class Status extends ImmutablePureComponent {
|
|||||||
data-id={status.get('id')}
|
data-id={status.get('id')}
|
||||||
>
|
>
|
||||||
|
|
||||||
<div className={[_s.default, _s.paddingHorizontal15PX, _s.paddingVertical10PX].join(' ')}>
|
<StatusHeader status={status} />
|
||||||
<div className={[_s.default, _s.flexRow, _s.marginTop5PX].join(' ')}>
|
|
||||||
<div className={[_s.default, _s.marginRight10PX].join(' ')}>{statusAvatar}</div>
|
|
||||||
<div className={[_s.default, _s.alignItemsStart, _s.flexGrow1, _s.marginTop5PX].join(' ')}>
|
|
||||||
<div className={[_s.default, _s.flexRow, _s.width100PC, _s.alignItemsStart].join(' ')}>
|
|
||||||
<NavLink
|
|
||||||
className={[_s.default, _s.flexRow, _s.alignItemsStart, _s.noUnderline].join(' ')}
|
|
||||||
to={`/${status.getIn(['account', 'acct'])}`}
|
|
||||||
title={status.getIn(['account', 'acct'])}
|
|
||||||
>
|
|
||||||
<DisplayName account={status.get('account')} />
|
|
||||||
</NavLink>
|
|
||||||
<Icon id='ellipsis' width='20px' height='20px' className={[_s.default, _s.fillcolorSecondary, _s.marginLeftAuto].join(' ')} />
|
|
||||||
</div>
|
|
||||||
<div className={[_s.default, _s.flexRow, _s.alignItemsCenter, _s.lineHeight15].join(' ')}>
|
|
||||||
<NavLink
|
|
||||||
to={statusUrl}
|
|
||||||
className={[_s.default, _s.text, _s.fontSize13PX, _s.noUnderline, _s.colorSecondary].join(' ')}
|
|
||||||
>
|
|
||||||
<RelativeTimestamp timestamp={status.get('created_at')} />
|
|
||||||
</NavLink>
|
|
||||||
<span className={[_s.default, _s.text, _s.fontSize12PX, _s.marginLeft5PX, _s.colorSecondary].join(' ')}>•</span>
|
|
||||||
<Icon id='globe' width='12px' height='12px' className={[_s.default, _s.displayInline, _s.marginLeft5PX, _s.fillcolorSecondary].join(' ')}/>
|
|
||||||
|
|
||||||
{
|
|
||||||
!!status.get('group') &&
|
|
||||||
<Fragment>
|
|
||||||
<span className={[_s.default, _s.text, _s.fontSize12PX, _s.marginLeft5PX, _s.colorSecondary].join(' ')}>•</span>
|
|
||||||
<NavLink
|
|
||||||
to={`/groups/${status.getIn(['group', 'id'])}`}
|
|
||||||
className={[_s.default, _s.text, _s.fontSize13PX, _s.marginLeft5PX, _s.colorPrimary].join(' ')}
|
|
||||||
>
|
|
||||||
{status.getIn(['group', 'title'])}
|
|
||||||
</NavLink>
|
|
||||||
</Fragment>
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
status.get('revised_at') !== null &&
|
|
||||||
<Fragment>
|
|
||||||
<span className={[_s.default, _s.text, _s.fontSize12PX, _s.marginLeft5PX, _s.colorSecondary].join(' ')}>•</span>
|
|
||||||
<button
|
|
||||||
onClick={() => other.onShowRevisions(status)}
|
|
||||||
className={[_s.default, _s.text, _s.fontSize13PX, _s.marginLeft5PX, _s.colorSecondary].join(' ')}
|
|
||||||
>
|
|
||||||
Edited
|
|
||||||
</button>
|
|
||||||
</Fragment>
|
|
||||||
}
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className={_s.default}>
|
<div className={_s.default}>
|
||||||
<StatusContent
|
<StatusContent
|
||||||
|
@ -165,134 +165,6 @@ class StatusActionBar extends ImmutablePureComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleDeleteClick = () => {
|
|
||||||
this.props.onDelete(this.props.status, this.context.router.history);
|
|
||||||
}
|
|
||||||
|
|
||||||
handleEditClick = () => {
|
|
||||||
this.props.onEdit(this.props.status);
|
|
||||||
}
|
|
||||||
|
|
||||||
handlePinClick = () => {
|
|
||||||
this.props.onPin(this.props.status);
|
|
||||||
}
|
|
||||||
|
|
||||||
handleMentionClick = () => {
|
|
||||||
this.props.onMention(this.props.status.get('account'), this.context.router.history);
|
|
||||||
}
|
|
||||||
|
|
||||||
handleMuteClick = () => {
|
|
||||||
this.props.onMute(this.props.status.get('account'));
|
|
||||||
}
|
|
||||||
|
|
||||||
handleBlockClick = () => {
|
|
||||||
this.props.onBlock(this.props.status);
|
|
||||||
}
|
|
||||||
|
|
||||||
handleOpen = () => {
|
|
||||||
this.context.router.history.push(`/${this.props.status.getIn(['account', 'acct'])}/posts/${this.props.status.get('id')}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
handleEmbed = () => {
|
|
||||||
this.props.onEmbed(this.props.status);
|
|
||||||
}
|
|
||||||
|
|
||||||
handleReport = () => {
|
|
||||||
this.props.onReport(this.props.status);
|
|
||||||
}
|
|
||||||
|
|
||||||
handleConversationMuteClick = () => {
|
|
||||||
this.props.onMuteConversation(this.props.status);
|
|
||||||
}
|
|
||||||
|
|
||||||
handleCopy = () => {
|
|
||||||
const url = this.props.status.get('url');
|
|
||||||
const textarea = document.createElement('textarea');
|
|
||||||
|
|
||||||
textarea.textContent = url;
|
|
||||||
textarea.style.position = 'fixed';
|
|
||||||
|
|
||||||
document.body.appendChild(textarea);
|
|
||||||
|
|
||||||
try {
|
|
||||||
textarea.select();
|
|
||||||
document.execCommand('copy');
|
|
||||||
} catch (e) {
|
|
||||||
//
|
|
||||||
} finally {
|
|
||||||
document.body.removeChild(textarea);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
handleGroupRemoveAccount = () => {
|
|
||||||
const { status } = this.props;
|
|
||||||
|
|
||||||
this.props.onGroupRemoveAccount(status.getIn(['group', 'id']), status.getIn(['account', 'id']));
|
|
||||||
}
|
|
||||||
|
|
||||||
handleGroupRemovePost = () => {
|
|
||||||
const { status } = this.props;
|
|
||||||
|
|
||||||
this.props.onGroupRemoveStatus(status.getIn(['group', 'id']), status.get('id'));
|
|
||||||
}
|
|
||||||
|
|
||||||
_makeMenu = (publicStatus) => {
|
|
||||||
const { status, intl: { formatMessage }, withDismiss, withGroupAdmin } = this.props;
|
|
||||||
const mutingConversation = status.get('muted');
|
|
||||||
|
|
||||||
let menu = [];
|
|
||||||
|
|
||||||
menu.push({ text: formatMessage(messages.open), action: this.handleOpen });
|
|
||||||
|
|
||||||
if (publicStatus) {
|
|
||||||
menu.push({ text: formatMessage(messages.copy), action: this.handleCopy });
|
|
||||||
menu.push({ text: formatMessage(messages.embed), action: this.handleEmbed });
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!me) {
|
|
||||||
return menu;
|
|
||||||
}
|
|
||||||
|
|
||||||
menu.push(null);
|
|
||||||
|
|
||||||
if (status.getIn(['account', 'id']) === me || withDismiss) {
|
|
||||||
menu.push({ text: formatMessage(mutingConversation ? messages.unmuteConversation : messages.muteConversation), action: this.handleConversationMuteClick });
|
|
||||||
menu.push(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (status.getIn(['account', 'id']) === me) {
|
|
||||||
if (publicStatus) {
|
|
||||||
menu.push({ text: formatMessage(status.get('pinned') ? messages.unpin : messages.pin), action: this.handlePinClick });
|
|
||||||
} else {
|
|
||||||
if (status.get('visibility') === 'private') {
|
|
||||||
menu.push({ text: formatMessage(status.get('reblogged') ? messages.cancel_reblog_private : messages.reblog_private), action: this.handleReblogClick });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
menu.push({ text: formatMessage(messages.delete), action: this.handleDeleteClick });
|
|
||||||
menu.push({ text: formatMessage(messages.edit), action: this.handleEditClick });
|
|
||||||
} else {
|
|
||||||
menu.push({ text: formatMessage(messages.mention, { name: status.getIn(['account', 'username']) }), action: this.handleMentionClick });
|
|
||||||
menu.push(null);
|
|
||||||
menu.push({ text: formatMessage(messages.mute, { name: status.getIn(['account', 'username']) }), action: this.handleMuteClick });
|
|
||||||
menu.push({ text: formatMessage(messages.block, { name: status.getIn(['account', 'username']) }), action: this.handleBlockClick });
|
|
||||||
menu.push({ text: formatMessage(messages.report, { name: status.getIn(['account', 'username']) }), action: this.handleReport });
|
|
||||||
|
|
||||||
if (isStaff) {
|
|
||||||
menu.push(null);
|
|
||||||
menu.push({ text: formatMessage(messages.admin_account, { name: status.getIn(['account', 'username']) }), href: `/admin/accounts/${status.getIn(['account', 'id'])}` });
|
|
||||||
menu.push({ text: formatMessage(messages.admin_status), href: `/admin/accounts/${status.getIn(['account', 'id'])}/statuses/${status.get('id')}` });
|
|
||||||
}
|
|
||||||
|
|
||||||
if (withGroupAdmin) {
|
|
||||||
menu.push(null);
|
|
||||||
menu.push({ text: formatMessage(messages.group_remove_account), action: this.handleGroupRemoveAccount });
|
|
||||||
menu.push({ text: formatMessage(messages.group_remove_post), action: this.handleGroupRemovePost });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return menu;
|
|
||||||
}
|
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { status, intl: { formatMessage } } = this.props;
|
const { status, intl: { formatMessage } } = this.props;
|
||||||
|
|
||||||
@ -311,8 +183,6 @@ class StatusActionBar extends ImmutablePureComponent {
|
|||||||
<IconButton className='status-action-bar-button' title={formatMessage(messages.share)} icon='share-alt' onClick={this.handleShareClick} />
|
<IconButton className='status-action-bar-button' title={formatMessage(messages.share)} icon='share-alt' onClick={this.handleShareClick} />
|
||||||
);
|
);
|
||||||
|
|
||||||
const menu = this._makeMenu(publicStatus);
|
|
||||||
|
|
||||||
const items = [
|
const items = [
|
||||||
{
|
{
|
||||||
title: formatMessage(messages.like),
|
title: formatMessage(messages.like),
|
||||||
@ -357,7 +227,7 @@ class StatusActionBar extends ImmutablePureComponent {
|
|||||||
flexRow: 1,
|
flexRow: 1,
|
||||||
width100PC: 1,
|
width100PC: 1,
|
||||||
borderTop1PX: !shouldCondense,
|
borderTop1PX: !shouldCondense,
|
||||||
bordercolorSecondary: !shouldCondense,
|
borderColorSecondary: !shouldCondense,
|
||||||
marginTop5PX: hasInteractions,
|
marginTop5PX: hasInteractions,
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -404,17 +274,6 @@ class StatusActionBar extends ImmutablePureComponent {
|
|||||||
<StatusActionBarItem key={`status-action-bar-item-${i}`} {...item} />
|
<StatusActionBarItem key={`status-action-bar-item-${i}`} {...item} />
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
{/*<div className='status-action-bar__dropdown'>
|
|
||||||
<DropdownMenuContainer
|
|
||||||
status={status}
|
|
||||||
items={menu}
|
|
||||||
icon='ellipsis-h'
|
|
||||||
size={18}
|
|
||||||
direction='right'
|
|
||||||
title={formatMessage(messages.more)}
|
|
||||||
/>
|
|
||||||
</div>*/}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className='status-action-bar__comment'>
|
<div className='status-action-bar__comment'>
|
||||||
|
268
app/javascript/gabsocial/components/status_header.js
Normal file
268
app/javascript/gabsocial/components/status_header.js
Normal file
@ -0,0 +1,268 @@
|
|||||||
|
import { Fragment } from 'react'
|
||||||
|
import { NavLink } from 'react-router-dom'
|
||||||
|
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||||
|
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||||
|
import RelativeTimestamp from './relative_timestamp'
|
||||||
|
import DisplayName from './display_name'
|
||||||
|
import Text from './text'
|
||||||
|
import DotTextSeperator from './dot_text_seperator'
|
||||||
|
import Icon from './icon'
|
||||||
|
import Button from './button'
|
||||||
|
import Avatar from './avatar'
|
||||||
|
|
||||||
|
export default class StatusHeader extends ImmutablePureComponent {
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
status: ImmutablePropTypes.map,
|
||||||
|
}
|
||||||
|
|
||||||
|
handleStatusOptionsClick() {
|
||||||
|
console.log("handleStatusOptionsClick")
|
||||||
|
}
|
||||||
|
|
||||||
|
handleOpenStatusEdits() {
|
||||||
|
console.log("handleOpenStatusEdits")
|
||||||
|
}
|
||||||
|
|
||||||
|
handleDeleteClick = () => {
|
||||||
|
this.props.onDelete(this.props.status, this.context.router.history);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleEditClick = () => {
|
||||||
|
this.props.onEdit(this.props.status);
|
||||||
|
}
|
||||||
|
|
||||||
|
handlePinClick = () => {
|
||||||
|
this.props.onPin(this.props.status);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleMentionClick = () => {
|
||||||
|
this.props.onMention(this.props.status.get('account'), this.context.router.history);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleMuteClick = () => {
|
||||||
|
this.props.onMute(this.props.status.get('account'));
|
||||||
|
}
|
||||||
|
|
||||||
|
handleBlockClick = () => {
|
||||||
|
this.props.onBlock(this.props.status);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleOpen = () => {
|
||||||
|
this.context.router.history.push(`/${this.props.status.getIn(['account', 'acct'])}/posts/${this.props.status.get('id')}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleEmbed = () => {
|
||||||
|
this.props.onEmbed(this.props.status);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleReport = () => {
|
||||||
|
this.props.onReport(this.props.status);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleConversationMuteClick = () => {
|
||||||
|
this.props.onMuteConversation(this.props.status);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleCopy = () => {
|
||||||
|
const url = this.props.status.get('url');
|
||||||
|
const textarea = document.createElement('textarea');
|
||||||
|
|
||||||
|
textarea.textContent = url;
|
||||||
|
textarea.style.position = 'fixed';
|
||||||
|
|
||||||
|
document.body.appendChild(textarea);
|
||||||
|
|
||||||
|
try {
|
||||||
|
textarea.select();
|
||||||
|
document.execCommand('copy');
|
||||||
|
} catch (e) {
|
||||||
|
//
|
||||||
|
} finally {
|
||||||
|
document.body.removeChild(textarea);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleGroupRemoveAccount = () => {
|
||||||
|
const { status } = this.props;
|
||||||
|
|
||||||
|
this.props.onGroupRemoveAccount(status.getIn(['group', 'id']), status.getIn(['account', 'id']));
|
||||||
|
}
|
||||||
|
|
||||||
|
handleGroupRemovePost = () => {
|
||||||
|
const { status } = this.props;
|
||||||
|
|
||||||
|
this.props.onGroupRemoveStatus(status.getIn(['group', 'id']), status.get('id'));
|
||||||
|
}
|
||||||
|
|
||||||
|
_makeMenu = (publicStatus) => {
|
||||||
|
const { status, intl: { formatMessage }, withDismiss, withGroupAdmin } = this.props;
|
||||||
|
const mutingConversation = status.get('muted');
|
||||||
|
|
||||||
|
let menu = [];
|
||||||
|
|
||||||
|
menu.push({ text: formatMessage(messages.open), action: this.handleOpen });
|
||||||
|
|
||||||
|
if (publicStatus) {
|
||||||
|
menu.push({ text: formatMessage(messages.copy), action: this.handleCopy });
|
||||||
|
menu.push({ text: formatMessage(messages.embed), action: this.handleEmbed });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!me) return menu
|
||||||
|
|
||||||
|
menu.push(null);
|
||||||
|
|
||||||
|
if (status.getIn(['account', 'id']) === me || withDismiss) {
|
||||||
|
menu.push({ text: formatMessage(mutingConversation ? messages.unmuteConversation : messages.muteConversation), action: this.handleConversationMuteClick });
|
||||||
|
menu.push(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status.getIn(['account', 'id']) === me) {
|
||||||
|
if (publicStatus) {
|
||||||
|
menu.push({ text: formatMessage(status.get('pinned') ? messages.unpin : messages.pin), action: this.handlePinClick });
|
||||||
|
} else {
|
||||||
|
if (status.get('visibility') === 'private') {
|
||||||
|
menu.push({ text: formatMessage(status.get('reblogged') ? messages.cancel_reblog_private : messages.reblog_private), action: this.handleReblogClick });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
menu.push({ text: formatMessage(messages.delete), action: this.handleDeleteClick });
|
||||||
|
menu.push({ text: formatMessage(messages.edit), action: this.handleEditClick });
|
||||||
|
} else {
|
||||||
|
menu.push({ text: formatMessage(messages.mention, { name: status.getIn(['account', 'username']) }), action: this.handleMentionClick });
|
||||||
|
menu.push(null);
|
||||||
|
menu.push({ text: formatMessage(messages.mute, { name: status.getIn(['account', 'username']) }), action: this.handleMuteClick });
|
||||||
|
menu.push({ text: formatMessage(messages.block, { name: status.getIn(['account', 'username']) }), action: this.handleBlockClick });
|
||||||
|
menu.push({ text: formatMessage(messages.report, { name: status.getIn(['account', 'username']) }), action: this.handleReport });
|
||||||
|
|
||||||
|
if (isStaff) {
|
||||||
|
menu.push(null);
|
||||||
|
menu.push({ text: formatMessage(messages.admin_account, { name: status.getIn(['account', 'username']) }), href: `/admin/accounts/${status.getIn(['account', 'id'])}` });
|
||||||
|
menu.push({ text: formatMessage(messages.admin_status), href: `/admin/accounts/${status.getIn(['account', 'id'])}/statuses/${status.get('id')}` });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (withGroupAdmin) {
|
||||||
|
menu.push(null);
|
||||||
|
menu.push({ text: formatMessage(messages.group_remove_account), action: this.handleGroupRemoveAccount });
|
||||||
|
menu.push({ text: formatMessage(messages.group_remove_post), action: this.handleGroupRemovePost });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return menu;
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { status } = this.props
|
||||||
|
|
||||||
|
const statusUrl = `/${status.getIn(['account', 'acct'])}/posts/${status.get('id')}`;
|
||||||
|
|
||||||
|
// const menu = this._makeMenu(publicStatus);
|
||||||
|
// <div className='status-action-bar__dropdown'>
|
||||||
|
// <DropdownMenuContainer
|
||||||
|
// status={status}
|
||||||
|
// items={menu}
|
||||||
|
// icon='ellipsis-h'
|
||||||
|
// size={18}
|
||||||
|
// direction='right'
|
||||||
|
// title={formatMessage(messages.more)}
|
||||||
|
// />
|
||||||
|
// </div>
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={[_s.default, _s.paddingHorizontal15PX, _s.paddingVertical10PX].join(' ')}>
|
||||||
|
<div className={[_s.default, _s.flexRow, _s.marginTop5PX].join(' ')}>
|
||||||
|
|
||||||
|
<NavLink
|
||||||
|
to={`/${status.getIn(['account', 'acct'])}`}
|
||||||
|
title={status.getIn(['account', 'acct'])}
|
||||||
|
className={[_s.default, _s.marginRight10PX].join(' ')}
|
||||||
|
>
|
||||||
|
<Avatar account={status.get('account')} size={50} />
|
||||||
|
</NavLink>
|
||||||
|
|
||||||
|
<div className={[_s.default, _s.alignItemsStart, _s.flexGrow1, _s.marginTop5PX].join(' ')}>
|
||||||
|
|
||||||
|
<div className={[_s.default, _s.flexRow, _s.width100PC, _s.alignItemsStart].join(' ')}>
|
||||||
|
<NavLink
|
||||||
|
className={[_s.default, _s.flexRow, _s.alignItemsStart, _s.noUnderline].join(' ')}
|
||||||
|
to={`/${status.getIn(['account', 'acct'])}`}
|
||||||
|
title={status.getIn(['account', 'acct'])}
|
||||||
|
>
|
||||||
|
<DisplayName account={status.get('account')} />
|
||||||
|
</NavLink>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
text
|
||||||
|
backgroundColor='none'
|
||||||
|
color='none'
|
||||||
|
icon='ellipsis'
|
||||||
|
iconWidth='20px'
|
||||||
|
iconHeight='20px'
|
||||||
|
iconClassName={_s.fillcolorSecondary}
|
||||||
|
className={_s.marginLeftAuto}
|
||||||
|
onClick={this.handleStatusOptionsClick}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={[_s.default, _s.flexRow, _s.alignItemsCenter, _s.lineHeight15].join(' ')}>
|
||||||
|
<Button
|
||||||
|
text
|
||||||
|
underlineOnHover
|
||||||
|
backgroundColor='none'
|
||||||
|
color='none'
|
||||||
|
to={statusUrl}
|
||||||
|
>
|
||||||
|
<Text size='small' color='secondary'>
|
||||||
|
<RelativeTimestamp timestamp={status.get('created_at')} />
|
||||||
|
</Text>
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<DotTextSeperator />
|
||||||
|
|
||||||
|
<Icon id='globe' width='12px' height='12px' className={[_s.default, _s.displayInline, _s.marginLeft5PX, _s.fillcolorSecondary].join(' ')} />
|
||||||
|
|
||||||
|
{
|
||||||
|
!!status.get('group') &&
|
||||||
|
<Fragment>
|
||||||
|
<DotTextSeperator />
|
||||||
|
<Button
|
||||||
|
text
|
||||||
|
underlineOnHover
|
||||||
|
backgroundColor='none'
|
||||||
|
color='none'
|
||||||
|
to={`/groups/${status.getIn(['group', 'id'])}`}
|
||||||
|
className={_s.marginLeft5PX}
|
||||||
|
>
|
||||||
|
<Text size='small' color='secondary'>
|
||||||
|
{status.getIn(['group', 'title'])}
|
||||||
|
</Text>
|
||||||
|
</Button>
|
||||||
|
</Fragment>
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
status.get('revised_at') !== null &&
|
||||||
|
<Fragment>
|
||||||
|
<DotTextSeperator />
|
||||||
|
<Button
|
||||||
|
text
|
||||||
|
underlineOnHover
|
||||||
|
backgroundColor='none'
|
||||||
|
color='none'
|
||||||
|
onClick={this.handleOpenStatusEdits}
|
||||||
|
className={_s.marginLeft5PX}
|
||||||
|
>
|
||||||
|
<Text size='small' color='secondary'>
|
||||||
|
Edited
|
||||||
|
</Text>
|
||||||
|
</Button>
|
||||||
|
</Fragment>
|
||||||
|
}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -8,6 +8,7 @@ const COLORS = {
|
|||||||
brand: 'brand',
|
brand: 'brand',
|
||||||
error: 'error',
|
error: 'error',
|
||||||
white: 'white',
|
white: 'white',
|
||||||
|
inherit: 'inherit',
|
||||||
}
|
}
|
||||||
|
|
||||||
const SIZES = {
|
const SIZES = {
|
||||||
@ -26,6 +27,11 @@ const WEIGHTS = {
|
|||||||
extraBold: 'extraBold',
|
extraBold: 'extraBold',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ALIGNMENTS = {
|
||||||
|
center: 'center',
|
||||||
|
left: 'left',
|
||||||
|
}
|
||||||
|
|
||||||
export default class Text extends PureComponent {
|
export default class Text extends PureComponent {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
tagName: PropTypes.string,
|
tagName: PropTypes.string,
|
||||||
@ -34,6 +40,7 @@ export default class Text extends PureComponent {
|
|||||||
color: PropTypes.oneOf(Object.keys(COLORS)),
|
color: PropTypes.oneOf(Object.keys(COLORS)),
|
||||||
size: PropTypes.oneOf(Object.keys(SIZES)),
|
size: PropTypes.oneOf(Object.keys(SIZES)),
|
||||||
weight: PropTypes.oneOf(Object.keys(WEIGHTS)),
|
weight: PropTypes.oneOf(Object.keys(WEIGHTS)),
|
||||||
|
align: PropTypes.oneOf(Object.keys(ALIGNMENTS)),
|
||||||
underline: PropTypes.bool,
|
underline: PropTypes.bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,7 +52,16 @@ export default class Text extends PureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { tagName, className, children, color, size, weight, underline } = this.props
|
const {
|
||||||
|
tagName,
|
||||||
|
className,
|
||||||
|
children,
|
||||||
|
color,
|
||||||
|
size,
|
||||||
|
weight,
|
||||||
|
underline,
|
||||||
|
align
|
||||||
|
} = this.props
|
||||||
|
|
||||||
const classes = cx(className, {
|
const classes = cx(className, {
|
||||||
default: 1,
|
default: 1,
|
||||||
@ -55,15 +71,21 @@ export default class Text extends PureComponent {
|
|||||||
colorSecondary: color === COLORS.secondary,
|
colorSecondary: color === COLORS.secondary,
|
||||||
colorBrand: color === COLORS.brand,
|
colorBrand: color === COLORS.brand,
|
||||||
colorWhite: color === COLORS.white,
|
colorWhite: color === COLORS.white,
|
||||||
|
inherit: color === COLORS.inherit,
|
||||||
|
|
||||||
fontSize19PX: size === SIZES.large,
|
fontSize19PX: size === SIZES.large,
|
||||||
fontSize15PX: size === SIZES.medium,
|
fontSize15PX: size === SIZES.medium,
|
||||||
fontSize14PX: size === SIZES.normal,
|
fontSize14PX: size === SIZES.normal,
|
||||||
fontSize13PX: size === SIZES.small,
|
fontSize13PX: size === SIZES.small,
|
||||||
|
fontSize12PX: size === SIZES.extraSmall,
|
||||||
|
|
||||||
fontWeightNormal: weight === WEIGHTS.normal,
|
fontWeightNormal: weight === WEIGHTS.normal,
|
||||||
fontWeightMedium: weight === WEIGHTS.medium,
|
fontWeightMedium: weight === WEIGHTS.medium,
|
||||||
fontWeightBold: weight === WEIGHTS.bold,
|
fontWeightBold: weight === WEIGHTS.bold,
|
||||||
|
fontWeightExtraBold: weight === WEIGHTS.extraBold,
|
||||||
|
|
||||||
|
textAlignLeft: align === ALIGNMENTS.left,
|
||||||
|
textAlignCenter: align === ALIGNMENTS.center,
|
||||||
|
|
||||||
underline: underline,
|
underline: underline,
|
||||||
})
|
})
|
||||||
|
@ -1,19 +1,28 @@
|
|||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||||
import { me } from '../initial_state';
|
import { injectIntl, defineMessages } from 'react-intl'
|
||||||
import ComposeFormContainer from '../features/compose/containers/compose_form_container';
|
import { me } from '../initial_state'
|
||||||
import Avatar from './avatar';
|
import ComposeFormContainer from '../features/compose/containers/compose_form_container'
|
||||||
|
import Avatar from './avatar'
|
||||||
|
import Heading from './heading'
|
||||||
|
|
||||||
|
const messages = defineMessages({
|
||||||
|
createPost: { id: 'column_header.create_post', defaultMessage: 'Create Post' },
|
||||||
|
})
|
||||||
|
|
||||||
const mapStateToProps = state => {
|
const mapStateToProps = state => {
|
||||||
return {
|
return {
|
||||||
account: state.getIn(['accounts', me]),
|
account: state.getIn(['accounts', me]),
|
||||||
};
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
export default @connect(mapStateToProps)
|
export default
|
||||||
|
@connect(mapStateToProps)
|
||||||
|
@injectIntl
|
||||||
class TimelineComposeBlock extends ImmutablePureComponent {
|
class TimelineComposeBlock extends ImmutablePureComponent {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
intl: PropTypes.object.isRequired,
|
||||||
account: ImmutablePropTypes.map.isRequired,
|
account: ImmutablePropTypes.map.isRequired,
|
||||||
size: PropTypes.number,
|
size: PropTypes.number,
|
||||||
}
|
}
|
||||||
@ -23,14 +32,14 @@ class TimelineComposeBlock extends ImmutablePureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { account, size, ...rest } = this.props;
|
const { account, size, intl, ...rest } = this.props
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className={[_s.default, _s.overflowHidden, _s.radiusSmall, _s.border1PX, _s.bordercolorSecondary, _s.backgroundWhite, _s.marginBottom15PX].join(' ')}>
|
<section className={[_s.default, _s.overflowHidden, _s.radiusSmall, _s.border1PX, _s.borderColorSecondary, _s.backgroundColorPrimary, _s.marginBottom15PX].join(' ')}>
|
||||||
<div className={[_s.default, _s.backgroundSubtle, _s.borderBottom1PX, _s.bordercolorSecondary, _s.paddingHorizontal15PX, _s.paddingVertical2PX].join(' ')}>
|
<div className={[_s.default, _s.backgroundSubtle, _s.borderBottom1PX, _s.borderColorSecondary, _s.paddingHorizontal15PX, _s.paddingVertical2PX].join(' ')}>
|
||||||
<h1 className={[_s.default, _s.text, _s.colorSecondary, _s.fontSize12PX, _s.fontWeightMedium, _s.lineHeight2, _s.paddingVertical2PX].join(' ')}>
|
<Heading size='h5'>
|
||||||
Create Post
|
{intl.formatMessage(messages.createPost)}
|
||||||
</h1>
|
</Heading>
|
||||||
</div>
|
</div>
|
||||||
<div className={[_s.default, _s.flexRow, _s.paddingVertical15PX, _s.paddingHorizontal15PX].join(' ')}>
|
<div className={[_s.default, _s.flexRow, _s.paddingVertical15PX, _s.paddingHorizontal15PX].join(' ')}>
|
||||||
<div className={[_s.default, _s.marginRight10PX].join(' ')}>
|
<div className={[_s.default, _s.marginRight10PX].join(' ')}>
|
||||||
|
@ -4,6 +4,11 @@ import ImmutablePureComponent from 'react-immutable-pure-component'
|
|||||||
import { NavLink } from 'react-router-dom'
|
import { NavLink } from 'react-router-dom'
|
||||||
import classNames from 'classnames/bind'
|
import classNames from 'classnames/bind'
|
||||||
import { shortNumberFormat } from '../utils/numbers'
|
import { shortNumberFormat } from '../utils/numbers'
|
||||||
|
import Text from './text'
|
||||||
|
import Button from './button'
|
||||||
|
import Image from './image'
|
||||||
|
import TrendingItemCard from './trends_panel_item_card'
|
||||||
|
import DotTextSeperator from './dot_text_seperator'
|
||||||
|
|
||||||
const cx = classNames.bind(_s)
|
const cx = classNames.bind(_s)
|
||||||
|
|
||||||
@ -42,12 +47,20 @@ export default class TrendingItem extends ImmutablePureComponent {
|
|||||||
return (
|
return (
|
||||||
<NavLink
|
<NavLink
|
||||||
to='/test'
|
to='/test'
|
||||||
className={[_s.default, _s.noUnderline, _s.marginBottom10PX].join(' ')}
|
className={[_s.default, _s.noUnderline, _s.paddingHorizontal15PX, _s.paddingVertical5PX, _s.borderColorSecondary, _s.borderBottom1PX, _s.backgroundSubtle_onHover].join(' ')}
|
||||||
onMouseEnter={() => this.handleOnMouseEnter()}
|
onMouseEnter={() => this.handleOnMouseEnter()}
|
||||||
onMouseLeave={() => this.handleOnMouseLeave()}
|
onMouseLeave={() => this.handleOnMouseLeave()}
|
||||||
>
|
>
|
||||||
<span className={[_s.default, _s.text, _s.displayFlex, _s.colorBrand, _s.fontSize15PX, _s.fontWeightBold, _s.lineHeight15].join(' ')}>#randomhashtag</span>
|
<div className={[_s.default, _s.flexRow, _s.marginTop5PX].join(' ')}>
|
||||||
<span className={subtitleClasses}>10,240 Gabs</span>
|
<Text size='small' color='secondary'>1</Text>
|
||||||
|
<DotTextSeperator />
|
||||||
|
<Text size='small' color='secondary' className={_s.marginLeft5PX}>Politics</Text>
|
||||||
|
</div>
|
||||||
|
<div className={[_s.default, _s.paddingVertical5PX].join(' ')}>
|
||||||
|
<Text color='primary' weight='bold' size='medium'>Trump Campaign</Text>
|
||||||
|
<Text color='secondary' className={[_s.marginTop5PX, _s.marginBottom10PX].join(' ')}>46.7K Gabs</Text>
|
||||||
|
<TrendingItemCard />
|
||||||
|
</div>
|
||||||
</NavLink>
|
</NavLink>
|
||||||
)
|
)
|
||||||
}
|
}
|
@ -0,0 +1,66 @@
|
|||||||
|
import { FormattedMessage } from 'react-intl'
|
||||||
|
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||||
|
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||||
|
import { NavLink } from 'react-router-dom'
|
||||||
|
import classNames from 'classnames/bind'
|
||||||
|
import { shortNumberFormat } from '../utils/numbers'
|
||||||
|
import Text from './text'
|
||||||
|
import Button from './button'
|
||||||
|
import Image from './image'
|
||||||
|
|
||||||
|
const cx = classNames.bind(_s)
|
||||||
|
|
||||||
|
export default class TrendingItemCard extends ImmutablePureComponent {
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
trend: ImmutablePropTypes.map.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
state = {
|
||||||
|
hovering: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
handleOnMouseEnter = () => {
|
||||||
|
this.setState({ hovering: true })
|
||||||
|
}
|
||||||
|
|
||||||
|
handleOnMouseLeave = () => {
|
||||||
|
this.setState({ hovering: false })
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { trend } = this.props
|
||||||
|
const { hovering } = this.state
|
||||||
|
|
||||||
|
const subtitleClasses = cx({
|
||||||
|
default: 1,
|
||||||
|
text: 1,
|
||||||
|
displayFlex: 1,
|
||||||
|
fontSize13PX: 1,
|
||||||
|
fontWeightNormal: 1,
|
||||||
|
colorSecondary: 1,
|
||||||
|
underline: hovering,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
// URL with title, description
|
||||||
|
|
||||||
|
// URL with video
|
||||||
|
|
||||||
|
// URL with title, description, image
|
||||||
|
return (
|
||||||
|
<div className={[_s.default, _s.flexRow, _s.overflowHidden, _s.borderColorSecondary, _s.border1PX, _s.radiusSmall, _s.backgroundSubtle_onHover].join(' ')}>
|
||||||
|
<div className={[_s.default, _s.flexNormal, _s.paddingVertical10PX, _s.paddingHorizontal10PX].join(' ')}>
|
||||||
|
<Text color='secondary' className={_s.lineHeight15}>
|
||||||
|
NYPost
|
||||||
|
</Text>
|
||||||
|
<Text size='medium' color='primary'>
|
||||||
|
The best flower subscription services: BloomsyBox, Bouqs...
|
||||||
|
</Text>
|
||||||
|
</div>
|
||||||
|
<Image width='92px' height='92px' />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1 +0,0 @@
|
|||||||
export { default } from './compose_search';
|
|
@ -1,7 +1,7 @@
|
|||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
import TrendingItem from '../../../../components/trending_item';
|
import TrendingItem from '../../../../components/trends_panel_item';
|
||||||
import Icon from '../../../../components/icon';
|
import Icon from '../../../../components/icon';
|
||||||
import { WhoToFollowPanel } from '../../../../components/panel';
|
import { WhoToFollowPanel } from '../../../../components/panel';
|
||||||
// import TrendsPanel from '../../ui/components/trends_panel';
|
// import TrendsPanel from '../../ui/components/trends_panel';
|
||||||
|
@ -10,7 +10,7 @@ import {
|
|||||||
import { mascot } from '../../initial_state';
|
import { mascot } from '../../initial_state';
|
||||||
import Motion from '../ui/util/optional_motion';
|
import Motion from '../ui/util/optional_motion';
|
||||||
import ComposeFormContainer from './containers/compose_form_container';
|
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 SearchResultsContainer from './containers/search_results_container';
|
||||||
import NavigationBar from './components/navigation_bar';
|
import NavigationBar from './components/navigation_bar';
|
||||||
import elephantUIPlane from '../../../images/logo_ui_column_footer.png';
|
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)}>
|
<div className='drawer' role='region' aria-label={intl.formatMessage(messages.compose)}>
|
||||||
{header}
|
{header}
|
||||||
|
|
||||||
{isSearchPage && <SearchContainer /> }
|
{ /* isSearchPage && <SearchContainer /> */ }
|
||||||
|
|
||||||
<div className='drawer__pager'>
|
<div className='drawer__pager'>
|
||||||
{!isSearchPage && <div className='drawer__inner' onFocus={this.onFocus}>
|
{!isSearchPage && <div className='drawer__inner' onFocus={this.onFocus}>
|
||||||
|
@ -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);
|
|
@ -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>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
export { default } from './group_timeline';
|
@ -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>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
export { default } from './groups_directory';
|
@ -6,7 +6,7 @@ import { setupListAdder, resetListAdder } from '../../actions/lists';
|
|||||||
import List from './components/list';
|
import List from './components/list';
|
||||||
import Account from '../../components/account';
|
import Account from '../../components/account';
|
||||||
import IconButton from '../../components/icon_button';
|
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 => {
|
const getOrderedLists = createSelector([state => state.get('lists')], lists => {
|
||||||
if (!lists) {
|
if (!lists) {
|
||||||
|
@ -1 +0,0 @@
|
|||||||
export { default } from './lists';
|
|
@ -0,0 +1 @@
|
|||||||
|
export { default } from './lists_directory';
|
@ -1,13 +1,10 @@
|
|||||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||||
import { NavLink } from 'react-router-dom'
|
|
||||||
import { createSelector } from 'reselect'
|
import { createSelector } from 'reselect'
|
||||||
import { defineMessages, injectIntl } from 'react-intl'
|
import { defineMessages, injectIntl } from 'react-intl'
|
||||||
import classNames from 'classnames/bind'
|
|
||||||
import { fetchLists } from '../../actions/lists'
|
import { fetchLists } from '../../actions/lists'
|
||||||
import ColumnIndicator from '../../components/column_indicator'
|
import ColumnIndicator from '../../components/column_indicator'
|
||||||
import ScrollableList from '../../components/scrollable_list'
|
import List from '../../components/list'
|
||||||
import Icon from '../../components/icon'
|
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
add: { id: 'lists.new.create', defaultMessage: 'Add List' },
|
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)
|
export default @connect(mapStateToProps, mapDispatchToProps)
|
||||||
@injectIntl
|
@injectIntl
|
||||||
class Lists extends ImmutablePureComponent {
|
class ListsDirectory extends ImmutablePureComponent {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
params: PropTypes.object.isRequired,
|
params: PropTypes.object.isRequired,
|
||||||
@ -63,56 +58,18 @@ class Lists extends ImmutablePureComponent {
|
|||||||
|
|
||||||
const emptyMessage = intl.formatMessage(messages.empty)
|
const emptyMessage = intl.formatMessage(messages.empty)
|
||||||
|
|
||||||
|
const listItems = lists.map(list => ({
|
||||||
|
to: `/list/${list.get('id')}`,
|
||||||
|
title: list.get('title'),
|
||||||
|
}))
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ScrollableList
|
<List
|
||||||
scrollKey='lists'
|
scrollKey='lists'
|
||||||
emptyMessage={emptyMessage}
|
emptyMessage={emptyMessage}
|
||||||
>
|
items={listItems}
|
||||||
<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>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
@ -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';
|
import SearchResultsContainer from '../compose/containers/search_results_container';
|
||||||
|
|
||||||
export default class Search extends PureComponent {
|
export default class Search extends PureComponent {
|
||||||
@ -6,7 +6,7 @@ export default class Search extends PureComponent {
|
|||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div className='column search-page'>
|
<div className='column search-page'>
|
||||||
<SearchContainer />
|
{ /* <SearchContainer /> */ }
|
||||||
|
|
||||||
<div className='drawer__pager'>
|
<div className='drawer__pager'>
|
||||||
<div className='drawer__inner darker'>
|
<div className='drawer__inner darker'>
|
||||||
|
@ -161,7 +161,7 @@ export default class Card extends ImmutablePureComponent {
|
|||||||
)
|
)
|
||||||
|
|
||||||
const description = (
|
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}
|
{title}
|
||||||
<p className={[_s.default, _s.displayFlex, _s.text, _s.marginVertical5PX, _s.overflowWrapBreakWord, _s.colorSecondary, _s.fontSize13PX, _s.fontWeightNormal].join(' ')}>
|
<p className={[_s.default, _s.displayFlex, _s.text, _s.marginVertical5PX, _s.overflowWrapBreakWord, _s.colorSecondary, _s.fontSize13PX, _s.fontWeightNormal].join(' ')}>
|
||||||
{trim(card.get('description') || '', maxDescription)}
|
{trim(card.get('description') || '', maxDescription)}
|
||||||
@ -192,7 +192,7 @@ export default class Card extends ImmutablePureComponent {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={[_s.default, _s.width100PC, _s.paddingHorizontal10PX].join(' ')}>
|
<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].join(' ')}>
|
||||||
<div className={[_s.default, _s.width100PC, _s.paddingTop5625PC].join(' ')}>
|
<div className={[_s.default, _s.width100PC, _s.paddingTop5625PC].join(' ')}>
|
||||||
{ !!embed && embed}
|
{ !!embed && embed}
|
||||||
@ -231,7 +231,7 @@ export default class Card extends ImmutablePureComponent {
|
|||||||
<div className={[_s.default, _s.width100PC, _s.paddingHorizontal10PX].join(' ')}>
|
<div className={[_s.default, _s.width100PC, _s.paddingHorizontal10PX].join(' ')}>
|
||||||
<a
|
<a
|
||||||
href={card.get('url')}
|
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'
|
rel='noopener'
|
||||||
ref={this.setRef}
|
ref={this.setRef}
|
||||||
>
|
>
|
||||||
|
@ -60,7 +60,7 @@ import {
|
|||||||
// Groups,
|
// Groups,
|
||||||
// GroupTimeline,
|
// GroupTimeline,
|
||||||
ListTimeline,
|
ListTimeline,
|
||||||
Lists,
|
ListsDirectory,
|
||||||
// GroupMembers,
|
// GroupMembers,
|
||||||
// GroupRemovedAccounts,
|
// GroupRemovedAccounts,
|
||||||
// GroupCreate,
|
// GroupCreate,
|
||||||
@ -195,7 +195,7 @@ class SwitchingColumnsArea extends PureComponent {
|
|||||||
|
|
||||||
<WrappedRoute path='/tags/:id' publicRoute component={HashtagTimeline} content={children} />
|
<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='/list/:id' page={ListPage} component={ListTimeline} content={children} />
|
||||||
|
|
||||||
<WrappedRoute path='/notifications' page={NotificationsPage} component={Notifications} content={children} />
|
<WrappedRoute path='/notifications' page={NotificationsPage} component={Notifications} content={children} />
|
||||||
|
@ -50,8 +50,8 @@ export function Groups () {
|
|||||||
return import(/* webpackChunkName: "features/groups/index" */'../../groups/index');
|
return import(/* webpackChunkName: "features/groups/index" */'../../groups/index');
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Lists () {
|
export function ListsDirectory () {
|
||||||
return import(/* webpackChunkName: "features/lists" */'../../lists');
|
return import(/* webpackChunkName: "features/lists_directory" */'../../lists_directory');
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Status () {
|
export function Status () {
|
||||||
|
@ -2228,7 +2228,7 @@
|
|||||||
"id": "getting_started.security"
|
"id": "getting_started.security"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"defaultMessage": "About this server",
|
"defaultMessage": "About",
|
||||||
"id": "navigation_bar.info"
|
"id": "navigation_bar.info"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -240,7 +240,7 @@
|
|||||||
"navigation_bar.filters": "Muted words",
|
"navigation_bar.filters": "Muted words",
|
||||||
"navigation_bar.follow_requests": "Follow requests",
|
"navigation_bar.follow_requests": "Follow requests",
|
||||||
"navigation_bar.follows_and_followers": "Follows and followers",
|
"navigation_bar.follows_and_followers": "Follows and followers",
|
||||||
"navigation_bar.info": "About this server",
|
"navigation_bar.info": "About",
|
||||||
"navigation_bar.keyboard_shortcuts": "Hotkeys",
|
"navigation_bar.keyboard_shortcuts": "Hotkeys",
|
||||||
"navigation_bar.lists": "Lists",
|
"navigation_bar.lists": "Lists",
|
||||||
"navigation_bar.logout": "Logout",
|
"navigation_bar.logout": "Logout",
|
||||||
|
@ -237,7 +237,7 @@
|
|||||||
"navigation_bar.favourites": "Favourites",
|
"navigation_bar.favourites": "Favourites",
|
||||||
"navigation_bar.filters": "Muted words",
|
"navigation_bar.filters": "Muted words",
|
||||||
"navigation_bar.follow_requests": "Follow requests",
|
"navigation_bar.follow_requests": "Follow requests",
|
||||||
"navigation_bar.info": "About this server",
|
"navigation_bar.info": "About",
|
||||||
"navigation_bar.keyboard_shortcuts": "Hotkeys",
|
"navigation_bar.keyboard_shortcuts": "Hotkeys",
|
||||||
"navigation_bar.lists": "Lists",
|
"navigation_bar.lists": "Lists",
|
||||||
"navigation_bar.logout": "Logout",
|
"navigation_bar.logout": "Logout",
|
||||||
|
@ -22,11 +22,11 @@ export default class ListsPage extends PureComponent {
|
|||||||
title='Lists'
|
title='Lists'
|
||||||
actions={[
|
actions={[
|
||||||
{
|
{
|
||||||
icon: 'subtract',
|
icon: 'list-delete',
|
||||||
onClick: this.handleClickEditLists
|
onClick: this.handleClickEditLists
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: 'add',
|
icon: 'list-add',
|
||||||
onClick: this.handleClickNewList
|
onClick: this.handleClickNewList
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
|
@ -95,14 +95,15 @@ body {
|
|||||||
|
|
||||||
.whiteSpaceNoWrap { white-space: nowrap; }
|
.whiteSpaceNoWrap { white-space: nowrap; }
|
||||||
|
|
||||||
|
.outlineNone { outline: none; }
|
||||||
.outlineFocusBrand:focus { outline: 2px solid #21cf7a; }
|
.outlineFocusBrand:focus { outline: 2px solid #21cf7a; }
|
||||||
.resizeNone { resize: none; }
|
.resizeNone { resize: none; }
|
||||||
|
|
||||||
.circle { border-radius: 9999px; }
|
.circle { border-radius: 9999px; }
|
||||||
.radiusSmall { border-radius: 8px; }
|
.radiusSmall { border-radius: 8px; }
|
||||||
|
|
||||||
.bordercolorSecondary2 { border-color: #e5e9ed; }
|
.borderColorSecondary2 { border-color: #e5e9ed; }
|
||||||
.bordercolorSecondary { border-color: #ECECED; }
|
.borderColorSecondary { border-color: #ECECED; }
|
||||||
.borderColorWhite { border-color: #fff; }
|
.borderColorWhite { border-color: #fff; }
|
||||||
.borderColorBrand { border-color: #21cf7a; }
|
.borderColorBrand { border-color: #21cf7a; }
|
||||||
.borderRight1PX { border-right-width: 1px; }
|
.borderRight1PX { border-right-width: 1px; }
|
||||||
@ -131,15 +132,17 @@ body {
|
|||||||
.backgroundSubtle_onHover:hover { background-color: #F5F8FA; }
|
.backgroundSubtle_onHover:hover { background-color: #F5F8FA; }
|
||||||
.backgroundSubtle2 { background-color: #e8ecef; }
|
.backgroundSubtle2 { background-color: #e8ecef; }
|
||||||
.backgroundcolorSecondary3 { background-color: #F6F6F9; }
|
.backgroundcolorSecondary3 { background-color: #F6F6F9; }
|
||||||
.backgroundWhite { background-color: #fff; }
|
.backgroundColorPrimary { background-color: #fff; }
|
||||||
.backgroundColorBrandLightOpaque { background-color: rgba(54, 233, 145, 0.1); }
|
.backgroundColorBrandLightOpaque { background-color: rgba(54, 233, 145, 0.1); }
|
||||||
.backgroundColorOpaque { background-color: rgba(0,0,0, 0.4); }
|
.backgroundColorOpaque { background-color: rgba(0,0,0, 0.4); }
|
||||||
.backgroundColorBrandLight { background-color: #36e991; }
|
.backgroundColorBrandLight { background-color: #36e991; }
|
||||||
.backgroundColorBrand { background-color: #21cf7a; }
|
.backgroundColorBrand { background-color: #21cf7a; }
|
||||||
|
.backgroundColorBrand_onHover:hover { background-color: #21cf7a; }
|
||||||
.backgroundColorBrandDark { background-color: #38A16B; }
|
.backgroundColorBrandDark { background-color: #38A16B; }
|
||||||
.backgroundColorBrandDark_onHover:hover { background-color: #38A16B; }
|
.backgroundColorBrandDark_onHover:hover { background-color: #38A16B; }
|
||||||
.colorPrimary { color: #000; }
|
.colorPrimary { color: #000; }
|
||||||
.colorWhite { color: #fff; }
|
.colorWhite { color: #fff; }
|
||||||
|
.colorWhite_onHover:hover { color: #fff; }
|
||||||
.colorSecondary { color: #4B4F55; }
|
.colorSecondary { color: #4B4F55; }
|
||||||
.colorBrand { color: #21cf7a }
|
.colorBrand { color: #21cf7a }
|
||||||
.fillColorBlack { fill: #000; }
|
.fillColorBlack { fill: #000; }
|
||||||
@ -175,9 +178,9 @@ body {
|
|||||||
.height350PX { height: 350px; }
|
.height350PX { height: 350px; }
|
||||||
|
|
||||||
.width1015PX { width: 1015px; }
|
.width1015PX { width: 1015px; }
|
||||||
.width660PX { width: 660px; }
|
.width645PX { width: 645px; }
|
||||||
.width400PX { width: 400px; }
|
.width400PX { width: 400px; }
|
||||||
.width325PX { width: 325px; }
|
.width340PX { width: 340px; }
|
||||||
.width240PX { width: 240px; }
|
.width240PX { width: 240px; }
|
||||||
.width100PC { width: 100%; }
|
.width100PC { width: 100%; }
|
||||||
.width72PX { width: 72px; }
|
.width72PX { width: 72px; }
|
||||||
@ -185,42 +188,43 @@ body {
|
|||||||
|
|
||||||
@media (min-width: 1480px) {
|
@media (min-width: 1480px) {
|
||||||
.width1015PX { width: 1080px; }
|
.width1015PX { width: 1080px; }
|
||||||
.width660PX { width: 700px; }
|
.width645PX { width: 700px; }
|
||||||
.width325PX { width: 350px; }
|
.width340PX { width: 350px; }
|
||||||
.width240PX { width: 250px; }
|
.width240PX { width: 250px; }
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 1160px) and (max-width: 1280px) {
|
@media (min-width: 1160px) and (max-width: 1280px) {
|
||||||
.width1015PX { width: 910px; }
|
.width1015PX { width: 910px; }
|
||||||
.width660PX { width: 580px; }
|
.width645PX { width: 580px; }
|
||||||
.width325PX { width: 300px; }
|
.width340PX { width: 300px; }
|
||||||
.width240PX { width: 230px; }
|
.width240PX { width: 230px; }
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 1080px) and (max-width: 1160px) {
|
@media (min-width: 1080px) and (max-width: 1160px) {
|
||||||
.width1015PX { width: 850px; }
|
.width1015PX { width: 850px; }
|
||||||
.width660PX { width: 525px; }
|
.width645PX { width: 525px; }
|
||||||
.width325PX { width: 300px; }
|
.width340PX { width: 300px; }
|
||||||
.width240PX { width: 210px; }
|
.width240PX { width: 210px; }
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 992px) and (max-width: 1080px) {
|
@media (min-width: 992px) and (max-width: 1080px) {
|
||||||
.width1015PX { width: 850px; }
|
.width1015PX { width: 850px; }
|
||||||
.width660PX { width: 525px; }
|
.width645PX { width: 525px; }
|
||||||
.width325PX { width: 300px; }
|
.width340PX { width: 300px; }
|
||||||
.width240PX { width: 100px; }
|
.width240PX { width: 100px; }
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 0px) and (max-width: 992px) {
|
@media (min-width: 0px) and (max-width: 992px) {
|
||||||
.width1015PX { width: 600px; }
|
.width1015PX { width: 600px; }
|
||||||
.width660PX { width: 600px; }
|
.width645PX { width: 600px; }
|
||||||
.width325PX { width: 0px; }
|
.width340PX { width: 0px; }
|
||||||
.width240PX { width: 100px; }
|
.width240PX { width: 100px; }
|
||||||
}
|
}
|
||||||
|
|
||||||
.top0 { top: 0; }
|
.top0 { top: 0; }
|
||||||
.top60PC { top: 60%; }
|
.top60PC { top: 60%; }
|
||||||
|
|
||||||
|
.textAlignLeft { text-align: left; }
|
||||||
.textAlignCenter { text-align: center; }
|
.textAlignCenter { text-align: center; }
|
||||||
|
|
||||||
.fontSize24PX { font-size: 24px; }
|
.fontSize24PX { font-size: 24px; }
|
||||||
|
Loading…
x
Reference in New Issue
Block a user