[Glitch] Add confirmation modal when logging out from the web app
Port fd3d45d38f
to glitch-soc
Signed-off-by: Thibaut Girka <thib@sitedethib.com>
This commit is contained in:
parent
7c22e32562
commit
f11e9d5524
4 changed files with 122 additions and 29 deletions
|
@ -53,8 +53,18 @@ class Header extends ImmutablePureComponent {
|
||||||
showNotificationsBadge: PropTypes.bool,
|
showNotificationsBadge: PropTypes.bool,
|
||||||
intl: PropTypes.object,
|
intl: PropTypes.object,
|
||||||
onSettingsClick: PropTypes.func,
|
onSettingsClick: PropTypes.func,
|
||||||
|
onLogout: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
handleLogoutClick = e => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
|
||||||
|
this.props.onLogout();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { intl, columns, unreadNotifications, showNotificationsBadge, onSettingsClick } = this.props;
|
const { intl, columns, unreadNotifications, showNotificationsBadge, onSettingsClick } = this.props;
|
||||||
|
|
||||||
|
@ -114,7 +124,7 @@ class Header extends ImmutablePureComponent {
|
||||||
><Icon icon='cogs' /></a>
|
><Icon icon='cogs' /></a>
|
||||||
<a
|
<a
|
||||||
aria-label={intl.formatMessage(messages.logout)}
|
aria-label={intl.formatMessage(messages.logout)}
|
||||||
data-method='delete'
|
onClick={this.handleLogoutClick}
|
||||||
href={ signOutLink }
|
href={ signOutLink }
|
||||||
title={intl.formatMessage(messages.logout)}
|
title={intl.formatMessage(messages.logout)}
|
||||||
><Icon icon='sign-out' /></a>
|
><Icon icon='sign-out' /></a>
|
||||||
|
|
|
@ -1,6 +1,13 @@
|
||||||
import { openModal } from 'flavours/glitch/actions/modal';
|
import { openModal } from 'flavours/glitch/actions/modal';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
import { defineMessages, injectIntl } from 'react-intl';
|
||||||
import Header from '../components/header';
|
import Header from '../components/header';
|
||||||
|
import { logOut } from 'flavours/glitch/util/log_out';
|
||||||
|
|
||||||
|
const messages = defineMessages({
|
||||||
|
logoutMessage: { id: 'confirmations.logout.message', defaultMessage: 'Are you sure you want to log out?' },
|
||||||
|
logoutConfirm: { id: 'confirmations.logout.confirm', defaultMessage: 'Log out' },
|
||||||
|
});
|
||||||
|
|
||||||
const mapStateToProps = state => {
|
const mapStateToProps = state => {
|
||||||
return {
|
return {
|
||||||
|
@ -16,6 +23,13 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
dispatch(openModal('SETTINGS', {}));
|
dispatch(openModal('SETTINGS', {}));
|
||||||
},
|
},
|
||||||
|
onLogout () {
|
||||||
|
dispatch(openModal('CONFIRM', {
|
||||||
|
message: intl.formatMessage(messages.logoutMessage),
|
||||||
|
confirm: intl.formatMessage(messages.logoutConfirm),
|
||||||
|
onConfirm: () => logOut(),
|
||||||
|
}));
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(Header);
|
export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(Header));
|
||||||
|
|
|
@ -1,11 +1,48 @@
|
||||||
|
import { connect } from 'react-redux';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage, defineMessages, injectIntl } from 'react-intl';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { invitesEnabled, version, repository, source_url } from 'flavours/glitch/util/initial_state';
|
import { invitesEnabled, version, repository, source_url } from 'flavours/glitch/util/initial_state';
|
||||||
import { signOutLink } from 'flavours/glitch/util/backend_links';
|
import { signOutLink } from 'flavours/glitch/util/backend_links';
|
||||||
|
import { logOut } from 'flavours/glitch/util/log_out';
|
||||||
|
import { openModal } from 'flavours/glitch/actions/modal';
|
||||||
|
|
||||||
const LinkFooter = () => (
|
const messages = defineMessages({
|
||||||
|
logoutMessage: { id: 'confirmations.logout.message', defaultMessage: 'Are you sure you want to log out?' },
|
||||||
|
logoutConfirm: { id: 'confirmations.logout.confirm', defaultMessage: 'Log out' },
|
||||||
|
});
|
||||||
|
|
||||||
|
const mapDispatchToProps = (dispatch, { intl }) => ({
|
||||||
|
onLogout () {
|
||||||
|
dispatch(openModal('CONFIRM', {
|
||||||
|
message: intl.formatMessage(messages.logoutMessage),
|
||||||
|
confirm: intl.formatMessage(messages.logoutConfirm),
|
||||||
|
onConfirm: () => logOut(),
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default @injectIntl
|
||||||
|
@connect(null, mapDispatchToProps)
|
||||||
|
class LinkFooter extends React.PureComponent {
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
onLogout: PropTypes.func.isRequired,
|
||||||
|
intl: PropTypes.object.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
handleLogoutClick = e => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
|
||||||
|
this.props.onLogout();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
render () {
|
||||||
|
return (
|
||||||
<div className='getting-started__footer'>
|
<div className='getting-started__footer'>
|
||||||
<ul>
|
<ul>
|
||||||
{invitesEnabled && <li><a href='/invites' target='_blank'><FormattedMessage id='getting_started.invite' defaultMessage='Invite people' /></a> · </li>}
|
{invitesEnabled && <li><a href='/invites' target='_blank'><FormattedMessage id='getting_started.invite' defaultMessage='Invite people' /></a> · </li>}
|
||||||
|
@ -15,7 +52,7 @@ const LinkFooter = () => (
|
||||||
<li><a href='/terms' target='_blank'><FormattedMessage id='getting_started.terms' defaultMessage='Terms of service' /></a> · </li>
|
<li><a href='/terms' target='_blank'><FormattedMessage id='getting_started.terms' defaultMessage='Terms of service' /></a> · </li>
|
||||||
<li><a href='/settings/applications' target='_blank'><FormattedMessage id='getting_started.developers' defaultMessage='Developers' /></a> · </li>
|
<li><a href='/settings/applications' target='_blank'><FormattedMessage id='getting_started.developers' defaultMessage='Developers' /></a> · </li>
|
||||||
<li><a href='https://docs.joinmastodon.org' target='_blank'><FormattedMessage id='getting_started.documentation' defaultMessage='Documentation' /></a> · </li>
|
<li><a href='https://docs.joinmastodon.org' target='_blank'><FormattedMessage id='getting_started.documentation' defaultMessage='Documentation' /></a> · </li>
|
||||||
<li><a href={signOutLink} data-method='delete'><FormattedMessage id='navigation_bar.logout' defaultMessage='Logout' /></a></li>
|
<li><a href={signOutLink} onClick={this.handleLogoutClick}><FormattedMessage id='navigation_bar.logout' defaultMessage='Logout' /></a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
@ -28,9 +65,7 @@ const LinkFooter = () => (
|
||||||
/>
|
/>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
LinkFooter.propTypes = {
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default LinkFooter;
|
|
||||||
|
|
34
app/javascript/flavours/glitch/util/log_out.js
Normal file
34
app/javascript/flavours/glitch/util/log_out.js
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
import Rails from 'rails-ujs';
|
||||||
|
import { signOutLink } from 'flavours/glitch/util/backend_links';
|
||||||
|
|
||||||
|
export const logOut = () => {
|
||||||
|
const form = document.createElement('form');
|
||||||
|
|
||||||
|
const methodInput = document.createElement('input');
|
||||||
|
methodInput.setAttribute('name', '_method');
|
||||||
|
methodInput.setAttribute('value', 'delete');
|
||||||
|
methodInput.setAttribute('type', 'hidden');
|
||||||
|
form.appendChild(methodInput);
|
||||||
|
|
||||||
|
const csrfToken = Rails.csrfToken();
|
||||||
|
const csrfParam = Rails.csrfParam();
|
||||||
|
|
||||||
|
if (csrfParam && csrfToken) {
|
||||||
|
const csrfInput = document.createElement('input');
|
||||||
|
csrfInput.setAttribute('name', csrfParam);
|
||||||
|
csrfInput.setAttribute('value', csrfToken);
|
||||||
|
csrfInput.setAttribute('type', 'hidden');
|
||||||
|
form.appendChild(csrfInput);
|
||||||
|
}
|
||||||
|
|
||||||
|
const submitButton = document.createElement('input');
|
||||||
|
submitButton.setAttribute('type', 'submit');
|
||||||
|
form.appendChild(submitButton);
|
||||||
|
|
||||||
|
form.method = 'post';
|
||||||
|
form.action = signOutLink;
|
||||||
|
form.style.display = 'none';
|
||||||
|
|
||||||
|
document.body.appendChild(form);
|
||||||
|
submitButton.click();
|
||||||
|
};
|
Loading…
Reference in a new issue