[Glitch] Add confirmation modal when logging out from the web app

Port d255ce2f1a to glitch-soc

Signed-off-by: Thibaut Girka <thib@sitedethib.com>
This commit is contained in:
ThibG 2019-08-26 18:24:10 +02:00 committed by Thibaut Girka
parent d212159f06
commit 47ffc93705
4 changed files with 122 additions and 29 deletions

View file

@ -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>

View file

@ -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));

View file

@ -1,36 +1,71 @@
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({
<div className='getting-started__footer'> logoutMessage: { id: 'confirmations.logout.message', defaultMessage: 'Are you sure you want to log out?' },
<ul> logoutConfirm: { id: 'confirmations.logout.confirm', defaultMessage: 'Log out' },
{invitesEnabled && <li><a href='/invites' target='_blank'><FormattedMessage id='getting_started.invite' defaultMessage='Invite people' /></a> · </li>} });
<li><a href='/auth/edit'><FormattedMessage id='getting_started.security' defaultMessage='Security' /></a> · </li>
<li><a href='/about/more' target='_blank'><FormattedMessage id='navigation_bar.info' defaultMessage='About this server' /></a> · </li>
<li><a href='https://joinmastodon.org/apps' target='_blank'><FormattedMessage id='navigation_bar.apps' defaultMessage='Mobile apps' /></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='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>
</ul>
<p> const mapDispatchToProps = (dispatch, { intl }) => ({
<FormattedMessage onLogout () {
id='getting_started.open_source_notice' dispatch(openModal('CONFIRM', {
defaultMessage='Glitchsoc is open source software, a friendly fork of {Mastodon}. You can contribute or report issues on GitHub at {github}.' message: intl.formatMessage(messages.logoutMessage),
values={{ confirm: intl.formatMessage(messages.logoutConfirm),
github: <span><a href='https://github.com/glitch-soc/mastodon' rel='noopener' target='_blank'>glitch-soc/mastodon</a> (v{version})</span>, onConfirm: () => logOut(),
Mastodon: <a href='https://github.com/tootsuite/mastodon' rel='noopener' target='_blank'>Mastodon</a> }} }));
/> },
</p> });
</div>
); 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'>
<ul>
{invitesEnabled && <li><a href='/invites' target='_blank'><FormattedMessage id='getting_started.invite' defaultMessage='Invite people' /></a> · </li>}
<li><a href='/auth/edit'><FormattedMessage id='getting_started.security' defaultMessage='Security' /></a> · </li>
<li><a href='/about/more' target='_blank'><FormattedMessage id='navigation_bar.info' defaultMessage='About this server' /></a> · </li>
<li><a href='https://joinmastodon.org/apps' target='_blank'><FormattedMessage id='navigation_bar.apps' defaultMessage='Mobile apps' /></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='https://docs.joinmastodon.org' target='_blank'><FormattedMessage id='getting_started.documentation' defaultMessage='Documentation' /></a> · </li>
<li><a href={signOutLink} onClick={this.handleLogoutClick}><FormattedMessage id='navigation_bar.logout' defaultMessage='Logout' /></a></li>
</ul>
<p>
<FormattedMessage
id='getting_started.open_source_notice'
defaultMessage='Glitchsoc is open source software, a friendly fork of {Mastodon}. You can contribute or report issues on GitHub at {github}.'
values={{
github: <span><a href='https://github.com/glitch-soc/mastodon' rel='noopener' target='_blank'>glitch-soc/mastodon</a> (v{version})</span>,
Mastodon: <a href='https://github.com/tootsuite/mastodon' rel='noopener' target='_blank'>Mastodon</a> }}
/>
</p>
</div>
);
}
LinkFooter.propTypes = {
}; };
export default LinkFooter;

View 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();
};