eslint --fix

This commit is contained in:
Alex Gleason 2020-04-14 13:44:40 -05:00
parent 5cf3affcd8
commit fc72e39ff4
No known key found for this signature in database
GPG key ID: 7211D1F99744FBB7
101 changed files with 1014 additions and 969 deletions

View file

@ -14,7 +14,7 @@ export function createAuthApp() {
// TODO: Add commit hash to client_name
client_name: `SoapboxFE_${(new Date()).toISOString()}`,
redirect_uris: 'urn:ietf:wg:oauth:2.0:oob',
scopes: 'read write follow push admin'
scopes: 'read write follow push admin',
}).then(response => {
dispatch(authAppCreated(response.data));
}).then(() => {
@ -23,12 +23,12 @@ export function createAuthApp() {
client_id: app.get('client_id'),
client_secret: app.get('client_secret'),
redirect_uri: 'urn:ietf:wg:oauth:2.0:oob',
grant_type: 'client_credentials'
grant_type: 'client_credentials',
});
}).then(response => {
dispatch(authAppAuthorized(response.data));
});
}
};
}
export function logIn(username, password) {
@ -40,14 +40,14 @@ export function logIn(username, password) {
redirect_uri: 'urn:ietf:wg:oauth:2.0:oob',
grant_type: 'password',
username: username,
password: password
password: password,
}).then(response => {
dispatch(authLoggedIn(response.data));
}).catch((error) => {
dispatch(showAlert('Login failed.', 'Invalid username or password.'));
throw error;
});
}
};
}
export function logOut() {
@ -60,20 +60,20 @@ export function logOut() {
export function authAppCreated(app) {
return {
type: AUTH_APP_CREATED,
app
app,
};
}
export function authAppAuthorized(app) {
return {
type: AUTH_APP_AUTHORIZED,
app
app,
};
}
export function authLoggedIn(user) {
return {
type: AUTH_LOGGED_IN,
user
user,
};
}

View file

@ -13,100 +13,100 @@ export const GROUP_EDITOR_RESET = 'GROUP_EDITOR_RESET';
export const GROUP_EDITOR_SETUP = 'GROUP_EDITOR_SETUP';
export const submit = (routerHistory) => (dispatch, getState) => {
const groupId = getState().getIn(['group_editor', 'groupId']);
const title = getState().getIn(['group_editor', 'title']);
const description = getState().getIn(['group_editor', 'description']);
const coverImage = getState().getIn(['group_editor', 'coverImage']);
const groupId = getState().getIn(['group_editor', 'groupId']);
const title = getState().getIn(['group_editor', 'title']);
const description = getState().getIn(['group_editor', 'description']);
const coverImage = getState().getIn(['group_editor', 'coverImage']);
if (groupId === null) {
dispatch(create(title, description, coverImage, routerHistory));
} else {
dispatch(update(groupId, title, description, coverImage, routerHistory));
}
if (groupId === null) {
dispatch(create(title, description, coverImage, routerHistory));
} else {
dispatch(update(groupId, title, description, coverImage, routerHistory));
}
};
export const create = (title, description, coverImage, routerHistory) => (dispatch, getState) => {
if (!getState().get('me')) return;
if (!getState().get('me')) return;
dispatch(createRequest());
dispatch(createRequest());
const formData = new FormData();
formData.append('title', title);
formData.append('description', description);
const formData = new FormData();
formData.append('title', title);
formData.append('description', description);
if (coverImage !== null) {
formData.append('cover_image', coverImage);
}
if (coverImage !== null) {
formData.append('cover_image', coverImage);
}
api(getState).post('/api/v1/groups', formData, { headers: { 'Content-Type': 'multipart/form-data' } }).then(({ data }) => {
dispatch(createSuccess(data));
routerHistory.push(`/groups/${data.id}`);
}).catch(err => dispatch(createFail(err)));
};
api(getState).post('/api/v1/groups', formData, { headers: { 'Content-Type': 'multipart/form-data' } }).then(({ data }) => {
dispatch(createSuccess(data));
routerHistory.push(`/groups/${data.id}`);
}).catch(err => dispatch(createFail(err)));
};
export const createRequest = id => ({
type: GROUP_CREATE_REQUEST,
id,
type: GROUP_CREATE_REQUEST,
id,
});
export const createSuccess = group => ({
type: GROUP_CREATE_SUCCESS,
group,
type: GROUP_CREATE_SUCCESS,
group,
});
export const createFail = error => ({
type: GROUP_CREATE_FAIL,
error,
type: GROUP_CREATE_FAIL,
error,
});
export const update = (groupId, title, description, coverImage, routerHistory) => (dispatch, getState) => {
if (!getState().get('me')) return;
if (!getState().get('me')) return;
dispatch(updateRequest());
dispatch(updateRequest());
const formData = new FormData();
formData.append('title', title);
formData.append('description', description);
const formData = new FormData();
formData.append('title', title);
formData.append('description', description);
if (coverImage !== null) {
formData.append('cover_image', coverImage);
}
if (coverImage !== null) {
formData.append('cover_image', coverImage);
}
api(getState).put(`/api/v1/groups/${groupId}`, formData, { headers: { 'Content-Type': 'multipart/form-data' } }).then(({ data }) => {
dispatch(updateSuccess(data));
routerHistory.push(`/groups/${data.id}`);
}).catch(err => dispatch(updateFail(err)));
};
api(getState).put(`/api/v1/groups/${groupId}`, formData, { headers: { 'Content-Type': 'multipart/form-data' } }).then(({ data }) => {
dispatch(updateSuccess(data));
routerHistory.push(`/groups/${data.id}`);
}).catch(err => dispatch(updateFail(err)));
};
export const updateRequest = id => ({
type: GROUP_UPDATE_REQUEST,
id,
type: GROUP_UPDATE_REQUEST,
id,
});
export const updateSuccess = group => ({
type: GROUP_UPDATE_SUCCESS,
group,
type: GROUP_UPDATE_SUCCESS,
group,
});
export const updateFail = error => ({
type: GROUP_UPDATE_FAIL,
error,
type: GROUP_UPDATE_FAIL,
error,
});
export const changeValue = (field, value) => ({
type: GROUP_EDITOR_VALUE_CHANGE,
field,
value,
type: GROUP_EDITOR_VALUE_CHANGE,
field,
value,
});
export const reset = () => ({
type: GROUP_EDITOR_RESET
type: GROUP_EDITOR_RESET,
});
export const setUp = (group) => ({
type: GROUP_EDITOR_SETUP,
group,
type: GROUP_EDITOR_SETUP,
group,
});

View file

@ -193,7 +193,7 @@ export function joinGroupRequest(id) {
export function joinGroupSuccess(relationship) {
return {
type: GROUP_JOIN_SUCCESS,
relationship
relationship,
};
};

View file

@ -5,7 +5,7 @@ export const INSTANCE_FAIL = 'INSTANCE_FAIL';
export function fetchInstance() {
return (dispatch, getState) => {
api(getState).get(`/api/v1/instance`).then(response => {
api(getState).get('/api/v1/instance').then(response => {
dispatch(importInstance(response.data));
}).catch(error => {
dispatch(instanceFail(error));
@ -16,7 +16,7 @@ export function fetchInstance() {
export function importInstance(instance) {
return {
type: INSTANCE_IMPORT,
instance
instance,
};
}

View file

@ -9,9 +9,9 @@ export const ME_FETCH_SKIP = 'ME_FETCH_SKIP';
export function fetchMe() {
return (dispatch, getState) => {
const accessToken = getState().getIn(['auth', 'user', 'access_token']);
if (!accessToken) return dispatch({type: ME_FETCH_SKIP});
if (!accessToken) return dispatch({ type: ME_FETCH_SKIP });
dispatch(fetchMeRequest());
api(getState).get(`/api/v1/accounts/verify_credentials`).then(response => {
api(getState).get('/api/v1/accounts/verify_credentials').then(response => {
dispatch(fetchMeSuccess(response.data));
dispatch(importFetchedAccount(response.data));
}).catch(error => {
@ -29,7 +29,7 @@ export function fetchMeRequest() {
export function fetchMeSuccess(me) {
return {
type: ME_FETCH_SUCCESS,
me
me,
};
}

View file

@ -47,7 +47,7 @@ const fetchRelatedRelationships = (dispatch, notifications) => {
export function initializeNotifications() {
return {
type: NOTIFICATIONS_INITIALIZE
type: NOTIFICATIONS_INITIALIZE,
};
}
@ -115,11 +115,10 @@ export function updateNotificationsQueue(notification, intlMessages, intlLocale,
intlMessages,
intlLocale,
});
}
else {
} else {
dispatch(updateNotifications(notification, intlMessages, intlLocale));
}
}
};
};
export function dequeueNotifications() {
@ -129,13 +128,11 @@ export function dequeueNotifications() {
if (totalQueuedNotificationsCount == 0) {
return;
}
else if (totalQueuedNotificationsCount > 0 && totalQueuedNotificationsCount <= MAX_QUEUED_NOTIFICATIONS) {
} else if (totalQueuedNotificationsCount > 0 && totalQueuedNotificationsCount <= MAX_QUEUED_NOTIFICATIONS) {
queuedNotifications.forEach(block => {
dispatch(updateNotifications(block.notification, block.intlMessages, block.intlLocale));
});
}
else {
} else {
dispatch(expandNotifications());
}
@ -143,7 +140,7 @@ export function dequeueNotifications() {
type: NOTIFICATIONS_DEQUEUE,
});
dispatch(markReadNotifications());
}
};
};
const excludeTypesFromSettings = state => state.getIn(['settings', 'notifications', 'shows']).filter(enabled => !enabled).keySeq().toJS();
@ -240,7 +237,7 @@ export function scrollTopNotifications(top) {
top,
});
dispatch(markReadNotifications());
}
};
}
export function setFilter (filterType) {
@ -262,12 +259,12 @@ export function markReadNotifications() {
const last_read = getState().getIn(['notifications', 'lastRead']);
if (top_notification && top_notification > last_read) {
api(getState).post('/api/v1/notifications/mark_read', {id: top_notification}).then(response => {
api(getState).post('/api/v1/notifications/mark_read', { id: top_notification }).then(response => {
dispatch({
type: NOTIFICATIONS_MARK_READ,
notification: top_notification,
});
});
}
}
};
}

View file

@ -5,7 +5,7 @@ export const PATRON_FUNDING_FETCH_FAIL = 'PATRON_FUNDING_FETCH_FAIL';
export function fetchFunding() {
return (dispatch, getState) => {
api(getState).get(`/patron/v1/funding`).then(response => {
api(getState).get('/patron/v1/funding').then(response => {
dispatch(importFetchedFunding(response.data));
}).then(() => {
dispatch(fetchFundingSuccess());
@ -18,7 +18,7 @@ export function fetchFunding() {
export function importFetchedFunding(funding) {
return {
type: PATRON_FUNDING_IMPORT,
funding
funding,
};
}

View file

@ -5,7 +5,7 @@ export const SOAPBOX_CONFIG_FAIL = 'SOAPBOX_CONFIG_FAIL';
export function fetchSoapboxConfig() {
return (dispatch, getState) => {
api(getState).get(`/soapbox/soapbox.json`).then(response => {
api(getState).get('/soapbox/soapbox.json').then(response => {
dispatch(importSoapboxConfig(response.data));
}).catch(error => {
dispatch(soapboxConfigFail(error));
@ -16,7 +16,7 @@ export function fetchSoapboxConfig() {
export function importSoapboxConfig(soapboxConfig) {
return {
type: SOAPBOX_CONFIG_IMPORT,
soapboxConfig
soapboxConfig,
};
}

View file

@ -45,7 +45,7 @@ export function updateTimelineQueue(timeline, status, accept) {
timeline,
status,
});
}
};
};
export function dequeueTimeline(timeline, expandFunc, optionalExpandArgs) {
@ -57,27 +57,22 @@ export function dequeueTimeline(timeline, expandFunc, optionalExpandArgs) {
if (totalQueuedItemsCount == 0) {
return;
}
else if (totalQueuedItemsCount > 0 && totalQueuedItemsCount <= MAX_QUEUED_ITEMS) {
} else if (totalQueuedItemsCount > 0 && totalQueuedItemsCount <= MAX_QUEUED_ITEMS) {
queuedItems.forEach(status => {
dispatch(updateTimeline(timeline, status.toJS(), null));
});
}
else {
} else {
if (typeof expandFunc === 'function') {
dispatch(clearTimeline(timeline));
expandFunc();
}
else {
} else {
if (timeline === 'home') {
dispatch(clearTimeline(timeline));
dispatch(expandHomeTimeline(optionalExpandArgs));
}
else if (timeline === 'community') {
} else if (timeline === 'community') {
dispatch(clearTimeline(timeline));
dispatch(expandCommunityTimeline(optionalExpandArgs));
}
else {
} else {
shouldDispatchDequeue = false;
}
}
@ -89,7 +84,7 @@ export function dequeueTimeline(timeline, expandFunc, optionalExpandArgs) {
type: TIMELINE_DEQUEUE,
timeline,
});
}
};
};
export function deleteFromTimelines(id) {

View file

@ -131,7 +131,7 @@ class Account extends ImmutablePureComponent {
<span className='relationship-tag'>
<FormattedMessage id='account.follows_you' defaultMessage='Follows you' />
</span>
: '' }
: '' }
<div className='account__relationship'>
{buttons}

View file

@ -22,7 +22,7 @@ export default class DisplayName extends React.PureComponent {
<bdi key={a.get('id')}>
<strong className='display-name__html' dangerouslySetInnerHTML={{ __html: a.get('display_name_html') }} />
</bdi>,
a.get('is_verified') && <VerificationBadge />
a.get('is_verified') && <VerificationBadge />,
]).reduce((prev, cur) => [prev, ', ', cur]);
if (others.size - 2 > 0) {

View file

@ -135,7 +135,8 @@ class DropdownMenu extends React.PureComponent {
onKeyDown={this.handleItemKeyDown}
data-index={i}
target={newTab ? '_blank' : null}
data-method={isLogout ? 'delete' : null}>
data-method={isLogout ? 'delete' : null}
>
{text}
</a>
</li>

View file

@ -41,9 +41,9 @@ export default class ExtendedVideoPlayer extends React.PureComponent {
render () {
const { src, muted, controls, alt } = this.props;
let conditionalAttributes = {}
let conditionalAttributes = {};
if (isIOS()) {
conditionalAttributes.playsInline = '1'
conditionalAttributes.playsInline = '1';
}
return (

View file

@ -119,34 +119,34 @@ class ColumnHeader extends React.PureComponent {
let expandedContent = null;
if ((expandedFor === 'lists' || activeItem === 'lists') && lists) {
expandedContent = lists.map(list =>
<Link
(<Link
key={list.get('id')}
to={`/list/${list.get('id')}`}
className={
classNames('btn btn--sub grouped', {
'active': list.get('id') === activeSubItem
'active': list.get('id') === activeSubItem,
})
}
>
{list.get('title')}
</Link>
)
</Link>)
);
}
return (
<div className={wrapperClassName}>
<h1 className={buttonClassName}>
<Link to='/' className={classNames('btn grouped', {'active': 'home' === activeItem})}>
<Link to='/' className={classNames('btn grouped', { 'active': 'home' === activeItem })}>
<Icon id='home' fixedWidth className='column-header__icon' />
{formatMessage(messages.homeTitle)}
</Link>
<Link to='/timeline/local' className={classNames('btn grouped', {'active': 'local' === activeItem})}>
<Link to='/timeline/local' className={classNames('btn grouped', { 'active': 'local' === activeItem })}>
<Icon id='site-icon' fixedWidth className='column-header__icon' />
{siteTitle}
</Link>
<Link to='/timeline/fediverse' className={classNames('btn grouped', {'active': 'fediverse' === activeItem})}>
<Link to='/timeline/fediverse' className={classNames('btn grouped', { 'active': 'fediverse' === activeItem })}>
<Icon id='fediverse' fixedWidth className='column-header__icon' />
{formatMessage(messages.fediverseTitle)}
</Link>
@ -171,6 +171,7 @@ class ColumnHeader extends React.PureComponent {
</div>
);
}
}
export default injectIntl(connect(mapStateToProps)(ColumnHeader));

View file

@ -16,7 +16,7 @@ export default class Icon extends React.PureComponent {
// tag. There is a common adblocker rule which hides elements with
// alt='retweet' unless the domain is twitter.com. This should
// change what screenreaders call it as well.
var alt_id = (id == "retweet") ? "repost" : id;
var alt_id = (id == 'retweet') ? 'repost' : id;
return (
<i role='img' alt={alt_id} className={classNames('fa', `fa-${id}`, className, { 'fa-fw': fixedWidth })} {...other} />
);

View file

@ -4,19 +4,19 @@ import Icon from 'gabsocial/components/icon';
import { shortNumberFormat } from 'gabsocial/utils/numbers';
const IconWithBadge = ({ id, count, className }) => {
if (count < 1) return null;
if (count < 1) return null;
return (
<i className='icon-with-badge'>
{count > 0 && <i className='icon-with-badge__badge'>{shortNumberFormat(count)}</i>}
</i>
)
return (
<i className='icon-with-badge'>
{count > 0 && <i className='icon-with-badge__badge'>{shortNumberFormat(count)}</i>}
</i>
);
};
IconWithBadge.propTypes = {
id: PropTypes.string.isRequired,
count: PropTypes.number.isRequired,
className: PropTypes.string,
id: PropTypes.string.isRequired,
count: PropTypes.number.isRequired,
className: PropTypes.string,
};
export default IconWithBadge;

View file

@ -178,12 +178,12 @@ class Item extends React.PureComponent {
</a>
);
} else if (attachment.get('type') === 'gifv') {
let conditionalAttributes = {}
let conditionalAttributes = {};
if (isIOS()) {
conditionalAttributes.playsInline = '1'
conditionalAttributes.playsInline = '1';
}
if (autoPlayGif) {
conditionalAttributes.autoPlay = '1'
conditionalAttributes.autoPlay = '1';
}
thumbnail = (
@ -329,12 +329,12 @@ class MediaGallery extends React.PureComponent {
if (isPortrait(ar1) && isPortrait(ar2)) {
itemsDimensions = [
{ w: 50, h: '100%', r: '2px' },
{ w: 50, h: '100%', l: '2px' }
{ w: 50, h: '100%', l: '2px' },
];
} else if (isPanoramic(ar1) && isPanoramic(ar2)) {
itemsDimensions = [
{ w: 100, h: panoSize_px, b: '2px' },
{ w: 100, h: panoSize_px, t: '2px' }
{ w: 100, h: panoSize_px, t: '2px' },
];
} else if (
(isPanoramic(ar1) && isPortrait(ar2)) ||
@ -355,7 +355,7 @@ class MediaGallery extends React.PureComponent {
} else {
itemsDimensions = [
{ w: 50, h: '100%', r: '2px' },
{ w: 50, h: '100%', l: '2px' }
{ w: 50, h: '100%', l: '2px' },
];
}
} else if (size == 3) {
@ -371,19 +371,19 @@ class MediaGallery extends React.PureComponent {
if (isPanoramic(ar1) && isNonConformingRatio(ar2) && isNonConformingRatio(ar3)) {
itemsDimensions = [
{ w: 100, h: `50%`, b: '2px' },
{ w: 100, h: '50%', b: '2px' },
{ w: 50, h: '50%', t: '2px', r: '2px' },
{ w: 50, h: '50%', t: '2px', l: '2px' }
{ w: 50, h: '50%', t: '2px', l: '2px' },
];
} else if (isPanoramic(ar1) && isPanoramic(ar2) && isPanoramic(ar3)) {
itemsDimensions = [
{ w: 100, h: panoSize_px, b: '4px' },
{ w: 100, h: panoSize_px },
{ w: 100, h: panoSize_px, t: '4px' }
{ w: 100, h: panoSize_px, t: '4px' },
];
} else if (isPortrait(ar1) && isNonConformingRatio(ar2) && isNonConformingRatio(ar3)) {
itemsDimensions = [
{ w: 50, h: `100%`, r: '2px' },
{ w: 50, h: '100%', r: '2px' },
{ w: 50, h: '50%', b: '2px', l: '2px' },
{ w: 50, h: '50%', t: '2px', l: '2px' },
];
@ -391,7 +391,7 @@ class MediaGallery extends React.PureComponent {
itemsDimensions = [
{ w: 50, h: '50%', b: '2px', r: '2px' },
{ w: 50, h: '50%', l: '-2px', b: '-2px', pos: 'absolute', float: 'none' },
{ w: 50, h: `100%`, r: '-2px', t: '0px', b: '0px', pos: 'absolute', float: 'none' }
{ w: 50, h: '100%', r: '-2px', t: '0px', b: '0px', pos: 'absolute', float: 'none' },
];
} else if (
(isNonConformingRatio(ar1) && isPortrait(ar2) && isNonConformingRatio(ar3)) ||
@ -399,8 +399,8 @@ class MediaGallery extends React.PureComponent {
) {
itemsDimensions = [
{ w: 50, h: '50%', b: '2px', r: '2px' },
{ w: 50, h: `100%`, l: '2px', float: 'right' },
{ w: 50, h: '50%', t: '2px', r: '2px' }
{ w: 50, h: '100%', l: '2px', float: 'right' },
{ w: 50, h: '50%', t: '2px', r: '2px' },
];
} else if (
(isPanoramic(ar1) && isPanoramic(ar2) && isNonConformingRatio(ar3)) ||
@ -409,7 +409,7 @@ class MediaGallery extends React.PureComponent {
itemsDimensions = [
{ w: 50, h: panoSize_px, b: '2px', r: '2px' },
{ w: 50, h: panoSize_px, b: '2px', l: '2px' },
{ w: 100, h: `${width - panoSize}px`, t: '2px' }
{ w: 100, h: `${width - panoSize}px`, t: '2px' },
];
} else if (
(isNonConformingRatio(ar1) && isPanoramic(ar2) && isPanoramic(ar3)) ||
@ -424,7 +424,7 @@ class MediaGallery extends React.PureComponent {
itemsDimensions = [
{ w: 50, h: '50%', b: '2px', r: '2px' },
{ w: 50, h: '50%', b: '2px', l: '2px' },
{ w: 100, h: `50%`, t: '2px' }
{ w: 100, h: '50%', t: '2px' },
];
}
} else if (size == 4) {
@ -471,7 +471,7 @@ class MediaGallery extends React.PureComponent {
{ w: 67, h: '100%', r: '2px' },
{ w: 33, h: '33%', b: '4px', l: '2px' },
{ w: 33, h: '33%', l: '2px' },
{ w: 33, h: '33%', t: '4px', l: '2px' }
{ w: 33, h: '33%', t: '4px', l: '2px' },
];
} else {
itemsDimensions = [

View file

@ -19,7 +19,7 @@ const mapDispatchToProps = (dispatch) => ({
},
onCancelReplyCompose() {
dispatch(cancelReplyCompose());
}
},
});
class ModalRoot extends React.PureComponent {
@ -57,8 +57,7 @@ class ModalRoot extends React.PureComponent {
onConfirm: () => onCancelReplyCompose(),
onCancel: () => onOpenModal('COMPOSE'),
});
}
else {
} else {
this.props.onClose();
}
};
@ -124,6 +123,7 @@ class ModalRoot extends React.PureComponent {
</div>
);
}
}
export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(ModalRoot));

View file

@ -3,13 +3,15 @@ import ImmutablePureComponent from 'react-immutable-pure-component';
export default class ProgressBar extends ImmutablePureComponent {
render() {
const { progress } = this.props;
return (
<div className='progress-bar'>
<div className='progress-bar__progress' style={{width: `${Math.floor(progress*100)}%`}}></div>
<div className='progress-bar__progress' style={{ width: `${Math.floor(progress*100)}%` }} />
</div>
)
);
}
};

View file

@ -27,11 +27,11 @@ const messages = defineMessages({
mutes: { id: 'navigation_bar.mutes', defaultMessage: 'Muted users' },
filters: { id: 'navigation_bar.filters', defaultMessage: 'Muted words' },
logout: { id: 'navigation_bar.logout', defaultMessage: 'Logout' },
lists: { id: 'column.lists', defaultMessage: 'Lists', },
lists: { id: 'column.lists', defaultMessage: 'Lists' },
apps: { id: 'tabs_bar.apps', defaultMessage: 'Apps' },
news: { id: 'tabs_bar.news', defaultMessage: 'News' },
donate: { id: 'donate', defaultMessage: 'Donate' },
})
});
const mapStateToProps = state => {
const me = state.get('me');
@ -92,7 +92,7 @@ class SidebarMenu extends ImmutablePureComponent {
</Link>
</div>
<div className='sidebar-menu-profile__name'>
<DisplayName account={account}/>
<DisplayName account={account} />
</div>
<div className='sidebar-menu-profile__stats'>
@ -113,7 +113,7 @@ class SidebarMenu extends ImmutablePureComponent {
<Icon id='user' />
<span className='sidebar-menu-item__title'>{intl.formatMessage(messages.profile)}</span>
</NavLink>
<NavLink className='sidebar-menu-item' to={`/messages`} onClick={onClose}>
<NavLink className='sidebar-menu-item' to={'/messages'} onClick={onClose}>
<Icon id='envelope' />
<span className='sidebar-menu-item__title'>{intl.formatMessage(messages.messages)}</span>
</NavLink>

View file

@ -303,20 +303,22 @@ class Status extends ImmutablePureComponent {
prepend = (
<div className='status__prepend'>
<div className='status__prepend-icon-wrapper'><Icon id='retweet' className='status__prepend-icon' fixedWidth /></div>
<FormattedMessage id='status.reblogged_by' defaultMessage='{name} reposted' values={{
name: <NavLink to={`/@${status.getIn(['account', 'acct'])}`} className='status__display-name muted'>
<bdi>
<strong dangerouslySetInnerHTML={display_name_html} />
</bdi>
</NavLink>
}} />
<FormattedMessage
id='status.reblogged_by' defaultMessage='{name} reposted' values={{
name: <NavLink to={`/@${status.getIn(['account', 'acct'])}`} className='status__display-name muted'>
<bdi>
<strong dangerouslySetInnerHTML={display_name_html} />
</bdi>
</NavLink>,
}}
/>
</div>
);
rebloggedByText = intl.formatMessage({ id: 'status.reblogged_by', defaultMessage: '{name} reposted' }, { name: status.getIn(['account', 'acct']) });
account = status.get('account');
reblogContent = status.get('contentHtml')
reblogContent = status.get('contentHtml');
status = status.get('reblog');
}

View file

@ -298,6 +298,7 @@ class StatusActionBar extends ImmutablePureComponent {
</div>
);
}
}
const mapStateToProps = state => {
@ -314,4 +315,4 @@ const mapDispatchToProps = (dispatch) => ({
export default injectIntl(
connect(mapStateToProps, mapDispatchToProps, null, { forwardRef: true }
)(StatusActionBar))
)(StatusActionBar));

View file

@ -141,7 +141,7 @@ export default class StatusList extends ImmutablePureComponent {
<TimelineQueueButtonHeader key='timeline-queue-button-header' onClick={this.handleDequeueTimeline} count={totalQueuedItemsCount} itemType='post' />,
<ScrollableList key='scrollable-list' {...other} isLoading={isLoading} showLoading={isLoading && statusIds.size === 0} onLoadMore={onLoadMore && this.handleLoadOlder} ref={this.setRef}>
{scrollableContent}
</ScrollableList>
</ScrollableList>,
];
}

View file

@ -5,6 +5,7 @@ import { shortNumberFormat } from '../utils/numbers';
import classNames from 'classnames';
export default class TimelineQueueButtonHeader extends React.PureComponent {
static propTypes = {
onClick: PropTypes.func.isRequired,
count: PropTypes.number,
@ -20,7 +21,7 @@ export default class TimelineQueueButtonHeader extends React.PureComponent {
const { count, itemType, onClick } = this.props;
const classes = classNames('timeline-queue-header', {
'hidden': (count <= 0)
'hidden': (count <= 0),
});
return (
@ -38,4 +39,5 @@ export default class TimelineQueueButtonHeader extends React.PureComponent {
</div>
);
}
}

View file

@ -2,8 +2,8 @@ import React from 'react';
import Icon from './icon';
const VerificationBadge = () => (
<span className="verified-icon">
<span className="visuallyhidden">Verified Account</span>
<span className='verified-icon'>
<span className='visuallyhidden'>Verified Account</span>
</span>
);

View file

@ -40,8 +40,8 @@ const mapStateToProps = (state) => {
return {
showIntroduction,
me,
}
}
};
};
@connect(mapStateToProps)
class GabSocialMount extends React.PureComponent {

View file

@ -31,7 +31,7 @@ import { boostModal, deleteModal } from '../initial_state';
import { showAlertForError } from '../actions/alerts';
import {
createRemovedAccount,
groupRemoveStatus
groupRemoveStatus,
} from '../actions/groups';
const messages = defineMessages({

View file

@ -230,10 +230,10 @@ class Header extends ImmutablePureComponent {
if (!account) {
return (
<div className='account__header'>
<div className='account__header__image account__header__image--none'></div>
<div className='account__header__image account__header__image--none' />
<div className='account__header__bar'>
<div className='account__header__extra'>
<div className='account__header__avatar'></div>
<div className='account__header__avatar' />
</div>
{
isSmallScreen &&
@ -296,15 +296,15 @@ class Header extends ImmutablePureComponent {
{
account.get('id') === me &&
<div>
<NavLink exact activeClassName='active' to={`/@${account.get('acct')}/favorites`}
/* : TODO : title={intl.formatNumber(account.get('favourite_count'))} */
<NavLink
exact activeClassName='active' to={`/@${account.get('acct')}/favorites`}
>
{ /* : TODO : shortNumberFormat(account.get('favourite_count')) */ }
<span></span>
<FormattedMessage id='navigation_bar.favourites' defaultMessage='Favorites' />
</NavLink>
<NavLink exact activeClassName='active' to={`/@${account.get('acct')}/pins`}
/* : TODO : title={intl.formatNumber(account.get('pinned_count'))} */
<NavLink
exact activeClassName='active' to={`/@${account.get('acct')}/pins`}
>
{ /* : TODO : shortNumberFormat(account.get('pinned_count')) */ }
<span></span>
@ -327,9 +327,11 @@ class Header extends ImmutablePureComponent {
{actionBtn}
{account.get('id') !== me &&
<Button className='button button-alternative-2' onClick={this.props.onDirect}>
<FormattedMessage id='account.message' defaultMessage='Message' values={{
name: account.get('acct')
}} />
<FormattedMessage
id='account.message' defaultMessage='Message' values={{
name: account.get('acct'),
}}
/>
</Button>
}
<DropdownMenuContainer items={menu} icon='ellipsis-v' size={24} direction='right' />

View file

@ -112,12 +112,12 @@ export default class MediaItem extends ImmutablePureComponent {
/>
);
} else if (['gifv', 'video'].indexOf(attachment.get('type')) !== -1) {
let conditionalAttributes = {}
let conditionalAttributes = {};
if (isIOS()) {
conditionalAttributes.playsInline = '1'
conditionalAttributes.playsInline = '1';
}
if (autoPlayGif) {
conditionalAttributes.autoPlay = '1'
conditionalAttributes.autoPlay = '1';
}
thumbnail = (
<div className={classNames('media-gallery__gifv', { autoplay: autoPlayGif })}>

View file

@ -27,8 +27,7 @@ const mapStateToProps = (state, { params: { username }, withReplies = false }) =
let accountUsername = username;
if (accountFetchError) {
accountId = null;
}
else {
} else {
let account = accounts.find(acct => username.toLowerCase() == acct.getIn(['acct'], '').toLowerCase());
accountId = account ? account.getIn(['id'], null) : -1;
accountUsername = account ? account.getIn(['acct'], '') : '';
@ -69,6 +68,7 @@ class LoadMoreMedia extends ImmutablePureComponent {
/>
);
}
}
export default @connect(mapStateToProps)
@ -94,8 +94,7 @@ class AccountGallery extends ImmutablePureComponent {
if (accountId && accountId !== -1) {
this.props.dispatch(fetchAccount(accountId));
this.props.dispatch(expandAccountMediaTimeline(accountId));
}
else {
} else {
this.props.dispatch(fetchAccountByUsername(username));
}
}
@ -190,7 +189,7 @@ class AccountGallery extends ImmutablePureComponent {
<Column>
<div className='slist slist--flex' onScroll={this.handleScroll}>
<div className='account__section-headline'>
<div style={{width: '100%', display: 'flex'}}>
<div style={{ width: '100%', display: 'flex' }}>
<NavLink exact to={`/@${accountUsername}`}>
<FormattedMessage id='account.posts' defaultMessage='Posts' />
</NavLink>
@ -213,7 +212,7 @@ class AccountGallery extends ImmutablePureComponent {
{
attachments.size == 0 &&
<div className='empty-column-indicator'>
<FormattedMessage id='account_gallery.none' defaultMessage='No media to show.'/>
<FormattedMessage id='account_gallery.none' defaultMessage='No media to show.' />
</div>
}

View file

@ -25,8 +25,7 @@ const mapStateToProps = (state, { params: { username }, withReplies = false }) =
let accountUsername = username;
if (accountFetchError) {
accountId = null;
}
else {
} else {
let account = accounts.find(acct => username.toLowerCase() == acct.getIn(['acct'], '').toLowerCase());
accountId = account ? account.getIn(['id'], null) : -1;
accountUsername = account ? account.getIn(['acct'], '') : '';
@ -79,8 +78,7 @@ class AccountTimeline extends ImmutablePureComponent {
}
this.props.dispatch(expandAccountTimeline(accountId, { withReplies }));
}
else {
} else {
this.props.dispatch(fetchAccountByUsername(username));
}
}
@ -137,7 +135,7 @@ class AccountTimeline extends ImmutablePureComponent {
return (
<Column>
<div className='account__section-headline'>
<div style={{width: '100%', display: 'flex'}}>
<div style={{ width: '100%', display: 'flex' }}>
<NavLink exact to={`/@${accountUsername}`}>
<FormattedMessage id='account.posts' defaultMessage='Posts' />
</NavLink>

View file

@ -1,5 +1,5 @@
import React from 'react';
import { connect } from 'react-redux'
import { connect } from 'react-redux';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { createAuthApp, logIn } from 'gabsocial/actions/auth';
import { fetchMe } from 'gabsocial/actions/me';
@ -7,9 +7,10 @@ import { Link } from 'react-router-dom';
export default @connect()
class LoginForm extends ImmutablePureComponent {
constructor(props) {
super(props);
this.state = {isLoading: false};
this.state = { isLoading: false };
}
componentWillMount() {
@ -28,9 +29,9 @@ class LoginForm extends ImmutablePureComponent {
dispatch(logIn(username, password)).then(() => {
return dispatch(fetchMe());
}).catch((error) => {
this.setState({isLoading: false});
this.setState({ isLoading: false });
});
this.setState({isLoading: true});
this.setState({ isLoading: true });
event.preventDefault();
}
@ -52,6 +53,7 @@ class LoginForm extends ImmutablePureComponent {
<button name='button' type='submit' className='btn button button-primary'>Log in</button>
</div>
</form>
)
);
}
}

View file

@ -1,5 +1,5 @@
import React from 'react';
import { connect } from 'react-redux'
import { connect } from 'react-redux';
import { Redirect } from 'react-router-dom';
import ImmutablePureComponent from 'react-immutable-pure-component';
import LoginForm from './login_form';
@ -10,10 +10,12 @@ const mapStateToProps = state => ({
export default @connect(mapStateToProps)
class LoginPage extends ImmutablePureComponent {
render() {
const { me } = this.props;
if (me) return <Redirect to='/' />;
return <LoginForm />
return <LoginForm />;
}
}

View file

@ -49,7 +49,7 @@ class ActionBar extends React.PureComponent {
let menu = [];
menu.push({ text: intl.formatMessage(messages.profile), to: `/@${meUsername}` });
menu.push({ text: intl.formatMessage(messages.messages), to: `/messages` });
menu.push({ text: intl.formatMessage(messages.messages), to: '/messages' });
menu.push(null);
menu.push({ text: intl.formatMessage(messages.follow_requests), to: '/follow_requests' });
menu.push({ text: intl.formatMessage(messages.mutes), to: '/mutes' });
@ -62,13 +62,14 @@ class ActionBar extends React.PureComponent {
menu.push({ text: intl.formatMessage(messages.logout), to: '/auth/sign_out', action: onClickLogOut });
return (
<div className='compose__action-bar' style={{'marginTop':'-6px'}}>
<div className='compose__action-bar' style={{ 'marginTop':'-6px' }}>
<div className='compose__action-bar-dropdown'>
<DropdownMenuContainer items={menu} icon='chevron-down' size={size} direction='right' />
</div>
</div>
);
}
}
export default injectIntl(connect(null, mapDispatchToProps)(ActionBar));

View file

@ -26,7 +26,7 @@ import Icon from 'gabsocial/components/icon';
const allowedAroundShortCode = '><\u0085\u0020\u00a0\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029\u0009\u000a\u000b\u000c\u000d';
const messages = defineMessages({
placeholder: { id: 'compose_form.placeholder', defaultMessage: "What's on your mind?" },
placeholder: { id: 'compose_form.placeholder', defaultMessage: 'What\'s on your mind?' },
spoiler_placeholder: { id: 'compose_form.spoiler_placeholder', defaultMessage: 'Write your warning here' },
publish: { id: 'compose_form.publish', defaultMessage: 'Publish' },
publishLoud: { id: 'compose_form.publish_loud', defaultMessage: '{publish}!' },
@ -151,11 +151,11 @@ class ComposeForm extends ImmutablePureComponent {
}
componentDidMount() {
document.addEventListener("click", this.handleClick, false);
document.addEventListener('click', this.handleClick, false);
}
componentWillUnmount() {
document.removeEventListener("click", this.handleClick, false);
document.removeEventListener('click', this.handleClick, false);
}
componentDidUpdate (prevProps) {
@ -211,7 +211,7 @@ class ComposeForm extends ImmutablePureComponent {
const disabled = this.props.isSubmitting;
const text = [this.props.spoilerText, countableText(this.props.text)].join('');
const disabledButton = disabled || this.props.isUploading || this.props.isChangingUpload || length(text) > maxTootChars || (text.length !== 0 && text.trim().length === 0 && !anyMedia);
const shouldAutoFocus = autoFocus && !showSearch && !isMobile(window.innerWidth)
const shouldAutoFocus = autoFocus && !showSearch && !isMobile(window.innerWidth);
let publishText = '';
@ -224,7 +224,7 @@ class ComposeForm extends ImmutablePureComponent {
const composeClassNames = classNames({
'compose-form': true,
'condensed': condensed,
})
});
return (
<div className={composeClassNames} ref={this.setForm} onClick={this.handleClick}>

View file

@ -67,8 +67,8 @@ const mapDispatchToProps = (dispatch) => ({
function mergeProps(stateProps, dispatchProps, ownProps) {
return Object.assign({}, ownProps, {
...stateProps,
...dispatchProps
})
...dispatchProps,
});
}
export default connect(mapStateToProps, mapDispatchToProps, mergeProps)(ComposeForm);

View file

@ -12,7 +12,7 @@ const mapStateToProps = state => {
needsLockWarning: state.getIn(['compose', 'privacy']) === 'private' && !state.getIn(['accounts', me, 'locked']),
hashtagWarning: state.getIn(['compose', 'privacy']) !== 'public' && APPROX_HASHTAG_RE.test(state.getIn(['compose', 'text'])),
directMessageWarning: state.getIn(['compose', 'privacy']) === 'direct',
}
};
};
const WarningWrapper = ({ needsLockWarning, hashtagWarning, directMessageWarning }) => {

View file

@ -26,8 +26,7 @@ const mapStateToProps = (state, { params: { username }, withReplies = false }) =
let accountUsername = username;
if (accountFetchError) {
accountId = null;
}
else {
} else {
let account = accounts.find(acct => username.toLowerCase() == acct.getIn(['acct'], '').toLowerCase());
accountId = account ? account.getIn(['id'], null) : -1;
}
@ -64,8 +63,7 @@ class Followers extends ImmutablePureComponent {
if (accountId && accountId !== -1) {
this.props.dispatch(fetchAccount(accountId));
this.props.dispatch(fetchFollowers(accountId));
}
else {
} else {
this.props.dispatch(fetchAccountByUsername(username));
}
}

View file

@ -26,8 +26,7 @@ const mapStateToProps = (state, { params: { username }, withReplies = false }) =
let accountId = -1;
if (accountFetchError) {
accountId = null;
}
else {
} else {
let account = accounts.find(acct => username.toLowerCase() == acct.getIn(['acct'], '').toLowerCase());
accountId = account ? account.getIn(['id'], null) : -1;
}
@ -64,8 +63,7 @@ class Following extends ImmutablePureComponent {
if (accountId && accountId !== -1) {
this.props.dispatch(fetchAccount(accountId));
this.props.dispatch(fetchFollowing(accountId));
}
else {
} else {
this.props.dispatch(fetchAccountByUsername(username));
}
}

View file

@ -39,7 +39,7 @@ const mapStateToProps = state => {
return {
myAccount: state.getIn(['accounts', me]),
unreadFollowRequests: state.getIn(['user_lists', 'follow_requests', 'items'], ImmutableList()).size,
}
};
};
const mapDispatchToProps = dispatch => ({

View file

@ -7,26 +7,26 @@ import { defineMessages, injectIntl } from 'react-intl';
import classNames from 'classnames';
const messages = defineMessages({
title: { id: 'groups.form.title', defaultMessage: 'Enter a new group title' },
description: { id: 'groups.form.description', defaultMessage: 'Enter the group description' },
coverImage: { id: 'groups.form.coverImage', defaultMessage: 'Upload a banner image' },
coverImageChange: { id: 'groups.form.coverImageChange', defaultMessage: 'Banner image selected' },
create: { id: 'groups.form.create', defaultMessage: 'Create group' },
title: { id: 'groups.form.title', defaultMessage: 'Enter a new group title' },
description: { id: 'groups.form.description', defaultMessage: 'Enter the group description' },
coverImage: { id: 'groups.form.coverImage', defaultMessage: 'Upload a banner image' },
coverImageChange: { id: 'groups.form.coverImageChange', defaultMessage: 'Banner image selected' },
create: { id: 'groups.form.create', defaultMessage: 'Create group' },
});
const mapStateToProps = state => ({
title: state.getIn(['group_editor', 'title']),
description: state.getIn(['group_editor', 'description']),
coverImage: state.getIn(['group_editor', 'coverImage']),
disabled: state.getIn(['group_editor', 'isSubmitting']),
title: state.getIn(['group_editor', 'title']),
description: state.getIn(['group_editor', 'description']),
coverImage: state.getIn(['group_editor', 'coverImage']),
disabled: state.getIn(['group_editor', 'isSubmitting']),
});
const mapDispatchToProps = dispatch => ({
onTitleChange: value => dispatch(changeValue('title', value)),
onDescriptionChange: value => dispatch(changeValue('description', value)),
onCoverImageChange: value => dispatch(changeValue('coverImage', value)),
onSubmit: routerHistory => dispatch(submit(routerHistory)),
reset: () => dispatch(reset()),
onTitleChange: value => dispatch(changeValue('title', value)),
onDescriptionChange: value => dispatch(changeValue('description', value)),
onCoverImageChange: value => dispatch(changeValue('coverImage', value)),
onSubmit: routerHistory => dispatch(submit(routerHistory)),
reset: () => dispatch(reset()),
});
export default @connect(mapStateToProps, mapDispatchToProps)
@ -34,80 +34,80 @@ export default @connect(mapStateToProps, mapDispatchToProps)
class Create extends React.PureComponent {
static contextTypes = {
router: PropTypes.object
router: PropTypes.object,
}
static propTypes = {
title: PropTypes.string.isRequired,
description: PropTypes.string.isRequired,
coverImage: PropTypes.object,
disabled: PropTypes.bool,
intl: PropTypes.object.isRequired,
onTitleChange: PropTypes.func.isRequired,
onSubmit: PropTypes.func.isRequired,
title: PropTypes.string.isRequired,
description: PropTypes.string.isRequired,
coverImage: PropTypes.object,
disabled: PropTypes.bool,
intl: PropTypes.object.isRequired,
onTitleChange: PropTypes.func.isRequired,
onSubmit: PropTypes.func.isRequired,
};
componentWillMount() {
this.props.reset();
this.props.reset();
}
handleTitleChange = e => {
this.props.onTitleChange(e.target.value);
this.props.onTitleChange(e.target.value);
}
handleDescriptionChange = e => {
this.props.onDescriptionChange(e.target.value);
this.props.onDescriptionChange(e.target.value);
}
handleCoverImageChange = e => {
this.props.onCoverImageChange(e.target.files[0]);
this.props.onCoverImageChange(e.target.files[0]);
}
handleSubmit = e => {
e.preventDefault();
this.props.onSubmit(this.context.router.history);
e.preventDefault();
this.props.onSubmit(this.context.router.history);
}
render () {
const { title, description, coverImage, disabled, intl } = this.props;
const { title, description, coverImage, disabled, intl } = this.props;
return (
<form className='group-form' onSubmit={this.handleSubmit}>
<div>
<input
className='standard'
type='text'
value={title}
disabled={disabled}
onChange={this.handleTitleChange}
placeholder={intl.formatMessage(messages.title)}
/>
</div>
<div>
<textarea
className='standard'
type='text'
value={description}
disabled={disabled}
onChange={this.handleDescriptionChange}
placeholder={intl.formatMessage(messages.description)}
/>
</div>
<div>
<label htmlFor='group_cover_image' className={classNames('group-form__file-label', { 'group-form__file-label--selected': coverImage !== null })}>
{intl.formatMessage(coverImage === null ? messages.coverImage : messages.coverImageChange)}
</label>
<input
type='file'
className='group-form__file'
id='group_cover_image'
disabled={disabled}
onChange={this.handleCoverImageChange}
/>
<button className='standard-small'>{intl.formatMessage(messages.create)}</button>
</div>
</form>
);
return (
<form className='group-form' onSubmit={this.handleSubmit}>
<div>
<input
className='standard'
type='text'
value={title}
disabled={disabled}
onChange={this.handleTitleChange}
placeholder={intl.formatMessage(messages.title)}
/>
</div>
<div>
<textarea
className='standard'
type='text'
value={description}
disabled={disabled}
onChange={this.handleDescriptionChange}
placeholder={intl.formatMessage(messages.description)}
/>
</div>
<div>
<label htmlFor='group_cover_image' className={classNames('group-form__file-label', { 'group-form__file-label--selected': coverImage !== null })}>
{intl.formatMessage(coverImage === null ? messages.coverImage : messages.coverImageChange)}
</label>
<input
type='file'
className='group-form__file'
id='group_cover_image'
disabled={disabled}
onChange={this.handleCoverImageChange}
/>
<button className='standard-small'>{intl.formatMessage(messages.create)}</button>
</div>
</form>
);
}
}

View file

@ -10,27 +10,27 @@ import Column from '../../../components/column';
import classNames from 'classnames';
const messages = defineMessages({
title: { id: 'groups.form.title', defaultMessage: 'Title' },
description: { id: 'groups.form.description', defaultMessage: 'Description' },
coverImage: { id: 'groups.form.coverImage', defaultMessage: 'Upload new banner image (optional)' },
coverImageChange: { id: 'groups.form.coverImageChange', defaultMessage: 'Banner image selected' },
update: { id: 'groups.form.update', defaultMessage: 'Update group' },
title: { id: 'groups.form.title', defaultMessage: 'Title' },
description: { id: 'groups.form.description', defaultMessage: 'Description' },
coverImage: { id: 'groups.form.coverImage', defaultMessage: 'Upload new banner image (optional)' },
coverImageChange: { id: 'groups.form.coverImageChange', defaultMessage: 'Banner image selected' },
update: { id: 'groups.form.update', defaultMessage: 'Update group' },
});
const mapStateToProps = (state, props) => ({
group: state.getIn(['groups', props.params.id]),
title: state.getIn(['group_editor', 'title']),
description: state.getIn(['group_editor', 'description']),
coverImage: state.getIn(['group_editor', 'coverImage']),
disabled: state.getIn(['group_editor', 'isSubmitting']),
group: state.getIn(['groups', props.params.id]),
title: state.getIn(['group_editor', 'title']),
description: state.getIn(['group_editor', 'description']),
coverImage: state.getIn(['group_editor', 'coverImage']),
disabled: state.getIn(['group_editor', 'isSubmitting']),
});
const mapDispatchToProps = dispatch => ({
onTitleChange: value => dispatch(changeValue('title', value)),
onDescriptionChange: value => dispatch(changeValue('description', value)),
onCoverImageChange: value => dispatch(changeValue('coverImage', value)),
onSubmit: routerHistory => dispatch(submit(routerHistory)),
setUp: group => dispatch(setUp(group)),
onTitleChange: value => dispatch(changeValue('title', value)),
onDescriptionChange: value => dispatch(changeValue('description', value)),
onCoverImageChange: value => dispatch(changeValue('coverImage', value)),
onSubmit: routerHistory => dispatch(submit(routerHistory)),
setUp: group => dispatch(setUp(group)),
});
export default @connect(mapStateToProps, mapDispatchToProps)
@ -38,111 +38,111 @@ export default @connect(mapStateToProps, mapDispatchToProps)
class Edit extends React.PureComponent {
static contextTypes = {
router: PropTypes.object
router: PropTypes.object,
}
static propTypes = {
group: ImmutablePropTypes.map,
title: PropTypes.string.isRequired,
description: PropTypes.string.isRequired,
coverImage: PropTypes.object,
disabled: PropTypes.bool,
intl: PropTypes.object.isRequired,
onTitleChange: PropTypes.func.isRequired,
onSubmit: PropTypes.func.isRequired,
group: ImmutablePropTypes.map,
title: PropTypes.string.isRequired,
description: PropTypes.string.isRequired,
coverImage: PropTypes.object,
disabled: PropTypes.bool,
intl: PropTypes.object.isRequired,
onTitleChange: PropTypes.func.isRequired,
onSubmit: PropTypes.func.isRequired,
};
componentWillMount(nextProps) {
if (this.props.group) {
this.props.setUp(this.props.group);
}
componentWillMount(nextProps) {
if (this.props.group) {
this.props.setUp(this.props.group);
}
}
componentWillReceiveProps(nextProps) {
if (!this.props.group && nextProps.group) {
this.props.setUp(nextProps.group);
}
if (!this.props.group && nextProps.group) {
this.props.setUp(nextProps.group);
}
}
handleTitleChange = e => {
this.props.onTitleChange(e.target.value);
this.props.onTitleChange(e.target.value);
}
handleDescriptionChange = e => {
this.props.onDescriptionChange(e.target.value);
this.props.onDescriptionChange(e.target.value);
}
handleCoverImageChange = e => {
this.props.onCoverImageChange(e.target.files[0]);
this.props.onCoverImageChange(e.target.files[0]);
}
handleSubmit = e => {
e.preventDefault();
this.props.onSubmit(this.context.router.history);
e.preventDefault();
this.props.onSubmit(this.context.router.history);
}
handleClick = () => {
this.props.onSubmit(this.context.router.history);
this.props.onSubmit(this.context.router.history);
}
render () {
const { group, title, description, coverImage, disabled, intl } = this.props;
if (typeof group === 'undefined') {
return (
<Column>
<LoadingIndicator />
</Column>
);
} else if (group === false) {
return (
<Column>
<MissingIndicator />
</Column>
);
}
const { group, title, description, coverImage, disabled, intl } = this.props;
return (
<form className='group-form' onSubmit={this.handleSubmit}>
<div>
<input
className='standard'
type='text'
value={title}
disabled={disabled}
onChange={this.handleTitleChange}
placeholder={intl.formatMessage(messages.title)}
/>
</div>
<div>
<textarea
className='standard'
type='text'
value={description}
disabled={disabled}
onChange={this.handleDescriptionChange}
placeholder={intl.formatMessage(messages.description)}
/>
</div>
if (typeof group === 'undefined') {
return (
<Column>
<LoadingIndicator />
</Column>
);
} else if (group === false) {
return (
<Column>
<MissingIndicator />
</Column>
);
}
<div>
<label htmlFor='group_cover_image' className={classNames('group-form__file-label', { 'group-form__file-label--selected': coverImage !== null })}>
{intl.formatMessage(coverImage === null ? messages.coverImage : messages.coverImageChange)}
</label>
<input
type='file'
className='group-form__file'
id='group_cover_image'
disabled={disabled}
onChange={this.handleCoverImageChange}
/>
return (
<form className='group-form' onSubmit={this.handleSubmit}>
<div>
<input
className='standard'
type='text'
value={title}
disabled={disabled}
onChange={this.handleTitleChange}
placeholder={intl.formatMessage(messages.title)}
/>
</div>
<button>{intl.formatMessage(messages.update)}</button>
</div>
</form>
);
<div>
<textarea
className='standard'
type='text'
value={description}
disabled={disabled}
onChange={this.handleDescriptionChange}
placeholder={intl.formatMessage(messages.description)}
/>
</div>
<div>
<label htmlFor='group_cover_image' className={classNames('group-form__file-label', { 'group-form__file-label--selected': coverImage !== null })}>
{intl.formatMessage(coverImage === null ? messages.coverImage : messages.coverImageChange)}
</label>
<input
type='file'
className='group-form__file'
id='group_cover_image'
disabled={disabled}
onChange={this.handleCoverImageChange}
/>
<button>{intl.formatMessage(messages.update)}</button>
</div>
</form>
);
}
}

View file

@ -7,48 +7,50 @@ import { shortNumberFormat } from '../../../utils/numbers';
import { connect } from 'react-redux';
const messages = defineMessages({
members: { id: 'groups.card.members', defaultMessage: 'Members' },
view: { id: 'groups.card.view', defaultMessage: 'View' },
join: { id: 'groups.card.join', defaultMessage: 'Join' },
role_member: { id: 'groups.card.roles.member', defaultMessage: 'You\'re a member' },
role_admin: { id: 'groups.card.roles.admin', defaultMessage: 'You\'re an admin' },
members: { id: 'groups.card.members', defaultMessage: 'Members' },
view: { id: 'groups.card.view', defaultMessage: 'View' },
join: { id: 'groups.card.join', defaultMessage: 'Join' },
role_member: { id: 'groups.card.roles.member', defaultMessage: 'You\'re a member' },
role_admin: { id: 'groups.card.roles.admin', defaultMessage: 'You\'re an admin' },
});
const mapStateToProps = (state, { id }) => ({
group: state.getIn(['groups', id]),
relationships: state.getIn(['group_relationships', id]),
group: state.getIn(['groups', id]),
relationships: state.getIn(['group_relationships', id]),
});
export default @connect(mapStateToProps)
@injectIntl
class GroupCard extends ImmutablePureComponent {
static propTypes = {
group: ImmutablePropTypes.map,
relationships: ImmutablePropTypes.map,
group: ImmutablePropTypes.map,
relationships: ImmutablePropTypes.map,
}
getRole() {
const { intl, relationships } = this.props;
const { intl, relationships } = this.props;
if (!relationships) return null;
if (relationships.get('admin')) return intl.formatMessage(messages.role_admin);
if (relationships.get('member')) return intl.formatMessage(messages.role_member);
if (!relationships) return null;
if (relationships.get('admin')) return intl.formatMessage(messages.role_admin);
if (relationships.get('member')) return intl.formatMessage(messages.role_member);
}
render() {
const { intl, group } = this.props;
const coverImageUrl = group.get('cover_image_url');
const role = this.getRole();
const { intl, group } = this.props;
const coverImageUrl = group.get('cover_image_url');
const role = this.getRole();
return (
<Link to={`/groups/${group.get('id')}`} className="group-card">
<div className="group-card__header">{coverImageUrl && <img alt="" src={coverImageUrl} />}</div>
<div className="group-card__content">
<div className="group-card__title">{group.get('title')}</div>
<div className="group-card__meta"><strong>{shortNumberFormat(group.get('member_count'))}</strong> {intl.formatMessage(messages.members)}{role && <span> · {role}</span>}</div>
<div className="group-card__description">{group.get('description')}</div>
</div>
</Link>
);
return (
<Link to={`/groups/${group.get('id')}`} className='group-card'>
<div className='group-card__header'>{coverImageUrl && <img alt='' src={coverImageUrl} />}</div>
<div className='group-card__content'>
<div className='group-card__title'>{group.get('title')}</div>
<div className='group-card__meta'><strong>{shortNumberFormat(group.get('member_count'))}</strong> {intl.formatMessage(messages.members)}{role && <span> · {role}</span>}</div>
<div className='group-card__description'>{group.get('description')}</div>
</div>
</Link>
);
}
}

View file

@ -11,79 +11,81 @@ 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' },
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]),
groupIds: state.getIn(['group_lists', activeTab]),
});
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,
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));
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));
}
if (this.props.activeTab && this.props.activeTab !== oldProps.activeTab) {
this.props.dispatch(fetchGroups(this.props.activeTab));
}
}
renderHeader() {
const { intl, activeTab } = this.props;
const { intl, activeTab } = this.props;
return (
<div className="group-column-header">
<div className="group-column-header__cta"><Link to="/groups/create" className="button standard-small">{intl.formatMessage(messages.create)}</Link></div>
<div className="group-column-header__title">{intl.formatMessage(messages.heading)}</div>
return (
<div className='group-column-header'>
<div className='group-column-header__cta'><Link to='/groups/create' className='button standard-small'>{intl.formatMessage(messages.create)}</Link></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>
<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/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>
);
<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;
const { groupIds, showCreateForm } = this.props;
return (
<div>
{!showCreateForm && this.renderHeader()}
{showCreateForm && <GroupCreate /> }
return (
<div>
{!showCreateForm && this.renderHeader()}
{showCreateForm && <GroupCreate /> }
<div className="group-card-list">
{groupIds.map(id => <GroupCard key={id} id={id} />)}
</div>
</div>
);
<div className='group-card-list'>
{groupIds.map(id => <GroupCard key={id} id={id} />)}
</div>
</div>
);
}
}

View file

@ -6,8 +6,8 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
import { debounce } from 'lodash';
import LoadingIndicator from '../../../components/loading_indicator';
import {
fetchMembers,
expandMembers,
fetchMembers,
expandMembers,
} from '../../../actions/groups';
import { FormattedMessage } from 'react-intl';
import AccountContainer from '../../../containers/account_container';
@ -15,59 +15,60 @@ import Column from '../../ui/components/column';
import ScrollableList from '../../../components/scrollable_list';
const mapStateToProps = (state, { params: { id } }) => ({
group: state.getIn(['groups', id]),
accountIds: state.getIn(['user_lists', 'groups', id, 'items']),
hasMore: !!state.getIn(['user_lists', 'groups', id, 'next']),
group: state.getIn(['groups', id]),
accountIds: state.getIn(['user_lists', 'groups', id, 'items']),
hasMore: !!state.getIn(['user_lists', 'groups', id, 'next']),
});
export default @connect(mapStateToProps)
class GroupMembers extends ImmutablePureComponent {
static propTypes = {
params: PropTypes.object.isRequired,
dispatch: PropTypes.func.isRequired,
accountIds: ImmutablePropTypes.list,
hasMore: PropTypes.bool,
params: PropTypes.object.isRequired,
dispatch: PropTypes.func.isRequired,
accountIds: ImmutablePropTypes.list,
hasMore: PropTypes.bool,
};
componentWillMount () {
const { params: { id } } = this.props;
const { params: { id } } = this.props;
this.props.dispatch(fetchMembers(id));
this.props.dispatch(fetchMembers(id));
}
componentWillReceiveProps (nextProps) {
if (nextProps.params.id !== this.props.params.id) {
this.props.dispatch(fetchMembers(nextProps.params.id));
}
if (nextProps.params.id !== this.props.params.id) {
this.props.dispatch(fetchMembers(nextProps.params.id));
}
}
handleLoadMore = debounce(() => {
this.props.dispatch(expandMembers(this.props.params.id));
this.props.dispatch(expandMembers(this.props.params.id));
}, 300, { leading: true });
render () {
const { accountIds, hasMore, group } = this.props;
const { accountIds, hasMore, group } = this.props;
if (!group || !accountIds) {
return (
<Column>
<LoadingIndicator />
</Column>
);
}
if (!group || !accountIds) {
return (
<Column>
<LoadingIndicator />
</Column>
);
}
return (
<Column>
<ScrollableList
scrollKey='members'
hasMore={hasMore}
onLoadMore={this.handleLoadMore}
emptyMessage={<FormattedMessage id='group.members.empty' defaultMessage='This group does not has any members.' />}
>
{accountIds.map(id => <AccountContainer key={id} id={id} withNote={false} />)}
</ScrollableList>
</Column>
);
return (
<Column>
<ScrollableList
scrollKey='members'
hasMore={hasMore}
onLoadMore={this.handleLoadMore}
emptyMessage={<FormattedMessage id='group.members.empty' defaultMessage='This group does not has any members.' />}
>
{accountIds.map(id => <AccountContainer key={id} id={id} withNote={false} />)}
</ScrollableList>
</Column>
);
}
}

View file

@ -6,9 +6,9 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
import { debounce } from 'lodash';
import LoadingIndicator from '../../../components/loading_indicator';
import {
fetchRemovedAccounts,
expandRemovedAccounts,
removeRemovedAccount,
fetchRemovedAccounts,
expandRemovedAccounts,
removeRemovedAccount,
} from '../../../actions/groups';
import { FormattedMessage } from 'react-intl';
import AccountContainer from '../../../containers/account_container';
@ -17,13 +17,13 @@ import ScrollableList from '../../../components/scrollable_list';
import { defineMessages, injectIntl } from 'react-intl';
const messages = defineMessages({
remove: { id: 'groups.removed_accounts', defaultMessage: 'Allow joining' },
remove: { id: 'groups.removed_accounts', defaultMessage: 'Allow joining' },
});
const mapStateToProps = (state, { params: { id } }) => ({
group: state.getIn(['groups', id]),
accountIds: state.getIn(['user_lists', 'groups_removed_accounts', id, 'items']),
hasMore: !!state.getIn(['user_lists', 'groups_removed_accounts', id, 'next']),
group: state.getIn(['groups', id]),
accountIds: state.getIn(['user_lists', 'groups_removed_accounts', id, 'items']),
hasMore: !!state.getIn(['user_lists', 'groups_removed_accounts', id, 'next']),
});
export default @connect(mapStateToProps)
@ -31,56 +31,57 @@ export default @connect(mapStateToProps)
class GroupRemovedAccounts extends ImmutablePureComponent {
static propTypes = {
params: PropTypes.object.isRequired,
dispatch: PropTypes.func.isRequired,
accountIds: ImmutablePropTypes.list,
hasMore: PropTypes.bool,
params: PropTypes.object.isRequired,
dispatch: PropTypes.func.isRequired,
accountIds: ImmutablePropTypes.list,
hasMore: PropTypes.bool,
};
componentWillMount () {
const { params: { id } } = this.props;
const { params: { id } } = this.props;
this.props.dispatch(fetchRemovedAccounts(id));
this.props.dispatch(fetchRemovedAccounts(id));
}
componentWillReceiveProps (nextProps) {
if (nextProps.params.id !== this.props.params.id) {
this.props.dispatch(fetchRemovedAccounts(nextProps.params.id));
}
if (nextProps.params.id !== this.props.params.id) {
this.props.dispatch(fetchRemovedAccounts(nextProps.params.id));
}
}
handleLoadMore = debounce(() => {
this.props.dispatch(expandRemovedAccounts(this.props.params.id));
this.props.dispatch(expandRemovedAccounts(this.props.params.id));
}, 300, { leading: true });
render () {
const { accountIds, hasMore, group, intl } = this.props;
const { accountIds, hasMore, group, intl } = this.props;
if (!group || !accountIds) {
return (
<Column>
<LoadingIndicator />
</Column>
);
}
if (!group || !accountIds) {
return (
<Column>
<LoadingIndicator />
</Column>
);
}
return (
<Column>
<ScrollableList
scrollKey='removed_accounts'
hasMore={hasMore}
onLoadMore={this.handleLoadMore}
emptyMessage={<FormattedMessage id='group.removed_accounts.empty' defaultMessage='This group does not has any removed accounts.' />}
>
{accountIds.map(id => <AccountContainer
key={id}
id={id}
actionIcon="remove"
onActionClick={() => this.props.dispatch(removeRemovedAccount(group.get('id'), id))}
actionTitle={intl.formatMessage(messages.remove)}
/>)}
</ScrollableList>
</Column>
);
return (
<Column>
<ScrollableList
scrollKey='removed_accounts'
hasMore={hasMore}
onLoadMore={this.handleLoadMore}
emptyMessage={<FormattedMessage id='group.removed_accounts.empty' defaultMessage='This group does not has any removed accounts.' />}
>
{accountIds.map(id => (<AccountContainer
key={id}
id={id}
actionIcon='remove'
onActionClick={() => this.props.dispatch(removeRemovedAccount(group.get('id'), id))}
actionTitle={intl.formatMessage(messages.remove)}
/>))}
</ScrollableList>
</Column>
);
}
}

View file

@ -8,42 +8,44 @@ import Icon from 'gabsocial/components/icon';
import { Link } from 'react-router-dom';
const messages = defineMessages({
title: { id: 'groups.sidebar-panel.title', defaultMessage: 'Groups You\'re In' },
show_all: { id: 'groups.sidebar-panel.show_all', defaultMessage: 'Show all' },
title: { id: 'groups.sidebar-panel.title', defaultMessage: 'Groups You\'re In' },
show_all: { id: 'groups.sidebar-panel.show_all', defaultMessage: 'Show all' },
});
const mapStateToProps = (state, { id }) => ({
groupIds: state.getIn(['group_lists', 'member']),
groupIds: state.getIn(['group_lists', 'member']),
});
export default @connect(mapStateToProps)
@injectIntl
class GroupSidebarPanel extends ImmutablePureComponent {
static propTypes = {
groupIds: ImmutablePropTypes.list,
groupIds: ImmutablePropTypes.list,
}
render() {
const { intl, groupIds } = this.props;
const count = groupIds.count();
const { intl, groupIds } = this.props;
const count = groupIds.count();
// Only when there are groups to show
if (count === 0) return null;
// Only when there are groups to show
if (count === 0) return null;
return (
<div className='wtf-panel group-sidebar-panel'>
<div className='wtf-panel-header'>
<Icon id='users' className='wtf-panel-header__icon' />
<span className='wtf-panel-header__label'>{intl.formatMessage(messages.title)}</span>
</div>
return (
<div className='wtf-panel group-sidebar-panel'>
<div className='wtf-panel-header'>
<Icon id='users' className='wtf-panel-header__icon' />
<span className='wtf-panel-header__label'>{intl.formatMessage(messages.title)}</span>
</div>
<div className='wtf-panel__content'>
<div className="group-sidebar-panel__items">
{groupIds.slice(0, 10).map(groupId => <Item key={groupId} id={groupId} />)}
{count > 10 && <Link className="group-sidebar-panel__items__show-all" to='/groups/browse/member'>{intl.formatMessage(messages.show_all)}</Link>}
</div>
</div>
<div className='wtf-panel__content'>
<div className='group-sidebar-panel__items'>
{groupIds.slice(0, 10).map(groupId => <Item key={groupId} id={groupId} />)}
{count > 10 && <Link className='group-sidebar-panel__items__show-all' to='/groups/browse/member'>{intl.formatMessage(messages.show_all)}</Link>}
</div>
);
</div>
</div>
);
}
}

View file

@ -7,39 +7,41 @@ import { shortNumberFormat } from '../../../utils/numbers';
import { connect } from 'react-redux';
const messages = defineMessages({
new_statuses: { id: 'groups.sidebar-panel.item.view', defaultMessage: 'new posts' },
no_recent_activity: { id: 'groups.sidebar-panel.item.no_recent_activity', defaultMessage: 'No recent activity' },
new_statuses: { id: 'groups.sidebar-panel.item.view', defaultMessage: 'new posts' },
no_recent_activity: { id: 'groups.sidebar-panel.item.no_recent_activity', defaultMessage: 'No recent activity' },
});
const mapStateToProps = (state, { id }) => ({
group: state.getIn(['groups', id]),
relationships: state.getIn(['group_relationships', id]),
group: state.getIn(['groups', id]),
relationships: state.getIn(['group_relationships', id]),
});
export default @connect(mapStateToProps)
@injectIntl
class Item extends ImmutablePureComponent {
static propTypes = {
group: ImmutablePropTypes.map,
relationships: ImmutablePropTypes.map,
group: ImmutablePropTypes.map,
relationships: ImmutablePropTypes.map,
}
render() {
const { intl, group, relationships } = this.props;
const { intl, group, relationships } = this.props;
// Wait for relationships
if (!relationships) return null;
// Wait for relationships
if (!relationships) return null;
const unreadCount = relationships.get('unread_count');
const unreadCount = relationships.get('unread_count');
return (
<Link to={`/groups/${group.get('id')}`} className="group-sidebar-panel__item">
<div className="group-sidebar-panel__item__title">{group.get('title')}</div>
<div className="group-sidebar-panel__item__meta">
{unreadCount > 0 && <span className="group-sidebar-panel__item__meta__unread">{shortNumberFormat(unreadCount)} {intl.formatMessage(messages.new_statuses)}</span>}
{unreadCount === 0 && <span>{intl.formatMessage(messages.no_recent_activity)}</span>}
</div>
</Link>
);
return (
<Link to={`/groups/${group.get('id')}`} className='group-sidebar-panel__item'>
<div className='group-sidebar-panel__item__title'>{group.get('title')}</div>
<div className='group-sidebar-panel__item__meta'>
{unreadCount > 0 && <span className='group-sidebar-panel__item__meta__unread'>{shortNumberFormat(unreadCount)} {intl.formatMessage(messages.new_statuses)}</span>}
{unreadCount === 0 && <span>{intl.formatMessage(messages.no_recent_activity)}</span>}
</div>
</Link>
);
}
}

View file

@ -8,70 +8,72 @@ import { NavLink } from 'react-router-dom';
import DropdownMenuContainer from '../../../../containers/dropdown_menu_container';
const messages = defineMessages({
join: { id: 'groups.join', defaultMessage: 'Join group' },
leave: { id: 'groups.leave', defaultMessage: 'Leave group' },
removed_accounts: { id: 'groups.removed_accounts', defaultMessage: 'Removed Accounts' },
edit: { id: 'groups.edit', defaultMessage: 'Edit' }
join: { id: 'groups.join', defaultMessage: 'Join group' },
leave: { id: 'groups.leave', defaultMessage: 'Leave group' },
removed_accounts: { id: 'groups.removed_accounts', defaultMessage: 'Removed Accounts' },
edit: { id: 'groups.edit', defaultMessage: 'Edit' },
});
export default @injectIntl
class Header extends ImmutablePureComponent {
static propTypes = {
group: ImmutablePropTypes.map,
relationships: ImmutablePropTypes.map,
toggleMembership: PropTypes.func.isRequired,
group: ImmutablePropTypes.map,
relationships: ImmutablePropTypes.map,
toggleMembership: PropTypes.func.isRequired,
};
static contextTypes = {
router: PropTypes.object,
router: PropTypes.object,
};
getActionButton() {
const { group, relationships, toggleMembership, intl } = this.props;
const toggle = () => toggleMembership(group, relationships);
const { group, relationships, toggleMembership, intl } = this.props;
const toggle = () => toggleMembership(group, relationships);
if (!relationships) {
return '';
} else if (!relationships.get('member')) {
return <Button className='logo-button' text={intl.formatMessage(messages.join)} onClick={toggle} />;
} else if (relationships.get('member')) {
return <Button className='logo-button' text={intl.formatMessage(messages.leave, { name: group.get('title') })} onClick={toggle} />;
}
if (!relationships) {
return '';
} else if (!relationships.get('member')) {
return <Button className='logo-button' text={intl.formatMessage(messages.join)} onClick={toggle} />;
} else if (relationships.get('member')) {
return <Button className='logo-button' text={intl.formatMessage(messages.leave, { name: group.get('title') })} onClick={toggle} />;
}
}
getAdminMenu() {
const { group, intl } = this.props;
const { group, intl } = this.props;
const menu = [
{ text: intl.formatMessage(messages.edit), to: `/groups/${group.get('id')}/edit` },
{ text: intl.formatMessage(messages.removed_accounts), to: `/groups/${group.get('id')}/removed_accounts` },
];
const menu = [
{ text: intl.formatMessage(messages.edit), to: `/groups/${group.get('id')}/edit` },
{ text: intl.formatMessage(messages.removed_accounts), to: `/groups/${group.get('id')}/removed_accounts` },
];
return <DropdownMenuContainer items={menu} icon='ellipsis-v' size={24} direction='right' />;
return <DropdownMenuContainer items={menu} icon='ellipsis-v' size={24} direction='right' />;
}
render () {
const { group, relationships } = this.props;
const { group, relationships } = this.props;
if (!group || !relationships) {
return null;
}
if (!group || !relationships) {
return null;
}
return (
<div className='group__header-container'>
<div className="group__header">
<div className='group__cover'>
<img src={group.get('cover_image_url')} alt='' className='parallax' />
</div>
<div className='group__tabs'>
<NavLink exact className='group__tabs__tab' activeClassName='group__tabs__tab--active' to={`/groups/${group.get('id')}`}>Posts</NavLink>
<NavLink exact className='group__tabs__tab' activeClassName='group__tabs__tab--active' to={`/groups/${group.get('id')}/members`}>Members</NavLink>
{this.getActionButton()}
{relationships.get('admin') && this.getAdminMenu()}
</div>
</div>
</div>
);
return (
<div className='group__header-container'>
<div className='group__header'>
<div className='group__cover'>
<img src={group.get('cover_image_url')} alt='' className='parallax' />
</div>
<div className='group__tabs'>
<NavLink exact className='group__tabs__tab' activeClassName='group__tabs__tab--active' to={`/groups/${group.get('id')}`}>Posts</NavLink>
<NavLink exact className='group__tabs__tab' activeClassName='group__tabs__tab--active' to={`/groups/${group.get('id')}/members`}>Members</NavLink>
{this.getActionButton()}
{relationships.get('admin') && this.getAdminMenu()}
</div>
</div>
</div>
);
}
}

View file

@ -4,31 +4,33 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
import { injectIntl, defineMessages } from 'react-intl';
const messages = defineMessages({
group_archived: { id: 'group.detail.archived_group', defaultMessage: 'Archived group' },
group_admin: { id: 'groups.detail.role_admin', defaultMessage: 'You\'re an admin' }
group_archived: { id: 'group.detail.archived_group', defaultMessage: 'Archived group' },
group_admin: { id: 'groups.detail.role_admin', defaultMessage: 'You\'re an admin' },
});
export default @injectIntl
class GroupPanel extends ImmutablePureComponent {
static propTypes = {
group: ImmutablePropTypes.map,
relationships: ImmutablePropTypes.map,
group: ImmutablePropTypes.map,
relationships: ImmutablePropTypes.map,
}
render() {
const { group, relationships, intl } = this.props;
const { group, relationships, intl } = this.props;
return (
<div className="group__panel">
<h1 className="group__panel__title">
{group.get('title')}
{group.get('archived') && <Icon id='lock' title={intl.formatMessage(messages.group_archived)} />}
</h1>
return (
<div className='group__panel'>
<h1 className='group__panel__title'>
{group.get('title')}
{group.get('archived') && <Icon id='lock' title={intl.formatMessage(messages.group_archived)} />}
</h1>
{relationships.get('admin') && <span className="group__panel__label">{intl.formatMessage(messages.group_admin)}</span>}
{relationships.get('admin') && <span className='group__panel__label'>{intl.formatMessage(messages.group_admin)}</span>}
<div className="group__panel__description">{group.get('description')}</div>
</div>
);
<div className='group__panel__description'>{group.get('description')}</div>
</div>
);
}
}

View file

@ -3,18 +3,18 @@ import Header from '../components/header';
import { joinGroup, leaveGroup } from '../../../../actions/groups';
const mapStateToProps = (state, { groupId }) => ({
group: state.getIn(['groups', groupId]),
relationships: state.getIn(['group_relationships', groupId]),
group: state.getIn(['groups', groupId]),
relationships: state.getIn(['group_relationships', groupId]),
});
const mapDispatchToProps = (dispatch, { intl }) => ({
toggleMembership (group, relationships) {
if (relationships.get('member')) {
dispatch(leaveGroup(group.get('id')));
} else {
dispatch(joinGroup(group.get('id')));
}
},
toggleMembership (group, relationships) {
if (relationships.get('member')) {
dispatch(leaveGroup(group.get('id')));
} else {
dispatch(joinGroup(group.get('id')));
}
},
});
export default connect(mapStateToProps, mapDispatchToProps)(Header);

View file

@ -13,95 +13,97 @@ import ComposeFormContainer from '../../../../gabsocial/features/compose/contain
import Avatar from '../../../components/avatar';
const mapStateToProps = (state, props) => {
const me = state.get('me');
return {
account: state.getIn(['accounts', me]),
group: state.getIn(['groups', props.params.id]),
relationships: state.getIn(['group_relationships', props.params.id]),
hasUnread: state.getIn(['timelines', `group:${props.params.id}`, 'unread']) > 0,
}
const me = state.get('me');
return {
account: state.getIn(['accounts', me]),
group: state.getIn(['groups', props.params.id]),
relationships: state.getIn(['group_relationships', props.params.id]),
hasUnread: state.getIn(['timelines', `group:${props.params.id}`, 'unread']) > 0,
};
};
export default @connect(mapStateToProps)
@injectIntl
class GroupTimeline extends React.PureComponent {
static contextTypes = {
router: PropTypes.object,
router: PropTypes.object,
};
static propTypes = {
params: PropTypes.object.isRequired,
dispatch: PropTypes.func.isRequired,
columnId: PropTypes.string,
hasUnread: PropTypes.bool,
group: PropTypes.oneOfType([ImmutablePropTypes.map, PropTypes.bool]),
relationships: ImmutablePropTypes.map,
account: ImmutablePropTypes.map,
intl: PropTypes.object.isRequired,
params: PropTypes.object.isRequired,
dispatch: PropTypes.func.isRequired,
columnId: PropTypes.string,
hasUnread: PropTypes.bool,
group: PropTypes.oneOfType([ImmutablePropTypes.map, PropTypes.bool]),
relationships: ImmutablePropTypes.map,
account: ImmutablePropTypes.map,
intl: PropTypes.object.isRequired,
};
componentDidMount () {
const { dispatch } = this.props;
const { id } = this.props.params;
const { dispatch } = this.props;
const { id } = this.props.params;
dispatch(expandGroupTimeline(id));
dispatch(expandGroupTimeline(id));
this.disconnect = dispatch(connectGroupStream(id));
this.disconnect = dispatch(connectGroupStream(id));
}
componentWillUnmount () {
if (this.disconnect) {
this.disconnect();
this.disconnect = null;
}
if (this.disconnect) {
this.disconnect();
this.disconnect = null;
}
}
handleLoadMore = maxId => {
const { id } = this.props.params;
this.props.dispatch(expandGroupTimeline(id, { maxId }));
const { id } = this.props.params;
this.props.dispatch(expandGroupTimeline(id, { maxId }));
}
render () {
const { columnId, group, relationships, account } = this.props;
const { id } = this.props.params;
const { columnId, group, relationships, account } = this.props;
const { id } = this.props.params;
if (typeof group === 'undefined' || !relationships) {
return (
<Column>
<LoadingIndicator />
</Column>
);
} else if (group === false) {
return (
<Column>
<MissingIndicator />
</Column>
);
}
if (typeof group === 'undefined' || !relationships) {
return (
<Column>
<LoadingIndicator />
</Column>
);
} else if (group === false) {
return (
<Column>
<MissingIndicator />
</Column>
);
}
return (
<div>
{relationships.get('member') && (
<div className='timeline-compose-block'>
<div className='timeline-compose-block__avatar'>
<Avatar account={account} size={46} />
</div>
<ComposeFormContainer group={group} shouldCondense={true} autoFocus={false}/>
</div>
)}
return (
<div>
{relationships.get('member') && (
<div className='timeline-compose-block'>
<div className='timeline-compose-block__avatar'>
<Avatar account={account} size={46} />
</div>
<ComposeFormContainer group={group} shouldCondense autoFocus={false} />
</div>
)}
<div className='group__feed'>
<StatusListContainer
alwaysPrepend
scrollKey={`group_timeline-${columnId}`}
timelineId={`group:${id}`}
onLoadMore={this.handleLoadMore}
group={group}
withGroupAdmin={relationships && relationships.get('admin')}
emptyMessage={<FormattedMessage id='empty_column.group' defaultMessage='There is nothing in this group yet. When members of this group make new posts, they will appear here.' />}
/>
</div>
</div>
);
<div className='group__feed'>
<StatusListContainer
alwaysPrepend
scrollKey={`group_timeline-${columnId}`}
timelineId={`group:${id}`}
onLoadMore={this.handleLoadMore}
group={group}
withGroupAdmin={relationships && relationships.get('admin')}
emptyMessage={<FormattedMessage id='empty_column.group' defaultMessage='There is nothing in this group yet. When members of this group make new posts, they will appear here.' />}
/>
</div>
</div>
);
}
}

View file

@ -68,7 +68,7 @@ class HomeTimeline extends React.PureComponent {
}
render () {
const { intl, hasUnread, siteTitle} = this.props;
const { intl, hasUnread, siteTitle } = this.props;
return (
<Column label={intl.formatMessage(messages.title)}>
@ -79,7 +79,7 @@ class HomeTimeline extends React.PureComponent {
scrollKey='home_timeline'
onLoadMore={this.handleLoadMore}
timelineId='home'
emptyMessage={<FormattedMessage id='empty_column.home' defaultMessage='Your home timeline is empty! Visit {public} to get started and meet other users.' values={{ public: <Link to='/timeline/local'><FormattedMessage id='empty_column.home.local_tab' defaultMessage='the {site_title} tab' values={{site_title: siteTitle}} /></Link> }} />}
emptyMessage={<FormattedMessage id='empty_column.home' defaultMessage='Your home timeline is empty! Visit {public} to get started and meet other users.' values={{ public: <Link to='/timeline/local'><FormattedMessage id='empty_column.home.local_tab' defaultMessage='the {site_title} tab' values={{ site_title: siteTitle }} /></Link> }} />}
/>
</Column>
);

View file

@ -1,5 +1,5 @@
import React from 'react';
import { connect } from 'react-redux'
import { connect } from 'react-redux';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { Link } from 'react-router-dom';
import LoginForm from 'gabsocial/features/auth_login/components/login_form';
@ -11,13 +11,14 @@ const mapStateToProps = (state, props) => ({
});
class LandingPage extends ImmutablePureComponent {
getSiteLogo = () => {
const { instance, soapbox } = this.props;
const logos = {
imgLogo: (<img alt={instance.get('title')} src={soapbox.get('logo')} />),
textLogo: (<h1>{instance.get('title')}</h1>),
}
return soapbox.get('logo') ? logos['imgLogo'] : logos['textLogo'];
};
return soapbox.get('logo') ? logos.imgLogo : logos.textLogo;
}
render() {
@ -36,7 +37,7 @@ class LandingPage extends ImmutablePureComponent {
<Link className='nav-link optional' to='/'>Home</Link>
<Link className='nav-link' to='/about'>About</Link>
</div>
<div className='nav-center'></div>
<div className='nav-center' />
<div className='nav-right'>
<div className='hidden-sm'>
<LoginForm />
@ -121,8 +122,9 @@ class LandingPage extends ImmutablePureComponent {
</div>
<NotificationsContainer />
</div>
)
);
}
}
export default connect(mapStateToProps)(LandingPage);

View file

@ -21,7 +21,7 @@ const getOrderedLists = createSelector([state => state.get('lists')], lists => {
return lists.toList().filter(item => !!item).sort((a, b) => a.get('title').localeCompare(b.get('title')));
});
const mapStateToProps = (state, {accountId}) => ({
const mapStateToProps = (state, { accountId }) => ({
listIds: getOrderedLists(state).map(list=>list.get('id')),
account: state.getIn(['accounts', accountId]),
});
@ -84,12 +84,12 @@ class ListAdder extends ImmutablePureComponent {
<Account accountId={accountId} />
</div>
<br/>
<br />
<ColumnSubheading text={intl.formatMessage(messages.add)} />
<NewListForm />
<br/>
<br />
<ColumnSubheading text={intl.formatMessage(messages.subheading)} />
<div className='list-adder__lists'>

View file

@ -75,7 +75,7 @@ class ListEditor extends ImmutablePureComponent {
<div className='list-editor'>
<ColumnSubheading text={intl.formatMessage(messages.changeTitle)} />
<EditListForm />
<br/>
<br />
{
accountIds.size > 0 &&
@ -87,7 +87,7 @@ class ListEditor extends ImmutablePureComponent {
</div>
}
<br/>
<br />
<ColumnSubheading text={intl.formatMessage(messages.addToList)} />
<Search />
<div className='list-editor__accounts'>

View file

@ -120,8 +120,8 @@ class ListTimeline extends React.PureComponent {
const emptyMessage = (
<div>
<FormattedMessage id='empty_column.list' defaultMessage='There is nothing in this list yet. When members of this list create new posts, they will appear here.' />
<br/><br/>
<Button onClick={this.handleEditClick}><FormattedMessage id='list.click_to_add' defaultMessage='Click here to add people'/></Button>
<br /><br />
<Button onClick={this.handleEditClick}><FormattedMessage id='list.click_to_add' defaultMessage='Click here to add people' /></Button>
</div>
);
@ -137,7 +137,7 @@ class ListTimeline extends React.PureComponent {
<Icon id='trash' /> <FormattedMessage id='lists.delete' defaultMessage='Delete list' />
</button>
<hr/>
<hr />
<Link to='/lists' className='text-btn column-header__setting-btn column-header__setting-btn--link'>
<FormattedMessage id='lists.view_all' defaultMessage='View all lists' />

View file

@ -61,10 +61,10 @@ class Lists extends ImmutablePureComponent {
return (
<Column icon='list-ul' heading={intl.formatMessage(messages.heading)} backBtnSlim>
<br/>
<br />
<ColumnSubheading text={intl.formatMessage(messages.add)} />
<NewListForm />
<br/>
<br />
<ColumnSubheading text={intl.formatMessage(messages.subheading)} />
<ScrollableList
scrollKey='lists'

View file

@ -51,7 +51,7 @@ class PinnedStatuses extends ImmutablePureComponent {
statusIds={statusIds}
scrollKey='pinned_statuses'
hasMore={hasMore}
emptyMessage={<FormattedMessage id='pinned_statuses.none' defaultMessage='No pins to show.'/>}
emptyMessage={<FormattedMessage id='pinned_statuses.none' defaultMessage='No pins to show.' />}
/>
</Column>
);

View file

@ -88,7 +88,7 @@ class CommunityTimeline extends React.PureComponent {
</HomeColumnHeader>
<ExplanationBox
title={<FormattedMessage id='fediverse_tab.explanation_box.title' defaultMessage='What is the Fediverse?' />}
explanation={<FormattedMessage id='fediverse_tab.explanation_box.explanation' defaultMessage='{site_title} is part of the Fediverse, a social network made up of thousands of independent social media sites (aka "servers"). The posts you see here are from 3rd-party servers. You have the freedom to engage with them, or to block any server you don&apos;t like. Pay attention to the full username after the second @ symbol to know which server a post is from. To see only {site_title} posts, visit {local}.' values={{site_title: siteTitle, local: <Link to='/timeline/local'><FormattedMessage id='empty_column.home.local_tab' defaultMessage='the {site_title} tab' values={{site_title: siteTitle}} /></Link>}} />}
explanation={<FormattedMessage id='fediverse_tab.explanation_box.explanation' defaultMessage='{site_title} is part of the Fediverse, a social network made up of thousands of independent social media sites (aka "servers"). The posts you see here are from 3rd-party servers. You have the freedom to engage with them, or to block any server you don&apos;t like. Pay attention to the full username after the second @ symbol to know which server a post is from. To see only {site_title} posts, visit {local}.' values={{ site_title: siteTitle, local: <Link to='/timeline/local'><FormattedMessage id='empty_column.home.local_tab' defaultMessage='the {site_title} tab' values={{ site_title: siteTitle }} /></Link> }} />}
/>
<StatusListContainer
scrollKey={`${timelineId}_timeline`}

View file

@ -17,13 +17,13 @@ const mapStateToProps = (state, props) => {
const getStatus = makeGetStatus();
const status = getStatus(state, {
id: props.params.statusId,
username: props.params.username
username: props.params.username,
});
return {
status,
accountIds: state.getIn(['user_lists', 'reblogged_by', props.params.statusId]),
}
};
};
export default @connect(mapStateToProps)

View file

@ -25,7 +25,7 @@ class Header extends ImmutablePureComponent {
componentWillReceiveProps (nextProps) {
if (nextProps.submitted) {
const submittedValue = nextProps.value;
this.setState({submittedValue})
this.setState({ submittedValue });
}
}
@ -67,6 +67,7 @@ class Header extends ImmutablePureComponent {
</div>
);
}
}
export default connect(mapStateToProps)(Header);

View file

@ -234,6 +234,7 @@ class ActionBar extends React.PureComponent {
</div>
);
}
}
export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(ActionBar));

View file

@ -64,7 +64,7 @@ const makeMapStateToProps = () => {
const mapStateToProps = (state, props) => {
const status = getStatus(state, {
id: props.params.statusId,
username: props.params.username
username: props.params.username,
});
let ancestorsIds = Immutable.List();
@ -462,10 +462,11 @@ class Status extends ImmutablePureComponent {
aria-label={intl.formatMessage(status.get('hidden') ? messages.revealAll : messages.hideAll)}
onClick={this.handleToggleAll}
aria-pressed={
status.get('hidden') ? 'false' : 'true'}>
<Icon id={status.get('hidden') ? 'eye-slash' : 'eye'
status.get('hidden') ? 'false' : 'true'}
>
<Icon id={status.get('hidden') ? 'eye-slash' : 'eye'
}
/>
/>
</button>
)}
/>

View file

@ -26,7 +26,7 @@ export default class Column extends React.PureComponent {
<ColumnHeader icon={icon} active={active} type={heading} columnHeaderId={columnHeaderId} />
);
const backBtn = backBtnSlim ? (<ColumnBackButtonSlim/>) : (<ColumnBackButton/>);
const backBtn = backBtnSlim ? (<ColumnBackButtonSlim />) : (<ColumnBackButton />);
return (
<div role='region' aria-labelledby={columnHeaderId} className='column'>

View file

@ -27,7 +27,7 @@ class ColumnsArea extends ImmutablePureComponent {
render () {
const { columns, children, intl } = this.props;
const layout = this.props.layout || {LEFT:null,RIGHT:null};
const layout = this.props.layout || { LEFT:null, RIGHT:null };
return (
<div className='page'>
@ -55,6 +55,7 @@ class ColumnsArea extends ImmutablePureComponent {
</div>
</div>
)
);
}
}

View file

@ -33,7 +33,7 @@ class ComposeModal extends ImmutablePureComponent {
};
onClickClose = () => {
const {composeText, dispatch, onClose, intl} = this.props;
const { composeText, dispatch, onClose, intl } = this.props;
if (composeText) {
dispatch(openModal('CONFIRM', {
@ -42,8 +42,7 @@ class ComposeModal extends ImmutablePureComponent {
onConfirm: () => dispatch(cancelReplyCompose()),
onCancel: () => dispatch(openModal('COMPOSE')),
}));
}
else {
} else {
onClose('COMPOSE');
}
};
@ -67,6 +66,7 @@ class ComposeModal extends ImmutablePureComponent {
</div>
);
}
}
export default injectIntl(connect(mapStateToProps)(ComposeModal));

View file

@ -32,7 +32,7 @@ class ConfirmationModal extends React.PureComponent {
}
handleCancel = () => {
const {onClose, onCancel} = this.props;
const { onClose, onCancel } = this.props;
onClose();
if (onCancel) onCancel();
}

View file

@ -17,6 +17,7 @@ class ExplanationBox extends React.PureComponent {
{dismissable && <span className='explanation-box__dismiss'>Dismiss</span>}
</div>
</div>
)
);
}
}

View file

@ -12,7 +12,7 @@ const mapStateToProps = state => {
return {
locked: state.getIn(['accounts', me, 'locked']),
count: state.getIn(['user_lists', 'follow_requests', 'items'], ImmutableList()).size,
}
};
};
export default @withRouter

View file

@ -34,7 +34,7 @@ class FundingPanel extends ImmutablePureComponent {
return (
<div className='wtf-panel funding-panel'>
<div className='wtf-panel-header'>
<i role='img' alt='users' className='fa fa-line-chart wtf-panel-header__icon'></i>
<i role='img' alt='users' className='fa fa-line-chart wtf-panel-header__icon' />
<span className='wtf-panel-header__label'>
<span>Funding Goal</span>
</span>
@ -50,13 +50,14 @@ class FundingPanel extends ImmutablePureComponent {
<a className='button' href='/donate'>Donate</a>
</div>
</div>
)
);
}
};
const mapStateToProps = state => {
return {
funding: state.getIn(['patron', 'funding'])
funding: state.getIn(['patron', 'funding']),
};
};
@ -64,4 +65,4 @@ export default injectIntl(
connect(mapStateToProps, null, null, {
forwardRef: true,
}
)(FundingPanel))
)(FundingPanel));

View file

@ -13,13 +13,13 @@ const sourceCode = {
url: 'https://gitlab.com/soapbox-pub/soapbox-fe',
repository: 'soapox-pub/soapbox-fe',
version: '0.0.0',
}
};
const mapStateToProps = state => {
const me = state.get('me');
return {
account: state.getIn(['accounts', me]),
}
};
};
const mapDispatchToProps = (dispatch) => ({

View file

@ -48,7 +48,7 @@ class ProfileInfoPanel extends ImmutablePureComponent {
<div className='profile-info-panel__content'>
<div className='profile-info-panel-content__name'>
<h1>
<span/>
<span />
<small>@{username}</small>
</h1>
</div>
@ -72,23 +72,25 @@ class ProfileInfoPanel extends ImmutablePureComponent {
<div className='profile-info-panel-content__name'>
<h1>
<span dangerouslySetInnerHTML={displayNameHtml} />
{account.get('is_verified') && <VerificationBadge />}
{badge}
{account.get('is_verified') && <VerificationBadge />}
{badge}
<small>@{acctFull(account)} {lockedIcon}</small>
</h1>
</div>
<div className='profile-info-panel-content__badges'>
{account.get('is_admin') && <Badge slug="admin" title="Admin" />}
{account.get('is_moderator') && <Badge slug="moderator" title="Moderator" />}
{account.get('is_admin') && <Badge slug='admin' title='Admin' />}
{account.get('is_moderator') && <Badge slug='moderator' title='Moderator' />}
{account.get('is_pro') && <ProBadge />}
{account.get('is_donor') && <DonorBadge />}
{account.get('is_investor') && <InvestorBadge />}
{account.get('acct').includes('@') || <div className='profile-info-panel-content__badges__join-date'>
<Icon id="calendar"/>
<FormattedMessage id='account.member_since' defaultMessage='Member since {date}' values={{
date: memberSinceDate
}} />
<Icon id='calendar' />
<FormattedMessage
id='account.member_since' defaultMessage='Member since {date}' values={{
date: memberSinceDate,
}}
/>
</div>}
</div>
@ -131,6 +133,7 @@ class ProfileInfoPanel extends ImmutablePureComponent {
</div>
);
}
}
const mapStateToProps = (state, { account }) => {
@ -145,4 +148,4 @@ export default injectIntl(
connect(mapStateToProps, null, null, {
forwardRef: true,
}
)(ProfileInfoPanel))
)(ProfileInfoPanel));

View file

@ -7,7 +7,7 @@ import { connect } from 'react-redux';
const mapStateToProps = state => ({
promoItems: state.getIn(['soapbox', 'promoPanel', 'items']),
})
});
export default @connect(mapStateToProps)
class PromoPanel extends React.PureComponent {
@ -20,15 +20,16 @@ class PromoPanel extends React.PureComponent {
<div className='wtf-panel promo-panel'>
<div className='promo-panel__container'>
{promoItems.map((item, i) =>
<div className='promo-panel-item' key={i}>
(<div className='promo-panel-item' key={i}>
<a className='promo-panel-item__btn' href={item.get('url')} target='_blank'>
<Icon id={item.get('icon')} className='promo-panel-item__icon' fixedWidth />
{item.get('text')}
</a>
</div>
</div>)
)}
</div>
</div>
)
);
}
}

View file

@ -17,7 +17,7 @@ const SignUpPanel = ({ siteTitle, me }) => {
<div className='wtf-panel'>
<div className='wtf-panel-header'>
<span className='wtf-panel-header__label'>
<FormattedMessage id='signup_panel.title' defaultMessage='New to {site_title}?' values={{site_title: siteTitle}} />
<FormattedMessage id='signup_panel.title' defaultMessage='New to {site_title}?' values={{ site_title: siteTitle }} />
</span>
</div>
<div className='wtf-panel__content'>
@ -25,13 +25,13 @@ const SignUpPanel = ({ siteTitle, me }) => {
<FormattedMessage id='signup_panel.subtitle' defaultMessage='Sign up now to discuss.' />
</span>
<div className='wtf-panel__form'>
<a className='button' href="/auth/sign_up">
<a className='button' href='/auth/sign_up'>
<FormattedMessage id='account.register' defaultMessage='Sign up' />
</a>
</div>
</div>
</div>
)
}
);
};
export default injectIntl(connect(mapStateToProps)(SignUpPanel));

View file

@ -64,33 +64,33 @@ class TabsBar extends React.PureComponent {
links.push(
<Link key='logo' className='tabs-bar__link--logo' to='/' data-preview-title-id='column.home' style={{ padding: '0', backgroundImage: `url(${logo})` }}>
<FormattedMessage id='tabs_bar.home' defaultMessage='Home' />
</Link>)
</Link>);
}
links.push(
<NavLink key='home' className='tabs-bar__link' exact to='/' data-preview-title-id='column.home'>
<i className='tabs-bar__link__icon home'/>
<i className='tabs-bar__link__icon home' />
<FormattedMessage id='tabs_bar.home' defaultMessage='Home' />
</NavLink>)
</NavLink>);
if (account) {
links.push(
<NavLink key='notifications' className='tabs-bar__link' to='/notifications' data-preview-title-id='column.notifications'>
<i className='tabs-bar__link__icon notifications'/>
<i className='tabs-bar__link__icon notifications' />
<NotificationsCounterIcon />
<FormattedMessage id='tabs_bar.notifications' defaultMessage='Notifications' />
</NavLink>)
</NavLink>);
}
links.push(
<NavLink key='search' className='tabs-bar__link tabs-bar__link--search' to='/search' data-preview-title-id='tabs_bar.search'>
<i className='tabs-bar__link__icon tabs-bar__link__icon--search'/>
<i className='tabs-bar__link__icon tabs-bar__link__icon--search' />
<FormattedMessage id='tabs_bar.search' defaultMessage='Search' />
</NavLink>
);
return links.map((link) =>
React.cloneElement(link, {
'aria-label': formatMessage({
id: link.props['data-preview-title-id']
})
}));
id: link.props['data-preview-title-id'],
}),
}));
}
handleScroll = throttle(() => {
@ -102,10 +102,10 @@ class TabsBar extends React.PureComponent {
let st = pageYOffset || scrollTop;
if (st > this.lastScrollTop){
let offset = st - this.lastScrollTop;
if (offset > 50) this.setState({collapsed: true});
if (offset > 50) this.setState({ collapsed: true });
} else {
let offset = this.lastScrollTop - st;
if (offset > 50) this.setState({collapsed: false});
if (offset > 50) this.setState({ collapsed: false });
}
this.lastScrollTop = st <= 0 ? 0 : st;
@ -120,7 +120,7 @@ class TabsBar extends React.PureComponent {
const classes = classNames('tabs-bar', {
'tabs-bar--collapsed': collapsed,
})
});
return (
<nav className={classes} ref={this.setRef}>
@ -136,7 +136,7 @@ class TabsBar extends React.PureComponent {
<div className='flex'>
<div className='tabs-bar__profile'>
<Avatar account={account} />
<button className='tabs-bar__sidebar-btn' onClick={onOpenSidebar}></button>
<button className='tabs-bar__sidebar-btn' onClick={onOpenSidebar} />
<ActionBar account={account} size={34} />
</div>
<button className='tabs-bar__button-compose button' onClick={onOpenCompose} aria-label='Gab'>
@ -160,6 +160,7 @@ class TabsBar extends React.PureComponent {
</nav>
);
}
}
const mapStateToProps = state => {
@ -181,4 +182,4 @@ const mapDispatchToProps = (dispatch) => ({
export default injectIntl(
connect(mapStateToProps, mapDispatchToProps, null, { forwardRef: true }
)(TabsBar))
)(TabsBar));

View file

@ -47,9 +47,10 @@ class TrendsPanel extends ImmutablePureComponent {
))}
</div>
</div>
</div>
)
};
</div>
);
};
};
@ -60,11 +61,11 @@ const mapStateToProps = state => ({
const mapDispatchToProps = dispatch => {
return {
fetchTrends: () => dispatch(fetchTrends()),
}
};
};
export default injectIntl(
connect(mapStateToProps, mapDispatchToProps, null, {
forwardRef: true,
}
)(TrendsPanel))
)(TrendsPanel));

View file

@ -36,7 +36,7 @@ class UnauthorizedModal extends ImmutablePureComponent {
return (
<div className='modal-root__modal compose-modal unauthorized-modal'>
<div className='compose-modal__header'>
<h3 className='compose-modal__header__title'><FormattedMessage id='unauthorized_modal.title' defaultMessage='Sign up for {site_title}' values={{site_title: siteTitle}} /></h3>
<h3 className='compose-modal__header__title'><FormattedMessage id='unauthorized_modal.title' defaultMessage='Sign up for {site_title}' values={{ site_title: siteTitle }} /></h3>
<IconButton className='compose-modal__close' title={intl.formatMessage(messages.close)} icon='times' onClick={this.onClickClose} size={20} />
</div>
<div className='compose-modal__content'>
@ -50,13 +50,16 @@ class UnauthorizedModal extends ImmutablePureComponent {
</div>
</div>
<div className='unauthorized-modal__footer'>
<FormattedMessage id='unauthorized_modal.footer' defaultMessage='Already have an account? {login}.' values={{
login: <a href='/auth/sign_in'><FormattedMessage id='account.login' defaultMessage='Log in' /></a>
}} />
<FormattedMessage
id='unauthorized_modal.footer' defaultMessage='Already have an account? {login}.' values={{
login: <a href='/auth/sign_in'><FormattedMessage id='account.login' defaultMessage='Log in' /></a>,
}}
/>
</div>
</div>
);
}
}
export default injectIntl(connect(mapStateToProps)(UnauthorizedModal));

View file

@ -12,6 +12,7 @@ import { shortNumberFormat } from 'gabsocial/utils/numbers';
import { acctFull } from 'gabsocial/utils/accounts';
class UserPanel extends ImmutablePureComponent {
static propTypes = {
account: ImmutablePropTypes.map,
intl: PropTypes.object.isRequired,
@ -78,8 +79,9 @@ class UserPanel extends ImmutablePureComponent {
</div>
</div>
)
);
}
};
@ -96,4 +98,4 @@ export default injectIntl(
connect(mapStateToProps, null, null, {
forwardRef: true,
}
)(UserPanel))
)(UserPanel));

View file

@ -58,6 +58,7 @@ class WhoToFollowPanel extends ImmutablePureComponent {
</div>
);
};
};
const mapStateToProps = state => ({
@ -68,11 +69,11 @@ const mapDispatchToProps = dispatch => {
return {
fetchSuggestions: () => dispatch(fetchSuggestions()),
dismissSuggestion: account => dispatch(dismissSuggestion(account.get('id'))),
}
};
};
export default injectIntl(
connect(mapStateToProps, mapDispatchToProps, null, {
forwardRef: true,
}
)(WhoToFollowPanel))
)(WhoToFollowPanel));

View file

@ -11,7 +11,7 @@ const mapStateToProps = state => ({
const mapDispatchToProps = (dispatch) => ({
onClose (optionalType) {
if (optionalType === 'COMPOSE') {
dispatch(cancelReplyCompose());
dispatch(cancelReplyCompose());
}
dispatch(closeModal());

View file

@ -30,7 +30,7 @@ const makeGetStatusIds = () => createSelector([
});
});
const mapStateToProps = (state, {timelineId}) => {
const mapStateToProps = (state, { timelineId }) => {
const getStatusIds = makeGetStatusIds();
return {

View file

@ -90,7 +90,7 @@ const mapStateToProps = state => {
me: state.get('me'),
accessToken: state.getIn(['auth', 'user', 'access_token']),
streamingUrl: state.getIn(['instance', 'urls', 'streaming_api']),
}
};
};
const keyMap = {
@ -239,6 +239,7 @@ class SwitchingColumnsArea extends React.PureComponent {
</Switch>
);
}
}
export default @connect(mapStateToProps)
@ -486,7 +487,7 @@ class UI extends React.PureComponent {
}
handleHotkeyToggleHelp = () => {
this.props.dispatch(openModal("HOTKEYS"));
this.props.dispatch(openModal('HOTKEYS'));
}
handleHotkeyGoToHome = () => {
@ -526,7 +527,7 @@ class UI extends React.PureComponent {
}
handleOpenComposeModal = () => {
this.props.dispatch(openModal("COMPOSE"));
this.props.dispatch(openModal('COMPOSE'));
}
render () {
@ -554,7 +555,7 @@ class UI extends React.PureComponent {
goToRequests: this.handleHotkeyGoToRequests,
} : {};
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>;
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)} />;
return (
<HotKeys keyMap={keyMap} handlers={handlers} ref={this.setHotkeysRef} attach={window} focused>

View file

@ -14,6 +14,7 @@ const mapStateToProps = state => {
};
class WrappedRoute extends React.Component {
static propTypes = {
component: PropTypes.func.isRequired,
page: PropTypes.func,
@ -35,11 +36,11 @@ class WrappedRoute extends React.Component {
<BundleContainer fetchComponent={component} loading={this.renderLoading} error={this.renderError}>
{Component =>
(
<Page params={match.params} {...componentParams}>
<Component params={match.params} {...componentParams}>
{content}
</Component>
</Page>
<Page params={match.params} {...componentParams}>
<Component params={match.params} {...componentParams}>
{content}
</Component>
</Page>
)
}
</BundleContainer>
@ -83,7 +84,8 @@ class WrappedRoute extends React.Component {
return <Route {...rest} render={this.renderComponent} />;
}
}
const wrappedRoute = connect(mapStateToProps)(WrappedRoute);
export {wrappedRoute as WrappedRoute};
export { wrappedRoute as WrappedRoute };

View file

@ -12,62 +12,63 @@ import { fetchGroup } from '../actions/groups';
import GroupSidebarPanel from '../features/groups/sidebar_panel';
const mapStateToProps = (state, { params: { id } }) => ({
group: state.getIn(['groups', id]),
relationships: state.getIn(['group_relationships', id]),
group: state.getIn(['groups', id]),
relationships: state.getIn(['group_relationships', id]),
});
export default @connect(mapStateToProps)
class GroupPage extends ImmutablePureComponent {
static propTypes = {
group: ImmutablePropTypes.map,
relationships: ImmutablePropTypes.map,
dispatch: PropTypes.func.isRequired,
};
group: ImmutablePropTypes.map,
relationships: ImmutablePropTypes.map,
dispatch: PropTypes.func.isRequired,
};
componentWillMount() {
const { params: { id }, dispatch } = this.props;
componentWillMount() {
const { params: { id }, dispatch } = this.props;
dispatch(fetchGroup(id));
}
dispatch(fetchGroup(id));
}
render () {
const { children, group, relationships } = this.props;
render () {
const { children, group, relationships } = this.props;
return (
<div className='page group'>
{group && <HeaderContainer groupId={group.get('id')} />}
return (
<div className='page group'>
{group && <HeaderContainer groupId={group.get('id')} />}
<div className='page__columns'>
<div className='columns-area__panels'>
<div className='columns-area__panels__pane columns-area__panels__pane--left'>
<div className='columns-area__panels__pane__inner'>
{group && relationships &&
<GroupPanel
group={group}
relationships={relationships}
/>}
<div className='page__columns'>
<div className='columns-area__panels'>
<div className='columns-area__panels__pane columns-area__panels__pane--left'>
<div className='columns-area__panels__pane__inner'>
{group && relationships &&
<GroupPanel
group={group}
relationships={relationships}
/>}
<PromoPanel />
<LinkFooter />
</div>
</div>
<PromoPanel />
<LinkFooter />
</div>
</div>
<div className='columns-area__panels__main'>
<div className='columns-area columns-area--mobile'>
{children}
</div>
</div>
<div className='columns-area__panels__main'>
<div className='columns-area columns-area--mobile'>
{children}
</div>
</div>
<div className='columns-area__panels__pane columns-area__panels__pane--right'>
<div className='columns-area__panels__pane__inner'>
<GroupSidebarPanel />
<WhoToFollowPanel />
</div>
</div>
</div>
</div>
</div>
);
}
<div className='columns-area__panels__pane columns-area__panels__pane--right'>
<div className='columns-area__panels__pane__inner'>
<GroupSidebarPanel />
<WhoToFollowPanel />
</div>
</div>
</div>
</div>
</div>
)
}
}

View file

@ -12,46 +12,48 @@ const mapStateToProps = state => {
const me = state.get('me');
return {
account: state.getIn(['accounts', me]),
}
};
};
export default @connect(mapStateToProps)
class GroupsPage extends ImmutablePureComponent {
static propTypes = {
account: ImmutablePropTypes.map
account: ImmutablePropTypes.map,
};
render () {
const { children } = this.props;
render () {
const { children } = this.props;
return (
<div className='page'>
<div className='page__columns'>
<div className='columns-area__panels'>
return (
<div className='page'>
<div className='page__columns'>
<div className='columns-area__panels'>
<div className='columns-area__panels__pane columns-area__panels__pane--left'>
<div className='columns-area__panels__pane__inner'>
<UserPanel />
<PromoPanel />
<LinkFooter />
<div className='columns-area__panels__pane columns-area__panels__pane--left'>
<div className='columns-area__panels__pane__inner'>
<UserPanel />
<PromoPanel />
<LinkFooter />
</div>
</div>
</div>
<div className='columns-area__panels__main'>
<div className='columns-area columns-area--mobile'>
{children}
<div className='columns-area__panels__main'>
<div className='columns-area columns-area--mobile'>
{children}
</div>
</div>
</div>
<div className='columns-area__panels__pane columns-area__panels__pane--right'>
<div className='columns-area__panels__pane__inner'>
<GroupSidebarPanel />
<WhoToFollowPanel />
<div className='columns-area__panels__pane columns-area__panels__pane--right'>
<div className='columns-area__panels__pane__inner'>
<GroupSidebarPanel />
<WhoToFollowPanel />
</div>
</div>
</div>
</div>
</div>
</div>
)
}
);
}
}

View file

@ -17,13 +17,14 @@ const mapStateToProps = state => {
return {
account: state.getIn(['accounts', me]),
hasPatron: state.getIn(['soapbox', 'extensions', 'patron']),
}
};
};
export default @connect(mapStateToProps)
class HomePage extends ImmutablePureComponent {
render () {
const {children, account, hasPatron} = this.props;
const { children, account, hasPatron } = this.props;
return (
<div className='page'>
@ -45,7 +46,7 @@ class HomePage extends ImmutablePureComponent {
<div className='timeline-compose-block__avatar'>
<Avatar account={account} size={46} />
</div>
<ComposeFormContainer shouldCondense={true} autoFocus={false}/>
<ComposeFormContainer shouldCondense autoFocus={false} />
</div>
{children}
@ -62,6 +63,7 @@ class HomePage extends ImmutablePureComponent {
</div>
</div>
</div>
)
);
}
}

View file

@ -24,8 +24,7 @@ const mapStateToProps = (state, { params: { username }, withReplies = false }) =
let accountUsername = username;
if (accountFetchError) {
accountId = null;
}
else {
} else {
account = accounts.find(acct => username.toLowerCase() == acct.getIn(['acct'], '').toLowerCase());
accountId = account ? account.getIn(['id'], null) : -1;
accountUsername = account ? account.getIn(['acct'], '') : '';
@ -42,19 +41,20 @@ const mapStateToProps = (state, { params: { username }, withReplies = false }) =
export default @connect(mapStateToProps)
class ProfilePage extends ImmutablePureComponent {
static propTypes = {
account: ImmutablePropTypes.map,
accountUsername: PropTypes.string.isRequired,
};
render () {
const {children, accountId, account, accountUsername} = this.props;
const { children, accountId, account, accountUsername } = this.props;
const bg = account ? account.getIn(['customizations', 'background']) : undefined;
return (
<div className={bg && `page page--customization page--${bg}` || 'page'}>
<div className='page__top'>
<HeaderContainer accountId={accountId} username={accountUsername}/>
<HeaderContainer accountId={accountId} username={accountUsername} />
</div>
<div className='page__columns'>
@ -85,6 +85,7 @@ class ProfilePage extends ImmutablePureComponent {
</div>
</div>
)
);
}
}

View file

@ -6,7 +6,7 @@ import WhoToFollowPanel from '../features/ui/components/who_to_follow_panel';
import LinkFooter from '../features/ui/components/link_footer';
import SignUpPanel from '../features/ui/components/sign_up_panel';
const SearchPage = ({children}) => (
const SearchPage = ({ children }) => (
<div className='page'>
<div className='page__top'>
<Header />

View file

@ -33,7 +33,7 @@ export default function accounts(state = initialState, action) {
return normalizeAccounts(state, action.accounts);
case ACCOUNT_FETCH_FAIL_FOR_USERNAME_LOOKUP:
return state.set(-1, ImmutableMap({
username: action.username
username: action.username,
}));
default:
return state;

View file

@ -1,57 +1,57 @@
import { Map as ImmutableMap } from 'immutable';
import {
GROUP_CREATE_REQUEST,
GROUP_CREATE_FAIL,
GROUP_CREATE_SUCCESS,
GROUP_UPDATE_REQUEST,
GROUP_UPDATE_FAIL,
GROUP_UPDATE_SUCCESS,
GROUP_EDITOR_RESET,
GROUP_EDITOR_SETUP,
GROUP_EDITOR_VALUE_CHANGE,
GROUP_CREATE_REQUEST,
GROUP_CREATE_FAIL,
GROUP_CREATE_SUCCESS,
GROUP_UPDATE_REQUEST,
GROUP_UPDATE_FAIL,
GROUP_UPDATE_SUCCESS,
GROUP_EDITOR_RESET,
GROUP_EDITOR_SETUP,
GROUP_EDITOR_VALUE_CHANGE,
} from '../actions/group_editor';
const initialState = ImmutableMap({
groupId: null,
isSubmitting: false,
isChanged: false,
title: '',
description: '',
coverImage: null,
groupId: null,
isSubmitting: false,
isChanged: false,
title: '',
description: '',
coverImage: null,
});
export default function groupEditorReducer(state = initialState, action) {
switch(action.type) {
case GROUP_EDITOR_RESET:
return initialState;
case GROUP_EDITOR_SETUP:
return state.withMutations(map => {
map.set('groupId', action.group.get('id'));
map.set('title', action.group.get('title'));
map.set('description', action.group.get('description'));
map.set('isSubmitting', false);
});
case GROUP_EDITOR_VALUE_CHANGE:
return state.withMutations(map => {
map.set(action.field, action.value);
map.set('isChanged', true);
});
case GROUP_CREATE_REQUEST:
case GROUP_UPDATE_REQUEST:
return state.withMutations(map => {
map.set('isSubmitting', true);
map.set('isChanged', false);
});
case GROUP_CREATE_FAIL:
case GROUP_UPDATE_FAIL:
return state.set('isSubmitting', false);
case GROUP_CREATE_SUCCESS:
case GROUP_UPDATE_SUCCESS:
return state.withMutations(map => {
map.set('isSubmitting', false);
map.set('groupId', action.group.id);
});
default:
return state;
}
switch(action.type) {
case GROUP_EDITOR_RESET:
return initialState;
case GROUP_EDITOR_SETUP:
return state.withMutations(map => {
map.set('groupId', action.group.get('id'));
map.set('title', action.group.get('title'));
map.set('description', action.group.get('description'));
map.set('isSubmitting', false);
});
case GROUP_EDITOR_VALUE_CHANGE:
return state.withMutations(map => {
map.set(action.field, action.value);
map.set('isChanged', true);
});
case GROUP_CREATE_REQUEST:
case GROUP_UPDATE_REQUEST:
return state.withMutations(map => {
map.set('isSubmitting', true);
map.set('isChanged', false);
});
case GROUP_CREATE_FAIL:
case GROUP_UPDATE_FAIL:
return state.set('isSubmitting', false);
case GROUP_CREATE_SUCCESS:
case GROUP_UPDATE_SUCCESS:
return state.withMutations(map => {
map.set('isSubmitting', false);
map.set('groupId', action.group.id);
});
default:
return state;
}
};

View file

@ -1,27 +1,26 @@
import { GROUP_RELATIONSHIPS_FETCH_SUCCESS, GROUP_JOIN_SUCCESS, GROUP_LEAVE_SUCCESS } from '../actions/groups';
import { Map as ImmutableMap, fromJS } from 'immutable';
const normalizeRelationship = (state, relationship) => state.set(relationship.id, fromJS(relationship));
const normalizeRelationships = (state, relationships) => {
relationships.forEach(relationship => {
state = normalizeRelationship(state, relationship);
});
return state;
relationships.forEach(relationship => {
state = normalizeRelationship(state, relationship);
});
return state;
};
const initialState = ImmutableMap();
export default function group_relationships(state = initialState, action) {
switch(action.type) {
case GROUP_JOIN_SUCCESS:
case GROUP_LEAVE_SUCCESS:
return normalizeRelationship(state, action.relationship);
case GROUP_RELATIONSHIPS_FETCH_SUCCESS:
return normalizeRelationships(state, action.relationships);
default:
return state;
}
switch(action.type) {
case GROUP_JOIN_SUCCESS:
case GROUP_LEAVE_SUCCESS:
return normalizeRelationship(state, action.relationship);
case GROUP_RELATIONSHIPS_FETCH_SUCCESS:
return normalizeRelationships(state, action.relationships);
default:
return state;
}
};

View file

@ -146,8 +146,8 @@ export default function notifications(state = initialState, action) {
return updateNotificationsQueue(state, action.notification, action.intlMessages, action.intlLocale);
case NOTIFICATIONS_DEQUEUE:
return state.withMutations(mutable => {
mutable.set('queuedNotifications', ImmutableList())
mutable.set('totalQueuedNotificationsCount', 0)
mutable.set('queuedNotifications', ImmutableList());
mutable.set('totalQueuedNotificationsCount', 0);
});
case NOTIFICATIONS_EXPAND_SUCCESS:
return expandNormalizedNotifications(state, action.notifications, action.next);

View file

@ -170,8 +170,8 @@ export default function timelines(state = initialState, action) {
return updateTimelineQueue(state, action.timeline, fromJS(action.status));
case TIMELINE_DEQUEUE:
return state.update(action.timeline, initialTimeline, map => map.withMutations(mMap => {
mMap.set('queuedItems', ImmutableList())
mMap.set('totalQueuedItemsCount', 0)
mMap.set('queuedItems', ImmutableList());
mMap.set('totalQueuedItemsCount', 0);
}));
case TIMELINE_DELETE:
return deleteStatus(state, action.id, action.accountId, action.references, action.reblogOf);
@ -193,7 +193,7 @@ export default function timelines(state = initialState, action) {
map => map.set('online', false).update('items', items => items.first() ? items.unshift(null) : items)
);
case GROUP_REMOVE_STATUS_SUCCESS:
return removeStatusFromGroup(state, action.groupId, action.id)
return removeStatusFromGroup(state, action.groupId, action.id);
default:
return state;
}

View file

@ -12,16 +12,16 @@ const initialState = ImmutableMap({
export default function trendsReducer(state = initialState, action) {
switch(action.type) {
case TRENDS_FETCH_REQUEST:
return state.set('isLoading', true);
case TRENDS_FETCH_SUCCESS:
return state.withMutations(map => {
map.set('items', fromJS(action.tags.map((x => x))))
map.set('isLoading', false);
});
case TRENDS_FETCH_FAIL:
return state.set('isLoading', false);
default:
return state;
case TRENDS_FETCH_REQUEST:
return state.set('isLoading', true);
case TRENDS_FETCH_SUCCESS:
return state.withMutations(map => {
map.set('items', fromJS(action.tags.map((x => x))));
map.set('isLoading', false);
});
case TRENDS_FETCH_FAIL:
return state.set('isLoading', false);
default:
return state;
}
};

View file

@ -21,7 +21,7 @@ import {
MUTES_EXPAND_SUCCESS,
} from '../actions/mutes';
import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
import {
import {
GROUP_MEMBERS_FETCH_SUCCESS,
GROUP_MEMBERS_EXPAND_SUCCESS,
GROUP_REMOVED_ACCOUNTS_FETCH_SUCCESS,

View file

@ -85,9 +85,9 @@ export default function getStream(streamingAPIBaseURL, accessToken, stream, { co
received(JSON.parse(e.data));
} catch(error) {
console.error(e);
console.error(`Could not parse the above streaming event.\n${error}`)
console.error(`Could not parse the above streaming event.\n${error}`);
}
}
};
return ws;
};

View file

@ -1,7 +1,7 @@
const getDomain = account => {
let re = /https?:\/\/(.*?)\//i;
return re.exec(account.get('url'))[1];
}
};
// user@domain even for local users
export const acctFull = account => {
@ -13,4 +13,4 @@ export const acctFull = account => {
return account.get('acct');
}
return [user, domain].join('@');
}
};

View file

@ -4,14 +4,14 @@ export const maximumAspectRatio = 2.8;
export const isPanoramic = ar => {
if (isNaN(ar)) return false;
return ar >= maximumAspectRatio;
}
};
export const isPortrait = ar => {
if (isNaN(ar)) return false;
return ar <= minimumAspectRatio;
}
};
export const isNonConformingRatio = ar => {
if (isNaN(ar)) return false;
return !isPanoramic(ar) && !isPortrait(ar);
}
};

View file

@ -64,7 +64,7 @@ delegate(document, '.btngroup__btn', 'click', ({ target: btn }) => {
if (other_btn_hides) {
other_btn_hides.style.display = '';
}
other_btn.classList.remove('btngroup__btn--active')
other_btn.classList.remove('btngroup__btn--active');
});
// Set given input
@ -73,7 +73,7 @@ delegate(document, '.btngroup__btn', 'click', ({ target: btn }) => {
}
// Highlight current button
btn.classList.add('btngroup__btn--active')
btn.classList.add('btngroup__btn--active');
// Set visibility of given elements
if (btn_shows) {
@ -96,26 +96,26 @@ delegate(document, '.btngroup__btn', 'click', ({ target: btn }) => {
delegate(document, '.payform', 'submit', (e) => {
e.preventDefault();
document.getElementById("paybtn").disabled = true;
document.getElementById('paybtn').disabled = true;
const stripe_pk = document.querySelector("meta[name='stripe-pk']").content;
const csrf_token = document.querySelector("meta[name='csrf-token']").content;
const price = Math.floor(document.getElementById("price").value.replace(/[^0-9.]/, "") * 100);
const stripe_pk = document.querySelector('meta[name=\'stripe-pk\']').content;
const csrf_token = document.querySelector('meta[name=\'csrf-token\']').content;
const price = Math.floor(document.getElementById('price').value.replace(/[^0-9.]/, '') * 100);
const stripe = Stripe(stripe_pk);
const req = new XMLHttpRequest();
function checkout () {
stripe.redirectToCheckout({
sessionId: this.responseText
sessionId: this.responseText,
}).then(function (result) {
console.log(result.error.message);
});
}
req.addEventListener("load", checkout);
req.open("POST", "/donate/stripe");
req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
req.setRequestHeader("X-CSRF-Token", csrf_token);
req.send("amount=" + price);
req.addEventListener('load', checkout);
req.open('POST', '/donate/stripe');
req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
req.setRequestHeader('X-CSRF-Token', csrf_token);
req.send('amount=' + price);
});

Some files were not shown because too many files have changed in this diff Show more