Commit 3d0a85cd authored by mgabdev's avatar mgabdev

Progress

parent 0f01c1bc
import classNames from 'classnames/bind'
const cx = classNames.bind(_s)
// : todo :
export default class AccountActionButton extends PureComponent {
static propTypes = {
children: PropTypes.any,
size: PropTypes.oneOf(Object.keys(SIZES)),
center: PropTypes.bool,
}
static defaultProps = {
size: SIZES.h1,
}
render() {
const { children, size, center } = this.props
const classes = cx({
default: 1,
text: 1,
textAlignCenter: center,
colorPrimary: [SIZES.h1, SIZES.h3].indexOf(size) > -1,
colorSecondary: [SIZES.h2, SIZES.h4, SIZES.h5].indexOf(size) > -1,
fontSize24PX: size === SIZES.h1,
fontSize19PX: size === SIZES.h2,
fontSize16PX: size === SIZES.h3,
fontSize13PX: size === SIZES.h4,
fontSize12PX: size === SIZES.h5,
mt5: [SIZES.h2, SIZES.h4].indexOf(size) > -1,
lineHeight2: size === SIZES.h5,
py2: size === SIZES.h5,
// fontWeightNormal: weight === WEIGHTS.normal,
fontWeightMedium: [SIZES.h1, SIZES.h5].indexOf(size) > -1,
fontWeightBold: [SIZES.h3, SIZES.h4].indexOf(size) > -1,
})
return React.createElement(
size,
{
className: classes,
role: 'heading',
},
children,
)
}
}
\ No newline at end of file
import { defineMessages, injectIntl } from 'react-intl'
import IconButton from './icon_button'
import Button from './button'
const messages = defineMessages({
title: { id: 'bundle_column_error.title', defaultMessage: 'Network error' },
......@@ -25,7 +25,7 @@ class BundleColumnError extends PureComponent {
return (
<div className='error-column'>
<IconButton title={formatMessage(messages.retry)} icon='refresh' onClick={this.handleRetry} size={64} />
<Button title={formatMessage(messages.retry)} icon='refresh' onClick={this.handleRetry} size={64} />
{formatMessage(messages.body)}
</div>
)
......
import { defineMessages, injectIntl } from 'react-intl';
import IconButton from './icon_button';
import Button from './button';
const messages = defineMessages({
error: { id: 'bundle_modal_error.message', defaultMessage: 'Something went wrong while loading this component.' },
......@@ -29,7 +29,7 @@ class BundleModalError extends PureComponent {
return (
<div className='modal-root__modal error-modal'>
<div className='error-modal__body'>
<IconButton title={formatMessage(messages.retry)} icon='refresh' onClick={this.handleRetry} size={64} />
<Button title={formatMessage(messages.retry)} icon='refresh' onClick={this.handleRetry} size={64} />
{formatMessage(messages.error)}
</div>
......
......@@ -10,8 +10,9 @@ const COLORS = {
secondary: 'secondary',
tertiary: 'tertiary',
white: 'white',
black: 'black',
brand: 'brand',
error: 'error',
danger: 'danger',
none: 'none',
}
......@@ -87,12 +88,11 @@ export default class Button extends PureComponent {
<Icon
id={icon}
width={iconWidth}
height={iconWidth}
height={iconHeight}
className={iconClassName}
/>
) : undefined
// : todo :
const classes = noClasses ? className : cx(className, {
default: 1,
noUnderline: 1,
......@@ -101,18 +101,22 @@ export default class Button extends PureComponent {
textAlignCenter: 1,
outlineNone: 1,
flexRow: !!children && !!icon,
cursorNotAllowed: disabled,
opacity05: disabled,
backgroundColorPrimary: backgroundColor === COLORS.white,
backgroundColorBlack: backgroundColor === COLORS.black,
backgroundColorBrand: backgroundColor === COLORS.brand,
backgroundTransparent: backgroundColor === COLORS.none,
backgroundSubtle2: backgroundColor === COLORS.tertiary,
backgroundSubtle: backgroundColor === COLORS.secondary,
colorPrimary: color === COLORS.primary,
colorSecondary: color === COLORS.secondary,
colorTertiary: color === COLORS.tertiary,
colorWhite: color === COLORS.white,
colorBrand: color === COLORS.brand,
backgroundColorDanger: backgroundColor === COLORS.danger,
colorPrimary: !!children && color === COLORS.primary,
colorSecondary: !!children && color === COLORS.secondary,
colorTertiary: !!children && color === COLORS.tertiary,
colorWhite: !!children && color === COLORS.white,
colorBrand: !!children && color === COLORS.brand,
borderColorBrand: color === COLORS.brand && outline,
border1PX: outline,
......@@ -128,12 +132,16 @@ export default class Button extends PureComponent {
underline_onHover: underlineOnHover,
backgroundSubtle2Dark_onHover: backgroundColor === COLORS.tertiary,
backgroundSubtle2Dark_onHover: backgroundColor === COLORS.tertiary || backgroundColor === COLORS.secondary,
backgroundColorBlackOpaque_onHover: backgroundColor === COLORS.black,
backgroundColorBrandDark_onHover: backgroundColor === COLORS.brand,
backgroundColorBrand_onHover: color === COLORS.brand && outline,
colorWhite_onHover: color === COLORS.brand && outline,
colorWhite_onHover: !!children && color === COLORS.brand && outline,
fillColorWhite: !!icon && color === COLORS.white,
fillColorBrand: !!icon && color === COLORS.brand,
fillColorWhite_onHover: !!icon && color === COLORS.brand && outline,
})
const tagName = !!href ? 'a' : !!to ? 'NavLink' : 'button'
......
import { defineMessages, injectIntl } from 'react-intl';
import IconButton from './icon_button';
import Button from './button';
const messages = defineMessages({
unblockDomain: { id: 'account.unblock_domain', defaultMessage: 'Unhide {domain}' },
......@@ -30,7 +30,7 @@ class Domain extends PureComponent {
</span>
<div className='domain__buttons'>
<IconButton
<Button
active
icon='unlock'
title={intl.formatMessage(messages.unblockDomain, {
......
......@@ -14,9 +14,19 @@ export default class FloatingActionButton extends Component {
render() {
const { onClick, message } = this.props;
// const shouldHideFAB = path => path.match(/^\/posts\/|^\/search|^\/getting-started/);
// const floatingActionButton = shouldHideFAB(this.context.router.history.location.pathname) ? null : <button key='floating-action-button' onClick={this.handleOpenComposeModal} className='floating-action-button' aria-label={intl.formatMessage(messages.publish)}></button>;
return (
<Button onClick={onClick} className='floating-action-button' aria-label={message}>
<Button
onClick={onClick}
color='white'
className={[_s.positionFixed, _s.z4, _s.bottom0, _s.right0].join(' ')}
title={message}
aria-label={message}
>
<Icon id='compose' />
[...]
</Button>
)
}
......
import classNames from 'classnames';
import spring from 'react-motion/lib/spring';
import Motion from '../../features/ui/util/optional_motion';
import Icon from '../icon';
export default class IconButton extends PureComponent {
static propTypes = {
className: PropTypes.string,
title: PropTypes.string.isRequired,
icon: PropTypes.string.isRequired,
onClick: PropTypes.func,
size: PropTypes.number,
active: PropTypes.bool,
pressed: PropTypes.bool,
expanded: PropTypes.bool,
style: PropTypes.object,
disabled: PropTypes.bool,
inverted: PropTypes.bool,
animate: PropTypes.bool,
overlay: PropTypes.bool,
tabIndex: PropTypes.string,
text: PropTypes.string,
width: PropTypes.string,
height: PropTypes.string,
};
static defaultProps = {
size: 18,
active: false,
disabled: false,
animate: false,
overlay: false,
tabIndex: '0',
};
handleClick = (e) => {
e.preventDefault();
if (!this.props.disabled) {
this.props.onClick(e);
}
}
render () {
const style = {
// fontSize: `${this.props.size}px`,
// width: `${this.props.size * 1.28571429}px`,
// height: `${this.props.size * 1.28571429}px`,
// lineHeight: `${this.props.size}px`,
...this.props.style,
};
const {
active,
animate,
className,
disabled,
expanded,
icon,
inverted,
overlay,
pressed,
tabIndex,
title,
text,
width,
height,
} = this.props;
const classes = classNames(className, 'icon-button', {
active,
disabled,
inverted,
overlayed: overlay,
});
return (
<button
aria-label={title}
aria-pressed={pressed}
aria-expanded={expanded}
title={title}
className={classes}
onClick={this.handleClick}
style={style}
tabIndex={tabIndex}
disabled={disabled}
>
<Icon id={icon} fixedWidth aria-hidden='true' width={width} height={height} />
{!!text && text}
</button>
);
}
}
export { default } from './icon_button'
\ No newline at end of file
......@@ -20,6 +20,8 @@ export default class Input extends PureComponent {
small: PropTypes.bool,
readOnly: PropTypes.string,
inputRef: PropTypes.func,
id: PropTypes.string,
hideLabel: PropTypes.bool,
}
render() {
......@@ -36,20 +38,25 @@ export default class Input extends PureComponent {
title,
small,
readOnly,
inputRef
inputRef,
id,
hideLabel
} = this.props
const inputClasses = cx({
default: 1,
text: 1,
outlineNone: 1,
lineHeight125: 1,
lineHeight125: !small,
lineHeight1: small,
displayBlock: 1,
py10: 1,
py10: !small,
py5: small,
backgroundTransparent: !readOnly,
backgroundSubtle2: readOnly,
colorSecondary: readOnly,
fontSize15PX: 1,
fontSize15PX: !small,
fontSize13PX: small,
flexGrow1: 1,
circle: 1,
px5: !!prependIcon,
......@@ -57,12 +64,19 @@ export default class Input extends PureComponent {
pr15: !hasClear,
})
const titleClasses = cx({
default: 1,
mb10: 1,
pl15: 1,
displayNone: hideLabel,
})
return (
<Fragment>
{
!!title &&
<div className={[_s.default, _s.mb10, _s.pl15].join(' ')}>
<Text size='small' weight='medium' color='secondary'>
<div className={titleClasses}>
<Text htmlFor={id} size='small' weight='medium' color='secondary' tagName='label'>
{title}
</Text>
</div>
......@@ -74,6 +88,7 @@ export default class Input extends PureComponent {
}
<input
id={id}
className={inputClasses}
type='text'
placeholder={placeholder}
......
......@@ -7,7 +7,7 @@ import { decode } from 'blurhash';
import { autoPlayGif, displayMedia } from '../../initial_state';
import { isIOS } from '../../utils/is_mobile';
import { isPanoramic, isPortrait, isNonConformingRatio, minimumAspectRatio, maximumAspectRatio } from '../../utils/media_aspect_ratio';
import IconButton from '../icon_button';
import Button from '../button';
const messages = defineMessages({
toggle_visible: { id: 'media_gallery.toggle_visible', defaultMessage: 'Toggle visibility' },
......@@ -503,7 +503,7 @@ class MediaGallery extends PureComponent {
));
if (visible) {
spoilerButton = <IconButton title={intl.formatMessage(messages.toggle_visible)} icon='eye-slash' overlay onClick={this.handleOpen} />;
spoilerButton = <Button title={intl.formatMessage(messages.toggle_visible)} icon='eye-slash' overlay onClick={this.handleOpen} />;
} else {
spoilerButton = (
<button type='button' onClick={this.handleOpen} className='spoiler-button__overlay'>
......
......@@ -5,7 +5,7 @@ import StatusContent from '../status_content';
import Avatar from '../avatar';
import RelativeTimestamp from '../relative_timestamp';
import DisplayName from '../display_name';
import IconButton from '../icon_button';
import Button from '../button';
export default class ActionsModal extends ImmutablePureComponent {
......@@ -32,7 +32,7 @@ export default class ActionsModal extends ImmutablePureComponent {
className={classNames({ active })}
data-method={isLogout ? 'delete' : null}
>
{icon && <IconButton title={text} icon={icon} role='presentation' tabIndex='-1' inverted />}
{icon && <Button title={text} icon={icon} role='presentation' tabIndex='-1' inverted />}
<div>
<div className={classNames({ 'actions-modal__item-label': !!meta })}>{text}</div>
<div>{meta}</div>
......
import { defineMessages, injectIntl } from 'react-intl'
import ImmutablePureComponent from 'react-immutable-pure-component'
import ImmutablePropTypes from 'react-immutable-proptypes'
import { closeModal } from '../../actions/modal'
import { changeSetting, saveSettings } from '../../actions/settings'
import ModalLayout from './modal_layout'
import Button from '../button'
import SettingSwitch from '../setting_switch'
import Text from '../text'
const messages = defineMessages({
title: { id: 'hashtag_timeline_settings', defaultMessage: 'Hashtag Timeline Settings' },
saveAndClose: { id: 'saveClose', defaultMessage: 'Save & Close' },
onlyMedia: { id: 'community.column_settings.media_only', defaultMessage: 'Media Only' },
showInSidebar: { id: 'show_in_sidebar', defaultMessage: 'Show in Sidebar' },
})
const mapStateToProps = state => ({
settings: state.getIn(['settings', 'community']),
})
const mapDispatchToProps = dispatch => {
return {
onChange(key, checked) {
dispatch(changeSetting(['community', ...key], checked))
},
onSave() {
dispatch(saveSettings())
dispatch(closeModal())
},
}
}
export default
@connect(mapStateToProps, mapDispatchToProps)
@injectIntl
class HashtagTimelineSettingsModal extends ImmutablePureComponent {
static propTypes = {
intl: PropTypes.object.isRequired,
settings: ImmutablePropTypes.map.isRequired,
onChange: PropTypes.func.isRequired,
onSave: PropTypes.func.isRequired,
}
handleSaveAndClose = () => {
this.props.onSave()
}
render() {
const { intl, settings, onChange } = this.props
// : todo :
return (
<ModalLayout
width='320'
title={intl.formatMessage(messages.title)}
>
<div className={[_s.default, _s.pb10].join(' ')}>
<SettingSwitch
prefix='community_timeline'
settings={settings}
settingPath={['shows', 'inSidebar']}
onChange={onChange}
label={intl.formatMessage(messages.showInSidebar)}
/>
</div>
<Button
centered
backgroundColor='brand'
color='white'
className={_s.justifyContentCenter}
onClick={this.handleSaveAndClose}
>
<Text color='inherit' weight='bold' align='center'>
{intl.formatMessage(messages.saveAndClose)}
</Text>
</Button>
</ModalLayout>
)
}
}
......@@ -5,7 +5,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
import Video from '../../features/video';
import ExtendedVideoPlayer from '../extended_video_player';
import IconButton from '../icon_button';
import Button from '../button';
import ImageLoader from '../image_loader';
import Icon from '../icon';
......@@ -221,7 +221,7 @@ class MediaModal extends ImmutablePureComponent {
</div>
<div className={navigationClassName}>
<IconButton className='media-modal__close' title={intl.formatMessage(messages.close)} icon='times' onClick={onClose} size={40} />
<Button className='media-modal__close' title={intl.formatMessage(messages.close)} icon='times' onClick={onClose} size={40} />
{leftNav}
{rightNav}
......
......@@ -23,6 +23,7 @@ import ConfirmationModal from './confirmation_modal'
import GroupCreateModal from './group_create_modal'
import GroupDeleteModal from './group_delete_modal'
import GroupEditorModal from './group_editor_modal'
import HashtagTimelineSettingsModal from './hashtag_timeline_settings_modal'
import HomeTimelineSettingsModal from './home_timeline_settings_modal'
import HotkeysModal from './hotkeys_modal'
import ListCreateModal from './list_create_modal'
......@@ -48,6 +49,7 @@ const MODAL_COMPONENTS = {
GROUP_CREATE: () => Promise.resolve({ default: GroupCreateModal }),
GROUP_DELETE: () => Promise.resolve({ default: GroupDeleteModal }),
GROUP_EDITOR: () => Promise.resolve({ default: GroupEditorModal }),
HASHTAG_TIMELINE_SETTINGS: () => Promise.resolve({ default: HashtagTimelineSettingsModal }),
HOME_TIMELINE_SETTINGS: () => Promise.resolve({ default: HomeTimelineSettingsModal }),
HOTKEYS: () => Promise.resolve({ default: HotkeysModal }),
LIST_CREATE: () => Promise.resolve({ default: ListCreateModal }),
......
import { defineMessages, injectIntl } from 'react-intl'
import ImmutablePureComponent from 'react-immutable-pure-component'
import Button from '../button'
import Text from '../text'
import ModalLayout from './modal_layout'
const messages = defineMessages({
title: { id: 'promo.gab_pro', defaultMessage: 'Upgrade to GabPRO' },
text: { id: 'pro_upgrade_modal.text', defaultMessage: 'Gab is fully funded by people like you. Please consider supporting us on our mission to defend free expression online for all people.' },
benefits: { id: 'pro_upgrade_modal.benefits', defaultMessage: 'Here are just some of the benefits that thousands of GabPRO members receive:' },
})
export default
@injectIntl
class HomeTimelineSettingsModal extends ImmutablePureComponent {
static propTypes = {
intl: PropTypes.object.isRequired,
}
render() {
const { intl } = this.props
return (
<div>
<Text>
{intl.formatMessage(messages.text)}
</Text>
<Text>
{intl.formatMessage(messages.benefits)}
</Text>
<div className={[_s.default, _s.my10].join(' ')}>
<Text> Schedule Posts</Text>
<Text> Get Verified</Text>
<Text> Create Groups</Text>
<Text> Larger Video and Image Uploads</Text>
<Text> Receive the PRO Badge</Text>
<Text> Remove in-feed promotions</Text>
</div>
<Button
centered
backgroundColor='brand'
color='white'
icon='pro'
href='https://pro.gab.com'
className={_s.justifyContentCenter}
iconClassName={[_s.mr5, _s.fillColorWhite].join(' ')}
>
<Text color='inherit' weight='bold' align='center'>
{intl.formatMessage(messages.title)}
</Text>
</Button>
</div>
)
}
}
......@@ -2,7 +2,7 @@ import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'
import ImmutablePropTypes from 'react-immutable-proptypes'
import ImmutablePureComponent from 'react-immutable-pure-component'
import StatusRevisionListContainer from '../../containers/status_revision_list_container'
import IconButton from '../icon_button'
import Button from '../button'
const messages = defineMessages({
close: { id: 'lightbox.close', defaultMessage: 'Close' },
......@@ -28,7 +28,7 @@ class StatusRevisionModal extends ImmutablePureComponent {
<h3 className='status-revisions__header__title'>
<FormattedMessage id='status_revisions.heading' defaultMessage='Revision History' />
</h3>
<IconButton className='status-revisions__close' title={intl.formatMessage(messages.close)} icon='times' onClick={onClose} size={20} />
<Button className='status-revisions__close' title={intl.formatMessage(messages.close)} icon='times' onClick={onClose} size={20} />
</div>
<div className='status-revisions__content'>
<StatusRevisionListContainer id={status.get('id')} />
......
......@@ -12,7 +12,11 @@ export default class ProgressPanel extends PureComponent {
subtitle="We are 100% funded by you"
hasBackground
>
<ProgressBar progress={monthlyExpensesComplete}/>
<ProgressBar
progress={monthlyExpensesComplete}
title={`${Math.min(parseFloat(monthlyExpensesComplete), 100)}% covered this month`}
href='https://shop.dissenter.com/category/donations'
/>
</PanelLayout>
)
}
......
import ImmutablePropTypes from 'react-immutable-proptypes'
import ImmutablePureComponent from 'react-immutable-pure-component'
import { defineMessages, injectIntl } from 'react-intl'
import PopoverLayout from './popover_layout'
import List from '../list'
export default class StatusOptionsPopover extends PureComponent {
_makeMenu = (publicStatus) => {
// const { status, intl: { formatMessage }, withDismiss, withGroupAdmin } = this.props
// const mutingConversation = status.get('muted')
const messages = defineMessages({
delete: { id: 'status.delete', defaultMessage: 'Delete' },
edit: { id: 'status.edit', defaultMessage: 'Edit' },
mention: { id: 'status.mention', defaultMessage: 'Mention @{name}' },
mute: { id: 'account.mute', defaultMessage: 'Mute @{name}' },
block: { id: 'account.block', defaultMessage: 'Block @{name}' },
reply: { id: 'status.reply', defaultMessage: 'Reply' },
comment: { id: 'status.comment', defaultMessage: 'Comment' },
more: { id: 'status.more', defaultMessage: 'More' },
share: { id: 'status.share', defaultMessage: 'Share' },
replyAll: { id: 'status.replyAll', defaultMessage: 'Reply to thread' },
repost: { id: 'repost', defaultMessage: 'Repost' },
quote: { id: 'status.quote', defaultMessage: 'Quote' },
repost_private: { id: 'status.repost_private', defaultMessage: 'Repost to original audience' },
cancel_repost_private: { id: 'status.cancel_repost_private', defaultMessage: 'Un-repost' },
cannot_repost: { id: 'status.cannot_repost', defaultMessage: 'This post cannot be reposted' },
cannot_quote: { id: 'status.cannot_quote', defaultMessage: 'This post cannot be quoted' },
like: { id: 'status.like', defaultMessage: 'Like' },
open: { id: 'status.open', defaultMessage: 'Expand this status' },
report: { id: 'status.report', defaultMessage: 'Report @{name}' },
muteConversation: { id: 'status.mute_conversation', defaultMessage: 'Mute conversation' },
unmuteConversation: { id: 'status.unmute_conversation', defaultMessage: 'Unmute conversation' },
pin: { id: 'status.pin', defaultMessage: 'Pin on profile' },