Commit 1c98dd28 authored by mgabdev's avatar mgabdev

Progress

parent fa66d082
......@@ -3,7 +3,6 @@
import Rails from 'rails-ujs';
export function start() {
require('font-awesome/css/font-awesome.css');
require.context('../images/', true);
try {
......
import { Fragment } from 'react';
import { Link } from 'react-router-dom';
import ImmutablePropTypes from 'react-immutable-proptypes';
import { defineMessages, injectIntl } from 'react-intl';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { me } from '../../initial_state';
import Avatar from '../avatar/avatar';
import DisplayName from '../display_name';
import IconButton from '../icon_button';
import './account.scss';
import { Fragment } from 'react'
import { NavLink } from 'react-router-dom'
import ImmutablePropTypes from 'react-immutable-proptypes'
import { defineMessages, injectIntl } from 'react-intl'
import ImmutablePureComponent from 'react-immutable-pure-component'
import { me } from '../../initial_state'
import Avatar from '../avatar/avatar'
import DisplayName from '../display_name'
import IconButton from '../icon_button'
import Icon from '../icon'
const messages = defineMessages({
follow: { id: 'account.follow', defaultMessage: 'Follow' },
......@@ -18,7 +17,7 @@ const messages = defineMessages({
unmute: { id: 'account.unmute', defaultMessage: 'Unmute @{name}' },
mute_notifications: { id: 'account.mute_notifications', defaultMessage: 'Mute notifications from @{name}' },
unmute_notifications: { id: 'account.unmute_notifications', defaultMessage: 'Unmute notifications from @{name}' },
});
})
export default @injectIntl
class Account extends ImmutablePureComponent {
......@@ -34,37 +33,36 @@ class Account extends ImmutablePureComponent {
actionIcon: PropTypes.string,
actionTitle: PropTypes.string,
onActionClick: PropTypes.func,
displayOnly: PropTypes.bool,
};
}
handleFollow = () => {
this.props.onFollow(this.props.account);
this.props.onFollow(this.props.account)
}
handleBlock = () => {
this.props.onBlock(this.props.account);
this.props.onBlock(this.props.account)
}
handleMute = () => {
this.props.onMute(this.props.account);
this.props.onMute(this.props.account)
}
handleMuteNotifications = () => {
this.props.onMuteNotifications(this.props.account, true);
this.props.onMuteNotifications(this.props.account, true)
}
handleUnmuteNotifications = () => {
this.props.onMuteNotifications(this.props.account, false);
this.props.onMuteNotifications(this.props.account, false)
}
handleAction = () => {
this.props.onActionClick(this.props.account);
this.props.onActionClick(this.props.account)
}
render() {
const { account, intl, hidden, onActionClick, actionIcon, actionTitle, displayOnly } = this.props;
const { account, intl, hidden, onActionClick, actionIcon, actionTitle } = this.props
if (!account) return null;
if (!account) return null
if (hidden) {
return (
......@@ -72,29 +70,29 @@ class Account extends ImmutablePureComponent {
{account.get('display_name')}
{account.get('username')}
</Fragment>
);
)
}
let buttons;
let buttons
if (onActionClick && actionIcon) {
buttons = <IconButton icon={actionIcon} title={actionTitle} onClick={this.handleAction} />;
buttons = <IconButton icon={actionIcon} title={actionTitle} onClick={this.handleAction} />
} else if (account.get('id') !== me && account.get('relationship', null) !== null) {
const following = account.getIn(['relationship', 'following']);
const requested = account.getIn(['relationship', 'requested']);
const blocking = account.getIn(['relationship', 'blocking']);
const muting = account.getIn(['relationship', 'muting']);
const following = account.getIn(['relationship', 'following'])
const requested = account.getIn(['relationship', 'requested'])
const blocking = account.getIn(['relationship', 'blocking'])
const muting = account.getIn(['relationship', 'muting'])
if (requested) {
buttons = <IconButton disabled icon='hourglass' title={intl.formatMessage(messages.requested)} />;
buttons = <IconButton disabled icon='hourglass' title={intl.formatMessage(messages.requested)} />
} else if (blocking) {
buttons = <IconButton active icon='unlock' title={intl.formatMessage(messages.unblock, { name: account.get('username') })} onClick={this.handleBlock} />;
buttons = <IconButton active icon='unlock' title={intl.formatMessage(messages.unblock, { name: account.get('username') })} onClick={this.handleBlock} />
} else if (muting) {
let hidingNotificationsButton;
let hidingNotificationsButton
if (account.getIn(['relationship', 'muting_notifications'])) {
hidingNotificationsButton = <IconButton active icon='bell' title={intl.formatMessage(messages.unmute_notifications, { name: account.get('username') })} onClick={this.handleUnmuteNotifications} />;
hidingNotificationsButton = <IconButton active icon='bell' title={intl.formatMessage(messages.unmute_notifications, { name: account.get('username') })} onClick={this.handleUnmuteNotifications} />
} else {
hidingNotificationsButton = <IconButton active icon='bell-slash' title={intl.formatMessage(messages.mute_notifications, { name: account.get('username') })} onClick={this.handleMuteNotifications} />;
hidingNotificationsButton = <IconButton active icon='bell-slash' title={intl.formatMessage(messages.mute_notifications, { name: account.get('username') })} onClick={this.handleMuteNotifications} />
}
buttons = (
......@@ -102,41 +100,44 @@ class Account extends ImmutablePureComponent {
<IconButton active icon='volume-up' title={intl.formatMessage(messages.unmute, { name: account.get('username') })} onClick={this.handleMute} />
{hidingNotificationsButton}
</Fragment>
);
)
} else if (!account.get('moved') || following) {
buttons = <IconButton icon={following ? 'user-times' : 'user-plus'} title={intl.formatMessage(following ? messages.unfollow : messages.follow)} onClick={this.handleFollow} active={following} />;
buttons = <IconButton icon={following ? 'user-times' : 'user-plus'} title={intl.formatMessage(following ? messages.unfollow : messages.follow)} onClick={this.handleFollow} active={following} />
}
}
if (displayOnly) {
return (
<div className='account'>
<div className='account__wrapper'>
<div className='account__display-name'>
<div className='account__avatar-wrapper'>
<Avatar account={account} size={36} />
</div>
return (
<div className={[styles.default, styles.marginTop5PX, styles.marginBottom15PX].join(' ')}>
<div className={[styles.default, styles.flexRow].join(' ')}>
<NavLink
className={[styles.default, styles.noUnderline].join(' ')}
title={account.get('acct')}
to={`/${account.get('acct')}`}
>
<Avatar account={account} size={52} />
</NavLink>
<div className={[styles.default, styles.alignItemsStart, styles.paddingHorizontal10PX].join(' ')}>
<NavLink
className={[styles.default, styles.noUnderline].join(' ')}
title={account.get('acct')}
to={`/${account.get('acct')}`}
>
<DisplayName account={account} />
</div>
</NavLink>
<button className={[styles.default, styles.marginTop5PX, styles.colorBrand, styles.text, styles.cursorPointer, styles.fontSize14PX, styles.circle, styles.border1PX, styles.borderColorBrand, styles.paddingHorizontal20PX, styles.paddingVertical5PX].join(' ')}>
{intl.formatMessage(messages.follow)}
</button>
</div>
</div>
);
}
return (
<div className='account'>
<div className='account__wrapper'>
<Link key={account.get('id')} className='account__display-name' title={account.get('acct')} to={`/${account.get('acct')}`}>
<div className='account__avatar-wrapper'><Avatar account={account} size={36} /></div>
<DisplayName account={account} />
</Link>
<div className='account__relationship'>
{buttons}
</div>
<button className={[styles.default, styles.marginLeftAuto, styles.paddingVertical2PX, styles.cursorPointer].join(' ')}>
<Icon width='14px' height='14px' />
</button>
</div>
</div>
);
)
}
}
.gab-logo {
enable-background: new 0 0 50 30;
&__path {
fill-rule: evenodd;
clip-rule: evenodd;
fill: $gab-brand-default;
}
}
\ No newline at end of file
export { default } from './gab_logo';
\ No newline at end of file
......@@ -4,8 +4,6 @@ import { makeGetAccount } from '../../selectors';
import Avatar from '../avatar';
import DisplayName from '../display_name';
import './autosuggest_account.scss';
const makeMapStateToProps = () => {
const getAccount = makeGetAccount();
......
import unicodeMapping from '../emoji/emoji_unicode_mapping_light';
import './autosuggest_emoji.scss';
const assetHost = process.env.CDN_HOST || '';
export default class AutosuggestEmoji extends PureComponent {
......
import { Fragment } from 'react'
import ImmutablePropTypes from 'react-immutable-proptypes';
import classNames from 'classnames';
import ImmutablePureComponent from 'react-immutable-pure-component';
......@@ -7,8 +8,6 @@ import { textAtCursorMatchesToken } from '../../utils/cursor_token_match';
import AutosuggestAccount from '../autosuggest_account';
import AutosuggestEmoji from '../autosuggest_emoji';
import './autosuggest_textbox.scss';
export default class AutosuggestTextbox extends ImmutablePureComponent {
static propTypes = {
......@@ -198,15 +197,13 @@ export default class AutosuggestTextbox extends ImmutablePureComponent {
}
if (textarea) {
return [
<div className='autosuggest-textarea__wrapper' key='autosuggest-textarea__wrapper'>
<div className='autosuggest-textarea'>
<label>
<span style={{ display: 'none' }}>{placeholder}</span>
return (
<Fragment>
<div className={[styles.default].join(' ')}>
<div className={[styles.default, styles.marginLeft5PX].join(' ')}>
<Textarea
inputRef={this.setTextbox}
className='autosuggest-textarea__textarea'
className={[styles.default, styles.backgroundWhite, styles.lineHeight125, styles.resizeNone, styles.paddingVertical15PX, styles.outlineNone, styles.fontSize16PX, styles.text, styles.displayBlock].join(' ')}
disabled={disabled}
placeholder={placeholder}
autoFocus={autoFocus}
......@@ -220,16 +217,16 @@ export default class AutosuggestTextbox extends ImmutablePureComponent {
style={style}
aria-autocomplete='list'
/>
</label>
</div>
{children}
</div>
{children}
</div>,
<div className='autosuggest-textarea__suggestions-wrapper' key='autosuggest-textarea__suggestions-wrapper'>
<div className={`autosuggest-textarea__suggestions ${suggestionsHidden || suggestions.isEmpty() ? '' : 'autosuggest-textarea__suggestions--visible'}`}>
{suggestions.map(this.renderSuggestion)}
<div className='autosuggest-textarea__suggestions-wrapper'>
<div className={`autosuggest-textarea__suggestions ${suggestionsHidden || suggestions.isEmpty() ? '' : 'autosuggest-textarea__suggestions--visible'}`}>
{suggestions.map(this.renderSuggestion)}
</div>
</div>
</div>,
];
</Fragment>
)
}
return (
......
import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { Map as ImmutableMap } from 'immutable';
import classNames from 'classnames';
import { autoPlayGif } from '../../initial_state';
import './avatar.scss';
import ImmutablePropTypes from 'react-immutable-proptypes'
import ImmutablePureComponent from 'react-immutable-pure-component'
import { Map as ImmutableMap } from 'immutable'
import classNames from 'classnames'
import { autoPlayGif } from '../../initial_state'
export default class Avatar extends ImmutablePureComponent {
......@@ -13,57 +11,53 @@ export default class Avatar extends ImmutablePureComponent {
size: PropTypes.number,
inline: PropTypes.bool,
animate: PropTypes.bool,
};
}
static defaultProps = {
account: ImmutableMap(),
animate: autoPlayGif,
inline: false,
};
}
state = {
hovering: false,
sameImg: this.props.account.get('avatar') === this.props.account.get('avatar_static'),
};
}
handleMouseEnter = () => {
if (this.props.animate || this.state.sameImg) return;
if (this.props.animate || this.state.sameImg) return
this.setState({ hovering: true });
this.setState({ hovering: true })
}
handleMouseLeave = () => {
if (this.props.animate || this.state.sameImg) return;
if (this.props.animate || this.state.sameImg) return
this.setState({ hovering: false });
this.setState({ hovering: false })
}
render () {
const { account, size, animate, inline } = this.props;
const { hovering } = this.state;
const { account, size, animate, inline } = this.props
const { hovering } = this.state
// : TODO : remove inline and change all avatars to be sized using css
const style = !size ? {} : {
width: `${size}px`,
height: `${size}px`,
};
const theSrc = account.get((hovering || animate) ? 'avatar' : 'avatar_static');
}
const className = classNames('account__avatar', {
'account__avatar--inline': inline,
});
const theSrc = account.get((hovering || animate) ? 'avatar' : 'avatar_static')
return (
<img
className={className}
className={[styles.default, styles.circle].join(' ')}
onMouseEnter={this.handleMouseEnter}
onMouseLeave={this.handleMouseLeave}
style={style}
src={theSrc}
alt={account.get('display_name')}
/>
);
)
}
}
......@@ -2,8 +2,6 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { autoPlayGif } from '../../initial_state';
import './avatar_overlay.scss';
export default class AvatarOverlay extends ImmutablePureComponent {
static propTypes = {
......
import './badge.scss';
export default class Badge extends PureComponent {
static propTypes = {
type: PropTypes.oneOf([
'pro',
'donor',
'investor',
]).isRequired,
};
render() {
const { type } = this.props;
if (!type) return null;
return (
<span className={`badge badge--${type}`}>
{type.toUpperCase()}
</span>
);
}
};
.badge {
text-transform: uppercase;
padding: 2px 6px;
border-radius: 2px;
margin: 0 5px 5px 0;
@include text-sizing(12px, 600, 1, center);
&--pro {
background-color: blueviolet;
color: #fff;
}
&--investor {
background-color: gold;
color: #000;
}
&--donor {
background-color: lightgreen;
color: #000;
}
}
\ No newline at end of file
export { default } from './badge';
\ No newline at end of file
......@@ -3,8 +3,6 @@ import Column from '../column';
import { ColumnHeader } from '../column_header';
import IconButton from '../icon_button';
import './bundle_column_error.scss';
const messages = defineMessages({
title: { id: 'bundle_column_error.title', defaultMessage: 'Network error' },
body: { id: 'bundle_column_error.body', defaultMessage: 'Something went wrong while loading this component.' },
......
import { defineMessages, injectIntl } from 'react-intl';
import IconButton from '../icon_button';
import './bundle_modal_error.scss';
const messages = defineMessages({
error: { id: 'bundle_modal_error.message', defaultMessage: 'Something went wrong while loading this component.' },
retry: { id: 'bundle_modal_error.retry', defaultMessage: 'Try again' },
......
......@@ -56,10 +56,10 @@ export default class Button extends PureComponent {
colorWhite: 1,
circle: 1,
cursorPointer: 1,
width100PC: 1,
textAlignCenter: 1,
paddingVertical10PX: 1,
paddingHorizontal15PX: 1,
width100PC: block,
backgroundColorBrand: !hovering,
backgroundColorBrandDark: hovering,
})
......
......@@ -2,8 +2,6 @@ import { isMobile } from '../../utils/is_mobile';
import { ColumnHeader } from '../column_header';
import ColumnBackButton from '../column_back_button';
import './column.scss';
export default class Column extends PureComponent {
static propTypes = {
......
......@@ -2,8 +2,6 @@ import { FormattedMessage } from 'react-intl';
import classNames from 'classnames';
import Icon from '../icon';
import './column_back_button.scss';
export default class ColumnBackButton extends PureComponent {
static contextTypes = {
......
......@@ -3,8 +3,6 @@ import classNames from 'classnames';
import { injectIntl, defineMessages } from 'react-intl';
import Icon from '../icon';
import './column_header.scss';
const messages = defineMessages({
show: { id: 'column_header.show_settings', defaultMessage: 'Show settings' },
hide: { id: 'column_header.hide_settings', defaultMessage: 'Hide settings' },
......
......@@ -7,8 +7,6 @@ import { createSelector } from 'reselect';
import { fetchLists } from '../../actions/lists';
import Icon from '../icon';
import './column_header.scss';
const messages = defineMessages({
show: { id: 'column_header.show_settings', defaultMessage: 'Show settings' },
hide: { id: 'column_header.hide_settings', defaultMessage: 'Hide settings' },
......
......@@ -2,8 +2,6 @@ import { Link } from 'react-router-dom';
import classNames from 'classnames';
import Icon from '../icon';
import './column_header_setting_button.scss';
export default class ColumnHeaderSettingButton extends PureComponent {
static propTypes = {
......
import { defineMessages, injectIntl } from 'react-intl';
import Column from '../column';
import './column_indicator.scss';
const messages = defineMessages({
loading: { id: 'loading_indicator.label', defaultMessage: 'Loading...' },
missing: { id: 'missing_indicator.sublabel', defaultMessage: 'This resource could not be found.' },
......
import Button from '../button';
import './column_inline_form.scss';
export default class ColumnInlineForm extends PureComponent {
static propTypes = {
......
import { Link } from 'react-router-dom';
import Icon from '../../components/icon';
import './column_link.scss';
export default class ColumnLink extends PureComponent {
static propTypes = {
......
import './column_settings_heading.scss';
export default class ColumnSettingsHeading extends PureComponent {
static propTypes = {
heading: PropTypes.object.isRequired,
......
import './column_subheading.scss';
export default class ColumnSubheading extends PureComponent {
static propTypes = {
text: PropTypes.string.isRequired,
......
import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
import Icon from './icon';
export default class DisplayName extends ImmutablePureComponent {
static propTypes = {
account: ImmutablePropTypes.map.isRequired,
};
render () {
const { account } = this.props;
return (
<span className={[styles.default, styles.flexRow, styles.maxWidth100PC, styles.alignItemsCenter].join(' ')}>
<bdi className={[styles.text, styles.whiteSpaceNoWrap, styles.textOverflowEllipsis].join(' ')}>
<strong
className={[styles.text, styles.overflowWrapBreakWord, styles.whiteSpaceNoWrap, styles.fontSize15PX, styles.fontWeightBold, styles.colorBlack, styles.lineHeight125, styles.marginRight2PX].join(' ')}
dangerouslySetInnerHTML={{ __html: account.get('display_name_html') }}
/>
</bdi>
{
account.get('is_verified') &&
<Icon id='verified' width='15px' height='15px' className={[styles.default]} title='Verified Account' />
/*<Icon id='verified' width='15px' height='15px' className={[styles.default]} title='PRO' />
<Icon id='verified' width='15px' height='15px' className={[styles.default]} title='Donor' />
<Icon id='verified' width='15px' height='15px' className={[styles.default]} title='Investor' />*/