Merge branch 'snackbar' into 'develop'
Snackbars See merge request soapbox-pub/soapbox-fe!243
This commit is contained in:
commit
d022978078
18 changed files with 122 additions and 44 deletions
|
@ -10,7 +10,7 @@ describe('logOut()', () => {
|
||||||
it('creates expected actions', () => {
|
it('creates expected actions', () => {
|
||||||
const expectedActions = [
|
const expectedActions = [
|
||||||
{ type: AUTH_LOGGED_OUT },
|
{ type: AUTH_LOGGED_OUT },
|
||||||
{ type: ALERT_SHOW, title: 'Successfully logged out.', message: '' },
|
{ type: ALERT_SHOW, message: 'Logged out.', severity: 'success' },
|
||||||
];
|
];
|
||||||
const store = mockStore(ImmutableMap());
|
const store = mockStore(ImmutableMap());
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
//test
|
|
||||||
import { defineMessages } from 'react-intl';
|
import { defineMessages } from 'react-intl';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
|
@ -23,11 +22,12 @@ export function clearAlert() {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export function showAlert(title = messages.unexpectedTitle, message = messages.unexpectedMessage) {
|
export function showAlert(title = messages.unexpectedTitle, message = messages.unexpectedMessage, severity = 'info') {
|
||||||
return {
|
return {
|
||||||
type: ALERT_SHOW,
|
type: ALERT_SHOW,
|
||||||
title,
|
title,
|
||||||
message,
|
message,
|
||||||
|
severity,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -47,9 +47,9 @@ export function showAlertForError(error) {
|
||||||
message = data.error;
|
message = data.error;
|
||||||
}
|
}
|
||||||
|
|
||||||
return showAlert(title, message);
|
return showAlert(title, message, 'error');
|
||||||
} else {
|
} else {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
return showAlert();
|
return showAlert(undefined, undefined, 'error');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import api from '../api';
|
import api from '../api';
|
||||||
import { showAlert } from 'soapbox/actions/alerts';
|
import snackbar from 'soapbox/actions/snackbar';
|
||||||
import { fetchMe } from 'soapbox/actions/me';
|
import { fetchMe } from 'soapbox/actions/me';
|
||||||
|
|
||||||
export const AUTH_APP_CREATED = 'AUTH_APP_CREATED';
|
export const AUTH_APP_CREATED = 'AUTH_APP_CREATED';
|
||||||
|
@ -136,7 +136,7 @@ export function logIn(username, password) {
|
||||||
if (error.response.data.error === 'mfa_required') {
|
if (error.response.data.error === 'mfa_required') {
|
||||||
throw error;
|
throw error;
|
||||||
} else {
|
} else {
|
||||||
dispatch(showAlert('Login failed.', 'Invalid username or password.'));
|
dispatch(snackbar.error('Invalid username or password.'));
|
||||||
}
|
}
|
||||||
throw error;
|
throw error;
|
||||||
});
|
});
|
||||||
|
@ -156,7 +156,7 @@ export function logOut() {
|
||||||
token: state.getIn(['auth', 'user', 'access_token']),
|
token: state.getIn(['auth', 'user', 'access_token']),
|
||||||
});
|
});
|
||||||
|
|
||||||
dispatch(showAlert('Successfully logged out.', ''));
|
dispatch(snackbar.success('Logged out.'));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,9 +172,9 @@ export function register(params) {
|
||||||
dispatch({ type: AUTH_REGISTER_SUCCESS, token: response.data });
|
dispatch({ type: AUTH_REGISTER_SUCCESS, token: response.data });
|
||||||
dispatch(authLoggedIn(response.data));
|
dispatch(authLoggedIn(response.data));
|
||||||
if (needsConfirmation) {
|
if (needsConfirmation) {
|
||||||
return dispatch(showAlert('', 'Check your email for further instructions.'));
|
return dispatch(snackbar.info('You must confirm your email.'));
|
||||||
} else if (needsApproval) {
|
} else if (needsApproval) {
|
||||||
return dispatch(showAlert('', 'Your account has been submitted for approval.'));
|
return dispatch(snackbar.info('Your account is being reviewed.'));
|
||||||
} else {
|
} else {
|
||||||
return dispatch(fetchMe());
|
return dispatch(fetchMe());
|
||||||
}
|
}
|
||||||
|
@ -232,7 +232,7 @@ export function deleteAccount(password) {
|
||||||
if (response.data.error) throw response.data.error; // This endpoint returns HTTP 200 even on failure
|
if (response.data.error) throw response.data.error; // This endpoint returns HTTP 200 even on failure
|
||||||
dispatch({ type: DELETE_ACCOUNT_SUCCESS, response });
|
dispatch({ type: DELETE_ACCOUNT_SUCCESS, response });
|
||||||
dispatch({ type: AUTH_LOGGED_OUT });
|
dispatch({ type: AUTH_LOGGED_OUT });
|
||||||
dispatch(showAlert('Successfully logged out.', ''));
|
dispatch(snackbar.success('Logged out.'));
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
dispatch({ type: DELETE_ACCOUNT_FAIL, error, skipAlert: true });
|
dispatch({ type: DELETE_ACCOUNT_FAIL, error, skipAlert: true });
|
||||||
throw error;
|
throw error;
|
||||||
|
|
|
@ -224,7 +224,7 @@ export function uploadCompose(files) {
|
||||||
let total = Array.from(files).reduce((a, v) => a + v.size, 0);
|
let total = Array.from(files).reduce((a, v) => a + v.size, 0);
|
||||||
|
|
||||||
if (files.length + media.size > uploadLimit) {
|
if (files.length + media.size > uploadLimit) {
|
||||||
dispatch(showAlert(undefined, messages.uploadErrorLimit));
|
dispatch(showAlert(undefined, messages.uploadErrorLimit, 'error'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import api from '../api';
|
import api from '../api';
|
||||||
import { showAlert } from 'soapbox/actions/alerts';
|
import snackbar from 'soapbox/actions/snackbar';
|
||||||
|
|
||||||
export const FILTERS_FETCH_REQUEST = 'FILTERS_FETCH_REQUEST';
|
export const FILTERS_FETCH_REQUEST = 'FILTERS_FETCH_REQUEST';
|
||||||
export const FILTERS_FETCH_SUCCESS = 'FILTERS_FETCH_SUCCESS';
|
export const FILTERS_FETCH_SUCCESS = 'FILTERS_FETCH_SUCCESS';
|
||||||
|
@ -47,7 +47,7 @@ export function createFilter(phrase, expires_at, context, whole_word, irreversib
|
||||||
expires_at,
|
expires_at,
|
||||||
}).then(response => {
|
}).then(response => {
|
||||||
dispatch({ type: FILTERS_CREATE_SUCCESS, filter: response.data });
|
dispatch({ type: FILTERS_CREATE_SUCCESS, filter: response.data });
|
||||||
dispatch(showAlert('', 'Filter added'));
|
dispatch(snackbar.success('Filter added.'));
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
dispatch({ type: FILTERS_CREATE_FAIL, error });
|
dispatch({ type: FILTERS_CREATE_FAIL, error });
|
||||||
});
|
});
|
||||||
|
@ -60,7 +60,7 @@ export function deleteFilter(id) {
|
||||||
dispatch({ type: FILTERS_DELETE_REQUEST });
|
dispatch({ type: FILTERS_DELETE_REQUEST });
|
||||||
return api(getState).delete('/api/v1/filters/'+id).then(response => {
|
return api(getState).delete('/api/v1/filters/'+id).then(response => {
|
||||||
dispatch({ type: FILTERS_DELETE_SUCCESS, filter: response.data });
|
dispatch({ type: FILTERS_DELETE_SUCCESS, filter: response.data });
|
||||||
dispatch(showAlert('', 'Filter deleted'));
|
dispatch(snackbar.success('Filter deleted.'));
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
dispatch({ type: FILTERS_DELETE_FAIL, error });
|
dispatch({ type: FILTERS_DELETE_FAIL, error });
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import api from '../api';
|
import api from '../api';
|
||||||
import { showAlert } from 'soapbox/actions/alerts';
|
import snackbar from 'soapbox/actions/snackbar';
|
||||||
|
|
||||||
export const IMPORT_FOLLOWS_REQUEST = 'IMPORT_FOLLOWS_REQUEST';
|
export const IMPORT_FOLLOWS_REQUEST = 'IMPORT_FOLLOWS_REQUEST';
|
||||||
export const IMPORT_FOLLOWS_SUCCESS = 'IMPORT_FOLLOWS_SUCCESS';
|
export const IMPORT_FOLLOWS_SUCCESS = 'IMPORT_FOLLOWS_SUCCESS';
|
||||||
|
@ -19,7 +19,7 @@ export function importFollows(params) {
|
||||||
return api(getState)
|
return api(getState)
|
||||||
.post('/api/pleroma/follow_import', params)
|
.post('/api/pleroma/follow_import', params)
|
||||||
.then(response => {
|
.then(response => {
|
||||||
dispatch(showAlert('', 'Followers imported successfully'));
|
dispatch(snackbar.success('Followers imported successfully'));
|
||||||
dispatch({ type: IMPORT_FOLLOWS_SUCCESS, config: response.data });
|
dispatch({ type: IMPORT_FOLLOWS_SUCCESS, config: response.data });
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
dispatch({ type: IMPORT_FOLLOWS_FAIL, error });
|
dispatch({ type: IMPORT_FOLLOWS_FAIL, error });
|
||||||
|
@ -33,7 +33,7 @@ export function importBlocks(params) {
|
||||||
return api(getState)
|
return api(getState)
|
||||||
.post('/api/pleroma/blocks_import', params)
|
.post('/api/pleroma/blocks_import', params)
|
||||||
.then(response => {
|
.then(response => {
|
||||||
dispatch(showAlert('', 'Blocks imported successfully'));
|
dispatch(snackbar.success('Blocks imported successfully'));
|
||||||
dispatch({ type: IMPORT_BLOCKS_SUCCESS, config: response.data });
|
dispatch({ type: IMPORT_BLOCKS_SUCCESS, config: response.data });
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
dispatch({ type: IMPORT_BLOCKS_FAIL, error });
|
dispatch({ type: IMPORT_BLOCKS_FAIL, error });
|
||||||
|
@ -47,7 +47,7 @@ export function importMutes(params) {
|
||||||
return api(getState)
|
return api(getState)
|
||||||
.post('/api/pleroma/mutes_import', params)
|
.post('/api/pleroma/mutes_import', params)
|
||||||
.then(response => {
|
.then(response => {
|
||||||
dispatch(showAlert('', 'Mutes imported successfully'));
|
dispatch(snackbar.success('Mutes imported successfully'));
|
||||||
dispatch({ type: IMPORT_MUTES_SUCCESS, config: response.data });
|
dispatch({ type: IMPORT_MUTES_SUCCESS, config: response.data });
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
dispatch({ type: IMPORT_MUTES_FAIL, error });
|
dispatch({ type: IMPORT_MUTES_FAIL, error });
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import api from '../api';
|
import api from '../api';
|
||||||
import { importFetchedAccounts, importFetchedStatus } from './importer';
|
import { importFetchedAccounts, importFetchedStatus } from './importer';
|
||||||
import { showAlert } from 'soapbox/actions/alerts';
|
import snackbar from 'soapbox/actions/snackbar';
|
||||||
|
|
||||||
export const REBLOG_REQUEST = 'REBLOG_REQUEST';
|
export const REBLOG_REQUEST = 'REBLOG_REQUEST';
|
||||||
export const REBLOG_SUCCESS = 'REBLOG_SUCCESS';
|
export const REBLOG_SUCCESS = 'REBLOG_SUCCESS';
|
||||||
|
@ -211,7 +211,7 @@ export function bookmark(status) {
|
||||||
api(getState).post(`/api/v1/statuses/${status.get('id')}/bookmark`).then(function(response) {
|
api(getState).post(`/api/v1/statuses/${status.get('id')}/bookmark`).then(function(response) {
|
||||||
dispatch(importFetchedStatus(response.data));
|
dispatch(importFetchedStatus(response.data));
|
||||||
dispatch(bookmarkSuccess(status, response.data));
|
dispatch(bookmarkSuccess(status, response.data));
|
||||||
dispatch(showAlert('', 'Bookmark added'));
|
dispatch(snackbar.success('Bookmark added'));
|
||||||
}).catch(function(error) {
|
}).catch(function(error) {
|
||||||
dispatch(bookmarkFail(status, error));
|
dispatch(bookmarkFail(status, error));
|
||||||
});
|
});
|
||||||
|
@ -225,7 +225,7 @@ export function unbookmark(status) {
|
||||||
api(getState).post(`/api/v1/statuses/${status.get('id')}/unbookmark`).then(response => {
|
api(getState).post(`/api/v1/statuses/${status.get('id')}/unbookmark`).then(response => {
|
||||||
dispatch(importFetchedStatus(response.data));
|
dispatch(importFetchedStatus(response.data));
|
||||||
dispatch(unbookmarkSuccess(status, response.data));
|
dispatch(unbookmarkSuccess(status, response.data));
|
||||||
dispatch(showAlert('', 'Bookmark removed'));
|
dispatch(snackbar.success('Bookmark removed'));
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
dispatch(unbookmarkFail(status, error));
|
dispatch(unbookmarkFail(status, error));
|
||||||
});
|
});
|
||||||
|
|
25
app/soapbox/actions/snackbar.js
Normal file
25
app/soapbox/actions/snackbar.js
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
import { ALERT_SHOW } from './alerts';
|
||||||
|
|
||||||
|
const show = (severity, message) => ({
|
||||||
|
type: ALERT_SHOW,
|
||||||
|
message,
|
||||||
|
severity,
|
||||||
|
});
|
||||||
|
|
||||||
|
export function info(message) {
|
||||||
|
return show('info', message);
|
||||||
|
};
|
||||||
|
|
||||||
|
export function success(message) {
|
||||||
|
return show('success', message);
|
||||||
|
};
|
||||||
|
|
||||||
|
export function error(message) {
|
||||||
|
return show('error', message);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default {
|
||||||
|
info,
|
||||||
|
success,
|
||||||
|
error,
|
||||||
|
};
|
|
@ -4,7 +4,7 @@ import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
import { resetPassword } from 'soapbox/actions/auth';
|
import { resetPassword } from 'soapbox/actions/auth';
|
||||||
import { SimpleForm, FieldsGroup, TextInput } from 'soapbox/features/forms';
|
import { SimpleForm, FieldsGroup, TextInput } from 'soapbox/features/forms';
|
||||||
import { Redirect } from 'react-router-dom';
|
import { Redirect } from 'react-router-dom';
|
||||||
import { showAlert } from 'soapbox/actions/alerts';
|
import snackbar from 'soapbox/actions/snackbar';
|
||||||
|
|
||||||
export default @connect()
|
export default @connect()
|
||||||
class PasswordReset extends ImmutablePureComponent {
|
class PasswordReset extends ImmutablePureComponent {
|
||||||
|
@ -20,7 +20,7 @@ class PasswordReset extends ImmutablePureComponent {
|
||||||
this.setState({ isLoading: true });
|
this.setState({ isLoading: true });
|
||||||
dispatch(resetPassword(nicknameOrEmail)).then(() => {
|
dispatch(resetPassword(nicknameOrEmail)).then(() => {
|
||||||
this.setState({ isLoading: false, success: true });
|
this.setState({ isLoading: false, success: true });
|
||||||
dispatch(showAlert('Password reset received. Check your email for further instructions.', ''));
|
dispatch(snackbar.info('Check your email for confirmation.'));
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
this.setState({ isLoading: false });
|
this.setState({ isLoading: false });
|
||||||
});
|
});
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import { showAlert } from 'soapbox/actions/alerts';
|
import snackbar from 'soapbox/actions/snackbar';
|
||||||
import Column from '../ui/components/column';
|
import Column from '../ui/components/column';
|
||||||
import {
|
import {
|
||||||
SimpleForm,
|
SimpleForm,
|
||||||
|
@ -124,7 +124,7 @@ class EditProfile extends ImmutablePureComponent {
|
||||||
const { dispatch } = this.props;
|
const { dispatch } = this.props;
|
||||||
dispatch(patchMe(this.getFormdata())).then(() => {
|
dispatch(patchMe(this.getFormdata())).then(() => {
|
||||||
this.setState({ isLoading: false });
|
this.setState({ isLoading: false });
|
||||||
dispatch(showAlert('', 'Profile saved!'));
|
dispatch(snackbar.success('Profile saved!'));
|
||||||
}).catch((error) => {
|
}).catch((error) => {
|
||||||
this.setState({ isLoading: false });
|
this.setState({ isLoading: false });
|
||||||
});
|
});
|
||||||
|
|
|
@ -14,7 +14,7 @@ import {
|
||||||
SelectDropdown,
|
SelectDropdown,
|
||||||
Checkbox,
|
Checkbox,
|
||||||
} from 'soapbox/features/forms';
|
} from 'soapbox/features/forms';
|
||||||
import { showAlert } from 'soapbox/actions/alerts';
|
import snackbar from 'soapbox/actions/snackbar';
|
||||||
import Icon from 'soapbox/components/icon';
|
import Icon from 'soapbox/components/icon';
|
||||||
import ColumnSubheading from '../ui/components/column_subheading';
|
import ColumnSubheading from '../ui/components/column_subheading';
|
||||||
|
|
||||||
|
@ -114,7 +114,7 @@ class Filters extends ImmutablePureComponent {
|
||||||
dispatch(createFilter(phrase, expires_at, context, whole_word, irreversible)).then(response => {
|
dispatch(createFilter(phrase, expires_at, context, whole_word, irreversible)).then(response => {
|
||||||
return dispatch(fetchFilters());
|
return dispatch(fetchFilters());
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
dispatch(showAlert('', intl.formatMessage(messages.create_error)));
|
dispatch(snackbar.error(intl.formatMessage(messages.create_error)));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,7 +123,7 @@ class Filters extends ImmutablePureComponent {
|
||||||
dispatch(deleteFilter(e.currentTarget.dataset.value)).then(response => {
|
dispatch(deleteFilter(e.currentTarget.dataset.value)).then(response => {
|
||||||
return dispatch(fetchFilters());
|
return dispatch(fetchFilters());
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
dispatch(showAlert('', intl.formatMessage(messages.delete_error)));
|
dispatch(snackbar.error(intl.formatMessage(messages.delete_error)));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ import {
|
||||||
deleteAccount,
|
deleteAccount,
|
||||||
} from 'soapbox/actions/auth';
|
} from 'soapbox/actions/auth';
|
||||||
import { fetchUserMfaSettings } from '../../actions/mfa';
|
import { fetchUserMfaSettings } from '../../actions/mfa';
|
||||||
import { showAlert } from 'soapbox/actions/alerts';
|
import snackbar from 'soapbox/actions/snackbar';
|
||||||
import { changeSetting, getSettings } from 'soapbox/actions/settings';
|
import { changeSetting, getSettings } from 'soapbox/actions/settings';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -119,10 +119,10 @@ class ChangeEmailForm extends ImmutablePureComponent {
|
||||||
this.setState({ isLoading: true });
|
this.setState({ isLoading: true });
|
||||||
return dispatch(changeEmail(email, password)).then(() => {
|
return dispatch(changeEmail(email, password)).then(() => {
|
||||||
this.setState({ email: '', password: '' }); // TODO: Maybe redirect user
|
this.setState({ email: '', password: '' }); // TODO: Maybe redirect user
|
||||||
dispatch(showAlert('', intl.formatMessage(messages.updateEmailSuccess)));
|
dispatch(snackbar.success(intl.formatMessage(messages.updateEmailSuccess)));
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
this.setState({ password: '' });
|
this.setState({ password: '' });
|
||||||
dispatch(showAlert('', intl.formatMessage(messages.updateEmailFail)));
|
dispatch(snackbar.error(intl.formatMessage(messages.updateEmailFail)));
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
this.setState({ isLoading: false });
|
this.setState({ isLoading: false });
|
||||||
});
|
});
|
||||||
|
@ -193,10 +193,10 @@ class ChangePasswordForm extends ImmutablePureComponent {
|
||||||
this.setState({ isLoading: true });
|
this.setState({ isLoading: true });
|
||||||
return dispatch(changePassword(oldPassword, newPassword, confirmation)).then(() => {
|
return dispatch(changePassword(oldPassword, newPassword, confirmation)).then(() => {
|
||||||
this.clearForm(); // TODO: Maybe redirect user
|
this.clearForm(); // TODO: Maybe redirect user
|
||||||
dispatch(showAlert('', intl.formatMessage(messages.updatePasswordSuccess)));
|
dispatch(snackbar.success(intl.formatMessage(messages.updatePasswordSuccess)));
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
this.clearForm();
|
this.clearForm();
|
||||||
dispatch(showAlert('', intl.formatMessage(messages.updatePasswordFail)));
|
dispatch(snackbar.error(intl.formatMessage(messages.updatePasswordFail)));
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
this.setState({ isLoading: false });
|
this.setState({ isLoading: false });
|
||||||
});
|
});
|
||||||
|
@ -374,10 +374,10 @@ class DeactivateAccount extends ImmutablePureComponent {
|
||||||
this.setState({ isLoading: true });
|
this.setState({ isLoading: true });
|
||||||
return dispatch(deleteAccount(password)).then(() => {
|
return dispatch(deleteAccount(password)).then(() => {
|
||||||
//this.setState({ email: '', password: '' }); // TODO: Maybe redirect user
|
//this.setState({ email: '', password: '' }); // TODO: Maybe redirect user
|
||||||
dispatch(showAlert('', intl.formatMessage(messages.deleteAccountSuccess)));
|
dispatch(snackbar.success(intl.formatMessage(messages.deleteAccountSuccess)));
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
this.setState({ password: '' });
|
this.setState({ password: '' });
|
||||||
dispatch(showAlert('', intl.formatMessage(messages.deleteAccountFail)));
|
dispatch(snackbar.error(intl.formatMessage(messages.deleteAccountFail)));
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
this.setState({ isLoading: false });
|
this.setState({ isLoading: false });
|
||||||
});
|
});
|
||||||
|
|
|
@ -10,7 +10,7 @@ import ColumnSubheading from '../ui/components/column_subheading';
|
||||||
import LoadingIndicator from 'soapbox/components/loading_indicator';
|
import LoadingIndicator from 'soapbox/components/loading_indicator';
|
||||||
import Button from 'soapbox/components/button';
|
import Button from 'soapbox/components/button';
|
||||||
import { changeSetting, getSettings } from 'soapbox/actions/settings';
|
import { changeSetting, getSettings } from 'soapbox/actions/settings';
|
||||||
import { showAlert } from 'soapbox/actions/alerts';
|
import snackbar from 'soapbox/actions/snackbar';
|
||||||
import {
|
import {
|
||||||
SimpleForm,
|
SimpleForm,
|
||||||
SimpleInput,
|
SimpleInput,
|
||||||
|
@ -129,7 +129,7 @@ class DisableOtpForm extends ImmutablePureComponent {
|
||||||
this.context.router.history.push('../auth/edit');
|
this.context.router.history.push('../auth/edit');
|
||||||
dispatch(changeSetting(['otpEnabled'], false));
|
dispatch(changeSetting(['otpEnabled'], false));
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
dispatch(showAlert('', intl.formatMessage(messages.disableFail)));
|
dispatch(snackbar.error(intl.formatMessage(messages.disableFail)));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,7 +180,7 @@ class EnableOtpForm extends ImmutablePureComponent {
|
||||||
dispatch(fetchBackupCodes()).then(response => {
|
dispatch(fetchBackupCodes()).then(response => {
|
||||||
this.setState({ backupCodes: response.data.codes });
|
this.setState({ backupCodes: response.data.codes });
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
dispatch(showAlert('', intl.formatMessage(messages.codesFail)));
|
dispatch(snackbar.error(intl.formatMessage(messages.codesFail)));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -261,7 +261,7 @@ class OtpConfirmForm extends ImmutablePureComponent {
|
||||||
dispatch(fetchToptSetup()).then(response => {
|
dispatch(fetchToptSetup()).then(response => {
|
||||||
this.setState({ qrCodeURI: response.data.provisioning_uri, confirm_key: response.data.key });
|
this.setState({ qrCodeURI: response.data.provisioning_uri, confirm_key: response.data.key });
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
dispatch(showAlert('', intl.formatMessage(messages.qrFail)));
|
dispatch(snackbar.error(intl.formatMessage(messages.qrFail)));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -276,7 +276,7 @@ class OtpConfirmForm extends ImmutablePureComponent {
|
||||||
dispatch(confirmToptSetup(code, password)).then(response => {
|
dispatch(confirmToptSetup(code, password)).then(response => {
|
||||||
dispatch(changeSetting(['otpEnabled'], true));
|
dispatch(changeSetting(['otpEnabled'], true));
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
dispatch(showAlert('', intl.formatMessage(messages.confirmFail)));
|
dispatch(snackbar.error(intl.formatMessage(messages.confirmFail)));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,14 @@ import { NotificationStack } from 'react-notification';
|
||||||
import { dismissAlert } from '../../../actions/alerts';
|
import { dismissAlert } from '../../../actions/alerts';
|
||||||
import { getAlerts } from '../../../selectors';
|
import { getAlerts } from '../../../selectors';
|
||||||
|
|
||||||
|
const defaultBarStyleFactory = (index, style, notification) => {
|
||||||
|
return Object.assign(
|
||||||
|
{},
|
||||||
|
style,
|
||||||
|
{ bottom: `${14 + index * 12 + index * 42}px` }
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const mapStateToProps = (state, { intl }) => {
|
const mapStateToProps = (state, { intl }) => {
|
||||||
const notifications = getAlerts(state);
|
const notifications = getAlerts(state);
|
||||||
|
|
||||||
|
@ -23,6 +31,8 @@ const mapDispatchToProps = (dispatch) => {
|
||||||
onDismiss: alert => {
|
onDismiss: alert => {
|
||||||
dispatch(dismissAlert(alert));
|
dispatch(dismissAlert(alert));
|
||||||
},
|
},
|
||||||
|
barStyleFactory: defaultBarStyleFactory,
|
||||||
|
activeBarStyleFactory: defaultBarStyleFactory,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ export default function alerts(state = initialState, action) {
|
||||||
key: state.size > 0 ? state.last().get('key') + 1 : 0,
|
key: state.size > 0 ? state.last().get('key') + 1 : 0,
|
||||||
title: action.title,
|
title: action.title,
|
||||||
message: action.message,
|
message: action.message,
|
||||||
|
severity: action.severity || 'info',
|
||||||
}));
|
}));
|
||||||
case ALERT_DISMISS:
|
case ALERT_DISMISS:
|
||||||
return state.filterNot(item => item.get('key') === action.alert.key);
|
return state.filterNot(item => item.get('key') === action.alert.key);
|
||||||
|
|
|
@ -124,10 +124,9 @@ export const getAlerts = createSelector([getAlertsBase], (base) => {
|
||||||
message: item.get('message'),
|
message: item.get('message'),
|
||||||
title: item.get('title'),
|
title: item.get('title'),
|
||||||
key: item.get('key'),
|
key: item.get('key'),
|
||||||
|
className: `snackbar snackbar--${item.get('severity', 'info')}`,
|
||||||
|
activeClassName: 'snackbar--active',
|
||||||
dismissAfter: 5000,
|
dismissAfter: 5000,
|
||||||
barStyle: {
|
|
||||||
zIndex: 200,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -70,6 +70,7 @@
|
||||||
@import 'components/profile_hover_card';
|
@import 'components/profile_hover_card';
|
||||||
@import 'components/filters';
|
@import 'components/filters';
|
||||||
@import 'components/mfa_form';
|
@import 'components/mfa_form';
|
||||||
|
@import 'components/snackbar';
|
||||||
|
|
||||||
// Holiday
|
// Holiday
|
||||||
@import 'holiday/halloween';
|
@import 'holiday/halloween';
|
||||||
|
|
42
app/styles/components/snackbar.scss
Normal file
42
app/styles/components/snackbar.scss
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
.snackbar {
|
||||||
|
font-size: 16px !important;
|
||||||
|
padding: 10px 20px 10px 14px !important;
|
||||||
|
z-index: 9999 !important;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
font-family: ForkAwesome;
|
||||||
|
font-size: 20px;
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--info {
|
||||||
|
background-color: #19759e !important;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&--success {
|
||||||
|
background-color: #199e5a !important;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&--error {
|
||||||
|
background-color: #9e1919 !important;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.notification-bar-wrapper {
|
||||||
|
transform: translateY(1px);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue